Added example.

This commit is contained in:
Scott Anderson 2017-05-02 18:13:17 +12:00
parent e9d716fc0c
commit e446a5300b
12 changed files with 220 additions and 13 deletions

39
CMake/FindGBM.cmake Normal file
View file

@ -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)

View file

@ -48,10 +48,11 @@ find_package(WaylandProtocols REQUIRED)
find_package(EGL REQUIRED) find_package(EGL REQUIRED)
find_package(GLESv2 REQUIRED) find_package(GLESv2 REQUIRED)
find_package(DRM REQUIRED) find_package(DRM REQUIRED)
find_package(GBM REQUIRED)
find_package(LibInput REQUIRED) find_package(LibInput REQUIRED)
find_package(Udev) find_package(Udev REQUIRED)
find_package(Dbus) find_package(Dbus)
find_package(Systemd) find_package(Systemd REQUIRED)
include(Wayland) include(Wayland)
include(Manpage) include(Manpage)

View file

@ -19,4 +19,11 @@ target_link_libraries(wlr-backend
wlr-common wlr-common
wlr-wayland wlr-wayland
${WAYLAND_LIBRARIES} ${WAYLAND_LIBRARIES}
${DRM_LIBRARIES}
${GBM_LIBRARIES}
${GLESv2_LIBRARIES}
${EGL_LIBRARIES}
${SYSTEMD_LIBRARIES}
${UDEV_LIBRARIES}
${GBM_LIBRARIES}
) )

View file

@ -12,7 +12,9 @@
#include "backend/drm/udev.h" #include "backend/drm/udev.h"
#include "common/log.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); struct wlr_drm_backend *backend = calloc(1, sizeof *backend);
if (!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_rem);
wl_signal_init(&backend->signals.display_render); 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); wlr_drm_scan_connectors(backend);
return backend; return backend;
@ -80,6 +89,7 @@ static void free_display(void *item)
{ {
struct wlr_drm_display *disp = item; struct wlr_drm_display *disp = item;
wlr_drm_display_free(disp, true); wlr_drm_display_free(disp, true);
free(disp);
} }
void wlr_drm_backend_free(struct wlr_drm_backend *backend) 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); wlr_session_end(&backend->session);
wl_event_source_remove(backend->event_src.drm); wl_event_source_remove(backend->event_src.drm);
wl_event_source_remove(backend->event_src.udev);
wl_event_loop_destroy(backend->event_loop); wl_event_loop_destroy(backend->event_loop);
list_free(backend->displays); list_free(backend->displays);
free(backend); free(backend);
} }
struct wl_event_loop *wlr_drm_backend_get_event_loop(struct wlr_drm_backend *backend)
{
return backend->event_loop;
}

View file

@ -281,6 +281,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend)
continue; continue;
} }
disp->renderer = &backend->renderer;
disp->state = DRM_DISP_DISCONNECTED; disp->state = DRM_DISP_DISCONNECTED;
disp->connector = res->connectors[i]; disp->connector = res->connectors[i];
snprintf(disp->name, sizeof disp->name, "%s-%"PRIu32, 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); conn->connector_type_id);
list_add(backend->displays, disp); list_add(backend->displays, disp);
wlr_log(L_INFO, "Found display '%s'", disp->name);
} else { } else {
disp = backend->displays->items[index]; 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 && if (disp->state == DRM_DISP_DISCONNECTED &&
conn->connection == DRM_MODE_CONNECTED) { conn->connection == DRM_MODE_CONNECTED) {
disp->state = DRM_DISP_NEEDS_MODESET; 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); wl_signal_emit(&backend->signals.display_add, disp);
} else if (disp->state == DRM_DISP_CONNECTED && } else if (disp->state == DRM_DISP_CONNECTED &&
conn->connection != DRM_MODE_CONNECTED) { conn->connection != DRM_MODE_CONNECTED) {
disp->state = DRM_DISP_DISCONNECTED; disp->state = DRM_DISP_DISCONNECTED;
wlr_drm_display_free(disp, false); 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); wl_signal_emit(&backend->signals.display_rem, disp);
} }
@ -430,9 +434,9 @@ static drmModeModeInfo *select_mode(size_t num_modes,
return NULL; return NULL;
} }
bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, bool wlr_drm_display_modeset(struct wlr_drm_display *disp, const char *str)
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); wlr_log(L_INFO, "Modesetting %s with '%s'", disp->name, str);
drmModeConnector *conn = drmModeGetConnector(backend->fd, disp->connector); drmModeConnector *conn = drmModeGetConnector(backend->fd, disp->connector);
@ -519,7 +523,7 @@ bool wlr_drm_display_modeset(struct wlr_drm_backend *backend,
drmModeFreeConnector(conn); 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->name, disp->active_mode->hdisplay, disp->active_mode->vdisplay,
disp->active_mode->vrefresh); disp->active_mode->vrefresh);

View file

@ -194,7 +194,7 @@ bool wlr_session_start(struct wlr_session *session)
sprintf(session->path, fmt, session->id); sprintf(session->path, fmt, session->id);
ret = sd_bus_open_system(&session->bus); ret = sd_bus_default_system(&session->bus);
if (ret < 0) { if (ret < 0) {
wlr_log(L_ERROR, "Failed to open DBus connection: %s", strerror(-ret)); wlr_log(L_ERROR, "Failed to open DBus connection: %s", strerror(-ret));
goto error; goto error;

View file

@ -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"); const char *id = udev_device_get_sysattr_value(pci, "boot_vga");
if (id && strcmp(id, "1") == 0) if (id && strcmp(id, "1") == 0)
is_boot_vga = true; is_boot_vga = true;
udev_device_unref(pci); //udev_device_unref(pci);
} }
// We already have a valid GPU
if (!is_boot_vga && fd >= 0) { if (!is_boot_vga && fd >= 0) {
udev_device_unref(dev); udev_device_unref(dev);
continue; continue;
@ -107,10 +108,11 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session)
continue; continue;
} }
if (is_boot_vga) { udev_device_unref(dev);
if (is_boot_vga)
break; break;
} }
}
udev_enumerate_unref(en); udev_enumerate_unref(en);

View file

@ -5,3 +5,11 @@ add_executable(example
target_link_libraries(example target_link_libraries(example
wlr-backend wlr-backend
) )
add_executable(example-drm
example-drm.c
)
target_link_libraries(example-drm
wlr-backend
)

109
example/example-drm.c Normal file
View file

@ -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);
}

View file

@ -9,6 +9,7 @@
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/common/list.h> #include <wlr/common/list.h>
#include <wlr/backend/drm.h>
#include "session.h" #include "session.h"
#include "udev.h" #include "udev.h"
@ -41,7 +42,9 @@ struct wlr_drm_backend {
struct wlr_udev udev; 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); void wlr_drm_backend_free(struct wlr_drm_backend *backend);
#endif #endif

View file

@ -57,8 +57,7 @@ struct wlr_drm_display {
bool cleanup; bool cleanup;
}; };
bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, bool wlr_drm_display_modeset(struct wlr_drm_display *disp, const char *str);
struct wlr_drm_display *disp, const char *str);
void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore); void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore);
void wlr_drm_display_begin(struct wlr_drm_display *disp); void wlr_drm_display_begin(struct wlr_drm_display *disp);

20
include/wlr/backend/drm.h Normal file
View file

@ -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