mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-05 01:48:00 +02:00
backend-drm: make GBM optional
Make GBM optional in case GL renderer is disabled. This allows to build Weston with DRM backend without Mesa dependencies. Signed-off-by: Stefan Agner <stefan@agner.ch>
This commit is contained in:
parent
3654c673f8
commit
ccf24076dd
6 changed files with 459 additions and 339 deletions
366
libweston/backend-drm/drm-gbm.c
Normal file
366
libweston/backend-drm/drm-gbm.c
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2017, 2018 Collabora, Ltd.
|
||||
* Copyright © 2017, 2018 General Electric Company
|
||||
* Copyright (c) 2018 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "drm-internal.h"
|
||||
#include "pixman-renderer.h"
|
||||
#include "pixel-formats.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
#include "linux-dmabuf.h"
|
||||
#include "linux-explicit-synchronization.h"
|
||||
|
||||
struct gl_renderer_interface *gl_renderer;
|
||||
|
||||
static struct gbm_device *
|
||||
create_gbm_device(int fd)
|
||||
{
|
||||
struct gbm_device *gbm;
|
||||
|
||||
gl_renderer = weston_load_module("gl-renderer.so",
|
||||
"gl_renderer_interface");
|
||||
if (!gl_renderer)
|
||||
return NULL;
|
||||
|
||||
/* GBM will load a dri driver, but even though they need symbols from
|
||||
* libglapi, in some version of Mesa they are not linked to it. Since
|
||||
* only the gl-renderer module links to it, the call above won't make
|
||||
* these symbols globally available, and loading the DRI driver fails.
|
||||
* Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
|
||||
dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
|
||||
|
||||
gbm = gbm_create_device(fd);
|
||||
|
||||
return gbm;
|
||||
}
|
||||
|
||||
/* When initializing EGL, if the preferred buffer format isn't available
|
||||
* we may be able to substitute an ARGB format for an XRGB one.
|
||||
*
|
||||
* This returns 0 if substitution isn't possible, but 0 might be a
|
||||
* legitimate format for other EGL platforms, so the caller is
|
||||
* responsible for checking for 0 before calling gl_renderer->create().
|
||||
*
|
||||
* This works around https://bugs.freedesktop.org/show_bug.cgi?id=89689
|
||||
* but it's entirely possible we'll see this again on other implementations.
|
||||
*/
|
||||
static uint32_t
|
||||
fallback_format_for(uint32_t format)
|
||||
{
|
||||
const struct pixel_format_info *pf;
|
||||
|
||||
pf = pixel_format_get_info_by_opaque_substitute(format);
|
||||
if (!pf)
|
||||
return 0;
|
||||
|
||||
return pf->format;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_backend_create_gl_renderer(struct drm_backend *b)
|
||||
{
|
||||
uint32_t format[3] = {
|
||||
b->gbm_format,
|
||||
fallback_format_for(b->gbm_format),
|
||||
0,
|
||||
};
|
||||
unsigned n_formats = 2;
|
||||
|
||||
if (format[1])
|
||||
n_formats = 3;
|
||||
if (gl_renderer->display_create(b->compositor,
|
||||
EGL_PLATFORM_GBM_KHR,
|
||||
(void *)b->gbm,
|
||||
EGL_WINDOW_BIT,
|
||||
format,
|
||||
n_formats) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
init_egl(struct drm_backend *b)
|
||||
{
|
||||
b->gbm = create_gbm_device(b->drm.fd);
|
||||
|
||||
if (!b->gbm)
|
||||
return -1;
|
||||
|
||||
if (drm_backend_create_gl_renderer(b) < 0) {
|
||||
gbm_device_destroy(b->gbm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_output_fini_cursor_egl(struct drm_output *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
drm_fb_unref(output->gbm_cursor_fb[i]);
|
||||
output->gbm_cursor_fb[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* No point creating cursors if we don't have a plane for them. */
|
||||
if (!output->cursor_plane)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
struct gbm_bo *bo;
|
||||
|
||||
bo = gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height,
|
||||
GBM_FORMAT_ARGB8888,
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||
if (!bo)
|
||||
goto err;
|
||||
|
||||
output->gbm_cursor_fb[i] =
|
||||
drm_fb_get_from_bo(bo, b, false, BUFFER_CURSOR);
|
||||
if (!output->gbm_cursor_fb[i]) {
|
||||
gbm_bo_destroy(bo);
|
||||
goto err;
|
||||
}
|
||||
output->gbm_cursor_handle[i] = gbm_bo_get_handle(bo).s32;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
weston_log("cursor buffers unavailable, using gl cursors\n");
|
||||
b->cursors_are_broken = 1;
|
||||
drm_output_fini_cursor_egl(output);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Init output state that depends on gl or gbm */
|
||||
int
|
||||
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
uint32_t format[2] = {
|
||||
output->gbm_format,
|
||||
fallback_format_for(output->gbm_format),
|
||||
};
|
||||
unsigned n_formats = 1;
|
||||
struct weston_mode *mode = output->base.current_mode;
|
||||
struct drm_plane *plane = output->scanout_plane;
|
||||
unsigned int i;
|
||||
|
||||
assert(output->gbm_surface == NULL);
|
||||
|
||||
for (i = 0; i < plane->count_formats; i++) {
|
||||
if (plane->formats[i].format == output->gbm_format)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == plane->count_formats) {
|
||||
weston_log("format 0x%x not supported by output %s\n",
|
||||
output->gbm_format, output->base.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GBM_MODIFIERS
|
||||
if (plane->formats[i].count_modifiers > 0) {
|
||||
output->gbm_surface =
|
||||
gbm_surface_create_with_modifiers(b->gbm,
|
||||
mode->width,
|
||||
mode->height,
|
||||
output->gbm_format,
|
||||
plane->formats[i].modifiers,
|
||||
plane->formats[i].count_modifiers);
|
||||
}
|
||||
|
||||
/* If allocating with modifiers fails, try again without. This can
|
||||
* happen when the KMS display device supports modifiers but the
|
||||
* GBM driver does not, e.g. the old i915 Mesa driver. */
|
||||
if (!output->gbm_surface)
|
||||
#endif
|
||||
{
|
||||
output->gbm_surface =
|
||||
gbm_surface_create(b->gbm, mode->width, mode->height,
|
||||
output->gbm_format,
|
||||
output->gbm_bo_flags);
|
||||
}
|
||||
|
||||
if (!output->gbm_surface) {
|
||||
weston_log("failed to create gbm surface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (format[1])
|
||||
n_formats = 2;
|
||||
if (gl_renderer->output_window_create(&output->base,
|
||||
(EGLNativeWindowType)output->gbm_surface,
|
||||
output->gbm_surface,
|
||||
format,
|
||||
n_formats) < 0) {
|
||||
weston_log("failed to create gl renderer output state\n");
|
||||
gbm_surface_destroy(output->gbm_surface);
|
||||
output->gbm_surface = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
drm_output_init_cursor_egl(output, b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
drm_output_fini_egl(struct drm_output *output)
|
||||
{
|
||||
struct drm_backend *b = to_drm_backend(output->base.compositor);
|
||||
|
||||
/* Destroying the GBM surface will destroy all our GBM buffers,
|
||||
* regardless of refcount. Ensure we destroy them here. */
|
||||
if (!b->shutting_down &&
|
||||
output->scanout_plane->state_cur->fb &&
|
||||
output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) {
|
||||
drm_plane_state_free(output->scanout_plane->state_cur, true);
|
||||
output->scanout_plane->state_cur =
|
||||
drm_plane_state_alloc(NULL, output->scanout_plane);
|
||||
output->scanout_plane->state_cur->complete = true;
|
||||
}
|
||||
|
||||
gl_renderer->output_destroy(&output->base);
|
||||
gbm_surface_destroy(output->gbm_surface);
|
||||
output->gbm_surface = NULL;
|
||||
drm_output_fini_cursor_egl(output);
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
||||
{
|
||||
struct drm_output *output = state->output;
|
||||
struct drm_backend *b = to_drm_backend(output->base.compositor);
|
||||
struct gbm_bo *bo;
|
||||
struct drm_fb *ret;
|
||||
|
||||
output->base.compositor->renderer->repaint_output(&output->base,
|
||||
damage);
|
||||
|
||||
bo = gbm_surface_lock_front_buffer(output->gbm_surface);
|
||||
if (!bo) {
|
||||
weston_log("failed to lock front buffer: %s\n",
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The renderer always produces an opaque image. */
|
||||
ret = drm_fb_get_from_bo(bo, b, true, BUFFER_GBM_SURFACE);
|
||||
if (!ret) {
|
||||
weston_log("failed to get drm_fb for bo\n");
|
||||
gbm_surface_release_buffer(output->gbm_surface, bo);
|
||||
return NULL;
|
||||
}
|
||||
ret->gbm_surface = output->gbm_surface;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
switch_to_gl_renderer(struct drm_backend *b)
|
||||
{
|
||||
struct drm_output *output;
|
||||
bool dmabuf_support_inited;
|
||||
bool linux_explicit_sync_inited;
|
||||
|
||||
if (!b->use_pixman)
|
||||
return;
|
||||
|
||||
dmabuf_support_inited = !!b->compositor->renderer->import_dmabuf;
|
||||
linux_explicit_sync_inited =
|
||||
b->compositor->capabilities & WESTON_CAP_EXPLICIT_SYNC;
|
||||
|
||||
weston_log("Switching to GL renderer\n");
|
||||
|
||||
b->gbm = create_gbm_device(b->drm.fd);
|
||||
if (!b->gbm) {
|
||||
weston_log("Failed to create gbm device. "
|
||||
"Aborting renderer switch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_list_for_each(output, &b->compositor->output_list, base.link)
|
||||
pixman_renderer_output_destroy(&output->base);
|
||||
|
||||
b->compositor->renderer->destroy(b->compositor);
|
||||
|
||||
if (drm_backend_create_gl_renderer(b) < 0) {
|
||||
gbm_device_destroy(b->gbm);
|
||||
weston_log("Failed to create GL renderer. Quitting.\n");
|
||||
/* FIXME: we need a function to shutdown cleanly */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
wl_list_for_each(output, &b->compositor->output_list, base.link)
|
||||
drm_output_init_egl(output, b);
|
||||
|
||||
b->use_pixman = 0;
|
||||
|
||||
if (!dmabuf_support_inited && b->compositor->renderer->import_dmabuf) {
|
||||
if (linux_dmabuf_setup(b->compositor) < 0)
|
||||
weston_log("Error: initializing dmabuf "
|
||||
"support failed.\n");
|
||||
}
|
||||
|
||||
if (!linux_explicit_sync_inited &&
|
||||
(b->compositor->capabilities & WESTON_CAP_EXPLICIT_SYNC)) {
|
||||
if (linux_explicit_synchronization_setup(b->compositor) < 0)
|
||||
weston_log("Error: initializing explicit "
|
||||
" synchronization support failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
renderer_switch_binding(struct weston_keyboard *keyboard,
|
||||
const struct timespec *time, uint32_t key, void *data)
|
||||
{
|
||||
struct drm_backend *b =
|
||||
to_drm_backend(keyboard->seat->compositor);
|
||||
|
||||
switch_to_gl_renderer(b);
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +47,9 @@
|
|||
#include <xf86drmMode.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#ifdef BUILD_DRM_GBM
|
||||
#include <gbm.h>
|
||||
#endif
|
||||
#include <libudev.h>
|
||||
|
||||
#include <libweston/libweston.h>
|
||||
|
|
@ -634,9 +636,17 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height,
|
|||
struct drm_fb *
|
||||
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
|
||||
bool is_opaque, enum drm_fb_type type);
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev);
|
||||
|
||||
#ifdef BUILD_DRM_GBM
|
||||
extern struct drm_fb *
|
||||
drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev);
|
||||
#else
|
||||
static inline struct drm_fb *
|
||||
drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct drm_pending_state *
|
||||
drm_pending_state_alloc(struct drm_backend *backend);
|
||||
|
|
@ -712,8 +722,51 @@ drm_backend_init_virtual_output_api(struct weston_compositor *compositor)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_DRM_GBM
|
||||
int
|
||||
init_egl(struct drm_backend *b);
|
||||
|
||||
int
|
||||
drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
|
||||
|
||||
void
|
||||
drm_output_fini_egl(struct drm_output *output);
|
||||
|
||||
struct drm_fb *
|
||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage);
|
||||
|
||||
void
|
||||
renderer_switch_binding(struct weston_keyboard *keyboard,
|
||||
const struct timespec *time, uint32_t key, void *data);
|
||||
#else
|
||||
inline static int
|
||||
init_egl(struct drm_backend *b)
|
||||
{
|
||||
weston_log("Compiled without GBM/EGL support\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline static int
|
||||
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline static void
|
||||
drm_output_fini_egl(struct drm_output *output)
|
||||
{
|
||||
}
|
||||
|
||||
inline static struct drm_fb *
|
||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline static void
|
||||
renderer_switch_binding(struct weston_keyboard *keyboard,
|
||||
const struct timespec *time, uint32_t key, void *data)
|
||||
{
|
||||
weston_log("Compiled without GBM/EGL support\n");
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@
|
|||
#include <linux/vt.h>
|
||||
#include <assert.h>
|
||||
#include <sys/mman.h>
|
||||
#include <dlfcn.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
|
@ -56,8 +55,6 @@
|
|||
#include "shared/helpers.h"
|
||||
#include "shared/timespec-util.h"
|
||||
#include "shared/string-helpers.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
#include "pixman-renderer.h"
|
||||
#include "pixel-formats.h"
|
||||
#include "libbacklight.h"
|
||||
|
|
@ -69,8 +66,6 @@
|
|||
#include "linux-dmabuf-unstable-v1-server-protocol.h"
|
||||
#include "linux-explicit-synchronization.h"
|
||||
|
||||
struct gl_renderer_interface *gl_renderer;
|
||||
|
||||
static const char default_seat[] = "seat0";
|
||||
|
||||
static void
|
||||
|
|
@ -276,37 +271,6 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags,
|
|||
weston_output_schedule_repaint(&output->base);
|
||||
}
|
||||
|
||||
|
||||
static struct drm_fb *
|
||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
||||
{
|
||||
struct drm_output *output = state->output;
|
||||
struct drm_backend *b = to_drm_backend(output->base.compositor);
|
||||
struct gbm_bo *bo;
|
||||
struct drm_fb *ret;
|
||||
|
||||
output->base.compositor->renderer->repaint_output(&output->base,
|
||||
damage);
|
||||
|
||||
bo = gbm_surface_lock_front_buffer(output->gbm_surface);
|
||||
if (!bo) {
|
||||
weston_log("failed to lock front buffer: %s\n",
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The renderer always produces an opaque image. */
|
||||
ret = drm_fb_get_from_bo(bo, b, true, BUFFER_GBM_SURFACE);
|
||||
if (!ret) {
|
||||
weston_log("failed to get drm_fb for bo\n");
|
||||
gbm_surface_release_buffer(output->gbm_surface, bo);
|
||||
return NULL;
|
||||
}
|
||||
ret->gbm_surface = output->gbm_surface;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct drm_fb *
|
||||
drm_output_render_pixman(struct drm_output_state *state,
|
||||
pixman_region32_t *damage)
|
||||
|
|
@ -681,97 +645,12 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct gbm_device *
|
||||
create_gbm_device(int fd)
|
||||
{
|
||||
struct gbm_device *gbm;
|
||||
|
||||
gl_renderer = weston_load_module("gl-renderer.so",
|
||||
"gl_renderer_interface");
|
||||
if (!gl_renderer)
|
||||
return NULL;
|
||||
|
||||
/* GBM will load a dri driver, but even though they need symbols from
|
||||
* libglapi, in some version of Mesa they are not linked to it. Since
|
||||
* only the gl-renderer module links to it, the call above won't make
|
||||
* these symbols globally available, and loading the DRI driver fails.
|
||||
* Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
|
||||
dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
|
||||
|
||||
gbm = gbm_create_device(fd);
|
||||
|
||||
return gbm;
|
||||
}
|
||||
|
||||
/* When initializing EGL, if the preferred buffer format isn't available
|
||||
* we may be able to substitute an ARGB format for an XRGB one.
|
||||
*
|
||||
* This returns 0 if substitution isn't possible, but 0 might be a
|
||||
* legitimate format for other EGL platforms, so the caller is
|
||||
* responsible for checking for 0 before calling gl_renderer->create().
|
||||
*
|
||||
* This works around https://bugs.freedesktop.org/show_bug.cgi?id=89689
|
||||
* but it's entirely possible we'll see this again on other implementations.
|
||||
*/
|
||||
static uint32_t
|
||||
fallback_format_for(uint32_t format)
|
||||
{
|
||||
const struct pixel_format_info *pf;
|
||||
|
||||
pf = pixel_format_get_info_by_opaque_substitute(format);
|
||||
if (!pf)
|
||||
return 0;
|
||||
|
||||
return pf->format;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_backend_create_gl_renderer(struct drm_backend *b)
|
||||
{
|
||||
uint32_t format[3] = {
|
||||
b->gbm_format,
|
||||
fallback_format_for(b->gbm_format),
|
||||
0,
|
||||
};
|
||||
unsigned n_formats = 2;
|
||||
|
||||
if (format[1])
|
||||
n_formats = 3;
|
||||
if (gl_renderer->display_create(b->compositor,
|
||||
EGL_PLATFORM_GBM_KHR,
|
||||
(void *)b->gbm,
|
||||
EGL_WINDOW_BIT,
|
||||
format,
|
||||
n_formats) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
init_egl(struct drm_backend *b)
|
||||
{
|
||||
b->gbm = create_gbm_device(b->drm.fd);
|
||||
|
||||
if (!b->gbm)
|
||||
return -1;
|
||||
|
||||
if (drm_backend_create_gl_renderer(b) < 0) {
|
||||
gbm_device_destroy(b->gbm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
init_pixman(struct drm_backend *b)
|
||||
{
|
||||
return pixman_renderer_init(b->compositor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a drm_plane for a hardware plane
|
||||
*
|
||||
|
|
@ -1224,146 +1103,6 @@ make_connector_name(const drmModeConnector *con)
|
|||
return name;
|
||||
}
|
||||
|
||||
static void drm_output_fini_cursor_egl(struct drm_output *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
drm_fb_unref(output->gbm_cursor_fb[i]);
|
||||
output->gbm_cursor_fb[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* No point creating cursors if we don't have a plane for them. */
|
||||
if (!output->cursor_plane)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
struct gbm_bo *bo;
|
||||
|
||||
bo = gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height,
|
||||
GBM_FORMAT_ARGB8888,
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||
if (!bo)
|
||||
goto err;
|
||||
|
||||
output->gbm_cursor_fb[i] =
|
||||
drm_fb_get_from_bo(bo, b, false, BUFFER_CURSOR);
|
||||
if (!output->gbm_cursor_fb[i]) {
|
||||
gbm_bo_destroy(bo);
|
||||
goto err;
|
||||
}
|
||||
output->gbm_cursor_handle[i] = gbm_bo_get_handle(bo).s32;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
weston_log("cursor buffers unavailable, using gl cursors\n");
|
||||
b->cursors_are_broken = 1;
|
||||
drm_output_fini_cursor_egl(output);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Init output state that depends on gl or gbm */
|
||||
int
|
||||
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
uint32_t format[2] = {
|
||||
output->gbm_format,
|
||||
fallback_format_for(output->gbm_format),
|
||||
};
|
||||
unsigned n_formats = 1;
|
||||
struct weston_mode *mode = output->base.current_mode;
|
||||
struct drm_plane *plane = output->scanout_plane;
|
||||
unsigned int i;
|
||||
|
||||
assert(output->gbm_surface == NULL);
|
||||
|
||||
for (i = 0; i < plane->count_formats; i++) {
|
||||
if (plane->formats[i].format == output->gbm_format)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == plane->count_formats) {
|
||||
weston_log("format 0x%x not supported by output %s\n",
|
||||
output->gbm_format, output->base.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GBM_MODIFIERS
|
||||
if (plane->formats[i].count_modifiers > 0) {
|
||||
output->gbm_surface =
|
||||
gbm_surface_create_with_modifiers(b->gbm,
|
||||
mode->width,
|
||||
mode->height,
|
||||
output->gbm_format,
|
||||
plane->formats[i].modifiers,
|
||||
plane->formats[i].count_modifiers);
|
||||
}
|
||||
|
||||
/* If allocating with modifiers fails, try again without. This can
|
||||
* happen when the KMS display device supports modifiers but the
|
||||
* GBM driver does not, e.g. the old i915 Mesa driver. */
|
||||
if (!output->gbm_surface)
|
||||
#endif
|
||||
{
|
||||
output->gbm_surface =
|
||||
gbm_surface_create(b->gbm, mode->width, mode->height,
|
||||
output->gbm_format,
|
||||
output->gbm_bo_flags);
|
||||
}
|
||||
|
||||
if (!output->gbm_surface) {
|
||||
weston_log("failed to create gbm surface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (format[1])
|
||||
n_formats = 2;
|
||||
if (gl_renderer->output_window_create(&output->base,
|
||||
(EGLNativeWindowType)output->gbm_surface,
|
||||
output->gbm_surface,
|
||||
format,
|
||||
n_formats) < 0) {
|
||||
weston_log("failed to create gl renderer output state\n");
|
||||
gbm_surface_destroy(output->gbm_surface);
|
||||
output->gbm_surface = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
drm_output_init_cursor_egl(output, b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
drm_output_fini_egl(struct drm_output *output)
|
||||
{
|
||||
struct drm_backend *b = to_drm_backend(output->base.compositor);
|
||||
|
||||
/* Destroying the GBM surface will destroy all our GBM buffers,
|
||||
* regardless of refcount. Ensure we destroy them here. */
|
||||
if (!b->shutting_down &&
|
||||
output->scanout_plane->state_cur->fb &&
|
||||
output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) {
|
||||
drm_plane_state_free(output->scanout_plane->state_cur, true);
|
||||
output->scanout_plane->state_cur =
|
||||
drm_plane_state_alloc(NULL, output->scanout_plane);
|
||||
output->scanout_plane->state_cur->complete = true;
|
||||
}
|
||||
|
||||
gl_renderer->output_destroy(&output->base);
|
||||
gbm_surface_destroy(output->gbm_surface);
|
||||
output->gbm_surface = NULL;
|
||||
drm_output_fini_cursor_egl(output);
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
|
|
@ -2339,7 +2078,9 @@ drm_output_create(struct weston_compositor *compositor, const char *name)
|
|||
return NULL;
|
||||
|
||||
output->backend = b;
|
||||
#ifdef BUILD_DRM_GBM
|
||||
output->gbm_bo_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
|
||||
#endif
|
||||
|
||||
weston_output_init(&output->base, compositor, name);
|
||||
|
||||
|
|
@ -2587,8 +2328,10 @@ drm_destroy(struct weston_compositor *ec)
|
|||
wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
|
||||
drm_head_destroy(to_drm_head(base));
|
||||
|
||||
#ifdef BUILD_DRM_GBM
|
||||
if (b->gbm)
|
||||
gbm_device_destroy(b->gbm);
|
||||
#endif
|
||||
|
||||
udev_monitor_unref(b->udev_monitor);
|
||||
udev_unref(b->udev);
|
||||
|
|
@ -2979,69 +2722,6 @@ recorder_binding(struct weston_keyboard *keyboard, const struct timespec *time,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
switch_to_gl_renderer(struct drm_backend *b)
|
||||
{
|
||||
struct drm_output *output;
|
||||
bool dmabuf_support_inited;
|
||||
bool linux_explicit_sync_inited;
|
||||
|
||||
if (!b->use_pixman)
|
||||
return;
|
||||
|
||||
dmabuf_support_inited = !!b->compositor->renderer->import_dmabuf;
|
||||
linux_explicit_sync_inited =
|
||||
b->compositor->capabilities & WESTON_CAP_EXPLICIT_SYNC;
|
||||
|
||||
weston_log("Switching to GL renderer\n");
|
||||
|
||||
b->gbm = create_gbm_device(b->drm.fd);
|
||||
if (!b->gbm) {
|
||||
weston_log("Failed to create gbm device. "
|
||||
"Aborting renderer switch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_list_for_each(output, &b->compositor->output_list, base.link)
|
||||
pixman_renderer_output_destroy(&output->base);
|
||||
|
||||
b->compositor->renderer->destroy(b->compositor);
|
||||
|
||||
if (drm_backend_create_gl_renderer(b) < 0) {
|
||||
gbm_device_destroy(b->gbm);
|
||||
weston_log("Failed to create GL renderer. Quitting.\n");
|
||||
/* FIXME: we need a function to shutdown cleanly */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
wl_list_for_each(output, &b->compositor->output_list, base.link)
|
||||
drm_output_init_egl(output, b);
|
||||
|
||||
b->use_pixman = 0;
|
||||
|
||||
if (!dmabuf_support_inited && b->compositor->renderer->import_dmabuf) {
|
||||
if (linux_dmabuf_setup(b->compositor) < 0)
|
||||
weston_log("Error: initializing dmabuf "
|
||||
"support failed.\n");
|
||||
}
|
||||
|
||||
if (!linux_explicit_sync_inited &&
|
||||
(b->compositor->capabilities & WESTON_CAP_EXPLICIT_SYNC)) {
|
||||
if (linux_explicit_synchronization_setup(b->compositor) < 0)
|
||||
weston_log("Error: initializing explicit "
|
||||
" synchronization support failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
renderer_switch_binding(struct weston_keyboard *keyboard,
|
||||
const struct timespec *time, uint32_t key, void *data)
|
||||
{
|
||||
struct drm_backend *b =
|
||||
to_drm_backend(keyboard->seat->compositor);
|
||||
|
||||
switch_to_gl_renderer(b);
|
||||
}
|
||||
|
||||
static const struct weston_drm_output_api api = {
|
||||
drm_output_set_mode,
|
||||
|
|
@ -3242,8 +2922,10 @@ err_drm_source:
|
|||
err_udev_input:
|
||||
udev_input_destroy(&b->input);
|
||||
err_sprite:
|
||||
#ifdef BUILD_DRM_GBM
|
||||
if (b->gbm)
|
||||
gbm_device_destroy(b->gbm);
|
||||
#endif
|
||||
destroy_sprites(b);
|
||||
err_udev_dev:
|
||||
udev_device_unref(drm_device);
|
||||
|
|
|
|||
|
|
@ -70,16 +70,6 @@ drm_fb_destroy_dumb(struct drm_fb *fb)
|
|||
drm_fb_destroy(fb);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_fb_destroy_gbm(struct gbm_bo *bo, void *data)
|
||||
{
|
||||
struct drm_fb *fb = data;
|
||||
|
||||
assert(fb->type == BUFFER_GBM_SURFACE || fb->type == BUFFER_CLIENT ||
|
||||
fb->type == BUFFER_CURSOR);
|
||||
drm_fb_destroy(fb);
|
||||
}
|
||||
|
||||
static int
|
||||
drm_fb_addfb(struct drm_backend *b, struct drm_fb *fb)
|
||||
{
|
||||
|
|
@ -211,6 +201,17 @@ drm_fb_ref(struct drm_fb *fb)
|
|||
return fb;
|
||||
}
|
||||
|
||||
#ifdef BUILD_DRM_GBM
|
||||
static void
|
||||
drm_fb_destroy_gbm(struct gbm_bo *bo, void *data)
|
||||
{
|
||||
struct drm_fb *fb = data;
|
||||
|
||||
assert(fb->type == BUFFER_GBM_SURFACE || fb->type == BUFFER_CLIENT ||
|
||||
fb->type == BUFFER_CURSOR);
|
||||
drm_fb_destroy(fb);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_fb_destroy_dmabuf(struct drm_fb *fb)
|
||||
{
|
||||
|
|
@ -450,6 +451,7 @@ drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer,
|
|||
weston_buffer_release_reference(&fb->buffer_release_ref,
|
||||
buffer_release);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
drm_fb_unref(struct drm_fb *fb)
|
||||
|
|
@ -465,6 +467,7 @@ drm_fb_unref(struct drm_fb *fb)
|
|||
case BUFFER_PIXMAN_DUMB:
|
||||
drm_fb_destroy_dumb(fb);
|
||||
break;
|
||||
#ifdef BUILD_DRM_GBM
|
||||
case BUFFER_CURSOR:
|
||||
case BUFFER_CLIENT:
|
||||
gbm_bo_destroy(fb->bo);
|
||||
|
|
@ -475,12 +478,14 @@ drm_fb_unref(struct drm_fb *fb)
|
|||
case BUFFER_DMABUF:
|
||||
drm_fb_destroy_dmabuf(fb);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BUILD_DRM_GBM
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev)
|
||||
{
|
||||
|
|
@ -537,3 +542,4 @@ drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev)
|
|||
ev->surface->buffer_release_ref.buffer_release);
|
||||
return fb;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -41,11 +41,10 @@ deps_drm = [
|
|||
dep_backlight
|
||||
]
|
||||
|
||||
# XXX: Actually let DRM-backend build without GBM, it really should
|
||||
if true # get_option('renderer-gl')
|
||||
if get_option('renderer-gl')
|
||||
dep_gbm = dependency('gbm', required: false)
|
||||
if not dep_gbm.found()
|
||||
error('drm-backend requires gbm which was not found. Or, you can use \'-Dbackend-drm=false\'.')
|
||||
error('drm-backend with GL renderer requires gbm which was not found. Or, you can use \'-Drenderer-gl=false\'.')
|
||||
endif
|
||||
if dep_gbm.version().version_compare('>= 17.1')
|
||||
config_h.set('HAVE_GBM_MODIFIERS', '1')
|
||||
|
|
@ -54,6 +53,8 @@ if true # get_option('renderer-gl')
|
|||
config_h.set('HAVE_GBM_FD_IMPORT', '1')
|
||||
endif
|
||||
deps_drm += dep_gbm
|
||||
srcs_drm += 'drm-gbm.c'
|
||||
config_h.set('BUILD_DRM_GBM', '1')
|
||||
endif
|
||||
|
||||
if get_option('backend-drm-screencast-vaapi')
|
||||
|
|
@ -71,6 +72,9 @@ if get_option('backend-drm-screencast-vaapi')
|
|||
endif
|
||||
|
||||
if get_option('remoting')
|
||||
if not get_option('renderer-gl')
|
||||
warning('DRM virtual requires renderer-gl.')
|
||||
endif
|
||||
srcs_drm += 'drm-virtual.c'
|
||||
config_h.set('BUILD_DRM_VIRTUAL', '1')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ out:
|
|||
return state;
|
||||
}
|
||||
|
||||
#ifdef BUILD_DRM_GBM
|
||||
/**
|
||||
* Update the image for the current cursor surface
|
||||
*
|
||||
|
|
@ -361,6 +362,14 @@ err:
|
|||
drm_plane_state_put_back(plane_state);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static struct drm_plane_state *
|
||||
drm_output_prepare_cursor_view(struct drm_output_state *output_state,
|
||||
struct weston_view *ev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct drm_plane_state *
|
||||
drm_output_prepare_scanout_view(struct drm_output_state *output_state,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue