[Nouveau] [PATCH] kms: Fix <nv11 hardware cursor.
Francisco Jerez
currojerez at riseup.net
Mon Aug 17 11:08:27 PDT 2009
---
src/drmmode_display.c | 29 +++++++++++++++++--
src/nouveau_hw.h | 17 +++++++++++
src/nv_cursor.c | 74 ++++++++++++++++++++++++------------------------
src/nv_proto.h | 2 +
4 files changed, 82 insertions(+), 40 deletions(-)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index f2fe0e8..7acddf1 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -333,7 +333,14 @@ done:
static void
drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
{
+ NVPtr pNv = NVPTR(crtc->scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ struct nouveau_bo *bo = drmmode_crtc->cursor;
+ nouveau_bo_map(bo, NOUVEAU_BO_WR);
+ nv_cursor_convert_cursor(pNv->curImage, bo->map, nv_cursor_width(pNv),
+ 64, 32, fg | (0xff << 24), bg | (0xff << 24));
+ nouveau_bo_unmap(bo);
}
static void
@@ -346,6 +353,24 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
}
static void
+drmmode_load_cursor_image (xf86CrtcPtr crtc, CARD8 *image)
+{
+ NVPtr pNv = NVPTR(crtc->scrn);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ struct nouveau_bo *bo = drmmode_crtc->cursor;
+
+ /* save copy of image for colour changes */
+ memcpy(pNv->curImage, image, nv_cursor_pixels(pNv)/4);
+
+ nouveau_bo_map(bo, NOUVEAU_BO_WR);
+ nv_cursor_convert_cursor(pNv->curImage, bo->map, nv_cursor_width(pNv),
+ 64, 32, config->cursor_fg | (0xff << 24),
+ config->cursor_bg | (0xff << 24));
+ nouveau_bo_unmap(bo);
+}
+
+static void
drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
@@ -505,14 +530,12 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
.set_cursor_position = drmmode_set_cursor_position,
.show_cursor = drmmode_show_cursor,
.hide_cursor = drmmode_hide_cursor,
+ .load_cursor_image = drmmode_load_cursor_image,
.load_cursor_argb = drmmode_load_cursor_argb,
.shadow_create = drmmode_crtc_shadow_create,
.shadow_allocate = drmmode_crtc_shadow_allocate,
.shadow_destroy = drmmode_crtc_shadow_destroy,
.gamma_set = drmmode_gamma_set,
-#if 0
- .set_cursor_colors = drmmode_crtc_set_cursor_colors,
-#endif
.destroy = NULL, /* XXX */
};
diff --git a/src/nouveau_hw.h b/src/nouveau_hw.h
index a548a4c..aa2a3b4 100644
--- a/src/nouveau_hw.h
+++ b/src/nouveau_hw.h
@@ -287,6 +287,23 @@ static inline bool NVLockVgaCrtcs(NVPtr pNv, bool lock)
return waslocked;
}
+/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
+#define NV04_CURSOR_SIZE 32
+/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
+#define NV10_CURSOR_SIZE 64
+
+static inline int nv_cursor_width(NVPtr pNv)
+{
+ return pNv->NVArch >= 0x10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
+}
+
+static inline int nv_cursor_pixels(NVPtr pNv)
+{
+ int width = nv_cursor_width(pNv);
+
+ return width * width;
+}
+
static inline void nv_fix_nv40_hw_cursor(NVPtr pNv, int head)
{
/* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
diff --git a/src/nv_cursor.c b/src/nv_cursor.c
index 22db9e6..b9320c5 100644
--- a/src/nv_cursor.c
+++ b/src/nv_cursor.c
@@ -30,44 +30,43 @@
((c & 0xf8) >> 3 )) /* Blue */
#define TO_ARGB8888(c) (0xff000000 | c)
-/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
-#define NV04_CURSOR_SIZE 32
-#define NV04_CURSOR_PIXELS (NV04_CURSOR_SIZE * NV04_CURSOR_SIZE)
-
-/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
-#define NV10_CURSOR_SIZE 64
-#define NV10_CURSOR_PIXELS (NV10_CURSOR_SIZE * NV10_CURSOR_SIZE)
-
#define SOURCE_MASK_INTERLEAVE 32
#define TRANSPARENT_PIXEL 0
-static void
-nv_cursor_convert_cursor(int px, uint32_t *src, uint16_t *dst, int bpp, uint32_t fg, uint32_t bg)
+void
+nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride, int dst_stride,
+ int bpp, uint32_t fg, uint32_t bg)
{
+ int width = min(src_stride, dst_stride);
uint32_t b, m, pxval;
- int i, j;
+ int i, j, k;
+
+ for (i = 0; i < width; i++) {
+ for (j = 0; j < width / SOURCE_MASK_INTERLEAVE; j++) {
+ int src_off = i*src_stride/SOURCE_MASK_INTERLEAVE + j;
+ int dst_off = i*dst_stride + j*SOURCE_MASK_INTERLEAVE;
+
+ b = src[2*src_off];
+ m = src[2*src_off + 1];
- for (i = 0; i < px / SOURCE_MASK_INTERLEAVE; i++) {
- b = *src++;
- m = *src++;
- for (j = 0; j < SOURCE_MASK_INTERLEAVE; j++) {
- pxval = TRANSPARENT_PIXEL;
+ for (k = 0; k < SOURCE_MASK_INTERLEAVE; k++) {
+ pxval = TRANSPARENT_PIXEL;
#if X_BYTE_ORDER == X_BIG_ENDIAN
- if (m & 0x80000000)
- pxval = (b & 0x80000000) ? fg : bg;
- b <<= 1;
- m <<= 1;
+ if (m & 0x80000000)
+ pxval = (b & 0x80000000) ? fg : bg;
+ b <<= 1;
+ m <<= 1;
#else
- if (m & 1)
- pxval = (b & 1) ? fg : bg;
- b >>= 1;
- m >>= 1;
+ if (m & 1)
+ pxval = (b & 1) ? fg : bg;
+ b >>= 1;
+ m >>= 1;
#endif
- if (bpp == 32) {
- *(uint32_t *)dst = pxval;
- dst += 2;
- } else
- *dst++ = pxval;
+ if (bpp == 32)
+ ((uint32_t *)dst)[dst_off + k] = pxval;
+ else
+ ((uint16_t *)dst)[dst_off + k] = pxval;
+ }
}
}
}
@@ -76,14 +75,16 @@ static void nv_cursor_transform_cursor(NVPtr pNv, struct nouveau_crtc *nv_crtc)
{
uint16_t *tmp;
struct nouveau_bo *cursor = NULL;
- int px = pNv->NVArch >= 0x10 ? NV10_CURSOR_PIXELS : NV04_CURSOR_PIXELS;
+ int px = nv_cursor_pixels(pNv);
+ int width = nv_cursor_width(pNv);
if (!(tmp = xcalloc(px, 4)))
return;
/* convert to colour cursor */
- nv_cursor_convert_cursor(px, pNv->curImage, tmp, pNv->alphaCursor ? 32 : 16,
- nv_crtc->cursor_fg, nv_crtc->cursor_bg);
+ nv_cursor_convert_cursor(pNv->curImage, tmp, width, width,
+ pNv->alphaCursor ? 32 : 16, nv_crtc->cursor_fg,
+ nv_crtc->cursor_bg);
nouveau_bo_ref(nv_crtc->head ? pNv->Cursor2 : pNv->Cursor, &cursor);
nouveau_bo_map(cursor, NOUVEAU_BO_WR);
@@ -126,10 +127,9 @@ void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image)
{
NVPtr pNv = NVPTR(crtc->scrn);
- int sz = (pNv->NVArch >= 0x10 ? NV10_CURSOR_PIXELS : NV04_CURSOR_PIXELS) / 4;
/* save copy of image for colour changes */
- memcpy(pNv->curImage, image, sz);
+ memcpy(pNv->curImage, image, nv_cursor_pixels(pNv) / 4);
nv_cursor_transform_cursor(pNv, to_nouveau_crtc(crtc));
}
@@ -151,7 +151,7 @@ void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
* 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
*/
- for (i = 0; i < NV10_CURSOR_PIXELS; i++) {
+ for (i = 0; i < nv_cursor_pixels(pNv); 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
@@ -202,10 +202,10 @@ void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
Bool NVCursorInitRandr12(ScreenPtr pScreen)
{
NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]);
- int size = pNv->NVArch >= 0x10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
+ int width = nv_cursor_width(pNv);
int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
(pNv->alphaCursor ? HARDWARE_CURSOR_ARGB : 0);
- return xf86_cursors_init(pScreen, size, size, flags);
+ return xf86_cursors_init(pScreen, width, width, flags);
}
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 7c917cc..4a0cbf4 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -48,6 +48,8 @@ void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y);
void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg);
void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image);
void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image);
+void nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride,
+ int dst_stride, int bpp, uint32_t fg, uint32_t bg);
/* in nv_dma.c */
void NVSync(ScrnInfoPtr pScrn);
--
1.6.3.3
More information about the Nouveau
mailing list