0

After days of trying I was not able to render Pixeldata into a textured quad correctly.

What I want is fairly simple (I think): I am currently writing a VNC implementation for my company to bind it into an existing application. I already successfully implemented the RfbProtocol (at least as far as I need it) and I am able to get the correct Pixeldata. Because the VNC server is sending incremental changes only I am receiving small rectangles with the changed region and the pixel information.

I already worked out that the corresponding OpenGL Formats for the Pixeldata is GL_BGRA and GL_UNSIGNED_INT_8_8_8_8_REV.

Because I was not able to use Textured Quads (whats seems to be the optimal implementation for this purpose) I used a different approach:

  if(m_queue.size() > 0)
  {
    if (!m_fbo || m_fbo->size() != size())
    {
      delete m_fbo;
      QOpenGLFramebufferObjectFormat format;
      format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
      m_fbo = new QOpenGLFramebufferObject(size());
    }

    m_fbo->bind();

    Q_FOREACH (RfbProtocol::RfbRectangle rect, m_queue.dequeue().rectangles())
    {
      glViewport(0, 0, 1920, 1080);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(0, 1920, 0, 1080, -1, 1);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glRasterPos2d(rect.xpos, rect.ypos);
      glDrawPixels(rect.width,rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, rect.pixelData.data());
    }
    m_fbo->release();
    this->update();
  }

This is all done inside an QOpenGLWidget.

Obviously this is not the best approach but it is working for testing. The problem is that I need to scale the Pixeldata to the size of the Widget, which would work nicely together with a OpenGLTexture but as I mentioned at the beginning I simply wasn't able to do it correctly.

zero695
  • 15
  • 5

1 Answers1

1

Don't use glDrawPixels. It's old and slow and has been removed from modern OpenGL.

Just use glTexSubImage2D to update the subrectangles of the texture holding the screen content.

EDIT:

GLuint create_texture(unsigned width, unsigned height)
{
    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);

    /* initialize texture to nil */
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
        width, height, 0,
        GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);

    /* disable mipmapping */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    return tex;
}

void update_texture(GLuint tex, RECT r, RGBA *pixels)
{
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexSubImage2D(GL_TEXTURE_2D, 0,
        r.left, r.bottom,
        r.right-r.left, r.top-r.bottom,
        GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
        pixels );
}

I guess you can tink the definitions for RECT and RGBA yourself.

Then just draw a viewport filling textured quad and you're done. Textured quads give you nice scaling for free.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • could you mybe give me a brief exmaple of how to use it? – zero695 Mar 29 '18 at 09:22
  • @ChristianRöskens: See my edit. But seriously, the documentation for glTexSubImage2D is pretty much self explanatory. And there are tons of tutorials out there how to create textures and draw them onto a quad. – datenwolf Mar 29 '18 at 09:47
  • thanks for your example, I will try to implement that. And yes you are right there are plenty of tutorials out there but I'm still struggling with it, maybe because I'm lacking a little bit of basic theory in OpenGL things. Is there a chance that I can contact you if I have further problems with this thematic? – zero695 Mar 29 '18 at 10:42
  • @ChristianRöskens: Sure. However I'm on vacation over the easter weekend. – datenwolf Mar 29 '18 at 10:47
  • unfortunatly i still have only a black screen when trying to draw a quad – zero695 Mar 29 '18 at 11:26
  • @CRoe: well, show your actual code. update the question, or make a new one if appropriate – derhass Mar 29 '18 at 20:26