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>
diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
index c91e381..0d0fed6 100644
--- a/libweston/backend-drm/kms.c
+++ b/libweston/backend-drm/kms.c
@@ -533,7 +533,7 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
{
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 @@
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 @@
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 @@
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. */