mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	Add x11 backend for compositor
This still needs all the bells and whistles from the egl-kms mesa branch, but it makes it a lot easier to work on wayland.
This commit is contained in:
		
							parent
							
								
									fc783d4071
								
							
						
					
					
						commit
						ce5325d3ed
					
				
					 7 changed files with 901 additions and 184 deletions
				
			
		
							
								
								
									
										1
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
					@ -28,6 +28,7 @@ $(libs) :
 | 
				
			||||||
compositor :					\
 | 
					compositor :					\
 | 
				
			||||||
	compositor.o				\
 | 
						compositor.o				\
 | 
				
			||||||
	compositor-drm.o			\
 | 
						compositor-drm.o			\
 | 
				
			||||||
 | 
						compositor-x11.o			\
 | 
				
			||||||
	screenshooter.o				\
 | 
						screenshooter.o				\
 | 
				
			||||||
	cairo-util.o
 | 
						cairo-util.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										260
									
								
								compositor-drm.c
									
										
									
									
									
								
							
							
						
						
									
										260
									
								
								compositor-drm.c
									
										
									
									
									
								
							| 
						 | 
					@ -37,8 +37,43 @@
 | 
				
			||||||
#include "wayland-protocol.h"
 | 
					#include "wayland-protocol.h"
 | 
				
			||||||
#include "compositor.h"
 | 
					#include "compositor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct drm_compositor {
 | 
				
			||||||
 | 
						struct wlsc_compositor base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct udev *udev;
 | 
				
			||||||
 | 
						struct wl_event_source *drm_source;
 | 
				
			||||||
 | 
						int drm_fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_event_source *term_signal_source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* tty handling state */
 | 
				
			||||||
 | 
						int tty_fd;
 | 
				
			||||||
 | 
						uint32_t vt_active : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct termios terminal_attributes;
 | 
				
			||||||
 | 
						struct wl_event_source *tty_input_source;
 | 
				
			||||||
 | 
						struct wl_event_source *enter_vt_source;
 | 
				
			||||||
 | 
						struct wl_event_source *leave_vt_source;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct drm_output {
 | 
				
			||||||
 | 
						struct wlsc_output   base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drmModeModeInfo mode;
 | 
				
			||||||
 | 
						uint32_t crtc_id;
 | 
				
			||||||
 | 
						uint32_t connector_id;
 | 
				
			||||||
 | 
						GLuint rbo[2];
 | 
				
			||||||
 | 
						uint32_t fb_id[2];
 | 
				
			||||||
 | 
						EGLImageKHR image[2];
 | 
				
			||||||
 | 
						uint32_t current;	
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct drm_input {
 | 
				
			||||||
 | 
						struct wlsc_input_device base;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct evdev_input_device {
 | 
					struct evdev_input_device {
 | 
				
			||||||
	struct wlsc_input_device *device;
 | 
						struct drm_input *master;
 | 
				
			||||||
	struct wl_event_source *source;
 | 
						struct wl_event_source *source;
 | 
				
			||||||
	int tool, new_x, new_y;
 | 
						int tool, new_x, new_y;
 | 
				
			||||||
	int base_x, base_y;
 | 
						int base_x, base_y;
 | 
				
			||||||
| 
						 | 
					@ -47,16 +82,21 @@ struct evdev_input_device {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void evdev_input_device_data(int fd, uint32_t mask, void *data)
 | 
					static void evdev_input_device_data(int fd, uint32_t mask, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct drm_compositor *c;
 | 
				
			||||||
	struct evdev_input_device *device = data;
 | 
						struct evdev_input_device *device = data;
 | 
				
			||||||
	struct input_event ev[8], *e, *end;
 | 
						struct input_event ev[8], *e, *end;
 | 
				
			||||||
	int len, value, dx, dy, absolute_event;
 | 
						int len, value, dx, dy, absolute_event;
 | 
				
			||||||
	int x, y;
 | 
						int x, y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c = (struct drm_compositor *) device->master->base.ec;
 | 
				
			||||||
 | 
						if (!c->vt_active)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dx = 0;
 | 
						dx = 0;
 | 
				
			||||||
	dy = 0;
 | 
						dy = 0;
 | 
				
			||||||
	absolute_event = 0;
 | 
						absolute_event = 0;
 | 
				
			||||||
	x = device->device->x;
 | 
						x = device->master->base.x;
 | 
				
			||||||
	y = device->device->y;
 | 
						y = device->master->base.y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	len = read(fd, &ev, sizeof ev);
 | 
						len = read(fd, &ev, sizeof ev);
 | 
				
			||||||
	if (len < 0 || len % sizeof e[0] != 0) {
 | 
						if (len < 0 || len % sizeof e[0] != 0) {
 | 
				
			||||||
| 
						 | 
					@ -132,24 +172,26 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data)
 | 
				
			||||||
			case BTN_FORWARD:
 | 
								case BTN_FORWARD:
 | 
				
			||||||
			case BTN_BACK:
 | 
								case BTN_BACK:
 | 
				
			||||||
			case BTN_TASK:
 | 
								case BTN_TASK:
 | 
				
			||||||
				notify_button(device->device, e->code, value);
 | 
									notify_button(&device->master->base,
 | 
				
			||||||
 | 
										      e->code, value);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				notify_key(device->device, e->code, value);
 | 
									notify_key(&device->master->base,
 | 
				
			||||||
 | 
										   e->code, value);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dx != 0 || dy != 0)
 | 
						if (dx != 0 || dy != 0)
 | 
				
			||||||
		notify_motion(device->device, x + dx, y + dy);
 | 
							notify_motion(&device->master->base, x + dx, y + dy);
 | 
				
			||||||
	if (absolute_event && device->tool)
 | 
						if (absolute_event && device->tool)
 | 
				
			||||||
		notify_motion(device->device, x, y);
 | 
							notify_motion(&device->master->base, x, y);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct evdev_input_device *
 | 
					static struct evdev_input_device *
 | 
				
			||||||
evdev_input_device_create(struct wlsc_input_device *master,
 | 
					evdev_input_device_create(struct drm_input *master,
 | 
				
			||||||
			  struct wl_display *display, const char *path)
 | 
								  struct wl_display *display, const char *path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct evdev_input_device *device;
 | 
						struct evdev_input_device *device;
 | 
				
			||||||
| 
						 | 
					@ -162,7 +204,7 @@ evdev_input_device_create(struct wlsc_input_device *master,
 | 
				
			||||||
	device->tool = 1;
 | 
						device->tool = 1;
 | 
				
			||||||
	device->new_x = 1;
 | 
						device->new_x = 1;
 | 
				
			||||||
	device->new_y = 1;
 | 
						device->new_y = 1;
 | 
				
			||||||
	device->device = master;
 | 
						device->master = master;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device->fd = open(path, O_RDONLY);
 | 
						device->fd = open(path, O_RDONLY);
 | 
				
			||||||
	if (device->fd < 0) {
 | 
						if (device->fd < 0) {
 | 
				
			||||||
| 
						 | 
					@ -184,13 +226,52 @@ evdev_input_device_create(struct wlsc_input_device *master,
 | 
				
			||||||
	return device;
 | 
						return device;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					static void
 | 
				
			||||||
wlsc_compositor_present_drm(struct wlsc_compositor *ec)
 | 
					drm_input_create(struct drm_compositor *c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_output *output;
 | 
						struct drm_input *input;
 | 
				
			||||||
 | 
						struct udev_enumerate *e;
 | 
				
			||||||
 | 
					        struct udev_list_entry *entry;
 | 
				
			||||||
 | 
						struct udev_device *device;
 | 
				
			||||||
 | 
						const char *path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_for_each(output, &ec->output_list, link) {
 | 
						input = malloc(sizeof *input);
 | 
				
			||||||
		drmModePageFlip(ec->drm_fd, output->crtc_id,
 | 
						if (input == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(input, 0, sizeof *input);
 | 
				
			||||||
 | 
						wlsc_input_device_init(&input->base, &c->base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e = udev_enumerate_new(c->udev);
 | 
				
			||||||
 | 
						udev_enumerate_add_match_subsystem(e, "input");
 | 
				
			||||||
 | 
						udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
 | 
				
			||||||
 | 
					        udev_enumerate_scan_devices(e);
 | 
				
			||||||
 | 
					        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
 | 
				
			||||||
 | 
							path = udev_list_entry_get_name(entry);
 | 
				
			||||||
 | 
							device = udev_device_new_from_syspath(c->udev, path);
 | 
				
			||||||
 | 
							evdev_input_device_create(input, c->base.wl_display,
 | 
				
			||||||
 | 
										  udev_device_get_devnode(device));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					        udev_enumerate_unref(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->base.input_device = &input->base;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					drm_compositor_present(struct wlsc_compositor *ec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct drm_compositor *c = (struct drm_compositor *) ec;
 | 
				
			||||||
 | 
						struct drm_output *output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_for_each(output, &ec->output_list, base.link) {
 | 
				
			||||||
 | 
							output->current ^= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							glFramebufferRenderbuffer(GL_FRAMEBUFFER,
 | 
				
			||||||
 | 
										  GL_COLOR_ATTACHMENT0,
 | 
				
			||||||
 | 
										  GL_RENDERBUFFER,
 | 
				
			||||||
 | 
										  output->rbo[output->current]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							drmModePageFlip(c->drm_fd, output->crtc_id,
 | 
				
			||||||
				output->fb_id[output->current ^ 1],
 | 
									output->fb_id[output->current ^ 1],
 | 
				
			||||||
				DRM_MODE_PAGE_FLIP_EVENT, output);
 | 
									DRM_MODE_PAGE_FLIP_EVENT, output);
 | 
				
			||||||
	}	
 | 
						}	
 | 
				
			||||||
| 
						 | 
					@ -220,9 +301,8 @@ on_drm_input(int fd, uint32_t mask, void *data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
init_egl(struct wlsc_compositor *ec, struct udev_device *device)
 | 
					init_egl(struct drm_compositor *ec, struct udev_device *device)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wl_event_loop *loop;
 | 
					 | 
				
			||||||
	EGLint major, minor, count;
 | 
						EGLint major, minor, count;
 | 
				
			||||||
	EGLConfig config;
 | 
						EGLConfig config;
 | 
				
			||||||
	PFNEGLGETTYPEDDISPLAYMESA get_typed_display_mesa;
 | 
						PFNEGLGETTYPEDDISPLAYMESA get_typed_display_mesa;
 | 
				
			||||||
| 
						 | 
					@ -241,8 +321,8 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ec->base.device = strdup(udev_device_get_devnode(device));
 | 
						ec->base.base.device = strdup(udev_device_get_devnode(device));
 | 
				
			||||||
	ec->drm_fd = open(ec->base.device, O_RDWR);
 | 
						ec->drm_fd = open(ec->base.base.device, O_RDWR);
 | 
				
			||||||
	if (ec->drm_fd < 0) {
 | 
						if (ec->drm_fd < 0) {
 | 
				
			||||||
		/* Probably permissions error */
 | 
							/* Probably permissions error */
 | 
				
			||||||
		fprintf(stderr, "couldn't open %s, skipping\n",
 | 
							fprintf(stderr, "couldn't open %s, skipping\n",
 | 
				
			||||||
| 
						 | 
					@ -250,41 +330,39 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ec->display = get_typed_display_mesa(EGL_DRM_DISPLAY_TYPE_MESA,
 | 
						ec->base.display = get_typed_display_mesa(EGL_DRM_DISPLAY_TYPE_MESA,
 | 
				
			||||||
						  (void *) ec->drm_fd);
 | 
											  (void *) ec->drm_fd);
 | 
				
			||||||
	if (ec->display == NULL) {
 | 
						if (ec->base.display == NULL) {
 | 
				
			||||||
		fprintf(stderr, "failed to create display\n");
 | 
							fprintf(stderr, "failed to create display\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!eglInitialize(ec->display, &major, &minor)) {
 | 
						if (!eglInitialize(ec->base.display, &major, &minor)) {
 | 
				
			||||||
		fprintf(stderr, "failed to initialize display\n");
 | 
							fprintf(stderr, "failed to initialize display\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!eglChooseConfig(ec->display, config_attribs, &config, 1, &count) ||
 | 
						if (!eglChooseConfig(ec->base.display,
 | 
				
			||||||
 | 
								     config_attribs, &config, 1, &count) ||
 | 
				
			||||||
	    count == 0) {
 | 
						    count == 0) {
 | 
				
			||||||
		fprintf(stderr, "eglChooseConfig() failed\n");
 | 
							fprintf(stderr, "eglChooseConfig() failed\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eglBindAPI(EGL_OPENGL_API);
 | 
						eglBindAPI(EGL_OPENGL_API);
 | 
				
			||||||
	ec->context = eglCreateContext(ec->display, config, EGL_NO_CONTEXT, NULL);
 | 
						ec->base.context = eglCreateContext(ec->base.display,
 | 
				
			||||||
	if (ec->context == NULL) {
 | 
										    config, EGL_NO_CONTEXT, NULL);
 | 
				
			||||||
 | 
						if (ec->base.context == NULL) {
 | 
				
			||||||
		fprintf(stderr, "failed to create context\n");
 | 
							fprintf(stderr, "failed to create context\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!eglMakeCurrent(ec->display, EGL_NO_SURFACE, EGL_NO_SURFACE, ec->context)) {
 | 
						if (!eglMakeCurrent(ec->base.display, EGL_NO_SURFACE,
 | 
				
			||||||
 | 
								    EGL_NO_SURFACE, ec->base.context)) {
 | 
				
			||||||
		fprintf(stderr, "failed to make context current\n");
 | 
							fprintf(stderr, "failed to make context current\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loop = wl_display_get_event_loop(ec->wl_display);
 | 
					 | 
				
			||||||
	ec->drm_source =
 | 
					 | 
				
			||||||
		wl_event_loop_add_fd(loop, ec->drm_fd,
 | 
					 | 
				
			||||||
				     WL_EVENT_READABLE, on_drm_input, ec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -299,11 +377,11 @@ static drmModeModeInfo builtin_1024x768 = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
create_output_for_connector(struct wlsc_compositor *ec,
 | 
					create_output_for_connector(struct drm_compositor *ec,
 | 
				
			||||||
			    drmModeRes *resources,
 | 
								    drmModeRes *resources,
 | 
				
			||||||
			    drmModeConnector *connector)
 | 
								    drmModeConnector *connector)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_output *output;
 | 
						struct drm_output *output;
 | 
				
			||||||
	drmModeEncoder *encoder;
 | 
						drmModeEncoder *encoder;
 | 
				
			||||||
	drmModeModeInfo *mode;
 | 
						drmModeModeInfo *mode;
 | 
				
			||||||
	int i, ret;
 | 
						int i, ret;
 | 
				
			||||||
| 
						 | 
					@ -339,14 +417,13 @@ create_output_for_connector(struct wlsc_compositor *ec,
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	output->compositor = ec;
 | 
						memset(output, 0, sizeof *output);
 | 
				
			||||||
 | 
						wlsc_output_init(&output->base, &ec->base, 0, 0,
 | 
				
			||||||
 | 
								 mode->hdisplay, mode->vdisplay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	output->crtc_id = resources->crtcs[i];
 | 
						output->crtc_id = resources->crtcs[i];
 | 
				
			||||||
	output->connector_id = connector->connector_id;
 | 
						output->connector_id = connector->connector_id;
 | 
				
			||||||
	output->mode = *mode;
 | 
						output->mode = *mode;
 | 
				
			||||||
	output->x = 0;
 | 
					 | 
				
			||||||
	output->y = 0;
 | 
					 | 
				
			||||||
	output->width = mode->hdisplay;
 | 
					 | 
				
			||||||
	output->height = mode->vdisplay;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drmModeFreeEncoder(encoder);
 | 
						drmModeFreeEncoder(encoder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -354,13 +431,17 @@ create_output_for_connector(struct wlsc_compositor *ec,
 | 
				
			||||||
	for (i = 0; i < 2; i++) {
 | 
						for (i = 0; i < 2; i++) {
 | 
				
			||||||
		glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]);
 | 
							glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		attribs[1] = output->width;
 | 
							attribs[1] = output->base.width;
 | 
				
			||||||
		attribs[3] = output->height;
 | 
							attribs[3] = output->base.height;
 | 
				
			||||||
		output->image[i] = eglCreateDRMImageMESA(ec->display, attribs);
 | 
							output->image[i] =
 | 
				
			||||||
		glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, output->image[i]);
 | 
								eglCreateDRMImageMESA(ec->base.display, attribs);
 | 
				
			||||||
		eglExportDRMImageMESA(ec->display, output->image[i], NULL, &handle, &stride);
 | 
							glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
 | 
				
			||||||
 | 
											       output->image[i]);
 | 
				
			||||||
 | 
							eglExportDRMImageMESA(ec->base.display, output->image[i],
 | 
				
			||||||
 | 
									      NULL, &handle, &stride);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = drmModeAddFB(ec->drm_fd, output->width, output->height,
 | 
							ret = drmModeAddFB(ec->drm_fd,
 | 
				
			||||||
 | 
									   output->base.width, output->base.height,
 | 
				
			||||||
				   32, 32, stride, handle, &output->fb_id[i]);
 | 
									   32, 32, stride, handle, &output->fb_id[i]);
 | 
				
			||||||
		if (ret) {
 | 
							if (ret) {
 | 
				
			||||||
			fprintf(stderr, "failed to add fb %d: %m\n", i);
 | 
								fprintf(stderr, "failed to add fb %d: %m\n", i);
 | 
				
			||||||
| 
						 | 
					@ -381,13 +462,13 @@ create_output_for_connector(struct wlsc_compositor *ec,
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_insert(ec->output_list.prev, &output->link);
 | 
						wl_list_insert(ec->base.output_list.prev, &output->base.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
create_outputs(struct wlsc_compositor *ec)
 | 
					create_outputs(struct drm_compositor *ec)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	drmModeConnector *connector;
 | 
						drmModeConnector *connector;
 | 
				
			||||||
	drmModeRes *resources;
 | 
						drmModeRes *resources;
 | 
				
			||||||
| 
						 | 
					@ -413,7 +494,7 @@ create_outputs(struct wlsc_compositor *ec)
 | 
				
			||||||
		drmModeFreeConnector(connector);
 | 
							drmModeFreeConnector(connector);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (wl_list_empty(&ec->output_list)) {
 | 
						if (wl_list_empty(&ec->base.output_list)) {
 | 
				
			||||||
		fprintf(stderr, "No currently active connector found.\n");
 | 
							fprintf(stderr, "No currently active connector found.\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -425,8 +506,8 @@ create_outputs(struct wlsc_compositor *ec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void on_enter_vt(int signal_number, void *data)
 | 
					static void on_enter_vt(int signal_number, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_compositor *ec = data;
 | 
						struct drm_compositor *ec = data;
 | 
				
			||||||
	struct wlsc_output *output;
 | 
						struct drm_output *output;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = drmSetMaster(ec->drm_fd);
 | 
						ret = drmSetMaster(ec->drm_fd);
 | 
				
			||||||
| 
						 | 
					@ -441,19 +522,20 @@ static void on_enter_vt(int signal_number, void *data)
 | 
				
			||||||
	ioctl(ec->tty_fd, VT_RELDISP, VT_ACKACQ);
 | 
						ioctl(ec->tty_fd, VT_RELDISP, VT_ACKACQ);
 | 
				
			||||||
	ec->vt_active = 1;
 | 
						ec->vt_active = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_for_each(output, &ec->output_list, link) {
 | 
						wl_list_for_each(output, &ec->base.output_list, base.link) {
 | 
				
			||||||
		ret = drmModeSetCrtc(ec->drm_fd, output->crtc_id,
 | 
							ret = drmModeSetCrtc(ec->drm_fd, output->crtc_id,
 | 
				
			||||||
				     output->fb_id[output->current ^ 1], 0, 0,
 | 
									     output->fb_id[output->current ^ 1], 0, 0,
 | 
				
			||||||
				     &output->connector_id, 1, &output->mode);
 | 
									     &output->connector_id, 1, &output->mode);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			fprintf(stderr, "failed to set mode for connector %d: %m\n",
 | 
								fprintf(stderr,
 | 
				
			||||||
 | 
									"failed to set mode for connector %d: %m\n",
 | 
				
			||||||
				output->connector_id);
 | 
									output->connector_id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void on_leave_vt(int signal_number, void *data)
 | 
					static void on_leave_vt(int signal_number, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_compositor *ec = data;
 | 
						struct drm_compositor *ec = data;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = drmDropMaster(ec->drm_fd);
 | 
						ret = drmDropMaster(ec->drm_fd);
 | 
				
			||||||
| 
						 | 
					@ -470,7 +552,7 @@ static void on_leave_vt(int signal_number, void *data)
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
on_tty_input(int fd, uint32_t mask, void *data)
 | 
					on_tty_input(int fd, uint32_t mask, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_compositor *ec = data;
 | 
						struct drm_compositor *ec = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Ignore input to tty.  We get keyboard events from evdev
 | 
						/* Ignore input to tty.  We get keyboard events from evdev
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -479,7 +561,7 @@ on_tty_input(int fd, uint32_t mask, void *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void on_term_signal(int signal_number, void *data)
 | 
					static void on_term_signal(int signal_number, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_compositor *ec = data;
 | 
						struct drm_compositor *ec = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tcsetattr(ec->tty_fd, TCSANOW, &ec->terminal_attributes) < 0)
 | 
						if (tcsetattr(ec->tty_fd, TCSANOW, &ec->terminal_attributes) < 0)
 | 
				
			||||||
		fprintf(stderr, "could not restore terminal to canonical mode\n");
 | 
							fprintf(stderr, "could not restore terminal to canonical mode\n");
 | 
				
			||||||
| 
						 | 
					@ -487,7 +569,7 @@ static void on_term_signal(int signal_number, void *data)
 | 
				
			||||||
	exit(0);
 | 
						exit(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int setup_tty(struct wlsc_compositor *ec, struct wl_event_loop *loop)
 | 
					static int setup_tty(struct drm_compositor *ec, struct wl_event_loop *loop)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct termios raw_attributes;
 | 
						struct termios raw_attributes;
 | 
				
			||||||
	struct vt_mode mode = { 0 };
 | 
						struct vt_mode mode = { 0 };
 | 
				
			||||||
| 
						 | 
					@ -536,59 +618,65 @@ static int setup_tty(struct wlsc_compositor *ec, struct wl_event_loop *loop)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					struct wlsc_compositor *
 | 
				
			||||||
wlsc_compositor_init_drm(struct wlsc_compositor *ec)
 | 
					drm_compositor_create(struct wl_display *display)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct drm_compositor *ec;
 | 
				
			||||||
	struct udev_enumerate *e;
 | 
						struct udev_enumerate *e;
 | 
				
			||||||
        struct udev_list_entry *entry;
 | 
					        struct udev_list_entry *entry;
 | 
				
			||||||
	struct udev_device *device;
 | 
						struct udev_device *device;
 | 
				
			||||||
	const char *path;
 | 
						const char *path;
 | 
				
			||||||
	struct wlsc_input_device *input_device;
 | 
					 | 
				
			||||||
	struct wl_event_loop *loop;
 | 
						struct wl_event_loop *loop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ec = malloc(sizeof *ec);
 | 
				
			||||||
 | 
						if (ec == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(ec, 0, sizeof *ec);
 | 
				
			||||||
	ec->udev = udev_new();
 | 
						ec->udev = udev_new();
 | 
				
			||||||
	if (ec->udev == NULL) {
 | 
						if (ec->udev == NULL) {
 | 
				
			||||||
		fprintf(stderr, "failed to initialize udev context\n");
 | 
							fprintf(stderr, "failed to initialize udev context\n");
 | 
				
			||||||
		return -1;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	input_device = wlsc_input_device_create(ec);
 | 
					 | 
				
			||||||
	ec->input_device = input_device;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	e = udev_enumerate_new(ec->udev);
 | 
					 | 
				
			||||||
	udev_enumerate_add_match_subsystem(e, "input");
 | 
					 | 
				
			||||||
	udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
 | 
					 | 
				
			||||||
        udev_enumerate_scan_devices(e);
 | 
					 | 
				
			||||||
        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
 | 
					 | 
				
			||||||
		path = udev_list_entry_get_name(entry);
 | 
					 | 
				
			||||||
		device = udev_device_new_from_syspath(ec->udev, path);
 | 
					 | 
				
			||||||
		evdev_input_device_create(input_device, ec->wl_display,
 | 
					 | 
				
			||||||
					  udev_device_get_devnode(device));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
        udev_enumerate_unref(e);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	e = udev_enumerate_new(ec->udev);
 | 
						e = udev_enumerate_new(ec->udev);
 | 
				
			||||||
	udev_enumerate_add_match_subsystem(e, "drm");
 | 
						udev_enumerate_add_match_subsystem(e, "drm");
 | 
				
			||||||
	udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
 | 
						udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
 | 
				
			||||||
        udev_enumerate_scan_devices(e);
 | 
					        udev_enumerate_scan_devices(e);
 | 
				
			||||||
 | 
						device = NULL;
 | 
				
			||||||
        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
 | 
					        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
 | 
				
			||||||
		path = udev_list_entry_get_name(entry);
 | 
							path = udev_list_entry_get_name(entry);
 | 
				
			||||||
		device = udev_device_new_from_syspath(ec->udev, path);
 | 
							device = udev_device_new_from_syspath(ec->udev, path);
 | 
				
			||||||
		fprintf(stderr, "creating output for %s\n", path);
 | 
							break;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (init_egl(ec, device) < 0) {
 | 
					 | 
				
			||||||
			fprintf(stderr, "failed to initialize egl\n");
 | 
					 | 
				
			||||||
			return -1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (create_outputs(ec) < 0) {
 | 
					 | 
				
			||||||
			fprintf(stderr, "failed to create output for %s\n", path);
 | 
					 | 
				
			||||||
			return -1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
        udev_enumerate_unref(e);
 | 
					        udev_enumerate_unref(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loop = wl_display_get_event_loop(ec->wl_display);
 | 
						if (device == NULL) {
 | 
				
			||||||
	setup_tty(ec, loop);
 | 
							fprintf(stderr, "no drm device found\n");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						if (init_egl(ec, device) < 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "failed to initialize egl\n");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/* Can't init base class until we have a current egl context */
 | 
				
			||||||
 | 
						wlsc_compositor_init(&ec->base, display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (create_outputs(ec) < 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "failed to create output for %s\n", path);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drm_input_create(ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loop = wl_display_get_event_loop(ec->base.wl_display);
 | 
				
			||||||
 | 
						ec->drm_source =
 | 
				
			||||||
 | 
							wl_event_loop_add_fd(loop, ec->drm_fd,
 | 
				
			||||||
 | 
									     WL_EVENT_READABLE, on_drm_input, ec);
 | 
				
			||||||
 | 
						setup_tty(ec, loop);
 | 
				
			||||||
 | 
						ec->base.present = drm_compositor_present;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &ec->base;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										666
									
								
								compositor-x11.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										666
									
								
								compositor-x11.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,666 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright © 2008-2010 Kristian Høgsberg
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, write to the Free Software Foundation,
 | 
				
			||||||
 | 
					 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <sys/time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <xcb/xcb.h>
 | 
				
			||||||
 | 
					#include <xcb/dri2.h>
 | 
				
			||||||
 | 
					#include <xcb/xfixes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GL_GLEXT_PROTOTYPES
 | 
				
			||||||
 | 
					#define EGL_EGLEXT_PROTOTYPES
 | 
				
			||||||
 | 
					#include <GLES2/gl2.h>
 | 
				
			||||||
 | 
					#include <GLES2/gl2ext.h>
 | 
				
			||||||
 | 
					#include <EGL/egl.h>
 | 
				
			||||||
 | 
					#include <EGL/eglext.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "wayland.h"
 | 
				
			||||||
 | 
					#include "wayland-protocol.h"
 | 
				
			||||||
 | 
					#include "compositor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct x11_compositor {
 | 
				
			||||||
 | 
						struct wlsc_compositor	 base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xcb_connection_t	*conn;
 | 
				
			||||||
 | 
						xcb_screen_t		*screen;
 | 
				
			||||||
 | 
						xcb_cursor_t		 null_cursor;
 | 
				
			||||||
 | 
						int			 dri2_major;
 | 
				
			||||||
 | 
						int			 dri2_minor;
 | 
				
			||||||
 | 
						int			 drm_fd;
 | 
				
			||||||
 | 
						struct wl_event_source	*xcb_source;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							xcb_atom_t		 wm_protocols;
 | 
				
			||||||
 | 
							xcb_atom_t		 wm_normal_hints;
 | 
				
			||||||
 | 
							xcb_atom_t		 wm_size_hints;
 | 
				
			||||||
 | 
							xcb_atom_t		 wm_delete_window;
 | 
				
			||||||
 | 
							xcb_atom_t		 net_wm_name;
 | 
				
			||||||
 | 
							xcb_atom_t		 utf8_string;
 | 
				
			||||||
 | 
						} atom;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct x11_output {
 | 
				
			||||||
 | 
						struct wlsc_output	base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xcb_xfixes_region_t	region;
 | 
				
			||||||
 | 
						xcb_window_t		window;
 | 
				
			||||||
 | 
						GLuint			rbo;
 | 
				
			||||||
 | 
						EGLImageKHR		image;
 | 
				
			||||||
 | 
						xcb_rectangle_t		damage[16];
 | 
				
			||||||
 | 
						int			damage_count;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct x11_input {
 | 
				
			||||||
 | 
						struct wlsc_input_device base;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					x11_input_create(struct x11_compositor *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct x11_input *input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input = malloc(sizeof *input);
 | 
				
			||||||
 | 
						if (input == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(input, 0, sizeof *input);
 | 
				
			||||||
 | 
						wlsc_input_device_init(&input->base, &c->base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->base.input_device = &input->base;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					dri2_connect(struct x11_compositor *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						xcb_xfixes_query_version_reply_t *xfixes_query;
 | 
				
			||||||
 | 
						xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
 | 
				
			||||||
 | 
						xcb_dri2_query_version_reply_t *dri2_query;
 | 
				
			||||||
 | 
						xcb_dri2_query_version_cookie_t dri2_query_cookie;
 | 
				
			||||||
 | 
						xcb_dri2_connect_reply_t *connect;
 | 
				
			||||||
 | 
						xcb_dri2_connect_cookie_t connect_cookie;
 | 
				
			||||||
 | 
						xcb_generic_error_t *error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xcb_prefetch_extension_data (c->conn, &xcb_xfixes_id);
 | 
				
			||||||
 | 
						xcb_prefetch_extension_data (c->conn, &xcb_dri2_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfixes_query_cookie =
 | 
				
			||||||
 | 
							xcb_xfixes_query_version(c->conn,
 | 
				
			||||||
 | 
										 XCB_XFIXES_MAJOR_VERSION,
 | 
				
			||||||
 | 
										 XCB_XFIXES_MINOR_VERSION);
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
						dri2_query_cookie =
 | 
				
			||||||
 | 
							xcb_dri2_query_version (c->conn,
 | 
				
			||||||
 | 
										XCB_DRI2_MAJOR_VERSION,
 | 
				
			||||||
 | 
										XCB_DRI2_MINOR_VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						connect_cookie = xcb_dri2_connect_unchecked (c->conn,
 | 
				
			||||||
 | 
											     c->screen->root,
 | 
				
			||||||
 | 
											     XCB_DRI2_DRIVER_TYPE_DRI);
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
						xfixes_query =
 | 
				
			||||||
 | 
							xcb_xfixes_query_version_reply (c->conn,
 | 
				
			||||||
 | 
											xfixes_query_cookie, &error);
 | 
				
			||||||
 | 
						if (xfixes_query == NULL ||
 | 
				
			||||||
 | 
						    error != NULL || xfixes_query->major_version < 2) {
 | 
				
			||||||
 | 
							free(error);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(xfixes_query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dri2_query =
 | 
				
			||||||
 | 
							xcb_dri2_query_version_reply (c->conn,
 | 
				
			||||||
 | 
										      dri2_query_cookie, &error);
 | 
				
			||||||
 | 
						if (dri2_query == NULL || error != NULL) {
 | 
				
			||||||
 | 
							fprintf(stderr, "DRI2: failed to query version");
 | 
				
			||||||
 | 
							free(error);
 | 
				
			||||||
 | 
							return EGL_FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c->dri2_major = dri2_query->major_version;
 | 
				
			||||||
 | 
						c->dri2_minor = dri2_query->minor_version;
 | 
				
			||||||
 | 
						free(dri2_query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						connect = xcb_dri2_connect_reply (c->conn,
 | 
				
			||||||
 | 
										  connect_cookie, NULL);
 | 
				
			||||||
 | 
						if (connect == NULL ||
 | 
				
			||||||
 | 
						    connect->driver_name_length + connect->device_name_length == 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "DRI2: failed to authenticate");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->base.base.device =
 | 
				
			||||||
 | 
							strndup(xcb_dri2_connect_device_name (connect),
 | 
				
			||||||
 | 
								xcb_dri2_connect_device_name_length (connect));
 | 
				
			||||||
 | 
							   
 | 
				
			||||||
 | 
						if (c->base.base.device == NULL) {
 | 
				
			||||||
 | 
							free(connect);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(connect);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					dri2_authenticate(struct x11_compositor *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						xcb_dri2_authenticate_reply_t *authenticate;
 | 
				
			||||||
 | 
						xcb_dri2_authenticate_cookie_t authenticate_cookie;
 | 
				
			||||||
 | 
						drm_magic_t magic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (drmGetMagic(c->drm_fd, &magic)) {
 | 
				
			||||||
 | 
							fprintf(stderr, "DRI2: failed to get drm magic");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						authenticate_cookie =
 | 
				
			||||||
 | 
							xcb_dri2_authenticate_unchecked(c->conn,
 | 
				
			||||||
 | 
											c->screen->root, magic);
 | 
				
			||||||
 | 
						authenticate =
 | 
				
			||||||
 | 
							xcb_dri2_authenticate_reply(c->conn,
 | 
				
			||||||
 | 
										    authenticate_cookie, NULL);
 | 
				
			||||||
 | 
						if (authenticate == NULL || !authenticate->authenticated) {
 | 
				
			||||||
 | 
							fprintf(stderr, "DRI2: failed to authenticate");
 | 
				
			||||||
 | 
							free(authenticate);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(authenticate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					x11_compositor_init_egl(struct x11_compositor *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PFNEGLGETTYPEDDISPLAYMESA get_typed_display_mesa;
 | 
				
			||||||
 | 
						EGLint major, minor, count;
 | 
				
			||||||
 | 
						EGLConfig config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static const EGLint config_attribs[] = {
 | 
				
			||||||
 | 
							EGL_SURFACE_TYPE,		0,
 | 
				
			||||||
 | 
							EGL_NO_SURFACE_CAPABLE_MESA,	EGL_OPENGL_BIT,
 | 
				
			||||||
 | 
							EGL_RENDERABLE_TYPE,		EGL_OPENGL_BIT,
 | 
				
			||||||
 | 
							EGL_NONE
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dri2_connect(c) < 0)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						c->drm_fd = open(c->base.base.device, O_RDWR);
 | 
				
			||||||
 | 
						if (c->drm_fd == -1) {
 | 
				
			||||||
 | 
							fprintf(stderr,
 | 
				
			||||||
 | 
								"DRI2: could not open %s (%s)", c->base.base.device,
 | 
				
			||||||
 | 
								strerror(errno));
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dri2_authenticate(c) < 0)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						get_typed_display_mesa =
 | 
				
			||||||
 | 
							(PFNEGLGETTYPEDDISPLAYMESA)
 | 
				
			||||||
 | 
							eglGetProcAddress("eglGetTypedDisplayMESA");
 | 
				
			||||||
 | 
						if (get_typed_display_mesa == NULL) {
 | 
				
			||||||
 | 
							fprintf(stderr, "eglGetTypedDisplayMESA() not found\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->base.display = get_typed_display_mesa(EGL_DRM_DISPLAY_TYPE_MESA,
 | 
				
			||||||
 | 
											 (void *) c->drm_fd);
 | 
				
			||||||
 | 
						if (c->base.display == NULL) {
 | 
				
			||||||
 | 
							fprintf(stderr, "failed to create display\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!eglInitialize(c->base.display, &major, &minor)) {
 | 
				
			||||||
 | 
							fprintf(stderr, "failed to initialize display\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!eglChooseConfig(c->base.display,
 | 
				
			||||||
 | 
								     config_attribs, &config, 1, &count) ||
 | 
				
			||||||
 | 
						    count == 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "eglChooseConfig() failed\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eglBindAPI(EGL_OPENGL_API);
 | 
				
			||||||
 | 
						c->base.context = eglCreateContext(c->base.display,
 | 
				
			||||||
 | 
										   config, EGL_NO_CONTEXT, NULL);
 | 
				
			||||||
 | 
						if (c->base.context == NULL) {
 | 
				
			||||||
 | 
							fprintf(stderr, "failed to create context\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE,
 | 
				
			||||||
 | 
								    EGL_NO_SURFACE, c->base.context)) {
 | 
				
			||||||
 | 
							fprintf(stderr, "failed to make context current\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					x11_compositor_present(struct wlsc_compositor *base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct x11_compositor *c = (struct x11_compositor *) base;
 | 
				
			||||||
 | 
						struct x11_output *output;
 | 
				
			||||||
 | 
						xcb_dri2_copy_region_cookie_t cookie;
 | 
				
			||||||
 | 
						struct timeval tv;
 | 
				
			||||||
 | 
						uint32_t msec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glFlush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_for_each(output, &c->base.output_list, base.link) {
 | 
				
			||||||
 | 
							cookie = xcb_dri2_copy_region_unchecked(c->conn,
 | 
				
			||||||
 | 
												output->window,
 | 
				
			||||||
 | 
												output->region,
 | 
				
			||||||
 | 
												XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
 | 
				
			||||||
 | 
												XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT);
 | 
				
			||||||
 | 
							free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL));
 | 
				
			||||||
 | 
						}	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gettimeofday(&tv, NULL);
 | 
				
			||||||
 | 
						msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
 | 
				
			||||||
 | 
						wlsc_compositor_finish_frame(&c->base, msec);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					x11_output_set_wm_protocols(struct x11_output *output)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						xcb_atom_t list[1];
 | 
				
			||||||
 | 
						struct x11_compositor *c =
 | 
				
			||||||
 | 
							(struct x11_compositor *) output->base.compositor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list[0] = c->atom.wm_delete_window;
 | 
				
			||||||
 | 
						xcb_change_property (c->conn, 
 | 
				
			||||||
 | 
								     XCB_PROP_MODE_REPLACE,
 | 
				
			||||||
 | 
								     output->window,
 | 
				
			||||||
 | 
								     c->atom.wm_protocols,
 | 
				
			||||||
 | 
								     XCB_ATOM_ATOM,
 | 
				
			||||||
 | 
								     32,
 | 
				
			||||||
 | 
								     ARRAY_SIZE(list),
 | 
				
			||||||
 | 
								     list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wm_normal_hints {
 | 
				
			||||||
 | 
					    	uint32_t flags;
 | 
				
			||||||
 | 
						uint32_t pad[4];
 | 
				
			||||||
 | 
						int32_t min_width, min_height;
 | 
				
			||||||
 | 
						int32_t max_width, max_height;
 | 
				
			||||||
 | 
					    	int32_t width_inc, height_inc;
 | 
				
			||||||
 | 
					    	int32_t min_aspect_x, min_aspect_y;
 | 
				
			||||||
 | 
					    	int32_t max_aspect_x, max_aspect_y;
 | 
				
			||||||
 | 
						int32_t base_width, base_height;
 | 
				
			||||||
 | 
						int32_t win_gravity;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define WM_NORMAL_HINTS_MIN_SIZE	16
 | 
				
			||||||
 | 
					#define WM_NORMAL_HINTS_MAX_SIZE	32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					x11_compositor_create_output(struct x11_compositor *c, int width, int height)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const char name[] = "Wayland Compositor";
 | 
				
			||||||
 | 
						struct x11_output *output;
 | 
				
			||||||
 | 
						xcb_dri2_dri2_buffer_t *buffers;
 | 
				
			||||||
 | 
						xcb_dri2_get_buffers_reply_t *reply;
 | 
				
			||||||
 | 
						xcb_dri2_get_buffers_cookie_t cookie;
 | 
				
			||||||
 | 
						xcb_screen_iterator_t iter;
 | 
				
			||||||
 | 
						xcb_rectangle_t rectangle;
 | 
				
			||||||
 | 
						struct wm_normal_hints normal_hints;
 | 
				
			||||||
 | 
						unsigned int attachments[] =
 | 
				
			||||||
 | 
							{ XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT};
 | 
				
			||||||
 | 
						uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
 | 
				
			||||||
 | 
						uint32_t values[2] = { 
 | 
				
			||||||
 | 
							XCB_EVENT_MASK_KEY_PRESS |
 | 
				
			||||||
 | 
							XCB_EVENT_MASK_KEY_RELEASE |
 | 
				
			||||||
 | 
							XCB_EVENT_MASK_BUTTON_PRESS |
 | 
				
			||||||
 | 
							XCB_EVENT_MASK_BUTTON_RELEASE |
 | 
				
			||||||
 | 
							XCB_EVENT_MASK_POINTER_MOTION |
 | 
				
			||||||
 | 
							XCB_EVENT_MASK_EXPOSURE |
 | 
				
			||||||
 | 
							XCB_EVENT_MASK_STRUCTURE_NOTIFY,
 | 
				
			||||||
 | 
							0
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						EGLint attribs[] = {
 | 
				
			||||||
 | 
							EGL_WIDTH,		0,
 | 
				
			||||||
 | 
							EGL_HEIGHT,		0,
 | 
				
			||||||
 | 
							EGL_IMAGE_STRIDE_MESA,	0,
 | 
				
			||||||
 | 
							EGL_IMAGE_FORMAT_MESA,	EGL_IMAGE_FORMAT_ARGB8888_MESA,
 | 
				
			||||||
 | 
							EGL_NONE
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output = malloc(sizeof *output);
 | 
				
			||||||
 | 
						if (output == NULL)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(output, 0, sizeof *output);
 | 
				
			||||||
 | 
						wlsc_output_init(&output->base, &c->base, 0, 0, width, height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						values[1] = c->null_cursor;
 | 
				
			||||||
 | 
						output->window = xcb_generate_id(c->conn);
 | 
				
			||||||
 | 
						iter = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
 | 
				
			||||||
 | 
						xcb_create_window(c->conn,
 | 
				
			||||||
 | 
								  XCB_COPY_FROM_PARENT,
 | 
				
			||||||
 | 
								  output->window,
 | 
				
			||||||
 | 
								  iter.data->root,
 | 
				
			||||||
 | 
								  0, 0,
 | 
				
			||||||
 | 
								  width, height,
 | 
				
			||||||
 | 
								  0,
 | 
				
			||||||
 | 
								  XCB_WINDOW_CLASS_INPUT_OUTPUT,
 | 
				
			||||||
 | 
								  iter.data->root_visual,
 | 
				
			||||||
 | 
								  mask, values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Don't resize me. */
 | 
				
			||||||
 | 
						memset(&normal_hints, 0, sizeof normal_hints);
 | 
				
			||||||
 | 
						normal_hints.flags =
 | 
				
			||||||
 | 
							WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE;
 | 
				
			||||||
 | 
						normal_hints.min_width = width;
 | 
				
			||||||
 | 
						normal_hints.min_height = height;
 | 
				
			||||||
 | 
						normal_hints.max_width = width;
 | 
				
			||||||
 | 
						normal_hints.max_height = height;
 | 
				
			||||||
 | 
						xcb_change_property (c->conn, XCB_PROP_MODE_REPLACE, output->window,
 | 
				
			||||||
 | 
								     c->atom.wm_normal_hints,
 | 
				
			||||||
 | 
								     c->atom.wm_size_hints, 32,
 | 
				
			||||||
 | 
								     sizeof normal_hints / 4,
 | 
				
			||||||
 | 
								     (uint8_t *) &normal_hints);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        xcb_map_window(c->conn, output->window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set window name.  Don't bother with non-EWMH WMs. */
 | 
				
			||||||
 | 
						xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window,
 | 
				
			||||||
 | 
								    c->atom.net_wm_name, c->atom.utf8_string, 8,
 | 
				
			||||||
 | 
								    strlen(name), name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rectangle.x = 0;
 | 
				
			||||||
 | 
						rectangle.y = 0;
 | 
				
			||||||
 | 
						rectangle.width = width;
 | 
				
			||||||
 | 
						rectangle.height = height;
 | 
				
			||||||
 | 
						output->region = xcb_generate_id(c->conn);
 | 
				
			||||||
 | 
						xcb_xfixes_create_region(c->conn, output->region, 1, &rectangle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xcb_dri2_create_drawable (c->conn, output->window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11_output_set_wm_protocols(output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cookie = xcb_dri2_get_buffers_unchecked (c->conn,
 | 
				
			||||||
 | 
											 output->window,
 | 
				
			||||||
 | 
											 1, 1, attachments);
 | 
				
			||||||
 | 
						reply = xcb_dri2_get_buffers_reply (c->conn, cookie, NULL);
 | 
				
			||||||
 | 
						if (reply == NULL)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						buffers = xcb_dri2_get_buffers_buffers (reply);
 | 
				
			||||||
 | 
						if (buffers == NULL)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (reply->count != 1) {
 | 
				
			||||||
 | 
							fprintf(stderr,
 | 
				
			||||||
 | 
								"got wrong number of buffers (%d)\n", reply->count);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						attribs[1] = reply->width;
 | 
				
			||||||
 | 
						attribs[3] = reply->height;
 | 
				
			||||||
 | 
						attribs[5] = buffers[0].pitch / 4;
 | 
				
			||||||
 | 
						free(reply);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output->image =
 | 
				
			||||||
 | 
							eglCreateImageKHR(c->base.display, c->base.context,
 | 
				
			||||||
 | 
									  EGL_DRM_IMAGE_MESA,
 | 
				
			||||||
 | 
									  (EGLClientBuffer) buffers[0].name,
 | 
				
			||||||
 | 
									  attribs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glGenRenderbuffers(1, &output->rbo);
 | 
				
			||||||
 | 
						glBindRenderbuffer(GL_RENDERBUFFER, output->rbo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
 | 
				
			||||||
 | 
										       output->image);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glFramebufferRenderbuffer(GL_FRAMEBUFFER,
 | 
				
			||||||
 | 
									  GL_COLOR_ATTACHMENT0,
 | 
				
			||||||
 | 
									  GL_RENDERBUFFER,
 | 
				
			||||||
 | 
									  output->rbo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_insert(c->base.output_list.prev, &output->base.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					idle_repaint(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct x11_output *output = data;
 | 
				
			||||||
 | 
						struct x11_compositor *c =
 | 
				
			||||||
 | 
							(struct x11_compositor *) output->base.compositor;
 | 
				
			||||||
 | 
						xcb_xfixes_region_t region;
 | 
				
			||||||
 | 
						xcb_dri2_copy_region_cookie_t cookie;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (output->damage_count <= ARRAY_SIZE(output->damage)) {
 | 
				
			||||||
 | 
							region = xcb_generate_id(c->conn);
 | 
				
			||||||
 | 
							xcb_xfixes_create_region(c->conn, region,
 | 
				
			||||||
 | 
										 output->damage_count, output->damage);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							region = output->region;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cookie = xcb_dri2_copy_region_unchecked(c->conn,
 | 
				
			||||||
 | 
											output->window,
 | 
				
			||||||
 | 
											region,
 | 
				
			||||||
 | 
											XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
 | 
				
			||||||
 | 
											XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (region != output->region)
 | 
				
			||||||
 | 
							xcb_xfixes_destroy_region(c->conn, region);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL));
 | 
				
			||||||
 | 
						output->damage_count = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct x11_output *
 | 
				
			||||||
 | 
					x11_compositor_find_output(struct x11_compositor *c, xcb_window_t window)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct x11_output *output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_for_each(output, &c->base.output_list, base.link) {
 | 
				
			||||||
 | 
							if (output->window == window)
 | 
				
			||||||
 | 
								return output;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					x11_compositor_handle_event(int fd, uint32_t mask, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct x11_compositor *c = data;
 | 
				
			||||||
 | 
						struct x11_output *output;
 | 
				
			||||||
 | 
					        xcb_generic_event_t *event;
 | 
				
			||||||
 | 
						struct wl_event_loop *loop;
 | 
				
			||||||
 | 
						xcb_client_message_event_t *client_message;
 | 
				
			||||||
 | 
						xcb_motion_notify_event_t *motion_notify;
 | 
				
			||||||
 | 
						xcb_key_press_event_t *key_press;
 | 
				
			||||||
 | 
						xcb_button_press_event_t *button_press;
 | 
				
			||||||
 | 
						xcb_expose_event_t *expose;
 | 
				
			||||||
 | 
						xcb_rectangle_t *r;
 | 
				
			||||||
 | 
						xcb_atom_t atom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loop = wl_display_get_event_loop(c->base.wl_display);
 | 
				
			||||||
 | 
					        while (event = xcb_poll_for_event (c->conn), event != NULL) {
 | 
				
			||||||
 | 
							switch (event->response_type & ~0x80) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case XCB_KEY_PRESS:
 | 
				
			||||||
 | 
								key_press = (xcb_key_press_event_t *) event;
 | 
				
			||||||
 | 
								notify_key(c->base.input_device,
 | 
				
			||||||
 | 
									   key_press->detail, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								fprintf(stderr, "code %d, sequence %d\n",
 | 
				
			||||||
 | 
									key_press->detail, key_press->sequence);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case XCB_KEY_RELEASE:
 | 
				
			||||||
 | 
								key_press = (xcb_key_press_event_t *) event;
 | 
				
			||||||
 | 
								notify_key(c->base.input_device,
 | 
				
			||||||
 | 
									   key_press->detail, 0);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case XCB_BUTTON_PRESS:
 | 
				
			||||||
 | 
								button_press = (xcb_button_press_event_t *) event;
 | 
				
			||||||
 | 
								notify_button(c->base.input_device,
 | 
				
			||||||
 | 
									      button_press->detail, 1);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case XCB_BUTTON_RELEASE:
 | 
				
			||||||
 | 
								button_press = (xcb_button_press_event_t *) event;
 | 
				
			||||||
 | 
								notify_button(c->base.input_device,
 | 
				
			||||||
 | 
									      button_press->detail, 0);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case XCB_MOTION_NOTIFY:
 | 
				
			||||||
 | 
								motion_notify = (xcb_motion_notify_event_t *) event;
 | 
				
			||||||
 | 
								notify_motion(c->base.input_device,
 | 
				
			||||||
 | 
									      motion_notify->event_x,
 | 
				
			||||||
 | 
									      motion_notify->event_y);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case XCB_EXPOSE:
 | 
				
			||||||
 | 
								expose = (xcb_expose_event_t *) event;
 | 
				
			||||||
 | 
								output = x11_compositor_find_output(c, expose->window);
 | 
				
			||||||
 | 
								if (output->damage_count == 0)
 | 
				
			||||||
 | 
									wl_event_loop_add_idle(loop,
 | 
				
			||||||
 | 
											       idle_repaint, output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								r = &output->damage[output->damage_count++];
 | 
				
			||||||
 | 
								if (output->damage_count > 16)
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								r->x = expose->x;
 | 
				
			||||||
 | 
								r->y = expose->y;
 | 
				
			||||||
 | 
								r->width = expose->width;
 | 
				
			||||||
 | 
								r->height = expose->height;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case XCB_CLIENT_MESSAGE:
 | 
				
			||||||
 | 
								client_message = (xcb_client_message_event_t *) event;
 | 
				
			||||||
 | 
								atom = client_message->data.data32[0];
 | 
				
			||||||
 | 
								if (atom == c->atom.wm_delete_window)
 | 
				
			||||||
 | 
									exit(1);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default: 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							free (event);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define F(field) offsetof(struct x11_compositor, field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					x11_compositor_get_resources(struct x11_compositor *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const struct { const char *name; int offset; } atoms[] = {
 | 
				
			||||||
 | 
							{ "WM_PROTOCOLS",	F(atom.wm_protocols) },
 | 
				
			||||||
 | 
							{ "WM_NORMAL_HINTS",	F(atom.wm_normal_hints) },
 | 
				
			||||||
 | 
							{ "WM_SIZE_HINTS",	F(atom.wm_size_hints) },
 | 
				
			||||||
 | 
							{ "WM_DELETE_WINDOW",	F(atom.wm_delete_window) },
 | 
				
			||||||
 | 
							{ "_NET_WM_NAME",	F(atom.net_wm_name) },
 | 
				
			||||||
 | 
							{ "UTF8_STRING",	F(atom.utf8_string) },
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xcb_intern_atom_cookie_t cookies[ARRAY_SIZE(atoms)];
 | 
				
			||||||
 | 
						xcb_intern_atom_reply_t *reply;
 | 
				
			||||||
 | 
						xcb_pixmap_t pixmap;
 | 
				
			||||||
 | 
						xcb_gc_t gc;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						uint8_t data[] = { 0, 0, 0, 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(atoms); i++)
 | 
				
			||||||
 | 
							cookies[i] = xcb_intern_atom (c->conn, 0,
 | 
				
			||||||
 | 
										      strlen(atoms[i].name),
 | 
				
			||||||
 | 
										      atoms[i].name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(atoms); i++) {
 | 
				
			||||||
 | 
							reply = xcb_intern_atom_reply (c->conn, cookies[i], NULL);
 | 
				
			||||||
 | 
							*(xcb_atom_t *) ((char *) c + atoms[i].offset) = reply->atom;
 | 
				
			||||||
 | 
							free(reply);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pixmap = xcb_generate_id(c->conn);
 | 
				
			||||||
 | 
						gc = xcb_generate_id(c->conn);
 | 
				
			||||||
 | 
						xcb_create_pixmap(c->conn, 1, pixmap, c->screen->root, 1, 1);
 | 
				
			||||||
 | 
						xcb_create_gc(c->conn, gc, pixmap, 0, NULL);
 | 
				
			||||||
 | 
						xcb_put_image(c->conn, XCB_IMAGE_FORMAT_XY_PIXMAP,
 | 
				
			||||||
 | 
							      pixmap, gc, 1, 1, 0, 0, 0, 32, sizeof data, data);
 | 
				
			||||||
 | 
						c->null_cursor = xcb_generate_id(c->conn);
 | 
				
			||||||
 | 
						xcb_create_cursor (c->conn, c->null_cursor,
 | 
				
			||||||
 | 
								   pixmap, pixmap, 0, 0, 0,  0, 0, 0,  1, 1);
 | 
				
			||||||
 | 
						xcb_free_gc(c->conn, gc);
 | 
				
			||||||
 | 
						xcb_free_pixmap(c->conn, pixmap);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlsc_compositor *
 | 
				
			||||||
 | 
					x11_compositor_create(struct wl_display *display)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct x11_compositor *c;
 | 
				
			||||||
 | 
						struct wl_event_loop *loop;
 | 
				
			||||||
 | 
						xcb_screen_iterator_t s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c = malloc(sizeof *c);
 | 
				
			||||||
 | 
						if (c == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(c, 0, sizeof *c);
 | 
				
			||||||
 | 
						c->conn = xcb_connect(0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (xcb_connection_has_error(c->conn))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
 | 
				
			||||||
 | 
						c->screen = s.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11_compositor_get_resources(c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11_compositor_init_egl(c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Can't init base class until we have a current egl context */
 | 
				
			||||||
 | 
						wlsc_compositor_init(&c->base, display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11_compositor_create_output(c, 1024, 640);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11_input_create(c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loop = wl_display_get_event_loop(c->base.wl_display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->xcb_source =
 | 
				
			||||||
 | 
							wl_event_loop_add_fd(loop, xcb_get_file_descriptor(c->conn),
 | 
				
			||||||
 | 
									     WL_EVENT_READABLE,
 | 
				
			||||||
 | 
									     x11_compositor_handle_event, c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->base.present = x11_compositor_present;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &c->base;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										108
									
								
								compositor.c
									
										
									
									
									
								
							
							
						
						
									
										108
									
								
								compositor.c
									
										
									
									
									
								
							| 
						 | 
					@ -355,8 +355,6 @@ wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs)
 | 
				
			||||||
			      compositor->current_frame, msecs);
 | 
								      compositor->current_frame, msecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_event_source_timer_update(compositor->timer_source, 5);
 | 
						wl_event_source_timer_update(compositor->timer_source, 5);
 | 
				
			||||||
	compositor->repaint_on_timeout = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	compositor->current_frame++;
 | 
						compositor->current_frame++;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -379,13 +377,6 @@ wlsc_output_repaint(struct wlsc_output *output)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_for_each(eid, &ec->input_device_list, link)
 | 
						wl_list_for_each(eid, &ec->input_device_list, link)
 | 
				
			||||||
		wlsc_surface_draw(eid->sprite, output);
 | 
							wlsc_surface_draw(eid->sprite, output);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	output->current ^= 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	glFramebufferRenderbuffer(GL_FRAMEBUFFER,
 | 
					 | 
				
			||||||
				  GL_COLOR_ATTACHMENT0,
 | 
					 | 
				
			||||||
				  GL_RENDERBUFFER,
 | 
					 | 
				
			||||||
				  output->rbo[output->current]);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					@ -402,7 +393,7 @@ repaint(void *data)
 | 
				
			||||||
	wl_list_for_each(output, &ec->output_list, link)
 | 
						wl_list_for_each(output, &ec->output_list, link)
 | 
				
			||||||
		wlsc_output_repaint(output);
 | 
							wlsc_output_repaint(output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlsc_compositor_present_drm(ec);
 | 
						ec->present(ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ec->repaint_needed = 0;
 | 
						ec->repaint_needed = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -628,9 +619,6 @@ notify_motion(struct wlsc_input_device *device, int x, int y)
 | 
				
			||||||
	const int hotspot_x = 16, hotspot_y = 16;
 | 
						const int hotspot_x = 16, hotspot_y = 16;
 | 
				
			||||||
	int32_t sx, sy;
 | 
						int32_t sx, sy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ec->vt_active)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* FIXME: We need some multi head love here. */
 | 
						/* FIXME: We need some multi head love here. */
 | 
				
			||||||
	output = container_of(ec->output_list.next, struct wlsc_output, link);
 | 
						output = container_of(ec->output_list.next, struct wlsc_output, link);
 | 
				
			||||||
	if (x < output->x)
 | 
						if (x < output->x)
 | 
				
			||||||
| 
						 | 
					@ -668,8 +656,7 @@ notify_button(struct wlsc_input_device *device,
 | 
				
			||||||
	struct wlsc_compositor *compositor = device->ec;
 | 
						struct wlsc_compositor *compositor = device->ec;
 | 
				
			||||||
	int32_t sx, sy;
 | 
						int32_t sx, sy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!compositor->vt_active)
 | 
						fprintf(stderr, "notify button: button %d, state %d\n", button, state);
 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	surface = pick_surface(device, &sx, &sy);
 | 
						surface = pick_surface(device, &sx, &sy);
 | 
				
			||||||
	if (surface) {
 | 
						if (surface) {
 | 
				
			||||||
| 
						 | 
					@ -700,9 +687,6 @@ notify_key(struct wlsc_input_device *device,
 | 
				
			||||||
	uint32_t *k, *end;
 | 
						uint32_t *k, *end;
 | 
				
			||||||
	uint32_t modifier;
 | 
						uint32_t modifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!compositor->vt_active)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key | compositor->modifier_state) {
 | 
						switch (key | compositor->modifier_state) {
 | 
				
			||||||
	case KEY_BACKSPACE | MODIFIER_CTRL | MODIFIER_ALT:
 | 
						case KEY_BACKSPACE | MODIFIER_CTRL | MODIFIER_ALT:
 | 
				
			||||||
		kill(0, SIGTERM);
 | 
							kill(0, SIGTERM);
 | 
				
			||||||
| 
						 | 
					@ -769,16 +753,10 @@ handle_surface_destroy(struct wlsc_listener *listener,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_input_device *
 | 
					void
 | 
				
			||||||
wlsc_input_device_create(struct wlsc_compositor *ec)
 | 
					wlsc_input_device_init(struct wlsc_input_device *device,
 | 
				
			||||||
 | 
							       struct wlsc_compositor *ec)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_input_device *device;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	device = malloc(sizeof *device);
 | 
					 | 
				
			||||||
	if (device == NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(device, 0, sizeof *device);
 | 
					 | 
				
			||||||
	device->base.interface = &wl_input_device_interface;
 | 
						device->base.interface = &wl_input_device_interface;
 | 
				
			||||||
	device->base.implementation = NULL;
 | 
						device->base.implementation = NULL;
 | 
				
			||||||
	wl_display_add_object(ec->wl_display, &device->base);
 | 
						wl_display_add_object(ec->wl_display, &device->base);
 | 
				
			||||||
| 
						 | 
					@ -786,13 +764,12 @@ wlsc_input_device_create(struct wlsc_compositor *ec)
 | 
				
			||||||
	device->x = 100;
 | 
						device->x = 100;
 | 
				
			||||||
	device->y = 100;
 | 
						device->y = 100;
 | 
				
			||||||
	device->ec = ec;
 | 
						device->ec = ec;
 | 
				
			||||||
 | 
						device->sprite = pointer_create(ec, device->x, device->y, 64, 64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device->listener.func = handle_surface_destroy;
 | 
						device->listener.func = handle_surface_destroy;
 | 
				
			||||||
	wl_list_insert(ec->surface_destroy_listener_list.prev,
 | 
						wl_list_insert(ec->surface_destroy_listener_list.prev,
 | 
				
			||||||
		       &device->listener.link);
 | 
							       &device->listener.link);
 | 
				
			||||||
	wl_list_insert(ec->input_device_list.prev, &device->link);
 | 
						wl_list_insert(ec->input_device_list.prev, &device->link);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return device;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					@ -916,18 +893,37 @@ add_visuals(struct wlsc_compositor *ec)
 | 
				
			||||||
	wl_display_add_global(ec->wl_display, &ec->rgb_visual.base, NULL);
 | 
						wl_display_add_global(ec->wl_display, &ec->rgb_visual.base, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct wlsc_compositor *
 | 
					void
 | 
				
			||||||
wlsc_compositor_create(struct wl_display *display)
 | 
					wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
 | 
				
			||||||
 | 
							 int x, int y, int width, int height)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						output->compositor = c;
 | 
				
			||||||
 | 
						output->x = x;
 | 
				
			||||||
 | 
						output->y = y;
 | 
				
			||||||
 | 
						output->width = width;
 | 
				
			||||||
 | 
						output->height = height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output->background =
 | 
				
			||||||
 | 
							background_create(output, option_background);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlsc_matrix_init(&output->matrix);
 | 
				
			||||||
 | 
						wlsc_matrix_translate(&output->matrix,
 | 
				
			||||||
 | 
								      -output->x - output->width / 2.0,
 | 
				
			||||||
 | 
								      -output->y - output->height / 2.0, 0);
 | 
				
			||||||
 | 
						wlsc_matrix_scale(&output->matrix,
 | 
				
			||||||
 | 
								  2.0 / output->width, 2.0 / output->height, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output->base.interface = &wl_output_interface;
 | 
				
			||||||
 | 
						wl_display_add_object(c->wl_display, &output->base);
 | 
				
			||||||
 | 
						wl_display_add_global(c->wl_display, &output->base,
 | 
				
			||||||
 | 
								      wlsc_output_post_geometry);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_compositor *ec;
 | 
					 | 
				
			||||||
	struct wl_event_loop *loop;
 | 
						struct wl_event_loop *loop;
 | 
				
			||||||
	struct wlsc_output *output;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ec = malloc(sizeof *ec);
 | 
					 | 
				
			||||||
	if (ec == NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(ec, 0, sizeof *ec);
 | 
					 | 
				
			||||||
	ec->wl_display = display;
 | 
						ec->wl_display = display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_display_set_compositor(display, &ec->base, &compositor_interface); 
 | 
						wl_display_set_compositor(display, &ec->base, &compositor_interface); 
 | 
				
			||||||
| 
						 | 
					@ -941,34 +937,6 @@ wlsc_compositor_create(struct wl_display *display)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	screenshooter_create(ec);
 | 
						screenshooter_create(ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (wlsc_compositor_init_drm(ec) < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "failed to initialize devices\n");
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Create the pointer and background surfaces now that we have
 | 
					 | 
				
			||||||
	 * a current EGL context. */
 | 
					 | 
				
			||||||
	ec->input_device->sprite =
 | 
					 | 
				
			||||||
		pointer_create(ec, 
 | 
					 | 
				
			||||||
			       ec->input_device->x,
 | 
					 | 
				
			||||||
			       ec->input_device->y, 64, 64);
 | 
					 | 
				
			||||||
	wl_list_for_each(output, &ec->output_list, link) {
 | 
					 | 
				
			||||||
		output->background = background_create(output,
 | 
					 | 
				
			||||||
						       option_background);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		wlsc_matrix_init(&output->matrix);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		wlsc_matrix_translate(&output->matrix,
 | 
					 | 
				
			||||||
				      -output->x - output->width / 2.0,
 | 
					 | 
				
			||||||
				      -output->y - output->height / 2.0, 0);
 | 
					 | 
				
			||||||
		wlsc_matrix_scale(&output->matrix,
 | 
					 | 
				
			||||||
				  2.0 / output->width, 2.0 / output->height, 1);
 | 
					 | 
				
			||||||
		output->base.interface = &wl_output_interface;
 | 
					 | 
				
			||||||
		wl_display_add_object(ec->wl_display, &output->base);
 | 
					 | 
				
			||||||
		wl_display_add_global(ec->wl_display, &output->base,
 | 
					 | 
				
			||||||
				      wlsc_output_post_geometry);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	glGenFramebuffers(1, &ec->fbo);
 | 
						glGenFramebuffers(1, &ec->fbo);
 | 
				
			||||||
	glBindFramebuffer(GL_FRAMEBUFFER, ec->fbo);
 | 
						glBindFramebuffer(GL_FRAMEBUFFER, ec->fbo);
 | 
				
			||||||
	glActiveTexture(GL_TEXTURE0);
 | 
						glActiveTexture(GL_TEXTURE0);
 | 
				
			||||||
| 
						 | 
					@ -978,7 +946,7 @@ wlsc_compositor_create(struct wl_display *display)
 | 
				
			||||||
	ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
 | 
						ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
 | 
				
			||||||
	wlsc_compositor_schedule_repaint(ec);
 | 
						wlsc_compositor_schedule_repaint(ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ec;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The plan here is to generate a random anonymous socket name and
 | 
					/* The plan here is to generate a random anonymous socket name and
 | 
				
			||||||
| 
						 | 
					@ -1002,7 +970,11 @@ int main(int argc, char *argv[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	display = wl_display_create();
 | 
						display = wl_display_create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ec = wlsc_compositor_create(display);
 | 
						if (getenv("DISPLAY"))
 | 
				
			||||||
 | 
							ec = x11_compositor_create(display);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ec = drm_compositor_create(display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ec == NULL) {
 | 
						if (ec == NULL) {
 | 
				
			||||||
		fprintf(stderr, "failed to create compositor\n");
 | 
							fprintf(stderr, "failed to create compositor\n");
 | 
				
			||||||
		exit(EXIT_FAILURE);
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										45
									
								
								compositor.h
									
										
									
									
									
								
							
							
						
						
									
										45
									
								
								compositor.h
									
										
									
									
									
								
							| 
						 | 
					@ -54,15 +54,6 @@ struct wlsc_output {
 | 
				
			||||||
	struct wlsc_surface *background;
 | 
						struct wlsc_surface *background;
 | 
				
			||||||
	struct wlsc_matrix matrix;
 | 
						struct wlsc_matrix matrix;
 | 
				
			||||||
	int32_t x, y, width, height;
 | 
						int32_t x, y, width, height;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	drmModeModeInfo mode;
 | 
					 | 
				
			||||||
	uint32_t crtc_id;
 | 
					 | 
				
			||||||
	uint32_t connector_id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GLuint rbo[2];
 | 
					 | 
				
			||||||
	uint32_t fb_id[2];
 | 
					 | 
				
			||||||
	EGLImageKHR image[2];
 | 
					 | 
				
			||||||
	uint32_t current;	
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_input_device {
 | 
					struct wlsc_input_device {
 | 
				
			||||||
| 
						 | 
					@ -87,7 +78,6 @@ struct wlsc_compositor {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EGLDisplay display;
 | 
						EGLDisplay display;
 | 
				
			||||||
	EGLContext context;
 | 
						EGLContext context;
 | 
				
			||||||
	int drm_fd;
 | 
					 | 
				
			||||||
	GLuint fbo, vbo;
 | 
						GLuint fbo, vbo;
 | 
				
			||||||
	GLuint proj_uniform, tex_uniform;
 | 
						GLuint proj_uniform, tex_uniform;
 | 
				
			||||||
	struct wl_display *wl_display;
 | 
						struct wl_display *wl_display;
 | 
				
			||||||
| 
						 | 
					@ -101,28 +91,16 @@ struct wlsc_compositor {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_list surface_destroy_listener_list;
 | 
						struct wl_list surface_destroy_listener_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_event_source *term_signal_source;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* tty handling state */
 | 
					 | 
				
			||||||
	int tty_fd;
 | 
					 | 
				
			||||||
	uint32_t vt_active : 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct termios terminal_attributes;
 | 
					 | 
				
			||||||
	struct wl_event_source *tty_input_source;
 | 
					 | 
				
			||||||
	struct wl_event_source *enter_vt_source;
 | 
					 | 
				
			||||||
	struct wl_event_source *leave_vt_source;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct udev *udev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Repaint state. */
 | 
						/* Repaint state. */
 | 
				
			||||||
	struct wl_event_source *timer_source;
 | 
						struct wl_event_source *timer_source;
 | 
				
			||||||
	int repaint_needed;
 | 
						int repaint_needed;
 | 
				
			||||||
	int repaint_on_timeout;
 | 
						int repaint_on_timeout;
 | 
				
			||||||
	struct timespec previous_swap;
 | 
						struct timespec previous_swap;
 | 
				
			||||||
	uint32_t current_frame;
 | 
						uint32_t current_frame;
 | 
				
			||||||
	struct wl_event_source *drm_source;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t modifier_state;
 | 
						uint32_t modifier_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void (*present)(struct wlsc_compositor *c);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MODIFIER_CTRL	(1 << 8)
 | 
					#define MODIFIER_CTRL	(1 << 8)
 | 
				
			||||||
| 
						 | 
					@ -151,15 +129,26 @@ notify_button(struct wlsc_input_device *device, int32_t button, int32_t state);
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
notify_key(struct wlsc_input_device *device, uint32_t key, uint32_t state);
 | 
					notify_key(struct wlsc_input_device *device, uint32_t key, uint32_t state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					 | 
				
			||||||
wlsc_compositor_present_drm(struct wlsc_compositor *wlsc);
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
wlsc_compositor_init_drm(struct wlsc_compositor *ec);
 | 
					 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs);
 | 
					wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs);
 | 
				
			||||||
struct wlsc_input_device *
 | 
					struct wlsc_input_device *
 | 
				
			||||||
wlsc_input_device_create(struct wlsc_compositor *ec);
 | 
					wlsc_input_device_create(struct wlsc_compositor *ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display);
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
 | 
				
			||||||
 | 
							 int x, int y, int width, int height);
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					wlsc_input_device_init(struct wlsc_input_device *device,
 | 
				
			||||||
 | 
							       struct wlsc_compositor *ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlsc_compositor *
 | 
				
			||||||
 | 
					x11_compositor_create(struct wl_display *display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlsc_compositor *
 | 
				
			||||||
 | 
					drm_compositor_create(struct wl_display *display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
screenshooter_create(struct wlsc_compositor *ec);
 | 
					screenshooter_create(struct wlsc_compositor *ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ PKG_PROG_PKG_CONFIG()
 | 
				
			||||||
PKG_CHECK_MODULES(FFI, [libffi])
 | 
					PKG_CHECK_MODULES(FFI, [libffi])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_CHECK_MODULES(COMPOSITOR,
 | 
					PKG_CHECK_MODULES(COMPOSITOR,
 | 
				
			||||||
		  [egl gl libpng cairo gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17])
 | 
							  [egl gl libpng cairo gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17] xcb-dri2 xcb-xfixes)
 | 
				
			||||||
PKG_CHECK_MODULES(CLIENT, [egl gl cairo-gl gdk-pixbuf-2.0 glib-2.0 gobject-2.0])
 | 
					PKG_CHECK_MODULES(CLIENT, [egl gl cairo-gl gdk-pixbuf-2.0 glib-2.0 gobject-2.0])
 | 
				
			||||||
PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0])
 | 
					PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -342,6 +342,7 @@ wl_event_source_idle_remove(struct wl_event_source *source)
 | 
				
			||||||
		(struct wl_event_source_idle *) source;
 | 
							(struct wl_event_source_idle *) source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_remove(&idle_source->link);
 | 
						wl_list_remove(&idle_source->link);
 | 
				
			||||||
 | 
						free(source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue