diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.cpp b/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.cpp index 957d6a623a..f730d18aba 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.cpp @@ -28,6 +28,11 @@ constexpr auto kBlurTextureSizeFactor = 1.7; constexpr auto kBlurOpacity = 0.7; constexpr auto kMinCameraVisiblePart = 0.75; +constexpr auto kQuads = 7; +constexpr auto kQuadVertices = kQuads * 4; +constexpr auto kQuadValues = kQuadVertices * 4; +constexpr auto kValues = kQuadValues + 8; // Blur texture coordinates. + [[nodiscard]] ShaderPart FragmentBlurTexture( bool vertical, char prefix = 'v') { @@ -200,10 +205,6 @@ void Viewport::RendererGL::init( _frameBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw); _frameBuffer->create(); _frameBuffer->bind(); - constexpr auto kQuads = 7; - constexpr auto kQuadVertices = kQuads * 4; - constexpr auto kQuadValues = kQuadVertices * 4; - constexpr auto kValues = kQuadValues + 8; // Blur texture coordinates. _frameBuffer->allocate(kValues * sizeof(GLfloat)); _downscaleProgram.yuv420.emplace(); _downscaleVertexShader = LinkProgram( @@ -235,8 +236,6 @@ void Viewport::RendererGL::init( FragmentRoundCorners(), })).vertex; - _background.init(f); - _imageProgram.emplace(); LinkProgram( &*_imageProgram, @@ -247,6 +246,8 @@ void Viewport::RendererGL::init( FragmentShader({ FragmentSampleARGB32Texture(), })); + + _background.init(f); } void Viewport::RendererGL::ensureARGB32Program() { @@ -275,6 +276,8 @@ void Viewport::RendererGL::ensureARGB32Program() { void Viewport::RendererGL::deinit( not_null widget, QOpenGLFunctions &f) { + _background.deinit(f); + _frameBuffer = std::nullopt; _frameVertexShader = nullptr; _imageProgram = std::nullopt; @@ -288,7 +291,6 @@ void Viewport::RendererGL::deinit( } _tileData.clear(); _tileDataIndices.clear(); - _background.deinit(f); _buttons.destroy(f); } @@ -545,13 +547,13 @@ void Viewport::RendererGL::paintTile( name.texture.left(), name.texture.top(), }; + _frameBuffer->bind(); + _frameBuffer->write(0, coords, sizeof(coords)); + const auto blurSize = CountBlurredSize(unscaled, _viewport, _factor); prepareObjects(f, tileData, blurSize); f.glViewport(0, 0, blurSize.width(), blurSize.height()); - _frameBuffer->bind(); - _frameBuffer->write(0, coords, sizeof(coords)); - bindFrame(f, data, tileData, _downscaleProgram); tile->track()->markFrameShown(); @@ -716,52 +718,17 @@ void Viewport::RendererGL::bindFrame( Program &program) { const auto upload = (tileData.trackIndex != data.index); tileData.trackIndex = data.index; - const auto uploadOne = [&]( - GLint internalformat, - GLint format, - QSize size, - QSize hasSize, - int stride, - const void *data) { - f.glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); - if (hasSize != size) { - f.glTexImage2D( - GL_TEXTURE_2D, - 0, - internalformat, - size.width(), - size.height(), - 0, - format, - GL_UNSIGNED_BYTE, - data); - } else { - f.glTexSubImage2D( - GL_TEXTURE_2D, - 0, - 0, - 0, - size.width(), - size.height(), - format, - GL_UNSIGNED_BYTE, - data); - } - f.glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - }; - //if (upload) { - // tileData.textureIndex = 1 - tileData.textureIndex; - //} if (_rgbaFrame) { ensureARGB32Program(); f.glUseProgram(program.argb32->programId()); f.glActiveTexture(GL_TEXTURE0); - tileData.textures.bind(f, tileData.textureIndex); + tileData.textures.bind(f, tileData.textureIndex * 5 + 0); if (upload) { const auto &image = data.original; const auto stride = image.bytesPerLine() / 4; const auto data = image.constBits(); - uploadOne( + uploadTexture( + f, GL_RGBA, GL_RGBA, image.size(), @@ -769,6 +736,7 @@ void Viewport::RendererGL::bindFrame( stride, data); tileData.rgbaSize = image.size(); + tileData.textureSize = QSize(); } program.argb32->setUniformValue("s_texture", GLint(0)); } else { @@ -778,7 +746,8 @@ void Viewport::RendererGL::bindFrame( tileData.textures.bind(f, tileData.textureIndex * 5 + 0); if (upload) { f.glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - uploadOne( + uploadTexture( + f, GL_RED, GL_RED, yuv->size, @@ -786,11 +755,13 @@ void Viewport::RendererGL::bindFrame( yuv->y.stride, yuv->y.data); tileData.textureSize = yuv->size; + tileData.rgbaSize = QSize(); } f.glActiveTexture(GL_TEXTURE1); tileData.textures.bind(f, tileData.textureIndex * 5 + 1); if (upload) { - uploadOne( + uploadTexture( + f, GL_RED, GL_RED, yuv->chromaSize, @@ -801,7 +772,8 @@ void Viewport::RendererGL::bindFrame( f.glActiveTexture(GL_TEXTURE2); tileData.textures.bind(f, tileData.textureIndex * 5 + 2); if (upload) { - uploadOne( + uploadTexture( + f, GL_RED, GL_RED, yuv->chromaSize, @@ -817,6 +789,41 @@ void Viewport::RendererGL::bindFrame( } } +void Viewport::RendererGL::uploadTexture( + QOpenGLFunctions &f, + GLint internalformat, + GLint format, + QSize size, + QSize hasSize, + int stride, + const void *data) const { + f.glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); + if (hasSize != size) { + f.glTexImage2D( + GL_TEXTURE_2D, + 0, + internalformat, + size.width(), + size.height(), + 0, + format, + GL_UNSIGNED_BYTE, + data); + } else { + f.glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + size.width(), + size.height(), + format, + GL_UNSIGNED_BYTE, + data); + } + f.glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +} + void Viewport::RendererGL::drawDownscalePass( QOpenGLFunctions &f, TileData &tileData) { @@ -854,12 +861,7 @@ Rect Viewport::RendererGL::transformRect(const Rect &raster) const { } Rect Viewport::RendererGL::transformRect(const QRect &raster) const { - return { - raster.x() * _factor, - (_viewport.height() - raster.y() - raster.height()) * _factor, - raster.width() * _factor, - raster.height() * _factor, - }; + return TransformRect(Rect(raster), _viewport, _factor); } void Viewport::RendererGL::ensureButtonsImage() { diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.h b/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.h index 244420c655..8966f911f1 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.h +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.h @@ -103,6 +103,15 @@ private: not_null tile, TileData &data); + void uploadTexture( + QOpenGLFunctions &f, + GLint internalformat, + GLint format, + QSize size, + QSize hasSize, + int stride, + const void *data) const; + [[nodiscard]] bool isExpanded( not_null tile, QSize unscaled, diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp index ffadd28be9..2b9b0556f0 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp @@ -7,13 +7,68 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "media/view/media_view_overlay_opengl.h" +#include "ui/gl/gl_shader.h" #include "base/platform/base_platform_info.h" namespace Media::View { +namespace { + +using namespace Ui::GL; + +constexpr auto kQuads = 8; +constexpr auto kQuadVertices = kQuads * 4; +constexpr auto kQuadValues = kQuadVertices * 4; +constexpr auto kControls = 6; +constexpr auto kControlValues = 2 * 4 + 4 * 4; +constexpr auto kControlsValues = kControls * kControlValues; +constexpr auto kValues = kQuadValues + kControlsValues; + +constexpr auto kRadialLoadingOffset = 4; +constexpr auto kThemePreviewOffset = kRadialLoadingOffset + 4; +constexpr auto kDocumentBubbleOffset = kThemePreviewOffset + 4; +constexpr auto kSaveMsgOffset = kDocumentBubbleOffset + 4; +constexpr auto kFooterOffset = kSaveMsgOffset + 4; +constexpr auto kCaptionOffset = kFooterOffset + 4; +constexpr auto kGroupThumbsOffset = kCaptionOffset + 4; + +} // namespace + +OverlayWidget::RendererGL::RendererGL(not_null owner) +: _owner(owner) { + style::PaletteChanged( + ) | rpl::start_with_next([=] { + _radialImage.invalidate(); + _documentBubbleImage.invalidate(); + _themePreviewImage.invalidate(); + _saveMsgImage.invalidate(); + _footerImage.invalidate(); + _captionImage.invalidate(); + }, _lifetime); +} void OverlayWidget::RendererGL::init( not_null widget, QOpenGLFunctions &f) { + _factor = widget->devicePixelRatio(); + _contentBuffer.emplace(); + _contentBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw); + _contentBuffer->create(); + _contentBuffer->bind(); + _contentBuffer->allocate(kValues * sizeof(GLfloat)); + + _textures.ensureCreated(f); + + _imageProgram.emplace(); + LinkProgram( + &*_imageProgram, + VertexShader({ + VertexViewportTransform(), + VertexPassTextureCoord(), + }), + FragmentShader({ + FragmentSampleARGB32Texture(), + })); + _background.init(f); } @@ -21,6 +76,9 @@ void OverlayWidget::RendererGL::deinit( not_null widget, QOpenGLFunctions &f) { _background.deinit(f); + _textures.destroy(f); + _imageProgram = std::nullopt; + _contentBuffer = std::nullopt; } void OverlayWidget::RendererGL::resize( @@ -46,6 +104,7 @@ void OverlayWidget::RendererGL::paint( } _f = &f; _owner->paint(this); + _f = nullptr; } bool OverlayWidget::RendererGL::handleHideWorkaround(QOpenGLFunctions &f) { @@ -67,6 +126,7 @@ void OverlayWidget::RendererGL::paintBackground() { if (_owner->opaqueContentShown()) { fill -= _owner->contentRect(); } + toggleBlending(false); _background.fill( *_f, fill, @@ -78,6 +138,11 @@ void OverlayWidget::RendererGL::paintBackground() { void OverlayWidget::RendererGL::paintTransformedVideoFrame( QRect rect, int rotation) { + paintTransformedStaticContent( + _owner->videoFrame(), + rect, + rotation, + false); } void OverlayWidget::RendererGL::paintTransformedStaticContent( @@ -85,44 +150,131 @@ void OverlayWidget::RendererGL::paintTransformedStaticContent( QRect rect, int rotation, bool fillTransparentBackground) { + AssertIsDebug(fillTransparentBackground); + auto texCoords = std::array, 4> { { + { { 0.f, 1.f } }, + { { 1.f, 1.f } }, + { { 1.f, 0.f } }, + { { 0.f, 0.f } }, + } }; + if (const auto shift = (rotation / 90); shift > 0) { + std::rotate( + texCoords.begin(), + texCoords.begin() + shift, + texCoords.end()); + } + + const auto geometry = transformRect(rect); + const GLfloat coords[] = { + geometry.left(), geometry.top(), + texCoords[0][0], texCoords[0][1], + + geometry.right(), geometry.top(), + texCoords[1][0], texCoords[1][1], + + geometry.right(), geometry.bottom(), + texCoords[2][0], texCoords[2][1], + + geometry.left(), geometry.bottom(), + texCoords[3][0], texCoords[3][1], + }; + + _contentBuffer->bind(); + _contentBuffer->write(0, coords, sizeof(coords)); + + _f->glUseProgram(_imageProgram->programId()); + _imageProgram->setUniformValue("viewport", QSizeF(_viewport * _factor)); + _imageProgram->setUniformValue("s_texture", GLint(0)); + + _f->glActiveTexture(GL_TEXTURE0); + _textures.bind(*_f, 0); + const auto cacheKey = image.cacheKey(); + const auto upload = (_cacheKey != cacheKey); + if (upload) { + const auto stride = image.bytesPerLine() / 4; + const auto data = image.constBits(); + uploadTexture( + GL_RGBA, + GL_RGBA, + image.size(), + _rgbaSize, + stride, + data); + _rgbaSize = image.size(); + _ySize = QSize(); + } + + toggleBlending(false); + FillTexturedRectangle(*_f, &*_imageProgram); +} + +void OverlayWidget::RendererGL::uploadTexture( + GLint internalformat, + GLint format, + QSize size, + QSize hasSize, + int stride, + const void *data) const { + _f->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); + if (hasSize != size) { + _f->glTexImage2D( + GL_TEXTURE_2D, + 0, + internalformat, + size.width(), + size.height(), + 0, + format, + GL_UNSIGNED_BYTE, + data); + } else { + _f->glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + size.width(), + size.height(), + format, + GL_UNSIGNED_BYTE, + data); + } + _f->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } void OverlayWidget::RendererGL::paintRadialLoading( QRect inner, bool radial, float64 radialOpacity) { - paintToCache(_radialCache, inner.size(), [&](Painter &&p) { + paintUsingRaster(_radialImage, inner, [&](Painter &&p) { const auto newInner = QRect(QPoint(), inner.size()); _owner->paintRadialLoadingContent(p, newInner, radial, radialOpacity); - }, true); - //p.drawImage(inner.topLeft(), _radialCache); + }, kRadialLoadingOffset, true); } void OverlayWidget::RendererGL::paintThemePreview(QRect outer) { - paintToCache(_themePreviewCache, outer.size(), [&](Painter &&p) { + paintUsingRaster(_themePreviewImage, outer, [&](Painter &&p) { const auto newOuter = QRect(QPoint(), outer.size()); _owner->paintThemePreviewContent(p, newOuter, newOuter); - }); + }, kThemePreviewOffset); } void OverlayWidget::RendererGL::paintDocumentBubble( QRect outer, QRect icon) { - paintToCache(_documentBubbleCache, outer.size(), [&](Painter &&p) { + paintUsingRaster(_documentBubbleImage, outer, [&](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); + }, kDocumentBubbleOffset); _owner->paintRadialLoading(this); } void OverlayWidget::RendererGL::paintSaveMsg(QRect outer) { - paintToCache(_saveMsgCache, outer.size(), [&](Painter &&p) { + paintUsingRaster(_saveMsgImage, outer, [&](Painter &&p) { const auto newOuter = QRect(QPoint(), outer.size()); _owner->paintSaveMsgContent(p, newOuter, newOuter); - }, true); - //p.drawImage(outer.topLeft(), _saveMsgCache); + }, kSaveMsgOffset, true); } void OverlayWidget::RendererGL::paintControl( @@ -132,52 +284,109 @@ void OverlayWidget::RendererGL::paintControl( QRect inner, float64 innerOpacity, const style::icon &icon) { - + AssertIsDebug(controls); } void OverlayWidget::RendererGL::paintFooter(QRect outer, float64 opacity) { - paintToCache(_footerCache, outer.size(), [&](Painter &&p) { + paintUsingRaster(_footerImage, outer, [&](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); + }, kFooterOffset, true); } void OverlayWidget::RendererGL::paintCaption(QRect outer, float64 opacity) { - paintToCache(_captionCache, outer.size(), [&](Painter &&p) { + paintUsingRaster(_captionImage, outer, [&](Painter &&p) { const auto newOuter = QRect(QPoint(), outer.size()); _owner->paintCaptionContent(p, newOuter, newOuter, opacity); - }); - //p.drawImage(outer, _captionCache, ...); + }, kCaptionOffset, true); } void OverlayWidget::RendererGL::paintGroupThumbs( QRect outer, float64 opacity) { - paintToCache(_groupThumbsCache, outer.size(), [&](Painter &&p) { + paintUsingRaster(_groupThumbsImage, outer, [&](Painter &&p) { const auto newOuter = QRect(QPoint(), outer.size()); _owner->paintGroupThumbsContent(p, newOuter, newOuter, opacity); - }); + }, kGroupThumbsOffset, true); } -void OverlayWidget::RendererGL::paintToCache( - QImage &cache, - QSize size, +void OverlayWidget::RendererGL::paintUsingRaster( + Ui::GL::Image &image, + QRect rect, Fn 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); + int bufferOffset, + bool transparent) { + auto raster = image.takeImage(); + const auto size = rect.size() * _factor; + if (raster.width() < size.width() || raster.height() < size.height()) { + raster = QImage(size, QImage::Format_ARGB32_Premultiplied); + raster.setDevicePixelRatio(_factor); + if (!transparent + && (raster.width() > size.width() + || raster.height() > size.height())) { + raster.fill(Qt::transparent); + } + } else if (raster.devicePixelRatio() != _factor) { + raster.setDevicePixelRatio(_factor); } - if (clear) { - cache.fill(Qt::transparent); + + if (transparent) { + raster.fill(Qt::transparent); } - method(Painter(&cache)); + method(Painter(&raster)); + + image.setImage(std::move(raster)); + image.bind(*_f, size); + + const auto textured = image.texturedRect(rect, QRect(QPoint(), size)); + const auto geometry = transformRect(textured.geometry); + const GLfloat coords[] = { + geometry.left(), geometry.top(), + textured.texture.left(), textured.texture.bottom(), + + geometry.right(), geometry.top(), + textured.texture.right(), textured.texture.bottom(), + + geometry.right(), geometry.bottom(), + textured.texture.right(), textured.texture.top(), + + geometry.left(), geometry.bottom(), + textured.texture.left(), textured.texture.top(), + }; + _contentBuffer->write( + bufferOffset * 4 * sizeof(GLfloat), + coords, + sizeof(coords)); + + _f->glUseProgram(_imageProgram->programId()); + _imageProgram->setUniformValue("viewport", QSizeF(_viewport * _factor)); + _imageProgram->setUniformValue("s_texture", GLint(0)); + + _f->glActiveTexture(GL_TEXTURE0); + image.bind(*_f, size); + + toggleBlending(transparent); + FillTexturedRectangle(*_f, &*_imageProgram, bufferOffset); +} + +void OverlayWidget::RendererGL::toggleBlending(bool enabled) { + if (_blendingEnabled == enabled) { + return; + } else if (enabled) { + _f->glEnable(GL_BLEND); + _f->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + _f->glDisable(GL_BLEND); + } + _blendingEnabled = enabled; +} + +Rect OverlayWidget::RendererGL::transformRect(const Rect &raster) const { + return TransformRect(raster, _viewport, _factor); +} + +Rect OverlayWidget::RendererGL::transformRect(const QRect &raster) const { + return TransformRect(Rect(raster), _viewport, _factor); } } // namespace Media::View diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_opengl.h b/Telegram/SourceFiles/media/view/media_view_overlay_opengl.h index 3db11a6368..2400b3a52e 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_opengl.h +++ b/Telegram/SourceFiles/media/view/media_view_overlay_opengl.h @@ -9,14 +9,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/view/media_view_overlay_renderer.h" #include "ui/gl/gl_surface.h" +#include "ui/gl/gl_image.h" #include "ui/gl/gl_primitives.h" +#include + namespace Media::View { class OverlayWidget::RendererGL final : public OverlayWidget::Renderer { public: - RendererGL(not_null owner) : _owner(owner) { - } + explicit RendererGL(not_null owner); void init( not_null widget, @@ -65,11 +67,26 @@ private: void paintCaption(QRect outer, float64 opacity) override; void paintGroupThumbs(QRect outer, float64 opacity) override; - void paintToCache( - QImage &cache, - QSize size, + void paintUsingRaster( + Ui::GL::Image &image, + QRect rect, Fn method, - bool clear = false); + int bufferOffset, + bool transparent = false); + + void toggleBlending(bool enabled); + + [[nodiscard]] Ui::GL::Rect transformRect(const QRect &raster) const; + [[nodiscard]] Ui::GL::Rect transformRect( + const Ui::GL::Rect &raster) const; + + void uploadTexture( + GLint internalformat, + GLint format, + QSize size, + QSize hasSize, + int stride, + const void *data) const; const not_null _owner; @@ -78,13 +95,24 @@ private: QSize _viewport; float _factor = 1.; - QImage _radialCache; - QImage _documentBubbleCache; - QImage _themePreviewCache; - QImage _saveMsgCache; - QImage _footerCache; - QImage _captionCache; - QImage _groupThumbsCache; + std::optional _contentBuffer; + std::optional _imageProgram; + + Ui::GL::Textures<3> _textures; + QSize _rgbaSize; + QSize _ySize; + quint64 _cacheKey = 0; + + Ui::GL::Image _radialImage; + Ui::GL::Image _documentBubbleImage; + Ui::GL::Image _themePreviewImage; + Ui::GL::Image _saveMsgImage; + Ui::GL::Image _footerImage; + Ui::GL::Image _captionImage; + Ui::GL::Image _groupThumbsImage; + bool _blendingEnabled = false; + + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp index a8675c9c4b..9d0bc291f2 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp @@ -24,6 +24,8 @@ void OverlayWidget::RendererSW::paintFallback( _clip = &clip; _clipOuter = clip.boundingRect(); _owner->paint(this); + _p = nullptr; + _clip = nullptr; } void OverlayWidget::RendererSW::paintBackground() { diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_raster.h b/Telegram/SourceFiles/media/view/media_view_overlay_raster.h index 052b776d23..1b9ecd9d05 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_raster.h +++ b/Telegram/SourceFiles/media/view/media_view_overlay_raster.h @@ -14,7 +14,7 @@ namespace Media::View { class OverlayWidget::RendererSW final : public OverlayWidget::Renderer { public: - RendererSW(not_null owner); + explicit RendererSW(not_null owner); void paintFallback( Painter &&p, diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index e1a18991d7..f10ae26f97 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -3121,7 +3121,7 @@ Ui::GL::ChosenRenderer OverlayWidget::chooseRenderer( ? true : capabilities.transparency; LOG(("OpenGL: %1 (OverlayWidget)").arg(Logs::b(use))); - if (use && false) { + if (use) { auto renderer = std::make_unique(this); _opengl = true; return { @@ -3160,7 +3160,7 @@ void OverlayWidget::paint(not_null renderer) { paintRadialLoading(renderer); } else if (_themePreviewShown) { renderer->paintThemePreview(_themePreviewRect); - } else if (documentBubbleShown()) { + } else if (documentBubbleShown() && !_docRect.isEmpty()) { renderer->paintDocumentBubble(_docRect, _docIconRect); } updateSaveMsgState(); diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 8b7aa44226..0df1579d4a 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 8b7aa442268a4928f7582d97b33cb624b29d0cde +Subproject commit 0df1579d4a2fe7b18419e5025db380250c86cc53