mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-10-29 05:40:16 -04:00 
			
		
		
		
	Add an EGL compositor. Still pretty lame.
This commit is contained in:
		
							parent
							
								
									427524aedf
								
							
						
					
					
						commit
						16eb675399
					
				
					 3 changed files with 261 additions and 5 deletions
				
			
		
							
								
								
									
										6
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -3,10 +3,12 @@ LDLIBS += $(shell pkg-config --libs libffi libdrm) | |||
| 
 | ||||
| all : wayland client | ||||
| 
 | ||||
| wayland_objs = wayland.o event-loop.o connection.o hash.o compositor.o | ||||
| wayland_objs = wayland.o event-loop.o connection.o hash.o egl-compositor.o | ||||
| wayland : CFLAGS += -I../eagle | ||||
| wayland : LDLIBS += -L../eagle -leagle -ldl | ||||
| 
 | ||||
| wayland : $(wayland_objs) | ||||
| 	gcc -o $@ $(wayland_objs) $(LDLIBS) | ||||
| 	gcc -o $@ $(LDLIBS) $(wayland_objs) | ||||
| 
 | ||||
| libwayland_objs = wayland-client.o connection.o | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										9
									
								
								client.c
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								client.c
									
										
									
									
									
								
							|  | @ -112,7 +112,7 @@ int main(int argc, char *argv[]) | |||
| { | ||||
| 	struct wl_display *display; | ||||
| 	struct wl_surface *surface; | ||||
| 	const int x = 400, y = 200, width = 300, height = 300; | ||||
| 	const int x = 200, y = 100, width = 300, height = 300; | ||||
| 	int fd, i, ret; | ||||
| 	uint32_t name, mask; | ||||
| 	cairo_surface_t *s; | ||||
|  | @ -141,9 +141,12 @@ int main(int argc, char *argv[]) | |||
| 			  cairo_image_surface_get_stride(s)); | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	while (ret = poll(p, 1, 40), ret >= 0) { | ||||
| 	while (ret = poll(p, 1, 20), ret >= 0) { | ||||
| 		if (ret == 0) { | ||||
| 			wl_surface_map(surface, x + i, y + i, width, height); | ||||
| 			wl_surface_map(surface,  | ||||
| 				       x + cos(i / 10.0) * 50, | ||||
| 				       y + sin(i / 10.0) * 50, | ||||
| 				       width, height); | ||||
| 			i++; | ||||
| 			continue; | ||||
| 		} | ||||
|  |  | |||
							
								
								
									
										251
									
								
								egl-compositor.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								egl-compositor.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,251 @@ | |||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <i915_drm.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/mman.h> | ||||
| #include <fcntl.h> | ||||
| #include <unistd.h> | ||||
| #include <linux/fb.h> | ||||
| 
 | ||||
| #include "wayland.h" | ||||
| 
 | ||||
| #include <GL/gl.h> | ||||
| #include <eagle.h> | ||||
| 
 | ||||
| #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) | ||||
| 
 | ||||
| struct egl_compositor { | ||||
| 	struct wl_compositor base; | ||||
| 	EGLDisplay display; | ||||
| 	EGLSurface surface; | ||||
| 	EGLContext context; | ||||
| 	int gem_fd; | ||||
| }; | ||||
| 
 | ||||
| struct surface_data { | ||||
| 	uint32_t handle; | ||||
| 	int32_t width, height, stride; | ||||
| 	GLuint texture; | ||||
| }; | ||||
| 
 | ||||
| void notify_surface_create(struct wl_compositor *compositor, | ||||
| 			   struct wl_surface *surface) | ||||
| { | ||||
| 	struct surface_data *sd; | ||||
| 
 | ||||
| 	sd = malloc(sizeof *sd); | ||||
| 	if (sd == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	sd->handle = 0; | ||||
| 	wl_surface_set_data(surface, sd); | ||||
| 
 | ||||
| 	glGenTextures(1, &sd->texture); | ||||
| } | ||||
| 				    | ||||
| void notify_surface_destroy(struct wl_compositor *compositor, | ||||
| 			    struct wl_surface *surface) | ||||
| { | ||||
| 	struct egl_compositor *ec = (struct egl_compositor *) compositor; | ||||
| 	struct surface_data *sd; | ||||
| 	struct drm_gem_close close_arg; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	sd = wl_surface_get_data(surface); | ||||
| 	if (sd == NULL || sd->handle == 0) | ||||
| 		return; | ||||
| 	 | ||||
| 	close_arg.handle = sd->handle; | ||||
| 	ret = ioctl(ec->gem_fd, DRM_IOCTL_GEM_CLOSE, &close_arg); | ||||
| 	if (ret != 0) { | ||||
| 		fprintf(stderr, "failed to gem_close handle %d: %m\n", sd->handle); | ||||
| 	} | ||||
| 
 | ||||
| 	glDeleteTextures(1, &sd->texture); | ||||
| 
 | ||||
| 	free(sd); | ||||
| } | ||||
| 
 | ||||
| void notify_surface_attach(struct wl_compositor *compositor, | ||||
| 			   struct wl_surface *surface, uint32_t name,  | ||||
| 			   uint32_t width, uint32_t height, uint32_t stride) | ||||
| { | ||||
| 	struct egl_compositor *ec = (struct egl_compositor *) compositor; | ||||
| 	struct surface_data *sd; | ||||
| 	struct drm_gem_open open_arg; | ||||
| 	struct drm_gem_close close_arg; | ||||
| 	struct drm_i915_gem_pread pread; | ||||
| 	void *data; | ||||
| 	uint32_t size; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	sd = wl_surface_get_data(surface); | ||||
| 	if (sd == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (sd->handle != 0) { | ||||
| 		close_arg.handle = sd->handle; | ||||
| 		ret = ioctl(ec->gem_fd, DRM_IOCTL_GEM_CLOSE, &close_arg); | ||||
| 		if (ret != 0) { | ||||
| 			fprintf(stderr, "failed to gem_close name %d: %m\n", name); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	open_arg.name = name; | ||||
| 	ret = ioctl(ec->gem_fd, DRM_IOCTL_GEM_OPEN, &open_arg); | ||||
| 	if (ret != 0) { | ||||
| 		fprintf(stderr, "failed to gem_open name %d, fd=%d: %m\n", name, ec->gem_fd); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	sd->handle = open_arg.handle; | ||||
| 	sd->width = width; | ||||
| 	sd->height = height; | ||||
| 	sd->stride = stride; | ||||
| 
 | ||||
| 	size = sd->height * sd->stride; | ||||
| 	data = malloc(size); | ||||
| 	if (data == NULL) { | ||||
| 		fprintf(stderr, "swap buffers malloc failed\n"); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	pread.handle = sd->handle; | ||||
| 	pread.pad = 0; | ||||
| 	pread.offset = 0; | ||||
| 	pread.size = size; | ||||
| 	pread.data_ptr = (long) data; | ||||
| 
 | ||||
| 	if (ioctl(ec->gem_fd, DRM_IOCTL_I915_GEM_PREAD, &pread)) { | ||||
| 		fprintf(stderr, "gem pread failed"); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	glBindTexture(GL_TEXTURE_2D, sd->texture); | ||||
| 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | ||||
| 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT); | ||||
| 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
| 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
| 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, | ||||
| 		     GL_BGRA, GL_UNSIGNED_BYTE, data); | ||||
| 
 | ||||
| 	free(data); | ||||
| } | ||||
| 
 | ||||
| void notify_surface_map(struct wl_compositor *compositor, | ||||
| 			struct wl_surface *surface, struct wl_map *map) | ||||
| { | ||||
| 	struct egl_compositor *ec = (struct egl_compositor *) compositor; | ||||
| 	struct surface_data *sd; | ||||
| 	GLint vertices[12] = { | ||||
| 		map->x, map->y, 0.0, | ||||
| 		map->x, map->y + map->height, 0.0, | ||||
| 		map->x + map->width, map->y + map->height, 0.0, | ||||
| 		map->x + map->width, map->y, 0.0 | ||||
| 	}; | ||||
| 	GLint tex_coords[8] = { | ||||
| 		1, 0, | ||||
| 		1, 1, | ||||
| 		0, 1, | ||||
| 		0, 0 | ||||
| 	}; | ||||
| 	GLuint indices[4] = { 0, 1, 2, 3 }; | ||||
| 
 | ||||
| 	/* This part is where we actually copy the buffer to screen.
 | ||||
| 	 * Needs to be part of the repaint loop, not in the notify_map | ||||
| 	 * handler. */ | ||||
| 
 | ||||
| 	sd = wl_surface_get_data(surface); | ||||
| 	if (sd == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	glClear(GL_COLOR_BUFFER_BIT);  | ||||
| 	glBindTexture(GL_TEXTURE_2D, sd->texture); | ||||
| 	glEnable(GL_TEXTURE_2D); | ||||
| 	glEnable(GL_BLEND); | ||||
| 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
| 
 | ||||
| 	glEnableClientState(GL_VERTEX_ARRAY); | ||||
| 	glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||||
| 	glVertexPointer(3, GL_INT, 0, vertices); | ||||
| 	glTexCoordPointer(2, GL_INT, 0, tex_coords); | ||||
| 	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, indices); | ||||
| 
 | ||||
| 	glFlush(); | ||||
| 
 | ||||
| 	eglSwapBuffers(ec->display, ec->surface); | ||||
| } | ||||
| 
 | ||||
| struct wl_compositor_interface interface = { | ||||
| 	notify_surface_create, | ||||
| 	notify_surface_destroy, | ||||
| 	notify_surface_attach, | ||||
| 	notify_surface_map | ||||
| }; | ||||
| 
 | ||||
| static const char gem_device[] = "/dev/dri/card0"; | ||||
| 
 | ||||
| struct wl_compositor * | ||||
| wl_compositor_create(void) | ||||
| { | ||||
| 	EGLConfig configs[64]; | ||||
| 	EGLint major, minor, count; | ||||
| 	struct egl_compositor *ec; | ||||
| 	const int width = 800, height = 600; | ||||
| 
 | ||||
| 	ec = malloc(sizeof *ec); | ||||
| 	if (ec == NULL) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	ec->base.interface = &interface; | ||||
| 
 | ||||
| 	ec->display = eglCreateDisplay(gem_device, "i965"); | ||||
| 	if (ec->display == NULL) { | ||||
| 		fprintf(stderr, "failed to create display\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!eglInitialize(ec->display, &major, &minor)) { | ||||
| 		fprintf(stderr, "failed to initialize display\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!eglGetConfigs(ec->display, configs, ARRAY_LENGTH(configs), &count)) { | ||||
| 		fprintf(stderr, "failed to get configs\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	ec->surface = eglCreateSurface(ec->display, configs[24], 0, 0, width, height); | ||||
| 	if (ec->surface == NULL) { | ||||
| 		fprintf(stderr, "failed to create surface\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	ec->context = eglCreateContext(ec->display, configs[24], NULL, NULL); | ||||
| 	if (ec->context == NULL) { | ||||
| 		fprintf(stderr, "failed to create context\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!eglMakeCurrent(ec->display, ec->surface, ec->surface, ec->context)) { | ||||
| 		fprintf(stderr, "failed to make context current\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	glViewport(0, 0, width, height); | ||||
| 	glMatrixMode(GL_PROJECTION); | ||||
| 	glLoadIdentity(); | ||||
| 	glOrtho(0, width, height, 0, 0, 1000.0); | ||||
| 	glMatrixMode(GL_MODELVIEW); | ||||
| 	glClearColor(0.0, 0.1, 0.3, 0.0); | ||||
| 
 | ||||
| 	ec->gem_fd = open(gem_device, O_RDWR); | ||||
| 	if (ec->gem_fd < 0) { | ||||
| 		fprintf(stderr, "failed to open drm device\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return &ec->base; | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kristian Høgsberg
						Kristian Høgsberg