compositor-drm: Create header for backend internals
Create a new header called drm-internal.h, and move many of drm.c's declarations and helpers to it. This will allow us to split the DRM backend into multiple files. Signed-off-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
@@ -0,0 +1,503 @@
|
|||||||
|
/*
|
||||||
|
* 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 <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/vt.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <xf86drm.h>
|
||||||
|
#include <xf86drmMode.h>
|
||||||
|
#include <drm_fourcc.h>
|
||||||
|
|
||||||
|
#include <gbm.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
|
||||||
|
#include <libweston/libweston.h>
|
||||||
|
#include <libweston/backend-drm.h>
|
||||||
|
#include <libweston/weston-debug.h>
|
||||||
|
#include "shared/helpers.h"
|
||||||
|
#include "libinput-seat.h"
|
||||||
|
|
||||||
|
#ifndef DRM_CLIENT_CAP_ASPECT_RATIO
|
||||||
|
#define DRM_CLIENT_CAP_ASPECT_RATIO 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GBM_BO_USE_CURSOR
|
||||||
|
#define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GBM_BO_USE_LINEAR
|
||||||
|
#define GBM_BO_USE_LINEAR (1 << 4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A small wrapper to print information into the 'drm-backend' debug scope.
|
||||||
|
*
|
||||||
|
* The following conventions are used to print variables:
|
||||||
|
*
|
||||||
|
* - fixed uint32_t values, including Weston object IDs such as weston_output
|
||||||
|
* IDs, DRM object IDs such as CRTCs or properties, and GBM/DRM formats:
|
||||||
|
* "%lu (0x%lx)" (unsigned long) value, (unsigned long) value
|
||||||
|
*
|
||||||
|
* - fixed uint64_t values, such as DRM property values (including object IDs
|
||||||
|
* when used as a value):
|
||||||
|
* "%llu (0x%llx)" (unsigned long long) value, (unsigned long long) value
|
||||||
|
*
|
||||||
|
* - non-fixed-width signed int:
|
||||||
|
* "%d" value
|
||||||
|
*
|
||||||
|
* - non-fixed-width unsigned int:
|
||||||
|
* "%u (0x%x)" value, value
|
||||||
|
*
|
||||||
|
* - non-fixed-width unsigned long:
|
||||||
|
* "%lu (0x%lx)" value, value
|
||||||
|
*
|
||||||
|
* Either the integer or hexadecimal forms may be omitted if it is known that
|
||||||
|
* one representation is not useful (e.g. width/height in hex are rarely what
|
||||||
|
* you want).
|
||||||
|
*
|
||||||
|
* This is to avoid implicit widening or narrowing when we use fixed-size
|
||||||
|
* types: uint32_t can be resolved by either unsigned int or unsigned long
|
||||||
|
* on a 32-bit system but only unsigned int on a 64-bit system, with uint64_t
|
||||||
|
* being unsigned long long on a 32-bit system and unsigned long on a 64-bit
|
||||||
|
* system. To avoid confusing side effects, we explicitly cast to the widest
|
||||||
|
* possible type and use a matching format specifier.
|
||||||
|
*/
|
||||||
|
#define drm_debug(b, ...) \
|
||||||
|
weston_log_scope_printf((b)->debug, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MAX_CLONED_CONNECTORS 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aspect ratio info taken from the drmModeModeInfo flag bits 19-22,
|
||||||
|
* which should be used to fill the aspect ratio field in weston_mode.
|
||||||
|
*/
|
||||||
|
#define DRM_MODE_FLAG_PIC_AR_BITS_POS 19
|
||||||
|
#ifndef DRM_MODE_FLAG_PIC_AR_MASK
|
||||||
|
#define DRM_MODE_FLAG_PIC_AR_MASK (0xF << DRM_MODE_FLAG_PIC_AR_BITS_POS)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the values of an enum-type KMS property
|
||||||
|
*/
|
||||||
|
struct drm_property_enum_info {
|
||||||
|
const char *name; /**< name as string (static, not freed) */
|
||||||
|
bool valid; /**< true if value is supported; ignore if false */
|
||||||
|
uint64_t value; /**< raw value */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds information on a DRM property, including its ID and the enum
|
||||||
|
* values it holds.
|
||||||
|
*
|
||||||
|
* DRM properties are allocated dynamically, and maintained as DRM objects
|
||||||
|
* within the normal object ID space; they thus do not have a stable ID
|
||||||
|
* to refer to. This includes enum values, which must be referred to by
|
||||||
|
* integer values, but these are not stable.
|
||||||
|
*
|
||||||
|
* drm_property_info allows a cache to be maintained where Weston can use
|
||||||
|
* enum values internally to refer to properties, with the mapping to DRM
|
||||||
|
* ID values being maintained internally.
|
||||||
|
*/
|
||||||
|
struct drm_property_info {
|
||||||
|
const char *name; /**< name as string (static, not freed) */
|
||||||
|
uint32_t prop_id; /**< KMS property object ID */
|
||||||
|
unsigned int num_enum_values; /**< number of enum values */
|
||||||
|
struct drm_property_enum_info *enum_values; /**< array of enum values */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of properties attached to DRM planes
|
||||||
|
*/
|
||||||
|
enum wdrm_plane_property {
|
||||||
|
WDRM_PLANE_TYPE = 0,
|
||||||
|
WDRM_PLANE_SRC_X,
|
||||||
|
WDRM_PLANE_SRC_Y,
|
||||||
|
WDRM_PLANE_SRC_W,
|
||||||
|
WDRM_PLANE_SRC_H,
|
||||||
|
WDRM_PLANE_CRTC_X,
|
||||||
|
WDRM_PLANE_CRTC_Y,
|
||||||
|
WDRM_PLANE_CRTC_W,
|
||||||
|
WDRM_PLANE_CRTC_H,
|
||||||
|
WDRM_PLANE_FB_ID,
|
||||||
|
WDRM_PLANE_CRTC_ID,
|
||||||
|
WDRM_PLANE_IN_FORMATS,
|
||||||
|
WDRM_PLANE_IN_FENCE_FD,
|
||||||
|
WDRM_PLANE_FB_DAMAGE_CLIPS,
|
||||||
|
WDRM_PLANE__COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible values for the WDRM_PLANE_TYPE property.
|
||||||
|
*/
|
||||||
|
enum wdrm_plane_type {
|
||||||
|
WDRM_PLANE_TYPE_PRIMARY = 0,
|
||||||
|
WDRM_PLANE_TYPE_CURSOR,
|
||||||
|
WDRM_PLANE_TYPE_OVERLAY,
|
||||||
|
WDRM_PLANE_TYPE__COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of properties attached to a DRM connector
|
||||||
|
*/
|
||||||
|
enum wdrm_connector_property {
|
||||||
|
WDRM_CONNECTOR_EDID = 0,
|
||||||
|
WDRM_CONNECTOR_DPMS,
|
||||||
|
WDRM_CONNECTOR_CRTC_ID,
|
||||||
|
WDRM_CONNECTOR_NON_DESKTOP,
|
||||||
|
WDRM_CONNECTOR__COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum wdrm_dpms_state {
|
||||||
|
WDRM_DPMS_STATE_OFF = 0,
|
||||||
|
WDRM_DPMS_STATE_ON,
|
||||||
|
WDRM_DPMS_STATE_STANDBY, /* unused */
|
||||||
|
WDRM_DPMS_STATE_SUSPEND, /* unused */
|
||||||
|
WDRM_DPMS_STATE__COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of properties attached to DRM CRTCs
|
||||||
|
*/
|
||||||
|
enum wdrm_crtc_property {
|
||||||
|
WDRM_CRTC_MODE_ID = 0,
|
||||||
|
WDRM_CRTC_ACTIVE,
|
||||||
|
WDRM_CRTC__COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_backend {
|
||||||
|
struct weston_backend base;
|
||||||
|
struct weston_compositor *compositor;
|
||||||
|
|
||||||
|
struct udev *udev;
|
||||||
|
struct wl_event_source *drm_source;
|
||||||
|
|
||||||
|
struct udev_monitor *udev_monitor;
|
||||||
|
struct wl_event_source *udev_drm_source;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int id;
|
||||||
|
int fd;
|
||||||
|
char *filename;
|
||||||
|
dev_t devnum;
|
||||||
|
} drm;
|
||||||
|
struct gbm_device *gbm;
|
||||||
|
struct wl_listener session_listener;
|
||||||
|
uint32_t gbm_format;
|
||||||
|
|
||||||
|
/* we need these parameters in order to not fail drmModeAddFB2()
|
||||||
|
* due to out of bounds dimensions, and then mistakenly set
|
||||||
|
* sprites_are_broken:
|
||||||
|
*/
|
||||||
|
int min_width, max_width;
|
||||||
|
int min_height, max_height;
|
||||||
|
|
||||||
|
struct wl_list plane_list;
|
||||||
|
int sprites_are_broken;
|
||||||
|
int sprites_hidden;
|
||||||
|
|
||||||
|
void *repaint_data;
|
||||||
|
|
||||||
|
bool state_invalid;
|
||||||
|
|
||||||
|
/* CRTC IDs not used by any enabled output. */
|
||||||
|
struct wl_array unused_crtcs;
|
||||||
|
|
||||||
|
int cursors_are_broken;
|
||||||
|
|
||||||
|
bool universal_planes;
|
||||||
|
bool atomic_modeset;
|
||||||
|
|
||||||
|
bool use_pixman;
|
||||||
|
bool use_pixman_shadow;
|
||||||
|
|
||||||
|
struct udev_input input;
|
||||||
|
|
||||||
|
int32_t cursor_width;
|
||||||
|
int32_t cursor_height;
|
||||||
|
|
||||||
|
uint32_t pageflip_timeout;
|
||||||
|
|
||||||
|
bool shutting_down;
|
||||||
|
|
||||||
|
bool aspect_ratio_supported;
|
||||||
|
|
||||||
|
bool fb_modifiers;
|
||||||
|
|
||||||
|
struct weston_log_scope *debug;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_mode {
|
||||||
|
struct weston_mode base;
|
||||||
|
drmModeModeInfo mode_info;
|
||||||
|
uint32_t blob_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum drm_fb_type {
|
||||||
|
BUFFER_INVALID = 0, /**< never used */
|
||||||
|
BUFFER_CLIENT, /**< directly sourced from client */
|
||||||
|
BUFFER_DMABUF, /**< imported from linux_dmabuf client */
|
||||||
|
BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
|
||||||
|
BUFFER_GBM_SURFACE, /**< internal EGL rendering */
|
||||||
|
BUFFER_CURSOR, /**< internal cursor buffer */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_fb {
|
||||||
|
enum drm_fb_type type;
|
||||||
|
|
||||||
|
int refcnt;
|
||||||
|
|
||||||
|
uint32_t fb_id, size;
|
||||||
|
uint32_t handles[4];
|
||||||
|
uint32_t strides[4];
|
||||||
|
uint32_t offsets[4];
|
||||||
|
int num_planes;
|
||||||
|
const struct pixel_format_info *format;
|
||||||
|
uint64_t modifier;
|
||||||
|
int width, height;
|
||||||
|
int fd;
|
||||||
|
struct weston_buffer_reference buffer_ref;
|
||||||
|
struct weston_buffer_release_reference buffer_release_ref;
|
||||||
|
|
||||||
|
/* Used by gbm fbs */
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
struct gbm_surface *gbm_surface;
|
||||||
|
|
||||||
|
/* Used by dumb fbs */
|
||||||
|
void *map;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_edid {
|
||||||
|
char eisa_id[13];
|
||||||
|
char monitor_name[13];
|
||||||
|
char pnp_id[5];
|
||||||
|
char serial_number[13];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pending state holds one or more drm_output_state structures, collected from
|
||||||
|
* performing repaint. This pending state is transient, and only lives between
|
||||||
|
* beginning a repaint group and flushing the results: after flush, each
|
||||||
|
* output state will complete and be retired separately.
|
||||||
|
*/
|
||||||
|
struct drm_pending_state {
|
||||||
|
struct drm_backend *backend;
|
||||||
|
struct wl_list output_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
|
||||||
|
* plus >= 1 each of encoder/connector/plane. Since everything but the planes
|
||||||
|
* is currently statically assigned per-output, we mainly use this to track
|
||||||
|
* plane state.
|
||||||
|
*
|
||||||
|
* pending_state is set when the output state is owned by a pending_state,
|
||||||
|
* i.e. when it is being constructed and has not yet been applied. When the
|
||||||
|
* output state has been applied, the owning pending_state is freed.
|
||||||
|
*/
|
||||||
|
struct drm_output_state {
|
||||||
|
struct drm_pending_state *pending_state;
|
||||||
|
struct drm_output *output;
|
||||||
|
struct wl_list link;
|
||||||
|
enum dpms_enum dpms;
|
||||||
|
struct wl_list plane_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plane state holds the dynamic state for a plane: where it is positioned,
|
||||||
|
* and which buffer it is currently displaying.
|
||||||
|
*
|
||||||
|
* The plane state is owned by an output state, except when setting an initial
|
||||||
|
* state. See drm_output_state for notes on state object lifetime.
|
||||||
|
*/
|
||||||
|
struct drm_plane_state {
|
||||||
|
struct drm_plane *plane;
|
||||||
|
struct drm_output *output;
|
||||||
|
struct drm_output_state *output_state;
|
||||||
|
|
||||||
|
struct drm_fb *fb;
|
||||||
|
|
||||||
|
struct weston_view *ev; /**< maintained for drm_assign_planes only */
|
||||||
|
|
||||||
|
int32_t src_x, src_y;
|
||||||
|
uint32_t src_w, src_h;
|
||||||
|
int32_t dest_x, dest_y;
|
||||||
|
uint32_t dest_w, dest_h;
|
||||||
|
|
||||||
|
bool complete;
|
||||||
|
|
||||||
|
/* We don't own the fd, so we shouldn't close it */
|
||||||
|
int in_fence_fd;
|
||||||
|
|
||||||
|
pixman_region32_t damage; /* damage to kernel */
|
||||||
|
|
||||||
|
struct wl_list link; /* drm_output_state::plane_list */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A plane represents one buffer, positioned within a CRTC, and stacked
|
||||||
|
* relative to other planes on the same CRTC.
|
||||||
|
*
|
||||||
|
* Each CRTC has a 'primary plane', which use used to display the classic
|
||||||
|
* framebuffer contents, as accessed through the legacy drmModeSetCrtc
|
||||||
|
* call (which combines setting the CRTC's actual physical mode, and the
|
||||||
|
* properties of the primary plane).
|
||||||
|
*
|
||||||
|
* The cursor plane also has its own alternate legacy API.
|
||||||
|
*
|
||||||
|
* Other planes are used opportunistically to display content we do not
|
||||||
|
* wish to blit into the primary plane. These non-primary/cursor planes
|
||||||
|
* are referred to as 'sprites'.
|
||||||
|
*/
|
||||||
|
struct drm_plane {
|
||||||
|
struct weston_plane base;
|
||||||
|
|
||||||
|
struct drm_backend *backend;
|
||||||
|
|
||||||
|
enum wdrm_plane_type type;
|
||||||
|
|
||||||
|
uint32_t possible_crtcs;
|
||||||
|
uint32_t plane_id;
|
||||||
|
uint32_t count_formats;
|
||||||
|
|
||||||
|
struct drm_property_info props[WDRM_PLANE__COUNT];
|
||||||
|
|
||||||
|
/* The last state submitted to the kernel for this plane. */
|
||||||
|
struct drm_plane_state *state_cur;
|
||||||
|
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t format;
|
||||||
|
uint32_t count_modifiers;
|
||||||
|
uint64_t *modifiers;
|
||||||
|
} formats[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_head {
|
||||||
|
struct weston_head base;
|
||||||
|
struct drm_backend *backend;
|
||||||
|
|
||||||
|
drmModeConnector *connector;
|
||||||
|
uint32_t connector_id;
|
||||||
|
struct drm_edid edid;
|
||||||
|
|
||||||
|
/* Holds the properties for the connector */
|
||||||
|
struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];
|
||||||
|
|
||||||
|
struct backlight *backlight;
|
||||||
|
|
||||||
|
drmModeModeInfo inherited_mode; /**< Original mode on the connector */
|
||||||
|
uint32_t inherited_crtc_id; /**< Original CRTC assignment */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_output {
|
||||||
|
struct weston_output base;
|
||||||
|
struct drm_backend *backend;
|
||||||
|
|
||||||
|
uint32_t crtc_id; /* object ID to pass to DRM functions */
|
||||||
|
int pipe; /* index of CRTC in resource array / bitmasks */
|
||||||
|
|
||||||
|
/* Holds the properties for the CRTC */
|
||||||
|
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
|
||||||
|
|
||||||
|
int page_flip_pending;
|
||||||
|
int atomic_complete_pending;
|
||||||
|
int destroy_pending;
|
||||||
|
int disable_pending;
|
||||||
|
int dpms_off_pending;
|
||||||
|
|
||||||
|
struct drm_fb *gbm_cursor_fb[2];
|
||||||
|
struct drm_plane *cursor_plane;
|
||||||
|
struct weston_view *cursor_view;
|
||||||
|
int current_cursor;
|
||||||
|
|
||||||
|
struct gbm_surface *gbm_surface;
|
||||||
|
uint32_t gbm_format;
|
||||||
|
uint32_t gbm_bo_flags;
|
||||||
|
|
||||||
|
/* Plane being displayed directly on the CRTC */
|
||||||
|
struct drm_plane *scanout_plane;
|
||||||
|
|
||||||
|
/* The last state submitted to the kernel for this CRTC. */
|
||||||
|
struct drm_output_state *state_cur;
|
||||||
|
/* The previously-submitted state, where the hardware has not
|
||||||
|
* yet acknowledged completion of state_cur. */
|
||||||
|
struct drm_output_state *state_last;
|
||||||
|
|
||||||
|
struct drm_fb *dumb[2];
|
||||||
|
pixman_image_t *image[2];
|
||||||
|
int current_image;
|
||||||
|
pixman_region32_t previous_damage;
|
||||||
|
|
||||||
|
struct vaapi_recorder *recorder;
|
||||||
|
struct wl_listener recorder_frame_listener;
|
||||||
|
|
||||||
|
struct wl_event_source *pageflip_timer;
|
||||||
|
|
||||||
|
bool virtual;
|
||||||
|
|
||||||
|
submit_frame_cb virtual_submit_frame;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct drm_head *
|
||||||
|
to_drm_head(struct weston_head *base)
|
||||||
|
{
|
||||||
|
return container_of(base, struct drm_head, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct drm_output *
|
||||||
|
to_drm_output(struct weston_output *base)
|
||||||
|
{
|
||||||
|
return container_of(base, struct drm_output, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct drm_backend *
|
||||||
|
to_drm_backend(struct weston_compositor *base)
|
||||||
|
{
|
||||||
|
return container_of(base->backend, struct drm_backend, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct drm_mode *
|
||||||
|
to_drm_mode(struct weston_mode *base)
|
||||||
|
{
|
||||||
|
return container_of(base, struct drm_mode, base);
|
||||||
|
}
|
||||||
+1
-446
@@ -53,6 +53,7 @@
|
|||||||
#include <libweston/libweston.h>
|
#include <libweston/libweston.h>
|
||||||
#include <libweston/backend-drm.h>
|
#include <libweston/backend-drm.h>
|
||||||
#include <libweston/weston-debug.h>
|
#include <libweston/weston-debug.h>
|
||||||
|
#include "drm-internal.h"
|
||||||
#include "shared/helpers.h"
|
#include "shared/helpers.h"
|
||||||
#include "shared/timespec-util.h"
|
#include "shared/timespec-util.h"
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
@@ -68,125 +69,6 @@
|
|||||||
#include "linux-dmabuf-unstable-v1-server-protocol.h"
|
#include "linux-dmabuf-unstable-v1-server-protocol.h"
|
||||||
#include "linux-explicit-synchronization.h"
|
#include "linux-explicit-synchronization.h"
|
||||||
|
|
||||||
#ifndef DRM_CLIENT_CAP_ASPECT_RATIO
|
|
||||||
#define DRM_CLIENT_CAP_ASPECT_RATIO 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GBM_BO_USE_CURSOR
|
|
||||||
#define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GBM_BO_USE_LINEAR
|
|
||||||
#define GBM_BO_USE_LINEAR (1 << 4)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A small wrapper to print information into the 'drm-backend' debug scope.
|
|
||||||
*
|
|
||||||
* The following conventions are used to print variables:
|
|
||||||
*
|
|
||||||
* - fixed uint32_t values, including Weston object IDs such as weston_output
|
|
||||||
* IDs, DRM object IDs such as CRTCs or properties, and GBM/DRM formats:
|
|
||||||
* "%lu (0x%lx)" (unsigned long) value, (unsigned long) value
|
|
||||||
*
|
|
||||||
* - fixed uint64_t values, such as DRM property values (including object IDs
|
|
||||||
* when used as a value):
|
|
||||||
* "%llu (0x%llx)" (unsigned long long) value, (unsigned long long) value
|
|
||||||
*
|
|
||||||
* - non-fixed-width signed int:
|
|
||||||
* "%d" value
|
|
||||||
*
|
|
||||||
* - non-fixed-width unsigned int:
|
|
||||||
* "%u (0x%x)" value, value
|
|
||||||
*
|
|
||||||
* - non-fixed-width unsigned long:
|
|
||||||
* "%lu (0x%lx)" value, value
|
|
||||||
*
|
|
||||||
* Either the integer or hexadecimal forms may be omitted if it is known that
|
|
||||||
* one representation is not useful (e.g. width/height in hex are rarely what
|
|
||||||
* you want).
|
|
||||||
*
|
|
||||||
* This is to avoid implicit widening or narrowing when we use fixed-size
|
|
||||||
* types: uint32_t can be resolved by either unsigned int or unsigned long
|
|
||||||
* on a 32-bit system but only unsigned int on a 64-bit system, with uint64_t
|
|
||||||
* being unsigned long long on a 32-bit system and unsigned long on a 64-bit
|
|
||||||
* system. To avoid confusing side effects, we explicitly cast to the widest
|
|
||||||
* possible type and use a matching format specifier.
|
|
||||||
*/
|
|
||||||
#define drm_debug(b, ...) \
|
|
||||||
weston_log_scope_printf((b)->debug, __VA_ARGS__)
|
|
||||||
|
|
||||||
#define MAX_CLONED_CONNECTORS 4
|
|
||||||
|
|
||||||
/**
|
|
||||||
* aspect ratio info taken from the drmModeModeInfo flag bits 19-22,
|
|
||||||
* which should be used to fill the aspect ratio field in weston_mode.
|
|
||||||
*/
|
|
||||||
#define DRM_MODE_FLAG_PIC_AR_BITS_POS 19
|
|
||||||
#ifndef DRM_MODE_FLAG_PIC_AR_MASK
|
|
||||||
#define DRM_MODE_FLAG_PIC_AR_MASK (0xF << DRM_MODE_FLAG_PIC_AR_BITS_POS)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the values of an enum-type KMS property
|
|
||||||
*/
|
|
||||||
struct drm_property_enum_info {
|
|
||||||
const char *name; /**< name as string (static, not freed) */
|
|
||||||
bool valid; /**< true if value is supported; ignore if false */
|
|
||||||
uint64_t value; /**< raw value */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds information on a DRM property, including its ID and the enum
|
|
||||||
* values it holds.
|
|
||||||
*
|
|
||||||
* DRM properties are allocated dynamically, and maintained as DRM objects
|
|
||||||
* within the normal object ID space; they thus do not have a stable ID
|
|
||||||
* to refer to. This includes enum values, which must be referred to by
|
|
||||||
* integer values, but these are not stable.
|
|
||||||
*
|
|
||||||
* drm_property_info allows a cache to be maintained where Weston can use
|
|
||||||
* enum values internally to refer to properties, with the mapping to DRM
|
|
||||||
* ID values being maintained internally.
|
|
||||||
*/
|
|
||||||
struct drm_property_info {
|
|
||||||
const char *name; /**< name as string (static, not freed) */
|
|
||||||
uint32_t prop_id; /**< KMS property object ID */
|
|
||||||
unsigned int num_enum_values; /**< number of enum values */
|
|
||||||
struct drm_property_enum_info *enum_values; /**< array of enum values */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of properties attached to DRM planes
|
|
||||||
*/
|
|
||||||
enum wdrm_plane_property {
|
|
||||||
WDRM_PLANE_TYPE = 0,
|
|
||||||
WDRM_PLANE_SRC_X,
|
|
||||||
WDRM_PLANE_SRC_Y,
|
|
||||||
WDRM_PLANE_SRC_W,
|
|
||||||
WDRM_PLANE_SRC_H,
|
|
||||||
WDRM_PLANE_CRTC_X,
|
|
||||||
WDRM_PLANE_CRTC_Y,
|
|
||||||
WDRM_PLANE_CRTC_W,
|
|
||||||
WDRM_PLANE_CRTC_H,
|
|
||||||
WDRM_PLANE_FB_ID,
|
|
||||||
WDRM_PLANE_CRTC_ID,
|
|
||||||
WDRM_PLANE_IN_FORMATS,
|
|
||||||
WDRM_PLANE_IN_FENCE_FD,
|
|
||||||
WDRM_PLANE_FB_DAMAGE_CLIPS,
|
|
||||||
WDRM_PLANE__COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Possible values for the WDRM_PLANE_TYPE property.
|
|
||||||
*/
|
|
||||||
enum wdrm_plane_type {
|
|
||||||
WDRM_PLANE_TYPE_PRIMARY = 0,
|
|
||||||
WDRM_PLANE_TYPE_CURSOR,
|
|
||||||
WDRM_PLANE_TYPE_OVERLAY,
|
|
||||||
WDRM_PLANE_TYPE__COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct drm_property_enum_info plane_type_enums[] = {
|
static struct drm_property_enum_info plane_type_enums[] = {
|
||||||
[WDRM_PLANE_TYPE_PRIMARY] = {
|
[WDRM_PLANE_TYPE_PRIMARY] = {
|
||||||
.name = "Primary",
|
.name = "Primary",
|
||||||
@@ -220,25 +102,6 @@ static const struct drm_property_info plane_props[] = {
|
|||||||
[WDRM_PLANE_FB_DAMAGE_CLIPS] = { .name = "FB_DAMAGE_CLIPS" },
|
[WDRM_PLANE_FB_DAMAGE_CLIPS] = { .name = "FB_DAMAGE_CLIPS" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* List of properties attached to a DRM connector
|
|
||||||
*/
|
|
||||||
enum wdrm_connector_property {
|
|
||||||
WDRM_CONNECTOR_EDID = 0,
|
|
||||||
WDRM_CONNECTOR_DPMS,
|
|
||||||
WDRM_CONNECTOR_CRTC_ID,
|
|
||||||
WDRM_CONNECTOR_NON_DESKTOP,
|
|
||||||
WDRM_CONNECTOR__COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum wdrm_dpms_state {
|
|
||||||
WDRM_DPMS_STATE_OFF = 0,
|
|
||||||
WDRM_DPMS_STATE_ON,
|
|
||||||
WDRM_DPMS_STATE_STANDBY, /* unused */
|
|
||||||
WDRM_DPMS_STATE_SUSPEND, /* unused */
|
|
||||||
WDRM_DPMS_STATE__COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct drm_property_enum_info dpms_state_enums[] = {
|
static struct drm_property_enum_info dpms_state_enums[] = {
|
||||||
[WDRM_DPMS_STATE_OFF] = {
|
[WDRM_DPMS_STATE_OFF] = {
|
||||||
.name = "Off",
|
.name = "Off",
|
||||||
@@ -265,15 +128,6 @@ static const struct drm_property_info connector_props[] = {
|
|||||||
[WDRM_CONNECTOR_NON_DESKTOP] = { .name = "non-desktop", },
|
[WDRM_CONNECTOR_NON_DESKTOP] = { .name = "non-desktop", },
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* List of properties attached to DRM CRTCs
|
|
||||||
*/
|
|
||||||
enum wdrm_crtc_property {
|
|
||||||
WDRM_CRTC_MODE_ID = 0,
|
|
||||||
WDRM_CRTC_ACTIVE,
|
|
||||||
WDRM_CRTC__COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct drm_property_info crtc_props[] = {
|
static const struct drm_property_info crtc_props[] = {
|
||||||
[WDRM_CRTC_MODE_ID] = { .name = "MODE_ID", },
|
[WDRM_CRTC_MODE_ID] = { .name = "MODE_ID", },
|
||||||
[WDRM_CRTC_ACTIVE] = { .name = "ACTIVE", },
|
[WDRM_CRTC_ACTIVE] = { .name = "ACTIVE", },
|
||||||
@@ -296,287 +150,12 @@ enum drm_state_apply_mode {
|
|||||||
DRM_STATE_TEST_ONLY, /**< test if the state can be applied */
|
DRM_STATE_TEST_ONLY, /**< test if the state can be applied */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_backend {
|
|
||||||
struct weston_backend base;
|
|
||||||
struct weston_compositor *compositor;
|
|
||||||
|
|
||||||
struct udev *udev;
|
|
||||||
struct wl_event_source *drm_source;
|
|
||||||
|
|
||||||
struct udev_monitor *udev_monitor;
|
|
||||||
struct wl_event_source *udev_drm_source;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
int id;
|
|
||||||
int fd;
|
|
||||||
char *filename;
|
|
||||||
dev_t devnum;
|
|
||||||
} drm;
|
|
||||||
struct gbm_device *gbm;
|
|
||||||
struct wl_listener session_listener;
|
|
||||||
uint32_t gbm_format;
|
|
||||||
|
|
||||||
/* we need these parameters in order to not fail drmModeAddFB2()
|
|
||||||
* due to out of bounds dimensions, and then mistakenly set
|
|
||||||
* sprites_are_broken:
|
|
||||||
*/
|
|
||||||
int min_width, max_width;
|
|
||||||
int min_height, max_height;
|
|
||||||
|
|
||||||
struct wl_list plane_list;
|
|
||||||
int sprites_are_broken;
|
|
||||||
int sprites_hidden;
|
|
||||||
|
|
||||||
void *repaint_data;
|
|
||||||
|
|
||||||
bool state_invalid;
|
|
||||||
|
|
||||||
/* CRTC IDs not used by any enabled output. */
|
|
||||||
struct wl_array unused_crtcs;
|
|
||||||
|
|
||||||
int cursors_are_broken;
|
|
||||||
|
|
||||||
bool universal_planes;
|
|
||||||
bool atomic_modeset;
|
|
||||||
|
|
||||||
bool use_pixman;
|
|
||||||
bool use_pixman_shadow;
|
|
||||||
|
|
||||||
struct udev_input input;
|
|
||||||
|
|
||||||
int32_t cursor_width;
|
|
||||||
int32_t cursor_height;
|
|
||||||
|
|
||||||
uint32_t pageflip_timeout;
|
|
||||||
|
|
||||||
bool shutting_down;
|
|
||||||
|
|
||||||
bool aspect_ratio_supported;
|
|
||||||
|
|
||||||
bool fb_modifiers;
|
|
||||||
|
|
||||||
struct weston_log_scope *debug;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_mode {
|
|
||||||
struct weston_mode base;
|
|
||||||
drmModeModeInfo mode_info;
|
|
||||||
uint32_t blob_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum drm_fb_type {
|
|
||||||
BUFFER_INVALID = 0, /**< never used */
|
|
||||||
BUFFER_CLIENT, /**< directly sourced from client */
|
|
||||||
BUFFER_DMABUF, /**< imported from linux_dmabuf client */
|
|
||||||
BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
|
|
||||||
BUFFER_GBM_SURFACE, /**< internal EGL rendering */
|
|
||||||
BUFFER_CURSOR, /**< internal cursor buffer */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_fb {
|
|
||||||
enum drm_fb_type type;
|
|
||||||
|
|
||||||
int refcnt;
|
|
||||||
|
|
||||||
uint32_t fb_id, size;
|
|
||||||
uint32_t handles[4];
|
|
||||||
uint32_t strides[4];
|
|
||||||
uint32_t offsets[4];
|
|
||||||
int num_planes;
|
|
||||||
const struct pixel_format_info *format;
|
|
||||||
uint64_t modifier;
|
|
||||||
int width, height;
|
|
||||||
int fd;
|
|
||||||
struct weston_buffer_reference buffer_ref;
|
|
||||||
struct weston_buffer_release_reference buffer_release_ref;
|
|
||||||
|
|
||||||
/* Used by gbm fbs */
|
|
||||||
struct gbm_bo *bo;
|
|
||||||
struct gbm_surface *gbm_surface;
|
|
||||||
|
|
||||||
/* Used by dumb fbs */
|
|
||||||
void *map;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_edid {
|
|
||||||
char eisa_id[13];
|
|
||||||
char monitor_name[13];
|
|
||||||
char pnp_id[5];
|
|
||||||
char serial_number[13];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pending state holds one or more drm_output_state structures, collected from
|
|
||||||
* performing repaint. This pending state is transient, and only lives between
|
|
||||||
* beginning a repaint group and flushing the results: after flush, each
|
|
||||||
* output state will complete and be retired separately.
|
|
||||||
*/
|
|
||||||
struct drm_pending_state {
|
|
||||||
struct drm_backend *backend;
|
|
||||||
struct wl_list output_list;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum drm_output_propose_state_mode {
|
enum drm_output_propose_state_mode {
|
||||||
DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */
|
DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */
|
||||||
DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY, /**< only assign to renderer & cursor */
|
DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY, /**< only assign to renderer & cursor */
|
||||||
DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< no renderer use, only planes */
|
DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< no renderer use, only planes */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
|
|
||||||
* plus >= 1 each of encoder/connector/plane. Since everything but the planes
|
|
||||||
* is currently statically assigned per-output, we mainly use this to track
|
|
||||||
* plane state.
|
|
||||||
*
|
|
||||||
* pending_state is set when the output state is owned by a pending_state,
|
|
||||||
* i.e. when it is being constructed and has not yet been applied. When the
|
|
||||||
* output state has been applied, the owning pending_state is freed.
|
|
||||||
*/
|
|
||||||
struct drm_output_state {
|
|
||||||
struct drm_pending_state *pending_state;
|
|
||||||
struct drm_output *output;
|
|
||||||
struct wl_list link;
|
|
||||||
enum dpms_enum dpms;
|
|
||||||
struct wl_list plane_list;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plane state holds the dynamic state for a plane: where it is positioned,
|
|
||||||
* and which buffer it is currently displaying.
|
|
||||||
*
|
|
||||||
* The plane state is owned by an output state, except when setting an initial
|
|
||||||
* state. See drm_output_state for notes on state object lifetime.
|
|
||||||
*/
|
|
||||||
struct drm_plane_state {
|
|
||||||
struct drm_plane *plane;
|
|
||||||
struct drm_output *output;
|
|
||||||
struct drm_output_state *output_state;
|
|
||||||
|
|
||||||
struct drm_fb *fb;
|
|
||||||
|
|
||||||
struct weston_view *ev; /**< maintained for drm_assign_planes only */
|
|
||||||
|
|
||||||
int32_t src_x, src_y;
|
|
||||||
uint32_t src_w, src_h;
|
|
||||||
int32_t dest_x, dest_y;
|
|
||||||
uint32_t dest_w, dest_h;
|
|
||||||
|
|
||||||
bool complete;
|
|
||||||
|
|
||||||
/* We don't own the fd, so we shouldn't close it */
|
|
||||||
int in_fence_fd;
|
|
||||||
|
|
||||||
pixman_region32_t damage; /* damage to kernel */
|
|
||||||
|
|
||||||
struct wl_list link; /* drm_output_state::plane_list */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A plane represents one buffer, positioned within a CRTC, and stacked
|
|
||||||
* relative to other planes on the same CRTC.
|
|
||||||
*
|
|
||||||
* Each CRTC has a 'primary plane', which use used to display the classic
|
|
||||||
* framebuffer contents, as accessed through the legacy drmModeSetCrtc
|
|
||||||
* call (which combines setting the CRTC's actual physical mode, and the
|
|
||||||
* properties of the primary plane).
|
|
||||||
*
|
|
||||||
* The cursor plane also has its own alternate legacy API.
|
|
||||||
*
|
|
||||||
* Other planes are used opportunistically to display content we do not
|
|
||||||
* wish to blit into the primary plane. These non-primary/cursor planes
|
|
||||||
* are referred to as 'sprites'.
|
|
||||||
*/
|
|
||||||
struct drm_plane {
|
|
||||||
struct weston_plane base;
|
|
||||||
|
|
||||||
struct drm_backend *backend;
|
|
||||||
|
|
||||||
enum wdrm_plane_type type;
|
|
||||||
|
|
||||||
uint32_t possible_crtcs;
|
|
||||||
uint32_t plane_id;
|
|
||||||
uint32_t count_formats;
|
|
||||||
|
|
||||||
struct drm_property_info props[WDRM_PLANE__COUNT];
|
|
||||||
|
|
||||||
/* The last state submitted to the kernel for this plane. */
|
|
||||||
struct drm_plane_state *state_cur;
|
|
||||||
|
|
||||||
struct wl_list link;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint32_t format;
|
|
||||||
uint32_t count_modifiers;
|
|
||||||
uint64_t *modifiers;
|
|
||||||
} formats[];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_head {
|
|
||||||
struct weston_head base;
|
|
||||||
struct drm_backend *backend;
|
|
||||||
|
|
||||||
drmModeConnector *connector;
|
|
||||||
uint32_t connector_id;
|
|
||||||
struct drm_edid edid;
|
|
||||||
|
|
||||||
/* Holds the properties for the connector */
|
|
||||||
struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];
|
|
||||||
|
|
||||||
struct backlight *backlight;
|
|
||||||
|
|
||||||
drmModeModeInfo inherited_mode; /**< Original mode on the connector */
|
|
||||||
uint32_t inherited_crtc_id; /**< Original CRTC assignment */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_output {
|
|
||||||
struct weston_output base;
|
|
||||||
struct drm_backend *backend;
|
|
||||||
|
|
||||||
uint32_t crtc_id; /* object ID to pass to DRM functions */
|
|
||||||
int pipe; /* index of CRTC in resource array / bitmasks */
|
|
||||||
|
|
||||||
/* Holds the properties for the CRTC */
|
|
||||||
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
|
|
||||||
|
|
||||||
int page_flip_pending;
|
|
||||||
int atomic_complete_pending;
|
|
||||||
int destroy_pending;
|
|
||||||
int disable_pending;
|
|
||||||
int dpms_off_pending;
|
|
||||||
|
|
||||||
struct drm_fb *gbm_cursor_fb[2];
|
|
||||||
struct drm_plane *cursor_plane;
|
|
||||||
struct weston_view *cursor_view;
|
|
||||||
int current_cursor;
|
|
||||||
|
|
||||||
struct gbm_surface *gbm_surface;
|
|
||||||
uint32_t gbm_format;
|
|
||||||
uint32_t gbm_bo_flags;
|
|
||||||
|
|
||||||
/* Plane being displayed directly on the CRTC */
|
|
||||||
struct drm_plane *scanout_plane;
|
|
||||||
|
|
||||||
/* The last state submitted to the kernel for this CRTC. */
|
|
||||||
struct drm_output_state *state_cur;
|
|
||||||
/* The previously-submitted state, where the hardware has not
|
|
||||||
* yet acknowledged completion of state_cur. */
|
|
||||||
struct drm_output_state *state_last;
|
|
||||||
|
|
||||||
struct drm_fb *dumb[2];
|
|
||||||
pixman_image_t *image[2];
|
|
||||||
int current_image;
|
|
||||||
pixman_region32_t previous_damage;
|
|
||||||
|
|
||||||
struct vaapi_recorder *recorder;
|
|
||||||
struct wl_listener recorder_frame_listener;
|
|
||||||
|
|
||||||
struct wl_event_source *pageflip_timer;
|
|
||||||
|
|
||||||
bool virtual;
|
|
||||||
|
|
||||||
submit_frame_cb virtual_submit_frame;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *const aspect_ratio_as_string[] = {
|
static const char *const aspect_ratio_as_string[] = {
|
||||||
[WESTON_MODE_PIC_AR_NONE] = "",
|
[WESTON_MODE_PIC_AR_NONE] = "",
|
||||||
[WESTON_MODE_PIC_AR_4_3] = " 4:3",
|
[WESTON_MODE_PIC_AR_4_3] = " 4:3",
|
||||||
@@ -615,24 +194,6 @@ wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct drm_head *
|
|
||||||
to_drm_head(struct weston_head *base)
|
|
||||||
{
|
|
||||||
return container_of(base, struct drm_head, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct drm_output *
|
|
||||||
to_drm_output(struct weston_output *base)
|
|
||||||
{
|
|
||||||
return container_of(base, struct drm_output, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct drm_backend *
|
|
||||||
to_drm_backend(struct weston_compositor *base)
|
|
||||||
{
|
|
||||||
return container_of(base->backend, struct drm_backend, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pageflip_timeout(void *data) {
|
pageflip_timeout(void *data) {
|
||||||
/*
|
/*
|
||||||
@@ -673,12 +234,6 @@ drm_output_pageflip_timer_create(struct drm_output *output)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct drm_mode *
|
|
||||||
to_drm_mode(struct weston_mode *base)
|
|
||||||
{
|
|
||||||
return container_of(base, struct drm_mode, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current value of a KMS property
|
* Get the current value of a KMS property
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user