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;
float _factor = 1.;
int _ifactor = 1;
QVector2D _uniformViewport;
std::optional<QOpenGLBuffer> _contentBuffer;
@ -189,9 +190,10 @@ void Panel::Incoming::RendererGL::paint(
return;
}
const auto factor = widget->devicePixelRatio();
const auto factor = widget->devicePixelRatioF();
if (_factor != factor) {
_factor = factor;
_ifactor = int(std::ceil(_factor));
_controlsShadowImage.invalidate();
}
_viewport = widget->size();
@ -375,9 +377,9 @@ void Panel::Incoming::RendererGL::validateShadowImage() {
return;
}
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);
image.setDevicePixelRatio(_factor);
image.setDevicePixelRatio(_ifactor);
image.fill(Qt::transparent);
{
auto p = QPainter(&image);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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