P
P
Philip Bondarev2019-02-08 17:49:38
Qt
Philip Bondarev, 2019-02-08 17:49:38

Why doesn't QOpenGLWidget use the default QSurfaceFormat?

I'm trying to display an image in RGB30 format.

  • System: Windows 10 x64
  • Qt version : 5.12.1 msvc2017_64
  • Video card: Quadro P400
  • Monitor: NEC MD211C2 (Checked with NEC benchmark - 10-bit works)

When creating a Qt application , I set the surface format:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QSurfaceFormat>

int main(int argc, char *argv[])
{
    QSurfaceFormat format;
    format.setDepthBufferSize(32);
    format.setRedBufferSize (10);
    format.setGreenBufferSize (10);
    format.setBlueBufferSize (10);
    format.setAlphaBufferSize(0);
    format.setRenderableType(QSurfaceFormat::OpenGL);
    format.setVersion(4, 6);
    QSurfaceFormat::setDefaultFormat(format);

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}


Then I manually create a widget inherited from QOpenGLWidget and place it in the layout, passing in the widget's constructor the generated QByteArray , which is the image data in RGB30 (10-10-10-x) format .
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QBuffer>
#include <QtEndian>


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    width = 2048;
    height = 600;

    QByteArray *arr = gen30bitImgArr(width, height);
    ogl10 = new MyOGL(this, arr);
    ui->vLout->addWidget(ogl10);
}

MainWindow::~MainWindow()
{
    delete ui;
}

QByteArray *MainWindow::gen30bitImgArr(int width, int height)
{
    QByteArray *arr = new QByteArray();
    QBuffer buffer(arr);
    buffer.open (QIODevice::WriteOnly);
    QDataStream out(&buffer);

    uint32_t rgb30color = 0;
    for (int row = 0; row < height; ++row) {
        for (uint32_t pixel = 0; static_cast<int>(pixel)< 1024; ++pixel) {
            for (int chanel = 0; chanel < 3; ++chanel) {
                rgb30color |= pixel;
                chanel == 2? 0 : rgb30color <<= 10;
            }
            rgb30color = qToBigEndian(rgb30color);
            out << rgb30color;
            out << rgb30color;
            rgb30color = 0;
        }
    }
    return arr;
}


In the MyOGL widget itself (based on the qopenglwidget example ), I create a rectangle and try to display a QOpenGLTexture in GL_RGB10_A2 format on it . This is where the problems begin, if I adjust the texture for an 8-bit array (I excluded it from the example), then everything is displayed correctly (not a fact, it seemed to me that black and white colors are not brought to the maximum at the edges of the rectangle), but it’s worth transfer everything to the 10-bit display mode, as here black is displayed instead of a rectangle. I suffered for a long time going through all the possible combinations of parameters suitable for my task, and then I decided to see what I have in this-> format (); . It turns out that in the MyOGL constructorQSurfaceFormat is the format that I specified as default, with 10 bits per channel, however, already in initializeGL() , it is changed to some unknown one, with 8 bits per channel ... In At what point is the replacement, I do not understand. In the documentation, no matter how much I dug, I did not find an explanation. Here is MyOGL :
myogl.h
#ifndef MYOGL_H
#define MYOGL_H

#include <QObject>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLTexture>
#include <QOpenGLBuffer>


class MyOGL : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    MyOGL(QWidget *parent = nullptr, const QByteArray *imgArr = nullptr);
    ~MyOGL() override;

protected:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int w, int h) override;

private:
    void makeObject();

    const QByteArray *imgData;

    qreal m_fAngle;
    qreal m_fScale;
    QVector<QVector3D> m_vertices;
    QOpenGLShader *m_vshader;
    QOpenGLShader *m_fshader;
    QOpenGLShaderProgram *m_program;
    QOpenGLTexture *m_texture;
    QOpenGLBuffer m_vbo;
    int m_vertexAttr;
    int m_texCoordAttr;
    int m_textureUniform;
    QColor m_background = QColor(30, 30, 30);

};

#endif // MYOGL_H

myogl.cpp
#include "myogl.h"
#include "qdebug.h"


MyOGL::MyOGL(QWidget *parent, const QByteArray *imgArr)
    : QOpenGLWidget(parent),
      m_program(nullptr),
      m_texture(nullptr)
{
    qDebug()<<"------------Start constructor-----------";
    this->setTextureFormat (GL_RGB10_A2);
    imgData = imgArr;

    qDebug()<<this->format()<<"\n";
    qDebug()<<this->format().renderableType()<<"\n";
    qDebug()<<this->textureFormat()<<"\n";
    qDebug()<<QSurfaceFormat::defaultFormat()<<"\n";
    qDebug()<<"------------END constructor-----------\n";

}

MyOGL::~MyOGL()
{
    makeCurrent();
    delete m_texture;
    delete m_program;
    delete m_vshader;
    delete m_fshader;
    m_vbo.destroy();
    doneCurrent();
}

void MyOGL::initializeGL()
{
    qDebug()<<"----------Start Initalization-----------";
    qDebug()<<this->format()<<"\n";
    qDebug()<<this->format().renderableType()<<"\n";
    qDebug()<<this->textureFormat()<<"\n";
    qDebug()<<QSurfaceFormat::defaultFormat()<<"\n";

    initializeOpenGLFunctions();

    m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_texture->setFormat(QOpenGLTexture::RGB10A2);
    m_texture->setSize(2048, 600);
    m_texture->setMipLevels(1);
    m_texture->allocateStorage(QOpenGLTexture::RGBA,
                               QOpenGLTexture::UInt32_RGB10A2);
    m_texture->setData(0,
                       QOpenGLTexture::RGBA,
                       QOpenGLTexture::UInt32_RGB10A2,
                       imgData->constData());

    m_vshader = new QOpenGLShader(QOpenGLShader::Vertex);
    const char *vsrc2 =
        "attribute highp vec4 vertex;\n"
        "attribute mediump vec4 texCoord;\n"
        "varying mediump vec4 texc;\n"
        "void main(void)\n"
        "{\n"
        "    gl_Position = vertex;\n"
        "    texc = texCoord;\n"
        "}\n";
    m_vshader->compileSourceCode(vsrc2);

    m_fshader = new QOpenGLShader(QOpenGLShader::Fragment);
    const char *fsrc2 =
        "uniform sampler2D tex;\n"
        "varying mediump vec4 texc;\n"
        "void main(void)\n"
        "{\n"
        "    gl_FragColor = texture2D(tex, texc.st);\n"
        "}\n";
    m_fshader->compileSourceCode(fsrc2);

    m_program = new QOpenGLShaderProgram;
    m_program->addShader(m_vshader);
    m_program->addShader(m_fshader);
    m_program->link();

    m_vertexAttr = m_program->attributeLocation("vertex");
    m_texCoordAttr = m_program->attributeLocation("texCoord");
    m_textureUniform = m_program->uniformLocation("tex");

    m_fAngle = 0;
    m_fScale = 1;

    const int vertexCount = m_vertices.count();
    QVector<GLfloat> buf;
    buf.resize(vertexCount * 3 * 2);
    GLfloat *p = buf.data();
    for (int i = 0; i < vertexCount; ++i) {
        *p++ = m_vertices[i].x();
        *p++ = m_vertices[i].y();
        *p++ = m_vertices[i].z();
    }
}

void MyOGL::paintGL()
{
    glClearColor(m_background.redF(),
                 m_background.greenF(),
                 m_background.blueF(),
                 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glFrontFace(GL_CW);
    //glCullFace(GL_FRONT);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);

    m_program->bind();
    makeObject();
    m_program->release();


    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);


    update();
}

void MyOGL::resizeGL(int w, int h)
{

}

void MyOGL::makeObject()
{
    m_texture->bind();
    if (!m_vbo.isCreated()) {
        static GLfloat afVertices[] = {

            -0.5f, -0.5f, 0.0f,
            -0.5f,  0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,

            0.5f,  0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            -0.5f,  0.5f, 0.0f

        };

        static GLfloat afTexCoord[] = {
            0.25f, 0.25f,
            0.25f, 0.75f,
            0.75f, 0.25f,

            0.75f, 0.75f,
            0.75f, 0.25f,
            0.25f, 0.75f

        };

        m_vbo.create();
        m_vbo.bind();
        m_vbo.allocate(30 * sizeof(GLfloat));
        m_vbo.write(0, afVertices, sizeof(afVertices));
        m_vbo.write(sizeof(afVertices), afTexCoord, sizeof(afTexCoord));
        m_vbo.release();
    }

    m_program->setUniformValue(m_textureUniform, 0); // use texture unit 0

    m_program->enableAttributeArray(m_vertexAttr);
    m_program->enableAttributeArray(m_texCoordAttr);

    m_vbo.bind();
    m_program->setAttributeBuffer(m_vertexAttr, GL_FLOAT, 0, 3);
    m_program->setAttributeBuffer(m_texCoordAttr, GL_FLOAT,
                                  6 * 3 * sizeof(GLfloat), 2);
    m_vbo.release();

    glDrawArrays(GL_TRIANGLES, 0, 6);

    m_program->disableAttributeArray(m_vertexAttr);
    m_program->disableAttributeArray(m_texCoordAttr);
}


Also, I am attaching the output to the console and the result of calling qtdiag.exe , I want to draw your attention to Buffer Size (RGBA) 8,8,8,8 . Why so, because the card supports 10,10,10,2 , and the monitor is set to 10-bit mode ?
I will leave the content of the output of qtdiag.exe in the comments, since the limit has been exhausted.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question