如何通过OpenGL编程访问显卡的显存,具体是获取显存的所有内容?
我尝试了以下两种方法,但都失败了。附上它们,希望您能指出我的程序或我对显存结构的理解中的错误。提前致谢!
我的基本想法是继续在显存中分配一个未初始化的区域,直到探索完显存的所有内容。
(1) 在 main 函数中,我创建了一个带有双缓冲区的窗口(参见下面的代码)。
int main(int argc,char ** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); // double buffers
glutInitWindowPosition(0,0);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("Hope to be successful!");
glutDisplayFunc(myDisplay); // call back function "myDisplay"
glutKeyboardFunc(keyboard);
glutMainLoop();
free(PixelData);
return 0;
}
然后,在“myDisplay”函数中,首先我调用 glReadPixels() 函数从后帧缓冲区中读出一个给定大小的像素矩形,将这些像素信息保存在一个数组“PixelData”中,最后将这些像素信息显示在通过调用 glDrawPixels() 函数来显示屏幕。执行此程序后,只出现一个黑色窗口。黑色是默认颜色。所以这意味着窗口不包含任何内容。然后我尝试从后面的帧缓冲区中读取其他区域,所有这些区域都没有包含任何内容。
从上面得出的结论是,后帧缓冲区中不包含任何内容。然而,这是不合理的,因为前缓冲区应该只包含当前屏幕内容/窗口,因此在屏幕底部打开和最小化的其他窗口应该在后帧缓冲区中有它们的内容,但后帧缓冲区是空的。那么这些窗口(由我在底部打开和最小化)存储在哪里?
我猜为我的程序分配的帧缓冲区(前后)只占整个视频内存的一小部分。因此,那些最小化的窗口内容应该存储在视频内存的其他位置。
过了一段时间,看了一篇OpenGL frameBuffer object (FBO)的介绍,里面有一句话:默认情况下,OpenGL使用framebuffer作为渲染目的地,完全由窗口系统创建和管理。此默认帧缓冲区称为窗口系统提供的帧缓冲区。这似乎验证了我的上述猜测。
(2) 然后我开始做FBO,希望FBO可以帮助我探索整个显存内容。
在下面的 main 函数中,我创建了一个 FBO 和 7 个渲染缓冲区对象(RBO),然后通过颜色附加点将这 7 个 RBO 附加到这个 FBO。
const int RBO_COUNT = 7; //how many renderBuffer objects are created to attach to the frameBuffer object
int main(int argc, char **argv)
{
....
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_ALPHA); // display mode
...
// create a framebuffer object
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
//Create several 7 render buffer objects and attach all of them to the FBO.
glGenRenderbuffers(RBO_COUNT, rbo);
for (int i = 0; i < RBO_COUNT; i++)
{
glBindRenderbuffer(GL_RENDERBUFFER, rbo[i]);
glRenderbufferStorage(GL_RENDERBUFFER, PIXEL_FORMAT, SCREEN_WIDTH, SCREEN_HEIGHT);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, colorAttach[i], GL_RENDERBUFFER, rbo[i]);
}
// check FBO status
bool status = checkFramebufferStatus();
if(!status) fboUsed = false;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
...
glutMainLoop(); /* Start GLUT event-processing loop */
return 0;
}
下面是我的显示回调函数的主要部分。它的作用是使用空格键控制读取哪个renderBuffer对象,然后将其内容显示在屏幕上。
void displayCB()
{
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
//read this FBO attached RBO, save its content to fboContent
//"count" is a global variable, and is incremented by 1 (mod )every time pressing the space key of the keyboard.
glReadBuffer(colorAttach[count]);
glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_FORMAT, GL_UNSIGNED_BYTE, fboContent);
// back to normal window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind
// render to the default framebuffer //////////////////////////
glClear(GL_COLOR_BUFFER_BIT); // clear buffer
glClearColor(1, 0, 0, 1);
glDrawBuffer(GL_BACK);
glRasterPos2i(-1, -1);
glDrawPixels(SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_FORMAT, GL_UNSIGNED_BYTE, fboContent);
glutSwapBuffers();
}
最后的结果令人失望。所有 renderBuffer 对象的内容都是空的。我不知道这是什么原因,因为我认为所有这些 RBO 都从未初始化过,应该包含一些剩余的内容。