diff --git a/example/common.c b/example/common.c index 69b206c..23375c4 100644 --- a/example/common.c +++ b/example/common.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include "common.h" @@ -79,6 +80,79 @@ void disable_all_crtcs_except(int drm_fd, drmModeRes *drm_res, uint32_t crtc_id) } } +static uint32_t find_drm_object_property_by_name(int drm_fd, drmModeObjectPropertiesPtr props, + const char *name) +{ + unsigned int i; + drmModePropertyRes *prop; + uint32_t ret = UINT32_MAX; + bool found = false; + + for (i = 0; !found && i < props->count_props; i++) { + prop = drmModeGetProperty(drm_fd, props->props[i]); + if (strcmp(prop->name, name) == 0) { + ret = prop->prop_id; + found = true; + } + drmModeFreeProperty(prop); + } + + return ret; +} + +bool set_global_properties(int drm_fd, drmModeAtomicReq *req, + const drmModeConnector *connector, const drmModeCrtc *crtc, + const drmModeModeInfo *mode) +{ + bool ok = true; + + drmModeObjectPropertiesPtr connector_props = drmModeObjectGetProperties(drm_fd, + connector->connector_id, + DRM_MODE_OBJECT_CONNECTOR); + + drmModeObjectPropertiesPtr crtc_props = drmModeObjectGetProperties(drm_fd, + crtc->crtc_id, + DRM_MODE_OBJECT_CRTC); + + assert(connector_props != NULL); + assert(crtc_props != NULL); + + uint32_t connector_crtc_prop = find_drm_object_property_by_name(drm_fd, connector_props, "CRTC_ID"); + uint32_t crtc_active_prop = find_drm_object_property_by_name(drm_fd, crtc_props, "ACTIVE"); + uint32_t crtc_mode_id_prop = find_drm_object_property_by_name(drm_fd, crtc_props, "MODE_ID"); + uint32_t mode_blob_id = UINT32_MAX; + + assert(connector_crtc_prop != UINT32_MAX); + assert(crtc_active_prop != UINT32_MAX); + assert(crtc_mode_id_prop != UINT32_MAX); + + /* connector::CRTC_ID */ + if (drmModeAtomicAddProperty(req, connector->connector_id, connector_crtc_prop, crtc->crtc_id) < 0) { + ok = false; + goto out; + } + + /* crtc::ACTIVE */ + if (drmModeAtomicAddProperty(req, crtc->crtc_id, crtc_active_prop, 1) < 0) { + ok = false; + goto out; + } + + /* crtc::MODE_ID */ + if (drmModeCreatePropertyBlob(drm_fd, mode, sizeof(*mode), &mode_blob_id) < 0 || + drmModeAtomicAddProperty(req, crtc->crtc_id, crtc_mode_id_prop, mode_blob_id) < 0) { + ok = false; + goto out; + } + +out: + /* free stuff */ + drmModeFreeObjectProperties(crtc_props); + drmModeFreeObjectProperties(connector_props); + + return ok; +} + bool dumb_fb_init(struct dumb_fb *fb, int drm_fd, uint32_t format, uint32_t width, uint32_t height) { diff --git a/example/common.h b/example/common.h index 8d4249b..7a96a42 100644 --- a/example/common.h +++ b/example/common.h @@ -16,6 +16,9 @@ drmModeConnector *pick_connector(int drm_fd, drmModeRes *drm_res); drmModeCrtc *pick_crtc(int drm_fd, drmModeRes *drm_res, drmModeConnector *connector); void disable_all_crtcs_except(int drm_fd, drmModeRes *drm_res, uint32_t crtc_id); +bool set_global_properties(int drm_fd, drmModeAtomicReq *req, + const drmModeConnector *connector, const drmModeCrtc *crtc, + const drmModeModeInfo *mode); bool dumb_fb_init(struct dumb_fb *fb, int drm_fd, uint32_t format, uint32_t width, uint32_t height); diff --git a/example/compositor.c b/example/compositor.c index 8aa07b4..8c6c5d7 100644 --- a/example/compositor.c +++ b/example/compositor.c @@ -167,7 +167,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "no connector found\n"); return 1; } - if (crtc == NULL || !crtc->mode_valid) { + if (crtc == NULL) { fprintf(stderr, "no CRTC found\n"); return 1; } @@ -175,11 +175,11 @@ int main(int argc, char *argv[]) printf("Using connector %d, CRTC %d\n", connector->connector_id, crtc->crtc_id); - composition_layer = add_layer(drm_fd, output, 0, 0, crtc->mode.hdisplay, - crtc->mode.vdisplay, false, true, + composition_layer = add_layer(drm_fd, output, 0, 0, connector->modes[0].hdisplay, + connector->modes[0].vdisplay, false, true, &composition_fb); - layers[0] = add_layer(drm_fd, output, 0, 0, crtc->mode.hdisplay, - crtc->mode.vdisplay, false, true, &fbs[0]); + layers[0] = add_layer(drm_fd, output, 0, 0, connector->modes[0].hdisplay, + connector->modes[0].vdisplay, false, true, &fbs[0]); for (i = 1; i < layers_len; i++) { layers[i] = add_layer(drm_fd, output, 100 * i, 100 * i, 256, 256, i % 2, false, &fbs[i]); @@ -206,7 +206,9 @@ int main(int argc, char *argv[]) } } - ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK, NULL); + set_global_properties(drm_fd, req, connector, crtc, &connector->modes[0]); + + ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); if (ret < 0) { perror("drmModeAtomicCommit"); return false; diff --git a/example/dynamic.c b/example/dynamic.c index c35f30f..dff2cb8 100644 --- a/example/dynamic.c +++ b/example/dynamic.c @@ -27,7 +27,12 @@ struct example_layer { struct liftoff_layer *layer; }; -static int drm_fd = -1; +struct pageflip_context { + int drm_fd; + drmModeConnectorPtr connector; + drmModeCrtcPtr crtc; +}; + static struct liftoff_display *display = NULL; static struct example_layer layers[LAYERS_LEN] = {0}; static size_t active_layer_idx = 2; @@ -84,7 +89,7 @@ static void draw_layer(int drm_fd, struct example_layer *layer) liftoff_layer_set_property(layer->layer, "CRTC_Y", layer->y); } -static bool draw(void) +static bool draw(struct pageflip_context *context) { struct example_layer *active_layer; drmModeAtomicReq *req; @@ -104,7 +109,7 @@ static bool draw(void) active_layer->dec = inc; } - draw_layer(drm_fd, active_layer); + draw_layer(context->drm_fd, active_layer); req = drmModeAtomicAlloc(); if (!liftoff_display_apply(display, req)) { @@ -112,8 +117,10 @@ static bool draw(void) return false; } - ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK | - DRM_MODE_PAGE_FLIP_EVENT, NULL); + set_global_properties(context->drm_fd, req, context->connector, context->crtc, &context->connector->modes[0]); + + ret = drmModeAtomicCommit(context->drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK | + DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET, context); if (ret < 0) { perror("drmModeAtomicCommit"); return false; @@ -132,62 +139,66 @@ static bool draw(void) static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, unsigned crtc_id, void *data) { - draw(); + struct pageflip_context *context = data; + draw(context); } int main(int argc, char *argv[]) { + struct pageflip_context context = { + .drm_fd = -1, + .connector = NULL, + .crtc = NULL, + }; drmModeRes *drm_res; - drmModeCrtc *crtc; - drmModeConnector *connector; struct liftoff_output *output; size_t i; int ret; - drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); - if (drm_fd < 0) { + context.drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); + if (context.drm_fd < 0) { perror("open"); return 1; } - if (drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) { + if (drmSetClientCap(context.drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) { perror("drmSetClientCap(UNIVERSAL_PLANES)"); return 1; } - if (drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) { + if (drmSetClientCap(context.drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) { perror("drmSetClientCap(ATOMIC)"); return 1; } - display = liftoff_display_create(drm_fd); + display = liftoff_display_create(context.drm_fd); if (display == NULL) { perror("liftoff_display_create"); return 1; } - drm_res = drmModeGetResources(drm_fd); - connector = pick_connector(drm_fd, drm_res); - crtc = pick_crtc(drm_fd, drm_res, connector); - disable_all_crtcs_except(drm_fd, drm_res, crtc->crtc_id); - output = liftoff_output_create(display, crtc->crtc_id); + drm_res = drmModeGetResources(context.drm_fd); + context.connector = pick_connector(context.drm_fd, drm_res); + context.crtc = pick_crtc(context.drm_fd, drm_res, context.connector); + disable_all_crtcs_except(context.drm_fd, drm_res, context.crtc->crtc_id); + output = liftoff_output_create(display, context.crtc->crtc_id); drmModeFreeResources(drm_res); - if (connector == NULL) { + if (context.connector == NULL) { fprintf(stderr, "no connector found\n"); return 1; } - if (crtc == NULL || !crtc->mode_valid) { + if (context.crtc == NULL) { fprintf(stderr, "no CRTC found\n"); return 1; } - printf("Using connector %d, CRTC %d\n", connector->connector_id, - crtc->crtc_id); + printf("Using connector %d, CRTC %d\n", context.connector->connector_id, + context.crtc->crtc_id); - init_layer(drm_fd, &layers[0], output, crtc->mode.hdisplay, - crtc->mode.vdisplay, false); + init_layer(context.drm_fd, &layers[0], output, context.connector->modes[0].hdisplay, + context.connector->modes[0].vdisplay, false); for (i = 1; i < LAYERS_LEN; i++) { - init_layer(drm_fd, &layers[i], output, 100, 100, i % 2); + init_layer(context.drm_fd, &layers[i], output, 100, 100, i % 2); layers[i].x = 100 * i; layers[i].y = 100 * i; } @@ -195,10 +206,10 @@ int main(int argc, char *argv[]) for (i = 0; i < LAYERS_LEN; i++) { liftoff_layer_set_property(layers[i].layer, "zpos", i); - draw_layer(drm_fd, &layers[i]); + draw_layer(context.drm_fd, &layers[i]); } - draw(); + draw(&context); for (i = 0; i < 120; i++) { drmEventContext drm_event = { @@ -206,7 +217,7 @@ int main(int argc, char *argv[]) .page_flip_handler2 = page_flip_handler, }; struct pollfd pfd = { - .fd = drm_fd, + .fd = context.drm_fd, .events = POLLIN, }; @@ -216,15 +227,15 @@ int main(int argc, char *argv[]) return 1; } - drmHandleEvent(drm_fd, &drm_event); + drmHandleEvent(context.drm_fd, &drm_event); } for (i = 0; i < sizeof(layers) / sizeof(layers[0]); i++) { liftoff_layer_destroy(layers[i].layer); } liftoff_output_destroy(output); - drmModeFreeCrtc(crtc); - drmModeFreeConnector(connector); + drmModeFreeCrtc(context.crtc); + drmModeFreeConnector(context.connector); liftoff_display_destroy(display); return 0; } diff --git a/example/multi-output.c b/example/multi-output.c index 6b60df4..23f794c 100644 --- a/example/multi-output.c +++ b/example/multi-output.c @@ -70,8 +70,8 @@ int main(int argc, char *argv[]) int drm_fd; struct liftoff_display *display; drmModeRes *drm_res; - drmModeConnector *connector; drmModeCrtc *crtcs[MAX_OUTPUTS], *crtc; + drmModeConnector *connectors[MAX_OUTPUTS], *connector; struct liftoff_output *outputs[MAX_OUTPUTS], *output; struct liftoff_layer *layers[MAX_OUTPUTS * LAYERS_PER_OUTPUT]; size_t outputs_len, layers_len; @@ -111,7 +111,7 @@ int main(int argc, char *argv[]) } crtc = pick_crtc(drm_fd, drm_res, connector); - if (crtc == NULL || !crtc->mode_valid) { + if (crtc == NULL) { drmModeFreeConnector(connector); continue; } @@ -121,8 +121,7 @@ int main(int argc, char *argv[]) printf("Using connector %d, CRTC %d\n", connector->connector_id, crtc->crtc_id); - drmModeFreeConnector(connector); - + connectors[outputs_len] = connector; crtcs[outputs_len] = crtc; outputs[outputs_len] = output; outputs_len++; @@ -137,11 +136,12 @@ int main(int argc, char *argv[]) layers_len = 0; for (i = 0; i < outputs_len; i++) { output = outputs[i]; + connector = connectors[i]; crtc = crtcs[i]; layers[layers_len++] = add_layer(drm_fd, output, 0, 0, - crtc->mode.hdisplay, - crtc->mode.vdisplay, false); + connector->modes[0].hdisplay, + connector->modes[0].vdisplay, false); for (j = 1; j < LAYERS_PER_OUTPUT; j++) { layers[layers_len++] = add_layer(drm_fd, output, 100 * j, 100 * j, @@ -159,7 +159,11 @@ int main(int argc, char *argv[]) return 1; } - ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK, NULL); + for (i = 0; i < outputs_len; i++) { + set_global_properties(drm_fd, req, connectors[i], crtcs[i], &connectors[i]->modes[0]); + } + + ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); if (ret < 0) { perror("drmModeAtomicCommit"); return false; @@ -178,6 +182,7 @@ int main(int argc, char *argv[]) } for (i = 0; i < outputs_len; i++) { liftoff_output_destroy(outputs[i]); + drmModeFreeConnector(connectors[i]); drmModeFreeCrtc(crtcs[i]); } liftoff_display_destroy(display); diff --git a/example/simple.c b/example/simple.c index daf1dec..4706cec 100644 --- a/example/simple.c +++ b/example/simple.c @@ -108,7 +108,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "no connector found\n"); return 1; } - if (crtc == NULL || !crtc->mode_valid) { + if (crtc == NULL) { fprintf(stderr, "no CRTC found\n"); return 1; } @@ -116,8 +116,8 @@ int main(int argc, char *argv[]) printf("Using connector %d, CRTC %d\n", connector->connector_id, crtc->crtc_id); - layers[0] = add_layer(drm_fd, output, 0, 0, crtc->mode.hdisplay, - crtc->mode.vdisplay, false); + layers[0] = add_layer(drm_fd, output, 0, 0, connector->modes[0].hdisplay, + connector->modes[0].vdisplay, false); for (i = 1; i < LAYERS_LEN; i++) { layers[i] = add_layer(drm_fd, output, 100 * i, 100 * i, 256, 256, i % 2); @@ -133,7 +133,9 @@ int main(int argc, char *argv[]) return 1; } - ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK, NULL); + set_global_properties(drm_fd, req, connector, crtc, &connector->modes[0]); + + ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); if (ret < 0) { perror("drmModeAtomicCommit"); return false;