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>dev
parent
c505af8820
commit
dd1bc50ba2
@ -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); |
||||||
|
} |
Loading…
Reference in new issue