GLXINTRO

名前
glXIntro - X ウィンドウシステムで OpenGL を使う方法の解説

概要
OpenGL(他のページでは GL と呼ぶ)は、高性能な 3 次元指向レンダラである。 OpenGL は GLX 機能拡張を通じて X ウィンドウシステムで利用することがで きる。 X サーバが GLX 機能拡張をサポートしているかどうかを確かめる場合や、 サポートしている場合にそのバージョンを確かめるには、 glXQueryExtension と glXQueryVersion を用いること。

GLX 機能拡張に対応したサーバは、OpenGL のレンダリングに使うことができ るビジュアルを、全体のビジュアルのサブセットとして生成する。 このようなビジュアルを使って生成されたドロウアブルは、コアの X レンダラ を使ってレンダリングすることや、コアの X ビジュアル全てと互換である任 意の機能拡張のレンダラを使ってレンダリングすることができる。

GLX は、標準のカラーバッファ以外にいくつかのバッファを追加してドロウア ブルを拡張する。 これらのバッファには、背面カラーバッファや補助カラーバッファ、 デプスバッファ、 ステンシルバッファ、 カラーアキュームレーションバッファが含まれる。 これらの一部あるいは全ては、OpenGL をサポートしているそれぞれの X ビジュ アルに含まれる。

OpenGL を用いて X のドロウアブルをレンダリングするにはまず、必要とされ る OpenGL バッファを定義するビジュアルを選択しなければならない。 glXChooseVisual を使うと、条件に合うビジュアルの選択を簡単に行う ことができる。 選択処理をもっと細かく制御する必要があれば、 XGetVisualInfo と glXGetConfig を用いて、利用可能な全ての ビジュアルの中から選択を行うこと。

GLX コンテクストと X のドロウアブルのどちらを作るにも、選択したビジュ アルを使うこと。 GLX コンテクストは glXCreateContext を使って生成し、ドロウアブル は XCreateWindow か glXCreateGLXPixmap を使って生成する。 最後に、glXMakeCurrent を使ってコンテクストとドロウアブルを関連 付けること。 このコンテクストとドロウアブルのペアは現在のコンテクストと現在の ドロウアブルになり、他の引き数を指定して glXMakeCurrent を呼び出 すまでは、全ての OpenGL のコマンドはこれを用いる。

コアの X コマンドを使っても、OpenGL のコマンドを使っても現在のドロウアブル を操作することができる。 しかし、X と OpenGL のコマンドストリームは同期していない( glXWaitGL, glXWaitX, XSync, glFlush を呼び出し て両者の境界を明示的に生成した場合は除く)。

例
以下に示すのは、RGBA 形式であり OpenGL と互換な X のウィンドウを生成し、 これを黄色でクリアするための最小限のコードである。 これは正しいコードであるが、エラーチェックは全く入っていない。 本来は返り値の dpy, vi, cx, cmap, win は 全てチェックすべきである。

#include <GL/glx.h> #include <GL/gl.h> #include <unistd.h> static int attributeListSgl[] = {
    GLX_RGBA,
    GLX_RED_SIZE, 1, /*Red ビットを 1 持つ最も深いバッファを取得*/
    GLX_GREEN_SIZE, 1,
    GLX_BLUE_SIZE, 1,
    None }; static int attributeListDbl[] = {
    GLX_RGBA,
    GLX_DOUBLE_BUFFER, /*シングルバッファリングがサポートされていない場合*/
    GLX_RED_SIZE, 1,
    GLX_GREEN_SIZE, 1,
    GLX_BLUE_SIZE, 1,
    None }; static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
    return (e->type == MapNotify) && (e->xmap.window == (Window)arg); } int main(int argc, char **argv) {
    Display *dpy;
    XVisualInfo *vi;
    Colormap cmap;
    XSetWindowAttributes swa;
    Window win;
    GLXContext cx;
    XEvent event;
    int swap_flag = FALSE;
    /* X サーバとの接続を取得する */
    dpy = XOpenDisplay(0);
    /* 適切なビジュアルを取得する */
    vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeListSgl);
    if (vi == NULL) {
       vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeListDbl);
       swap_flag = TRUE;
    }
    /* GLX コンテクストを生成する */
    cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
    /* カラーマップを生成する */
    cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
               vi->visual, AllocNone);
    /* ウィンドウを生成する */
    swa.colormap = cmap;
    swa.border_pixel = 0;
    swa.event_mask = StructureNotifyMask;
    win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 100, 100,
                        0, vi->depth, InputOutput, vi->visual,
                        CWBorderPixel|CWColormap|CWEventMask, &swa);
    XMapWindow(dpy, win);
    XIfEvent(dpy, &event, WaitForNotify, (char*)win);
    /* コンテクストをウィンドウに接続する */
    glXMakeCurrent(dpy, win, cx);
    /* バッファをクリアする */
    glClearColor(1,1,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    glFlush();
    if (swap_flag) glXSwapBuffers(dpy,win);
    /* しばらく待つ */
    sleep(10); }

注意
カラーマップは必ず生成し、XCreateWindow に渡さなければならない。 上記のサンプルコードを参照すること。

GLX コンテクストは、OpenGL のコマンドが実行される前に生成し、X の ドロウアブルに割り当てなければならない。 現在のコンテクストとドロウアブルのペアが無い状態で OpenGL のコマンドを 発行すると、その動作は未定義である。

露出イベントは、指定されたウィンドウに関係がある全てのバッファの 内容が壊れた可能性があり、再描画しなければならないことを示す。 一部のシステムでは、一部のビジュアルの特定のバッファ(例えばデプスバッ ファ)は再描画を全く必要としないことがあるが、このようなバッファの内容 が壊れないことを前提としてプログラムを書くことは間違いである。

GLX コマンドは XVisualInfo 構造体を扱い、ビジュアルへのポインタやビジュ アルの ID を扱うことはない。 XVisualInfo には、visual, visualID, screen, depth 要素や他の X 固有の情報が含まれる。

GLX 機能拡張の使用
サポートされている全ての GLX 機能拡張について、対応する定義が glx.h に ある。また、glXQueryExtensionsString が返す拡張内容を表す文字列 にはトークンが含まれる。 例えば、EXT_visual_info 機能拡張がサポートされていれば、このトー クンは glx.h で定義されており、glXQueryExtensionsString が返す拡 張内容を表す文字列には EXT_visual_info が現れる。glx.h における 定義は、拡張に対応する手続きがライブラリ内に存在しているかどうかを調べ るためにコンパイル時に使われる。

OpenGL そのものも今まで拡張されてきている。詳しくは glIntro を参 照すること。

GLX 1.1 と GLX 1.2
GLX 1.2 は既にサポートされている。これは GLX 1.1 と GLX 1.0 に対して後 方互換性を持つ。

GLX 1.2 は OpenGL 1.1 に対応し、新しい関数として glGetCurrentDisplay が導入されている。

GLX 1.1 は OpenGL 1.0 に対応し、新しい関数として glXQueryExtensionsString, glXQueryServerString, glXGetClientString が導入されている。

どのバージョンの GLX が利用可能であるかを実行時に調べるには glQueryVersion を用いること。glQueryVersion はサーバとの接 続においてサポートされているバージョンを返す。つまり、1.2 が返された場 合には、サーバトクライアントの双方が GLX 1.2 をサポートしているという ことである。 GLX のバージョンをコンパイル時に調べることもできる。 GLX 1.1 の関数がサポートされていれば glx.h 内で GLX_VERSION_1_1 が定義 されており、GLX 1.2 の関数がサポートされていれば GLX_VERSION_1_2 が定 義されている。

関連項目
glIntro, glFinish, glFlush, glXChooseVisual, glXCopyContext,
glXCreateContext, glXCreateGLXPixmap, glXDestroyContext,
glXGetClientString, glXGetConfig, glXIsDirect, glXMakeCurrent,
glXQueryExtension, glXQueryExtensionsString, glXQueryServerString, glXQueryVersion, glXSwapBuffers, glXUseXFont, glXWaitGL, glXWaitX, XCreateColormap, XCreateWindow, XSync