Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #4
0
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();
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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);
}
Beispiel #11
0
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();
}
Beispiel #12
0
Datei: main.c Projekt: yuq/gfx
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;
}
Beispiel #13
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;
}