Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-56780

[OpenGL] Qt paint engine doesn't call glTexParameter when creating the texture in some cases

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P1: Critical
    • None
    • 5.7.0
    • GUI: OpenGL
    • None
    • PC + Window 10

    Description

      Issue can be reproduced on both AMD and Intel graphics card.

      Upload test app source code to demonstrate the issues, there are two Qt OpenGL issues in this test app.
      Test app runs on PC + Windows 10, the logic of this app is quite simple, QT draws a spinbox, then QT render the 2D window to a texture,
      and then call glReadPixel to read the texture back and dump as an BMP file named test.bmp. (please don’t care about the abnormal of the window present, just focus on the result picture test.bmp),
      Using Nvidia card, you will see the correct test.bmp, but with AMD and Intel card, you will get nothing since there are two Qt issues, you can use any AMD/Intel card can reproduce the issue.

      1. For the first issue:
      Test app uses Qt to create core profile 4.1 OpenGL context, it will call API glVertexAttribPointer but input parameter pointer is a pointer to system memory vertex data, which violates spec because
      OpenGL 4.1 context needs to bind a vertex buffer before calling glVertexAttribPointer, so AMD OGL driver will report the following error " glVertexAttribPointer in a Core context called without a bound
      Vertex Array Object [which is now required for Core Contexts]". Nvidia may not fully follow the OpenGL spec, so it can pass the test case.
      In Qt paint engine call sequence, before calling glVertexAttribPointer, it doesn’t bind an array buffer, it is not allowed after OpenGL spec 3.1 anymore
      glEnableVertexAttribArray(0)
      glGetUniformLocation(9, "fragmentColor") = 0
      glUniform4fv(0, 1, [0.941176, 0.941176, 0.941176, 1])
      glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0D5A8C2C)
      glDrawArrays(GL_TRIANGLE_FAN, 0, 4)
      The correct call sequence for OpenGL 3.1 above should be:
      glEnableVertexAttribArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, VBO);
      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
      glDrawArrays(GL_TRIANGLES, 0, 3);
      glDisableVertexAttribArray(0);
      App call stack:
      Qt5Guid.dll!QOpenGLFunctions::glVertexAttribPointer(unsigned int indx, int size, unsigned int type, unsigned char normalized, int stride, const void * ptr) Line 2169 C++
      Qt5Guid.dll!QOpenGL2PaintEngineExPrivate::setVertexAttributePointer(unsigned int arrayIndex, const float * pointer) Line 339 C++
      Qt5Guid.dll!QOpenGL2PaintEngineExPrivate::composite(const QOpenGLRect & boundingRect) Line 1217 C++
      Qt5Guid.dll!QOpenGL2PaintEngineExPrivate::fill(const QVectorPath & path) Line 770 C++
      Qt5Guid.dll!QOpenGL2PaintEngineEx::fill(const QVectorPath & path, const QBrush & brush) Line 1260 C++
      Qt5Guid.dll!QPaintEngineEx::fillRect(const QRectF & r, const QBrush & brush) Line 700 C++
      Qt5Guid.dll!QPainter::fillRect(const QRect & r, const QBrush & brush) Line 6937 C++
      Qt5Widgetsd.dll!fillRegion(QPainter * painter, const QRegion & rgn, const QBrush & brush) Line 2410 C++
      Qt5Widgetsd.dll!QWidgetPrivate::paintBackground(QPainter * painter, const QRegion & rgn, int flags) Line 2444 C++
      Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5582 C++
      Qt5Widgetsd.dll!QWidgetPrivate::render(QPaintDevice * target, const QPoint & targetOffset, const QRegion & sourceRegion, QFlags<enum QWidget::RenderFlag> renderFlags) Line 5776 C++
      Qt5Widgetsd.dll!QWidget::render(QPainter * painter, const QPoint & targetOffset, const QRegion & sourceRegion, QFlags<enum QWidget::RenderFlag> renderFlags) Line 5210 C++
      Qt5Widgetsd.dll!QGraphicsProxyWidget::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) Line 1534 C++
      Qt5Widgetsd.dll!_q_paintItem(QGraphicsItem * item, QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget, bool useWindowOpacity, bool painterStateProtection) Line 4312 C++
      Qt5Widgetsd.dll!QGraphicsScenePrivate::drawItemHelper(QGraphicsItem * item, QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget, bool painterStateProtection) Line 4405 C++
      Qt5Widgetsd.dll!QGraphicsScenePrivate::draw(QGraphicsItem * item, QPainter * painter, const QTransform * const viewTransform, const QTransform * const transformPtr, QRegion * exposedRegion, QWidget * widget, double opacity, const QTransform * const effectTransform, bool wasDirtyParentSceneTransform, bool drawItem) Line 4964 C++
      Qt5Widgetsd.dll!QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem * item, QPainter * painter, const QTransform * const viewTransform, QRegion * exposedRegion, QWidget * widget, double parentOpacity, const QTransform * const effectTransform) Line 4855 C++
      Qt5Widgetsd.dll!QGraphicsScene::drawItems(QPainter * painter, int numItems, QGraphicsItem * * items, const QStyleOptionGraphicsItem * options, QWidget * widget) Line 5388 C++
      Qt5Widgetsd.dll!QGraphicsScene::render(QPainter * painter, const QRectF & target, const QRectF & source, Qt::AspectRatioMode aspectRatioMode) Line 1827 C++
      HelloWorldOverlay.exe!COpenVROverlayController::OnSceneChanged(const QList<QRectF> & __formal) Line 186 C++
      HelloWorldOverlay.exe!COpenVROverlayController::OnTimeoutPumpEvents() Line 243 C++
      HelloWorldOverlay.exe!COpenVROverlayController::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 79 C++
      Qt5Cored.dll!QMetaObject::activate(QObject * sender, int signalOffset, int local_signal_index, void * * argv) Line 3740 C++
      Qt5Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Line 3602 C++
      Qt5Cored.dll!QTimer::timeout(QTimer::QPrivateSignal __formal) Line 198 C++
      Qt5Cored.dll!QTimer::timerEvent(QTimerEvent * e) Line 256 C++
      Qt5Cored.dll!QObject::event(QEvent * e) Line 1245 C++
      Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3799 C++
      Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3159 C++
      Qt5Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 988 C++
      Qt5Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 231 C++
      Qt5Cored.dll!QEventDispatcherWin32Private::sendTimerEvent(int timerId) Line 657 C++
      Qt5Cored.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned int wp, long lp) Line 449 C++
      [External Code]
      [Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]
      Qt5Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 845 C++
      qwindowsd.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 74 C++
      Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 135 C++
      Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 210 C++
      Qt5Cored.dll!QCoreApplication::exec() Line 1261 C++
      Qt5Guid.dll!QGuiApplication::exec() Line 1640 C++
      Qt5Widgetsd.dll!QApplication::exec() Line 2976 C++
      HelloWorldOverlay.exe!main(int argc, char * * argv) Line 17 C++
      HelloWorldOverlay.exe!WinMain(HINSTANCE__ * formal, HINSTANCE * __formal, char * __formal, int __formal) Line 123 C++

      2. For the second issue:
      After you fix the first issue, then you will still see spinbox corruption in test.bmp, and the corruptionis caused by:
      When creating the texture for Qt Spinbox, Qt paint engine doesn’t generate the mip map or even no call something like
      glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

      We grab the following OpenGL API sequence from the driver side, apparently, Qt paint engine doesn't call glTexParameter when creating the texture for Spinbox.

      glDeleteTextures(1, 00EDA180)
      glGenTextures(1, 00ED9F2C)
      glBindTexture(GL_TEXTURE_2D, 2)
      glTexImage2D(GL_TEXTURE_2D, 0, 6408, 16, 10, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 09B80000)
      glDisable(GL_BLEND)
      glDrawArrays(GL_TRIANGLE_FAN, 0, 4)

      Please refer to the link to check the right way to create a complete texture:
      https://www.opengl.org/wiki/Common_Mistakes#Creating_a_complete_texture

      Attachments

        1. gl.trace
          26 kB
          Gunnar Sletta
        2. mytest2.rar
          15 kB
          Jeff liu
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            sletta Gunnar Sletta
            jeff-htc-vr Jeff liu
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes