[PATCH 2/3] Use generic buffers for pointer images instead of drm buffers

Yuval Fledel yuvalfl at gmail.com
Mon Nov 29 11:39:07 PST 2010


EGLImageKHR can only be used with current mesa if DRM is
present. This is a too strict requirement for Wayland.
This patch will stop using EGLImageKHR for pointer images.

This has the downside of having to load the pointer image from
RAM every time the pointer changes, but since it doesn't happen
too often, and the cpu is already involved in this act, it shouldn't
degrade performance. On the upside, it prepares for using Wayland
in non-drm environments.

---
 compositor/compositor.c |   53 +++++++++++++++++++++++++---------------------
 compositor/compositor.h |   20 ++++++-----------
 compositor/drm.c        |    5 ++++
 compositor/shm.c        |   45 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 86 insertions(+), 37 deletions(-)

diff --git a/compositor/compositor.c b/compositor/compositor.c
index ff24224..e9acbd3 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -171,33 +171,49 @@ destroy_surface(struct wl_resource *resource,
struct wl_client *client)
 	wlsc_compositor_schedule_repaint(compositor);
 }

-static int
-texture_from_png(const char *filename, int width, int height)
+static struct wl_buffer *
+load_png(struct wlsc_compositor *ec, const char *filename,
+	 int width, int height)
 {
 	GdkPixbuf *pixbuf;
 	GError *error = NULL;
-	void *data;
-	GLenum format;
+	void *data, *data2;
+	struct wl_visual *format;
+	struct wl_buffer *buffer;
+	int stride;

 	pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
 						   width, height,
 						   FALSE, &error);
 	if (error != NULL)
-		return -1;
+		return NULL;

 	data = gdk_pixbuf_get_pixels(pixbuf);
+ 	stride = gdk_pixbuf_get_rowstride(pixbuf);

 	if (gdk_pixbuf_get_has_alpha(pixbuf))
-		format = GL_RGBA;
+		format = &ec->argb_visual;
 	else
-		format = GL_RGB;
+		format = &ec->rgb_visual;
+
+	data2 = malloc(stride * height);
+	if (data2 == NULL) {
+		gdk_pixbuf_unref(pixbuf);
+		return NULL;
+	}
+	memcpy(data2, data, stride * height);

-	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
-			format, GL_UNSIGNED_BYTE, data);
+	buffer = wl_ram_buffer_create(&ec->base, width, height, stride, format,
+				      data2);

 	gdk_pixbuf_unref(pixbuf);

-	return 0;
+	if (buffer == NULL) {
+		free(data2);
+		return NULL;
+	}
+
+	return buffer;
 }

 static const struct {
@@ -221,25 +237,14 @@ static void
 create_pointer_images(struct wlsc_compositor *ec)
 {
 	int i, count;
-	GLuint texture;
 	const int width = 32, height = 32;

-	glGenTextures(1, &texture);
-	glBindTexture(GL_TEXTURE_2D, texture);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
 	count = ARRAY_LENGTH(pointer_images);
 	ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers);
 	for (i = 0; i < count; i++) {
 		ec->pointer_buffers[i] =
-			wlsc_drm_buffer_create(ec, width, height,
-					       &ec->argb_visual);
-		glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
-					     ec->pointer_buffers[i]->image);
-		texture_from_png(pointer_images[i].filename, width, height);
+			load_png(ec, pointer_images[i].filename,
+				 width, height);
 	}
 }

@@ -473,7 +478,7 @@ wlsc_input_device_set_pointer_image(struct
wlsc_input_device *device,
 	struct wlsc_compositor *compositor = device->ec;

 	wlsc_input_device_attach(device,
-				 &compositor->pointer_buffers[type]->base,
+				 compositor->pointer_buffers[type],
 				 pointer_images[type].hotspot_x,
 				 pointer_images[type].hotspot_y);
 }
diff --git a/compositor/compositor.h b/compositor/compositor.h
index 4280a33..a15a29b 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -40,6 +40,7 @@ struct wlsc_matrix {
 };

 struct wlsc_surface;
+struct wlsc_drm_buffer;
 struct tty_evdev;

 struct wlsc_listener {
@@ -120,21 +121,10 @@ struct wlsc_drm {
 	char *filename;
 };

-struct wlsc_drm_buffer {
-	struct wl_buffer base;
-	EGLImageKHR image;
-};
-
 struct wlsc_shm {
 	struct wl_object base;
 };

-struct wlsc_shm_buffer {
-	struct wl_buffer base;
-	int32_t stride;
-	void *data;
-};
-
 struct wlsc_compositor {
 	struct wl_compositor base;
 	struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual;
@@ -145,7 +135,7 @@ struct wlsc_compositor {
 	EGLContext context;
 	GLuint fbo, vbo;
 	GLuint proj_uniform, tex_uniform;
-	struct wlsc_drm_buffer **pointer_buffers;
+	struct wl_buffer **pointer_buffers;
 	struct wl_display *wl_display;

 	/* We implement the shell interface. */
@@ -226,9 +216,13 @@ int
 wlsc_shm_init(struct wlsc_compositor *ec);

 struct wl_buffer *
-wl_buffer_create_drm(struct wlsc_compositor *compositor,
+wl_drm_buffer_create(struct wlsc_compositor *compositor,
 		     struct wl_visual *visual);

+struct wl_buffer *
+wl_ram_buffer_create(struct wl_compositor *c, int32_t width, int32_t height,
+		     uint32_t stride, struct wl_visual *visual, void *data);
+
 /* Backends */

 struct wlsc_compositor *
diff --git a/compositor/drm.c b/compositor/drm.c
index 1fe5fa5..982e697 100644
--- a/compositor/drm.c
+++ b/compositor/drm.c
@@ -22,6 +22,11 @@

 #include "compositor.h"

+struct wlsc_drm_buffer {
+	struct wl_buffer base;
+	EGLImageKHR image;
+};
+
 static void
 drm_authenticate(struct wl_client *client,
 		 struct wl_drm *drm_base, uint32_t id)
diff --git a/compositor/shm.c b/compositor/shm.c
index cdade52..5a58ad9 100644
--- a/compositor/shm.c
+++ b/compositor/shm.c
@@ -24,6 +24,12 @@

 #include "compositor.h"

+struct wlsc_shm_buffer {
+	struct wl_buffer base;
+	int32_t stride;
+	void *data;
+};
+
 static void
 destroy_buffer(struct wl_resource *resource, struct wl_client *client)
 {
@@ -147,6 +153,45 @@ const static struct wl_shm_interface shm_interface = {
 	shm_create_buffer
 };

+static void
+wl_ram_destroy_buffer(struct wl_resource *resource, struct wl_client *client)
+{
+	struct wlsc_shm_buffer *buffer =
+		container_of(resource, struct wlsc_shm_buffer, base.base);
+
+	free(buffer->data);
+	free(buffer);
+}
+
+struct wl_buffer *
+wl_ram_buffer_create(struct wl_compositor *c, int32_t width, int32_t height,
+		uint32_t stride, struct wl_visual *visual, void *data)
+{
+	struct wlsc_shm_buffer *buffer;
+
+	buffer = calloc(1, sizeof *buffer);
+	if (buffer == NULL) {
+		return NULL;
+	}
+
+	buffer->base.compositor = c;
+	buffer->base.width = width;
+	buffer->base.height = height;
+	buffer->base.visual = visual;
+	buffer->base.attach = shm_buffer_attach;
+	buffer->base.damage = shm_buffer_damage;
+	buffer->stride = stride;
+	buffer->data = data;
+
+	buffer->base.base.base.id = 0;
+	buffer->base.base.base.interface = NULL;
+	buffer->base.base.base.implementation = NULL;
+
+	buffer->base.base.destroy = wl_ram_destroy_buffer;
+
+	return &buffer->base;
+}
+
 int
 wlsc_shm_init(struct wlsc_compositor *ec)
 {
-- 
1.7.1


More information about the wayland-devel mailing list