aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/drm/backend.c8
-rw-r--r--backend/drm/drm.c46
-rw-r--r--example/main.c22
-rw-r--r--include/backend/drm/drm.h5
-rw-r--r--include/wlr/backend/drm.h2
5 files changed, 81 insertions, 2 deletions
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index 0da84745..f202d4d6 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -101,3 +101,11 @@ error_backend:
free(backend);
return NULL;
}
+
+void wlr_drm_backend_dpms(struct wlr_backend *backend, bool screen_on) {
+ struct wlr_backend_state *state = backend->state;
+ for (size_t i = 0; i < state->outputs->length; ++i) {
+ struct wlr_output_state *output = state->outputs->items[i];
+ wlr_drm_output_dpms(state->fd, output, screen_on);
+ }
+}
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 7cbd3e4a..a8e8c9ae 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -249,6 +249,30 @@ static struct wlr_output_impl output_impl = {
.destroy = wlr_drm_output_destroy,
};
+static void scan_property_ids(int fd, drmModeConnector *conn,
+ struct wlr_output_state *output) {
+ for (int i = 0; i < conn->count_props; ++i) {
+ drmModePropertyRes *prop = drmModeGetProperty(fd, conn->props[i]);
+ if (!prop) {
+ continue;
+ }
+
+ // I think this is guranteed to exist
+ if (strcmp(prop->name, "DPMS") == 0) {
+ output->props.dpms = prop->prop_id;
+
+ /* There may be more properties we want to get,
+ * but since it's currently only this, we exit early
+ */
+
+ drmModeFreeProperty(prop);
+ break;
+ }
+
+ drmModeFreeProperty(prop);
+ }
+}
+
void wlr_drm_scan_connectors(struct wlr_backend_state *state) {
wlr_log(L_INFO, "Scanning DRM connectors");
@@ -300,6 +324,8 @@ void wlr_drm_scan_connectors(struct wlr_backend_state *state) {
free(curr_enc);
}
+ scan_property_ids(state->fd, conn, output);
+
list_add(state->outputs, output);
wlr_log(L_INFO, "Found display '%s'", output->name);
} else {
@@ -416,3 +442,23 @@ void wlr_drm_output_cleanup(struct wlr_output_state *output, bool restore) {
}
// TODO: free wlr_output
}
+
+void wlr_drm_output_dpms(int fd, struct wlr_output_state *output, bool screen_on) {
+ if (output->state != DRM_OUTPUT_CONNECTED) {
+ return;
+ }
+
+ if (screen_on) {
+ drmModeConnectorSetProperty(fd, output->connector, output->props.dpms,
+ DRM_MODE_DPMS_ON);
+
+ // Start rendering loop again by drawing a black frame
+ wlr_drm_output_begin(output->wlr_output);
+ glClearColor(0.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ wlr_drm_output_end(output->wlr_output);
+ } else {
+ drmModeConnectorSetProperty(fd, output->connector, output->props.dpms,
+ DRM_MODE_DPMS_STANDBY);
+ }
+}
diff --git a/example/main.c b/example/main.c
index 2c168d98..ed9eac0b 100644
--- a/example/main.c
+++ b/example/main.c
@@ -81,6 +81,18 @@ int timer_done(void *data) {
return 1;
}
+int dpms_on(void *data) {
+ struct wlr_backend *backend = data;
+ wlr_drm_backend_dpms(backend, false);
+ return 1;
+}
+
+int dpms_off(void *data) {
+ struct wlr_backend *backend = data;
+ wlr_drm_backend_dpms(backend, true);
+ return 1;
+}
+
int main() {
if (getenv("DISPLAY")) {
fprintf(stderr, "Detected that X is running. Run this in its own virtual terminal.\n");
@@ -120,8 +132,14 @@ int main() {
bool done = false;
struct wl_event_source *timer = wl_event_loop_add_timer(event_loop,
timer_done, &done);
-
- wl_event_source_timer_update(timer, 5000);
+ struct wl_event_source *timer_dpms_on = wl_event_loop_add_timer(event_loop,
+ dpms_on, wlr);
+ struct wl_event_source *timer_dpms_off = wl_event_loop_add_timer(event_loop,
+ dpms_off, wlr);
+
+ wl_event_source_timer_update(timer, 20000);
+ wl_event_source_timer_update(timer_dpms_on, 5000);
+ wl_event_source_timer_update(timer_dpms_off, 10000);
while (!done) {
wl_event_loop_dispatch(event_loop, 0);
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index 4b42aa68..93de4fb8 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -36,6 +36,10 @@ struct wlr_output_state {
uint32_t connector;
char name[16];
+ struct {
+ uint32_t dpms;
+ } props;
+
uint32_t width;
uint32_t height;
@@ -51,6 +55,7 @@ struct wlr_output_state {
};
void wlr_drm_output_cleanup(struct wlr_output_state *output, bool restore);
+void wlr_drm_output_dpms(int fd, struct wlr_output_state *output, bool screen_on);
void wlr_drm_scan_connectors(struct wlr_backend_state *state);
int wlr_drm_event(int fd, uint32_t mask, void *data);
diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h
index 2d9bf879..c76d280a 100644
--- a/include/wlr/backend/drm.h
+++ b/include/wlr/backend/drm.h
@@ -10,6 +10,8 @@
struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
struct wlr_session *session);
+void wlr_drm_backend_dpms(struct wlr_backend *backend, bool screen_on);
+
void wlr_drm_output_begin(struct wlr_output *out);
void wlr_drm_output_end(struct wlr_output *out);