WaylandクライアントがEGL経由で描画を行う際のサーバーとのやり取りをざっくり解説。
WaylandサーバーはWestonでgl-rendererによる描画、EGL回りはMesaを想定。
クライアントによる描画
基本的にEGLサーフェスの作成、OpenGLによる描画に関しては通常のX11アプリとあまり大きな違いはない。違いが出るのはeglSwapBuffers()からである。
eglSwapBuffers()でのクライアントとサーバの処理
DRMバッファ作成
クライアント側
EGLSurfaceからPRIMEにより共有バッファ(クライアントの描画結果が格納されている)のFDを取得して、wl_drm_create_prime_buffer()でwl_bufferを作成する。
古いドライバの場合は共有バッファのGEM名を取得し、wl_drm_create_buffer()で、wl_drm_bufferを持つwl_bufferを作成する。
(FDの方が高速に動作できる)
wl_drm_create_prime_buffer()はWaylandプロトコルでサーバへ通知される。
サーバ側
Waylandによりwl_drm_buffer作成が通知されると、wayland-drm.cのcreate_buffer()が呼び出され、サーバ側のwl_drm_bufferが作成される。
このとき~~wayland_drm_bufmgr_reference_buffer()~~dri2_wl_reference_bufferが呼び出され、
native_display.pipe_screen.resource_from_handle()(関数ポインタ。実体はGPU毎に設定される)によりクライアントから渡されたDRMのハンドルからDRMバッファ(wl_drm_buffer.driver_buffer)を取得する。
サーフェスコミット
クライアントはバッファ作成後に以下の処理を行う。
- wl_surface_attachにてバッファをアタッチ
- wl_surface_damage
- wl_surface_commit
サーバ側のアタッチ処理はコミットを受けた後gl_renderer_attach_egl()にて行われる。
ここでは、eglCreateImageKHR()とglEGLImageTargetTexture2DOES()を(関数ポインタ経由で)用いて、wl_drm_buffer.driver_bufferを直接テクスチャとして使用可能にしている。
ここまでくればあとは、テクスチャをOpenGLで描画してコンポジションするだけである。