Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 058e9f5c authored by Andreas Pokorny's avatar Andreas Pokorny Committed by Dave Airlie
Browse files

drm/qxl: simple crtc page flipping emulated using buffer copy

parent 6ba59f3b
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -187,6 +187,54 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc)
	kfree(qxl_crtc);
}

static int qxl_crtc_page_flip(struct drm_crtc *crtc,
                              struct drm_framebuffer *fb,
                              struct drm_pending_vblank_event *event,
                              uint32_t page_flip_flags)
{
	struct drm_device *dev = crtc->dev;
	struct qxl_device *qdev = dev->dev_private;
	struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
	struct qxl_framebuffer *qfb_src = to_qxl_framebuffer(fb);
	struct qxl_framebuffer *qfb_old = to_qxl_framebuffer(crtc->primary->fb);
	struct qxl_bo *bo_old = gem_to_qxl_bo(qfb_old->obj);
	struct qxl_bo *bo = gem_to_qxl_bo(qfb_src->obj);
	unsigned long flags;
	struct drm_clip_rect norect = {
	    .x1 = 0,
	    .y1 = 0,
	    .x2 = fb->width,
	    .y2 = fb->height
	};
	int inc = 1;
	int one_clip_rect = 1;
	int ret = 0;

	crtc->primary->fb = fb;
	bo_old->is_primary = false;
	bo->is_primary = true;

	ret = qxl_bo_reserve(bo, false);
	if (ret)
		return ret;

	qxl_draw_dirty_fb(qdev, qfb_src, bo, 0, 0,
			  &norect, one_clip_rect, inc);

	drm_vblank_get(dev, qcrtc->index);

	if (event) {
		spin_lock_irqsave(&dev->event_lock, flags);
		drm_send_vblank_event(dev, qcrtc->index, event);
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}
	drm_vblank_put(dev, qcrtc->index);

	qxl_bo_unreserve(bo);

	return 0;
}

static int
qxl_hide_cursor(struct qxl_device *qdev)
{
@@ -374,6 +422,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
	.cursor_move = qxl_crtc_cursor_move,
	.set_config = drm_crtc_helper_set_config,
	.destroy = qxl_crtc_destroy,
	.page_flip = qxl_crtc_page_flip,
};

static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
+18 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ static const struct file_operations qxl_fops = {
	.release = drm_release,
	.unlocked_ioctl = drm_ioctl,
	.poll = drm_poll,
	.read = drm_read,
	.mmap = qxl_mmap,
};

@@ -195,6 +196,20 @@ static int qxl_pm_restore(struct device *dev)
	return qxl_drm_resume(drm_dev, false);
}

static u32 qxl_noop_get_vblank_counter(struct drm_device *dev, int crtc)
{
	return dev->vblank[crtc].count.counter;
}

static int qxl_noop_enable_vblank(struct drm_device *dev, int crtc)
{
	return 0;
}

static void qxl_noop_disable_vblank(struct drm_device *dev, int crtc)
{
}

static const struct dev_pm_ops qxl_pm_ops = {
	.suspend = qxl_pm_suspend,
	.resume = qxl_pm_resume,
@@ -216,6 +231,9 @@ static struct drm_driver qxl_driver = {
			   DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
	.load = qxl_driver_load,
	.unload = qxl_driver_unload,
	.get_vblank_counter = qxl_noop_get_vblank_counter,
	.enable_vblank = qxl_noop_enable_vblank,
	.disable_vblank = qxl_noop_disable_vblank,

	.dumb_create = qxl_mode_dumb_create,
	.dumb_map_offset = qxl_mode_dumb_mmap,
+12 −4
Original line number Diff line number Diff line
@@ -298,6 +298,9 @@ int qxl_driver_unload(struct drm_device *dev)

	if (qdev == NULL)
		return 0;

	drm_vblank_cleanup(dev);

	qxl_modeset_fini(qdev);
	qxl_device_fini(qdev);

@@ -325,15 +328,20 @@ int qxl_driver_load(struct drm_device *dev, unsigned long flags)
	if (r)
		goto out;

	r = drm_vblank_init(dev, 1);
	if (r)
		goto unload;

	r = qxl_modeset_init(qdev);
	if (r) {
		qxl_driver_unload(dev);
		goto out;
	}
	if (r)
		goto unload;

	drm_kms_helper_poll_init(qdev->ddev);

	return 0;
unload:
	qxl_driver_unload(dev);

out:
	kfree(qdev);
	return r;