QOpenGLWidget with RGBA 10-10-10-2 isn't created correctly
-
When requesting a QSurfaceFormat with 10R-10G-10B-2A, OpenGL succeeds but QSurfaceFormat reports 8-8-8-2 instead of 10-10-10-2.
The bug exists since at least Qt 6.5.3 probably much longer.
This is critical for us (Autodesk) as one of our applications recently migrated from Qt5/QGLWidget to Qt6/QOpenGLWidget an 10-bit color workflow isn't working anymore.
I'd like to attach a file but (I can't) so here's a sample main.cpp that will show the bug.
#include <QApplication> #include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QSurfaceFormat> #include <QVBoxLayout> #include <QWidget> #include <iostream> void explain() { std::cout << "EXPLANATION OF THE BUG\n" << std::endl; std::cout << "Location:" << std::endl; std::cout << " File: qtbase/src/plugins/platforms/cocoa/qcocoaglcontext.mm" << std::endl; std::cout << " Line: 267-271\n" << std::endl; std::cout << "The Bug:" << std::endl; std::cout << " Qt divides NSOpenGLPFAColorSize by 4, assuming it includes alpha." << std::endl; std::cout << " However, NSOpenGLPFAColorSize returns ONLY R+G+B bits (no alpha).\n" << std::endl; std::cout << "Buggy Code:" << std::endl; std::cout << " int colorSize = pixelFormatAttribute(NSOpenGLPFAColorSize);" << std::endl; std::cout << " colorSize /= 4; // WRONG!" << std::endl; std::cout << " m_format.setRedBufferSize(colorSize);" << std::endl; std::cout << " m_format.setGreenBufferSize(colorSize);" << std::endl; std::cout << " m_format.setBlueBufferSize(colorSize);\n" << std::endl; std::cout << "What Happens with 10-10-10-2:" << std::endl; std::cout << " 1. You request: 10-10-10-2 (30 bits RGB + 2 bits alpha)" << std::endl; std::cout << " 2. macOS gives closest match: 32 bits RGB total" << std::endl; std::cout << " 3. NSOpenGLPFAColorSize returns: 32 (R+G+B only)" << std::endl; std::cout << " 4. Qt divides by 4: 32 / 4 = 8" << std::endl; std::cout << " 5. Qt reports: 8-8-8-2 WRONG!" << std::endl; std::cout << " 6. Actual format: 10-10-10-2 (OpenGL confirms this)\n" << std::endl; std::cout << "Solution:" << std::endl; std::cout << " Query OpenGL directly using glGetIntegerv():" << std::endl; std::cout << " glGetIntegerv(GL_RED_BITS/GL_GREEN_BITS/GL_BLUE_BITS)" << std::endl; std::cout << " This bypasses Qt's incorrect reporting.\n" << std::endl; std::cout << "Platform Status:" << std::endl; std::cout << " macOS: BUG (present in Qt 6.10.1)" << std::endl; std::cout << " Windows: OK (queries WGL_RED_BITS_ARB separately)" << std::endl; std::cout << " Linux: OK (queries GLX_RED_SIZE separately)" << std::endl; } class TestGLWidget : public QOpenGLWidget, protected QOpenGLFunctions { public: TestGLWidget(QWidget* parent = nullptr) : QOpenGLWidget(parent) { // Request 10-10-10-2 format QSurfaceFormat fmt; fmt.setRedBufferSize(10); fmt.setGreenBufferSize(10); fmt.setBlueBufferSize(10); fmt.setAlphaBufferSize(2); fmt.setDepthBufferSize(24); fmt.setStencilBufferSize(8); fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer); std::cout << "REQUESTED FORMAT:" << std::endl; std::cout << " R-G-B-A: " << fmt.redBufferSize() << "-" << fmt.greenBufferSize() << "-" << fmt.blueBufferSize() << "-" << fmt.alphaBufferSize() << std::endl; setFormat(fmt); } protected: void initializeGL() override { initializeOpenGLFunctions(); std::cout << "AFTER initializeGL():" << std::endl; // What Qt reports via format() QSurfaceFormat qtFormat = format(); std::cout << "Qt format() reports:" << std::endl; std::cout << " R-G-B-A: " << qtFormat.redBufferSize() << "-" << qtFormat.greenBufferSize() << "-" << qtFormat.blueBufferSize() << "-" << qtFormat.alphaBufferSize() << std::endl; // What OpenGL actually has GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0; glGetIntegerv(GL_RED_BITS, &redBits); glGetIntegerv(GL_GREEN_BITS, &greenBits); glGetIntegerv(GL_BLUE_BITS, &blueBits); glGetIntegerv(GL_ALPHA_BITS, &alphaBits); std::cout << "OpenGL glGetIntegerv() reports:" << std::endl; std::cout << " R-G-B-A: " << redBits << "-" << greenBits << "-" << blueBits << "-" << alphaBits << std::endl; if (qtFormat.redBufferSize() != redBits || qtFormat.greenBufferSize() != greenBits || qtFormat.blueBufferSize() != blueBits) { std::cout << "BUG DETECTED!" << std::endl; std::cout << " Qt reports different values than OpenGL!" << std::endl; std::cout << " This is the Qt macOS bug in qcocoaglcontext.mm:268\n" << std::endl; // Provide detailed explanation of the bug explain(); } else { std::cout << "Qt correctly reports the OpenGL format\n" << std::endl; } } void paintGL() override { glClearColor(0.2f, 0.3f, 0.4f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); } }; class MainWindow : public QWidget { public: MainWindow() { setWindowTitle("Qt 10-bit Format Bug Test"); resize(640, 480); QVBoxLayout* layout = new QVBoxLayout(this); TestGLWidget* glWidget = new TestGLWidget(); layout->addWidget(glWidget); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow window; window.show(); return app.exec(); } -
Hi and welcome to devnet,
Do you see this on all platforms ?