Wayland helloworld (四)之窗口显示

匿名 (未验证) 提交于 2019-12-02 23:59:01

Wayland窗口绘制

    Wayland窗口绘制有两种:1) 共享内存方式、2)EGL。

本文使用方式1绘制窗口。


Wayland窗口:wl_surface

    Wayland窗口绘制完全由程序控制,包括标题栏绘制,边框绘制,窗口移动,改变大小等。 其中与窗口绘制有关的函数有:

wl_surface_attach() 将缓存绑定到窗口上,窗口大小会根据缓存重新计算。

wl_surface_damage() 标记窗口失效的区域

wl_surface_commit() 缓存提交请求,合成器会锁定提交的缓存,直到下一次wl_surface_attach或合成器主动释放。

wl_surface_frame() 申请帧绘制回调,每当绘制完一帧就发送wl_callback::done消息。


Walyand缓存:wl_buffer

    Wayland窗口显示的内容由wl_buffer负责。Wayland与X Server不同,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); }








转载于:https://my.oschina.net/txl/blog/266931

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!