OpenGLプログラミングを介してグラフィックカードのビデオメモリにアクセスするには、具体的には、ビデオメモリのすべてのコンテンツを取得するにはどうすればよいですか?
次の2つの方法を試しましたが、失敗しました。それらを添付することで、私のプログラムまたはビデオメモリの構造の理解におけるエラーを指摘していただければ幸いです。前もって感謝します!
私の基本的な考え方は、ビデオメモリのすべての内容を調べるまで、ビデオメモリに初期化されていない領域を割り当て続けることです。
(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()関数を呼び出して画面を表示します。このプログラムを実行すると、黒いウィンドウのみが表示されます。デフォルトの色は黒です。つまり、ウィンドウには何も含まれていません。次に、バックフレームバッファから他の領域を読み取ろうとしましたが、すべてに何も含まれていません。
上記の結論は、バックフレームバッファには何も含まれていないということです。ただし、フロントバッファには現在の画面コンテンツ/ウィンドウのみが含まれている必要があるため、これは不合理です。したがって、画面の下部で開いて最小化された他のウィンドウのコンテンツはバックフレームバッファに含まれている必要がありますが、バックフレームバッファは空です。では、それらのウィンドウ(下部にある私が開いて最小化したもの)はどこに保存されますか?
私のプログラムに割り当てられたフレームバッファ(背面と前面)は、ビデオメモリ全体のごく一部しか占めていないと思います。したがって、これらの最小化されたWindowsコンテンツは、ビデオメモリの他の場所に保存する必要があります。
しばらくして、OpenGL frameBufferオブジェクト(FBO)の概要を読みましたが、次のような文があります。デフォルトでは、OpenGLは、ウィンドウシステムによって完全に作成および管理されるレンダリング先としてフレームバッファーを使用します。このデフォルトのフレームバッファは、ウィンドウシステムが提供するフレームバッファと呼ばれます。これは私の上記の推測を検証しているようです。
(2)次に、FBOがビデオメモリコンテンツ全体の調査に役立つことを期待して、FBOの作業を開始します。
以下のメイン関数では、FBOと7つのrenderbufferオブジェクト(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;
}
以下は、私のdisplayコールバック関数の主要部分です。その機能は、スペースキーを使用して、読み取る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はすべて初期化されておらず、残りのコンテンツが含まれているはずだと思ったので、原因はわかりません。