Beispiel #1
0
/**
 * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target
 *
 * @crtc: CRTC to attach FB to
 * @fb: FB to attach
 * @event: Event to be posted. This event should've been alloced
 *         using k[mz]alloc, and should've been completely initialized.
 * @page_flip_flags: Input flags.
 *
 * If the STDU uses the same display and content buffers, i.e. a true flip,
 * this function will replace the existing display buffer with the new content
 * buffer.
 *
 * If the STDU uses different display and content buffers, i.e. a blit, then
 * only the content buffer will be updated.
 *
 * RETURNS:
 * 0 on success, error code on failure
 */
static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
                                   struct drm_framebuffer *new_fb,
                                   struct drm_pending_vblank_event *event,
                                   uint32_t flags)

{
    struct vmw_private *dev_priv = vmw_priv(crtc->dev);
    struct vmw_screen_target_display_unit *stdu;
    struct drm_vmw_rect vclips;
    struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
    int ret;

    dev_priv          = vmw_priv(crtc->dev);
    stdu              = vmw_crtc_to_stdu(crtc);

    if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc))
        return -EINVAL;

    ret = vmw_stdu_bind_fb(dev_priv, crtc, &crtc->mode, new_fb);
    if (ret)
        return ret;

    if (stdu->base.is_implicit)
        vmw_kms_update_implicit_fb(dev_priv, crtc);

    vclips.x = crtc->x;
    vclips.y = crtc->y;
    vclips.w = crtc->mode.hdisplay;
    vclips.h = crtc->mode.vdisplay;
    if (vfb->dmabuf)
        ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, &vclips,
                               1, 1, true, false);
    else
        ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, &vclips,
                                         NULL, 0, 0, 1, 1, NULL);
    if (ret)
        return ret;

    if (event) {
        struct vmw_fence_obj *fence = NULL;
        struct drm_file *file_priv = event->base.file_priv;

        vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
        if (!fence)
            return -ENOMEM;

        ret = vmw_event_fence_action_queue(file_priv, fence,
                                           &event->base,
                                           &event->event.tv_sec,
                                           &event->event.tv_usec,
                                           true);
        vmw_fence_obj_unreference(&fence);
    } else {
        vmw_fifo_flush(dev_priv, false);
    }

    return 0;
}
Beispiel #2
0
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
				  struct drm_framebuffer *fb,
				  struct drm_pending_vblank_event *event,
				  uint32_t flags)
{
	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
	struct drm_framebuffer *old_fb = crtc->primary->fb;
	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
	struct vmw_fence_obj *fence = NULL;
	struct drm_vmw_rect vclips;
	int ret;

	if (!vmw_kms_crtc_flippable(dev_priv, crtc))
		return -EINVAL;

	crtc->primary->fb = fb;

	/* do a full screen dirty update */
	vclips.x = crtc->x;
	vclips.y = crtc->y;
	vclips.w = crtc->mode.hdisplay;
	vclips.h = crtc->mode.vdisplay;

	if (vfb->dmabuf)
		ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb,
						  NULL, &vclips, 1, 1,
						  true, &fence);
	else
		ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb,
						   NULL, &vclips, NULL,
						   0, 0, 1, 1, &fence);


	if (ret != 0)
		goto out_no_fence;
	if (!fence) {
		ret = -EINVAL;
		goto out_no_fence;
	}

	if (event) {
		struct drm_file *file_priv = event->base.file_priv;

		ret = vmw_event_fence_action_queue(file_priv, fence,
						   &event->base,
						   &event->event.tv_sec,
						   &event->event.tv_usec,
						   true);
	}

	/*
	 * No need to hold on to this now. The only cleanup
	 * we need to do if we fail is unref the fence.
	 */
	vmw_fence_obj_unreference(&fence);

	if (vmw_crtc_to_du(crtc)->is_implicit)
		vmw_kms_update_implicit_fb(dev_priv, crtc);

	return ret;

out_no_fence:
	crtc->primary->fb = old_fb;
	return ret;
}
Beispiel #3
0
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
				  struct drm_framebuffer *fb,
				  struct drm_pending_vblank_event *event,
				  uint32_t flags)
{
	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
	struct drm_framebuffer *old_fb = crtc->primary->fb;
	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
	struct vmw_fence_obj *fence = NULL;
	struct drm_clip_rect clips;
	int ret;

	/* require ScreenObject support for page flipping */
	if (!dev_priv->sou_priv)
		return -ENOSYS;

	if (!vmw_sou_screen_object_flippable(dev_priv, crtc))
		return -EINVAL;

	crtc->primary->fb = fb;

	/* do a full screen dirty update */
	clips.x1 = clips.y1 = 0;
	clips.x2 = fb->width;
	clips.y2 = fb->height;

	if (vfb->dmabuf)
		ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb,
						  &clips, 1, 1,
						  true, &fence);
	else
		ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb,
						   &clips, NULL, NULL,
						   0, 0, 1, 1, &fence);


	if (ret != 0)
		goto out_no_fence;
	if (!fence) {
		ret = -EINVAL;
		goto out_no_fence;
	}

	if (event) {
		struct drm_file *file_priv = event->base.file_priv;

		ret = vmw_event_fence_action_queue(file_priv, fence,
						   &event->base,
						   &event->event.tv_sec,
						   &event->event.tv_usec,
						   true);
	}

	/*
	 * No need to hold on to this now. The only cleanup
	 * we need to do if we fail is unref the fence.
	 */
	vmw_fence_obj_unreference(&fence);

	if (vmw_crtc_to_du(crtc)->is_implicit)
		vmw_sou_update_implicit_fb(dev_priv, crtc);

	return ret;

out_no_fence:
	crtc->primary->fb = old_fb;
	return ret;
}
Beispiel #4
0
static void
vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
				    struct drm_plane_state *old_state)
{
	struct drm_crtc *crtc = plane->state->crtc;
	struct drm_pending_vblank_event *event = NULL;
	struct vmw_fence_obj *fence = NULL;
	int ret;

	if (crtc && plane->state->fb) {
		struct vmw_private *dev_priv = vmw_priv(crtc->dev);
		struct vmw_framebuffer *vfb =
			vmw_framebuffer_to_vfb(plane->state->fb);
		struct drm_vmw_rect vclips;

		vclips.x = crtc->x;
		vclips.y = crtc->y;
		vclips.w = crtc->mode.hdisplay;
		vclips.h = crtc->mode.vdisplay;

		if (vfb->bo)
			ret = vmw_kms_sou_do_bo_dirty(dev_priv, vfb, NULL,
						      &vclips, 1, 1, true,
						      &fence, crtc);
		else
			ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb, NULL,
							   &vclips, NULL, 0, 0,
							   1, 1, &fence, crtc);

		/*
		 * We cannot really fail this function, so if we do, then output
		 * an error and maintain consistent atomic state.
		 */
		if (ret != 0)
			DRM_ERROR("Failed to update screen.\n");
	} else {
		/*
		 * When disabling a plane, CRTC and FB should always be NULL
		 * together, otherwise it's an error.
		 * Here primary plane is being disable so should really blank
		 * the screen object display unit, if not already done.
		 */
		return;
	}

	event = crtc->state->event;
	/*
	 * In case of failure and other cases, vblank event will be sent in
	 * vmw_du_crtc_atomic_flush.
	 */
	if (event && fence) {
		struct drm_file *file_priv = event->base.file_priv;

		ret = vmw_event_fence_action_queue(file_priv,
						   fence,
						   &event->base,
						   &event->event.vbl.tv_sec,
						   &event->event.vbl.tv_usec,
						   true);

		if (unlikely(ret != 0))
			DRM_ERROR("Failed to queue event on fence.\n");
		else
			crtc->state->event = NULL;
	}

	if (fence)
		vmw_fence_obj_unreference(&fence);
}
Beispiel #5
0
/**
 * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target
 *
 * @crtc: CRTC to attach FB to
 * @fb: FB to attach
 * @event: Event to be posted. This event should've been alloced
 *         using k[mz]alloc, and should've been completely initialized.
 * @page_flip_flags: Input flags.
 *
 * If the STDU uses the same display and content buffers, i.e. a true flip,
 * this function will replace the existing display buffer with the new content
 * buffer.
 *
 * If the STDU uses different display and content buffers, i.e. a blit, then
 * only the content buffer will be updated.
 *
 * RETURNS:
 * 0 on success, error code on failure
 */
static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
				   struct drm_framebuffer *new_fb,
				   struct drm_pending_vblank_event *event,
				   uint32_t flags)

{
	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
	struct vmw_screen_target_display_unit *stdu;
	int ret;

	if (crtc == NULL)
		return -EINVAL;

	dev_priv          = vmw_priv(crtc->dev);
	stdu              = vmw_crtc_to_stdu(crtc);
	crtc->primary->fb = new_fb;
	stdu->content_fb  = new_fb;

	if (stdu->display_srf) {
		/*
		 * If the display surface is the same as the content surface
		 * then remove the reference
		 */
		if (stdu->content_fb_type == SAME_AS_DISPLAY) {
			if (stdu->defined) {
				/* Unbind the current surface */
				ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
				if (unlikely(ret != 0))
					goto err_out;
			}
			vmw_stdu_unpin_display(stdu);
			stdu->display_srf = NULL;
		}
	}


	if (!new_fb) {
		/* Blanks the display */
		(void) vmw_stdu_update_st(dev_priv, stdu);

		return 0;
	}


	if (stdu->content_fb_type == SAME_AS_DISPLAY) {
		stdu->display_srf = vmw_framebuffer_to_vfbs(new_fb)->surface;
		ret = vmw_stdu_pin_display(stdu);
		if (ret) {
			stdu->display_srf = NULL;
			goto err_out;
		}

		/* Bind display surface */
		ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
		if (unlikely(ret != 0))
			goto err_unpin_display_and_content;
	}

	/* Update display surface: after this point everything is bound */
	ret = vmw_stdu_update_st(dev_priv, stdu);
	if (unlikely(ret != 0))
		return ret;

	if (event) {
		struct vmw_fence_obj *fence = NULL;
		struct drm_file *file_priv = event->base.file_priv;

		vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
		if (!fence)
			return -ENOMEM;

		ret = vmw_event_fence_action_queue(file_priv, fence,
						   &event->base,
						   &event->event.tv_sec,
						   &event->event.tv_usec,
						   true);
		vmw_fence_obj_unreference(&fence);
	}

	return ret;

err_unpin_display_and_content:
	vmw_stdu_unpin_display(stdu);
err_out:
	crtc->primary->fb = NULL;
	stdu->content_fb = NULL;
	return ret;
}
Beispiel #6
0
static void vmw_sync_obj_unref(void **sync_obj)
{
	vmw_fence_obj_unreference((struct vmw_fence_obj **) sync_obj);
}
Beispiel #7
0
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
				  struct drm_framebuffer *new_fb,
				  struct drm_pending_vblank_event *event,
				  uint32_t flags,
				  struct drm_modeset_acquire_ctx *ctx)
{
	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
	struct drm_framebuffer *old_fb = crtc->primary->fb;
	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
	struct vmw_fence_obj *fence = NULL;
	struct drm_vmw_rect vclips;
	int ret;

	if (!vmw_kms_crtc_flippable(dev_priv, crtc))
		return -EINVAL;

	flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
	ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx);
	if (ret) {
		DRM_ERROR("Page flip error %d.\n", ret);
		return ret;
	}

	/* do a full screen dirty update */
	vclips.x = crtc->x;
	vclips.y = crtc->y;
	vclips.w = crtc->mode.hdisplay;
	vclips.h = crtc->mode.vdisplay;

	if (vfb->dmabuf)
		ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb,
						  NULL, &vclips, 1, 1,
						  true, &fence);
	else
		ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb,
						   NULL, &vclips, NULL,
						   0, 0, 1, 1, &fence);


	if (ret != 0)
		goto out_no_fence;
	if (!fence) {
		ret = -EINVAL;
		goto out_no_fence;
	}

	if (event) {
		struct drm_file *file_priv = event->base.file_priv;

		ret = vmw_event_fence_action_queue(file_priv, fence,
						   &event->base,
						   &event->event.tv_sec,
						   &event->event.tv_usec,
						   true);
	}

	/*
	 * No need to hold on to this now. The only cleanup
	 * we need to do if we fail is unref the fence.
	 */
	vmw_fence_obj_unreference(&fence);

	if (vmw_crtc_to_du(crtc)->is_implicit)
		vmw_kms_update_implicit_fb(dev_priv, crtc);

	return ret;

out_no_fence:
	drm_atomic_set_fb_for_plane(crtc->primary->state, old_fb);
	return ret;
}