static int stereo_open(int *out, const struct gbm_options *options) { const char *card = options->card; int fd, ret; if (card == NULL) card = "/dev/dri/card0"; fd = open(card, O_RDWR | O_CLOEXEC); if (fd < 0) { ret = -errno; fprintf(stderr, "cannot open '%s': %m\n", card); return ret; } if (drmSetClientCap(fd, DRM_CLIENT_CAP_STEREO_3D, 1)) { fprintf(stderr, "error setting stereo client cap: %m\n"); close(fd); return -errno; } *out = fd; return 0; }
bool CDRMUtils::InitDrm() { if(m_fd >= 0) { /* caps need to be set before allocating connectors, encoders, crtcs, and planes */ auto ret = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); if (ret) { CLog::Log(LOGERROR, "CDRMUtils::%s - failed to set Universal planes capability: %s", __FUNCTION__, strerror(errno)); return false; } if(!GetResources()) { return false; } if(!GetConnector()) { return false; } if(!GetEncoder()) { return false; } if(!GetCrtc()) { return false; } if(!GetPlanes()) { return false; } } drmModeFreeResources(m_drm_resources); m_drm_resources = nullptr; if(m_fd < 0) { return false; } if(!GetPreferredMode()) { return false; } drmSetMaster(m_fd); m_orig_crtc = drmModeGetCrtc(m_fd, m_crtc->crtc->crtc_id); return true; }
int drm_get_overlay_plane(int drm_fd, int crtc_pipe, uint32_t format, uint32_t *plane_id) { drmModePlaneRes *res; drmModePlane *p; uint32_t id = 0; int i, j; if (drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { ErrorMsg("Failed to set universal planes CAP\n"); goto err; } res = drmModeGetPlaneResources(drm_fd); if (!res) goto err; for (i = 0; i < res->count_planes && !id; i++) { p = drmModeGetPlane(drm_fd, res->planes[i]); if (!p) continue; if (!p->crtc_id && (p->possible_crtcs & (1 << crtc_pipe))) { if (drm_plane_type(drm_fd, p->plane_id) == DRM_PLANE_TYPE_OVERLAY) { for (j = 0; j < p->count_formats; j++) { if (p->formats[j] == format) { id = p->plane_id; break; } } } } drmModeFreePlane(p); } drmModeFreePlaneResources(res); if (!id) goto err; *plane_id = id; return 0; err: ErrorMsg("Failed to get overlay plane\n"); return -EFAULT; }
bool CDRMAtomic::InitDrm() { if (!CDRMUtils::OpenDrm()) { return false; } auto ret = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1); if (ret) { CLog::Log(LOGERROR, "CDRMAtomic::%s - no atomic modesetting support: %s", __FUNCTION__, strerror(errno)); return false; } m_req = drmModeAtomicAlloc(); if (!CDRMUtils::InitDrm()) { return false; } CLog::Log(LOGDEBUG, "CDRMAtomic::%s - initialized atomic DRM", __FUNCTION__); return true; }
int DrmResources::Init() { char path[PROPERTY_VALUE_MAX]; property_get("hwc.drm.device", path, "/dev/dri/card0"); /* TODO: Use drmOpenControl here instead */ fd_ = open(path, O_RDWR); if (fd_ < 0) { ALOGE("Failed to open dri- %s", strerror(-errno)); return -ENODEV; } int ret = drmSetClientCap(fd_, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); if (ret) { ALOGE("Failed to set universal plane cap %d", ret); return ret; } ret = drmSetClientCap(fd_, DRM_CLIENT_CAP_ATOMIC, 1); if (ret) { ALOGE("Failed to set atomic cap %d", ret); return ret; } drmModeResPtr res = drmModeGetResources(fd_); if (!res) { ALOGE("Failed to get DrmResources resources"); return -ENODEV; } bool found_primary = false; int display_num = 1; for (int i = 0; !ret && i < res->count_crtcs; ++i) { drmModeCrtcPtr c = drmModeGetCrtc(fd_, res->crtcs[i]); if (!c) { ALOGE("Failed to get crtc %d", res->crtcs[i]); ret = -ENODEV; break; } DrmCrtc *crtc = new DrmCrtc(this, c, i); drmModeFreeCrtc(c); if (!crtc) { ALOGE("Failed to allocate crtc %d", res->crtcs[i]); ret = -ENOMEM; break; } ret = crtc->Init(); if (ret) { ALOGE("Failed to initialize crtc %d", res->crtcs[i]); delete crtc; break; } crtcs_.push_back(crtc); } for (int i = 0; !ret && i < res->count_encoders; ++i) { drmModeEncoderPtr e = drmModeGetEncoder(fd_, res->encoders[i]); if (!e) { ALOGE("Failed to get encoder %d", res->encoders[i]); ret = -ENODEV; break; } std::vector<DrmCrtc *> possible_crtcs; DrmCrtc *current_crtc = NULL; for (std::vector<DrmCrtc *>::const_iterator iter = crtcs_.begin(); iter != crtcs_.end(); ++iter) { if ((1 << (*iter)->pipe()) & e->possible_crtcs) possible_crtcs.push_back(*iter); if ((*iter)->id() == e->crtc_id) current_crtc = (*iter); } DrmEncoder *enc = new DrmEncoder(e, current_crtc, possible_crtcs); drmModeFreeEncoder(e); if (!enc) { ALOGE("Failed to allocate enc %d", res->encoders[i]); ret = -ENOMEM; break; } encoders_.push_back(enc); } for (int i = 0; !ret && i < res->count_connectors; ++i) { drmModeConnectorPtr c = drmModeGetConnector(fd_, res->connectors[i]); if (!c) { ALOGE("Failed to get connector %d", res->connectors[i]); ret = -ENODEV; break; } std::vector<DrmEncoder *> possible_encoders; DrmEncoder *current_encoder = NULL; for (int j = 0; j < c->count_encoders; ++j) { for (std::vector<DrmEncoder *>::const_iterator iter = encoders_.begin(); iter != encoders_.end(); ++iter) { if ((*iter)->id() == c->encoders[j]) possible_encoders.push_back((*iter)); if ((*iter)->id() == c->encoder_id) current_encoder = *iter; } } DrmConnector *conn = new DrmConnector(this, c, current_encoder, possible_encoders); drmModeFreeConnector(c); if (!conn) { ALOGE("Failed to allocate conn %d", res->connectors[i]); ret = -ENOMEM; break; } ret = conn->Init(); if (ret) { ALOGE("Init connector %d failed", res->connectors[i]); delete conn; break; } connectors_.push_back(conn); if (conn->built_in() && !found_primary) { conn->set_display(0); found_primary = true; } else { conn->set_display(display_num); ++display_num; } } if (res) drmModeFreeResources(res); // Catch-all for the above loops if (ret) return ret; drmModePlaneResPtr plane_res = drmModeGetPlaneResources(fd_); if (!plane_res) { ALOGE("Failed to get plane resources"); return -ENOENT; } for (uint32_t i = 0; i < plane_res->count_planes; ++i) { drmModePlanePtr p = drmModeGetPlane(fd_, plane_res->planes[i]); if (!p) { ALOGE("Failed to get plane %d", plane_res->planes[i]); ret = -ENODEV; break; } DrmPlane *plane = new DrmPlane(this, p); drmModeFreePlane(p); if (!plane) { ALOGE("Allocate plane %d failed", plane_res->planes[i]); ret = -ENOMEM; break; } ret = plane->Init(); if (ret) { ALOGE("Init plane %d failed", plane_res->planes[i]); delete plane; break; } planes_.push_back(plane); } drmModeFreePlaneResources(plane_res); if (ret) return ret; return compositor_.Init(); }
static bool init_drm(void) { int ret; drmModeConnector *connector; uint i; drm.fd = open("/dev/dri/card0", O_RDWR); if (drm.fd < 0) { RARCH_LOG ("DRM: could not open drm device\n"); return false; } /* Programmer!! Save your sanity!! * VERY important or we won't get all the available planes on drmGetPlaneResources()! * We also need to enable the ATOMIC cap to see the atomic properties in objects!! */ ret = drmSetClientCap(drm.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); if (ret) RARCH_ERR ("DRM: can't set UNIVERSAL PLANES cap.\n"); else RARCH_LOG ("DRM: UNIVERSAL PLANES cap set\n"); ret = drmSetClientCap(drm.fd, DRM_CLIENT_CAP_ATOMIC, 1); if (ret) { /*If this happens, check kernel support and kernel parameters * (add i915.nuclear_pageflip=y to the kernel boot line for example) */ RARCH_ERR ("DRM: can't set ATOMIC caps: %s\n", strerror(errno)); } else RARCH_LOG ("DRM: ATOMIC caps set\n"); drm.resources = drmModeGetResources(drm.fd); if (!drm.resources) { RARCH_ERR ("DRM: drmModeGetResources failed\n"); return false; } /* Find a connected connector. */ for (i = 0; i < (uint)drm.resources->count_connectors; i++) { connector = drmModeGetConnector(drm.fd, drm.resources->connectors[i]); /* It's connected, let's use it. */ if (connector->connection == DRM_MODE_CONNECTED) break; drmModeFreeConnector(connector); connector = NULL; } if (!connector) { RARCH_ERR ("DRM: no connected connector found\n"); return false; } /* Find encoder */ for (i = 0; i < (uint)drm.resources->count_encoders; i++) { drm.encoder = drmModeGetEncoder(drm.fd, drm.resources->encoders[i]); if (drm.encoder->encoder_id == connector->encoder_id) break; drmModeFreeEncoder(drm.encoder); drm.encoder = NULL; } if (!drm.encoder) { RARCH_ERR ("DRM: no encoder found.\n"); return false; } drm.crtc_id = drm.encoder->crtc_id; drm.connector_id = connector->connector_id; /* Backup original crtc and it's mode, so we can restore the original video mode * on exit in case we change it. */ drm.orig_crtc = drmModeGetCrtc(drm.fd, drm.encoder->crtc_id); drm.current_mode = &(drm.orig_crtc->mode); /* Set mode physical video mode. Not really needed, but clears TTY console. */ struct modeset_buf buf; buf.width = drm.current_mode->hdisplay; buf.height = drm.current_mode->vdisplay; ret = modeset_create_dumbfb(drm.fd, &buf, 4, DRM_FORMAT_XRGB8888); if (ret) { RARCH_ERR ("DRM: can't create dumb fb\n"); } if (drmModeSetCrtc(drm.fd, drm.crtc_id, buf.fb_id, 0, 0, &drm.connector_id, 1, drm.current_mode)) { RARCH_ERR ("DRM: failed to set mode\n"); return false; } return true; }
const struct drm *init_drm_atomic(const char *device, uint64_t *modifiers, unsigned int num_modifiers) { uint32_t plane_id; int ret; ret = init_drm(&drm, device); if (ret) return NULL; drm.num_modifiers = num_modifiers; drm.modifiers = modifiers; ret = drmSetClientCap(drm.fd, DRM_CLIENT_CAP_ATOMIC, 1); if (ret) { printf("no atomic modesetting support: %s\n", strerror(errno)); return NULL; } ret = get_plane_id(); if (!ret) { printf("could not find a suitable plane\n"); return NULL; } else { plane_id = ret; } /* We only do single plane to single crtc to single connector, no * fancy multi-monitor or multi-plane stuff. So just grab the * plane/crtc/connector property info for one of each: */ drm.plane = calloc(1, sizeof(*drm.plane)); drm.crtc = calloc(1, sizeof(*drm.crtc)); drm.connector = calloc(1, sizeof(*drm.connector)); #define get_resource(type, Type, id) do { \ drm.type->type = drmModeGet##Type(drm.fd, id); \ if (!drm.type->type) { \ printf("could not get %s %i: %s\n", \ #type, id, strerror(errno)); \ return NULL; \ } \ } while (0) get_resource(plane, Plane, plane_id); get_resource(crtc, Crtc, drm.crtc_id); get_resource(connector, Connector, drm.connector_id); #define get_properties(type, TYPE, id) do { \ uint32_t i; \ drm.type->props = drmModeObjectGetProperties(drm.fd, \ id, DRM_MODE_OBJECT_##TYPE); \ if (!drm.type->props) { \ printf("could not get %s %u properties: %s\n", \ #type, id, strerror(errno)); \ return NULL; \ } \ drm.type->props_info = calloc(drm.type->props->count_props, \ sizeof(drm.type->props_info)); \ for (i = 0; i < drm.type->props->count_props; i++) { \ drm.type->props_info[i] = drmModeGetProperty(drm.fd, \ drm.type->props->props[i]); \ } \ } while (0) get_properties(plane, PLANE, plane_id); get_properties(crtc, CRTC, drm.crtc_id); get_properties(connector, CONNECTOR, drm.connector_id); if (num_modifiers == 0) { ret = drm_atomic_get_modifiers(&drm); if (ret < 0) return NULL; } drm.run = atomic_run; return &drm; }
static gboolean gst_kms_sink_start (GstBaseSink * bsink) { GstKMSSink *self; drmModeRes *res; drmModeConnector *conn; drmModeCrtc *crtc; drmModePlaneRes *pres; drmModePlane *plane; gboolean universal_planes; gboolean ret; self = GST_KMS_SINK (bsink); universal_planes = FALSE; ret = FALSE; res = NULL; conn = NULL; crtc = NULL; pres = NULL; plane = NULL; if (self->devname) self->fd = drmOpen (self->devname, NULL); else self->fd = kms_open (&self->devname); if (self->fd < 0) goto open_failed; log_drm_version (self); if (!get_drm_caps (self)) goto bail; res = drmModeGetResources (self->fd); if (!res) goto resources_failed; if (self->conn_id == -1) conn = find_main_monitor (self->fd, res); else conn = drmModeGetConnector (self->fd, self->conn_id); if (!conn) goto connector_failed; crtc = find_crtc_for_connector (self->fd, res, conn, &self->pipe); if (!crtc) goto crtc_failed; retry_find_plane: if (universal_planes && drmSetClientCap (self->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) goto set_cap_failed; pres = drmModeGetPlaneResources (self->fd); if (!pres) goto plane_resources_failed; if (self->plane_id == -1) plane = find_plane_for_crtc (self->fd, res, pres, crtc->crtc_id); else plane = drmModeGetPlane (self->fd, self->plane_id); if (!plane) goto plane_failed; /* let's get the available color formats in plane */ if (!ensure_allowed_caps (self, plane, res)) goto bail; self->conn_id = conn->connector_id; self->crtc_id = crtc->crtc_id; self->plane_id = plane->plane_id; GST_INFO_OBJECT (self, "connector id = %d / crtc id = %d / plane id = %d", self->conn_id, self->crtc_id, self->plane_id); self->hdisplay = crtc->mode.hdisplay; self->vdisplay = crtc->mode.vdisplay; self->buffer_id = crtc->buffer_id; self->mm_width = conn->mmWidth; self->mm_height = conn->mmHeight; GST_INFO_OBJECT (self, "display size: pixels = %dx%d / millimeters = %dx%d", self->hdisplay, self->vdisplay, self->mm_width, self->mm_height); self->pollfd.fd = self->fd; gst_poll_add_fd (self->poll, &self->pollfd); gst_poll_fd_ctl_read (self->poll, &self->pollfd, TRUE); ret = TRUE; bail: if (plane) drmModeFreePlane (plane); if (pres) drmModeFreePlaneResources (pres); if (crtc) drmModeFreeCrtc (crtc); if (conn) drmModeFreeConnector (conn); if (res) drmModeFreeResources (res); if (!ret && self->fd >= 0) { drmClose (self->fd); self->fd = -1; } return ret; /* ERRORS */ open_failed: { GST_ERROR_OBJECT (self, "Could not open DRM module %s: %s", GST_STR_NULL (self->devname), strerror (errno)); return FALSE; } resources_failed: { GST_ERROR_OBJECT (self, "drmModeGetResources failed: %s (%d)", strerror (errno), errno); goto bail; } connector_failed: { GST_ERROR_OBJECT (self, "Could not find a valid monitor connector"); goto bail; } crtc_failed: { GST_ERROR_OBJECT (self, "Could not find a crtc for connector"); goto bail; } set_cap_failed: { GST_ERROR_OBJECT (self, "Could not set universal planes capability bit"); goto bail; } plane_resources_failed: { GST_ERROR_OBJECT (self, "drmModeGetPlaneResources failed: %s (%d)", strerror (errno), errno); goto bail; } plane_failed: { if (universal_planes) { GST_ERROR_OBJECT (self, "Could not find a plane for crtc"); goto bail; } else { universal_planes = TRUE; goto retry_find_plane; } } }
int main(int argc, char *argv[]) { static const char opts[] = "chopv"; static struct option options[] = { { "cursor", 0, 0, 'c' }, { "help", 0, 0, 'h' }, { "overlay", 0, 0, 'o' }, { "primary", 0, 0, 'p' }, { "verbose", 0, 0, 'v' }, { 0, 0, 0, 0 }, }; struct kms_framebuffer *cursor = NULL; struct kms_framebuffer *root = NULL; struct kms_framebuffer *fb = NULL; struct kms_device *device; bool use_overlay = false; bool use_primary = false; struct kms_plane *plane; bool use_cursor = false; bool verbose = false; unsigned int i; int opt, idx; int fd, err; while ((opt = getopt_long(argc, argv, opts, options, &idx)) != -1) { switch (opt) { case 'c': use_cursor = true; break; case 'h': break; case 'o': use_overlay = true; break; case 'p': use_primary = true; break; case 'v': verbose = true; break; default: printf("unknown option \"%c\"\n", opt); return 1; } } if (optind >= argc) { fprintf(stderr, "usage: %s [options] DEVICE\n", argv[0]); return 1; } fd = open(argv[optind], O_RDWR); if (fd < 0) { fprintf(stderr, "open() failed: %m\n"); return 1; } err = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); if (err < 0) { fprintf(stderr, "drmSetClientCap() failed: %d\n", err); return 1; } device = kms_device_open(fd); if (!device) return 1; if (verbose) { printf("Screens: %u\n", device->num_screens); for (i = 0; i < device->num_screens; i++) { struct kms_screen *screen = device->screens[i]; const char *status = "disconnected"; if (screen->connected) status = "connected"; printf(" %u: %x\n", i, screen->id); printf(" Status: %s\n", status); printf(" Name: %s\n", screen->name); printf(" Resolution: %ux%u\n", screen->width, screen->height); } printf("Planes: %u\n", device->num_planes); for (i = 0; i < device->num_planes; i++) { struct kms_plane *plane = device->planes[i]; const char *type = NULL; switch (plane->type) { case DRM_PLANE_TYPE_OVERLAY: type = "overlay"; break; case DRM_PLANE_TYPE_PRIMARY: type = "primary"; break; case DRM_PLANE_TYPE_CURSOR: type = "cursor"; break; } printf(" %u: %p\n", i, plane); printf(" ID: %x\n", plane->id); printf(" CRTC: %x\n", plane->crtc->id); printf(" Type: %x (%s)\n", plane->type, type); } } if (use_cursor) { unsigned int x, y; uint32_t format; plane = kms_device_find_plane_by_type(device, DRM_PLANE_TYPE_CURSOR, 0); if (!plane) { fprintf(stderr, "no cursor plane found\n"); return 1; } format = choose_format(plane); if (!format) { fprintf(stderr, "no matching format found\n"); return 1; } cursor = kms_framebuffer_create(device, 32, 32, format); if (!cursor) { fprintf(stderr, "failed to create cursor buffer\n"); return 1; } prepare_framebuffer(cursor, false); x = (device->screens[0]->width - cursor->width) / 2; y = (device->screens[0]->height - cursor->height) / 2; kms_plane_set(plane, cursor, x, y); } if (use_overlay) { uint32_t format; plane = kms_device_find_plane_by_type(device, DRM_PLANE_TYPE_OVERLAY, 0); if (!plane) { fprintf(stderr, "no overlay plane found\n"); return 1; } format = choose_format(plane); if (!format) { fprintf(stderr, "no matching format found\n"); return 1; } fb = kms_framebuffer_create(device, 320, 240, format); if (!fb) return 1; prepare_framebuffer(fb, false); kms_plane_set(plane, fb, 0, 0); } if (use_primary) { unsigned int x, y; uint32_t format; plane = kms_device_find_plane_by_type(device, DRM_PLANE_TYPE_PRIMARY, 0); if (!plane) { fprintf(stderr, "no primary plane found\n"); return 1; } format = choose_format(plane); if (!format) { fprintf(stderr, "no matching format found\n"); return 1; } root = kms_framebuffer_create(device, 640, 480, format); if (!root) return 1; prepare_framebuffer(root, true); x = (device->screens[0]->width - root->width) / 2; y = (device->screens[0]->height - root->height) / 2; kms_plane_set(plane, root, x, y); } while (1) { struct timeval timeout = { 1, 0 }; fd_set fds; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); err = select(STDIN_FILENO + 1, &fds, NULL, NULL, &timeout); if (err < 0) { fprintf(stderr, "select() failed: %m\n"); break; } /* timeout */ if (err == 0) continue; if (FD_ISSET(STDIN_FILENO, &fds)) break; } if (cursor) kms_framebuffer_free(cursor); if (root) kms_framebuffer_free(root); if (fb) kms_framebuffer_free(fb); kms_device_close(device); close(fd); return 0; }
static void atomic_setup(struct kms_atomic_state *state) { struct kms_atomic_desc *desc = state->desc; drmModeResPtr res; drmModePlaneResPtr res_plane; int i; desc->fd = drm_open_driver_master(DRIVER_INTEL); igt_assert_fd(desc->fd); do_or_die(drmSetClientCap(desc->fd, DRM_CLIENT_CAP_ATOMIC, 1)); res = drmModeGetResources(desc->fd); res_plane = drmModeGetPlaneResources(desc->fd); igt_assert(res); igt_assert(res_plane); igt_assert_lt(0, res->count_crtcs); state->num_crtcs = res->count_crtcs; state->crtcs = calloc(state->num_crtcs, sizeof(*state->crtcs)); igt_assert(state->crtcs); igt_assert_lt(0, res_plane->count_planes); state->num_planes = res_plane->count_planes; state->planes = calloc(state->num_planes, sizeof(*state->planes)); igt_assert(state->planes); igt_assert_lt(0, res->count_connectors); state->num_connectors = res->count_connectors; state->connectors = calloc(state->num_connectors, sizeof(*state->connectors)); igt_assert(state->connectors); fill_obj_props(desc->fd, res->crtcs[0], DRM_MODE_OBJECT_CRTC, NUM_CRTC_PROPS, crtc_prop_names, desc->props_crtc); fill_obj_props(desc->fd, res_plane->planes[0], DRM_MODE_OBJECT_PLANE, NUM_PLANE_PROPS, plane_prop_names, desc->props_plane); fill_obj_prop_map(desc->fd, res_plane->planes[0], DRM_MODE_OBJECT_PLANE, "type", NUM_PLANE_TYPE_PROPS, plane_type_prop_names, desc->props_plane_type); fill_obj_props(desc->fd, res->connectors[0], DRM_MODE_OBJECT_CONNECTOR, NUM_CONNECTOR_PROPS, connector_prop_names, desc->props_connector); for (i = 0; i < state->num_crtcs; i++) { struct kms_atomic_crtc_state *crtc = &state->crtcs[i]; crtc->state = state; crtc->obj = res->crtcs[i]; crtc->idx = i; crtc_get_current_state(crtc); /* The blob pointed to by MODE_ID could well be transient, * and lose its last reference as we switch away from it. * Duplicate the blob here so we have a reference we know we * own. */ if (crtc->mode.id != 0) crtc->mode.id = blob_duplicate(desc->fd, crtc->mode.id); } for (i = 0; i < state->num_planes; i++) { drmModePlanePtr plane = drmModeGetPlane(desc->fd, res_plane->planes[i]); igt_assert(plane); state->planes[i].state = state; state->planes[i].obj = res_plane->planes[i]; state->planes[i].crtc_mask = plane->possible_crtcs; plane_get_current_state(&state->planes[i]); } for (i = 0; i < state->num_connectors; i++) { state->connectors[i].state = state; state->connectors[i].obj = res->connectors[i]; connector_get_current_state(&state->connectors[i]); } drmModeFreePlaneResources(res_plane); drmModeFreeResources(res); }
int main(int argc, char **argv) { int c; int ret = 0; GIOChannel *stdinchannel; GMainLoop *mainloop; float force_clock; bool opt_dump_info = false; struct option long_opts[] = { {"list-subtests", 0, 0, SUBTEST_OPTS}, {"run-subtest", 1, 0, SUBTEST_OPTS}, {"help-description", 0, 0, HELP_DESCRIPTION}, {"help", 0, 0, 'h'}, {"yb", 0, 0, Yb_OPT}, {"yf", 0, 0, Yf_OPT}, { 0, 0, 0, 0 } }; igt_skip_on_simulation(); enter_exec_path( argv ); while ((c = getopt_long(argc, argv, optstr, long_opts, NULL)) != -1) { switch (c) { case '3': test_stereo_modes = 1; break; case 'i': opt_dump_info = true; break; case 'a': test_all_modes = 1; break; case 'f': force_mode = 1; if(sscanf(optarg,"%f,%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu", &force_clock,&force_timing.hdisplay, &force_timing.hsync_start,&force_timing.hsync_end,&force_timing.htotal, &force_timing.vdisplay, &force_timing.vsync_start, &force_timing.vsync_end, &force_timing.vtotal)!= 9) usage(argv[0], c); force_timing.clock = force_clock*1000; break; case 's': sleep_between_modes = atoi(optarg); break; case 'j': do_dpms = atoi(optarg); if (do_dpms == 0) do_dpms = DRM_MODE_DPMS_OFF; break; case 'd': depth = atoi(optarg); igt_info("using depth %d\n", depth); break; case 'p': if (sscanf(optarg, "%d,%d,%d,%d,%d,%d", &plane_width, &plane_height, &crtc_x, &crtc_y, &crtc_w, &crtc_h) != 6) usage(argv[0], c); test_plane = 1; break; case 'm': test_preferred_mode = 1; break; case 't': tiling = LOCAL_I915_FORMAT_MOD_X_TILED; break; case 'y': case Yb_OPT: tiling = LOCAL_I915_FORMAT_MOD_Y_TILED; break; case Yf_OPT: tiling = LOCAL_I915_FORMAT_MOD_Yf_TILED; break; case 'r': qr_code = 1; break; case 'o': sscanf(optarg, "%d,%d", &specified_disp_id, &specified_mode_num); break; case SUBTEST_OPTS: /* invalid subtest options */ exit(IGT_EXIT_INVALID); break; case HELP_DESCRIPTION: igt_info("Tests display functionality."); exit(0); break; default: /* fall through */ case 'h': usage(argv[0], c); break; } } set_termio_mode(); if (depth <= 8) bpp = 8; else if (depth <= 16) bpp = 16; else if (depth <= 32) bpp = 32; if (!test_all_modes && !force_mode && !test_preferred_mode && specified_mode_num == -1 && !test_stereo_modes) test_all_modes = 1; drm_fd = drm_open_driver(DRIVER_INTEL); if (test_stereo_modes && drmSetClientCap(drm_fd, DRM_CLIENT_CAP_STEREO_3D, 1) < 0) { igt_warn("DRM_CLIENT_CAP_STEREO_3D failed\n"); goto out_close; } if (opt_dump_info) { dump_info(); goto out_close; } kmstest_set_vt_graphics_mode(); mainloop = g_main_loop_new(NULL, FALSE); if (!mainloop) { igt_warn("failed to create glib mainloop\n"); ret = -1; goto out_close; } if (!testdisplay_setup_hotplug()) { igt_warn("failed to initialize hotplug support\n"); goto out_mainloop; } stdinchannel = g_io_channel_unix_new(0); if (!stdinchannel) { igt_warn("failed to create stdin GIO channel\n"); goto out_hotplug; } ret = g_io_add_watch(stdinchannel, G_IO_IN | G_IO_ERR, input_event, NULL); if (ret < 0) { igt_warn("failed to add watch on stdin GIO channel\n"); goto out_stdio; } ret = 0; if (!update_display()) { ret = 1; goto out_stdio; } if (test_all_modes) goto out_stdio; g_main_loop_run(mainloop); out_stdio: g_io_channel_shutdown(stdinchannel, TRUE, NULL); out_hotplug: testdisplay_cleanup_hotplug(); out_mainloop: g_main_loop_unref(mainloop); out_close: close(drm_fd); igt_assert_eq(ret, 0); igt_exit(); }
int main(int argc, char **argv) { int fd = drmOpen("radeon", NULL); assert(fd >= 0); // expose all planes including primary and cursor planes assert(!drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)); drmModeResPtr res = drmModeGetResources(fd); assert(res); int i, j; drmModeConnectorPtr connector = NULL; for (i = 0; i < res->count_connectors; i++) { connector = drmModeGetConnector(fd, res->connectors[i]); assert(connector); if (connector->connection == DRM_MODE_CONNECTED) break; drmFree(connector); } drmModeEncoderPtr encoder = drmModeGetEncoder(fd, connector->encoder_id); assert(encoder); drmModeCrtcPtr crtc = drmModeGetCrtc(fd, encoder->crtc_id); assert(crtc); drmModeFBPtr fb = drmModeGetFB(fd, crtc->buffer_id); assert(fb); drmModePlaneResPtr plane_res = drmModeGetPlaneResources(fd); assert(plane_res); drmModePlanePtr plane = NULL; for (i = 0; i < plane_res->count_planes; i++) { plane = drmModeGetPlane(fd, plane_res->planes[i]); assert(plane); if (plane->fb_id == fb->fb_id) break; drmFree(plane); } uint64_t has_dumb; assert(!drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb)); assert(has_dumb); struct drm_mode_create_dumb creq; memset(&creq, 0, sizeof(creq)); creq.width = fb->width; creq.height = fb->height; creq.bpp = fb->bpp; assert(!drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq)); printf("width=%d height=%d bpp=%d pitch=%d size=%d\n", creq.width, creq.height, creq.bpp, creq.pitch, creq.size); uint32_t my_fb; assert(!drmModeAddFB(fd, creq.width, creq.height, 24, creq.bpp, creq.pitch, creq.handle, &my_fb)); struct drm_mode_map_dumb mreq; memset(&mreq, 0, sizeof(mreq)); mreq.handle = creq.handle; assert(!drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)); uint32_t *map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset); assert(map != MAP_FAILED); memset(map, 0, creq.size); for (i = 100; i < 500; i++) for (j = 200; j < 460; j++) map[i * (creq.pitch >> 2) + j] = 0x12345678; assert(!drmModeSetCrtc(fd, crtc->crtc_id, my_fb, 0, 0, &connector->connector_id, 1, &crtc->mode)); sleep(10); assert(!drmModeSetCrtc(fd, crtc->crtc_id, fb->fb_id, 0, 0, &connector->connector_id, 1, &crtc->mode)); assert(!drmModeRmFB(fd, my_fb)); struct drm_mode_destroy_dumb dreq; memset(&dreq, 0, sizeof(dreq)); dreq.handle = creq.handle; assert(!drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq)); drmFree(plane); drmFree(plane_res); drmFree(fb); drmFree(crtc); drmFree(encoder); drmFree(connector); drmFree(res); drmClose(fd); return 0; }
struct sp_dev* create_sp_dev(void) { struct sp_dev *dev; int ret, fd, i, j; drmModeRes *r = NULL; drmModePlaneRes *pr = NULL; fd = open("/dev/dri/card0", O_RDWR); if (fd < 0) { printf("failed to open card0\n"); return NULL; } dev = calloc(1, sizeof(*dev)); if (!dev) { printf("failed to allocate dev\n"); return NULL; } dev->fd = fd; #if 0 ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1); if (ret) { printf("failed to set client cap atomic\n"); goto err; } ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); if (ret) { printf("failed to set client cap\n"); goto err; } #endif r = drmModeGetResources(dev->fd); if (!r) { printf("failed to get r\n"); goto err; } dev->num_connectors = r->count_connectors; dev->connectors = calloc(dev->num_connectors, sizeof(*dev->connectors)); if (!dev->connectors) { printf("failed to allocate connectors\n"); goto err; } for (i = 0; i < dev->num_connectors; i++) { dev->connectors[i] = drmModeGetConnector(dev->fd, r->connectors[i]); if (!dev->connectors[i]) { printf("failed to get connector %d\n", i); goto err; } } dev->num_encoders = r->count_encoders; dev->encoders = calloc(dev->num_encoders, sizeof(*dev->encoders)); if (!dev->encoders) { printf("failed to allocate encoders\n"); goto err; } for (i = 0; i < dev->num_encoders; i++) { dev->encoders[i] = drmModeGetEncoder(dev->fd, r->encoders[i]); if (!dev->encoders[i]) { printf("failed to get encoder %d\n", i); goto err; } } dev->num_crtcs = r->count_crtcs; dev->crtcs = calloc(dev->num_crtcs, sizeof(struct sp_crtc)); if (!dev->crtcs) { printf("failed to allocate crtcs\n"); goto err; } for (i = 0; i < dev->num_crtcs; i++) { dev->crtcs[i].crtc = drmModeGetCrtc(dev->fd, r->crtcs[i]); if (!dev->crtcs[i].crtc) { printf("failed to get crtc %d\n", i); goto err; } dev->crtcs[i].scanout = NULL; dev->crtcs[i].pipe = i; dev->crtcs[i].num_planes = 0; } pr = drmModeGetPlaneResources(dev->fd); if (!pr) { printf("failed to get plane resources\n"); goto err; } dev->num_planes = pr->count_planes; dev->planes = calloc(dev->num_planes, sizeof(struct sp_plane)); for (i = 0; i < dev->num_planes; i++) { drmModeObjectPropertiesPtr props; struct sp_plane *plane = &dev->planes[i]; plane->dev = dev; plane->plane = drmModeGetPlane(dev->fd, pr->planes[i]); if (!plane->plane) { printf("failed to get plane %d\n", i); goto err; } plane->bo = NULL; plane->in_use = 0; ret = get_supported_format(plane, &plane->format); if (ret) { printf("failed to get supported format: %d\n", ret); goto err; } for (j = 0; j < dev->num_crtcs; j++) { if (plane->plane->possible_crtcs & (1 << j)) dev->crtcs[j].num_planes++; } props = drmModeObjectGetProperties(dev->fd, pr->planes[i], DRM_MODE_OBJECT_PLANE); if (!props) { printf("failed to get plane properties\n"); goto err; } #if 0//def USE_ATOMIC_API plane->crtc_pid = get_prop_id(dev, props, "CRTC_ID"); if (!plane->crtc_pid) { drmModeFreeObjectProperties(props); goto err; } plane->fb_pid = get_prop_id(dev, props, "FB_ID"); if (!plane->fb_pid) { drmModeFreeObjectProperties(props); goto err; } plane->crtc_x_pid = get_prop_id(dev, props, "CRTC_X"); if (!plane->crtc_x_pid) { drmModeFreeObjectProperties(props); goto err; } plane->crtc_y_pid = get_prop_id(dev, props, "CRTC_Y"); if (!plane->crtc_y_pid) { drmModeFreeObjectProperties(props); goto err; } plane->crtc_w_pid = get_prop_id(dev, props, "CRTC_W"); if (!plane->crtc_w_pid) { drmModeFreeObjectProperties(props); goto err; } plane->crtc_h_pid = get_prop_id(dev, props, "CRTC_H"); if (!plane->crtc_h_pid) { drmModeFreeObjectProperties(props); goto err; } plane->src_x_pid = get_prop_id(dev, props, "SRC_X"); if (!plane->src_x_pid) { drmModeFreeObjectProperties(props); goto err; } plane->src_y_pid = get_prop_id(dev, props, "SRC_Y"); if (!plane->src_y_pid) { drmModeFreeObjectProperties(props); goto err; } plane->src_w_pid = get_prop_id(dev, props, "SRC_W"); if (!plane->src_w_pid) { drmModeFreeObjectProperties(props); goto err; } plane->src_h_pid = get_prop_id(dev, props, "SRC_H"); if (!plane->src_h_pid) { drmModeFreeObjectProperties(props); goto err; } #endif drmModeFreeObjectProperties(props); } if (pr) drmModeFreePlaneResources(pr); if (r) drmModeFreeResources(r); return dev; err: if (pr) drmModeFreePlaneResources(pr); if (r) drmModeFreeResources(r); destroy_sp_dev(dev); return NULL; }