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で描画してコンポジションするだけである。