ThibG from irc reported an issue with transparent cursors, i noticed
the ddx had a workaround, which wasn't in the kms code.

ThibG (whoever you are), please test. The patch is untested.

Maarten.
From 7ce90b3297782e5ecada6e4e917be7a9c316d082 Mon Sep 17 00:00:00 2001
From: Maarten Maathuis <madman2...@gmail.com>
Date: Mon, 20 Jul 2009 21:46:08 +0200
Subject: [PATCH] nv04: import hw workaround for partially transparent pixels from the ddx

- Untested, ThibG from IRC should test this at least.
---
 drivers/gpu/drm/nouveau/nouveau_crtc.h |    3 -
 drivers/gpu/drm/nouveau/nv04_crtc.c    |   90 +++++++++++++++++++++++++++++++-
 drivers/gpu/drm/nouveau/nv50_crtc.c    |    2 +-
 3 files changed, 90 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index d8f18f9..b9b4c8a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -76,9 +76,6 @@ struct nouveau_crtc {
 int nv50_crtc_create(struct drm_device *dev, int index);
 int nv50_cursor_init(struct nouveau_crtc *);
 void nv50_cursor_fini(struct nouveau_crtc *);
-int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv,
-			 uint32_t buffer_handle, uint32_t width,
-			 uint32_t height);
 int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y);
 
 int nv04_cursor_init(struct nouveau_crtc *);
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c
index f27f6fe..02edb5f 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -857,6 +857,94 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
 {
 }
 
+int
+nv04_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv,
+		     uint32_t buffer_handle, uint32_t width, uint32_t height)
+{
+	struct drm_device *dev = drm_crtc->dev;
+	struct nouveau_crtc *crtc = to_nouveau_crtc(drm_crtc);
+	int ret = 0;
+
+	if (width != 64 || height != 64)
+		return -EINVAL;
+
+	if (crtc->cursor.nvbo) {
+		nouveau_bo_unpin(crtc->cursor.nvbo);
+		nouveau_bo_ref(NULL, &crtc->cursor.nvbo);
+	}
+
+	if (buffer_handle) {
+		struct drm_nouveau_private *dev_priv = dev->dev_private;
+		struct drm_gem_object *gem;
+		struct nouveau_bo *nvbo;
+		uint32_t alpha;
+		uint32_t *pixel;
+		int i;
+
+		gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
+		if (!gem)
+			return -EINVAL;
+		nvbo = nouveau_gem_object(gem);
+
+		nouveau_bo_ref(nvbo, &crtc->cursor.nvbo);
+		mutex_lock(&dev->struct_mutex);
+		drm_gem_object_unreference(gem);
+		mutex_unlock(&dev->struct_mutex);
+
+		ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM);
+		if (ret) {
+			nouveau_bo_ref(NULL, &crtc->cursor.nvbo);
+			return ret;
+		}
+
+		ret = nouveau_bo_map(nvbo);
+		if (ret) {
+			nouveau_bo_ref(NULL, &crtc->cursor.nvbo);
+			return ret;
+		}
+
+		/* nv11+ supports premultiplied (PM), or non-premultiplied (NPM) 
+		 * alpha cursors (though NPM in combination with fp dithering 
+		 * may not work on nv11, from "nv" driver history).
+		 * NPM mode needs NV_PCRTC_CURSOR_CONFIG_ALPHA_BLEND 
+		 * set and is what the blob uses, however we get given PM cursors 
+		 * so we use PM mode.
+		 */
+
+		pixel = nvbo->kmap.virtual;
+
+		for (i = 0; i < 64*64; i++) {
+			/* hw gets unhappy if alpha <= rgb values.  for a PM image 
+			 * "less than" shouldn't happen; fix "equal to" case by adding 
+			 * one to alpha channel (slightly inaccurate, but so is 
+			 * attempting to get back to NPM images, due to limits of 
+			 * integer precision).
+			 */
+
+			alpha = pixel[i] >> 24;
+			/* fully transparent and solid colors are fine */
+			if (alpha > 0 && alpha < 255)
+				pixel[i] = ((alpha + 1) << 24) | (pixel[i] & 0xFFFFFF);
+
+#ifdef __BIG_ENDIAN
+			if (dev_priv->chipset == 0x11)
+				pixel[i] = lswapl(pixel[i]);
+#endif
+		}
+
+		nouveau_bo_unmap(nvbo);
+
+		crtc->cursor.offset = nvbo->bo.offset -
+				      dev_priv->vm_vram_base;
+		crtc->cursor.set_offset(crtc, crtc->cursor.offset);
+		crtc->cursor.show(crtc, true);
+	} else {
+		crtc->cursor.hide(crtc, true);
+	}
+
+	return ret;
+}
+
 #define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
 static void
 nv_crtc_gamma_load(struct nouveau_crtc *nv_crtc)
@@ -972,7 +1060,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 static const struct drm_crtc_funcs nv04_crtc_funcs = {
 	.save = nv_crtc_save,
 	.restore = nv_crtc_restore,
-	.cursor_set = nv50_crtc_cursor_set,
+	.cursor_set = nv04_crtc_cursor_set,
 	.cursor_move = nv50_crtc_cursor_move,
 	.gamma_set = nv_crtc_gamma_set,
 	.set_config = drm_crtc_helper_set_config,
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index b1351e4..e6772ac 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -367,7 +367,7 @@ static void nv50_crtc_destroy(struct drm_crtc *drm_crtc)
 	kfree(crtc);
 }
 
-int
+static int
 nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv,
 		     uint32_t buffer_handle, uint32_t width, uint32_t height)
 {
-- 
1.6.3.3

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to