GLwDrawingArea(3) OpenGL 用の描画ウィジェット

Other Alias

GLwMDrawingArea

書式

#include <X11/GLw/GLwDrawA.h>
ld ... -lGLw -lGL -l<任意のウィジェットライブラリ> -lXext -lXt -lX11 -lm

#include <X11/GLw/GLwMDrawA.h>
ld ... -lGLw -lGL -lXm -lXext -lXt -lX11 -lm

説明

GLwDrawingArea および GLwMDrawingArea は OpenGL の描画に使 えるウィジェットである。これらのウィジェットは、指定されたパラメータに 基づいて、OpenGL で必要となる適切なビジュアルとカラーマップを持つ ウィンドウを与える。 また、GLwDrawingArea と GLwMDrawingArea は再描画・リサイズ・入力・ 初期化のためのコールバックも与える。

GLwDrawingArea はいかなるウィジェットセットの一部でもないが、Xt だけに は依存する。 GLwDrawingArea はどんなウィジェットセットと組み合わせても使える。 GLwMDrawingArea は GLwDrawingArea とほぼ同じであるが、MotifTm のウィジェットクラスである XmPrimitive のサブクラスであり、デフォルト 状態が Motif に適したようになっている。例えば、GLwMDrawingArea は Motif のデフォルトの前景色と背景色をリソースに持ち、キーボードの移動も よりうまく扱える。 GLwDrawingArea を Motif のプログラムで使えるが、GLwMDrawingArea を使う 方が推奨される。

GLwDrawingArea と GLwMDrawingArea はほとんど同じ動作なので、この オンラインマニュアルの残りの部分では、動作が異なる部分を除いて GLwDrawingArea だけを説明する。明示的に述べない限り、GLwDrawingArea に 関する全ての説明は GLwMDrawingArea にも当てはまる。

GLwDrawingArea を生成する時に与える情報の中でも、特に重要なのは ビジュアルを決めるために必要な情報である。 これを与える方法は 3 つあり、そのいずれもリソース経由で行われる。 特定の visualInfo 構造体を渡すこともできる。 (この visualInfo は既に別のところで取得していなければならない。 アプリケーションが行う OpenGL の描画とこの visualInfo の互換性を保証す るのはアプリケーション設計者の責任である)。 別の方法として、属性リストを与えることもできる。この属性リストは、 直接 OpenGL プログラミングを行う場合に使われるものと全く同じ書式である。 最後に、それぞれの属性を個別のリソースとして指定することもできる。 最後の方法が最も単純であり、リソースファイルから操作できる唯一の方法であ る。

ビジュアルの割り当て以外にも、GLwDrawingArea は アプリケーションに割り当てられなければカラーマップの割り当ても行う (カラーマップが割り当てられる場合、カラーマップとビジュアルの互換性を 保証するのはアプリケーション設計者の責任である。) アプリケーションが同じビジュアルから複数個の GLwDrawingAreas を生成す る場合、同じカラーマップが使われる(ただし異なるアプリケーション間では カラーマップは共有されない)。

ウィジェットを生成しても、ウィジェットがリアライズされるまではウィンドウ は生成されない。したがってアプリケーションはウィンドウに対する OpenGL の操作をウィジェットの生成直後に行ってはならない。 アプリケーションはウィンドウがリアライズされるのを待たなければならない。 そこでこれに代わる方法として、ウィンドウが生成されたことを示す ginit コールバック を使ってもよい。このコールバックを受け取れば、アプリケーションは そのウィンドウに対して全ての OpenGL 初期化処理を行い、それからその他の 操作を行うことができる。初期化については後で詳しく説明する。

アプリケーションは glXMakeCurrent または簡易関数 GLwDrawingAreaMakeCurrent を使って、アクセスする GLwDrawingArea を選択する。 GLwDrawingAreaMakeCurrent はディスプレイとウィンドウの代わりに ウィジェットを引き数に取る。 これらの関数は、GLwDrawingArea が一つしかなければ一度だけ呼べばよいが、 複数の GLwDrawingArea がある場合は、それぞれのコールバックの先頭で呼ば なければならない。 ここで言うコールバックには、ウィジェット自身が与えるコールバックだけで なく、GL の動作に影響を与える全てのコールバック(タイムアウトや作業手続き等) も含まれる。

アプリケーションがダブルバッファリングを使っている場合は、 glXSwapBuffers ではなく GLwDrawingAreaSwapBuffers を呼ぶとよい。 この関数を使うとディスプレイとウィンドウの代わりにウィジェットを指定す ることができる。

GLwDrawingArea クラス

GLwDrawingArea は Core クラスから動作とリソースを継承する。
クラスポインタは glwDrawingAreaWidgetClass である。
クラス名は GLwDrawingArea である。

GLwMDrawingArea クラス

GLwMDrawingArea は XmPrimitive クラスと Core クラスから 動作とリソースを継承する。
クラスポインタは glwMDrawingAreaWidgetClass である。
クラス名は GLwMDrawingArea である。

新しいリソース

以下の表はプログラマがデータを指定するために使うウィジェットリソースを 定義する。プログラマは継承されたクラスに対してリソース値を設定して、 そのウィジェットの属性を設定してもよい。.Xdefaults ファイル内で リソースを名前またはクラスで参照するには、プレフィックス GLwN お よび GLwC を取り、残った文字列を使うこと。 以下では 2 つの表を示す。最初の表には glXChooseVisual が直接使う 属性に対応するリソースが示されている。 glXChooseVisual の場合と同様、全ての Boolean 型のリソースの デフォルト値は FALSE であり、全ての整数型リソースのデフォルト値は 0 で ある。ただし redSize, greenSize, blueSize は例外で、これらのデフォルト 値は 1 である。これらのリソースは生成時にのみ設定され、ビジュアルを 生成する時に使われる。 GLwNattribList リソースまたは GLwNvisualInfo リソースが 設定されている場合は、これらのリソースは無視される。 これらのリソースの固有の意味は glXChooseVisual の オンラインマニュアルで説明されているので、ここでは説明しない。

名前クラスOpenGL 属性
GLwNbufferSizeGLwCBufferSizeintGLX_BUFFER_SIZE
GLwNlevelGLwCLevelintGLX_LEVEL
GLwNrgbaGLwCRgbaBooleanGLX_RGBA
GLwNdoublebufferGLwCDoublebufferBooleanGLX_DOUBLEBUFFER
GLwNstereoGLwCStereoBooleanGLX_STEREO
GLwNauxBuffersGLwCAuxBuffersBooleanGLX_AUX_BUFFERS
GLwNredSizeGLwCColorSizeintGLX_RED_SIZE
GLwNgreenSizeGLwCColorSizeintGLX_GREEN_SIZE
GLwNblueSizeGLwCColorSizeintGLX_BLUE_SIZE
GLwNalphaSizeGLwCAlphaSizeintGLX_ALPHA_SIZE
GLwNdepthSizeGLwCDepthSizeintGLX_DEPTH_SIZE
GLwNstencilSizeGLwCStencilSizeintGLX_STENCIL_SIZE
GLwNaccumRedSizeGLwCAccumColorSizeintGLX_ACCUM_RED_SIZE
GLwNaccumGreenSizeGLwCAccumColorSizeintGLX_ACCUM_GREEN_SIZE
GLwNaccumBlueSizeGLwCAccumColorSizeintGLX_ACCUM_BLUE_SIZE
GLwNaccumAlphaSizeGLwCAccumAlphaSizeintGLX_ACCUM_ALPHA_SIZE

以下の表は GLwDrawingArea ウィジェットのその他のリソースを列挙したもの である。それぞれについての詳しい説明は後で述べる。 「アクセス」カラムのコードの意味は以下の通りである: 指定されたリソースが生成時に設定される(C)、 XtSetValues を使って設定される(S)、 XtGetValues を使って取得される(G)、 適用されない(N/A)。

名前クラス初期値アクセス

GLwNallocateBackgroundGLwCAllocateColorsBooleanFCG
GLwNallocateOtherColorsGLwCAllocateColorsBooleanFCG
GLwNattribListGLwCAttribListint *NULLCG
GLwNexposeCallbackGLwCCallbackXtCallbackListNULLC
GLwNginitCallbackGLwCCallbackXtCallbackListNULLC
GLwNinputCallbackGLwCCallbackXtCallbackListNULLC
GLwNinstallBackgroundGLwCInstallBackgroundBooleanTCG
GLwNinstallColormapGLwCInstallColormapBooleanTCG
GLwNresizeCallbackGLwCCallbackXtCallbackListNULLC
GLwNvisualInfoGLwCVisualInfoXVisualInfo*NULLCG

GLwNallocateBackground
TRUE の場合、(そうすることが適切であれば)新しく計算されたカラーマップ とビジュアルを用いて背景ピクセルとピックスマップが割り当てられる。 FALSE の場合、親のカラーマップとビジュアルを使って計算された値がそのま ま保持される。 X に背景をクリアさせたいアプリケーションでは、普通はこの値を TRUE にする。 背景を自分でクリアするアプリケーションではこの値を FALSE にすることが 多いが、自分で使うために背景色を問い合わせる場合にはこの値を TRUE に してもよい。 また、カラーマップを一つしかサポートしていないハードウェアでは、 OpenGL のカラーマップとデフォルトの X のカラーマップの行き来で画面の 色が乱れるのを避けるために、アプリケーションは色をよく注意して割り当てる必 要があるかもしれない。 (注意: Xt の動作の仕方のため、背景色は最初はデフォルトのカラーマップ を使って計算される。このリソースが設定されていると、背景色は正しく 再計算できる。カラーマップが動的に計算されるのではなく、明示的に ウィジェットに与えられた場合、これらのリソースは常にそのカラーマップを 使って計算される。)
GLwNallocateOtherColors
これは GLwNallocateBackground に似ているが、 通常はウィジェットによって割り当てられる、その他の色を割り当てる。 GLwDrawingArea ウィジェットおよび GLwMDrawingArea ウィジェットはこれら の色を使わないが、アプリケーションは問い合わせることを選んでもよい。 非 Motif の GLwDrawingArea ウィジェットの場合は、割り当てられる色が他に ないので、このリソースは何もしない。Motif の GLwMDrawingArea の場合は、 XmPrimitive resources XmNforeground, XmNhighlightColor, XmNhighlightPixmap が計算される。
GLwNattribList
glXChooseVisual を呼ぶのに必要な属性のリストを持つ。 このリソースが NULL の場合、これは属性関連リソースに基づいて計算される。 NULL でない場合は、属性関連リソースは無視される。
GLwNexposeCallback
ウィジェットが露出イベントを受け取った時に呼び出されるコールバックの リストを指定する。 コールバックの理由は GLwCR_EXPOSE となる。 コールバック構造体も露出イベントを持っている。 アプリケーションは一般的には画面の再描画を行うとよい。
GLwNginitCallback
ウィジェットが最初にリアライズされた時に呼ばれるコールバックを指定する。 ウィジェットがリアライズされるまではどのような OpenGL の操作も実行でき ないので、このコールバックは OpenGL の適切な初期化を行うために使える (コンテクストの生成など)。
GLwNinputCallback
ウィジェットがキーボードイベントまたはマウスイベントを受け取った時に 呼び出されるコールバックを指定する。デフォルトでは、入力コールバックは キーの押したり離したりしたとき、マウスのボタンを押したり離したりしたと き、ボタンを押しながらマウスを動かした時に毎回呼び出される。 ただし、この動作はトランスレーションテーブルを変えることにより変更できる。 このコールバック構造体は入力イベントも持つ。 このコールバックの理由は GLwCR_INPUT となる。
入力コールバックはプログラミングを楽にするために与えられている。 というのも、これは全ての入力イベントを簡単に捕捉する方法を与えるからで ある。しかし、モジュール化が進んだプログラムは、全てのコールバックを 個々に捕捉するのではなく、専用のアクションとトランスレーションを アプリケーションで与えることにより実現できることが多い。 明示的にトランスレーションを指定することにより、さらにカスタマイズする ことができる。
GLwNinstallBackground
TRUE が設定されている場合、背景色がウィンドウにインストールされる。 FALSE が設定されている場合、ウィンドウは背景色を持たない。 このリソースは GLwNallocateBackground も TRUE でなければ効果がない。
GLwNinstallColormap
TRUE が設定されている場合、このウィンドウのシェルがフォーカスを得た時 に、ウィジェットは XSetWMColormapWindows を呼び出して ウィンドウマネージャにカラーマップをインストールするように指示する。 複数の GLwDrawingAreas で一つのカラーマップを共有しているアプリケーション の場合、各々のカラーマップに対してただ一つだけの GLwDrawingArea に このリソースに TRUE を設定するのが最も効率的である。 アプリケーションがカラーマップの順序についてさらに制御を必要とする場合 は、このリソースには FALSE を指定し、アプリケーションが明示的に XSetWMColormapWindows を呼び出すとよい。
GLwNresizeCallback
GLwDrawingArea がリアライズされた時に呼び出されるコールバックのリスト を指定する。 コールバックの理由は GLwCR_RESIZE となる。
GLwNvisualInfo
ウィンドウのビジュアル情報構造体へのポインタを持つ。 この値が NULL の場合、visualInfo 構造体はウィジェットの生成時に GLwNattributeList リソース(このリソース自身はさまざまなリソース から計算される)に基づいて計算される。 GLwNvisualInfo が NULL でなければ、GLwNattributList と 属性関連リソースは無視される。

継承されるリソース

GLwDrawingArea と GLwMDrawingArea のいずれも、コアのスーパークラスから 動作とリソースを継承する。 前に述べたカラーマップと背景色リソースの動作を除き、全てのデフォルト値 はコアのものと同じである。

これに加えて、Motif 版の GLwMDrawingArea は XmPrimitive も継承している。 色リソースの動作については既に説明した。 このウィジェットでは TraversalOn リソースは無効にされているが、 キーボード入力が必要なら有効にすべきである(また、アプリケーションは ウィジェット内でマウスのボタン 1 が押される度に XmProcessTraversal(widget, XmTRAVERSE_CURRENT) を呼ぶべきである。これは Motif の描画領域で必要なことと同様である)。 Motif は一つのトップレベルシェルが複数個のビジュアルを持つと混乱するの で、XmNhighlightOnEnter は無効にされており、 XmNhighlightThickness には 0 が設定されている。

コールバック情報

以下の構造体を指すポインタが各々のコールバックに渡される:


typedef struct
{
   int        reason;
   XEvent    *event;
   Dimension  width, height;
} GLwDrawingAreaCallbackStruct;

reason
コールバックが呼び出された理由を示す。 ここに入る値は、前述のリソースの説明で述べられている。 Motif プログラマの場合 GLwCR_EXPOSE, GLwCR_RESIZE, GLwCR_INPUT は順に XmCR_EXPOSE, XmCR_RESIZE, XmCR_INPUT と同等である。GLwCR_GINIT に相当するものは Motif には存在しない。
event
コールバックを起こした XEvent を指すポインタである。 GLwNginitCallbackGLwNresizeCallback の場合は NULL となる。
width および height
ウィンドウの幅と高さが設定される。

トランスレーション

GLwDrawingArea は以下のトランスレーションを持つ:
<KeyDown>:     glwInput()
<KeyUp>:       glwInput()
<BtnDown>:     glwInput()
<BtnUp>:       glwInput()
<BtnMotion>:   glwInput()

GLwMDrawingArea はさらに以下のトランスレーションを持つ:

<Key>osfHelp:  PrimitiveHelp()

アプリケーションでデフォルト値以外のイベントを受け取りたければ、 別のトランスレーションテーブルをインストールすることで実現できる。

アクションルーチン

GLwDrawingArea は以下のアクションルーチンを持つ:
glwInput():
前述のトランスレーションのいずれかが入力が起きたことを示した場合に呼び 出される。 このアクションルーチンの唯一の目的は入力コールバックの呼び出しである。

初期化

ウィジェットが最初に生成された時(例えば XtCreateWidget(3X) を使用)、 ウィジェットに対応するウィンドウは自動的には生成されない。 実際にはウィンドウの生成はウィジェットがリアライズするまで待たされる。 しかし、glXchooseVisual はすぐに呼ばれるので、その結果を元にした 情報は利用できる。

ウィジェット生成とリアライズの間は以下のようになる:

  • ウィンドウに対する OpenGL の操作はできない。
  • resize コールバックは生成されない。
  • 通常のウィンドウは利用できない(XtWindow は NULL を返す)。
  • GLwDrawingAreaMakeCurrent (および glXMakeCurrent) を呼んで はならない。

ウィジェットがリアライズすると、以下の動作が起きる:

  • ウィンドウが生成される。
  • ginit コールバックが呼ばれる。 ユーザはこのコールバックを使って、必要な OpenGL の初期化をウィンドウに 対して行うとよい。

注意

入力コールバックを使ってキーボード入力を受け取る場合、イベント内の キーコードを KeySym に変換しなければならない。 変換には XLookupKeysym(3X) または XLookupString(3X) を使う こと。 キーボード入力はトランスレーションでも扱える。こちらの場合には変換は 不要である。

Motif プログラマは、OSF がキーの仮想割り当てを使っていて、いくつかの キー割り当てを置き換えていることを意識しておくべきである。 一般的な例としては、(GL プログラムでよくするように)ESC キーを使って プログラムを終了させる場合には、トランスレーションには <key>Escape で なく <key>osfCancel を指定すべきである。

Motif プログラマは、Motif スタイルの GLwCreateMDrawingArea を使っ て GLwMDrawingArea を生成してもよい。

使用例

GLwDrawingArea ウィジェットを生成し、適切なコールバックを割り当てる コードを一部抜粋して示す。


   #include <stdlib.h>
   #include <X11/GLw/GLwDrawA.h>
   static GLXContext glx_context;  
   . . .
   main()
   {
       Arg args[10];
       int n;
       Widget parent;    
       Widget glw;       
       . . .
       
       n = 0;
       XtSetArg(args[n], GLwNrgba, True); n++;
       glw = XtCreateManagedWidget("glw", glwDrawingAreaWidgetClass,
                                   parent, args, n);
       XtAddCallback(glw, GLwNexposeCallback, exposeCB, NULL);
       XtAddCallback(glw, GLwNresizeCallback, resizeCB, NULL);
       XtAddCallback(glw, GLwNginitCallback, ginitCB, NULL);
       
       . . .
   }
   static void
   exposeCB(Widget w, XtPointer client_data,
            GLwDrawingAreaCallbackStruct *call_data)
   {
       GLwDrawingAreaMakeCurrent(w, glx_context);
       
   }
   static void
   resizeCB(Widget w, XtPointer client_data,
            GLwDrawingAreaCallbackStruct *call_data)
   {
       GLwDrawingAreaMakeCurrent(w, glx_context);
       
   }
   static void
   ginitCB(Widget w, XtPointer client_data,
           GLwDrawingAreaCallbackStruct *call_data)
   {
       Arg args[1];
       XVisualInfo *vi;
       XtSetArg(args[0], GLwNvisualInfo, &vi);
       XtGetValues(w, args, 1);
       
       glx_context = glXCreateContext(XtDisplay(w), vi,
                                      NULL, GL_FALSE);
       GLwDrawingAreaMakeCurrent(w, glx_context);
       
   }

Motif プログラムで必要となる相違点は、 GLwDrawingArea.h ではなく GLwMDrawingArea.h を使い、 GLwDrawingAreaWidgetClass 型でなく GLwMDrawingAreaWidgetClass 型の ウィジェットを生成することだけである。 これらを行う代わりに、Motif プログラムでは GLwCreateMDraw(3X) を 使ってもよい。

警告

GLwDrawingArea が既にリアライズされているウィジェットの子として生成さ れた場合、GLwDrawingArea は即座に生成され、ユーザには ginit を 追加する機会が与えられない。このような場合には、初期化にはコールバック を使わず、ウィジェット生成の直後に行うべきである。

非 Motif の GLwDrawingArea ウィジェットを Motif プログラムで使い、さら にキーボードの遷移も行う場合には、ユーザが GLwDrawingArea へ遷移した場 合の動作は未定義である。