mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 15:47:11 +02:00
Start OpenGL media viewer renderer.
This commit is contained in:
parent
fc78769e9c
commit
24f8a88625
18 changed files with 1019 additions and 578 deletions
|
@ -777,6 +777,11 @@ PRIVATE
|
|||
media/streaming/media_streaming_video_track.h
|
||||
media/view/media_view_group_thumbs.cpp
|
||||
media/view/media_view_group_thumbs.h
|
||||
media/view/media_view_overlay_opengl.cpp
|
||||
media/view/media_view_overlay_opengl.h
|
||||
media/view/media_view_overlay_raster.cpp
|
||||
media/view/media_view_overlay_raster.h
|
||||
media/view/media_view_overlay_renderer.h
|
||||
media/view/media_view_overlay_widget.cpp
|
||||
media/view/media_view_overlay_widget.h
|
||||
media/view/media_view_pip.cpp
|
||||
|
|
|
@ -349,7 +349,9 @@ EditColorBox::Slider::Slider(
|
|||
, _type(type)
|
||||
, _color(color.red(), color.green(), color.blue())
|
||||
, _value(valueFromColor(color))
|
||||
, _transparent((_type == Type::Opacity) ? style::transparentPlaceholderBrush() : QBrush()) {
|
||||
, _transparent((_type == Type::Opacity)
|
||||
? style::TransparentPlaceholder()
|
||||
: QBrush()) {
|
||||
prepareMinSize();
|
||||
}
|
||||
|
||||
|
@ -758,7 +760,7 @@ EditColorBox::EditColorBox(
|
|||
, _greenField(this, st::colorValueInput, "G", 255)
|
||||
, _blueField(this, st::colorValueInput, "B", 255)
|
||||
, _result(this, st::colorResultInput)
|
||||
, _transparent(style::transparentPlaceholderBrush())
|
||||
, _transparent(style::TransparentPlaceholder())
|
||||
, _current(current)
|
||||
, _new(current) {
|
||||
if (_mode == Mode::RGBA) {
|
||||
|
|
|
@ -798,7 +798,7 @@ Ui::GL::ChosenRenderer Viewport::chooseRenderer(
|
|||
};
|
||||
}
|
||||
return {
|
||||
.renderer = std::make_unique<Renderer>(this),
|
||||
.renderer = std::make_unique<RendererSW>(this),
|
||||
.backend = Ui::GL::Backend::Raster,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ public:
|
|||
private:
|
||||
struct Textures;
|
||||
class VideoTile;
|
||||
class Renderer;
|
||||
class RendererSW;
|
||||
class RendererGL;
|
||||
using TileId = quintptr;
|
||||
|
||||
|
|
|
@ -174,90 +174,6 @@ vec4 background() {
|
|||
} };
|
||||
}
|
||||
|
||||
void FillRectVertices(GLfloat *coords, Rect rect) {
|
||||
coords[0] = coords[10] = rect.left();
|
||||
coords[1] = coords[11] = rect.top();
|
||||
coords[2] = rect.right();
|
||||
coords[3] = rect.top();
|
||||
coords[4] = coords[6] = rect.right();
|
||||
coords[5] = coords[7] = rect.bottom();
|
||||
coords[8] = rect.left();
|
||||
coords[9] = rect.bottom();
|
||||
}
|
||||
|
||||
void FillTriangles(
|
||||
QOpenGLFunctions &f,
|
||||
gsl::span<const GLfloat> coords,
|
||||
not_null<QOpenGLBuffer*> buffer,
|
||||
not_null<QOpenGLShaderProgram*> program,
|
||||
QSize viewportWithFactor,
|
||||
const QColor &color,
|
||||
Fn<void()> additional = nullptr) {
|
||||
Expects(coords.size() % 6 == 0);
|
||||
|
||||
if (coords.empty()) {
|
||||
return;
|
||||
}
|
||||
buffer->bind();
|
||||
buffer->allocate(coords.data(), coords.size() * sizeof(GLfloat));
|
||||
|
||||
f.glUseProgram(program->programId());
|
||||
program->setUniformValue("viewport", QSizeF(viewportWithFactor));
|
||||
program->setUniformValue("s_color", Uniform(color));
|
||||
|
||||
GLint position = program->attributeLocation("position");
|
||||
f.glVertexAttribPointer(
|
||||
position,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
2 * sizeof(GLfloat),
|
||||
nullptr);
|
||||
f.glEnableVertexAttribArray(position);
|
||||
|
||||
if (additional) {
|
||||
additional();
|
||||
}
|
||||
|
||||
f.glDrawArrays(GL_TRIANGLES, 0, coords.size() / 2);
|
||||
|
||||
f.glDisableVertexAttribArray(position);
|
||||
}
|
||||
|
||||
void FillTexturedRectangle(
|
||||
QOpenGLFunctions &f,
|
||||
not_null<QOpenGLShaderProgram*> program,
|
||||
int skipVertices = 0) {
|
||||
const auto shift = [&](int elements) {
|
||||
return reinterpret_cast<const void*>(
|
||||
(skipVertices * 4 + elements) * sizeof(GLfloat));
|
||||
};
|
||||
GLint position = program->attributeLocation("position");
|
||||
f.glVertexAttribPointer(
|
||||
position,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
4 * sizeof(GLfloat),
|
||||
shift(0));
|
||||
f.glEnableVertexAttribArray(position);
|
||||
|
||||
GLint texcoord = program->attributeLocation("v_texcoordIn");
|
||||
f.glVertexAttribPointer(
|
||||
texcoord,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
4 * sizeof(GLfloat),
|
||||
shift(2));
|
||||
f.glEnableVertexAttribArray(texcoord);
|
||||
|
||||
f.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
f.glDisableVertexAttribArray(position);
|
||||
f.glDisableVertexAttribArray(texcoord);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Viewport::RendererGL::RendererGL(not_null<Viewport*> owner)
|
||||
|
@ -319,14 +235,7 @@ void Viewport::RendererGL::init(
|
|||
FragmentRoundCorners(),
|
||||
})).vertex;
|
||||
|
||||
_bgBuffer.emplace();
|
||||
_bgBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
|
||||
_bgBuffer->create();
|
||||
_bgProgram.emplace();
|
||||
LinkProgram(
|
||||
&*_bgProgram,
|
||||
VertexShader({ VertexViewportTransform() }),
|
||||
FragmentShader({ FragmentStaticColor() }));
|
||||
_background.init(f);
|
||||
|
||||
_imageProgram.emplace();
|
||||
LinkProgram(
|
||||
|
@ -366,10 +275,8 @@ void Viewport::RendererGL::ensureARGB32Program() {
|
|||
void Viewport::RendererGL::deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) {
|
||||
_bgBuffer = std::nullopt;
|
||||
_frameBuffer = std::nullopt;
|
||||
_frameVertexShader = nullptr;
|
||||
_bgProgram = std::nullopt;
|
||||
_imageProgram = std::nullopt;
|
||||
_downscaleProgram.argb32 = std::nullopt;
|
||||
_downscaleProgram.yuv420 = std::nullopt;
|
||||
|
@ -381,6 +288,7 @@ void Viewport::RendererGL::deinit(
|
|||
}
|
||||
_tileData.clear();
|
||||
_tileDataIndices.clear();
|
||||
_background.deinit(f);
|
||||
_buttons.destroy(f);
|
||||
}
|
||||
|
||||
|
@ -422,28 +330,13 @@ void Viewport::RendererGL::paint(
|
|||
void Viewport::RendererGL::fillBackground(QOpenGLFunctions &f) {
|
||||
const auto radius = st::roundRadiusLarge;
|
||||
const auto radiuses = QMargins{ radius, radius, radius, radius };
|
||||
auto bg = QRegion(QRect(QPoint(), _viewport));
|
||||
auto region = QRegion(QRect(QPoint(), _viewport));
|
||||
for (const auto &tile : _owner->_tiles) {
|
||||
if (tile->shown()) {
|
||||
bg -= tile->geometry().marginsRemoved(radiuses);
|
||||
region -= tile->geometry().marginsRemoved(radiuses);
|
||||
}
|
||||
}
|
||||
if (bg.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
_bgTriangles.resize((bg.end() - bg.begin()) * 12);
|
||||
auto coords = _bgTriangles.data();
|
||||
for (const auto rect : bg) {
|
||||
FillRectVertices(coords, transformRect(rect));
|
||||
coords += 12;
|
||||
}
|
||||
FillTriangles(
|
||||
f,
|
||||
_bgTriangles,
|
||||
&*_bgBuffer,
|
||||
&*_bgProgram,
|
||||
_viewport * _factor,
|
||||
st::groupCallBg->c);
|
||||
_background.fill(f, region, _viewport, _factor, st::groupCallBg);
|
||||
}
|
||||
|
||||
void Viewport::RendererGL::paintTile(
|
||||
|
@ -957,12 +850,7 @@ void Viewport::RendererGL::drawFirstBlurPass(
|
|||
}
|
||||
|
||||
Rect Viewport::RendererGL::transformRect(const Rect &raster) const {
|
||||
return {
|
||||
raster.left() * _factor,
|
||||
float(_viewport.height() - raster.bottom()) * _factor,
|
||||
raster.width() * _factor,
|
||||
raster.height() * _factor,
|
||||
};
|
||||
return TransformRect(raster, _viewport, _factor);
|
||||
}
|
||||
|
||||
Rect Viewport::RendererGL::transformRect(const QRect &raster) const {
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/round_rect.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/cross_line.h"
|
||||
#include "ui/gl/gl_primitives.h"
|
||||
#include "ui/gl/gl_surface.h"
|
||||
#include "ui/gl/gl_image.h"
|
||||
|
||||
|
@ -116,13 +117,12 @@ private:
|
|||
GLfloat _factor = 1.;
|
||||
QSize _viewport;
|
||||
bool _rgbaFrame = false;
|
||||
Ui::GL::BackgroundFiller _background;
|
||||
std::optional<QOpenGLBuffer> _frameBuffer;
|
||||
std::optional<QOpenGLBuffer> _bgBuffer;
|
||||
Program _downscaleProgram;
|
||||
std::optional<QOpenGLShaderProgram> _blurProgram;
|
||||
Program _frameProgram;
|
||||
std::optional<QOpenGLShaderProgram> _imageProgram;
|
||||
std::optional<QOpenGLShaderProgram> _bgProgram;
|
||||
QOpenGLShader *_downscaleVertexShader = nullptr;
|
||||
QOpenGLShader *_frameVertexShader = nullptr;
|
||||
|
||||
|
@ -137,7 +137,6 @@ private:
|
|||
std::vector<TileData> _tileData;
|
||||
std::vector<int> _tileDataIndices;
|
||||
|
||||
std::vector<GLfloat> _bgTriangles;
|
||||
Ui::CrossLineAnimation _pinIcon;
|
||||
Ui::CrossLineAnimation _muteIcon;
|
||||
Ui::RoundRect _pinBackground;
|
||||
|
|
|
@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Calls::Group {
|
||||
|
||||
Viewport::Renderer::Renderer(not_null<Viewport*> owner)
|
||||
Viewport::RendererSW::RendererSW(not_null<Viewport*> owner)
|
||||
: _owner(owner)
|
||||
, _pinIcon(st::groupCallVideoTile.pin)
|
||||
, _pinBackground(
|
||||
|
@ -28,27 +28,25 @@ Viewport::Renderer::Renderer(not_null<Viewport*> owner)
|
|||
st::radialBg) {
|
||||
}
|
||||
|
||||
void Viewport::Renderer::paintFallback(
|
||||
void Viewport::RendererSW::paintFallback(
|
||||
Painter &&p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) {
|
||||
auto bg = clip;
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
const auto bounding = clip.boundingRect();
|
||||
const auto opengl = (backend == Ui::GL::Backend::OpenGL);
|
||||
for (const auto &tile : _owner->_tiles) {
|
||||
paintTile(p, tile.get(), bounding, opengl, bg);
|
||||
paintTile(p, tile.get(), bounding, bg);
|
||||
}
|
||||
for (const auto rect : bg) {
|
||||
p.fillRect(rect, st::groupCallBg);
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::Renderer::paintTile(
|
||||
void Viewport::RendererSW::paintTile(
|
||||
Painter &p,
|
||||
not_null<VideoTile*> tile,
|
||||
const QRect &clip,
|
||||
bool opengl,
|
||||
QRegion &bg) {
|
||||
const auto track = tile->track();
|
||||
const auto data = track->frameWithInfo(true);
|
||||
|
@ -79,7 +77,7 @@ void Viewport::Renderer::paintTile(
|
|||
const auto left = (width - scaled.width()) / 2;
|
||||
const auto top = (height - scaled.height()) / 2;
|
||||
const auto target = QRect(QPoint(x + left, y + top), scaled);
|
||||
if (UsePainterRotation(rotation, opengl)) {
|
||||
if (UsePainterRotation(rotation, false)) {
|
||||
if (rotation) {
|
||||
p.save();
|
||||
p.rotate(rotation);
|
||||
|
@ -113,7 +111,7 @@ void Viewport::Renderer::paintTile(
|
|||
paintTileOutline(p, x, y, width, height, tile);
|
||||
}
|
||||
|
||||
void Viewport::Renderer::paintTileOutline(
|
||||
void Viewport::RendererSW::paintTileOutline(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
|
@ -137,7 +135,7 @@ void Viewport::Renderer::paintTileOutline(
|
|||
p.fillRect(x, y + height - outline, width - outline, outline, color);
|
||||
}
|
||||
|
||||
void Viewport::Renderer::paintTileControls(
|
||||
void Viewport::RendererSW::paintTileControls(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
|
|
|
@ -15,9 +15,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Calls::Group {
|
||||
|
||||
class Viewport::Renderer final : public Ui::GL::Renderer {
|
||||
class Viewport::RendererSW final : public Ui::GL::Renderer {
|
||||
public:
|
||||
explicit Renderer(not_null<Viewport*> owner);
|
||||
explicit RendererSW(not_null<Viewport*> owner);
|
||||
|
||||
void paintFallback(
|
||||
Painter &&p,
|
||||
|
@ -29,7 +29,6 @@ private:
|
|||
Painter &p,
|
||||
not_null<VideoTile*> tile,
|
||||
const QRect &clip,
|
||||
bool opengl,
|
||||
QRegion &bg);
|
||||
void paintTileOutline(
|
||||
Painter &p,
|
||||
|
|
|
@ -237,7 +237,7 @@ mediaviewTextOpacity: 0.5;
|
|||
mediaviewTextOverOpacity: 1;
|
||||
|
||||
mediaviewIconOpacity: 0.45;
|
||||
mediaviewIconOverOpacity: 1;
|
||||
mediaviewIconOverOpacity: 1.;
|
||||
mediaviewControlBgOpacity: 0.3;
|
||||
mediaviewControlMargin: 0px;
|
||||
mediaviewControlSize: 90px;
|
||||
|
|
183
Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp
Normal file
183
Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "media/view/media_view_overlay_opengl.h"
|
||||
|
||||
#include "base/platform/base_platform_info.h"
|
||||
|
||||
namespace Media::View {
|
||||
|
||||
void OverlayWidget::RendererGL::init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) {
|
||||
_background.init(f);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) {
|
||||
_background.deinit(f);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::resize(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f,
|
||||
int w,
|
||||
int h) {
|
||||
_factor = widget->devicePixelRatio();
|
||||
_viewport = QSize(w, h);
|
||||
setDefaultViewport(f);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::setDefaultViewport(QOpenGLFunctions &f) {
|
||||
const auto size = _viewport * _factor;
|
||||
f.glViewport(0, 0, size.width(), size.height());
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paint(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) {
|
||||
if (handleHideWorkaround(f)) {
|
||||
return;
|
||||
}
|
||||
_f = &f;
|
||||
_owner->paint(this);
|
||||
}
|
||||
|
||||
bool OverlayWidget::RendererGL::handleHideWorkaround(QOpenGLFunctions &f) {
|
||||
if (!Platform::IsWindows() || !_owner->_hideWorkaround) {
|
||||
return false;
|
||||
}
|
||||
// This is needed on Windows,
|
||||
// because on reopen it blinks with the last shown content.
|
||||
f.glClearColor(0., 0., 0., 0.);
|
||||
f.glClear(GL_COLOR_BUFFER_BIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintBackground() {
|
||||
const auto &bg = _owner->_fullScreenVideo
|
||||
? st::mediaviewVideoBg
|
||||
: st::mediaviewBg;
|
||||
auto fill = QRegion(QRect(QPoint(), _viewport));
|
||||
if (_owner->opaqueContentShown()) {
|
||||
fill -= _owner->contentRect();
|
||||
}
|
||||
_background.fill(
|
||||
*_f,
|
||||
fill,
|
||||
_viewport,
|
||||
_factor,
|
||||
bg);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintTransformedVideoFrame(
|
||||
QRect rect,
|
||||
int rotation) {
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintTransformedStaticContent(
|
||||
const QImage &image,
|
||||
QRect rect,
|
||||
int rotation,
|
||||
bool fillTransparentBackground) {
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintRadialLoading(
|
||||
QRect inner,
|
||||
bool radial,
|
||||
float64 radialOpacity) {
|
||||
paintToCache(_radialCache, inner.size(), [&](Painter &&p) {
|
||||
const auto newInner = QRect(QPoint(), inner.size());
|
||||
_owner->paintRadialLoadingContent(p, newInner, radial, radialOpacity);
|
||||
}, true);
|
||||
//p.drawImage(inner.topLeft(), _radialCache);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintThemePreview(QRect outer) {
|
||||
paintToCache(_themePreviewCache, outer.size(), [&](Painter &&p) {
|
||||
const auto newOuter = QRect(QPoint(), outer.size());
|
||||
_owner->paintThemePreviewContent(p, newOuter, newOuter);
|
||||
});
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintDocumentBubble(
|
||||
QRect outer,
|
||||
QRect icon) {
|
||||
paintToCache(_documentBubbleCache, outer.size(), [&](Painter &&p) {
|
||||
const auto newOuter = QRect(QPoint(), outer.size());
|
||||
const auto newIcon = icon.translated(-outer.topLeft());
|
||||
_owner->paintDocumentBubbleContent(p, newOuter, newIcon, newOuter);
|
||||
});
|
||||
//p.drawImage(outer.topLeft(), _documentBubbleCache);
|
||||
_owner->paintRadialLoading(this);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintSaveMsg(QRect outer) {
|
||||
paintToCache(_saveMsgCache, outer.size(), [&](Painter &&p) {
|
||||
const auto newOuter = QRect(QPoint(), outer.size());
|
||||
_owner->paintSaveMsgContent(p, newOuter, newOuter);
|
||||
}, true);
|
||||
//p.drawImage(outer.topLeft(), _saveMsgCache);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintControl(
|
||||
OverState control,
|
||||
QRect outer,
|
||||
float64 outerOpacity,
|
||||
QRect inner,
|
||||
float64 innerOpacity,
|
||||
const style::icon &icon) {
|
||||
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintFooter(QRect outer, float64 opacity) {
|
||||
paintToCache(_footerCache, outer.size(), [&](Painter &&p) {
|
||||
const auto newOuter = QRect(QPoint(), outer.size());
|
||||
_owner->paintFooterContent(p, newOuter, newOuter, opacity);
|
||||
}, true);
|
||||
//p.drawImage(outer, _footerCache, QRect(QPoint(), outer.size()) * factor);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintCaption(QRect outer, float64 opacity) {
|
||||
paintToCache(_captionCache, outer.size(), [&](Painter &&p) {
|
||||
const auto newOuter = QRect(QPoint(), outer.size());
|
||||
_owner->paintCaptionContent(p, newOuter, newOuter, opacity);
|
||||
});
|
||||
//p.drawImage(outer, _captionCache, ...);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintGroupThumbs(
|
||||
QRect outer,
|
||||
float64 opacity) {
|
||||
paintToCache(_groupThumbsCache, outer.size(), [&](Painter &&p) {
|
||||
const auto newOuter = QRect(QPoint(), outer.size());
|
||||
_owner->paintGroupThumbsContent(p, newOuter, newOuter, opacity);
|
||||
});
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintToCache(
|
||||
QImage &cache,
|
||||
QSize size,
|
||||
Fn<void(Painter&&)> method,
|
||||
bool clear) {
|
||||
if (cache.width() < size.width() * _factor
|
||||
|| cache.height() < size.height() * _factor) {
|
||||
cache = QImage(
|
||||
size * _factor,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
cache.setDevicePixelRatio(_factor);
|
||||
} else if (cache.devicePixelRatio() != _factor) {
|
||||
cache.setDevicePixelRatio(_factor);
|
||||
}
|
||||
if (clear) {
|
||||
cache.fill(Qt::transparent);
|
||||
}
|
||||
method(Painter(&cache));
|
||||
}
|
||||
|
||||
} // namespace Media::View
|
91
Telegram/SourceFiles/media/view/media_view_overlay_opengl.h
Normal file
91
Telegram/SourceFiles/media/view/media_view_overlay_opengl.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "media/view/media_view_overlay_renderer.h"
|
||||
#include "ui/gl/gl_surface.h"
|
||||
#include "ui/gl/gl_primitives.h"
|
||||
|
||||
namespace Media::View {
|
||||
|
||||
class OverlayWidget::RendererGL final : public OverlayWidget::Renderer {
|
||||
public:
|
||||
RendererGL(not_null<OverlayWidget*> owner) : _owner(owner) {
|
||||
}
|
||||
|
||||
void init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) override;
|
||||
|
||||
void deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) override;
|
||||
|
||||
void resize(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f,
|
||||
int w,
|
||||
int h);
|
||||
|
||||
void paint(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) override;
|
||||
|
||||
private:
|
||||
bool handleHideWorkaround(QOpenGLFunctions &f);
|
||||
void setDefaultViewport(QOpenGLFunctions &f);
|
||||
|
||||
void paintBackground();
|
||||
void paintTransformedVideoFrame(QRect rect, int rotation) override;
|
||||
void paintTransformedStaticContent(
|
||||
const QImage &image,
|
||||
QRect rect,
|
||||
int rotation,
|
||||
bool fillTransparentBackground) override;
|
||||
void paintRadialLoading(
|
||||
QRect inner,
|
||||
bool radial,
|
||||
float64 radialOpacity) override;
|
||||
void paintThemePreview(QRect outer) override;
|
||||
void paintDocumentBubble(QRect outer, QRect icon) override;
|
||||
void paintSaveMsg(QRect outer) override;
|
||||
void paintControl(
|
||||
OverState control,
|
||||
QRect outer,
|
||||
float64 outerOpacity,
|
||||
QRect inner,
|
||||
float64 innerOpacity,
|
||||
const style::icon &icon) override;
|
||||
void paintFooter(QRect outer, float64 opacity) override;
|
||||
void paintCaption(QRect outer, float64 opacity) override;
|
||||
void paintGroupThumbs(QRect outer, float64 opacity) override;
|
||||
|
||||
void paintToCache(
|
||||
QImage &cache,
|
||||
QSize size,
|
||||
Fn<void(Painter&&)> method,
|
||||
bool clear = false);
|
||||
|
||||
const not_null<OverlayWidget*> _owner;
|
||||
|
||||
QOpenGLFunctions *_f = nullptr;
|
||||
Ui::GL::BackgroundFiller _background;
|
||||
QSize _viewport;
|
||||
float _factor = 1.;
|
||||
|
||||
QImage _radialCache;
|
||||
QImage _documentBubbleCache;
|
||||
QImage _themePreviewCache;
|
||||
QImage _saveMsgCache;
|
||||
QImage _footerCache;
|
||||
QImage _captionCache;
|
||||
QImage _groupThumbsCache;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Media::View
|
166
Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp
Normal file
166
Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "media/view/media_view_overlay_raster.h"
|
||||
|
||||
#include "media/view/media_view_pip.h"
|
||||
|
||||
namespace Media::View {
|
||||
|
||||
OverlayWidget::RendererSW::RendererSW(not_null<OverlayWidget*> owner)
|
||||
: _owner(owner)
|
||||
, _transparentBrush(style::TransparentPlaceholder()) {
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintFallback(
|
||||
Painter &&p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) {
|
||||
_p = &p;
|
||||
_clip = &clip;
|
||||
_clipOuter = clip.boundingRect();
|
||||
_owner->paint(this);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintBackground() {
|
||||
const auto region = _owner->opaqueContentShown()
|
||||
? (*_clip - _owner->contentRect())
|
||||
: *_clip;
|
||||
|
||||
const auto m = _p->compositionMode();
|
||||
_p->setCompositionMode(QPainter::CompositionMode_Source);
|
||||
const auto &bg = _owner->_fullScreenVideo
|
||||
? st::mediaviewVideoBg
|
||||
: st::mediaviewBg;
|
||||
for (const auto rect : region) {
|
||||
_p->fillRect(rect, bg);
|
||||
}
|
||||
_p->setCompositionMode(m);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintTransformedVideoFrame(
|
||||
QRect rect,
|
||||
int rotation) {
|
||||
Expects(_owner->_streamed != nullptr);
|
||||
|
||||
if (!rect.intersects(_clipOuter)) {
|
||||
return;
|
||||
}
|
||||
paintTransformedImage(_owner->videoFrame(), rect, rotation);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintTransformedStaticContent(
|
||||
const QImage &image,
|
||||
QRect rect,
|
||||
int rotation,
|
||||
bool fillTransparentBackground) {
|
||||
if (!rect.intersects(_clipOuter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fillTransparentBackground) {
|
||||
_p->fillRect(rect, _transparentBrush);
|
||||
}
|
||||
if (image.isNull()) {
|
||||
return;
|
||||
}
|
||||
paintTransformedImage(image, rect, rotation);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintTransformedImage(
|
||||
const QImage &image,
|
||||
QRect rect,
|
||||
int rotation) {
|
||||
PainterHighQualityEnabler hq(*_p);
|
||||
if (UsePainterRotation(rotation, false)) {
|
||||
if (rotation) {
|
||||
_p->save();
|
||||
_p->rotate(rotation);
|
||||
}
|
||||
_p->drawImage(RotatedRect(rect, rotation), image);
|
||||
if (rotation) {
|
||||
_p->restore();
|
||||
}
|
||||
} else {
|
||||
_p->drawImage(rect, _owner->transformShownContent(image, rotation));
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintRadialLoading(
|
||||
QRect inner,
|
||||
bool radial,
|
||||
float64 radialOpacity) {
|
||||
_owner->paintRadialLoadingContent(*_p, inner, radial, radialOpacity);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintThemePreview(QRect outer) {
|
||||
_owner->paintThemePreviewContent(*_p, outer, _clipOuter);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintDocumentBubble(
|
||||
QRect outer,
|
||||
QRect icon) {
|
||||
if (outer.intersects(_clipOuter)) {
|
||||
_owner->paintDocumentBubbleContent(*_p, outer, icon, _clipOuter);
|
||||
if (icon.intersects(_clipOuter)) {
|
||||
_owner->paintRadialLoading(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintSaveMsg(QRect outer) {
|
||||
if (outer.intersects(_clipOuter)) {
|
||||
_owner->paintSaveMsgContent(*_p, outer, _clipOuter);
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintControl(
|
||||
OverState control,
|
||||
QRect outer,
|
||||
float64 outerOpacity,
|
||||
QRect inner,
|
||||
float64 innerOpacity,
|
||||
const style::icon &icon) {
|
||||
if (!outer.isEmpty() && !outer.intersects(_clipOuter)) {
|
||||
return;
|
||||
}
|
||||
if (!outer.isEmpty() && outerOpacity > 0) {
|
||||
_p->setOpacity(outerOpacity);
|
||||
for (const auto &rect : *_clip) {
|
||||
const auto fill = outer.intersected(rect);
|
||||
if (!fill.isEmpty()) {
|
||||
_p->fillRect(fill, st::mediaviewControlBg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inner.intersects(_clipOuter)) {
|
||||
_p->setOpacity(innerOpacity);
|
||||
icon.paintInCenter(*_p, inner);
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintFooter(QRect outer, float64 opacity) {
|
||||
if (outer.intersects(_clipOuter)) {
|
||||
_owner->paintFooterContent(*_p, outer, _clipOuter, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintCaption(QRect outer, float64 opacity) {
|
||||
if (outer.intersects(_clipOuter)) {
|
||||
_owner->paintCaptionContent(*_p, outer, _clipOuter, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintGroupThumbs(
|
||||
QRect outer,
|
||||
float64 opacity) {
|
||||
if (outer.intersects(_clipOuter)) {
|
||||
_owner->paintGroupThumbsContent(*_p, outer, _clipOuter, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Media::View
|
63
Telegram/SourceFiles/media/view/media_view_overlay_raster.h
Normal file
63
Telegram/SourceFiles/media/view/media_view_overlay_raster.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "media/view/media_view_overlay_renderer.h"
|
||||
#include "ui/gl/gl_surface.h"
|
||||
|
||||
namespace Media::View {
|
||||
|
||||
class OverlayWidget::RendererSW final : public OverlayWidget::Renderer {
|
||||
public:
|
||||
RendererSW(not_null<OverlayWidget*> owner);
|
||||
|
||||
void paintFallback(
|
||||
Painter &&p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) override;
|
||||
|
||||
private:
|
||||
void paintBackground() override;
|
||||
void paintTransformedVideoFrame(QRect rect, int rotation) override;
|
||||
void paintTransformedStaticContent(
|
||||
const QImage &image,
|
||||
QRect rect,
|
||||
int rotation,
|
||||
bool fillTransparentBackground) override;
|
||||
void paintTransformedImage(
|
||||
const QImage &image,
|
||||
QRect rect,
|
||||
int rotation);
|
||||
void paintRadialLoading(
|
||||
QRect inner,
|
||||
bool radial,
|
||||
float64 radialOpacity) override;
|
||||
void paintThemePreview(QRect outer) override;
|
||||
void paintDocumentBubble(QRect outer, QRect icon) override;
|
||||
void paintSaveMsg(QRect outer) override;
|
||||
void paintControl(
|
||||
OverState control,
|
||||
QRect outer,
|
||||
float64 outerOpacity,
|
||||
QRect inner,
|
||||
float64 innerOpacity,
|
||||
const style::icon &icon) override;
|
||||
void paintFooter(QRect outer, float64 opacity) override;
|
||||
void paintCaption(QRect outer, float64 opacity) override;
|
||||
void paintGroupThumbs(QRect outer, float64 opacity) override;
|
||||
|
||||
const not_null<OverlayWidget*> _owner;
|
||||
QBrush _transparentBrush;
|
||||
|
||||
Painter *_p = nullptr;
|
||||
const QRegion *_clip = nullptr;
|
||||
QRect _clipOuter;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Media::View
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "media/view/media_view_overlay_widget.h"
|
||||
|
||||
namespace Media::View {
|
||||
|
||||
class OverlayWidget::Renderer : public Ui::GL::Renderer {
|
||||
public:
|
||||
virtual void paintBackground() = 0;
|
||||
virtual void paintTransformedVideoFrame(QRect rect, int rotation) = 0;
|
||||
virtual void paintTransformedStaticContent(
|
||||
const QImage &image,
|
||||
QRect rect,
|
||||
int rotation,
|
||||
bool fillTransparentBackground) = 0;
|
||||
virtual void paintRadialLoading(
|
||||
QRect inner,
|
||||
bool radial,
|
||||
float64 radialOpacity) = 0;
|
||||
virtual void paintThemePreview(QRect outer) = 0;
|
||||
virtual void paintDocumentBubble(QRect outer, QRect icon) = 0;
|
||||
virtual void paintSaveMsg(QRect outer) = 0;
|
||||
virtual void paintControl(
|
||||
OverState control,
|
||||
QRect outer,
|
||||
float64 outerOpacity,
|
||||
QRect inner,
|
||||
float64 innerOpacity,
|
||||
const style::icon &icon) = 0;
|
||||
virtual void paintFooter(QRect outer, float64 opacity) = 0;
|
||||
virtual void paintCaption(QRect outer, float64 opacity) = 0;
|
||||
virtual void paintGroupThumbs(QRect outer, float64 opacity) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Media::View
|
File diff suppressed because it is too large
Load diff
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "base/timer.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/gl/gl_surface.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/radial_animation.h"
|
||||
|
@ -50,8 +51,7 @@ enum class Error;
|
|||
} // namespace Streaming
|
||||
} // namespace Media
|
||||
|
||||
namespace Media {
|
||||
namespace View {
|
||||
namespace Media::View {
|
||||
|
||||
class GroupThumbs;
|
||||
class Pip;
|
||||
|
@ -111,7 +111,11 @@ public:
|
|||
private:
|
||||
struct Streamed;
|
||||
struct PipWrap;
|
||||
class Renderer;
|
||||
class RendererSW;
|
||||
class RendererGL;
|
||||
|
||||
// If changing, see paintControls()!
|
||||
enum OverState {
|
||||
OverNone,
|
||||
OverLeftNav,
|
||||
|
@ -147,7 +151,7 @@ private:
|
|||
|
||||
[[nodiscard]] Ui::GL::ChosenRenderer chooseRenderer(
|
||||
Ui::GL::Capabilities capabilities);
|
||||
void paint(Painter &p, const QRegion &clip);
|
||||
void paint(not_null<Renderer*> renderer);
|
||||
|
||||
void handleMousePress(QPoint position, Qt::MouseButton button);
|
||||
void handleMouseRelease(QPoint position, Qt::MouseButton button);
|
||||
|
@ -342,13 +346,39 @@ private:
|
|||
void zoomReset();
|
||||
void zoomUpdate(int32 &newZoom);
|
||||
|
||||
void paintRadialLoading(Painter &p, bool radial, float64 radialOpacity);
|
||||
void paintRadialLoading(not_null<Renderer*> renderer);
|
||||
void paintRadialLoadingContent(
|
||||
Painter &p,
|
||||
QRect inner,
|
||||
bool radial,
|
||||
float64 radialOpacity) const;
|
||||
void paintThemePreview(Painter &p, QRect clip);
|
||||
void paintThemePreviewContent(Painter &p, QRect outer, QRect clip);
|
||||
void paintDocumentBubbleContent(
|
||||
Painter &p,
|
||||
QRect outer,
|
||||
QRect icon,
|
||||
QRect clip) const;
|
||||
void paintSaveMsgContent(Painter &p, QRect outer, QRect clip);
|
||||
void paintControls(not_null<Renderer*> renderer, float64 opacity);
|
||||
void paintFooterContent(
|
||||
Painter &p,
|
||||
QRect outer,
|
||||
QRect clip,
|
||||
float64 opacity);
|
||||
[[nodiscard]] QRect footerGeometry() const;
|
||||
void paintCaptionContent(
|
||||
Painter &p,
|
||||
QRect outer,
|
||||
QRect clip,
|
||||
float64 opacity);
|
||||
[[nodiscard]] QRect captionGeometry() const;
|
||||
void paintGroupThumbsContent(
|
||||
Painter &p,
|
||||
QRect outer,
|
||||
QRect clip,
|
||||
float64 opacity);
|
||||
|
||||
void updateSaveMsgState();
|
||||
|
||||
void updateOverRect(OverState state);
|
||||
bool updateOverState(OverState newState);
|
||||
|
@ -367,13 +397,14 @@ private:
|
|||
[[nodiscard]] QSize videoSize() const;
|
||||
[[nodiscard]] bool videoIsGifOrUserpic() const;
|
||||
[[nodiscard]] QImage videoFrame() const;
|
||||
[[nodiscard]] QImage videoFrameForDirectPaint() const;
|
||||
[[nodiscard]] QImage transformVideoFrame(QImage frame) const;
|
||||
[[nodiscard]] QImage transformStaticContent(QPixmap content) const;
|
||||
[[nodiscard]] QImage transformedShownContent() const;
|
||||
[[nodiscard]] QImage transformShownContent(
|
||||
QImage content,
|
||||
int rotation) const;
|
||||
[[nodiscard]] bool documentContentShown() const;
|
||||
[[nodiscard]] bool documentBubbleShown() const;
|
||||
void paintTransformedVideoFrame(Painter &p);
|
||||
void paintTransformedStaticContent(Painter &p);
|
||||
[[nodiscard]] bool contentShown() const;
|
||||
[[nodiscard]] bool opaqueContentShown() const;
|
||||
void clearStreaming(bool savePosition = true);
|
||||
bool canInitStreaming() const;
|
||||
|
||||
|
@ -382,7 +413,6 @@ private:
|
|||
bool _opengl = false;
|
||||
const std::unique_ptr<Ui::RpWidgetWrap> _surface;
|
||||
const not_null<QWidget*> _widget;
|
||||
QBrush _transparentBrush;
|
||||
|
||||
Main::Session *_session = nullptr;
|
||||
rpl::lifetime _sessionLifetime;
|
||||
|
@ -436,7 +466,7 @@ private:
|
|||
QPoint _mStart;
|
||||
bool _pressed = false;
|
||||
int32 _dragging = 0;
|
||||
QPixmap _staticContent;
|
||||
QImage _staticContent;
|
||||
bool _blurred = true;
|
||||
|
||||
rpl::lifetime _screenGeometryLifetime;
|
||||
|
@ -451,6 +481,7 @@ private:
|
|||
QString _docName, _docSize, _docExt;
|
||||
int _docNameWidth = 0, _docSizeWidth = 0, _docExtWidth = 0;
|
||||
QRect _docRect, _docIconRect;
|
||||
QImage _docRectImage;
|
||||
int _docThumbx = 0, _docThumby = 0, _docThumbw = 0;
|
||||
object_ptr<Ui::LinkButton> _docDownload;
|
||||
object_ptr<Ui::LinkButton> _docSaveAs;
|
||||
|
@ -458,7 +489,6 @@ private:
|
|||
|
||||
QRect _photoRadialRect;
|
||||
Ui::RadialAnimation _radial;
|
||||
QImage _radialCache;
|
||||
|
||||
History *_migrated = nullptr;
|
||||
History *_history = nullptr; // if conversation photos or files overview
|
||||
|
@ -519,6 +549,7 @@ private:
|
|||
crl::time _saveMsgStarted = 0;
|
||||
anim::value _saveMsgOpacity;
|
||||
QRect _saveMsg;
|
||||
QImage _saveMsgImage;
|
||||
base::Timer _saveMsgUpdater;
|
||||
Ui::Text::String _saveMsgText;
|
||||
SavePhotoVideo _savePhotoVideoWhenLoaded = SavePhotoVideo::None;
|
||||
|
@ -545,5 +576,4 @@ private:
|
|||
|
||||
};
|
||||
|
||||
} // namespace View
|
||||
} // namespace Media
|
||||
} // namespace Media::View
|
||||
|
|
|
@ -165,7 +165,7 @@ void EditorBlock::Row::fillSearchIndex() {
|
|||
EditorBlock::EditorBlock(QWidget *parent, Type type, Context *context) : TWidget(parent)
|
||||
, _type(type)
|
||||
, _context(context)
|
||||
, _transparent(style::transparentPlaceholderBrush()) {
|
||||
, _transparent(style::TransparentPlaceholder()) {
|
||||
setMouseTracking(true);
|
||||
subscribe(_context->updated, [this] {
|
||||
if (_mouseSelection) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e6b736e718abd783e0ca32b471846f0ec38d0750
|
||||
Subproject commit 8b7aa442268a4928f7582d97b33cb624b29d0cde
|
Loading…
Add table
Reference in a new issue