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

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 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 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
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by SGaist
        #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
        0
        • SGaistS SGaist

          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 last edited by
          #4

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

          1 Reply Last reply
          0

          • Login

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