2
* Copyright 2003 NVIDIA, Corporation
3
* Copyright 2007 Maarten Maathuis
4
* Copyright 2009 Stuart Bennett
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
#include "nv_include.h"
27
#define TO_ARGB1555(c) (0x8000 | /* Mask bit */ \
28
((c & 0xf80000) >> 9 ) | /* Red */ \
29
((c & 0xf800) >> 6 ) | /* Green */ \
30
((c & 0xf8) >> 3 )) /* Blue */
31
#define TO_ARGB8888(c) (0xff000000 | c)
33
#define SOURCE_MASK_INTERLEAVE 32
34
#define TRANSPARENT_PIXEL 0
37
* Convert a source/mask bitmap cursor to an ARGB cursor, clipping or
38
* padding as necessary. source/mask are assumed to be alternated each
39
* SOURCE_MASK_INTERLEAVE bits.
42
nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride, int dst_stride,
43
int bpp, uint32_t fg, uint32_t bg)
45
int width = min(src_stride, dst_stride);
49
for (i = 0; i < width; i++) {
50
for (j = 0; j < width / SOURCE_MASK_INTERLEAVE; j++) {
51
int src_off = i*src_stride/SOURCE_MASK_INTERLEAVE + j;
52
int dst_off = i*dst_stride + j*SOURCE_MASK_INTERLEAVE;
55
m = src[2*src_off + 1];
57
for (k = 0; k < SOURCE_MASK_INTERLEAVE; k++) {
58
pxval = TRANSPARENT_PIXEL;
59
#if X_BYTE_ORDER == X_BIG_ENDIAN
61
pxval = (b & 0x80000000) ? fg : bg;
66
pxval = (b & 1) ? fg : bg;
71
((uint32_t *)dst)[dst_off + k] = pxval;
73
((uint16_t *)dst)[dst_off + k] = pxval;
79
static void nv_cursor_transform_cursor(NVPtr pNv, struct nouveau_crtc *nv_crtc)
82
struct nouveau_bo *cursor = NULL;
83
int px = nv_cursor_pixels(pNv);
84
int width = nv_cursor_width(pNv);
86
if (!(tmp = xcalloc(px, 4)))
89
/* convert to colour cursor */
90
nv_cursor_convert_cursor(pNv->curImage, tmp, width, width,
91
pNv->alphaCursor ? 32 : 16, nv_crtc->cursor_fg,
94
nouveau_bo_ref(nv_crtc->head ? pNv->Cursor2 : pNv->Cursor, &cursor);
95
nouveau_bo_map(cursor, NOUVEAU_BO_WR);
97
memcpy(cursor->map, tmp, px * 4);
99
nouveau_bo_unmap(cursor);
100
nouveau_bo_ref(NULL, &cursor);
105
void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
107
NVPtr pNv = NVPTR(crtc->scrn);
108
struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
111
if (pNv->alphaCursor) {
112
fore = TO_ARGB8888(fg);
113
back = TO_ARGB8888(bg);
114
#if X_BYTE_ORDER == X_BIG_ENDIAN
115
if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
121
fore = TO_ARGB1555(fg);
122
back = TO_ARGB1555(bg);
125
if (nv_crtc->cursor_fg != fore || nv_crtc->cursor_bg != back) {
126
nv_crtc->cursor_fg = fore;
127
nv_crtc->cursor_bg = back;
128
nv_cursor_transform_cursor(pNv, nv_crtc);
132
void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image)
134
NVPtr pNv = NVPTR(crtc->scrn);
136
/* save copy of image for colour changes */
137
memcpy(pNv->curImage, image, nv_cursor_pixels(pNv) / 4);
139
nv_cursor_transform_cursor(pNv, to_nouveau_crtc(crtc));
142
void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
144
NVPtr pNv = NVPTR(crtc->scrn);
145
int head = to_nouveau_crtc(crtc)->head, i, alpha;
146
struct nouveau_bo *cursor = NULL;
147
uint32_t *dst, *src = (uint32_t *)image, tmp;
149
nouveau_bo_ref(head ? pNv->Cursor2 : pNv->Cursor, &cursor);
150
nouveau_bo_map(cursor, NOUVEAU_BO_WR);
153
/* nv11+ supports premultiplied (PM), or non-premultiplied (NPM) alpha
154
* cursors (though NPM in combination with fp dithering may not work on
155
* nv11, from "nv" driver history)
156
* NPM mode needs NV_PCRTC_CURSOR_CONFIG_ALPHA_BLEND set and is what the
157
* blob uses, however we get given PM cursors so we use PM mode
159
for (i = 0; i < nv_cursor_pixels(pNv); i++) {
160
/* hw gets unhappy if alpha <= rgb values. for a PM image "less
161
* than" shouldn't happen; fix "equal to" case by adding one to
162
* alpha channel (slightly inaccurate, but so is attempting to
163
* get back to NPM images, due to limits of integer precision)
165
alpha = (*src >> 24);
166
if (!alpha || alpha == 0xff)
167
/* alpha == max(r,g,b) works ok for 0x0 and 0xff */
170
tmp = ((alpha + 1) << 24) | (*src & 0xffffff);
171
#if X_BYTE_ORDER == X_BIG_ENDIAN
172
if (pNv->NVArch == 0x11)
179
nouveau_bo_unmap(cursor);
180
nouveau_bo_ref(NULL, &cursor);
183
void nv_crtc_show_cursor(xf86CrtcPtr crtc)
185
struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
187
nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, true);
190
void nv_crtc_hide_cursor(xf86CrtcPtr crtc)
192
struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
194
nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, false);
197
void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
199
struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
200
NVPtr pNv = NVPTR(crtc->scrn);
202
NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_CU_START_POS,
203
XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
204
XLATE(x, 0, NV_PRAMDAC_CU_START_POS_X));
207
Bool NVCursorInitRandr12(ScreenPtr pScreen)
209
NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]);
210
int width = nv_cursor_width(pNv);
211
int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
212
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
213
(pNv->alphaCursor ? HARDWARE_CURSOR_ARGB : 0);
215
return xf86_cursors_init(pScreen, width, width, flags);