0

我们正在开发用于创建幻灯片的软件并使用 OpenGL。我们使用 FBO + PBO 将数据从 VGA 快速读取到 RAM,但在 ATI 的一些视频卡上,我们面临以下问题:

  1. 交换 RGB 分量
  2. 像素移位

如果我们不使用 PBO,就没有问题。我们还注意到 PBO/FBO (4:3) 的纵横比解决了像素偏移问题。

有什么想法或建议吗?

以下是更多详细信息:

  • ATI Radeon HD 3650

PBO代码:

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 将数据读回内存

                    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 初始化

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];
    }

在此处输入图像描述

4

1 回答 1

2

似乎重新安装/更新 VGA 驱动程序确实可以解决此问题。

真的很奇怪的行为(另外,可能是官方笔记本驱动程序太旧/错误/等导致了问题,所以用 AMD 的最新驱动程序更新,对于这个 vga 芯片系列,似乎会影响/解决问题。另外我不确定之前的驱动程序是否设置正确,因此我说重新安装/更新)

谢谢大家的帮助。

于 2013-10-28T08:31:27.183 回答