Wayland helloworld(4)のウィンドウ表示
Waylandウィンドウの描画
Waylandウィンドウの描画には,1)共有メモリ方式,2)EGLの2種類がある.
この文書では、方法1を使用してウィンドウを描画します.
Waylandウィンドウ:wl_surface
Waylandウィンドウの描画は、タイトルバーの描画、枠線の描画、ウィンドウの移動、サイズの変更など、プログラムによって完全に制御されます.ウィンドウの描画に関連する関数は次のとおりです.
wl_surface_attach()はキャッシュをウィンドウにバインドし、ウィンドウサイズはキャッシュに基づいて再計算されます.
wl_surface_damage()タグウィンドウが無効な領域
wl_surface_commit()キャッシュコミット要求、合成器はコミットされたキャッシュを次のwl_までロックしますsurface_attachまたは合成器はアクティブに解放されます.
wl_surface_frame()はフレームペイントコールバックを申請し、1フレームペイントが完了するたびにwl_を送信するcallback::doneメッセージ.
Walyandキャッシュ:wl_buffer
Waylandウィンドウに表示される内容はwl_bufferが責任を負う.WaylandはXサーバとは異なり、Waylandはクライアントの直接描画のみをサポートし、コンポジタはwl_bufferの描画操作.とwl_bufferに関する関数は、次のとおりです.
wl_shm_create_pool()は、プログラムのメモリ領域にmmapを使用できるキャッシュプールを作成します.
wl_shm_pool_create()wlを作成するbuffer.
サンプルコード:
ウィンドウの描画:
Waylandウィンドウの描画には,1)共有メモリ方式,2)EGLの2種類がある.
この文書では、方法1を使用してウィンドウを描画します.
Waylandウィンドウ:wl_surface
Waylandウィンドウの描画は、タイトルバーの描画、枠線の描画、ウィンドウの移動、サイズの変更など、プログラムによって完全に制御されます.ウィンドウの描画に関連する関数は次のとおりです.
wl_surface_attach()はキャッシュをウィンドウにバインドし、ウィンドウサイズはキャッシュに基づいて再計算されます.
wl_surface_damage()タグウィンドウが無効な領域
wl_surface_commit()キャッシュコミット要求、合成器はコミットされたキャッシュを次のwl_までロックしますsurface_attachまたは合成器はアクティブに解放されます.
wl_surface_frame()はフレームペイントコールバックを申請し、1フレームペイントが完了するたびにwl_を送信するcallback::doneメッセージ.
Walyandキャッシュ:wl_buffer
Waylandウィンドウに表示される内容はwl_bufferが責任を負う.WaylandはXサーバとは異なり、Waylandはクライアントの直接描画のみをサポートし、コンポジタはwl_bufferの描画操作.とwl_bufferに関する関数は、次のとおりです.
wl_shm_create_pool()は、プログラムのメモリ領域にmmapを使用できるキャッシュプールを作成します.
wl_shm_pool_create()wlを作成するbuffer.
サンプルコード:
lpBuffer->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
//lpBuffer->data == MAP_FAILED
HSHMPOOL pool = wl_shm_create_pool(wlGetRegistry()->s_shm, fd, size);
lpBuffer->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_XRGB8888);
のうち、fdは一時ファイルであり、サイズはsizeであり、mmap用である.ウィンドウの描画:
void buffer_release(void *data, struct wl_buffer *buffer)
{
LPPAINTBUFFER lpBuffer = data;
lpBuffer->busy = 0;
}
static const struct wl_buffer_listener buffer_listener =
{
.release = buffer_release
};
void _wlCreatePaintStructure(int width, int height, LPPAINTBUFFER lpBuffer)
{
int stride = width * 4;
int size = stride * height;
char filename[] = "/tmp/weston-shared-XXXXXX";
int fd = mkstemp(filename);
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
unlink(filename);
ftruncate(fd, size);
lpBuffer->busy = 0;
lpBuffer->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
//lpBuffer->data == MAP_FAILED
HSHMPOOL pool = wl_shm_create_pool(wlGetRegistry()->s_shm, fd, size);
lpBuffer->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(lpBuffer->buffer, &buffer_listener, lpBuffer);
wl_shm_pool_destroy(pool);
close(fd);
}
void wlBeginPaint(HSURFACE surface, LPPAINTSTRUCTURE lpPaint)
{
LPSURFACEPRIVATE _priv = _wlGetSurfacePrivate(surface);
if (!_priv->buffer[0].busy && _priv->buffer[0].buffer)
{
lpPaint->buffer = &_priv->buffer[0];
}
else if (!_priv->buffer[1].busy && _priv->buffer[1].buffer)
{
lpPaint->buffer = &_priv->buffer[1];
}
else
{
SIZE sz = wlGetSurfaceSize(surface);
_wlCreatePaintStructure(sz.width, sz.height, &_priv->buffer[0]);
lpPaint->buffer = &_priv->buffer[0];
}
}
void wlEndPaint(HSURFACE surface, LPPAINTSTRUCTURE lpPaint)
{
lpPaint->buffer->busy = 1;
wl_surface_attach(surface, lpPaint->buffer->buffer, 0, 0);
SIZE sz = wlGetSurfaceSize(surface);
wl_surface_damage(surface, 0, 0, sz.width, sz.height);
wl_surface_commit(surface);
}
void frame_listener_done(void *data, HCALLBACK callback, uint32_t time)
{
HSURFACE surface = (HSURFACE)data;
/* */
_wlSetFrameListener(surface);
/* */
_wlDrawFrame(surface, time);
}
static struct wl_callback_listener frame_listener = { frame_listener_done };
void _wlSetFrameListener(HSURFACE surface)
{
static struct wl_callback_listener frame_listener;
frame_listener.done = frame_listener_done;
HCALLBACK callback = wl_surface_frame(surface);
wl_callback_add_listener(callback, &frame_listener, surface);
}
void _wlDrawFrame(HSURFACE surface, uint32_t time)
{
PAINTSTRUCTURE ps;
memset(&ps, 0, sizeof(ps));
wlBeginPaint(surface, &ps);
wlCallPaintProc(surface, &ps, time);
wlEndPaint(surface, &ps);
}
void wlSetPaintProc(HSURFACE surface, REPAINTPROC surfaceproc)
{
_wlGetSurfacePrivate(surface)->surfaceproc = surfaceproc;
_wlSetFrameListener(surface);
_wlDrawFrame(surface, 0);
}