static void dump_planes(int gfx_fd, drmModeRes *resources)
{
	drmModePlaneRes             *plane_resources;
	drmModePlane                *ovr;
	int i;

	plane_resources = drmModeGetPlaneResources(gfx_fd);
	if (!plane_resources) {
		printf("drmModeGetPlaneResources failed: %s\n",
			strerror(errno));
		return;
	}

	printf("Planes:\n");
	printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\n");
	for (i = 0; i < plane_resources->count_planes; i++) {
		ovr = drmModeGetPlane(gfx_fd, plane_resources->planes[i]);
		if (!ovr) {
			printf("drmModeGetPlane failed: %s\n",
				strerror(errno));
			continue;
		}

		printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%d\n",
			ovr->plane_id, ovr->crtc_id, ovr->fb_id,
			ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
			ovr->gamma_size);

		drmModeFreePlane(ovr);
	}
	printf("\n");

	return;
}
Пример #2
0
static int connector_find_plane(int fd, unsigned int *plane_id)
{
	drmModePlaneRes *plane_resources;
	drmModePlane *ovr;
	int i;

	plane_resources = drmModeGetPlaneResources(fd);
	if (!plane_resources) {
		fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
			strerror(errno));
		return -1;
	}

	for (i = 0; i < plane_resources->count_planes; i++) {
		plane_id[i] = 0;

		ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
		if (!ovr) {
			fprintf(stderr, "drmModeGetPlane failed: %s\n",
				strerror(errno));
			continue;
		}

		if (ovr->possible_crtcs & (1 << 0))
			plane_id[i] = ovr->plane_id;
		drmModeFreePlane(ovr);
	}

	return 0;
}
Пример #3
0
static void
init_crtc_rotations (MetaMonitorManager *manager,
                     MetaCRTC           *crtc,
                     unsigned int        idx)
{
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
  drmModeObjectPropertiesPtr props;
  drmModePlaneRes *planes;
  drmModePlane *drm_plane;
  MetaCRTCKms *crtc_kms;
  unsigned int i;

  crtc_kms = crtc->driver_private;

  planes = drmModeGetPlaneResources(manager_kms->fd);
  if (planes == NULL)
    return;

  for (i = 0; i < planes->count_planes; i++)
    {
      drmModePropertyPtr prop;

      drm_plane = drmModeGetPlane (manager_kms->fd, planes->planes[i]);

      if (!drm_plane)
        continue;

      if ((drm_plane->possible_crtcs & (1 << idx)))
        {
          props = drmModeObjectGetProperties (manager_kms->fd,
                                              drm_plane->plane_id,
                                              DRM_MODE_OBJECT_PLANE);

          if (props && is_primary_plane (manager, props))
            {
              int rotation_idx;

              crtc_kms->primary_plane_id = drm_plane->plane_id;
              rotation_idx = find_property_index (manager, props, "rotation", &prop);

              if (rotation_idx >= 0)
                {
                  crtc_kms->rotation_prop_id = props->props[rotation_idx];
                  parse_transforms (manager, prop, crtc);
                  drmModeFreeProperty (prop);
                }
            }

          if (props)
            drmModeFreeObjectProperties (props);
        }

      drmModeFreePlane (drm_plane);
    }

  drmModeFreePlaneResources (planes);
}
Пример #4
0
/* Pick a plane.. something that at a minimum can be connected to
 * the chosen crtc, but prefer primary plane.
 *
 * Seems like there is some room for a drmModeObjectGetNamedProperty()
 * type helper in libdrm..
 */
static int get_plane_id(void)
{
	drmModePlaneResPtr plane_resources;
	uint32_t i, j;
	int ret = -EINVAL;
	int found_primary = 0;

	plane_resources = drmModeGetPlaneResources(drm.fd);
	if (!plane_resources) {
		printf("drmModeGetPlaneResources failed: %s\n", strerror(errno));
		return -1;
	}

	for (i = 0; (i < plane_resources->count_planes) && !found_primary; i++) {
		uint32_t id = plane_resources->planes[i];
		drmModePlanePtr plane = drmModeGetPlane(drm.fd, id);
		if (!plane) {
			printf("drmModeGetPlane(%u) failed: %s\n", id, strerror(errno));
			continue;
		}

		if (plane->possible_crtcs & (1 << drm.crtc_index)) {
			drmModeObjectPropertiesPtr props =
				drmModeObjectGetProperties(drm.fd, id, DRM_MODE_OBJECT_PLANE);

			/* primary or not, this plane is good enough to use: */
			ret = id;

			for (j = 0; j < props->count_props; j++) {
				drmModePropertyPtr p =
					drmModeGetProperty(drm.fd, props->props[j]);

				if ((strcmp(p->name, "type") == 0) &&
						(props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY)) {
					/* found our primary plane, lets use that: */
					found_primary = 1;
				}

				drmModeFreeProperty(p);
			}

			drmModeFreeObjectProperties(props);
		}

		drmModeFreePlane(plane);
	}

	drmModeFreePlaneResources(plane_resources);

	return ret;
}
Пример #5
0
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;
}
static int find_plane(int drmfd, struct setup *s)
{
	drmModePlaneResPtr planes;
	drmModePlanePtr plane;
	unsigned int i;
	unsigned int j;
	int ret = 0;

	planes = drmModeGetPlaneResources(drmfd);
	if (WARN_ON(!planes, "drmModeGetPlaneResources failed: %s\n", ERRSTR))
		return -1;

	for (i = 0; i < planes->count_planes; ++i) {
		plane = drmModeGetPlane(drmfd, planes->planes[i]);
		if (WARN_ON(!planes, "drmModeGetPlane failed: %s\n", ERRSTR))
			break;

		if (!(plane->possible_crtcs & (1 << s->crtIdx))) {
			drmModeFreePlane(plane);
			continue;
		}

		for (j = 0; j < plane->count_formats; ++j) {
			if (plane->formats[j] == s->out_fourcc)
				break;
		}

		if (j == plane->count_formats) {
			drmModeFreePlane(plane);
			continue;
		}

		s->planeId = plane->plane_id;
		drmModeFreePlane(plane);
		break;
	}

	if (i == planes->count_planes)
		ret = -1;

	drmModeFreePlaneResources(planes);
	return ret;
}
Пример #7
0
static uint32_t get_plane_prop_id(uint32_t obj_id, const char *name)
{
   int i,j;
   drmModePlaneRes *plane_resources;
   drmModePlane *plane;
   drmModeObjectProperties *props;	
   drmModePropertyRes **props_info;

   char format_str[5];

   plane_resources = drmModeGetPlaneResources(drm.fd);
   for (i = 0; i < plane_resources->count_planes; i++)
   {
      plane = drmModeGetPlane(drm.fd, plane_resources->planes[i]);
      if (plane->plane_id != obj_id)
         continue;

      /* TODO: Improvement. We get all the properties of the 
       * plane and info about the properties.
       * We should have done this already... 
       * This implementation must be improved. */
      props      = drmModeObjectGetProperties(drm.fd,
            plane->plane_id, DRM_MODE_OBJECT_PLANE);
      props_info = malloc(props->count_props * sizeof *props_info);

      for (j = 0; j < props->count_props; ++j)
         props_info[j] =	drmModeGetProperty(drm.fd, props->props[j]);	

      /* We look for the prop_id we need */
      for (j = 0; j < props->count_props; j++)
      {
         if (!strcmp(props_info[j]->name, name))
            return props_info[j]->prop_id;
      }
      RARCH_ERR ("DRM: plane %d fb property ID with name %s not found\n",
            plane->plane_id, name);
   }
   return (0);
}
static int connector_find_plane(int gfx_fd, struct connector *c,
				unsigned int **sprite_plane_id)
{
	drmModePlaneRes *plane_resources;
	drmModePlane *ovr;
	int i, sprite_plane_count = 0;

	plane_resources = drmModeGetPlaneResources(gfx_fd);
	if (!plane_resources) {
		printf("drmModeGetPlaneResources failed: %s\n",
			strerror(errno));
		return 0;
	}

	/* Allocating buffer to hold sprite plane ids of the
         * current connector.
         */
	*sprite_plane_id = (unsigned int *) malloc(plane_resources->count_planes *
						   sizeof(unsigned int));

	for (i = 0; i < plane_resources->count_planes; i++) {
		ovr = drmModeGetPlane(gfx_fd, plane_resources->planes[i]);
		if (!ovr) {
			printf("drmModeGetPlane failed: %s\n",
				strerror(errno));
			continue;
		}
		/* Add the available sprite id to the buffer sprite_plane_id.
                 */
		if (ovr->possible_crtcs & (1 << c->pipe)) {
			(*sprite_plane_id)[sprite_plane_count++] = ovr->plane_id;
		}
		drmModeFreePlane(ovr);
	}

	return sprite_plane_count;
}
Пример #9
0
/* This configures our only overlay plane to render the given surface. */ 
static void drm_plane_setup(struct drm_surface *surface)
{
   int i,j;
   char fmt_name[5];

   /* Get plane resources */
   drmModePlane *plane;	
   drmModePlaneRes *plane_resources;
   plane_resources = drmModeGetPlaneResources(drm.fd);
   if (!plane_resources)
   {
      RARCH_ERR ("DRM: No scaling planes available!\n");
   }

   RARCH_LOG ("DRM: Number of planes on FD %d is %d\n",
         drm.fd, plane_resources->count_planes);	

   /* dump_planes(drm.fd); */	

   /* Look for a plane/overlay we can use with the configured CRTC	
    * Find a  plane which can be connected to our CRTC. Find the
    * CRTC index first, then iterate over available planes.
    * Yes, strangely we need the in-use CRTC index to mask possible_crtc 
    * during the planes iteration... */
   unsigned int crtc_index = 0;
   for (i = 0; i < (unsigned int)drm.resources->count_crtcs; i++)
   {
      if (drm.crtc_id == drm.resources->crtcs[i])
      {
         crtc_index = i;
         RARCH_LOG ("DRM: CRTC index found %d with ID %d\n", crtc_index, drm.crtc_id);
         break;
      }
   }

   /* Programmer!! Save your sanity!! Primary planes have to 
    * cover the entire CRTC, and if you don't do that, you 
    * will get dmesg error "Plane must cover entire CRTC".
    *
    * Look at linux/source/drivers/gpu/drm/drm_plane_helper.c comments for more info.
    * Also, primary planes can't be scaled: we need overlays for that. */
   for (i = 0; i < plane_resources->count_planes; i++)
   {
      plane = drmModeGetPlane(drm.fd, plane_resources->planes[i]);

      if (!(plane->possible_crtcs & (1 << crtc_index))){
         RARCH_LOG ("DRM: plane with ID %d can't be used with current CRTC\n",
               plane->plane_id);
         continue;
      }

      /* We are only interested in overlay planes. No overlay, no fun. 
       * (no scaling, must cover crtc..etc) so we skip primary planes */
      if (drm_plane_type(plane) != DRM_PLANE_TYPE_OVERLAY)
      {
         RARCH_LOG ("DRM: plane with ID %d is not an overlay. May be primary or cursor. Not usable.\n",
               plane->plane_id);
         continue;
      }	

      if (!format_support(plane, surface->pixformat))
      {
         RARCH_LOG ("DRM: plane with ID %d does not support framebuffer format\n", plane->plane_id);
         continue;
      }         

      drm.plane_id = plane->plane_id;
      drmModeFreePlane(plane);
   }

   if (!drm.plane_id)
   {
      RARCH_LOG ("DRM: couldn't find an usable overlay plane for current CRTC and framebuffer pixel formal.\n");
      deinit_drm();
      exit (0);
   }
   else
   {
      RARCH_LOG ("DRM: using plane/overlay ID %d\n", drm.plane_id);
   }

   /* We are going to be changing the framebuffer ID property of the chosen overlay every time
    * we do a pageflip, so we get the property ID here to have it handy on the PageFlip function. */	
   drm.plane_fb_prop_id = get_plane_prop_id(drm.plane_id, "FB_ID");
   if (!drm.plane_fb_prop_id)
   {
      RARCH_LOG("DRM: Can't get the FB property ID for plane(%u)\n", drm.plane_id);
   }

   /* Note src coords (last 4 args) are in Q16 format
    * crtc_w and crtc_h are the final size with applied scale/ratio.
    * crtc_x and crtc_y are the position of the plane
    * pw and ph are the input size: the size of the area we read from the fb. */
   uint32_t plane_flags = 0;
   uint32_t plane_w = drm.current_mode->vdisplay * surface->aspect;;
   uint32_t plane_h = drm.current_mode->vdisplay;
   /* If we obtain a scaled image width that is bigger than the physical screen width,
    * then we keep the physical screen width as our maximun width. */
   if (plane_w > drm.current_mode->hdisplay)
      plane_w = drm.current_mode->hdisplay;

   uint32_t plane_x = (drm.current_mode->hdisplay - plane_w) / 2;
   uint32_t plane_y = (drm.current_mode->vdisplay - plane_h) / 2;

   uint32_t src_w = surface->src_width;
   uint32_t src_h = surface->src_height;
   uint32_t src_x = 0;
   uint32_t src_y = 0;

   /* We have to set a buffer for the plane, whatever buffer we want, 
    * but we must set a buffer so the plane starts reading from it now. */
   if (drmModeSetPlane(drm.fd, drm.plane_id, drm.crtc_id, 
            surface->pages[surface->flip_page].buf.fb_id,
            plane_flags, plane_x, plane_y, plane_w, plane_h,
            src_x<<16, src_y<<16, src_w<<16, src_h<<16))
   {
      RARCH_ERR("DRM: failed to enable plane: %s\n", strerror(errno));	
   }

   RARCH_LOG("DRM: src_w %d, src_h %d, plane_w %d, plane_h %d\n",
         src_w, src_h, plane_w, plane_h);

   /* Report what plane (of overlay type) we're using. */
   drm_format_name(surface->pixformat, fmt_name);
   RARCH_LOG("DRM: Using plane with ID %d on CRTC ID %d format %s\n",
         drm.plane_id, drm.crtc_id, fmt_name);
}
Пример #10
0
Файл: main.c Проект: 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;
}
Пример #11
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;
    }
  }
}
Пример #12
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);
}
Пример #13
0
// -----------------------------------------------------------------------------
bool WindowOffscreenEGL::initDrm(const char *name, EGLAttrib *layerAttribs, int &dispWidth, int &dispHeight)
{
    // screen attached to which connector id?
    int conn = 0;
    int crtc = -1, plane = -1;
    int xSurfSize = 0, ySurfSize = 0;
    int xOffset = 0, yOffset = 0;
    // auto detect resolution by setting modesize to 0
    //int xModeSize = dispWidth, yModeSize = dispHeight;
    int xModeSize = 0, yModeSize = 0;
    int bounce = 0;

    int drmFd;
    uint32_t drmConnId, drmEncId, drmCrtcId, drmPlaneId;
    uint32_t crtcMask;
    drmModeRes *drmResInfo           = nullptr;
    drmModePlaneRes *drmPlaneResInfo = nullptr;
    drmModeCrtc *drmCrtcInfo         = nullptr;
    drmModeConnector *drmConnInfo    = nullptr;
    drmModeEncoder *drmEncInfo       = nullptr;
    drmModePlane *drmPlaneInfo       = nullptr;
    int drmModeIndex                 = 0;

    bool setMode = false;

    drmFd = drmOpen(name, nullptr);
    if (drmFd == -1) {
        std::cout << "Couldn't open device file " << name << std::endl;
        return false;
    }

    // Obtain DRM-KMS resources
    drmResInfo = drmModeGetResources(drmFd);
    if (!drmResInfo) {
        std::cout << "Couldn't obtain DRM-KMS resources" << std::endl;
        return false;
    }

    // If a specific crtc was requested, make sure it exists
    if (crtc >= drmResInfo->count_crtcs) {
        std::cout << "Requested crtc index (" << crtc
                  << ") exceeds count (" << drmResInfo->count_crtcs << ")" << std::endl;
        return false;
    }
    crtcMask = (crtc >= 0) ? (1 << crtc) : ((1 << drmResInfo->count_crtcs) - 1);

    // If drawing to a plane is requested, obtain the plane info
    if (plane >= 0) {
        drmPlaneResInfo = drmModeGetPlaneResources(drmFd);
        if (!drmPlaneResInfo) {
            std::cout << "Unable to obtain plane resource list" << std::endl;
            return false;
        }
        if (plane >= (int)drmPlaneResInfo->count_planes) {
            std::cout << "Requested plane index (" << plane
                      << ") exceeds count (" << drmPlaneResInfo->count_planes << ")" << std::endl;
            return false;
        }
        drmPlaneId   = drmPlaneResInfo->planes[plane];
        drmPlaneInfo = drmModeGetPlane(drmFd, drmPlaneId);
        if (!drmPlaneInfo) {
            std::cout << "Unable to obtain info for plane (" << drmPlaneId << ")" << std::endl;
            return false;
        }
        crtcMask &= drmPlaneInfo->possible_crtcs;
        if (!crtcMask) {
            std::cout << "Requested crtc and plane not compatible" << std::endl;
            return false;
        }
        std::cout << "Obtained plane information\n" << std::endl;
    }

    // Query info for requested connector
    if (conn >= drmResInfo->count_connectors) {
        std::cout << "Requested connector index (" << conn << ") exceeds count ("
                  << drmResInfo->count_connectors << ")" << std::endl;
        return false;
    }
    drmConnId   = drmResInfo->connectors[conn];
    drmConnInfo = drmModeGetConnector(drmFd, drmConnId);
    if (!drmConnInfo) {
        std::cout << "Unable to obtain info for connector (" << drmConnId << ")" << std::endl;
        return false;
    } else if (drmConnInfo->connection != DRM_MODE_CONNECTED) {
        std::cout << "Requested connnector is not connected (mode="
                  << drmConnInfo->connection << ")" << std::endl;
        return false;
    } else if (drmConnInfo->count_modes <= 0) {
        std::cout << "Requested connnector has no available modes" << std::endl;
        return false;
    }

    // If there is already an encoder attached to the connector, choose
    //   it unless not compatible with crtc/plane
    drmEncId   = drmConnInfo->encoder_id;
    drmEncInfo = drmModeGetEncoder(drmFd, drmEncId);
    if (drmEncInfo) {
        if (!(drmEncInfo->possible_crtcs & crtcMask)) {
            drmModeFreeEncoder(drmEncInfo);
            drmEncInfo = nullptr;
        }
    }

    // If we didn't have a suitable encoder, find one
    if (!drmEncInfo) {
        int i;
        for (i = 0; i < drmConnInfo->count_encoders; ++i) {
            drmEncId   = drmConnInfo->encoders[i];
            drmEncInfo = drmModeGetEncoder(drmFd, drmEncId);
            if (drmEncInfo) {
                if (crtcMask & drmEncInfo->possible_crtcs) {
                    crtcMask &= drmEncInfo->possible_crtcs;
                    break;
                }
                drmModeFreeEncoder(drmEncInfo);
                drmEncInfo = nullptr;
            }
        }
        if (i == drmConnInfo->count_encoders) {
            std::cout << "Unable to find suitable encoder" << std::endl;
            return false;
        }
    }

    // Select a suitable crtc. Give preference to any that is already
    // attached to the encoder.
    drmCrtcId = drmEncInfo->crtc_id;
    for (int i = 0; i < drmResInfo->count_crtcs; ++i) {
        if (crtcMask & (1 << i)) {
            drmCrtcId = drmResInfo->crtcs[i];
            if (drmResInfo->crtcs[i] == drmEncInfo->crtc_id) {
                break;
            }
        }
    }

    // Query info for crtc
    drmCrtcInfo = drmModeGetCrtc(drmFd, drmCrtcId);
    if (!drmCrtcInfo) {
        std::cout << "Unable to obtain info for crtc (" << drmCrtcId << ")" << std::endl;
        return false;
    }

    // If dimensions are specified and not using a plane, find closest mode
    if ((xModeSize || yModeSize) && (plane < 0)) {
        // Find best fit among available modes
        int best_index = 0;
        int best_fit = 0x7fffffff;
        for (int i = 0; i < drmConnInfo->count_modes; ++i) {
            drmModeModeInfoPtr mode = drmConnInfo->modes + i;
            int fit                 = 0;

            if (xModeSize) {
                fit += abs((int)mode->hdisplay - xModeSize) * (int)mode->vdisplay;
            }
            if (yModeSize) {
                fit += abs((int)mode->vdisplay - yModeSize) * (int)mode->hdisplay;
            }

            if (fit < best_fit) {
                best_index = i;
                best_fit   = fit;
            }
            std::cout << i << ": " << (int)mode->hdisplay << " x "
                      << (int)mode->vdisplay - yModeSize << std::endl;
        }

        // Choose this size/mode
        drmModeIndex = best_index;
        xModeSize    = (int)drmConnInfo->modes[best_index].hdisplay;
        yModeSize    = (int)drmConnInfo->modes[best_index].vdisplay;
    }

    // We'll only set the mode if we have to.
    if ((drmConnInfo->encoder_id != drmEncId) ||
        (drmEncInfo->crtc_id != drmCrtcId) ||
        !drmCrtcInfo->mode_valid ||
        ((plane < 0) && xModeSize && (xModeSize != (int)drmCrtcInfo->mode.hdisplay)) ||
        ((plane < 0) && yModeSize && (yModeSize != (int)drmCrtcInfo->mode.vdisplay))) {
        setMode = true;
    }

    // If dimensions haven't been specified, figure out good values to use
    if (!xModeSize || !yModeSize) {
        // If mode requires reset, just pick the first one available
        //   from the connector
        if (setMode) {
            xModeSize = (int)drmConnInfo->modes[0].hdisplay;
            yModeSize = (int)drmConnInfo->modes[0].vdisplay;
        }
        // Otherwise get it from the current crtc settings
        else {
            xModeSize = (int)drmCrtcInfo->mode.hdisplay;
            yModeSize = (int)drmCrtcInfo->mode.vdisplay;
        }
    }

    // If surf size is unspecified, default to fullscreen normally
    // or to 1/4 fullscreen if in animated bounce mode.
    if (!xSurfSize || !ySurfSize) {
        if (bounce) {
            xSurfSize = xModeSize / 2;
            ySurfSize = yModeSize / 2;
        } else {
            xSurfSize = xModeSize;
            ySurfSize = yModeSize;
        }
    }

    // If necessary, set the mode
    if (setMode) {
        drmModeSetCrtc(drmFd, drmCrtcId, -1, 0, 0, &drmConnId, 1, drmConnInfo->modes + drmModeIndex);
        std::cout << "Set mode" << std::endl;
    }

    // If plane is in use, set it
    if (plane >= 0) {
        drmModeSetPlane(drmFd, drmPlaneId, drmCrtcId, -1, 0,
                        xOffset, yOffset, xSurfSize, ySurfSize,
                        0, 0, xSurfSize << 16, ySurfSize << 16);
        std::cout << "Set plane configuration" << std::endl;
    }

    // Get the layer for this crtc/plane
    if (plane >= 0) {
        layerAttribs[0] = EGL_DRM_PLANE_EXT;
        layerAttribs[1] = (EGLAttrib)drmPlaneId;
    } else {
        layerAttribs[0] = EGL_DRM_CRTC_EXT;
        layerAttribs[1] = (EGLAttrib)drmCrtcId;
    }
    dispWidth  = xSurfSize;
    dispHeight = ySurfSize;

    return true;
}
int
gralloc_kms_planes_init(struct gralloc_drm_t *drm)
{
	drmModeResPtr resources;
	drmModePlaneResPtr planes;
	int i, order;

	/* What else than the ordering in the main resources would reliably
	   tell us what the possible_crtcs field for the planes mean?
	   Way to save overhead! */
	resources = drmModeGetResources(drm->fd);
	if (!resources) {
		LOGE("Failed to get KMS resources\n");
		return -EINVAL;
	}

	for (order = 0; order < resources->count_crtcs; order++)
		if (resources->crtcs[order] == drm->crtc_id)
			break;

	if (order == resources->count_crtcs) {
		LOGE("Failed to find crtc %d in KMS resources\n", drm->crtc_id);
		drmModeFreeResources(resources);
		return -EINVAL;
	}

	drmModeFreeResources(resources);

	planes = drmModeGetPlaneResources(drm->fd);
	if (!planes) {
		LOGE("Failed to get KMS Plane resources\n");
		return -EINVAL;
	}

	for (i = 0; i < (int) planes->count_planes; i++) {
		drmModePlanePtr plane =
			drmModeGetPlane(drm->fd, planes->planes[i]);

		if (!plane) {
			LOGE("Failed to get Plane %d: %s\n", planes->planes[i],
			     strerror(errno));
			return errno;
		}

		if (plane->possible_crtcs & (1 << order)) {
			int ret = gralloc_kms_plane_add(drm, plane);
			if (ret) {
				drmModeFreePlane(plane);
				drmModeFreePlaneResources(planes);
				return ret;
			}
		}

		drmModeFreePlane(plane);
	}

	drmModeFreePlaneResources(planes);

	LOGI("%s: %d planes\n", __func__, drm->plane_count);
	for (i = 0; i < drm->plane_count; i++) {
		char buffer[1024];
		int j;

		for (j = 0; j < drm->planes[i]->format_count; j++)
			sprintf(buffer + 6 * j, " %c%c%c%c,",
				drm->planes[i]->formats[j] & 0xFF,
				(drm->planes[i]->formats[j] >> 8) & 0xFF,
				(drm->planes[i]->formats[j] >> 16) & 0xFF,
				(drm->planes[i]->formats[j] >> 24) & 0xFF);
		LOGI("\t%d: %s", drm->planes[i]->id, buffer);
	}

	return 0;
}
Пример #15
0
int main(int argc, char *argv[])
{
	uint64_t has_dumb;
	int ret, fd, opt, i;
	void *map;

	struct drm_mode_destroy_dumb dreq;
	struct drm_mode_create_dumb creq;
	struct drm_mode_map_dumb mreq;

	drmModePlaneRes *resources;
	drmModePlane *plane = NULL;

	uint32_t handle, stride, size;
	uint32_t plane_id, crtc_id;
	uint32_t width, height;
	uint32_t posx, posy;
	uint32_t fb;

	/* parse command line */

	while ((opt = getopt(argc, argv, "x:y:w:v:c:p:h")) != -1) {
		switch (opt) {
			case 'x':
				posx = atoi(optarg);
				break;
			case 'y':
				posy = atoi(optarg);
				break;
			case 'w':
				width = atoi(optarg);
				break;
			case 'v':
				height = atoi(optarg);
				break;
			case 'p':
				plane_id = atoi(optarg);
				break;
			case 'c':
				crtc_id = atoi(optarg);
				break;
			case 'h':
			default:
				printf("usage: -h] -c <connector> -e <encoder> -m <mode>\n");
				printf("\t-h: this help message\n");
				printf("\t-c <crtc>			crtc id, default is 0\n");
				printf("\t-p <plane>		plane id, default is 0\n");
				printf("\t-x <posx>			plane top left corner xpos, default is 0'\n");
				printf("\t-y <posy>			plane top left corner ypos, default is 0'\n");
				printf("\t-w <width>		plane width, default is 0'\n");
				printf("\t-v <height>		plane height, default is 0'\n");
				exit(0);
		}
	}

	/* open drm device */

	fd = open(device_name, O_RDWR | O_CLOEXEC);
	if (fd < 0) {
		perror("cannot open drm device");
		exit(-1);
	}

	drmSetMaster(fd);

    /* check dumb buffer support */

	if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0) {
		perror("DRM_CAP_DUMB_BUFFER ioctl");
		ret = -EFAULT;
		goto err_close;
	}

	if (!has_dumb) {
		fprintf(stderr, "driver does not support dumb buffers\n");
		ret = -EFAULT;
		goto err_close;
	}

	/* get plane */

	resources = drmModeGetPlaneResources(fd);
	if (!resources || resources->count_planes == 0) {
		fprintf(stderr, "drmModeGetPlaneResources failed\n");
		ret = -ENODEV;
		goto err_close;
	}

	for (i = 0; i < resources->count_planes; i++) {
		drmModePlane *p = drmModeGetPlane(fd, resources->planes[i]);
		if (!p)
			continue;

		if (p->plane_id == plane_id) {
			plane = p;
			break;
		}

		drmModeFreePlane(plane);
	}

	if (!plane) {
		fprintf(stderr, "couldn't find specified plane\n");
		ret = -ENODEV;
		goto err_close;
	}

	/* create dumb buffer object */

	memset(&creq, 0, sizeof(creq));

	creq.height = height;
	creq.width = width;
	creq.bpp = 32;

	ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
	if (ret) {
		fprintf(stderr, "failed drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)\n");
		goto err_close;
	}

	handle = creq.handle;
	stride = creq.pitch;
	size = creq.size;

	/* create framebuffer for dumb buffer object */

	ret = drmModeAddFB(fd, width, height, 24, 32, stride, handle, &fb);
	if (ret) {
		fprintf(stderr, "cannot add drm framebuffer for dumb buffer object\n");
		goto err_destroy_dumb;
	}

	/* map dumb buffer object */

	memset(&mreq, 0, sizeof(mreq));

	mreq.handle = handle;

	ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
	if (ret) {
		fprintf(stderr, "failed drmIoctl(DRM_IOCTL_MODE_MAP_DUMB)\n");
		goto err_destroy_fb;
	}

	map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
	if (map == MAP_FAILED) {
		fprintf(stderr, "cannot mmap dumb buffer\n");
		goto err_destroy_fb;
	}

	/* setup new plane */

	ret = drmModeSetPlane(fd, plane_id, crtc_id, fb, 0, posx, posy,
		width, height, 0, 0, width << 16, height << 16);
	if (ret) {
		fprintf(stderr, "cannot set plane\n");
		goto err_unmap;
	}

	/* draw on the screen */
	draw_test_image((uint32_t *) map, width, height);
	getchar();

	draw_fancy_image((uint32_t *) map, width, height);
	getchar();

	drmModeSetPlane(fd, plane_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

err_unmap:
	if (map)
		munmap(map, size);

err_destroy_fb:
	drmModeRmFB(fd, fb);

err_destroy_dumb:
	memset(&dreq, 0, sizeof(dreq));

	dreq.handle = handle;

	ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
	if (ret) {
		fprintf(stderr, "cannot destroy dumb buffer\n");
	}

err_close:
	close(fd);

	return ret;
}
Пример #16
0
bool CDRMUtils::GetPlanes()
{
  drmModePlaneResPtr plane_resources;
  uint32_t primary_plane_id = 0;
  uint32_t overlay_plane_id = 0;
  uint32_t fourcc = 0;

  plane_resources = drmModeGetPlaneResources(m_fd);
  if (!plane_resources)
  {
    CLog::Log(LOGERROR, "CDRMUtils::%s - drmModeGetPlaneResources failed: %s", __FUNCTION__, strerror(errno));
    return false;
  }

  for (uint32_t i = 0; i < plane_resources->count_planes; i++)
  {
    uint32_t id = plane_resources->planes[i];
    drmModePlanePtr plane = drmModeGetPlane(m_fd, id);
    if (!plane)
    {
      CLog::Log(LOGERROR, "CDRMUtils::%s - drmModeGetPlane(%u) failed: %s", __FUNCTION__, id, strerror(errno));
      continue;
    }

    if (plane->possible_crtcs & (1 << m_crtc_index))
    {
      drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(m_fd, id, DRM_MODE_OBJECT_PLANE);

      for (uint32_t j = 0; j < props->count_props; j++)
      {
        drmModePropertyPtr p = drmModeGetProperty(m_fd, props->props[j]);

        if ((strcmp(p->name, "type") == 0) && (props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY) && (primary_plane_id == 0))
        {
          CLog::Log(LOGDEBUG, "CDRMUtils::%s - found primary plane: %u", __FUNCTION__, id);
          primary_plane_id = id;
        }
        else if ((strcmp(p->name, "type") == 0) && (props->prop_values[j] == DRM_PLANE_TYPE_OVERLAY) && (overlay_plane_id == 0))
        {
          CLog::Log(LOGDEBUG, "CDRMUtils::%s - found overlay plane: %u", __FUNCTION__, id);
          overlay_plane_id = id;
        }

        drmModeFreeProperty(p);
      }

      drmModeFreeObjectProperties(props);
    }

    drmModeFreePlane(plane);
  }

  drmModeFreePlaneResources(plane_resources);

  // primary plane
  m_primary_plane->plane = drmModeGetPlane(m_fd, primary_plane_id);
  if (!m_primary_plane->plane)
  {
    CLog::Log(LOGERROR, "CDRMUtils::%s - could not get primary plane %u: %s", __FUNCTION__, primary_plane_id, strerror(errno));
    return false;
  }

  if (!GetProperties(m_fd, primary_plane_id, DRM_MODE_OBJECT_PLANE, m_primary_plane))
  {
    CLog::Log(LOGERROR, "CDRMUtils::%s - could not get primary plane %u properties: %s", __FUNCTION__, primary_plane_id, strerror(errno));
    return false;
  }

  for (uint32_t i = 0; i < m_primary_plane->plane->count_formats; i++)
  {
    /* we want an alpha layer so break if we find one */
    if (m_primary_plane->plane->formats[i] == DRM_FORMAT_XRGB8888)
    {
      fourcc = DRM_FORMAT_XRGB8888;
      m_primary_plane->format = fourcc;
    }
    else if (m_primary_plane->plane->formats[i] == DRM_FORMAT_ARGB8888)
    {
      fourcc = DRM_FORMAT_ARGB8888;
      m_primary_plane->format = fourcc;
      break;
    }
  }

  if (fourcc == 0)
  {
    CLog::Log(LOGERROR, "CDRMUtils::%s - could not find a suitable primary plane format", __FUNCTION__);
    return false;
  }

  CLog::Log(LOGDEBUG, "CDRMUtils::%s - primary plane format: %c%c%c%c", __FUNCTION__, fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24);

  if (overlay_plane_id != 0)
  {
    // overlay plane
    m_overlay_plane->plane = drmModeGetPlane(m_fd, overlay_plane_id);
    if (!m_overlay_plane->plane)
    {
      CLog::Log(LOGERROR, "CDRMUtils::%s - could not get overlay plane %u: %s", __FUNCTION__, overlay_plane_id, strerror(errno));
      return false;
    }

    if (!GetProperties(m_fd, overlay_plane_id, DRM_MODE_OBJECT_PLANE, m_overlay_plane))
    {
      CLog::Log(LOGERROR, "CDRMUtils::%s - could not get overlay plane %u properties: %s", __FUNCTION__, overlay_plane_id, strerror(errno));
      return false;
    }

    fourcc = 0;

    for (uint32_t i = 0; i < m_overlay_plane->plane->count_formats; i++)
    {
      /* we want an alpha layer so break if we find one */
      if (m_overlay_plane->plane->formats[i] == DRM_FORMAT_XRGB8888)
      {
        fourcc = DRM_FORMAT_XRGB8888;
        m_overlay_plane->format = fourcc;
      }
      else if(m_overlay_plane->plane->formats[i] == DRM_FORMAT_ARGB8888)
      {
        fourcc = DRM_FORMAT_ARGB8888;
        m_overlay_plane->format = fourcc;
        break;
      }
    }

    if (fourcc == 0)
    {
      CLog::Log(LOGERROR, "CDRMUtils::%s - could not find a suitable overlay plane format", __FUNCTION__);
      return false;
    }

    CLog::Log(LOGDEBUG, "CDRMUtils::%s - overlay plane format: %c%c%c%c", __FUNCTION__, fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24);
  }
Пример #17
0
struct drm_atomic_context *drm_atomic_create_context(struct mp_log *log, int fd, int crtc_id,
                                                     int connector_id, int osd_plane_id, int video_plane_id)
{
    drmModePlaneRes *plane_res = NULL;
    drmModeRes *res = NULL;
    struct drm_object *plane = NULL;
    struct drm_atomic_context *ctx;
    int crtc_index = -1;
    int layercount = -1;
    int primary_id = 0;
    int overlay_id = 0;

    uint64_t value;

    res = drmModeGetResources(fd);
    if (!res) {
        mp_err(log, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
        goto fail;
    }

    plane_res = drmModeGetPlaneResources(fd);
    if (!plane_res) {
        mp_err(log, "Cannot retrieve plane ressources: %s\n", mp_strerror(errno));
        goto fail;
    }

    ctx = talloc_zero(NULL, struct drm_atomic_context);
    if (!ctx) {
        mp_err(log, "Out of memory\n");
        goto fail;
    }

    ctx->fd = fd;
    ctx->crtc = drm_object_create(log, ctx->fd, crtc_id, DRM_MODE_OBJECT_CRTC);
    if (!ctx->crtc) {
        mp_err(log, "Failed to create CRTC object\n");
        goto fail;
    }

    for (int i = 0; i < res->count_crtcs; i++) {
        if (res->crtcs[i] == crtc_id) {
            crtc_index = i;
            break;
        }
    }

    for (int i = 0; i < res->count_connectors; i++) {
        drmModeConnector *connector = drmModeGetConnector(fd, res->connectors[i]);
        if (connector) {
            if (connector->connector_id == connector_id)
                ctx->connector =  drm_object_create(log, ctx->fd, connector->connector_id,
                                                    DRM_MODE_OBJECT_CONNECTOR);

            drmModeFreeConnector(connector);
            if (ctx->connector)
                break;
        }
    }

    for (unsigned int j = 0; j < plane_res->count_planes; j++) {

        drmModePlane *drmplane = drmModeGetPlane(ctx->fd, plane_res->planes[j]);
        const uint32_t possible_crtcs = drmplane->possible_crtcs;
        const uint32_t plane_id = drmplane->plane_id;
        drmModeFreePlane(drmplane);
        drmplane = NULL;

        if (possible_crtcs & (1 << crtc_index)) {
            plane = drm_object_create(log, ctx->fd, plane_id,
                                      DRM_MODE_OBJECT_PLANE);

            if (!plane) {
                mp_err(log, "Failed to create Plane object from plane ID %d\n",
                       plane_id);
                goto fail;
            }

            if (drm_object_get_property(plane, "TYPE", &value) == -EINVAL) {
                mp_err(log, "Unable to retrieve type property from plane %d\n", j);
                goto fail;
            }

            if (value != DRM_PLANE_TYPE_CURSOR) { // Skip cursor planes
                layercount++;

                if ((!primary_id) && (value == DRM_PLANE_TYPE_PRIMARY))
                    primary_id = plane_id;

                if ((!overlay_id) && (value == DRM_PLANE_TYPE_OVERLAY))
                    overlay_id = plane_id;

                if (layercount == osd_plane_id) {
                    ctx->osd_plane = plane;
                    continue;
                }

                if (layercount == video_plane_id) {
                    ctx->video_plane = plane;
                    continue;
                }
            }

            drm_object_free(plane);
            plane = NULL;
        }
    }

    // default OSD plane to primary if unspecified
    if (!ctx->osd_plane) {
        if (primary_id) {
            mp_verbose(log, "Using default plane %d for OSD\n", primary_id);
            ctx->osd_plane = drm_object_create(log, ctx->fd, primary_id, DRM_MODE_OBJECT_PLANE);
        } else {
            mp_err(log, "Failed to find OSD plane with id=%d\n", osd_plane_id);
            goto fail;
        }
    } else {
        mp_verbose(log, "Found OSD plane with ID %d\n", ctx->osd_plane->id);
    }

    // default video plane to overlay if unspecified
    if (!ctx->video_plane) {
        if (overlay_id) {
            mp_verbose(log, "Using default plane %d for video\n", overlay_id);
            ctx->video_plane = drm_object_create(log, ctx->fd, overlay_id, DRM_MODE_OBJECT_PLANE);
        } else {
            mp_verbose(log, "Failed to find video plane with id=%d. drmprime-drm hwdec interop will not work\n", video_plane_id);
        }
    } else {
        mp_verbose(log, "Found video plane with ID %d\n", ctx->video_plane->id);
    }

    drmModeFreePlaneResources(plane_res);
    drmModeFreeResources(res);
    return ctx;

fail:
    if (res)
        drmModeFreeResources(res);
    if (plane_res)
        drmModeFreePlaneResources(plane_res);
    if (plane)
        drm_object_free(plane);
    return NULL;
}
Пример #18
0
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();
}
Пример #19
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;
}