5

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はすべて初期化されておらず、残りのコンテンツが含まれているはずだと思ったので、原因はわかりません。

4

3 に答える 3

6

OpenGLプログラミングを介してグラフィックカードのビデオメモリにアクセスする方法、具体的にはビデオメモリのすべての内容を取得する方法は?

それをしてはいけない。Raw ビデオ メモリには、OpenGL または DirectX 経由でアクセスできません。OpenGL にはさまざまな「バッファ」しかありません。それにアクセスできるのは、Windows プラットフォーム専用のビデオ ドライバーだけです。空きビデオ メモリはビデオ ドライバによって管理され、ビデオ メモリ内の特定のオブジェクトは一時的にしか存在しない場合があります。ドライバはコピーをシステム メモリに保存し、それらを移動して、必要に応じてディスクにオフロードできます。したがって、空きメモリを手動で管理するというあなたの考えには、実用的なアプリケーションはありません。

古いハードウェア (EGA/CGA/VGA など) や、VESA をサポートするカードでも、ビデオ メモリに直接アクセスできるはずですが、ハードウェア アクセラレーションがなく、MS-DOS に似たものを実行する必要があります。カーネル/ドライバー アクセス権限を持っています。Linux ではメモリの内容にアクセスできるかもしれませんが、役に立たないと思います。

この考えを忘れることをお勧めします。

OpenGLはそのようなタスクを実行できないということですか? 実際、私はこの問題に 2 か月近く取り組んできました。

このようなことは、最初に十分な量の調査を行わずに壮大なプロジェクトを開始した場合に通常発生します。この経験から学ぶことをお勧めします。コーディングを開始する前に、アプリがまだ作成されていないかどうか、実用的なアプリケーションがあるかどうか、作成できるかどうか、そのアプリの必要性があるかどうか、作成するのに十分なリソースがあるかどうかを必ず確認してください。

現在、ビデオ メモリに格納されているオブジェクトを管理するのはドライバーの仕事です。

他のアプリケーションによって作成されたオブジェクトを見たい場合は、プロキシ dll、dll インジェクション、または同様の手法を使用して OpenGL API をハイジャックし、関連する呼び出しを傍受する方がおそらく簡単です。

于 2012-05-11T19:43:41.967 に答える
2

OpenGLプログラミングを介してグラフィックカードのビデオメモリにアクセスする方法、具体的にはビデオメモリのすべての内容を取得する方法は?

OpenGL ではなく、オペレーティング システムと対話します。

于 2012-05-11T17:32:47.090 に答える
-1

なぜこれをしたいのか、そしてあなたの最終的なゲームは何なのかは明らかではありませんが、サードパーティのアプリケーションによって生成されたグラフィック情報にアクセスしようとしているようです.

FRAPS の機能を実現しようとしている場合は、目的とはまったく異なる手法 (はるかに単純な手法) を使用していることに注意してください: OpenGL や DirectX などのグラフィック ライブラリへの呼び出しをインターセプトします。

于 2012-05-11T19:38:21.803 に答える