drm-backend: move CRTC data from struct drm_output to new struct drm_crtc

There are no 'struct drm_output' for CRTCs that are not active.
Also, CRTC data lives in 'struct drm_output'. This is causing
us some trouble, as the DRM-backend needs to program those
unnactive CRTCs to be off.

If the DRM-backend had the reference for every CRTC (being
active or not), it would make certain functions (e.g.
drm_pending_state_apply_atomic()) more simple and efficient.

Move CRTC data from 'struct drm_output' to 'struct drm_crtc',
as this is the first step to allow the DRM-backend to have
references for every CRTC.

Also, add list of CRTCs to DRM-backend object. Now the
DRM-backend is responsible for allocating/deallocating the CRTC
objects. The outputs will only reference, init and fini the CRTCs
in this list.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
dev
Leandro Ribeiro 4 years ago
parent ad41a88535
commit b00d1a2efb
  1. 21
      libweston/backend-drm/drm-internal.h
  2. 51
      libweston/backend-drm/drm-virtual.c
  3. 317
      libweston/backend-drm/drm.c
  4. 56
      libweston/backend-drm/kms.c

@ -275,6 +275,9 @@ struct drm_backend {
bool state_invalid;
/* drm_crtc::link */
struct wl_list crtc_list;
/* CRTC IDs not used by any enabled output. */
struct wl_array unused_crtcs;
@ -483,15 +486,25 @@ struct drm_head {
uint32_t inherited_crtc_id; /**< Original CRTC assignment */
};
struct drm_output {
struct weston_output base;
struct drm_crtc {
/* drm_backend::crtc_list */
struct wl_list link;
struct drm_backend *backend;
/* The output driven by the CRTC */
struct drm_output *output;
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];
};
struct drm_output {
struct weston_output base;
struct drm_backend *backend;
struct drm_crtc *crtc;
bool page_flip_pending;
bool atomic_complete_pending;
@ -573,8 +586,8 @@ drm_output_get_plane_type_name(struct drm_plane *p)
}
}
struct drm_output *
drm_output_find_by_crtc(struct drm_backend *b, uint32_t crtc_id);
struct drm_crtc *
drm_crtc_find(struct drm_backend *b, uint32_t crtc_id);
struct drm_head *
drm_head_find_by_connector(struct drm_backend *backend, uint32_t connector_id);

@ -38,6 +38,49 @@
#include "drm-internal.h"
#include "renderer-gl/gl-renderer.h"
#define POISON_PTR ((void *)8)
/**
* Create a drm_crtc for virtual output
*
* It will leave its ID and pipe zeroed, as virtual outputs should not use real
* CRTC's. Also, as this is a fake CRTC, it will not try to populate props.
*/
static struct drm_crtc *
drm_virtual_crtc_create(struct drm_backend *b, struct drm_output *output)
{
struct drm_crtc *crtc;
crtc = zalloc(sizeof(*crtc));
if (!crtc)
return NULL;
crtc->backend = b;
crtc->output = output;
crtc->crtc_id = 0;
crtc->pipe = 0;
/* Poisoning the pointers as CRTC's of virtual outputs should not be
* added to the DRM-backend CRTC list. With this we can assure (in
* function drm_virtual_crtc_destroy()) that this did not happen. */
crtc->link.prev = POISON_PTR;
crtc->link.next = POISON_PTR;
return crtc;
}
/**
* Destroy drm_crtc created by drm_virtual_crtc_create()
*/
static void
drm_virtual_crtc_destroy(struct drm_crtc *crtc)
{
assert(crtc->link.prev == POISON_PTR);
assert(crtc->link.next == POISON_PTR);
free(crtc);
}
/**
* Create a drm_plane for virtual output
*
@ -184,6 +227,7 @@ drm_virtual_output_deinit(struct weston_output *base)
drm_output_fini_egl(output);
drm_virtual_plane_destroy(output->scanout_plane);
drm_virtual_crtc_destroy(output->crtc);
}
static void
@ -267,11 +311,18 @@ static struct weston_output *
drm_virtual_output_create(struct weston_compositor *c, char *name)
{
struct drm_output *output;
struct drm_backend *b = to_drm_backend(c);
output = zalloc(sizeof *output);
if (!output)
return NULL;
output->crtc = drm_virtual_crtc_create(b, output);
if (!output->crtc) {
free(output);
return NULL;
}
output->virtual = true;
output->gbm_bo_flags = GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING;

@ -208,17 +208,17 @@ drm_plane_is_available(struct drm_plane *plane, struct drm_output *output)
/* Check whether the plane can be used with this CRTC; possible_crtcs
* is a bitmask of CRTC indices (pipe), rather than CRTC object ID. */
return !!(plane->possible_crtcs & (1 << output->pipe));
return !!(plane->possible_crtcs & (1 << output->crtc->pipe));
}
struct drm_output *
drm_output_find_by_crtc(struct drm_backend *b, uint32_t crtc_id)
struct drm_crtc *
drm_crtc_find(struct drm_backend *b, uint32_t crtc_id)
{
struct drm_output *output;
struct drm_crtc *crtc;
wl_list_for_each(output, &b->compositor->output_list, base.link) {
if (output->crtc_id == crtc_id)
return output;
wl_list_for_each(crtc, &b->crtc_list, link) {
if (crtc->crtc_id == crtc_id)
return crtc;
}
return NULL;
@ -506,12 +506,12 @@ err:
* using DRM_BLANK_HIGH_CRTC_MASK.
*/
static unsigned int
drm_waitvblank_pipe(struct drm_output *output)
drm_waitvblank_pipe(struct drm_crtc *crtc)
{
if (output->pipe > 1)
return (output->pipe << DRM_VBLANK_HIGH_CRTC_SHIFT) &
if (crtc->pipe > 1)
return (crtc->pipe << DRM_VBLANK_HIGH_CRTC_SHIFT) &
DRM_VBLANK_HIGH_CRTC_MASK;
else if (output->pipe > 0)
else if (crtc->pipe > 0)
return DRM_VBLANK_SECONDARY;
else
return 0;
@ -552,7 +552,7 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
assert(scanout_plane->state_cur->output == output);
/* Try to get current msc and timestamp via instant query */
vbl.request.type |= drm_waitvblank_pipe(output);
vbl.request.type |= drm_waitvblank_pipe(output->crtc);
ret = drmWaitVBlank(backend->drm.fd, &vbl);
/* Error ret or zero timestamp means failure to get valid timestamp */
@ -818,7 +818,7 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
drmModeFreeObjectProperties(props);
}
else {
plane->possible_crtcs = (1 << output->pipe);
plane->possible_crtcs = (1 << output->crtc->pipe);
plane->plane_id = 0;
plane->count_formats = 1;
plane->formats[0].format = format;
@ -929,7 +929,7 @@ drm_output_find_special_plane(struct drm_backend *b, struct drm_output *output,
if (found_elsewhere)
continue;
plane->possible_crtcs = (1 << output->pipe);
plane->possible_crtcs = (1 << output->crtc->pipe);
return plane;
}
@ -1435,8 +1435,8 @@ drm_output_init_gamma_size(struct drm_output *output)
drmModeCrtc *crtc;
assert(output->base.compositor);
assert(output->crtc_id != 0);
crtc = drmModeGetCrtc(backend->drm.fd, output->crtc_id);
assert(output->crtc);
crtc = drmModeGetCrtc(backend->drm.fd, output->crtc->crtc_id);
if (!crtc)
return -1;
@ -1467,39 +1467,25 @@ drm_head_get_possible_crtcs_mask(struct drm_head *head)
return possible_crtcs;
}
static int
drm_crtc_get_index(drmModeRes *resources, uint32_t crtc_id)
{
int i;
for (i = 0; i < resources->count_crtcs; i++) {
if (resources->crtcs[i] == crtc_id)
return i;
}
assert(0 && "unknown crtc id");
return -1;
}
/** Pick a CRTC that might be able to drive all attached connectors
*
* @param output The output whose attached heads to include.
* @param resources The DRM KMS resources.
* @return CRTC index, or -1 on failure or not found.
* @return CRTC object to pick, or NULL on failure or not found.
*/
static int
drm_output_pick_crtc(struct drm_output *output, drmModeRes *resources)
static struct drm_crtc *
drm_output_pick_crtc(struct drm_output *output)
{
struct drm_backend *backend;
struct weston_head *base;
struct drm_head *head;
struct drm_crtc *crtc;
struct drm_crtc *best_crtc = NULL;
struct drm_crtc *fallback_crtc = NULL;
struct drm_crtc *existing_crtc[32];
uint32_t possible_crtcs = 0xffffffff;
int existing_crtc[32];
unsigned j, n = 0;
unsigned n = 0;
uint32_t crtc_id;
int best_crtc_index = -1;
int fallback_crtc_index = -1;
int i;
unsigned int i;
bool match;
backend = to_drm_backend(output->base.compositor);
@ -1515,30 +1501,28 @@ drm_output_pick_crtc(struct drm_output *output, drmModeRes *resources)
crtc_id = head->inherited_crtc_id;
if (crtc_id > 0 && n < ARRAY_LENGTH(existing_crtc))
existing_crtc[n++] = drm_crtc_get_index(resources,
crtc_id);
existing_crtc[n++] = drm_crtc_find(backend, crtc_id);
}
/* Find a crtc that could drive each connector individually at least,
* and prefer existing routings. */
for (i = 0; i < resources->count_crtcs; i++) {
crtc_id = resources->crtcs[i];
wl_list_for_each(crtc, &backend->crtc_list, link) {
/* Could the crtc not drive each connector? */
if (!(possible_crtcs & (1 << i)))
if (!(possible_crtcs & (1 << crtc->pipe)))
continue;
/* Is the crtc already in use? */
if (drm_output_find_by_crtc(backend, crtc_id))
if (crtc->output)
continue;
/* Try to preserve the existing CRTC -> connector routing;
* it makes initialisation faster, and also since we have a
* very dumb picking algorithm, may preserve a better
* choice. */
for (j = 0; j < n; j++) {
if (existing_crtc[j] == i)
return i;
for (i = 0; i < n; i++) {
if (existing_crtc[i] == crtc)
return crtc;
}
/* Check if any other head had existing routing to this CRTC.
@ -1555,22 +1539,22 @@ drm_output_pick_crtc(struct drm_output *output, drmModeRes *resources)
if (weston_head_is_enabled(&head->base))
continue;
if (head->inherited_crtc_id == crtc_id) {
if (head->inherited_crtc_id == crtc->crtc_id) {
match = true;
break;
}
}
if (!match)
best_crtc_index = i;
best_crtc = crtc;
fallback_crtc_index = i;
fallback_crtc = crtc;
}
if (best_crtc_index != -1)
return best_crtc_index;
if (best_crtc)
return best_crtc;
if (fallback_crtc_index != -1)
return fallback_crtc_index;
if (fallback_crtc)
return fallback_crtc;
/* Likely possible_crtcs was empty due to asking for clones,
* but since the DRM documentation says the kernel lies, let's
@ -1578,64 +1562,133 @@ drm_output_pick_crtc(struct drm_output *output, drmModeRes *resources)
* be sure if something doesn't work. */
/* First pick any existing assignment. */
for (j = 0; j < n; j++) {
crtc_id = resources->crtcs[existing_crtc[j]];
if (!drm_output_find_by_crtc(backend, crtc_id))
return existing_crtc[j];
for (i = 0; i < n; i++) {
crtc = existing_crtc[i];
if (!crtc->output)
return crtc;
}
/* Otherwise pick any available crtc. */
for (i = 0; i < resources->count_crtcs; i++) {
crtc_id = resources->crtcs[i];
wl_list_for_each(crtc, &backend->crtc_list, link) {
if (!crtc->output)
return crtc;
}
if (!drm_output_find_by_crtc(backend, crtc_id))
return i;
return NULL;
}
return -1;
/** Create an "empty" drm_crtc. It will only set its ID, pipe and props. After
* all, it adds the object to the DRM-backend CRTC list.
*/
static struct drm_crtc *
drm_crtc_create(struct drm_backend *b, uint32_t crtc_id, uint32_t pipe)
{
struct drm_crtc *crtc;
drmModeObjectPropertiesPtr props;
props = drmModeObjectGetProperties(b->drm.fd, crtc_id,
DRM_MODE_OBJECT_CRTC);
if (!props) {
weston_log("failed to get CRTC properties\n");
return NULL;
}
/** Allocate a CRTC for the output
*
* @param output The output with no allocated CRTC.
* @param resources DRM KMS resources.
* @return 0 on success, -1 on failure.
crtc = zalloc(sizeof(*crtc));
if (!crtc)
goto ret;
drm_property_info_populate(b, crtc_props, crtc->props_crtc,
WDRM_CRTC__COUNT, props);
crtc->backend = b;
crtc->crtc_id = crtc_id;
crtc->pipe = pipe;
crtc->output = NULL;
/* Add it to the last position of the DRM-backend CRTC list */
wl_list_insert(b->crtc_list.prev, &crtc->link);
ret:
drmModeFreeObjectProperties(props);
return crtc;
}
/** Destroy a drm_crtc object that was created with drm_crtc_create(). It will
* also remove it from the DRM-backend CRTC list.
*/
static void
drm_crtc_destroy(struct drm_crtc *crtc)
{
/* TODO: address the issue below to be able to remove the comment
* from the assert.
*
* Finds a free CRTC that might drive the attached connectors, reserves the CRTC
* for the output, and loads the CRTC properties.
* https://gitlab.freedesktop.org/wayland/weston/-/issues/421
*/
//assert(!crtc->output);
wl_list_remove(&crtc->link);
drm_property_info_free(crtc->props_crtc, WDRM_CRTC__COUNT);
free(crtc);
}
/** Find all CRTCs of the fd and create drm_crtc objects for them.
*
* Populates the cursor and scanout planes.
* The CRTCs are saved in a list of the drm_backend and will keep there until
* the fd gets closed.
*
* On failure, the output remains without a CRTC.
* @param b The DRM-backend structure.
* @return 0 on success (at least one CRTC in the list), -1 on failure.
*/
static int
drm_output_init_crtc(struct drm_output *output, drmModeRes *resources)
drm_backend_create_crtc_list(struct drm_backend *b)
{
struct drm_backend *b = to_drm_backend(output->base.compositor);
drmModeObjectPropertiesPtr props;
drmModeRes *resources;
struct drm_crtc *crtc, *crtc_tmp;
int i;
assert(output->crtc_id == 0);
resources = drmModeGetResources(b->drm.fd);
if (!resources) {
weston_log("drmModeGetResources failed\n");
return -1;
}
/* Iterate through all CRTCs */
for (i = 0; i < resources->count_crtcs; i++) {
i = drm_output_pick_crtc(output, resources);
if (i < 0) {
weston_log("Output '%s': No available CRTCs.\n",
output->base.name);
/* Let's create an object for the CRTC and add it to the list */
crtc = drm_crtc_create(b, resources->crtcs[i], i);
if (!crtc)
goto err;
}
drmModeFreeResources(resources);
return 0;
err:
wl_list_for_each_safe(crtc, crtc_tmp, &b->crtc_list, link)
drm_crtc_destroy(crtc);
drmModeFreeResources(resources);
return -1;
}
output->crtc_id = resources->crtcs[i];
output->pipe = i;
/** Pick a CRTC and reserve it for the output.
*
* On failure, the output remains without a CRTC.
*
* @param output The output with no CRTC associated.
* @return 0 on success, -1 on failure.
*/
static int
drm_output_attach_crtc(struct drm_output *output)
{
struct drm_backend *b = to_drm_backend(output->base.compositor);
props = drmModeObjectGetProperties(b->drm.fd, output->crtc_id,
DRM_MODE_OBJECT_CRTC);
if (!props) {
weston_log("failed to get CRTC properties\n");
goto err_crtc;
output->crtc = drm_output_pick_crtc(output);
if (!output->crtc) {
weston_log("Output '%s': No available CRTCs.\n",
output->base.name);
return -1;
}
drm_property_info_populate(b, crtc_props, output->props_crtc,
WDRM_CRTC__COUNT, props);
drmModeFreeObjectProperties(props);
output->scanout_plane =
drm_output_find_special_plane(b, output,
@ -1643,7 +1696,8 @@ drm_output_init_crtc(struct drm_output *output, drmModeRes *resources)
if (!output->scanout_plane) {
weston_log("Failed to find primary plane for output %s\n",
output->base.name);
goto err_crtc;
output->crtc = NULL;
return -1;
}
/* Without universal planes, we can't discover which formats are
@ -1658,27 +1712,24 @@ drm_output_init_crtc(struct drm_output *output, drmModeRes *resources)
drm_output_find_special_plane(b, output,
WDRM_PLANE_TYPE_CURSOR);
wl_array_remove_uint32(&b->unused_crtcs, output->crtc_id);
/* Reserve the CRTC for the output */
output->crtc->output = output;
wl_array_remove_uint32(&b->unused_crtcs, output->crtc->crtc_id);
return 0;
err_crtc:
output->crtc_id = 0;
output->pipe = 0;
return -1;
}
/** Free the CRTC from the output
/** Release reservation of the CRTC.
*
* @param output The output whose CRTC to deallocate.
* Make the CRTC free to be reserved and used by another output.
*
* The CRTC reserved for the given output becomes free to use again.
* @param output The output that will release its CRTC.
*/
static void
drm_output_fini_crtc(struct drm_output *output)
drm_output_detach_crtc(struct drm_output *output)
{
struct drm_backend *b = to_drm_backend(output->base.compositor);
struct drm_crtc *crtc = output->crtc;
uint32_t *unused;
/* If the compositor is already shutting down, the planes have already
@ -1706,17 +1757,15 @@ drm_output_fini_crtc(struct drm_output *output)
}
}
drm_property_info_free(output->props_crtc, WDRM_CRTC__COUNT);
assert(output->crtc_id != 0);
unused = wl_array_add(&b->unused_crtcs, sizeof(*unused));
*unused = output->crtc_id;
*unused = crtc->crtc_id;
/* Force resetting unused CRTCs */
b->state_invalid = true;
output->crtc_id = 0;
crtc->output = NULL;
output->crtc = NULL;
output->cursor_plane = NULL;
output->scanout_plane = NULL;
}
@ -1726,18 +1775,11 @@ drm_output_enable(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
struct drm_backend *b = to_drm_backend(base->compositor);
drmModeRes *resources;
int ret;
assert(!output->virtual);
resources = drmModeGetResources(b->drm.fd);
if (!resources) {
weston_log("drmModeGetResources failed\n");
return -1;
}
ret = drm_output_init_crtc(output, resources);
drmModeFreeResources(resources);
ret = drm_output_attach_crtc(output);
if (ret < 0)
return -1;
@ -1778,14 +1820,13 @@ drm_output_enable(struct weston_output *base)
&b->compositor->primary_plane);
weston_log("Output %s (crtc %d) video modes:\n",
output->base.name, output->crtc_id);
output->base.name, output->crtc->crtc_id);
drm_output_print_modes(output);
return 0;
err:
drm_output_fini_crtc(output);
drm_output_detach_crtc(output);
return -1;
}
@ -1812,11 +1853,11 @@ drm_output_deinit(struct weston_output *base)
wl_list_remove(&output->cursor_plane->base.link);
wl_list_init(&output->cursor_plane->base.link);
/* Turn off hardware cursor */
drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
drmModeSetCursor(b->drm.fd, output->crtc->crtc_id, 0, 0, 0);
}
}
drm_output_fini_crtc(output);
drm_output_detach_crtc(output);
}
static void
@ -1891,10 +1932,14 @@ drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
wl_array_init(&b->unused_crtcs);
for (i = 0; i < resources->count_crtcs; i++) {
struct drm_output *output;
struct drm_output *output = NULL;
struct drm_crtc *crtc;
uint32_t *crtc_id;
output = drm_output_find_by_crtc(b, resources->crtcs[i]);
crtc = drm_crtc_find(b, resources->crtcs[i]);
if (crtc)
output = crtc->output;
if (output && output->base.enabled)
continue;
@ -2177,6 +2222,8 @@ drm_output_create(struct weston_compositor *compositor, const char *name)
return NULL;
output->backend = b;
output->crtc = NULL;
#ifdef BUILD_DRM_GBM
output->gbm_bo_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
#endif
@ -2410,6 +2457,7 @@ drm_destroy(struct weston_compositor *ec)
{
struct drm_backend *b = to_drm_backend(ec);
struct weston_head *base, *next;
struct drm_crtc *crtc, *crtc_tmp;
udev_input_destroy(&b->input);
@ -2424,6 +2472,9 @@ drm_destroy(struct weston_compositor *ec)
b->debug = NULL;
weston_compositor_shutdown(ec);
wl_list_for_each_safe(crtc, crtc_tmp, &b->crtc_list, link)
drm_crtc_destroy(crtc);
wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
drm_head_destroy(to_drm_head(base));
@ -2451,6 +2502,7 @@ session_notify(struct wl_listener *listener, void *data)
struct drm_backend *b = to_drm_backend(compositor);
struct drm_plane *plane;
struct drm_output *output;
struct drm_crtc *crtc;
if (compositor->session_active) {
weston_log("activating session\n");
@ -2473,23 +2525,22 @@ session_notify(struct wl_listener *listener, void *data)
* pending frame callbacks. */
wl_list_for_each(output, &compositor->output_list, base.link) {
crtc = output->crtc;
output->base.repaint_needed = false;
if (output->cursor_plane)
drmModeSetCursor(b->drm.fd, output->crtc_id,
drmModeSetCursor(b->drm.fd, crtc->crtc_id,
0, 0, 0);
}
output = container_of(compositor->output_list.next,
struct drm_output, base.link);
crtc = output->crtc;
wl_list_for_each(plane, &b->plane_list, link) {
if (plane->type != WDRM_PLANE_TYPE_OVERLAY)
continue;
drmModeSetPlane(b->drm.fd,
plane->plane_id,
output->crtc_id, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0);
drmModeSetPlane(b->drm.fd, plane->plane_id, crtc->crtc_id,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
}
}
@ -2923,6 +2974,12 @@ drm_backend_create(struct weston_compositor *compositor,
weston_setup_vt_switch_bindings(compositor);
wl_list_init(&b->crtc_list);
if (drm_backend_create_crtc_list(b) == -1) {
weston_log("Failed to create CRTC list for DRM-backend\n");
goto err_udev_dev;
}
wl_list_init(&b->plane_list);
create_sprites(b);

@ -533,7 +533,7 @@ drm_output_set_gamma(struct weston_output *output_base,
return;
rc = drmModeCrtcSetGamma(backend->drm.fd,
output->crtc_id,
output->crtc->crtc_id,
size, r, g, b);
if (rc)
weston_log("set gamma failed: %s\n", strerror(errno));
@ -568,7 +568,8 @@ drm_output_assign_state(struct drm_output_state *state,
output->state_cur = state;
if (b->atomic_modeset && mode == DRM_STATE_APPLY_ASYNC) {
drm_debug(b, "\t[CRTC:%u] setting pending flip\n", output->crtc_id);
drm_debug(b, "\t[CRTC:%u] setting pending flip\n",
output->crtc->crtc_id);
output->atomic_complete_pending = true;
}
@ -608,6 +609,7 @@ drm_output_set_cursor(struct drm_output_state *output_state)
{
struct drm_output *output = output_state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor);
struct drm_crtc *crtc = output->crtc;
struct drm_plane *plane = output->cursor_plane;
struct drm_plane_state *state;
uint32_t handle;
@ -622,7 +624,7 @@ drm_output_set_cursor(struct drm_output_state *output_state)
if (!state->fb) {
pixman_region32_fini(&plane->base.damage);
pixman_region32_init(&plane->base.damage);
drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
drmModeSetCursor(b->drm.fd, crtc->crtc_id, 0, 0, 0);
return;
}
@ -631,7 +633,7 @@ drm_output_set_cursor(struct drm_output_state *output_state)
handle = output->gbm_cursor_handle[output->current_cursor];
if (plane->state_cur->fb != state->fb) {
if (drmModeSetCursor(b->drm.fd, output->crtc_id, handle,
if (drmModeSetCursor(b->drm.fd, crtc->crtc_id, handle,
b->cursor_width, b->cursor_height)) {
weston_log("failed to set cursor: %s\n",
strerror(errno));
@ -642,7 +644,7 @@ drm_output_set_cursor(struct drm_output_state *output_state)
pixman_region32_fini(&plane->base.damage);
pixman_region32_init(&plane->base.damage);
if (drmModeMoveCursor(b->drm.fd, output->crtc_id,
if (drmModeMoveCursor(b->drm.fd, crtc->crtc_id,
state->dest_x, state->dest_y)) {
weston_log("failed to move cursor: %s\n", strerror(errno));
goto err;
@ -652,7 +654,7 @@ drm_output_set_cursor(struct drm_output_state *output_state)
err:
b->cursors_are_broken = true;
drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
drmModeSetCursor(b->drm.fd, crtc->crtc_id, 0, 0, 0);
}
static int
@ -661,6 +663,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
struct drm_output *output = state->output;
struct drm_backend *backend = to_drm_backend(output->base.compositor);
struct drm_plane *scanout_plane = output->scanout_plane;
struct drm_crtc *crtc = output->crtc;
struct drm_property_info *dpms_prop;
struct drm_plane_state *scanout_state;
struct drm_mode *mode;
@ -690,14 +693,14 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
if (state->dpms != WESTON_DPMS_ON) {
if (output->cursor_plane) {
ret = drmModeSetCursor(backend->drm.fd, output->crtc_id,
ret = drmModeSetCursor(backend->drm.fd, crtc->crtc_id,
0, 0, 0);
if (ret)
weston_log("drmModeSetCursor failed disable: %s\n",
strerror(errno));
}
ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, 0, 0, 0,
ret = drmModeSetCrtc(backend->drm.fd, crtc->crtc_id, 0, 0, 0,
NULL, 0, NULL);
if (ret)
weston_log("drmModeSetCrtc failed disabling: %s\n",
@ -736,7 +739,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
scanout_plane->state_cur->fb->strides[0] !=
scanout_state->fb->strides[0]) {
ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
ret = drmModeSetCrtc(backend->drm.fd, crtc->crtc_id,
scanout_state->fb->fb_id,
0, 0,
connectors, n_conn,
@ -749,10 +752,10 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
pinfo = scanout_state->fb->format;
drm_debug(backend, "\t[CRTC:%u, PLANE:%u] FORMAT: %s\n",
output->crtc_id, scanout_state->plane->plane_id,
crtc->crtc_id, scanout_state->plane->plane_id,
pinfo ? pinfo->drm_format_name : "UNKNOWN");
if (drmModePageFlip(backend->drm.fd, output->crtc_id,
if (drmModePageFlip(backend->drm.fd, crtc->crtc_id,
scanout_state->fb->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
weston_log("queueing pageflip failed: %s\n", strerror(errno));
@ -795,19 +798,19 @@ err:
}
static int
crtc_add_prop(drmModeAtomicReq *req, struct drm_output *output,
crtc_add_prop(drmModeAtomicReq *req, struct drm_crtc *crtc,
enum wdrm_crtc_property prop, uint64_t val)
{
struct drm_property_info *info = &output->props_crtc[prop];
struct drm_property_info *info = &crtc->props_crtc[prop];
int ret;
if (info->prop_id == 0)
return -1;
ret = drmModeAtomicAddProperty(req, output->crtc_id, info->prop_id,
ret = drmModeAtomicAddProperty(req, crtc->crtc_id, info->prop_id,
val);
drm_debug(output->backend, "\t\t\t[CRTC:%lu] %lu (%s) -> %llu (0x%llx)\n",
(unsigned long) output->crtc_id,
drm_debug(crtc->backend, "\t\t\t[CRTC:%lu] %lu (%s) -> %llu (0x%llx)\n",
(unsigned long) crtc->crtc_id,
(unsigned long) info->prop_id, info->name,
(unsigned long long) val, (unsigned long long) val);
return (ret <= 0) ? -1 : 0;
@ -939,6 +942,7 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
{
struct drm_output *output = state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor);
struct drm_crtc *crtc = output->crtc;
struct drm_plane_state *plane_state;
struct drm_mode *current_mode = to_drm_mode(output->base.current_mode);
struct drm_head *head;
@ -958,19 +962,19 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
if (ret != 0)
return ret;
ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID,
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_MODE_ID,
current_mode->blob_id);
ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 1);
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 1);
/* No need for the DPMS property, since it is implicit in
* routing and CRTC activity. */
wl_list_for_each(head, &output->base.head_list, base.output_link) {
ret |= connector_add_prop(req, head, WDRM_CONNECTOR_CRTC_ID,
output->crtc_id);
crtc->crtc_id);
}
} else {
ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID, 0);
ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 0);
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_MODE_ID, 0);
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 0);
/* No need for the DPMS property, since it is implicit in
* routing and CRTC activity. */
@ -993,7 +997,7 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
ret |= plane_add_prop(req, plane, WDRM_PLANE_FB_ID,
plane_state->fb ? plane_state->fb->fb_id : 0);
ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_ID,
plane_state->fb ? output->crtc_id : 0);
plane_state->fb ? crtc->crtc_id : 0);
ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_X,
plane_state->src_x);
ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_Y,
@ -1391,11 +1395,17 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
unsigned int usec, unsigned int crtc_id, void *data)
{
struct drm_backend *b = data;
struct drm_output *output = drm_output_find_by_crtc(b, crtc_id);
struct drm_crtc *crtc;
struct drm_output *output;
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
crtc = drm_crtc_find(b, crtc_id);
assert(crtc);
output = crtc->output;
/* During the initial modeset, we can disable CRTCs which we don't
* actually handle during normal operation; this will give us events
* for unknown outputs. Ignore them. */

Loading…
Cancel
Save