Skip to content

Commit 354d298

Browse files
committed
Share PiP control atlas and story crop across renderers
Task: 2026/10/29/share-media-viewer-renderer-preparation-across-backends
1 parent d3b51bc commit 354d298

8 files changed

Lines changed: 56 additions & 115 deletions

‎Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ float roundedCorner() {
107107
};
108108
}
109109

110-
[[nodiscard]] QRectF StoryCropTextureRect(
110+
} // namespace
111+
112+
QRectF OverlayWidget::Renderer::StoryCropTextureRect(
111113
QSizeF imageSize,
112114
QSizeF targetSize) {
113115
if (imageSize.isEmpty() || targetSize.isEmpty()) {
@@ -135,8 +137,6 @@ float roundedCorner() {
135137
return QRectF(0., 0., 1., 1.);
136138
}
137139

138-
} // namespace
139-
140140
OverlayWidget::RendererGL::RendererGL(not_null<OverlayWidget*> owner)
141141
: _owner(owner) {
142142
style::PaletteChanged(

‎Telegram/SourceFiles/media/view/media_view_overlay_renderer.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ class OverlayWidget::Renderer : public Ui::GL::Renderer {
5252
const QImage &image,
5353
QRect rect,
5454
float64 opacity = 1.) = 0;
55+
56+
protected:
57+
[[nodiscard]] static QRectF StoryCropTextureRect(
58+
QSizeF imageSize,
59+
QSizeF targetSize);
60+
5561
};
5662

5763
} // namespace Media::View

‎Telegram/SourceFiles/media/view/media_view_overlay_rhi.cpp‎

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -68,34 +68,6 @@ struct RoundedCornersUniforms {
6868
};
6969
static_assert(sizeof(RoundedCornersUniforms) == 48);
7070

71-
[[nodiscard]] QRectF StoryCropTextureRect(
72-
QSizeF imageSize,
73-
QSizeF targetSize) {
74-
if (imageSize.isEmpty() || targetSize.isEmpty()) {
75-
return QRectF(0., 0., 1., 1.);
76-
}
77-
const auto targetAspect = targetSize.width() / targetSize.height();
78-
const auto imageAspect = imageSize.width() / imageSize.height();
79-
if (imageAspect > targetAspect) {
80-
const auto cropW = imageSize.height() * targetAspect;
81-
const auto offset = (imageSize.width() - cropW) / 2.;
82-
return QRectF(
83-
offset / imageSize.width(),
84-
0.,
85-
cropW / imageSize.width(),
86-
1.);
87-
} else if (imageAspect < targetAspect) {
88-
const auto cropH = imageSize.width() / targetAspect;
89-
const auto offset = (imageSize.height() - cropH) / 2.;
90-
return QRectF(
91-
0.,
92-
offset / imageSize.height(),
93-
1.,
94-
cropH / imageSize.height());
95-
}
96-
return QRectF(0., 0., 1., 1.);
97-
}
98-
9971
[[nodiscard]] QShader LoadShader(const QString &name) {
10072
return Ui::Rhi::ShaderFromFile(
10173
u":/shaders/"_q + name + u".qsb"_q);

‎Telegram/SourceFiles/media/view/media_view_pip_opengl.cpp‎

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -630,20 +630,28 @@ void Pip::RendererGL::paintButton(
630630

631631
auto Pip::RendererGL::ControlMeta(OverState control, int index)
632632
-> Control {
633+
if (const auto result = FindControlMeta(control, index)) {
634+
return *result;
635+
}
636+
Unexpected("Control value in Pip::RendererGL::ControlIndex.");
637+
}
638+
639+
auto Pip::Renderer::FindControlMeta(OverState control, int index)
640+
-> std::optional<Control> {
633641
Expects(index >= 0);
634642

635643
switch (control) {
636-
case OverState::Close: Assert(index < 1); return {
644+
case OverState::Close: Assert(index < 1); return Control{
637645
0,
638646
&st::pipCloseIcon,
639647
&st::pipCloseIconOver,
640648
};
641-
case OverState::Enlarge: Assert(index < 1); return {
649+
case OverState::Enlarge: Assert(index < 1); return Control{
642650
1,
643651
&st::pipEnlargeIcon,
644652
&st::pipEnlargeIconOver,
645653
};
646-
case OverState::VolumeToggle: Assert(index < 3); return {
654+
case OverState::VolumeToggle: Assert(index < 3); return Control{
647655
(2 + index),
648656
(index == 0
649657
? &st::pipVolumeIcon0
@@ -656,13 +664,13 @@ auto Pip::RendererGL::ControlMeta(OverState control, int index)
656664
? &st::pipVolumeIcon1Over
657665
: &st::pipVolumeIcon2Over),
658666
};
659-
case OverState::Other: Assert(index < 2); return {
667+
case OverState::Other: Assert(index < 2); return Control{
660668
(5 + index),
661669
(index ? &st::pipPauseIcon : &st::pipPlayIcon),
662670
(index ? &st::pipPauseIconOver : &st::pipPlayIconOver),
663671
};
664672
}
665-
Unexpected("Control value in Pip::RendererGL::ControlIndex.");
673+
return std::nullopt;
666674
}
667675

668676
void Pip::RendererGL::validateControls() {
@@ -678,6 +686,14 @@ void Pip::RendererGL::validateControls() {
678686
ControlMeta(OverState::Other),
679687
ControlMeta(OverState::Other, 1),
680688
};
689+
_controlsImage.setImage(
690+
PrepareControlsImage(metas, _controlsTextures, _ifactor));
691+
}
692+
693+
QImage Pip::Renderer::PrepareControlsImage(
694+
std::initializer_list<Control> metas,
695+
std::array<QRect, kControlsCount * 2> &textures,
696+
int factor) {
681697
auto maxWidth = 0;
682698
auto fullHeight = 0;
683699
for (const auto &meta : metas) {
@@ -686,27 +702,27 @@ void Pip::RendererGL::validateControls() {
686702
fullHeight += 2 * meta.icon->height();
687703
}
688704
auto image = QImage(
689-
QSize(maxWidth, fullHeight) * _ifactor,
705+
QSize(maxWidth, fullHeight) * factor,
690706
QImage::Format_ARGB32_Premultiplied);
691707
image.fill(Qt::transparent);
692-
image.setDevicePixelRatio(_ifactor);
708+
image.setDevicePixelRatio(factor);
693709
{
694710
auto p = QPainter(&image);
695711
auto index = 0;
696712
auto height = 0;
697713
const auto paint = [&](not_null<const style::icon*> icon) {
698714
icon->paint(p, 0, height, maxWidth);
699-
_controlsTextures[index++] = QRect(
700-
QPoint(0, height) * _ifactor,
701-
icon->size() * _ifactor);
715+
textures[index++] = QRect(
716+
QPoint(0, height) * factor,
717+
icon->size() * factor);
702718
height += icon->height();
703719
};
704720
for (const auto &meta : metas) {
705721
paint(meta.icon);
706722
paint(meta.iconOver);
707723
}
708724
}
709-
_controlsImage.setImage(std::move(image));
725+
return image;
710726
}
711727

712728
void Pip::RendererGL::invalidateControls() {

‎Telegram/SourceFiles/media/view/media_view_pip_opengl.h‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ class Pip::RendererGL final : public Pip::Renderer {
3030
std::optional<QColor> clearColor() override;
3131

3232
private:
33-
struct Control {
34-
int index = -1;
35-
not_null<const style::icon*> icon;
36-
not_null<const style::icon*> iconOver;
37-
};
3833
void createShadowTexture();
3934

4035
void paintTransformedVideoFrame(ContentGeometry geometry) override;
@@ -115,7 +110,6 @@ class Pip::RendererGL final : public Pip::Renderer {
115110
Ui::GL::Image _volumeControllerImage;
116111
Ui::GL::Image _shadowImage;
117112

118-
static constexpr auto kControlsCount = 7;
119113
[[nodiscard]] static Control ControlMeta(
120114
OverState control,
121115
int index = 0);

‎Telegram/SourceFiles/media/view/media_view_pip_renderer.h‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ class Pip::Renderer : public Ui::GL::Renderer {
3232
virtual void paintPlayback(QRect outer, float64 shown) = 0;
3333
virtual void paintVolumeController(QRect outer, float64 shown) = 0;
3434

35+
protected:
36+
struct Control {
37+
int index = -1;
38+
not_null<const style::icon*> icon;
39+
not_null<const style::icon*> iconOver;
40+
};
41+
static constexpr auto kControlsCount = 7;
42+
43+
[[nodiscard]] static std::optional<Control> FindControlMeta(
44+
OverState control,
45+
int index);
46+
[[nodiscard]] static QImage PrepareControlsImage(
47+
std::initializer_list<Control> metas,
48+
std::array<QRect, kControlsCount * 2> &textures,
49+
int factor);
50+
3551
};
3652

3753
} // namespace Media::View

‎Telegram/SourceFiles/media/view/media_view_pip_rhi.cpp‎

Lines changed: 4 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,37 +1059,8 @@ void Pip::RendererRhi::paintButton(
10591059

10601060
auto Pip::RendererRhi::ControlMeta(OverState control, int index)
10611061
-> Control {
1062-
Expects(index >= 0);
1063-
1064-
switch (control) {
1065-
case OverState::Close: Assert(index < 1); return {
1066-
0,
1067-
&st::pipCloseIcon,
1068-
&st::pipCloseIconOver,
1069-
};
1070-
case OverState::Enlarge: Assert(index < 1); return {
1071-
1,
1072-
&st::pipEnlargeIcon,
1073-
&st::pipEnlargeIconOver,
1074-
};
1075-
case OverState::VolumeToggle: Assert(index < 3); return {
1076-
(2 + index),
1077-
(index == 0
1078-
? &st::pipVolumeIcon0
1079-
: (index == 1)
1080-
? &st::pipVolumeIcon1
1081-
: &st::pipVolumeIcon2),
1082-
(index == 0
1083-
? &st::pipVolumeIcon0Over
1084-
: (index == 1)
1085-
? &st::pipVolumeIcon1Over
1086-
: &st::pipVolumeIcon2Over),
1087-
};
1088-
case OverState::Other: Assert(index < 2); return {
1089-
(5 + index),
1090-
(index ? &st::pipPauseIcon : &st::pipPlayIcon),
1091-
(index ? &st::pipPauseIconOver : &st::pipPlayIconOver),
1092-
};
1062+
if (const auto result = FindControlMeta(control, index)) {
1063+
return *result;
10931064
}
10941065
Unexpected("Control value in Pip::RendererRhi::ControlIndex.");
10951066
}
@@ -1107,35 +1078,8 @@ void Pip::RendererRhi::validateControls() {
11071078
ControlMeta(OverState::Other),
11081079
ControlMeta(OverState::Other, 1),
11091080
};
1110-
auto maxWidth = 0;
1111-
auto fullHeight = 0;
1112-
for (const auto &meta : metas) {
1113-
Assert(meta.icon->size() == meta.iconOver->size());
1114-
maxWidth = std::max(meta.icon->width(), maxWidth);
1115-
fullHeight += 2 * meta.icon->height();
1116-
}
1117-
auto image = QImage(
1118-
QSize(maxWidth, fullHeight) * _ifactor,
1119-
QImage::Format_ARGB32_Premultiplied);
1120-
image.fill(Qt::transparent);
1121-
image.setDevicePixelRatio(_ifactor);
1122-
{
1123-
auto p = QPainter(&image);
1124-
auto index = 0;
1125-
auto height = 0;
1126-
const auto paint = [&](not_null<const style::icon*> icon) {
1127-
icon->paint(p, 0, height, maxWidth);
1128-
_controlsTextures[index++] = QRect(
1129-
QPoint(0, height) * _ifactor,
1130-
icon->size() * _ifactor);
1131-
height += icon->height();
1132-
};
1133-
for (const auto &meta : metas) {
1134-
paint(meta.icon);
1135-
paint(meta.iconOver);
1136-
}
1137-
}
1138-
_controlsImage.setImage(std::move(image));
1081+
_controlsImage.setImage(
1082+
PrepareControlsImage(metas, _controlsTextures, _ifactor));
11391083
}
11401084

11411085
void Pip::RendererRhi::invalidateControls() {

‎Telegram/SourceFiles/media/view/media_view_pip_rhi.h‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,6 @@ class Pip::RendererRhi final
5454
}
5555

5656
private:
57-
struct Control {
58-
int index = -1;
59-
not_null<const style::icon*> icon;
60-
not_null<const style::icon*> iconOver;
61-
};
62-
6357
void paintTransformedVideoFrame(ContentGeometry geometry) override;
6458
void paintTransformedStaticContent(
6559
const QImage &image,
@@ -166,7 +160,6 @@ class Pip::RendererRhi final
166160
Ui::Rhi::Image _playbackImage;
167161
Ui::Rhi::Image _volumeControllerImage;
168162

169-
static constexpr auto kControlsCount = 7;
170163
static constexpr auto kMaxDraws = 12;
171164
static constexpr auto kVertexSlotSize = 4 * 6 * sizeof(float);
172165
std::array<QRect, kControlsCount * 2> _controlsTextures;

0 commit comments

Comments
 (0)