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

Commit fee25cb9 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2017-11-02' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

Driver Changes:
- qxl: Use a shadow bo as primary and blit to it to fix flicker (Gerd)

* tag 'drm-misc-fixes-2017-11-02' of git://anongit.freedesktop.org/drm/drm-misc:
  qxl: alloc & use shadow for dumb buffers
  drm/qxl: replace QXL_INFO with DRM_DEBUG_DRIVER
parents e7e62c7e 62676d10
Loading
Loading
Loading
Loading
+12 −10
Original line number Diff line number Diff line
@@ -219,7 +219,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
	union qxl_release_info *info;

	while (qxl_ring_pop(qdev->release_ring, &id)) {
		QXL_INFO(qdev, "popped %lld\n", id);
		DRM_DEBUG_DRIVER("popped %lld\n", id);
		while (id) {
			release = qxl_release_from_id_locked(qdev, id);
			if (release == NULL)
@@ -229,7 +229,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
			next_id = info->next;
			qxl_release_unmap(qdev, release, info);

			QXL_INFO(qdev, "popped %lld, next %lld\n", id,
			DRM_DEBUG_DRIVER("popped %lld, next %lld\n", id,
					 next_id);

			switch (release->type) {
@@ -248,7 +248,7 @@ int qxl_garbage_collect(struct qxl_device *qdev)
		}
	}

	QXL_INFO(qdev, "%s: %d\n", __func__, i);
	DRM_DEBUG_DRIVER("%d\n", i);

	return i;
}
@@ -381,17 +381,19 @@ void qxl_io_create_primary(struct qxl_device *qdev,
{
	struct qxl_surface_create *create;

	QXL_INFO(qdev, "%s: qdev %p, ram_header %p\n", __func__, qdev,
		 qdev->ram_header);
	DRM_DEBUG_DRIVER("qdev %p, ram_header %p\n", qdev, qdev->ram_header);
	create = &qdev->ram_header->create_surface;
	create->format = bo->surf.format;
	create->width = bo->surf.width;
	create->height = bo->surf.height;
	create->stride = bo->surf.stride;
	if (bo->shadow) {
		create->mem = qxl_bo_physical_address(qdev, bo->shadow, offset);
	} else {
		create->mem = qxl_bo_physical_address(qdev, bo, offset);
	}

	QXL_INFO(qdev, "%s: mem = %llx, from %p\n", __func__, create->mem,
		 bo->kptr);
	DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);

	create->flags = QXL_SURF_FLAG_KEEP_DATA;
	create->type = QXL_SURF_TYPE_PRIMARY;
@@ -401,7 +403,7 @@ void qxl_io_create_primary(struct qxl_device *qdev,

void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
{
	QXL_INFO(qdev, "qxl_memslot_add %d\n", id);
	DRM_DEBUG_DRIVER("qxl_memslot_add %d\n", id);
	wait_for_io_cmd(qdev, id, QXL_IO_MEMSLOT_ADD_ASYNC);
}

+46 −3
Original line number Diff line number Diff line
@@ -305,7 +305,9 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
	struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
	struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj);

	WARN_ON(bo->shadow);
	drm_gem_object_unreference_unlocked(qxl_fb->obj);
	drm_framebuffer_cleanup(fb);
	kfree(qxl_fb);
@@ -508,6 +510,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
	    .x2 = qfb->base.width,
	    .y2 = qfb->base.height
	};
	bool same_shadow = false;

	if (old_state->fb) {
		qfb_old = to_qxl_framebuffer(old_state->fb);
@@ -519,15 +522,23 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
	if (bo == bo_old)
		return;

	if (bo_old && bo_old->shadow && bo->shadow &&
	    bo_old->shadow == bo->shadow) {
		same_shadow = true;
	}

	if (bo_old && bo_old->is_primary) {
		if (!same_shadow)
			qxl_io_destroy_primary(qdev);
		bo_old->is_primary = false;
	}

	if (!bo->is_primary) {
		if (!same_shadow)
			qxl_io_create_primary(qdev, 0, bo);
		bo->is_primary = true;
	}

	qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
}

@@ -679,8 +690,9 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
static int qxl_plane_prepare_fb(struct drm_plane *plane,
				struct drm_plane_state *new_state)
{
	struct qxl_device *qdev = plane->dev->dev_private;
	struct drm_gem_object *obj;
	struct qxl_bo *user_bo;
	struct qxl_bo *user_bo, *old_bo = NULL;
	int ret;

	if (!new_state->fb)
@@ -689,6 +701,32 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
	obj = to_qxl_framebuffer(new_state->fb)->obj;
	user_bo = gem_to_qxl_bo(obj);

	if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
	    user_bo->is_dumb && !user_bo->shadow) {
		if (plane->state->fb) {
			obj = to_qxl_framebuffer(plane->state->fb)->obj;
			old_bo = gem_to_qxl_bo(obj);
		}
		if (old_bo && old_bo->shadow &&
		    user_bo->gem_base.size == old_bo->gem_base.size &&
		    plane->state->crtc     == new_state->crtc &&
		    plane->state->crtc_w   == new_state->crtc_w &&
		    plane->state->crtc_h   == new_state->crtc_h &&
		    plane->state->src_x    == new_state->src_x &&
		    plane->state->src_y    == new_state->src_y &&
		    plane->state->src_w    == new_state->src_w &&
		    plane->state->src_h    == new_state->src_h &&
		    plane->state->rotation == new_state->rotation &&
		    plane->state->zpos     == new_state->zpos) {
			drm_gem_object_get(&old_bo->shadow->gem_base);
			user_bo->shadow = old_bo->shadow;
		} else {
			qxl_bo_create(qdev, user_bo->gem_base.size,
				      true, true, QXL_GEM_DOMAIN_VRAM, NULL,
				      &user_bo->shadow);
		}
	}

	ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
	if (ret)
		return ret;
@@ -713,6 +751,11 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
	obj = to_qxl_framebuffer(old_state->fb)->obj;
	user_bo = gem_to_qxl_bo(obj);
	qxl_bo_unpin(user_bo);

	if (user_bo->shadow && !user_bo->is_primary) {
		drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
		user_bo->shadow = NULL;
	}
}

static const uint32_t qxl_cursor_plane_formats[] = {
+3 −25
Original line number Diff line number Diff line
@@ -62,33 +62,9 @@

#define QXL_DEBUGFS_MAX_COMPONENTS		32

extern int qxl_log_level;
extern int qxl_num_crtc;
extern int qxl_max_ioctls;

enum {
	QXL_INFO_LEVEL = 1,
	QXL_DEBUG_LEVEL = 2,
};

#define QXL_INFO(qdev, fmt, ...) do { \
		if (qxl_log_level >= QXL_INFO_LEVEL) {	\
			qxl_io_log(qdev, fmt, __VA_ARGS__); \
		}	\
	} while (0)
#define QXL_DEBUG(qdev, fmt, ...) do { \
		if (qxl_log_level >= QXL_DEBUG_LEVEL) {	\
			qxl_io_log(qdev, fmt, __VA_ARGS__); \
		}	\
	} while (0)
#define QXL_INFO_ONCE(qdev, fmt, ...) do { \
		static int done;		\
		if (!done) {			\
			done = 1;			\
			QXL_INFO(qdev, fmt, __VA_ARGS__);	\
		}						\
	} while (0)

#define DRM_FILE_OFFSET 0x100000000ULL
#define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT)

@@ -113,6 +89,8 @@ struct qxl_bo {
	/* Constant after initialization */
	struct drm_gem_object		gem_base;
	bool is_primary; /* is this now a primary surface */
	bool is_dumb;
	struct qxl_bo *shadow;
	bool hw_surf_alloc;
	struct qxl_surface surf;
	uint32_t surface_id;
@@ -351,7 +329,7 @@ int qxl_check_idle(struct qxl_ring *ring);
static inline void *
qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical)
{
	QXL_INFO(qdev, "not implemented (%lu)\n", physical);
	DRM_DEBUG_DRIVER("not implemented (%lu)\n", physical);
	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
					      &handle);
	if (r)
		return r;
	qobj->is_dumb = true;
	args->pitch = pitch;
	args->handle = handle;
	return 0;
+5 −8
Original line number Diff line number Diff line
@@ -240,18 +240,15 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
		return ret;

	qbo = gem_to_qxl_bo(gobj);
	QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width,
	DRM_DEBUG_DRIVER("%dx%d %d\n", mode_cmd.width,
			 mode_cmd.height, mode_cmd.pitches[0]);

	shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height);
	/* TODO: what's the usual response to memory allocation errors? */
	BUG_ON(!shadow);
	QXL_INFO(qdev,
	"surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
		 qxl_bo_gpu_offset(qbo),
		 qxl_bo_mmap_offset(qbo),
		 qbo->kptr,
		 shadow);
	DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
			 qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo),
			 qbo->kptr, shadow);
	size = mode_cmd.pitches[0] * mode_cmd.height;

	info = drm_fb_helper_alloc_fbi(&qfbdev->helper);
Loading