Qt5.6: suporte a altos DPI e OpenGL (OpenSceneGraph)

Eu tenho um aplicativo mínimo que usaQOpenGLWidget que integra uma biblioteca de wrappers OpenGL (OpenSceneGraph). Estou tentando descobrir como usar corretamente o suporte Qt5.6 para telas de alto DPI ao lidar com conteúdo OpenGL como eu uso.

Minhasmain() A função possui o seguinte código:

int main(int argc, char** argv)
{
    // DPI support is on
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);
    QMainWindow window;

    // QOpenGLWidget with OpenSceneGraph content
    QtOSGWidget* widget = new QtOSGWidget();

    window.setCentralWidget(widget);
    window.show();
    return app.exec();
}

oQtOSGWidget é derivado deQOpenGLWidget com conteúdo OpenSceneGraph: eu usoosgViewer::GraphicsWindowEmbedded para renderizar minha cena simples.

Para mesclar OSG com Qt, redefino o*GL() métodos:paintGL(), resizeGL() einitializeGL(). Sigo os documentos Qt sobre o que cada um dos*GL() métodos devem conter, ou seja:

paintGL() garante que o visualizador seja atualizadoresizeGL() garante que a janela de desenho seja redimensionada corretamente (junto com a câmera e a janela de visualização);initializeGL() garante que o estado OpenGL seja inicializado.Também redefini os eventos do mouse Qt para passar os eventos para o OSG

Quando executo meu exemplo na tela de resolução normal, ou comQApplication::setAttribute(Qt::AA_DisableHighDpiScaling);, a cena parece que deveria:

Além disso, quando manipulo a visualização da câmera, as coordenadas do mouse são capturadas corretamente.

No entanto, quando eu ativo a opção de DPI alto, é isso que recebo:

As coordenadas do mouse para eventos também são dimensionadas e não são passadas para o manipulador de eventos do OpenSceneGraph corretamente.

Como você pode ver, o tamanho da janela de desenho não é dimensionado pelo Qt. Provavelmente é por causa da maneira como eu configuro o dimensionamento:

virtual void resizeGL( int width, int height ) 
{
    // resize event is passed to OSG
    this->getEventQueue()->windowResize(this->x(), this->y(), width, height);

    // graphics window resize
    m_graphicsWindow->resized(this->x(), this->y(), width, height);

    // camera viewport
    osg::Camera* camera = m_viewer->getCamera();
    camera->setViewport(0, 0, this->width(), this->height());
}

Esse dimensionamento não é dimensionado pelo Qt. O mesmo acontece com as coordenadas dos eventos do mouse.

Minha pergunta: existe uma maneira de saber em que tamanho a escala será executada para queresizeGL() corretamente? Ou qual é a maneira correta de lidar com o problema?

Atualização / solução usando o dimensionamento manualmente: graças à resposta do @AlexanderVX, descobri a solução de dimensionamento. No começo, preciso conhecer alguns valores de referência de DPI nas dimensões X e Y. Então eu calculo as coordenadas de escala com base nisso e as passo para o meu widgetQtOSGWidget. Então, o código domain() deve conter:

QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);

int x = QApplication::desktop()->physicalDpiX();
int y = QApplication::desktop()->physicalDpiY();
// values 284 and 285 are the reference values
double scaleX = 284.0/double(x);
double scaleY = 285.0/double(y);

QMainWindow window;
QtOSGWidget* widget = new QtOSGWidget(scaleX, scaleY, &window);
// etc.

Então, sempre que me refiro às funções de dimensionamento que precisavam ser passadas para o conteúdo do OpenSceneGraph (OpenGL), preciso fazer o dimensionamento, por exemplo:

// resizeGL example
this->getEventQueue()->windowResize(this->x()*m_scaleX, this->y() * m_scaleY, width*m_scaleX, height*m_scaleY);

// mouse event example
this->getEventQueue()->mouseButtonPress(event->x()*m_scaleX, event->y()*m_scaleY, button);

Atualização final: como a plataforma de destino do meu aplicativo é o Windows 7-10, faz muito mais sentido seguir a resposta proposta por @AlexanderV (segunda parte), ou seja, usarSetProcessDPIAware() função.

questionAnswers(1)

yourAnswerToTheQuestion