Fix OpenGL rendering with precise HighDPI.

This commit is contained in:
John Preston 2023-08-17 14:22:04 +02:00
parent 311691a3bc
commit af3cf63e5f
7 changed files with 50 additions and 39 deletions

View file

@ -73,6 +73,7 @@ private:
QSize _viewport; QSize _viewport;
float _factor = 1.; float _factor = 1.;
int _ifactor = 1;
QVector2D _uniformViewport; QVector2D _uniformViewport;
std::optional<QOpenGLBuffer> _contentBuffer; std::optional<QOpenGLBuffer> _contentBuffer;
@ -189,9 +190,10 @@ void Panel::Incoming::RendererGL::paint(
return; return;
} }
const auto factor = widget->devicePixelRatio(); const auto factor = widget->devicePixelRatioF();
if (_factor != factor) { if (_factor != factor) {
_factor = factor; _factor = factor;
_ifactor = int(std::ceil(_factor));
_controlsShadowImage.invalidate(); _controlsShadowImage.invalidate();
} }
_viewport = widget->size(); _viewport = widget->size();
@ -375,9 +377,9 @@ void Panel::Incoming::RendererGL::validateShadowImage() {
return; return;
} }
const auto size = st::callTitleShadowLeft.size(); const auto size = st::callTitleShadowLeft.size();
const auto full = QSize(size.width(), 2 * size.height()) * int(_factor); const auto full = QSize(size.width(), 2 * size.height()) * _ifactor;
auto image = QImage(full, QImage::Format_ARGB32_Premultiplied); auto image = QImage(full, QImage::Format_ARGB32_Premultiplied);
image.setDevicePixelRatio(_factor); image.setDevicePixelRatio(_ifactor);
image.fill(Qt::transparent); image.fill(Qt::transparent);
{ {
auto p = QPainter(&image); auto p = QPainter(&image);

View file

@ -414,16 +414,20 @@ void Viewport::RendererGL::deinit(
} }
void Viewport::RendererGL::setDefaultViewport(QOpenGLFunctions &f) { void Viewport::RendererGL::setDefaultViewport(QOpenGLFunctions &f) {
const auto size = _viewport * _factor; f.glViewport(
f.glViewport(0, 0, size.width(), size.height()); 0,
0,
_viewport.width() * _factor,
_viewport.height() * _factor);
} }
void Viewport::RendererGL::paint( void Viewport::RendererGL::paint(
not_null<QOpenGLWidget*> widget, not_null<QOpenGLWidget*> widget,
QOpenGLFunctions &f) { QOpenGLFunctions &f) {
const auto factor = widget->devicePixelRatio(); const auto factor = widget->devicePixelRatioF();
if (_factor != factor) { if (_factor != factor) {
_factor = factor; _factor = factor;
_ifactor = int(std::ceil(_factor));
_buttons.invalidate(); _buttons.invalidate();
} }
_viewport = widget->size(); _viewport = widget->size();
@ -773,7 +777,7 @@ void Viewport::RendererGL::paintTile(
const auto program = _rgbaFrame const auto program = _rgbaFrame
? &*_frameProgram.argb32 ? &*_frameProgram.argb32
: &*_frameProgram.yuv420; : &*_frameProgram.yuv420;
const auto uniformViewport = QSizeF(_viewport * _factor); const auto uniformViewport = QSizeF(_viewport) * _factor;
program->setUniformValue("viewport", uniformViewport); program->setUniformValue("viewport", uniformViewport);
program->setUniformValue( program->setUniformValue(
@ -1122,18 +1126,18 @@ void Viewport::RendererGL::ensureButtonsImage() {
+ backSize.height() + backSize.height()
+ muteSize.height() + muteSize.height()
+ pausedSize.height())); + pausedSize.height()));
const auto imageSize = fullSize * _factor; const auto imageSize = fullSize * _ifactor;
auto image = _buttons.takeImage(); auto image = _buttons.takeImage();
if (image.size() != imageSize) { if (image.size() != imageSize) {
image = QImage(imageSize, QImage::Format_ARGB32_Premultiplied); image = QImage(imageSize, QImage::Format_ARGB32_Premultiplied);
} }
image.fill(Qt::transparent); image.fill(Qt::transparent);
image.setDevicePixelRatio(_factor); image.setDevicePixelRatio(_ifactor);
{ {
auto p = Painter(&image); auto p = Painter(&image);
auto hq = PainterHighQualityEnabler(p); auto hq = PainterHighQualityEnabler(p);
_pinOn = QRect(QPoint(), pinOnSize * _factor); _pinOn = QRect(QPoint(), pinOnSize * _ifactor);
VideoTile::PaintPinButton( VideoTile::PaintPinButton(
p, p,
true, true,
@ -1145,8 +1149,8 @@ void Viewport::RendererGL::ensureButtonsImage() {
const auto pinOffTop = pinOnSize.height(); const auto pinOffTop = pinOnSize.height();
_pinOff = QRect( _pinOff = QRect(
QPoint(0, pinOffTop) * _factor, QPoint(0, pinOffTop) * _ifactor,
pinOffSize * _factor); pinOffSize * _ifactor);
VideoTile::PaintPinButton( VideoTile::PaintPinButton(
p, p,
false, false,
@ -1157,7 +1161,7 @@ void Viewport::RendererGL::ensureButtonsImage() {
&_pinIcon); &_pinIcon);
const auto backTop = pinOffTop + pinOffSize.height(); const auto backTop = pinOffTop + pinOffSize.height();
_back = QRect(QPoint(0, backTop) * _factor, backSize * _factor); _back = QRect(QPoint(0, backTop) * _ifactor, backSize * _ifactor);
VideoTile::PaintBackButton( VideoTile::PaintBackButton(
p, p,
0, 0,
@ -1166,18 +1170,18 @@ void Viewport::RendererGL::ensureButtonsImage() {
&_pinBackground); &_pinBackground);
const auto muteTop = backTop + backSize.height(); const auto muteTop = backTop + backSize.height();
_muteOn = QRect(QPoint(0, muteTop) * _factor, muteSize * _factor); _muteOn = QRect(QPoint(0, muteTop) * _ifactor, muteSize * _ifactor);
_muteIcon.paint(p, { 0, muteTop }, 1.); _muteIcon.paint(p, { 0, muteTop }, 1.);
_muteOff = QRect( _muteOff = QRect(
QPoint(muteSize.width(), muteTop) * _factor, QPoint(muteSize.width(), muteTop) * _ifactor,
muteSize * _factor); muteSize * _ifactor);
_muteIcon.paint(p, { muteSize.width(), muteTop }, 0.); _muteIcon.paint(p, { muteSize.width(), muteTop }, 0.);
const auto pausedTop = muteTop + muteSize.height(); const auto pausedTop = muteTop + muteSize.height();
_paused = QRect( _paused = QRect(
QPoint(0, pausedTop) * _factor, QPoint(0, pausedTop) * _ifactor,
pausedSize * _factor); pausedSize * _ifactor);
st::groupCallPaused.paint(p, 0, pausedTop, fullSize.width()); st::groupCallPaused.paint(p, 0, pausedTop, fullSize.width());
} }
_buttons.setImage(std::move(image)); _buttons.setImage(std::move(image));

View file

@ -130,6 +130,7 @@ private:
const not_null<Viewport*> _owner; const not_null<Viewport*> _owner;
GLfloat _factor = 1.; GLfloat _factor = 1.;
int _ifactor = 1;
QSize _viewport; QSize _viewport;
bool _rgbaFrame = false; bool _rgbaFrame = false;
bool _userpicFrame; bool _userpicFrame;

View file

@ -263,9 +263,10 @@ void OverlayWidget::RendererGL::paint(
if (handleHideWorkaround(f)) { if (handleHideWorkaround(f)) {
return; return;
} }
const auto factor = widget->devicePixelRatio(); const auto factor = widget->devicePixelRatioF();
if (_factor != factor) { if (_factor != factor) {
_factor = factor; _factor = factor;
_ifactor = int(std::ceil(factor));
_controlsImage.invalidate(); _controlsImage.invalidate();
// We use the fact that fade texture atlas // We use the fact that fade texture atlas
@ -763,10 +764,10 @@ void OverlayWidget::RendererGL::validateControls() {
maxWidth = std::max(st::mediaviewIconOver, maxWidth); maxWidth = std::max(st::mediaviewIconOver, maxWidth);
fullHeight += st::mediaviewIconOver; fullHeight += st::mediaviewIconOver;
auto image = QImage( auto image = QImage(
QSize(maxWidth, fullHeight) * _factor, QSize(maxWidth, fullHeight) * _ifactor,
QImage::Format_ARGB32_Premultiplied); QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent); image.fill(Qt::transparent);
image.setDevicePixelRatio(_factor); image.setDevicePixelRatio(_ifactor);
{ {
auto p = QPainter(&image); auto p = QPainter(&image);
auto index = 0; auto index = 0;
@ -774,8 +775,8 @@ void OverlayWidget::RendererGL::validateControls() {
for (const auto &meta : metas) { for (const auto &meta : metas) {
meta.icon->paint(p, 0, height, maxWidth); meta.icon->paint(p, 0, height, maxWidth);
_controlsTextures[index++] = QRect( _controlsTextures[index++] = QRect(
QPoint(0, height) * _factor, QPoint(0, height) * _ifactor,
meta.icon->size() * _factor); meta.icon->size() * _ifactor);
height += meta.icon->height(); height += meta.icon->height();
} }
auto hq = PainterHighQualityEnabler(p); auto hq = PainterHighQualityEnabler(p);
@ -784,8 +785,8 @@ void OverlayWidget::RendererGL::validateControls() {
p.drawEllipse( p.drawEllipse(
QRect(0, height, st::mediaviewIconOver, st::mediaviewIconOver)); QRect(0, height, st::mediaviewIconOver, st::mediaviewIconOver));
_controlsTextures[index++] = QRect( _controlsTextures[index++] = QRect(
QPoint(0, height) * _factor, QPoint(0, height) * _ifactor,
QSize(st::mediaviewIconOver, st::mediaviewIconOver) * _factor); QSize(st::mediaviewIconOver, st::mediaviewIconOver) * _ifactor);
height += st::mediaviewIconOver; height += st::mediaviewIconOver;
} }
_controlsImage.setImage(std::move(image)); _controlsImage.setImage(std::move(image));
@ -817,10 +818,10 @@ void OverlayWidget::RendererGL::validateControlsFade() {
const auto height = bottomTop + bottom.height(); const auto height = bottomTop + bottom.height();
auto image = QImage( auto image = QImage(
QSize(width, height) * _factor, QSize(width, height) * _ifactor,
QImage::Format_ARGB32_Premultiplied); QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent); image.fill(Qt::transparent);
image.setDevicePixelRatio(_factor); image.setDevicePixelRatio(_ifactor);
auto p = QPainter(&image); auto p = QPainter(&image);
top.paint(p, 0, 0, width); top.paint(p, 0, 0, width);
@ -1007,18 +1008,18 @@ void OverlayWidget::RendererGL::paintUsingRaster(
int bufferOffset, int bufferOffset,
bool transparent) { bool transparent) {
auto raster = image.takeImage(); auto raster = image.takeImage();
const auto size = rect.size() * _factor; const auto size = rect.size() * _ifactor;
if (raster.width() < size.width() || raster.height() < size.height()) { if (raster.width() < size.width() || raster.height() < size.height()) {
raster = QImage(size, QImage::Format_ARGB32_Premultiplied); raster = QImage(size, QImage::Format_ARGB32_Premultiplied);
Assert(!raster.isNull()); Assert(!raster.isNull());
raster.setDevicePixelRatio(_factor); raster.setDevicePixelRatio(_ifactor);
if (!transparent if (!transparent
&& (raster.width() > size.width() && (raster.width() > size.width()
|| raster.height() > size.height())) { || raster.height() > size.height())) {
raster.fill(Qt::transparent); raster.fill(Qt::transparent);
} }
} else if (raster.devicePixelRatio() != _factor) { } else if (raster.devicePixelRatio() != _ifactor) {
raster.setDevicePixelRatio(_factor); raster.setDevicePixelRatio(_ifactor);
} }
if (transparent) { if (transparent) {

View file

@ -114,6 +114,7 @@ private:
QOpenGLFunctions *_f = nullptr; QOpenGLFunctions *_f = nullptr;
QSize _viewport; QSize _viewport;
float _factor = 1.; float _factor = 1.;
int _ifactor = 1;
QVector2D _uniformViewport; QVector2D _uniformViewport;
std::optional<QOpenGLBuffer> _contentBuffer; std::optional<QOpenGLBuffer> _contentBuffer;

View file

@ -269,9 +269,10 @@ void Pip::RendererGL::createShadowTexture() {
void Pip::RendererGL::paint( void Pip::RendererGL::paint(
not_null<QOpenGLWidget*> widget, not_null<QOpenGLWidget*> widget,
QOpenGLFunctions &f) { QOpenGLFunctions &f) {
const auto factor = widget->devicePixelRatio(); const auto factor = widget->devicePixelRatioF();
if (_factor != factor) { if (_factor != factor) {
_factor = factor; _factor = factor;
_ifactor = int(std::ceil(_factor));
_controlsImage.invalidate(); _controlsImage.invalidate();
} }
_blendingEnabled = false; _blendingEnabled = false;
@ -667,10 +668,10 @@ void Pip::RendererGL::validateControls() {
fullHeight += 2 * meta.icon->height(); fullHeight += 2 * meta.icon->height();
} }
auto image = QImage( auto image = QImage(
QSize(maxWidth, fullHeight) * _factor, QSize(maxWidth, fullHeight) * _ifactor,
QImage::Format_ARGB32_Premultiplied); QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent); image.fill(Qt::transparent);
image.setDevicePixelRatio(_factor); image.setDevicePixelRatio(_ifactor);
{ {
auto p = QPainter(&image); auto p = QPainter(&image);
auto index = 0; auto index = 0;
@ -678,8 +679,8 @@ void Pip::RendererGL::validateControls() {
const auto paint = [&](not_null<const style::icon*> icon) { const auto paint = [&](not_null<const style::icon*> icon) {
icon->paint(p, 0, height, maxWidth); icon->paint(p, 0, height, maxWidth);
_controlsTextures[index++] = QRect( _controlsTextures[index++] = QRect(
QPoint(0, height) * _factor, QPoint(0, height) * _ifactor,
icon->size() * _factor); icon->size() * _ifactor);
height += icon->height(); height += icon->height();
}; };
for (const auto &meta : metas) { for (const auto &meta : metas) {
@ -702,7 +703,7 @@ void Pip::RendererGL::paintUsingRaster(
int bufferOffset, int bufferOffset,
bool transparent) { bool transparent) {
auto raster = image.takeImage(); auto raster = image.takeImage();
const auto size = rect.size() * _factor; const auto size = rect.size() * _ifactor;
if (raster.width() < size.width() || raster.height() < size.height()) { if (raster.width() < size.width() || raster.height() < size.height()) {
raster = QImage(size, QImage::Format_ARGB32_Premultiplied); raster = QImage(size, QImage::Format_ARGB32_Premultiplied);
raster.setDevicePixelRatio(_factor); raster.setDevicePixelRatio(_factor);
@ -711,8 +712,8 @@ void Pip::RendererGL::paintUsingRaster(
|| raster.height() > size.height())) { || raster.height() > size.height())) {
raster.fill(Qt::transparent); raster.fill(Qt::transparent);
} }
} else if (raster.devicePixelRatio() != _factor) { } else if (raster.devicePixelRatio() != _ifactor) {
raster.setDevicePixelRatio(_factor); raster.setDevicePixelRatio(_ifactor);
} }
if (transparent) { if (transparent) {

View file

@ -93,6 +93,7 @@ private:
QOpenGLFunctions *_f = nullptr; QOpenGLFunctions *_f = nullptr;
QSize _viewport; QSize _viewport;
float _factor = 1.; float _factor = 1.;
int _ifactor = 1;
QVector2D _uniformViewport; QVector2D _uniformViewport;
std::optional<QOpenGLBuffer> _contentBuffer; std::optional<QOpenGLBuffer> _contentBuffer;