Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Bug in Qt >= 5.4 when drawing QPixmap onto QOpenGLPaintDevice
Forum Update on Monday, May 27th 2025

Bug in Qt >= 5.4 when drawing QPixmap onto QOpenGLPaintDevice

Scheduled Pinned Locked Moved Unsolved General and Desktop
qpixmapdrawpixmapopenglbugglbindtexture
4 Posts 2 Posters 2.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    matejtomcik
    wrote on 4 May 2016, 12:44 last edited by
    #1

    Hello,
    I came across a strange behavior when drawing QPixmap-s onto QOpenGLPaintDevice in Qt 5.4+
    Here is the Qt project which can reproduce this behavior: http://s000.tinyupload.com/?file_id=47422674383658218989

    What I do is I render scene into two textures, first is rendered with OpenGL (simple triangle), the second one is rendered with QPainter using QOpenGLPaintDevice. These two textures are then sent into a shader program where I combine them.
    Correct result in Qt 5.3.2: http://pasteboard.co/FCKxxWJ.png
    Incorrect result in Qt 5.6.0: http://pasteboard.co/FCM2FIu.png

    Here is what I do:

    // Render triangle into the first texture
    mLayer1FBO->bind();
    glViewport(0, 0, mLayer1FBO->width(), mLayer1FBO->height());
    glClearColor(0, 1, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1, 1, -1, 1, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    glBegin(GL_TRIANGLES);
    glColor4f(0, 0, 1, 1);
    glVertex2f(-1, -1);
    glVertex2f( 0,  1);
    glVertex2f( 1, -1);
    glEnd();
    mLayer1FBO->release();
    
    // Render translucent line and a rectangle into the second texture
    mLayer2FBO->bind();
    glViewport(0, 0, mLayer2FBO->width(), mLayer2FBO->height());
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);
    {
    	QOpenGLPaintDevice openglPaintDevice(mLayer2FBO->size());
    	QPainter openglPainter(&openglPaintDevice);
    
    	/*
    	 * Abnormality #1
    	 * Rendering strokes with opacity fills the bounding box with pen's color
    	 */
    	openglPainter.setPen(QColor(255, 255, 0, 200));
    	openglPainter.drawLine(0, 0, 120, 100);
    
    	{
    		mLayer2Pixmap->fill(Qt::transparent);
    		QPainter pixmapPainter(mLayer2Pixmap);
    		pixmapPainter.fillRect(50, 50, 100, 100, QColor(255, 0, 0, 255));
    	}
    	/*
    	 * Abnormality #2
    	 * Rendering to a QPixmap then drawing the pixmap with QPainter onto OpenGL surface
    	 * will lead to an invalid OpenGL state (third part of this example which takes two
    	 * textures and blends them together in a simple fragment shader stops working).
    	 * Using QImage over QPixmap does not help
    	 */
    	openglPainter.drawPixmap(0, 0, *mLayer2Pixmap);
    }
    mLayer2FBO->release();
    
    // Blend two textures together into the default render target
    #if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
    glBindFramebuffer(GL_FRAMEBUFFER, context()->contextHandle()->defaultFramebufferObject());
    #else
    glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
    #endif
    mBlender->setBackgroundColor(Color::Black);
    mBlender->setTextureCount(2);
    mBlender->setTexture(0, mLayer1FBO->texture(), 1.0f);
    mBlender->setTexture(1, mLayer2FBO->texture(), 1.0f);
    mBlender->render(CompositionEffect::InvalidSourceTexture, mLayer1FBO->width(), mLayer2FBO->height());
    

    If I comment out this line:

    openglPainter.drawPixmap(0, 0, *mLayer2Pixmap);
    

    then everything works fine (except the second texture does not contain the red rectangle, obviously).
    My guess is that the drawPixmap method somehow modifies the OpenGL state.

    This is the code used to blend together the textures (see TextureCombineCompositionEffect.cpp and ShaderCompositionEffect.cpp in the attached ZIP):

    // Bind shader program
    mShaderProgram.bind();
    
    // Bind vertex buffer object and set attribute pointer
    mOpenGLFunctions.glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    mOpenGLFunctions.glEnableVertexAttribArray(mAttribPos);
    mOpenGLFunctions.glVertexAttribPointer(mAttribPos, 2, GL_FLOAT, GL_FALSE, 0, 0);
    
    // Bind textures
    const int count = static_cast<int>(mTextureCount);
    for (int i = 0; i < count; i++)
    {
    	mOpenGLFunctions.glActiveTexture(GL_TEXTURE0 + i);
    	glEnable(GL_TEXTURE_2D);
    	glBindTexture(GL_TEXTURE_2D, mTextures[i]);
    	mShaderProgram.setUniformValue(mAttribSamplers + i, i);
    }
    
    // Set attributes
    mShaderProgram.setUniformValue(mAttribCount, count);
    mShaderProgram.setUniformValueArray(mAttribFactors, mBlendFactors, count, 1);
    mShaderProgram.setUniformValue(mAttribBackground, QVector4D(mBackgroundColor.r, mBackgroundColor.g,
    															mBackgroundColor.b, mBackgroundColor.a));
    
    // Render screen quad
    mOpenGLFunctions.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
    // Unbind textures
    const int textureCount = static_cast<int>(mTextureCount);
    for (int i = 0; i < textureCount; ++i)
    {
    	mOpenGLFunctions.glActiveTexture(GL_TEXTURE0 + i);
    	glDisable(GL_TEXTURE_2D);
    	glBindTexture(GL_TEXTURE_2D, 0);
    }
    
    // Unbind vertex buffer object and shader program
    mOpenGLFunctions.glDisableVertexAttribArray(mAttribPos);
    mOpenGLFunctions.glBindBuffer(GL_ARRAY_BUFFER, 0);
    mShaderProgram.release();
    
    1 Reply Last reply
    0
    • M Offline
      M Offline
      matejtomcik
      wrote on 5 May 2016, 06:38 last edited by
      #2

      I have found out that if I call:

      glActiveTexture(GL_TEXTURE0);
      

      before calling

      openglPainter.drawPixmap(0, 0, *mLayer2Pixmap);
      

      then it works. I have no idea why, because the QGL2PaintEngineEx::drawPixmap(const QRectF&, const QPixmap&, const QRectF&) method activates the texture unit like this:

      d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
      

      What is going on, Qt devs?

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 5 May 2016, 18:36 last edited by SGaist 5 Jun 2016, 20:03
        #3

        Hi,

        What OS are you running ? Your shader crashes on my old OS X.

        In any case, you should take a look at the bug report system to see if it's something know.

        As for the Qt developers/maintainers, you can reach them on the interest mailing list. This forum is more user oriented.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        M 1 Reply Last reply 6 May 2016, 08:01
        0
        • S SGaist
          5 May 2016, 18:36

          Hi,

          What OS are you running ? Your shader crashes on my old OS X.

          In any case, you should take a look at the bug report system to see if it's something know.

          As for the Qt developers/maintainers, you can reach them on the interest mailing list. This forum is more user oriented.

          M Offline
          M Offline
          matejtomcik
          wrote on 6 May 2016, 08:01 last edited by
          #4

          @SGaist Hi, I'm running Windows 10, OpenGL 4.5.0

          1 Reply Last reply
          0

          1/4

          4 May 2016, 12:44

          • Login

          • Login or register to search.
          1 out of 4
          • First post
            1/4
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved