aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/FindGBM.cmake39
-rw-r--r--CMakeLists.txt5
-rw-r--r--backend/CMakeLists.txt7
-rw-r--r--backend/drm/backend.c17
-rw-r--r--backend/drm/drm.c10
-rw-r--r--backend/drm/session.c2
-rw-r--r--backend/drm/udev.c8
-rw-r--r--example/CMakeLists.txt8
-rw-r--r--example/example-drm.c109
-rw-r--r--include/backend/drm/backend.h5
-rw-r--r--include/backend/drm/drm.h3
-rw-r--r--include/wlr/backend/drm.h20
12 files changed, 220 insertions, 13 deletions
diff --git a/CMake/FindGBM.cmake b/CMake/FindGBM.cmake
new file mode 100644
index 00000000..85df1f7c
--- /dev/null
+++ b/CMake/FindGBM.cmake
@@ -0,0 +1,39 @@
+#.rst:
+# FindGBM
+# -------
+#
+# Find GBM library
+#
+# Try to find GBM library on UNIX systems. The following values are defined
+#
+# ::
+#
+# GBM_FOUND - True if gbm is available
+# GBM_INCLUDE_DIRS - Include directories for gbm
+# GBM_LIBRARIES - List of libraries for gbm
+# GBM_DEFINITIONS - List of definitions for gbm
+#
+#=============================================================================
+# Copyright (c) 2015 Jari Vetoniemi
+#
+# Distributed under the OSI-approved BSD License (the "License");
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+set_package_properties(GBM PROPERTIES
+ URL "http://www.mesa3d.org/"
+ DESCRIPTION "Generic buffer manager")
+
+find_package(PkgConfig)
+pkg_check_modules(PC_GBM QUIET gbm)
+find_library(GBM_LIBRARIES NAMES gbm HINTS ${PC_GBM_LIBRARY_DIRS})
+find_path(GBM_INCLUDE_DIRS gbm.h HINTS ${PC_GBM_INCLUDE_DIRS})
+
+set(GBM_DEFINITIONS ${PC_GBM_CFLAGS_OTHER})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(GBM DEFAULT_MSG GBM_INCLUDE_DIRS GBM_LIBRARIES)
+mark_as_advanced(GBM_INCLUDE_DIRS GBM_LIBRARIES GBM_DEFINITIONS)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30a2c37d..192eb444 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,10 +48,11 @@ find_package(WaylandProtocols REQUIRED)
find_package(EGL REQUIRED)
find_package(GLESv2 REQUIRED)
find_package(DRM REQUIRED)
+find_package(GBM REQUIRED)
find_package(LibInput REQUIRED)
-find_package(Udev)
+find_package(Udev REQUIRED)
find_package(Dbus)
-find_package(Systemd)
+find_package(Systemd REQUIRED)
include(Wayland)
include(Manpage)
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
index 344dd3cc..184854fe 100644
--- a/backend/CMakeLists.txt
+++ b/backend/CMakeLists.txt
@@ -19,4 +19,11 @@ target_link_libraries(wlr-backend
wlr-common
wlr-wayland
${WAYLAND_LIBRARIES}
+ ${DRM_LIBRARIES}
+ ${GBM_LIBRARIES}
+ ${GLESv2_LIBRARIES}
+ ${EGL_LIBRARIES}
+ ${SYSTEMD_LIBRARIES}
+ ${UDEV_LIBRARIES}
+ ${GBM_LIBRARIES}
)
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index 73e57bfa..7db6e9a1 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -12,7 +12,9 @@
#include "backend/drm/udev.h"
#include "common/log.h"
-struct wlr_drm_backend *wlr_drm_backend_init(void)
+struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add,
+ struct wl_listener *rem,
+ struct wl_listener *render)
{
struct wlr_drm_backend *backend = calloc(1, sizeof *backend);
if (!backend) {
@@ -57,6 +59,13 @@ struct wlr_drm_backend *wlr_drm_backend_init(void)
wl_signal_init(&backend->signals.display_rem);
wl_signal_init(&backend->signals.display_render);
+ if (add)
+ wl_signal_add(&backend->signals.display_add, add);
+ if (rem)
+ wl_signal_add(&backend->signals.display_rem, rem);
+ if (render)
+ wl_signal_add(&backend->signals.display_render, render);
+
wlr_drm_scan_connectors(backend);
return backend;
@@ -80,6 +89,7 @@ static void free_display(void *item)
{
struct wlr_drm_display *disp = item;
wlr_drm_display_free(disp, true);
+ free(disp);
}
void wlr_drm_backend_free(struct wlr_drm_backend *backend)
@@ -95,9 +105,14 @@ void wlr_drm_backend_free(struct wlr_drm_backend *backend)
wlr_session_end(&backend->session);
wl_event_source_remove(backend->event_src.drm);
+ wl_event_source_remove(backend->event_src.udev);
wl_event_loop_destroy(backend->event_loop);
list_free(backend->displays);
free(backend);
}
+struct wl_event_loop *wlr_drm_backend_get_event_loop(struct wlr_drm_backend *backend)
+{
+ return backend->event_loop;
+}
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 226c79fb..470a76bb 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -281,6 +281,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend)
continue;
}
+ disp->renderer = &backend->renderer;
disp->state = DRM_DISP_DISCONNECTED;
disp->connector = res->connectors[i];
snprintf(disp->name, sizeof disp->name, "%s-%"PRIu32,
@@ -288,6 +289,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend)
conn->connector_type_id);
list_add(backend->displays, disp);
+ wlr_log(L_INFO, "Found display '%s'", disp->name);
} else {
disp = backend->displays->items[index];
}
@@ -295,12 +297,14 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend)
if (disp->state == DRM_DISP_DISCONNECTED &&
conn->connection == DRM_MODE_CONNECTED) {
disp->state = DRM_DISP_NEEDS_MODESET;
+ wlr_log(L_INFO, "Sending modesetting signal for '%s'", disp->name);
wl_signal_emit(&backend->signals.display_add, disp);
} else if (disp->state == DRM_DISP_CONNECTED &&
conn->connection != DRM_MODE_CONNECTED) {
disp->state = DRM_DISP_DISCONNECTED;
wlr_drm_display_free(disp, false);
+ wlr_log(L_INFO, "Sending destruction signal for '%s'", disp->name);
wl_signal_emit(&backend->signals.display_rem, disp);
}
@@ -430,9 +434,9 @@ static drmModeModeInfo *select_mode(size_t num_modes,
return NULL;
}
-bool wlr_drm_display_modeset(struct wlr_drm_backend *backend,
- struct wlr_drm_display *disp, const char *str)
+bool wlr_drm_display_modeset(struct wlr_drm_display *disp, const char *str)
{
+ struct wlr_drm_backend *backend = disp->renderer->backend;
wlr_log(L_INFO, "Modesetting %s with '%s'", disp->name, str);
drmModeConnector *conn = drmModeGetConnector(backend->fd, disp->connector);
@@ -519,7 +523,7 @@ bool wlr_drm_display_modeset(struct wlr_drm_backend *backend,
drmModeFreeConnector(conn);
- wlr_log(L_INFO, "Configuring %s with mode %"PRIu16"x%"PRIu16"@%"PRIu32"\n",
+ wlr_log(L_INFO, "Configuring %s with mode %"PRIu16"x%"PRIu16"@%"PRIu32"",
disp->name, disp->active_mode->hdisplay, disp->active_mode->vdisplay,
disp->active_mode->vrefresh);
diff --git a/backend/drm/session.c b/backend/drm/session.c
index 49223334..073f822b 100644
--- a/backend/drm/session.c
+++ b/backend/drm/session.c
@@ -194,7 +194,7 @@ bool wlr_session_start(struct wlr_session *session)
sprintf(session->path, fmt, session->id);
- ret = sd_bus_open_system(&session->bus);
+ ret = sd_bus_default_system(&session->bus);
if (ret < 0) {
wlr_log(L_ERROR, "Failed to open DBus connection: %s", strerror(-ret));
goto error;
diff --git a/backend/drm/udev.c b/backend/drm/udev.c
index 6c4aa074..ae99bcfc 100644
--- a/backend/drm/udev.c
+++ b/backend/drm/udev.c
@@ -94,9 +94,10 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session)
const char *id = udev_device_get_sysattr_value(pci, "boot_vga");
if (id && strcmp(id, "1") == 0)
is_boot_vga = true;
- udev_device_unref(pci);
+ //udev_device_unref(pci);
}
+ // We already have a valid GPU
if (!is_boot_vga && fd >= 0) {
udev_device_unref(dev);
continue;
@@ -107,9 +108,10 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session)
continue;
}
- if (is_boot_vga) {
+ udev_device_unref(dev);
+
+ if (is_boot_vga)
break;
- }
}
udev_enumerate_unref(en);
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index 73768393..dfb069b4 100644
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -5,3 +5,11 @@ add_executable(example
target_link_libraries(example
wlr-backend
)
+
+add_executable(example-drm
+ example-drm.c
+)
+
+target_link_libraries(example-drm
+ wlr-backend
+)
diff --git a/example/example-drm.c b/example/example-drm.c
new file mode 100644
index 00000000..4c944226
--- /dev/null
+++ b/example/example-drm.c
@@ -0,0 +1,109 @@
+#define _POSIX_C_SOURCE 199309L
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wayland-server.h>
+#include <GLES3/gl3.h>
+
+#include <wlr/backend/drm.h>
+
+struct state {
+ float color[3];
+ int dec;
+
+ struct timespec last_frame;
+
+ struct wl_listener add;
+ struct wl_listener rem;
+ struct wl_listener render;
+};
+
+void display_add(struct wl_listener *listener, void *data)
+{
+ struct wlr_drm_display *disp = data;
+
+ fprintf(stderr, "Display added\n");
+ wlr_drm_display_modeset(disp, "preferred");
+}
+
+void display_rem(struct wl_listener *listener, void *data)
+{
+ fprintf(stderr, "Display removed\n");
+}
+
+void display_render(struct wl_listener *listener, void *data)
+{
+ struct wlr_drm_display *disp = data;
+ struct state *s = wl_container_of(listener, s, render);
+
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ long ms = (now.tv_sec - s->last_frame.tv_sec) * 1000 +
+ (now.tv_nsec - s->last_frame.tv_nsec) / 1000000;
+ int inc = (s->dec + 1) % 3;
+
+ s->color[inc] += ms / 2000.0f;
+ s->color[s->dec] -= ms / 2000.0f;
+
+ if (s->color[s->dec] < 0.0f) {
+ s->color[inc] = 1.0f;
+ s->color[s->dec] = 0.0f;
+
+ s->dec = inc;
+ }
+
+ s->last_frame = now;
+
+ wlr_drm_display_begin(disp);
+
+ glClearColor(s->color[0], s->color[1], s->color[2], 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ wlr_drm_display_end(disp);
+}
+
+int timer_done(void *data)
+{
+ *(bool *)data = true;
+ return 1;
+}
+
+int main()
+{
+ if (getenv("DISPLAY")) {
+ fprintf(stderr, "Detected that X is running. Run this in its own virtual terminal.\n");
+ return 1;
+ } else if (getenv("WAYLAND_DISPLAY")) {
+ fprintf(stderr, "Detected that Wayland is running. Run this in its own virtual terminal.\n");
+ return 1;
+ }
+
+ struct state state = {
+ .color = { 1.0, 0.0, 0.0 },
+ .dec = 0,
+ .add = { .notify = display_add },
+ .rem = { .notify = display_rem },
+ .render = { .notify = display_render },
+ };
+
+ wl_list_init(&state.add.link);
+ wl_list_init(&state.rem.link);
+ wl_list_init(&state.render.link);
+ clock_gettime(CLOCK_MONOTONIC, &state.last_frame);
+
+ struct wlr_drm_backend *wlr = wlr_drm_backend_init(&state.add, &state.rem, &state.render);
+
+ bool done = false;
+ struct wl_event_loop *event_loop = wlr_drm_backend_get_event_loop(wlr);
+ struct wl_event_source *timer = wl_event_loop_add_timer(event_loop,
+ timer_done, &done);
+
+ wl_event_source_timer_update(timer, 10000);
+
+ while (!done)
+ wl_event_loop_dispatch(event_loop, 0);
+
+ wl_event_source_remove(timer);
+ wlr_drm_backend_free(wlr);
+}
diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h
index 87471fbb..1ad8e479 100644
--- a/include/backend/drm/backend.h
+++ b/include/backend/drm/backend.h
@@ -9,6 +9,7 @@
#include <wayland-server.h>
#include <wlr/common/list.h>
+#include <wlr/backend/drm.h>
#include "session.h"
#include "udev.h"
@@ -41,7 +42,9 @@ struct wlr_drm_backend {
struct wlr_udev udev;
};
-struct wlr_drm_backend *wlr_drm_backend_init(void);
+struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add,
+ struct wl_listener *rem,
+ struct wl_listener *render);
void wlr_drm_backend_free(struct wlr_drm_backend *backend);
#endif
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index 1fe4b7b0..17d4aa90 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -57,8 +57,7 @@ struct wlr_drm_display {
bool cleanup;
};
-bool wlr_drm_display_modeset(struct wlr_drm_backend *backend,
- struct wlr_drm_display *disp, const char *str);
+bool wlr_drm_display_modeset(struct wlr_drm_display *disp, const char *str);
void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore);
void wlr_drm_display_begin(struct wlr_drm_display *disp);
diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h
new file mode 100644
index 00000000..5179db4b
--- /dev/null
+++ b/include/wlr/backend/drm.h
@@ -0,0 +1,20 @@
+#ifndef WLR_BACKEND_DRM_H
+#define WLR_BACKEND_DRM_H
+
+#include <wayland-server.h>
+
+struct wlr_drm_backend;
+struct wlr_drm_display;
+
+struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add,
+ struct wl_listener *rem,
+ struct wl_listener *render);
+void wlr_drm_backend_free(struct wlr_drm_backend *backend);
+
+struct wl_event_loop *wlr_drm_backend_get_event_loop(struct wlr_drm_backend *backend);
+
+bool wlr_drm_display_modeset(struct wlr_drm_display *disp, const char *str);
+void wlr_drm_display_begin(struct wlr_drm_display *disp);
+void wlr_drm_display_end(struct wlr_drm_display *disp);
+
+#endif