0

We are developing software for slide show creation and use OpenGL. We use FBO + PBO for fast data reading from VGA to RAM but on some video cards from ATI we faced with the following problems:

  1. swapping RGB components
  2. pixel shifting

There are no problems if we do not use PBO. Also we have noticed that the aspect ratio of PBO/FBO (4:3) solve the pixel shifting problem.

Any thoughts or suggestions?

Here are more details:

  • ATI Radeon HD 3650

PBO code:

public bool PBO_Initialize(
        int bgl_size_w,
        int bgl_size_h)
    {
        PBO_Release();
        if (mCSGL12Control1 != null)
        {
            GL mGL = mCSGL12Control1.GetGL();
            mCSGL12Control1.wgl_MakeCurrent();
            //
            // check PBO is supported by your video card
            if (mGL.bglGenBuffersARB == true &&
                mGL.bglBindBufferARB == true &&
                mGL.bglBufferDataARB == true &&
                mGL.bglBufferSubDataARB == true &&
               mGL.bglMapBufferARB == true &&
               mGL.bglUnmapBufferARB == true &&
               mGL.bglDeleteBuffersARB == true &&
               mGL.bglGetBufferParameterivARB == true)
            {
                mGL.glGenBuffersARB(2, _pbo_imageBuffers);
                int clientHeight1 = bgl_size_h / 2;
                int clientHeight2 = bgl_size_h - clientHeight1;
                int clientSize1 = bgl_size_w * clientHeight1 * 4;
                int clientSize2 = bgl_size_w * clientHeight2 * 4;


                mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[0]);
                mGL.glBufferDataARB(GL.GL_PIXEL_PACK_BUFFER_ARB, clientSize1, IntPtr.Zero,
                                GL.GL_STREAM_READ_ARB);

                mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[1]);
                mGL.glBufferDataARB(GL.GL_PIXEL_PACK_BUFFER_ARB, clientSize2, IntPtr.Zero,
                                GL.GL_STREAM_READ_ARB);

                return true;
            }
        }
        return false;
    }

... PBO read data back to memory

                    int clientHeight1 = _bgl_size_h / 2;
                    int clientHeight2 = _bgl_size_h - clientHeight1;
                    int clientSize1 = _bgl_size_w * clientHeight1 * 4;
                    int clientSize2 = _bgl_size_w * clientHeight2 * 4;
                    //mGL.glPushAttrib(GL.GL_VIEWPORT_BIT | GL.GL_COLOR_BUFFER_BIT);

                    // Bind two different buffer objects and start the glReadPixels
                    // asynchronously. Each call will return directly after
                    // starting the DMA transfer.
                    mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[0]);
                    mGL.glReadPixels(0, 0, _bgl_size_w, clientHeight1, imageFormat,
                                    pixelTransferMethod, IntPtr.Zero);

                    mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[1]);
                    mGL.glReadPixels(0, clientHeight1, _bgl_size_w, clientHeight2, imageFormat,
                                    pixelTransferMethod, IntPtr.Zero);

                    //mGL.glPopAttrib();
                    mGL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);

                    // Process partial images.  Mapping the buffer waits for
                    // outstanding DMA transfers into the buffer to finish.
                    mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[0]);
                    IntPtr pboMemory1 = mGL.glMapBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB,
                                                GL.GL_READ_ONLY_ARB);

                    mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[1]);
                    IntPtr pboMemory2 = mGL.glMapBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB,
                                                GL.GL_READ_ONLY_ARB);


                    System.Runtime.InteropServices.Marshal.Copy(pboMemory1, _bgl_rgbaData_out, 0, clientSize1);
                    System.Runtime.InteropServices.Marshal.Copy(pboMemory2, _bgl_rgbaData_out, clientSize1, clientSize2);


                    // Unmap the image buffers
                    mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[0]);
                    mGL.glUnmapBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB);
                    mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[1]);
                    mGL.glUnmapBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB);

FBO initialization

private static void FBO_Initialize(GL mGL,
        ref int[] bgl_texture,
        ref int[] bgl_framebuffer,
        ref int[] bgl_renderbuffer,
        ref byte[] bgl_rgbaData,
        int bgl_size_w,
        int bgl_size_h)
    {
        // Texture
        mGL.glGenTextures(1, bgl_texture);
        mGL.glBindTexture(GL.GL_TEXTURE_2D, bgl_texture[0]);

        mGL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
        mGL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
        mGL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
        mGL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
        IntPtr null_ptr = new IntPtr(0);
        // <null> means reserve texture memory, but texels are undefined
        mGL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, bgl_size_w, bgl_size_h, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, null_ptr);
        //
        mGL.glGenFramebuffersEXT(1, bgl_framebuffer);
        mGL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, bgl_framebuffer[0]);

        mGL.glGenRenderbuffersEXT(1, bgl_renderbuffer);
        mGL.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, bgl_renderbuffer[0]);
        mGL.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT, GL.GL_DEPTH_COMPONENT24, bgl_size_w, bgl_size_h);


        mGL.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT,
            GL.GL_TEXTURE_2D, bgl_texture[0], 0);
        mGL.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT,
            GL.GL_RENDERBUFFER_EXT, bgl_renderbuffer[0]);

        // Errors?
        int status = mGL.glCheckFramebufferStatusEXT(GL.GL_FRAMEBUFFER_EXT);
        if (status != GL.GL_FRAMEBUFFER_COMPLETE_EXT || mGL.glGetError() != GL.GL_NO_ERROR)
        {
            mGL.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT,
                GL.GL_TEXTURE_2D, 0, 0);
            mGL.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT,
                GL.GL_RENDERBUFFER_EXT, 0);

            mGL.glBindTexture(GL.GL_TEXTURE_2D, 0);
            mGL.glDeleteTextures(1, bgl_texture);
            mGL.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, 0);
            mGL.glDeleteRenderbuffersEXT(1, bgl_renderbuffer);
            mGL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
            mGL.glDeleteFramebuffersEXT(1, bgl_framebuffer);

            throw new Exception("Bad framebuffer.");
        }

        mGL.glDrawBuffer(GL.GL_COLOR_ATTACHMENT0_EXT);
        mGL.glReadBuffer(GL.GL_COLOR_ATTACHMENT0_EXT); // For glReadPixels()

        mGL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);

        mGL.glDrawBuffer(GL.GL_BACK);
        mGL.glReadBuffer(GL.GL_BACK);
        mGL.glBindTexture(GL.GL_TEXTURE_2D, 0);

        bgl_rgbaData = new byte[bgl_size_w * bgl_size_h * 4];
    }

enter image description here

okarpov
  • 864
  • 14
  • 22
  • We can't help you without seeing your code. There are many possible causes. – derhass Oct 08 '13 at 19:53
  • Thx, have updated information – okarpov Oct 10 '13 at 09:59
  • 1
    Is there any reason in particular you are using the EXT FBO extension? Radeon HD 3xxx hardware supports OpenGL 3.2, the EXT extension is an unmaintained mess and you should use ARB or core OpenGL 3.0 FBOs whenever they are available. Likewise, PBOs are core as well. I would start with migrating the code to use core OpenGL first and see if that changes anything; you may need to write multiple code paths if this turns out to be an extension interop. issue on AMD hardware. – Andon M. Coleman Oct 12 '13 at 06:09
  • Thank you for the information, we will try it – okarpov Oct 14 '13 at 07:46

1 Answers1

2

It seems that re-installing/updating VGA Driver does solve this problem.

Really strange behaviour (also, it may be that the official notebook driver is old/buggy/etc. and causes the problem, so updating with the latest driver from AMD, for this vga-chip series, seems affect/solve the problem. Also I'm not sure if the previouse driver was set up correct thus I say re-installing/updating)

Thank you all for help.

okarpov
  • 864
  • 14
  • 22