mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	Factor out common cairo code, add blur function.
This commit is contained in:
		
							parent
							
								
									e4feb56316
								
							
						
					
					
						commit
						2f2cfae227
					
				
					 5 changed files with 244 additions and 170 deletions
				
			
		
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
					@ -45,9 +45,9 @@ libwayland.so $(compositors) :
 | 
				
			||||||
	gcc -o $@ $^ $(LDLIBS) -shared 
 | 
						gcc -o $@ $^ $(LDLIBS) -shared 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
flower_objs = flower.o wayland-glib.o
 | 
					flower_objs = flower.o wayland-glib.o
 | 
				
			||||||
pointer_objs = pointer.o wayland-glib.o
 | 
					pointer_objs = pointer.o wayland-glib.o cairo-util.o
 | 
				
			||||||
background_objs = background.o wayland-glib.o
 | 
					background_objs = background.o wayland-glib.o
 | 
				
			||||||
window_objs = window.o gears.o wayland-glib.o
 | 
					window_objs = window.o gears.o wayland-glib.o cairo-util.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(clients) : CFLAGS += $(shell pkg-config --cflags cairo glib-2.0)
 | 
					$(clients) : CFLAGS += $(shell pkg-config --cflags cairo glib-2.0)
 | 
				
			||||||
$(clients) : LDLIBS += $(shell pkg-config --libs cairo glib-2.0) -lrt
 | 
					$(clients) : LDLIBS += $(shell pkg-config --libs cairo glib-2.0) -lrt
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										176
									
								
								cairo-util.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								cairo-util.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,176 @@
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <i915_drm.h>
 | 
				
			||||||
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <cairo.h>
 | 
				
			||||||
 | 
					#include "cairo-util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct buffer *
 | 
				
			||||||
 | 
					buffer_create(int fd, int width, int height, int stride)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct buffer *buffer;
 | 
				
			||||||
 | 
						struct drm_i915_gem_create create;
 | 
				
			||||||
 | 
						struct drm_gem_flink flink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer = malloc(sizeof *buffer);
 | 
				
			||||||
 | 
						buffer->width = width;
 | 
				
			||||||
 | 
						buffer->height = height;
 | 
				
			||||||
 | 
						buffer->stride = stride;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&create, 0, sizeof(create));
 | 
				
			||||||
 | 
						create.size = height * stride;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "gem create failed: %m\n");
 | 
				
			||||||
 | 
							free(buffer);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flink.handle = create.handle;
 | 
				
			||||||
 | 
						if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "gem flink failed: %m\n");
 | 
				
			||||||
 | 
							free(buffer);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer->handle = flink.handle;
 | 
				
			||||||
 | 
						buffer->name = flink.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return buffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					buffer_destroy(struct buffer *buffer, int fd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct drm_gem_close close;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						close.handle = buffer->handle;
 | 
				
			||||||
 | 
						if (ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "gem close failed: %m\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						free(buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					buffer_data(struct buffer *buffer, int fd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct drm_i915_gem_pwrite pwrite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pwrite.handle = buffer->handle;
 | 
				
			||||||
 | 
						pwrite.offset = 0;
 | 
				
			||||||
 | 
						pwrite.size = buffer->height * buffer->stride;
 | 
				
			||||||
 | 
						pwrite.data_ptr = (uint64_t) (uintptr_t) data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "gem pwrite failed: %m\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct buffer *
 | 
				
			||||||
 | 
					buffer_create_from_cairo_surface(int fd, cairo_surface_t *surface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct buffer *buffer;
 | 
				
			||||||
 | 
						int32_t width, height, stride;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						width = cairo_image_surface_get_width(surface);
 | 
				
			||||||
 | 
						height = cairo_image_surface_get_height(surface);
 | 
				
			||||||
 | 
						stride = cairo_image_surface_get_stride(surface);
 | 
				
			||||||
 | 
						data = cairo_image_surface_get_data(surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer = buffer_create(fd, width, height, stride);
 | 
				
			||||||
 | 
						if (buffer == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (buffer_data(buffer, fd, data) < 0) {
 | 
				
			||||||
 | 
							buffer_destroy(buffer, fd);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}			
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return buffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					blur_surface(cairo_surface_t *surface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cairo_surface_t *tmp;
 | 
				
			||||||
 | 
						int32_t width, height, stride, x, y, z, w;
 | 
				
			||||||
 | 
						uint8_t *src, *dst;
 | 
				
			||||||
 | 
						uint32_t *s, *d, a, p;
 | 
				
			||||||
 | 
						int i, j, k, size = 23, half;
 | 
				
			||||||
 | 
						uint8_t kernel[100];
 | 
				
			||||||
 | 
						double f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						width = cairo_image_surface_get_width(surface);
 | 
				
			||||||
 | 
						height = cairo_image_surface_get_height(surface);
 | 
				
			||||||
 | 
						stride = cairo_image_surface_get_stride(surface);
 | 
				
			||||||
 | 
						src = cairo_image_surface_get_data(surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmp = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
 | 
				
			||||||
 | 
						dst = cairo_image_surface_get_data(tmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						half = size / 2;
 | 
				
			||||||
 | 
						a = 0;
 | 
				
			||||||
 | 
						for (i = 0; i < size; i++) {
 | 
				
			||||||
 | 
							f = (i - half);
 | 
				
			||||||
 | 
							kernel[i] = exp(- f * f / 30.0) * 80;
 | 
				
			||||||
 | 
							a += kernel[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < height; i++) {
 | 
				
			||||||
 | 
							s = (uint32_t *) (src + i * stride);
 | 
				
			||||||
 | 
							d = (uint32_t *) (dst + i * stride);
 | 
				
			||||||
 | 
							for (j = 0; j < width; j++) {
 | 
				
			||||||
 | 
								x = 0;
 | 
				
			||||||
 | 
								y = 0;
 | 
				
			||||||
 | 
								z = 0;
 | 
				
			||||||
 | 
								w = 0;
 | 
				
			||||||
 | 
								for (k = 0; k < size; k++) {
 | 
				
			||||||
 | 
									if (j - half + k < 0 || j - half + k >= width)
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									p = s[j - half + k];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									x += (p >> 24) * kernel[k];
 | 
				
			||||||
 | 
									y += ((p >> 16) & 0xff) * kernel[k];
 | 
				
			||||||
 | 
									z += ((p >> 8) & 0xff) * kernel[k];
 | 
				
			||||||
 | 
									w += (p & 0xff) * kernel[k];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < height; i++) {
 | 
				
			||||||
 | 
							s = (uint32_t *) (dst + i * stride);
 | 
				
			||||||
 | 
							d = (uint32_t *) (src + i * stride);
 | 
				
			||||||
 | 
							for (j = 0; j < width; j++) {
 | 
				
			||||||
 | 
								x = 0;
 | 
				
			||||||
 | 
								y = 0;
 | 
				
			||||||
 | 
								z = 0;
 | 
				
			||||||
 | 
								w = 0;
 | 
				
			||||||
 | 
								for (k = 0; k < size; k++) {
 | 
				
			||||||
 | 
									if (i - half + k < 0 || i - half + k >= height)
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									s = (uint32_t *) (dst + (i - half + k) * stride);
 | 
				
			||||||
 | 
									p = s[j];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									x += (p >> 24) * kernel[k];
 | 
				
			||||||
 | 
									y += ((p >> 16) & 0xff) * kernel[k];
 | 
				
			||||||
 | 
									z += ((p >> 8) & 0xff) * kernel[k];
 | 
				
			||||||
 | 
									w += (p & 0xff) * kernel[k];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cairo_surface_destroy(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								cairo-util.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								cairo-util.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					#ifndef _CAIRO_UTIL_H
 | 
				
			||||||
 | 
					#define _CAIRO_UTIL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct buffer {
 | 
				
			||||||
 | 
						int width, height, stride;
 | 
				
			||||||
 | 
						uint32_t name, handle;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct buffer *
 | 
				
			||||||
 | 
					buffer_create(int fd, int width, int height, int stride);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					buffer_destroy(struct buffer *buffer, int fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					buffer_data(struct buffer *buffer, int fd, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct buffer *
 | 
				
			||||||
 | 
					buffer_create_from_cairo_surface(int fd, cairo_surface_t *surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					blur_surface(cairo_surface_t *surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										95
									
								
								pointer.c
									
										
									
									
									
								
							
							
						
						
									
										95
									
								
								pointer.c
									
										
									
									
									
								
							| 
						 | 
					@ -2,8 +2,6 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <i915_drm.h>
 | 
					 | 
				
			||||||
#include <sys/ioctl.h>
 | 
					 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
| 
						 | 
					@ -13,64 +11,31 @@
 | 
				
			||||||
#include "wayland-client.h"
 | 
					#include "wayland-client.h"
 | 
				
			||||||
#include "wayland-glib.h"
 | 
					#include "wayland-glib.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "cairo-util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char gem_device[] = "/dev/dri/card0";
 | 
					static const char gem_device[] = "/dev/dri/card0";
 | 
				
			||||||
static const char socket_name[] = "\0wayland";
 | 
					static const char socket_name[] = "\0wayland";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
 | 
					static void
 | 
				
			||||||
 | 
					pointer_path(cairo_t *cr, int x, int y)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct drm_i915_gem_create create;
 | 
						const int end = 4, tx = 2, ty = 7, dx = 3, dy = 5;
 | 
				
			||||||
	struct drm_gem_flink flink;
 | 
						const int width = 16, height = 16;
 | 
				
			||||||
	struct drm_i915_gem_pwrite pwrite;
 | 
					 | 
				
			||||||
	int32_t width, height, stride;
 | 
					 | 
				
			||||||
	void *data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	width = cairo_image_surface_get_width(surface);
 | 
						cairo_move_to(cr, x, y);
 | 
				
			||||||
	height = cairo_image_surface_get_height(surface);
 | 
						cairo_line_to(cr, x + tx, y + ty);
 | 
				
			||||||
	stride = cairo_image_surface_get_stride(surface);
 | 
						cairo_line_to(cr, x + dx, y + dy);
 | 
				
			||||||
	data = cairo_image_surface_get_data(surface);
 | 
						cairo_line_to(cr, x + width - end, y + height);
 | 
				
			||||||
 | 
						cairo_line_to(cr, x + width, y + height - end);
 | 
				
			||||||
	memset(&create, 0, sizeof(create));
 | 
						cairo_line_to(cr, x + dy, y + dx);
 | 
				
			||||||
	create.size = height * stride;
 | 
						cairo_line_to(cr, x + ty, y + tx);
 | 
				
			||||||
 | 
						cairo_close_path(cr);
 | 
				
			||||||
	if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "gem create failed: %m\n");
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pwrite.handle = create.handle;
 | 
					 | 
				
			||||||
	pwrite.offset = 0;
 | 
					 | 
				
			||||||
	pwrite.size = height * stride;
 | 
					 | 
				
			||||||
	pwrite.data_ptr = (uint64_t) (uintptr_t) data;
 | 
					 | 
				
			||||||
	if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "gem pwrite failed: %m\n");
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	flink.handle = create.handle;
 | 
					 | 
				
			||||||
	if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "gem flink failed: %m\n");
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
	/* We need to hold on to the handle until the server has received
 | 
					 | 
				
			||||||
	 * the attach request... we probably need a confirmation event.
 | 
					 | 
				
			||||||
	 * I guess the breadcrumb idea will suffice. */
 | 
					 | 
				
			||||||
	struct drm_gem_close close;
 | 
					 | 
				
			||||||
	close.handle = create.handle;
 | 
					 | 
				
			||||||
	if (ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "gem close failed: %m\n");
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return flink.name;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *
 | 
					static void *
 | 
				
			||||||
draw_pointer(int width, int height)
 | 
					draw_pointer(int width, int height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const int d = 2, end = 6, tx = 2, ty = 7, dx = 3, dy = 5;
 | 
						const int hotspot_x = 16, hotspot_y = 16;
 | 
				
			||||||
	cairo_surface_t *surface;
 | 
						cairo_surface_t *surface;
 | 
				
			||||||
	cairo_t *cr;
 | 
						cairo_t *cr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,20 +43,17 @@ draw_pointer(int width, int height)
 | 
				
			||||||
					     width, height);
 | 
										     width, height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cr = cairo_create(surface);
 | 
						cr = cairo_create(surface);
 | 
				
			||||||
	cairo_set_line_width (cr, d);
 | 
						pointer_path(cr, hotspot_x + 3, hotspot_y + 2);
 | 
				
			||||||
	cairo_move_to(cr, d, d);
 | 
						cairo_set_line_width (cr, 2);
 | 
				
			||||||
	cairo_line_to(cr, d + tx, d + ty);
 | 
					 | 
				
			||||||
	cairo_line_to(cr, d + dx, d + dy);
 | 
					 | 
				
			||||||
	cairo_line_to(cr, width - end, height - d);
 | 
					 | 
				
			||||||
	cairo_line_to(cr, width - d, height - end);
 | 
					 | 
				
			||||||
	cairo_line_to(cr, d + dy, d + dx);
 | 
					 | 
				
			||||||
	cairo_line_to(cr, d + ty, d + tx);
 | 
					 | 
				
			||||||
	cairo_close_path(cr);
 | 
					 | 
				
			||||||
	cairo_set_source_rgb(cr, 0, 0, 0);
 | 
						cairo_set_source_rgb(cr, 0, 0, 0);
 | 
				
			||||||
	cairo_stroke_preserve(cr);
 | 
						cairo_stroke_preserve(cr);
 | 
				
			||||||
 | 
						cairo_fill(cr);
 | 
				
			||||||
 | 
						blur_surface(surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pointer_path(cr, hotspot_x, hotspot_y);
 | 
				
			||||||
 | 
						cairo_stroke_preserve(cr);
 | 
				
			||||||
	cairo_set_source_rgb(cr, 1, 1, 1);
 | 
						cairo_set_source_rgb(cr, 1, 1, 1);
 | 
				
			||||||
	cairo_fill(cr);
 | 
						cairo_fill(cr);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	cairo_destroy(cr);
 | 
						cairo_destroy(cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return surface;
 | 
						return surface;
 | 
				
			||||||
| 
						 | 
					@ -118,10 +80,10 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	struct wl_display *display;
 | 
						struct wl_display *display;
 | 
				
			||||||
	struct pointer pointer;
 | 
						struct pointer pointer;
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	uint32_t name;
 | 
					 | 
				
			||||||
	cairo_surface_t *s;
 | 
						cairo_surface_t *s;
 | 
				
			||||||
	GMainLoop *loop;
 | 
						GMainLoop *loop;
 | 
				
			||||||
	GSource *source;
 | 
						GSource *source;
 | 
				
			||||||
 | 
						struct buffer *buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fd = open(gem_device, O_RDWR);
 | 
						fd = open(gem_device, O_RDWR);
 | 
				
			||||||
	if (fd < 0) {
 | 
						if (fd < 0) {
 | 
				
			||||||
| 
						 | 
					@ -139,16 +101,15 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	source = wayland_source_new(display);
 | 
						source = wayland_source_new(display);
 | 
				
			||||||
	g_source_attach(source, NULL);
 | 
						g_source_attach(source, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pointer.width = 16;
 | 
						pointer.width = 48;
 | 
				
			||||||
	pointer.height = 16;
 | 
						pointer.height = 48;
 | 
				
			||||||
	pointer.surface = wl_display_create_surface(display);
 | 
						pointer.surface = wl_display_create_surface(display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s = draw_pointer(pointer.width, pointer.height);
 | 
						s = draw_pointer(pointer.width, pointer.height);
 | 
				
			||||||
	name = name_cairo_surface(fd, s);
 | 
						buffer = buffer_create_from_cairo_surface(fd, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_surface_attach(pointer.surface, name,
 | 
						wl_surface_attach(pointer.surface, buffer->name,
 | 
				
			||||||
			  pointer.width, pointer.height,
 | 
								  buffer->width, buffer->height, buffer->stride);
 | 
				
			||||||
			  cairo_image_surface_get_stride(s));
 | 
					 | 
				
			||||||
	wl_surface_map(pointer.surface, 512, 384, pointer.width, pointer.height);
 | 
						wl_surface_map(pointer.surface, 512, 384, pointer.width, pointer.height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_display_set_event_handler(display, event_handler, &pointer);
 | 
						wl_display_set_event_handler(display, event_handler, &pointer);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										115
									
								
								window.c
									
										
									
									
									
								
							
							
						
						
									
										115
									
								
								window.c
									
										
									
									
									
								
							| 
						 | 
					@ -2,8 +2,6 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <i915_drm.h>
 | 
					 | 
				
			||||||
#include <sys/ioctl.h>
 | 
					 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
| 
						 | 
					@ -16,7 +14,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "wayland-client.h"
 | 
					#include "wayland-client.h"
 | 
				
			||||||
#include "wayland-glib.h"
 | 
					#include "wayland-glib.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gears.h"
 | 
					#include "gears.h"
 | 
				
			||||||
 | 
					#include "cairo-util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char gem_device[] = "/dev/dri/card0";
 | 
					static const char gem_device[] = "/dev/dri/card0";
 | 
				
			||||||
static const char socket_name[] = "\0wayland";
 | 
					static const char socket_name[] = "\0wayland";
 | 
				
			||||||
| 
						 | 
					@ -27,103 +27,6 @@ static void die(const char *msg)
 | 
				
			||||||
	exit(EXIT_FAILURE);
 | 
						exit(EXIT_FAILURE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct buffer {
 | 
					 | 
				
			||||||
	int width, height, stride;
 | 
					 | 
				
			||||||
	uint32_t name, handle;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct buffer *
 | 
					 | 
				
			||||||
buffer_create(int fd, int width, int height, int stride)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct buffer *buffer;
 | 
					 | 
				
			||||||
	struct drm_i915_gem_create create;
 | 
					 | 
				
			||||||
	struct drm_gem_flink flink;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buffer = malloc(sizeof *buffer);
 | 
					 | 
				
			||||||
	buffer->width = width;
 | 
					 | 
				
			||||||
	buffer->height = height;
 | 
					 | 
				
			||||||
	buffer->stride = stride;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(&create, 0, sizeof(create));
 | 
					 | 
				
			||||||
	create.size = height * stride;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "gem create failed: %m\n");
 | 
					 | 
				
			||||||
		free(buffer);
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	flink.handle = create.handle;
 | 
					 | 
				
			||||||
	if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "gem flink failed: %m\n");
 | 
					 | 
				
			||||||
		free(buffer);
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buffer->handle = flink.handle;
 | 
					 | 
				
			||||||
	buffer->name = flink.name;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return buffer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int
 | 
					 | 
				
			||||||
buffer_destroy(struct buffer *buffer, int fd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct drm_gem_close close;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	close.handle = buffer->handle;
 | 
					 | 
				
			||||||
	if (ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "gem close failed: %m\n");
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	free(buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int
 | 
					 | 
				
			||||||
buffer_data(struct buffer *buffer, int fd, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct drm_i915_gem_pwrite pwrite;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pwrite.handle = buffer->handle;
 | 
					 | 
				
			||||||
	pwrite.offset = 0;
 | 
					 | 
				
			||||||
	pwrite.size = buffer->height * buffer->stride;
 | 
					 | 
				
			||||||
	pwrite.data_ptr = (uint64_t) (uintptr_t) data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "gem pwrite failed: %m\n");
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct buffer *
 | 
					 | 
				
			||||||
buffer_create_from_cairo_surface(int fd, cairo_surface_t *surface)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct buffer *buffer;
 | 
					 | 
				
			||||||
	int32_t width, height, stride;
 | 
					 | 
				
			||||||
	void *data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	width = cairo_image_surface_get_width(surface);
 | 
					 | 
				
			||||||
	height = cairo_image_surface_get_height(surface);
 | 
					 | 
				
			||||||
	stride = cairo_image_surface_get_stride(surface);
 | 
					 | 
				
			||||||
	data = cairo_image_surface_get_data(surface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buffer = buffer_create(fd, width, height, stride);
 | 
					 | 
				
			||||||
	if (buffer == NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (buffer_data(buffer, fd, data) < 0) {
 | 
					 | 
				
			||||||
		buffer_destroy(buffer, fd);
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}			
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return buffer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct window {
 | 
					struct window {
 | 
				
			||||||
	struct wl_surface *surface;
 | 
						struct wl_surface *surface;
 | 
				
			||||||
	int x, y, width, height;
 | 
						int x, y, width, height;
 | 
				
			||||||
| 
						 | 
					@ -172,13 +75,23 @@ draw_window(void *data)
 | 
				
			||||||
	const static char title[] = "Wayland First Post";
 | 
						const static char title[] = "Wayland First Post";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
 | 
						surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
 | 
				
			||||||
					     window->width, window->height);
 | 
										     window->width + 32, window->height + 32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	outline = cairo_pattern_create_rgb(0.1, 0.1, 0.1);
 | 
						outline = cairo_pattern_create_rgb(0.1, 0.1, 0.1);
 | 
				
			||||||
	bright = cairo_pattern_create_rgb(0.6, 0.6, 0.6);
 | 
						bright = cairo_pattern_create_rgb(0.6, 0.6, 0.6);
 | 
				
			||||||
	dim = cairo_pattern_create_rgb(0.4, 0.4, 0.4);
 | 
						dim = cairo_pattern_create_rgb(0.4, 0.4, 0.4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cr = cairo_create(surface);
 | 
						cr = cairo_create(surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cairo_translate(cr, 16 + 5, 16 + 3);
 | 
				
			||||||
 | 
						cairo_set_line_width (cr, border);
 | 
				
			||||||
 | 
						cairo_set_source_rgba(cr, 0, 0, 0, 0.5);
 | 
				
			||||||
 | 
						rounded_rect(cr, 1, 1, window->width - 1, window->height - 1, radius);
 | 
				
			||||||
 | 
						cairo_stroke_preserve(cr);
 | 
				
			||||||
 | 
						cairo_fill(cr);
 | 
				
			||||||
 | 
						blur_surface(surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cairo_translate(cr, -5, -3);
 | 
				
			||||||
	cairo_set_line_width (cr, border);
 | 
						cairo_set_line_width (cr, border);
 | 
				
			||||||
	rounded_rect(cr, 1, 1, window->width - 1, window->height - 1, radius);
 | 
						rounded_rect(cr, 1, 1, window->width - 1, window->height - 1, radius);
 | 
				
			||||||
	cairo_set_source(cr, outline);
 | 
						cairo_set_source(cr, outline);
 | 
				
			||||||
| 
						 | 
					@ -301,7 +214,7 @@ event_handler(struct wl_display *display,
 | 
				
			||||||
			window->x = window->drag_x + arg1;
 | 
								window->x = window->drag_x + arg1;
 | 
				
			||||||
			window->y = window->drag_y + arg2;
 | 
								window->y = window->drag_y + arg2;
 | 
				
			||||||
			wl_surface_map(window->surface, window->x, window->y,
 | 
								wl_surface_map(window->surface, window->x, window->y,
 | 
				
			||||||
				       window->width, window->height);
 | 
									       window->buffer->width, window->buffer->height);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case WINDOW_RESIZING_LOWER_RIGHT:
 | 
							case WINDOW_RESIZING_LOWER_RIGHT:
 | 
				
			||||||
			window->width = window->drag_x + arg1;
 | 
								window->width = window->drag_x + arg1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue