[RFC] compositor: add dpms and backlight support

Tiago Vignatti tiago.vignatti at intel.com
Tue Feb 28 03:52:21 PST 2012


- hotplug doesn't work; it's easy fix though.
- DPMS off only kicks in when wscreensaver is launched, cause then the
  compositor will trigger the second call to lock(), inside shell. It works
  anyway with the current wscreensaver broken.
- for backlight, we're using the changes I've done here:
	http://cgit.freedesktop.org/~vignatti/libbacklight/commit/

There's a couple of things to evaluate now, but one is the API we're using now
for libbacklight. You will see that the application is encharged of setting
the connector udev handler and passing also the connector_type, which will be
used internally as heuristic to find the device. This is very simple API and
accommodates pretty well with Weston. It's leaving the burden of discovering
and probing the device for the application itself, which in case of Weston is
great because it was already done for other reasons.

Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
---

 configure.ac             |    2 +-
 src/compositor-drm.c     |   98 +++++++++++++++++++++++++++++++++++++++++----
 src/compositor-openwfd.c |    2 +
 src/compositor-wayland.c |    2 +
 src/compositor-x11.c     |    2 +
 src/compositor.c         |   14 +++++++
 src/compositor.h         |    2 +
 src/shell.c              |   36 ++++++++++++++++-
 8 files changed, 146 insertions(+), 12 deletions(-)

diff --git a/configure.ac b/configure.ac
index ba42a04..6b54bb3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,7 +73,7 @@ AC_ARG_ENABLE(drm-compositor, [  --enable-drm-compositor],,
 AM_CONDITIONAL(ENABLE_DRM_COMPOSITOR, test x$enable_drm_compositor = xyes)
 if test x$enable_drm_compositor = xyes; then
   AC_DEFINE([BUILD_DRM_COMPOSITOR], [1], [Build the DRM compositor])
-  PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm])
+  PKG_CHECK_MODULES(DRM_COMPOSITOR, [libbacklight libudev >= 136 libdrm >= 2.4.30 gbm])
 fi
 
 
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 38ff02b..1d5d013 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -35,6 +35,7 @@
 #include <drm_fourcc.h>
 
 #include <gbm.h>
+#include <libbacklight.h>
 
 #include "compositor.h"
 #include "evdev.h"
@@ -86,6 +87,7 @@ struct drm_output {
 	struct wl_listener scanout_buffer_destroy_listener;
 	struct wl_buffer *pending_scanout_buffer;
 	struct wl_listener pending_scanout_buffer_destroy_listener;
+	struct backlight *backlight;
 };
 
 /*
@@ -697,6 +699,9 @@ drm_output_destroy(struct weston_output *output_base)
 	drmModeCrtcPtr origcrtc = output->original_crtc;
 	int i;
 
+	if (output->backlight)
+		backlight_destroy(output->backlight);
+
 	/* Turn off hardware cursor */
 	drm_output_set_cursor(&output->base, NULL);
 
@@ -907,11 +912,76 @@ sprite_handle_pending_buffer_destroy(struct wl_listener *listener,
 	sprite->pending_surface = NULL;
 }
 
+static void
+drm_set_backlight(struct weston_output *output_base, uint32_t up_down)
+{
+	struct drm_output *output = (struct drm_output *) output_base;
+	long brightness;
+
+	if (!output->backlight)
+		return;
+
+	/* I know, very very rudimentary logic for turning brighter/darker.
+	 * Maybe we should normalize brightness value to have a scale say from
+	 * 1 to 10 or something. */
+	brightness = backlight_get_brightness(output->backlight);
+	if (up_down == 1)
+		brightness++;
+	else if (up_down == -1)
+		brightness--;
+	else
+		return;
+
+	if (brightness > backlight_get_max_brightness(output->backlight) ||
+	    brightness < 0)
+		return;
+
+	backlight_set_brightness(output->backlight, brightness);
+	fprintf(stderr, "setting brightness to: %ld\n", brightness);
+}
+
+static void
+drm_set_dpms(struct weston_output *output_base, uint32_t state)
+{
+	struct drm_output *output = (struct drm_output *) output_base;
+	struct weston_compositor *ec = output_base->compositor;
+	struct drm_compositor *c = (struct drm_compositor *) ec;
+	drmModeConnectorPtr connector;
+	int i;
+
+	connector = drmModeGetConnector(c->drm.fd, output->connector_id);
+	if (!connector)
+		return;
+
+	if (connector->connection == DRM_MODE_DISCONNECTED)
+		return;
+
+	for (i = 0; i < connector->count_props; i++) {
+		drmModePropertyPtr props;
+		props = drmModeGetProperty(c->drm.fd, connector->props[i]);
+		if (!props)
+			continue;
+
+		if (!strcmp(props->name, "DPMS")) {
+			drmModeConnectorSetProperty(c->drm.fd,
+					connector->connector_id,
+					props->prop_id,
+					state);
+			fprintf(stderr, "setting dpms state to: %d\n", state);
+			drmModeFreeProperty(props);
+			drmModeFreeConnector(connector);
+			return;
+		}
+		drmModeFreeProperty(props);
+	}
+	drmModeFreeConnector(connector);
+}
+
 static int
 create_output_for_connector(struct drm_compositor *ec,
 			    drmModeRes *resources,
 			    drmModeConnector *connector,
-			    int x, int y)
+			    int x, int y, struct udev_device *drm_device)
 {
 	struct drm_output *output;
 	struct drm_mode *drm_mode, *next;
@@ -1026,6 +1096,12 @@ create_output_for_connector(struct drm_compositor *ec,
 		goto err_fb;
 	}
 
+	output->backlight = backlight_init(drm_device,
+					   connector->connector_type);
+	if (!output->backlight) {
+		fprintf(stderr, "failed to initiate backlight control\n");
+	}
+
 	weston_output_init(&output->base, &ec->base, x, y,
 			 connector->mmWidth, connector->mmHeight, 0);
 
@@ -1040,6 +1116,8 @@ create_output_for_connector(struct drm_compositor *ec,
 	output->base.repaint = drm_output_repaint;
 	output->base.destroy = drm_output_destroy;
 	output->base.assign_planes = drm_assign_planes;
+	output->base.set_backlight = drm_set_backlight;
+	output->base.set_dpms = drm_set_dpms;
 
 	return 0;
 
@@ -1148,7 +1226,8 @@ destroy_sprites(struct drm_compositor *compositor)
 }
 
 static int
-create_outputs(struct drm_compositor *ec, int option_connector)
+create_outputs(struct drm_compositor *ec, int option_connector,
+	       struct udev_device *drm_device)
 {
 	drmModeConnector *connector;
 	drmModeRes *resources;
@@ -1178,7 +1257,8 @@ create_outputs(struct drm_compositor *ec, int option_connector)
 		    (option_connector == 0 ||
 		     connector->connector_id == option_connector)) {
 			if (create_output_for_connector(ec, resources,
-							connector, x, y) < 0) {
+							connector, x, y,
+							drm_device) < 0) {
 				drmModeFreeConnector(connector);
 				continue;
 			}
@@ -1202,7 +1282,7 @@ create_outputs(struct drm_compositor *ec, int option_connector)
 }
 
 static void
-update_outputs(struct drm_compositor *ec)
+update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
 {
 	drmModeConnector *connector;
 	drmModeRes *resources;
@@ -1245,7 +1325,8 @@ update_outputs(struct drm_compositor *ec)
 				x = 0;
 			y = 0;
 			create_output_for_connector(ec, resources,
-						    connector, x, y);
+						    connector, x, y,
+						    drm_device);
 			printf("connector %d connected\n", connector_id);
 
 		}
@@ -1301,7 +1382,7 @@ udev_drm_event(int fd, uint32_t mask, void *data)
 	event = udev_monitor_receive_device(ec->udev_monitor);
 
 	if (udev_event_is_hotplug(event))
-		update_outputs(ec);
+		update_outputs(ec, event);
 
 	udev_device_unref(event);
 
@@ -1469,8 +1550,6 @@ drm_compositor_create(struct wl_display *display,
 		return NULL;
 	}
 
-	udev_device_unref(drm_device);
-
 	ec->base.destroy = drm_destroy;
 
 	ec->base.focus = 1;
@@ -1487,11 +1566,12 @@ drm_compositor_create(struct wl_display *display,
 	wl_list_init(&ec->sprite_list);
 	create_sprites(ec);
 
-	if (create_outputs(ec, connector) < 0) {
+	if (create_outputs(ec, connector, drm_device) < 0) {
 		fprintf(stderr, "failed to create output for %s\n", path);
 		return NULL;
 	}
 
+	udev_device_unref(drm_device);
 	udev_enumerate_unref(e);
 	path = NULL;
 
diff --git a/src/compositor-openwfd.c b/src/compositor-openwfd.c
index 8dce304..eae1e66 100644
--- a/src/compositor-openwfd.c
+++ b/src/compositor-openwfd.c
@@ -407,6 +407,8 @@ create_output_for_port(struct wfd_compositor *ec,
 	output->base.set_hardware_cursor = wfd_output_set_cursor;
 	output->base.destroy = wfd_output_destroy;
 	output->base.assign_planes = NULL;
+	output->base.set_backlight = NULL;
+	output->base.set_dpms = NULL;
 
 	wl_list_insert(ec->base.output_list.prev, &output->base.link);
 
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index a42e76f..f8b5a32 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -435,6 +435,8 @@ wayland_compositor_create_output(struct wayland_compositor *c,
 	output->base.repaint = wayland_output_repaint;
 	output->base.destroy = wayland_output_destroy;
 	output->base.assign_planes = NULL;
+	output->base.set_backlight = NULL;
+	output->base.set_dpms = NULL;
 
 	wl_list_insert(c->base.output_list.prev, &output->base.link);
 
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 7243329..53998d2 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -441,6 +441,8 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
 	output->base.repaint = x11_output_repaint;
 	output->base.destroy = x11_output_destroy;
 	output->base.assign_planes = NULL;
+	output->base.set_backlight = NULL;
+	output->base.set_dpms = NULL;
 
 	wl_list_insert(c->base.output_list.prev, &output->base.link);
 
diff --git a/src/compositor.c b/src/compositor.c
index b12c583..6943b41 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1362,12 +1362,25 @@ weston_compositor_wake(struct weston_compositor *compositor)
 				     compositor->idle_time * 1000);
 }
 
+static void
+weston_compositor_dpms_on(struct weston_compositor *compositor)
+{
+        struct weston_output *output;
+
+	/* TODO: we'd need a state machine to test whether dpms is on/off
+	 * before just going and setting it */
+        wl_list_for_each(output, &compositor->output_list, link)
+		if (output->set_dpms)
+			output->set_dpms(output, 0);
+}
+
 WL_EXPORT void
 weston_compositor_activity(struct weston_compositor *compositor)
 {
 	if (compositor->state == WESTON_COMPOSITOR_ACTIVE) {
 		weston_compositor_wake(compositor);
 	} else {
+		weston_compositor_dpms_on(compositor);
 		compositor->shell->unlock(compositor->shell);
 	}
 }
@@ -2482,6 +2495,7 @@ int main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	weston_compositor_dpms_on(ec);
 	weston_compositor_wake(ec);
 	if (setjmp(segv_jmp_buf) == 0)
 		wl_display_run(display);
diff --git a/src/compositor.h b/src/compositor.h
index 881f53c..bb45bd1 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -86,6 +86,8 @@ struct weston_output {
 	void (*repaint)(struct weston_output *output);
 	void (*destroy)(struct weston_output *output);
 	void (*assign_planes)(struct weston_output *output);
+	void (*set_backlight)(struct weston_output *output, uint32_t up_down);
+	void (*set_dpms)(struct weston_output *output, uint32_t state);
 };
 
 struct weston_input_device {
diff --git a/src/shell.c b/src/shell.c
index d949d0c..1510035 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1311,10 +1311,16 @@ lock(struct weston_shell *base)
 	struct weston_surface *tmp;
 	struct weston_input_device *device;
 	struct shell_surface *shsurf;
+	struct weston_output *output;
 	uint32_t time;
 
-	if (shell->locked)
+	if (shell->locked) {
+		/* set DPMS off for all outputs */
+		wl_list_for_each(output, &shell->compositor->output_list, link)
+			if (output->set_dpms)
+				output->set_dpms(output, 1);
 		return;
+	}
 
 	shell->locked = true;
 
@@ -1833,6 +1839,29 @@ switcher_binding(struct wl_input_device *device, uint32_t time,
 }
 
 static void
+backlight_binding(struct wl_input_device *device, uint32_t time,
+		  uint32_t key, uint32_t button, uint32_t state, void *data)
+{
+	struct weston_compositor *compositor = data;
+	struct weston_output *output;
+
+	/* TODO: find a better way to get the desired output */
+	output = get_default_output(compositor);
+	if (!output)
+		return;
+
+	if (!output->set_backlight)
+		return;
+
+	/* darker */
+	if (key == KEY_F9)
+		output->set_backlight(output, -1);
+	/* brighter */
+	else if (key == KEY_F10)
+		output->set_backlight(output, 1);
+}
+
+static void
 shell_destroy(struct weston_shell *base)
 {
 	struct wl_shell *shell = container_of(base, struct wl_shell, shell);
@@ -1904,9 +1933,12 @@ shell_init(struct weston_compositor *ec)
 	weston_compositor_add_binding(ec, 0, BTN_LEFT,
 				      MODIFIER_SUPER | MODIFIER_ALT,
 				      rotate_binding, NULL);
-
 	weston_compositor_add_binding(ec, KEY_TAB, 0, MODIFIER_SUPER,
 				      switcher_binding, ec);
+	weston_compositor_add_binding(ec, KEY_F9, 0, MODIFIER_CTRL,
+				      backlight_binding, ec);
+	weston_compositor_add_binding(ec, KEY_F10, 0, MODIFIER_CTRL,
+				      backlight_binding, ec);
 
 	ec->shell = &shell->shell;
 
-- 
1.7.5.4



More information about the wayland-devel mailing list