display: weston: client: screenshoot

总体三部分:

client: screenshot.c

server: screenshooter.c + gl-renderer.c + weston-screenshooter.c

client很简单,总共三百行代码,标准注册流程的代码就不拿出来了。

int main(int argc, char *argv[])
{
	wl_list_init(&sh_data.output_list);
    //创建一个outputlist。管理多个output
...
	wl_registry_add_listener(registry, &registry_listener, &sh_data);
	wl_display_dispatch(display);
	wl_display_roundtrip(display);
    //注意这里注册上监听的第一次动作要完成一次roundtrip
...
	weston_screenshooter_add_listener(sh_data.screenshooter,
					  &screenshooter_listener,
					  &sh_data);
    //这个listener主要是保证截屏完成,server发过来一个done事件。
	if (screenshot_set_buffer_size(&buff_size, &sh_data.output_list))
		return -1;
    //根据之前的output算出需要的shmbuffer的大小。

	wl_list_for_each(output, &sh_data.output_list, link) {
		output->buffer =
			screenshot_create_shm_buffer(output->width,
						     output->height,
						     &output->data,
						     sh_data.shm);
        //创建buffer,与server完成共享。
		weston_screenshooter_take_shot(sh_data.screenshooter,
					       output->output,
					       output->buffer);
        //和server交互的操作。在weston-screenshooter.c里面。
		sh_data.buffer_copy_done = 0;
		while (!sh_data.buffer_copy_done)
			wl_display_roundtrip(display);
        //如果没接收到done。就一直转圈圈等。
	}

	screenshot_write_png(&buff_size, &sh_data.output_list);
}


static void
handle_global(void *data, struct wl_registry *registry,
	      uint32_t name, const char *interface, uint32_t version)
{
	static struct screenshooter_output *output;
	struct screenshooter_data *sh_data = data;

	if (strcmp(interface, "wl_output") == 0) {
		output = xmalloc(sizeof *output);
		output->output = wl_registry_bind(registry, name,
						  &wl_output_interface, 1);
		wl_list_insert(&sh_data->output_list, &output->link);
		wl_output_add_listener(output->output, &output_listener, output);
	} else if (strcmp(interface, "wl_shm") == 0) {
		sh_data->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
	} else if (strcmp(interface, "weston_screenshooter") == 0) {
		sh_data->screenshooter = wl_registry_bind(registry, name,
							  &weston_screenshooter_interface,
							  1);
	}
}
handle里面绑了shm,output和screenshooter三个必要的服务。
screeenshot.c里面的 weston_screenshooter_take_shot对应的是weston-screenshooter.c里面的如下部分:

static void
screenshooter_take_shot(struct wl_client *client,
			struct wl_resource *resource,
			struct wl_resource *output_resource,
			struct wl_resource *buffer_resource)
{
	struct weston_output *output =
		weston_head_from_resource(output_resource)->output;
	struct weston_buffer *buffer =
		weston_buffer_from_resource(buffer_resource);

	if (buffer == NULL) {
		wl_resource_post_no_memory(resource);
		return;
	}

	weston_screenshooter_shoot(output, buffer, screenshooter_done, resource);
}

struct weston_screenshooter_interface screenshooter_implementation = {
	screenshooter_take_shot
};

weston_screenshooter_shoot里面主要如下:
	l->buffer = buffer;
	l->output = output;
	l->done = done;
	l->data = data;
	l->listener.notify = screenshooter_frame_notify;
	wl_signal_add(&output->frame_signal, &l->listener);
	weston_output_disable_planes_incr(output);
	weston_output_schedule_repaint(output);

先讲一下和这个weston_output_disable_planes_incr和weston_output_disable_planes_decr
这俩函数是用来保证protected surface的。也就是hdcp相关的功能。可以具体看注释,代码。


最重要就是绑定这个screenshooter_frame_notify
出发是在repaint-output的swapbuffer之前,最重要的就是:
	compositor->renderer->read_pixels(output,
			     compositor->read_format, pixels,
			     0, 0, output->current_mode->width,
			     output->current_mode->height);


对应的实现:
	if (use_output(output) < 0)
		return -1;

	glPixelStorei(GL_PACK_ALIGNMENT, 1);
	glReadPixels(x, y, width, height, gl_format,
		     GL_UNSIGNED_BYTE, pixels);

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值