예제 #1
0
파일: DRMAtomic.cpp 프로젝트: Arcko/xbmc
void CDRMAtomic::DestroyDrm()
{
  CDRMUtils::DestroyDrm();

  drmModeAtomicFree(m_req);
  m_req = nullptr;
}
예제 #2
0
static int drm_atomic_commit(uint32_t fb_id, uint32_t flags)
{
	drmModeAtomicReq *req;
	uint32_t plane_id = drm.plane->plane->plane_id;
	uint32_t blob_id;
	int ret;

	req = drmModeAtomicAlloc();

	if (flags & DRM_MODE_ATOMIC_ALLOW_MODESET) {
		if (add_connector_property(req, drm.connector_id, "CRTC_ID",
						drm.crtc_id) < 0)
			return -1;

		if (drmModeCreatePropertyBlob(drm.fd, drm.mode, sizeof(*drm.mode),
					      &blob_id) != 0)
			return -1;

		if (add_crtc_property(req, drm.crtc_id, "MODE_ID", blob_id) < 0)
			return -1;

		if (add_crtc_property(req, drm.crtc_id, "ACTIVE", 1) < 0)
			return -1;
	}

	add_plane_property(req, plane_id, "FB_ID", fb_id);
	add_plane_property(req, plane_id, "CRTC_ID", drm.crtc_id);
	add_plane_property(req, plane_id, "SRC_X", 0);
	add_plane_property(req, plane_id, "SRC_Y", 0);
	add_plane_property(req, plane_id, "SRC_W", drm.mode->hdisplay << 16);
	add_plane_property(req, plane_id, "SRC_H", drm.mode->vdisplay << 16);
	add_plane_property(req, plane_id, "CRTC_X", 0);
	add_plane_property(req, plane_id, "CRTC_Y", 0);
	add_plane_property(req, plane_id, "CRTC_W", drm.mode->hdisplay);
	add_plane_property(req, plane_id, "CRTC_H", drm.mode->vdisplay);

	if (drm.kms_in_fence_fd != -1) {
		add_crtc_property(req, drm.crtc_id, "OUT_FENCE_PTR",
				VOID2U64(&drm.kms_out_fence_fd));
		add_plane_property(req, plane_id, "IN_FENCE_FD", drm.kms_in_fence_fd);
	}

	ret = drmModeAtomicCommit(drm.fd, req, flags, NULL);
	if (ret)
		goto out;

	if (drm.kms_in_fence_fd != -1) {
		close(drm.kms_in_fence_fd);
		drm.kms_in_fence_fd = -1;
	}

out:
	drmModeAtomicFree(req);

	return ret;
}
예제 #3
0
static void plane_primary(struct kms_atomic_crtc_state *crtc,
			  struct kms_atomic_plane_state *plane_old)
{
	struct drm_mode_modeinfo *mode = crtc->mode.data;
	struct kms_atomic_plane_state plane = *plane_old;
	uint32_t format = plane_get_igt_format(&plane);
	drmModeAtomicReq *req = drmModeAtomicAlloc();
	uint32_t *connectors;
	int num_connectors;
	struct igt_fb fb;
	int i;

	connectors = calloc(crtc->state->num_connectors, sizeof(*connectors));
	igt_assert(connectors);

	for (i = 0; i < crtc->state->num_connectors; i++) {
		if (crtc->state->connectors[i].crtc_id == crtc->obj)
			connectors[num_connectors++] =
				crtc->state->connectors[i].obj;
	}

	igt_require(format != 0);

	plane.src_x = 0;
	plane.src_y = 0;
	plane.src_w = mode->hdisplay << 16;
	plane.src_h = mode->vdisplay << 16;
	plane.crtc_x = 0;
	plane.crtc_y = 0;
	plane.crtc_w = mode->hdisplay;
	plane.crtc_h = mode->vdisplay;
	plane.crtc_id = crtc->obj;
	plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd,
					    plane.crtc_w, plane.crtc_h,
					    format, I915_TILING_NONE, &fb);

	/* Flip the primary plane using the atomic API, and double-check
	 * state is what we think it should be. */
	crtc_commit_atomic(crtc, &plane, req, ATOMIC_RELAX_NONE);

	/* Restore the primary plane and check the state matches the old. */
	crtc_commit_atomic(crtc, plane_old, req, ATOMIC_RELAX_NONE);

	/* Re-enable the plane through the legacy CRTC/primary-plane API, and
	 * verify through atomic. */
	crtc_commit_legacy(crtc, &plane, CRTC_RELAX_MODE);

	/* Restore the plane to its original settings through the legacy CRTC
	 * API, and verify through atomic. */
	crtc_commit_legacy(crtc, plane_old, CRTC_RELAX_MODE);

	/* Finally, restore to the original state. */
	crtc_commit_atomic(crtc, plane_old, req, ATOMIC_RELAX_NONE);

	drmModeAtomicFree(req);
}
예제 #4
0
static void crtc_invalid_params(struct kms_atomic_crtc_state *crtc_old,
				struct kms_atomic_plane_state *plane,
				struct kms_atomic_connector_state *conn)
{
	struct kms_atomic_crtc_state crtc = *crtc_old;
	drmModeAtomicReq *req = drmModeAtomicAlloc();

	igt_assert(req);

	/* Pass a series of invalid object IDs for the mode ID. */
	crtc.mode.id = plane->obj;
	crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req,
	                       ATOMIC_RELAX_NONE, EINVAL);

	crtc.mode.id = crtc.obj;
	crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req,
	                       ATOMIC_RELAX_NONE, EINVAL);

	crtc.mode.id = conn->obj;
	crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req,
	                       ATOMIC_RELAX_NONE, EINVAL);

	crtc.mode.id = plane->fb_id;
	crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req,
	                       ATOMIC_RELAX_NONE, EINVAL);

	crtc.mode.id = crtc_old->mode.id;
	crtc_commit_atomic(&crtc, plane, req, ATOMIC_RELAX_NONE);

	/* Create a blob which is the wrong size to be a valid mode. */
	do_or_die(drmModeCreatePropertyBlob(crtc.state->desc->fd,
					    crtc.mode.data,
					    sizeof(struct drm_mode_modeinfo) - 1,
					    &crtc.mode.id));
	crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req,
	                       ATOMIC_RELAX_NONE, EINVAL);


	do_or_die(drmModeCreatePropertyBlob(crtc.state->desc->fd,
					    crtc.mode.data,
					    sizeof(struct drm_mode_modeinfo) + 1,
					    &crtc.mode.id));
	crtc_commit_atomic_err(&crtc, plane, crtc_old, plane, req,
	                       ATOMIC_RELAX_NONE, EINVAL);

	/* Restore the CRTC and check the state matches the old. */
	crtc_commit_atomic(crtc_old, plane, req, ATOMIC_RELAX_NONE);

	drmModeAtomicFree(req);
}
예제 #5
0
static void plane_overlay(struct kms_atomic_crtc_state *crtc,
			  struct kms_atomic_plane_state *plane_old)
{
	struct drm_mode_modeinfo *mode = crtc->mode.data;
	struct kms_atomic_plane_state plane = *plane_old;
	uint32_t format = plane_get_igt_format(&plane);
	drmModeAtomicReq *req = drmModeAtomicAlloc();
	struct igt_fb fb;

	igt_require(req);
	igt_require(format != 0);

	plane.src_x = 0;
	plane.src_y = 0;
	plane.src_w = (mode->hdisplay / 2) << 16;
	plane.src_h = (mode->vdisplay / 2) << 16;
	plane.crtc_x = mode->hdisplay / 4;
	plane.crtc_y = mode->vdisplay / 4;
	plane.crtc_w = mode->hdisplay / 2;
	plane.crtc_h = mode->vdisplay / 2;
	plane.crtc_id = crtc->obj;
	plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd,
					    plane.crtc_w, plane.crtc_h,
					    format, I915_TILING_NONE, &fb);

	/* Enable the overlay plane using the atomic API, and double-check
	 * state is what we think it should be. */
	plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE);

	/* Disable the plane and check the state matches the old. */
	plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE);

	/* Re-enable the plane through the legacy plane API, and verify through
	 * atomic. */
	plane_commit_legacy(&plane, ATOMIC_RELAX_NONE);

	/* Restore the plane to its original settings through the legacy plane
	 * API, and verify through atomic. */
	plane_commit_legacy(plane_old, ATOMIC_RELAX_NONE);

	drmModeAtomicFree(req);
}
예제 #6
0
파일: drm_gfx.c 프로젝트: IlDucci/RetroArch
static void drm_page_flip(struct drm_surface *surface)
{
   /* We alredy have the id of the FB_ID property of 
    * the plane on which we are going to do a pageflip:
    * we got it back in drm_plane_setup()  */
   int ret;
   static drmModeAtomicReqPtr req = NULL;

   req = drmModeAtomicAlloc();	

   /* We add the buffer to the plane properties we want to 
    * set on an atomically, in a single step. 
    * We pass the plane id, the property id and the new fb id. */
   ret = drmModeAtomicAddProperty(req, 
         drm.plane_id, 
         drm.plane_fb_prop_id, 
         surface->pages[surface->flip_page].buf.fb_id);

   if (ret < 0)
   {
      RARCH_ERR ("DRM: failed to add atomic property for pageflip\n");
   }
   /*... now we just need to do the commit */

   /* REMEMBER!!! The DRM_MODE_PAGE_FLIP_EVENT flag asks the kernel 
    * to send you an event to the drm.fd once the 
    * pageflip is complete. If you don't want -12 errors 
    * (ENOMEM), namely "Cannot allocate memory", then
    * you must drain the event queue of that fd. */
   ret = drmModeAtomicCommit(drm.fd, req, 0, NULL);

   if (ret < 0)
   {
      RARCH_ERR ("DRM: failed to commit for pageflip: %s\n", strerror(errno));
   }

   surface->flip_page = !(surface->flip_page);

   drmModeAtomicFree(req);
}
예제 #7
0
파일: DRMAtomic.cpp 프로젝트: Arcko/xbmc
void CDRMAtomic::DrmAtomicCommit(int fb_id, int flags, bool rendered, bool videoLayer)
{
  uint32_t blob_id;
  struct plane *plane;

  if (flags & DRM_MODE_ATOMIC_ALLOW_MODESET)
  {
    if (!AddProperty(m_req, m_connector, "CRTC_ID", m_crtc->crtc->crtc_id))
    {
      return;
    }

    if (drmModeCreatePropertyBlob(m_fd, m_mode, sizeof(*m_mode), &blob_id) != 0)
    {
      return;
    }

    if (!AddProperty(m_req, m_crtc, "MODE_ID", blob_id))
    {
      return;
    }

    if (!AddProperty(m_req, m_crtc, "ACTIVE", m_active ? 1 : 0))
    {
      return;
    }

    if (!videoLayer)
    {
      // disable overlay plane on modeset
      AddProperty(m_req, m_overlay_plane, "FB_ID", 0);
      AddProperty(m_req, m_overlay_plane, "CRTC_ID", 0);
    }
  }

  if (videoLayer)
    plane = m_overlay_plane;
  else
    plane = m_primary_plane;

  if (rendered)
  {
    AddProperty(m_req, plane, "FB_ID", fb_id);
    AddProperty(m_req, plane, "CRTC_ID", m_crtc->crtc->crtc_id);
    AddProperty(m_req, plane, "SRC_X", 0);
    AddProperty(m_req, plane, "SRC_Y", 0);
    AddProperty(m_req, plane, "SRC_W", m_mode->hdisplay << 16);
    AddProperty(m_req, plane, "SRC_H", m_mode->vdisplay << 16);
    AddProperty(m_req, plane, "CRTC_X", 0);
    AddProperty(m_req, plane, "CRTC_Y", 0);
    AddProperty(m_req, plane, "CRTC_W", m_mode->hdisplay);
    AddProperty(m_req, plane, "CRTC_H", m_mode->vdisplay);
  }
  else if (videoLayer && !CServiceBroker::GetGUI()->GetWindowManager().HasVisibleControls())
  {
    // disable gui plane when video layer is active and gui has no visible controls
    AddProperty(m_req, plane, "FB_ID", 0);
    AddProperty(m_req, plane, "CRTC_ID", 0);
  }

  auto ret = drmModeAtomicCommit(m_fd, m_req, flags | DRM_MODE_ATOMIC_TEST_ONLY, nullptr);
  if (ret < 0)
  {
    CLog::Log(LOGERROR, "CDRMAtomic::%s - test commit failed: %s", __FUNCTION__, strerror(errno));
  }
  else if (ret == 0)
  {
    ret = drmModeAtomicCommit(m_fd, m_req, flags, nullptr);
    if (ret < 0)
    {
      CLog::Log(LOGERROR, "CDRMAtomic::%s - atomic commit failed: %s", __FUNCTION__, strerror(errno));
    }
  }

  if (flags & DRM_MODE_ATOMIC_ALLOW_MODESET)
  {
    if (drmModeDestroyPropertyBlob(m_fd, blob_id) != 0)
      CLog::Log(LOGERROR, "CDRMAtomic::%s - failed to destroy property blob: %s", __FUNCTION__, strerror(errno));
  }

  drmModeAtomicFree(m_req);
  m_req = drmModeAtomicAlloc();
}
예제 #8
0
static void plane_cursor(struct kms_atomic_crtc_state *crtc,
			 struct kms_atomic_plane_state *plane_old)
{
	struct drm_mode_modeinfo *mode = crtc->mode.data;
	struct kms_atomic_plane_state plane = *plane_old;
	drmModeAtomicReq *req = drmModeAtomicAlloc();
	struct igt_fb fb;
	uint64_t width, height;

	igt_assert(req);

	/* Any kernel new enough for atomic, also has the cursor size caps. */
	do_or_die(drmGetCap(plane.state->desc->fd,
	                    DRM_CAP_CURSOR_WIDTH, &width));
	do_or_die(drmGetCap(plane.state->desc->fd,
	                    DRM_CAP_CURSOR_HEIGHT, &height));

	plane.src_x = 0;
	plane.src_y = 0;
	plane.src_w = width << 16;
	plane.src_h = height << 16;
	plane.crtc_x = mode->hdisplay / 2;
	plane.crtc_y = mode->vdisplay / 2;
	plane.crtc_w = width;
	plane.crtc_h = height;
	plane.crtc_id = crtc->obj;
	plane.fb_id = igt_create_color_fb(plane.state->desc->fd,
					  width, height,
					  DRM_FORMAT_ARGB8888,
					  LOCAL_DRM_FORMAT_MOD_NONE,
					  0.0, 0.0, 0.0,
					  &fb);
	igt_assert_neq_u32(plane.fb_id, 0);

	/* Flip the cursor plane using the atomic API, and double-check
	 * state is what we think it should be. */
	plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE);

	/* Restore the cursor plane and check the state matches the old. */
	plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE);

	/* Re-enable the plane through the legacy cursor API, and verify
	 * through atomic. */
	do_or_die(drmModeMoveCursor(plane.state->desc->fd, plane.crtc_id,
				    plane.crtc_x, plane.crtc_y));
	do_or_die(drmModeSetCursor(plane.state->desc->fd, plane.crtc_id,
				   fb.gem_handle, width, height));
	plane_check_current_state(&plane, PLANE_RELAX_FB);

	/* Wiggle. */
	plane.crtc_x -= 16;
	plane.crtc_y -= 16;
	do_or_die(drmModeMoveCursor(plane.state->desc->fd, plane.crtc_id,
				    plane.crtc_x, plane.crtc_y));
	plane_check_current_state(&plane, PLANE_RELAX_FB);

	/* Restore the plane to its original settings through the legacy cursor
	 * API, and verify through atomic. */
	do_or_die(drmModeSetCursor2(plane.state->desc->fd, plane.crtc_id,
				    0, 0, 0, 0, 0));
	plane_check_current_state(plane_old, ATOMIC_RELAX_NONE);

	/* Finally, restore to the original state. */
	plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE);

	drmModeAtomicFree(req);
}
예제 #9
0
static void plane_invalid_params(struct kms_atomic_crtc_state *crtc,
				 struct kms_atomic_plane_state *plane_old,
				 struct kms_atomic_connector_state *conn)
{
	struct drm_mode_modeinfo *mode = crtc->mode.data;
	struct kms_atomic_plane_state plane = *plane_old;
	uint32_t format = plane_get_igt_format(&plane);
	drmModeAtomicReq *req = drmModeAtomicAlloc();
	struct igt_fb fb;

	/* Pass a series of invalid object IDs for the FB ID. */
	plane.fb_id = plane.obj;
	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, EINVAL);

	plane.fb_id = crtc->obj;
	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, EINVAL);

	plane.fb_id = conn->obj;
	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, EINVAL);

	plane.fb_id = crtc->mode.id;
	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, EINVAL);

	plane.fb_id = plane_old->fb_id;
	plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE);

	/* Pass a series of invalid object IDs for the CRTC ID. */
	plane.crtc_id = plane.obj;
	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, EINVAL);

	plane.crtc_id = plane.fb_id;
	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, EINVAL);

	plane.crtc_id = conn->obj;
	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, EINVAL);

	plane.crtc_id = crtc->mode.id;
	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, EINVAL);

	plane.crtc_id = plane_old->crtc_id;
	plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE);

	/* Create a framebuffer too small for the plane configuration. */
	igt_require(format != 0);

	plane.src_x = 0;
	plane.src_y = 0;
	plane.src_w = mode->hdisplay << 16;
	plane.src_h = mode->vdisplay << 16;
	plane.crtc_x = 0;
	plane.crtc_y = 0;
	plane.crtc_w = mode->hdisplay;
	plane.crtc_h = mode->vdisplay;
	plane.crtc_id = crtc->obj;
	plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd,
					    plane.crtc_w - 1, plane.crtc_h - 1,
					    format, I915_TILING_NONE, &fb);

	plane_commit_atomic_err(&plane, plane_old, req,
	                        ATOMIC_RELAX_NONE, ENOSPC);

	/* Restore the primary plane and check the state matches the old. */
	plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE);

	drmModeAtomicFree(req);
}