void CDRMAtomic::DestroyDrm() { CDRMUtils::DestroyDrm(); drmModeAtomicFree(m_req); m_req = nullptr; }
static int drm_atomic_commit(uint32_t fb_id, uint32_t flags) { drmModeAtomicReq *req; uint32_t plane_id = drm.plane->plane->plane_id; uint32_t blob_id; int ret; req = drmModeAtomicAlloc(); if (flags & DRM_MODE_ATOMIC_ALLOW_MODESET) { if (add_connector_property(req, drm.connector_id, "CRTC_ID", drm.crtc_id) < 0) return -1; if (drmModeCreatePropertyBlob(drm.fd, drm.mode, sizeof(*drm.mode), &blob_id) != 0) return -1; if (add_crtc_property(req, drm.crtc_id, "MODE_ID", blob_id) < 0) return -1; if (add_crtc_property(req, drm.crtc_id, "ACTIVE", 1) < 0) return -1; } add_plane_property(req, plane_id, "FB_ID", fb_id); add_plane_property(req, plane_id, "CRTC_ID", drm.crtc_id); add_plane_property(req, plane_id, "SRC_X", 0); add_plane_property(req, plane_id, "SRC_Y", 0); add_plane_property(req, plane_id, "SRC_W", drm.mode->hdisplay << 16); add_plane_property(req, plane_id, "SRC_H", drm.mode->vdisplay << 16); add_plane_property(req, plane_id, "CRTC_X", 0); add_plane_property(req, plane_id, "CRTC_Y", 0); add_plane_property(req, plane_id, "CRTC_W", drm.mode->hdisplay); add_plane_property(req, plane_id, "CRTC_H", drm.mode->vdisplay); if (drm.kms_in_fence_fd != -1) { add_crtc_property(req, drm.crtc_id, "OUT_FENCE_PTR", VOID2U64(&drm.kms_out_fence_fd)); add_plane_property(req, plane_id, "IN_FENCE_FD", drm.kms_in_fence_fd); } ret = drmModeAtomicCommit(drm.fd, req, flags, NULL); if (ret) goto out; if (drm.kms_in_fence_fd != -1) { close(drm.kms_in_fence_fd); drm.kms_in_fence_fd = -1; } out: drmModeAtomicFree(req); return ret; }
static void plane_primary(struct kms_atomic_crtc_state *crtc, struct kms_atomic_plane_state *plane_old) { struct drm_mode_modeinfo *mode = crtc->mode.data; struct kms_atomic_plane_state plane = *plane_old; uint32_t format = plane_get_igt_format(&plane); drmModeAtomicReq *req = drmModeAtomicAlloc(); uint32_t *connectors; int num_connectors; struct igt_fb fb; int i; connectors = calloc(crtc->state->num_connectors, sizeof(*connectors)); igt_assert(connectors); for (i = 0; i < crtc->state->num_connectors; i++) { if (crtc->state->connectors[i].crtc_id == crtc->obj) connectors[num_connectors++] = crtc->state->connectors[i].obj; } igt_require(format != 0); plane.src_x = 0; plane.src_y = 0; plane.src_w = mode->hdisplay << 16; plane.src_h = mode->vdisplay << 16; plane.crtc_x = 0; plane.crtc_y = 0; plane.crtc_w = mode->hdisplay; plane.crtc_h = mode->vdisplay; plane.crtc_id = crtc->obj; plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd, plane.crtc_w, plane.crtc_h, format, I915_TILING_NONE, &fb); /* Flip the primary plane using the atomic API, and double-check * state is what we think it should be. */ crtc_commit_atomic(crtc, &plane, req, ATOMIC_RELAX_NONE); /* Restore the primary plane and check the state matches the old. */ crtc_commit_atomic(crtc, plane_old, req, ATOMIC_RELAX_NONE); /* Re-enable the plane through the legacy CRTC/primary-plane API, and * verify through atomic. */ crtc_commit_legacy(crtc, &plane, CRTC_RELAX_MODE); /* Restore the plane to its original settings through the legacy CRTC * API, and verify through atomic. */ crtc_commit_legacy(crtc, plane_old, CRTC_RELAX_MODE); /* Finally, restore to the original state. */ crtc_commit_atomic(crtc, plane_old, req, ATOMIC_RELAX_NONE); drmModeAtomicFree(req); }
static void crtc_invalid_params(struct kms_atomic_crtc_state *crtc_old, struct kms_atomic_plane_state *plane, struct kms_atomic_connector_state *conn) { struct kms_atomic_crtc_state crtc = *crtc_old; drmModeAtomicReq *req = drmModeAtomicAlloc(); igt_assert(req); /* Pass a series of invalid object IDs for the mode ID. */ crtc.mode.id = plane->obj; crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req, ATOMIC_RELAX_NONE, EINVAL); crtc.mode.id = crtc.obj; crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req, ATOMIC_RELAX_NONE, EINVAL); crtc.mode.id = conn->obj; crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req, ATOMIC_RELAX_NONE, EINVAL); crtc.mode.id = plane->fb_id; crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req, ATOMIC_RELAX_NONE, EINVAL); crtc.mode.id = crtc_old->mode.id; crtc_commit_atomic(&crtc, plane, req, ATOMIC_RELAX_NONE); /* Create a blob which is the wrong size to be a valid mode. */ do_or_die(drmModeCreatePropertyBlob(crtc.state->desc->fd, crtc.mode.data, sizeof(struct drm_mode_modeinfo) - 1, &crtc.mode.id)); crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req, ATOMIC_RELAX_NONE, EINVAL); do_or_die(drmModeCreatePropertyBlob(crtc.state->desc->fd, crtc.mode.data, sizeof(struct drm_mode_modeinfo) + 1, &crtc.mode.id)); crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req, ATOMIC_RELAX_NONE, EINVAL); /* Restore the CRTC and check the state matches the old. */ crtc_commit_atomic(crtc_old, plane, req, ATOMIC_RELAX_NONE); drmModeAtomicFree(req); }
static void plane_overlay(struct kms_atomic_crtc_state *crtc, struct kms_atomic_plane_state *plane_old) { struct drm_mode_modeinfo *mode = crtc->mode.data; struct kms_atomic_plane_state plane = *plane_old; uint32_t format = plane_get_igt_format(&plane); drmModeAtomicReq *req = drmModeAtomicAlloc(); struct igt_fb fb; igt_require(req); igt_require(format != 0); plane.src_x = 0; plane.src_y = 0; plane.src_w = (mode->hdisplay / 2) << 16; plane.src_h = (mode->vdisplay / 2) << 16; plane.crtc_x = mode->hdisplay / 4; plane.crtc_y = mode->vdisplay / 4; plane.crtc_w = mode->hdisplay / 2; plane.crtc_h = mode->vdisplay / 2; plane.crtc_id = crtc->obj; plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd, plane.crtc_w, plane.crtc_h, format, I915_TILING_NONE, &fb); /* Enable the overlay plane using the atomic API, and double-check * state is what we think it should be. */ plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE); /* Disable the plane and check the state matches the old. */ plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE); /* Re-enable the plane through the legacy plane API, and verify through * atomic. */ plane_commit_legacy(&plane, ATOMIC_RELAX_NONE); /* Restore the plane to its original settings through the legacy plane * API, and verify through atomic. */ plane_commit_legacy(plane_old, ATOMIC_RELAX_NONE); drmModeAtomicFree(req); }
static void drm_page_flip(struct drm_surface *surface) { /* We alredy have the id of the FB_ID property of * the plane on which we are going to do a pageflip: * we got it back in drm_plane_setup() */ int ret; static drmModeAtomicReqPtr req = NULL; req = drmModeAtomicAlloc(); /* We add the buffer to the plane properties we want to * set on an atomically, in a single step. * We pass the plane id, the property id and the new fb id. */ ret = drmModeAtomicAddProperty(req, drm.plane_id, drm.plane_fb_prop_id, surface->pages[surface->flip_page].buf.fb_id); if (ret < 0) { RARCH_ERR ("DRM: failed to add atomic property for pageflip\n"); } /*... now we just need to do the commit */ /* REMEMBER!!! The DRM_MODE_PAGE_FLIP_EVENT flag asks the kernel * to send you an event to the drm.fd once the * pageflip is complete. If you don't want -12 errors * (ENOMEM), namely "Cannot allocate memory", then * you must drain the event queue of that fd. */ ret = drmModeAtomicCommit(drm.fd, req, 0, NULL); if (ret < 0) { RARCH_ERR ("DRM: failed to commit for pageflip: %s\n", strerror(errno)); } surface->flip_page = !(surface->flip_page); drmModeAtomicFree(req); }
void CDRMAtomic::DrmAtomicCommit(int fb_id, int flags, bool rendered, bool videoLayer) { uint32_t blob_id; struct plane *plane; if (flags & DRM_MODE_ATOMIC_ALLOW_MODESET) { if (!AddProperty(m_req, m_connector, "CRTC_ID", m_crtc->crtc->crtc_id)) { return; } if (drmModeCreatePropertyBlob(m_fd, m_mode, sizeof(*m_mode), &blob_id) != 0) { return; } if (!AddProperty(m_req, m_crtc, "MODE_ID", blob_id)) { return; } if (!AddProperty(m_req, m_crtc, "ACTIVE", m_active ? 1 : 0)) { return; } if (!videoLayer) { // disable overlay plane on modeset AddProperty(m_req, m_overlay_plane, "FB_ID", 0); AddProperty(m_req, m_overlay_plane, "CRTC_ID", 0); } } if (videoLayer) plane = m_overlay_plane; else plane = m_primary_plane; if (rendered) { AddProperty(m_req, plane, "FB_ID", fb_id); AddProperty(m_req, plane, "CRTC_ID", m_crtc->crtc->crtc_id); AddProperty(m_req, plane, "SRC_X", 0); AddProperty(m_req, plane, "SRC_Y", 0); AddProperty(m_req, plane, "SRC_W", m_mode->hdisplay << 16); AddProperty(m_req, plane, "SRC_H", m_mode->vdisplay << 16); AddProperty(m_req, plane, "CRTC_X", 0); AddProperty(m_req, plane, "CRTC_Y", 0); AddProperty(m_req, plane, "CRTC_W", m_mode->hdisplay); AddProperty(m_req, plane, "CRTC_H", m_mode->vdisplay); } else if (videoLayer && !CServiceBroker::GetGUI()->GetWindowManager().HasVisibleControls()) { // disable gui plane when video layer is active and gui has no visible controls AddProperty(m_req, plane, "FB_ID", 0); AddProperty(m_req, plane, "CRTC_ID", 0); } auto ret = drmModeAtomicCommit(m_fd, m_req, flags | DRM_MODE_ATOMIC_TEST_ONLY, nullptr); if (ret < 0) { CLog::Log(LOGERROR, "CDRMAtomic::%s - test commit failed: %s", __FUNCTION__, strerror(errno)); } else if (ret == 0) { ret = drmModeAtomicCommit(m_fd, m_req, flags, nullptr); if (ret < 0) { CLog::Log(LOGERROR, "CDRMAtomic::%s - atomic commit failed: %s", __FUNCTION__, strerror(errno)); } } if (flags & DRM_MODE_ATOMIC_ALLOW_MODESET) { if (drmModeDestroyPropertyBlob(m_fd, blob_id) != 0) CLog::Log(LOGERROR, "CDRMAtomic::%s - failed to destroy property blob: %s", __FUNCTION__, strerror(errno)); } drmModeAtomicFree(m_req); m_req = drmModeAtomicAlloc(); }
static void plane_cursor(struct kms_atomic_crtc_state *crtc, struct kms_atomic_plane_state *plane_old) { struct drm_mode_modeinfo *mode = crtc->mode.data; struct kms_atomic_plane_state plane = *plane_old; drmModeAtomicReq *req = drmModeAtomicAlloc(); struct igt_fb fb; uint64_t width, height; igt_assert(req); /* Any kernel new enough for atomic, also has the cursor size caps. */ do_or_die(drmGetCap(plane.state->desc->fd, DRM_CAP_CURSOR_WIDTH, &width)); do_or_die(drmGetCap(plane.state->desc->fd, DRM_CAP_CURSOR_HEIGHT, &height)); plane.src_x = 0; plane.src_y = 0; plane.src_w = width << 16; plane.src_h = height << 16; plane.crtc_x = mode->hdisplay / 2; plane.crtc_y = mode->vdisplay / 2; plane.crtc_w = width; plane.crtc_h = height; plane.crtc_id = crtc->obj; plane.fb_id = igt_create_color_fb(plane.state->desc->fd, width, height, DRM_FORMAT_ARGB8888, LOCAL_DRM_FORMAT_MOD_NONE, 0.0, 0.0, 0.0, &fb); igt_assert_neq_u32(plane.fb_id, 0); /* Flip the cursor plane using the atomic API, and double-check * state is what we think it should be. */ plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE); /* Restore the cursor plane and check the state matches the old. */ plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE); /* Re-enable the plane through the legacy cursor API, and verify * through atomic. */ do_or_die(drmModeMoveCursor(plane.state->desc->fd, plane.crtc_id, plane.crtc_x, plane.crtc_y)); do_or_die(drmModeSetCursor(plane.state->desc->fd, plane.crtc_id, fb.gem_handle, width, height)); plane_check_current_state(&plane, PLANE_RELAX_FB); /* Wiggle. */ plane.crtc_x -= 16; plane.crtc_y -= 16; do_or_die(drmModeMoveCursor(plane.state->desc->fd, plane.crtc_id, plane.crtc_x, plane.crtc_y)); plane_check_current_state(&plane, PLANE_RELAX_FB); /* Restore the plane to its original settings through the legacy cursor * API, and verify through atomic. */ do_or_die(drmModeSetCursor2(plane.state->desc->fd, plane.crtc_id, 0, 0, 0, 0, 0)); plane_check_current_state(plane_old, ATOMIC_RELAX_NONE); /* Finally, restore to the original state. */ plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE); drmModeAtomicFree(req); }
static void plane_invalid_params(struct kms_atomic_crtc_state *crtc, struct kms_atomic_plane_state *plane_old, struct kms_atomic_connector_state *conn) { struct drm_mode_modeinfo *mode = crtc->mode.data; struct kms_atomic_plane_state plane = *plane_old; uint32_t format = plane_get_igt_format(&plane); drmModeAtomicReq *req = drmModeAtomicAlloc(); struct igt_fb fb; /* Pass a series of invalid object IDs for the FB ID. */ plane.fb_id = plane.obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.fb_id = crtc->obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.fb_id = conn->obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.fb_id = crtc->mode.id; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.fb_id = plane_old->fb_id; plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE); /* Pass a series of invalid object IDs for the CRTC ID. */ plane.crtc_id = plane.obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.crtc_id = plane.fb_id; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.crtc_id = conn->obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.crtc_id = crtc->mode.id; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.crtc_id = plane_old->crtc_id; plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE); /* Create a framebuffer too small for the plane configuration. */ igt_require(format != 0); plane.src_x = 0; plane.src_y = 0; plane.src_w = mode->hdisplay << 16; plane.src_h = mode->vdisplay << 16; plane.crtc_x = 0; plane.crtc_y = 0; plane.crtc_w = mode->hdisplay; plane.crtc_h = mode->vdisplay; plane.crtc_id = crtc->obj; plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd, plane.crtc_w - 1, plane.crtc_h - 1, format, I915_TILING_NONE, &fb); plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, ENOSPC); /* Restore the primary plane and check the state matches the old. */ plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE); drmModeAtomicFree(req); }