Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

glReadPixels works fine in Linux but not in Windows 10



  • I'm trying to save an image drawn in an QOpenGLWindow. The code is simple

    void XYScene::CreateTIFF()
    {
       emit AlertMsg("Creating Screenshot image as TIFF ....",' ');
    
       int nNoRGBABytes = XImageSize*YImageSize*4;
    
       GLubyte* ScreenData=nullptr;
       try{
           ScreenData = new GLubyte[size_t(nNoRGBABytes)];
       }
       catch (std::bad_alloc& ba)
       {
           emit AlertMsg(QString("Unable to allocate memory for TIFF creation<br>Reason: %1").arg(ba.what()),'r');
           return;
       }
       glPixelStorei(GL_PACK_ALIGNMENT, 1);
       glReadPixels(0, 0, XImageSize, YImageSize, GL_RGBA, GL_UNSIGNED_BYTE, ScreenData);
      .........
    
    

    This code works perfectly in Linux (Fedora using XWindows and g++) but not in Windows (Win10 using MSVC 2019). When I look at ScreenData in Windows it's filled with zero's which would seem to indicate that something is being transferred but not from the right place. Is there some code that I need to insert for it to work on Windows?

    This is on a dual-boot machine so that all that differs is the Operating system and the NVIDIA drivers (and whatever difference there is in how OpenGL is implemented). In Windows Qt::AA_UseDesktopOpenGL is set via QCoreApplication.



  • I did, but same problem - it turns out that in Windows, with my setup, the image is on the back buffer, not the front, so the solution was:

    void XYScene::CreateTIFF()
    {
       emit AlertMsg("Creating Screenshot image as TIFF ....",' ');
    
       int nNoRGBABytes = XImageSize*YImageSize*4;
    
       GLubyte* ScreenData=nullptr;
       try{
           ScreenData = new GLubyte[size_t(nNoRGBABytes)];
       }
       catch (std::bad_alloc& ba)
       {
           emit AlertMsg(QString("Unable to allocate memory for TIFF creation<br>Reason: %1").arg(ba.what()),'r');
           return;
       }
    #ifdef WIN32
       QOpenGLContext* ctx = context();
       QSurface* ctsurf = ctx->surface();
       ctx->swapBuffers(ctsurf);       // swap buffers to bring image to the front buffer to be read.
    #endif
       glReadPixels(0, 0, XImageSize, YImageSize, GL_RGBA, GL_UNSIGNED_BYTE, ScreenData);
    #ifdef WIN32
       ctx->swapBuffers(ctsurf);  // need this to see the image otherwise screen is black 
       makeCurrent();
    #endif
    
    

    Why this happening in my setup and whether it would occur on other Window systems, I don't know.


  • Lifetime Qt Champion

    Hi,

    Why not use QOpenGLWindow::grabFramebuffer ?



  • I did, but same problem - it turns out that in Windows, with my setup, the image is on the back buffer, not the front, so the solution was:

    void XYScene::CreateTIFF()
    {
       emit AlertMsg("Creating Screenshot image as TIFF ....",' ');
    
       int nNoRGBABytes = XImageSize*YImageSize*4;
    
       GLubyte* ScreenData=nullptr;
       try{
           ScreenData = new GLubyte[size_t(nNoRGBABytes)];
       }
       catch (std::bad_alloc& ba)
       {
           emit AlertMsg(QString("Unable to allocate memory for TIFF creation<br>Reason: %1").arg(ba.what()),'r');
           return;
       }
    #ifdef WIN32
       QOpenGLContext* ctx = context();
       QSurface* ctsurf = ctx->surface();
       ctx->swapBuffers(ctsurf);       // swap buffers to bring image to the front buffer to be read.
    #endif
       glReadPixels(0, 0, XImageSize, YImageSize, GL_RGBA, GL_UNSIGNED_BYTE, ScreenData);
    #ifdef WIN32
       ctx->swapBuffers(ctsurf);  // need this to see the image otherwise screen is black 
       makeCurrent();
    #endif
    
    

    Why this happening in my setup and whether it would occur on other Window systems, I don't know.


Log in to reply