~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c,v 1.23 2003/02/24 20:34:55 tsi Exp $ */
 
2
/*
 
3
 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
 
4
 *                VA Linux Systems Inc., Fremont, California.
 
5
 *
 
6
 * All Rights Reserved.
 
7
 *
 
8
 * Permission is hereby granted, free of charge, to any person obtaining
 
9
 * a copy of this software and associated documentation files (the
 
10
 * "Software"), to deal in the Software without restriction, including
 
11
 * without limitation on the rights to use, copy, modify, merge,
 
12
 * publish, distribute, sublicense, and/or sell copies of the Software,
 
13
 * and to permit persons to whom the Software is furnished to do so,
 
14
 * subject to the following conditions:
 
15
 *
 
16
 * The above copyright notice and this permission notice (including the
 
17
 * next paragraph) shall be included in all copies or substantial
 
18
 * portions of the Software.
 
19
 *
 
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
21
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
22
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
23
 * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
 
24
 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
25
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
27
 * DEALINGS IN THE SOFTWARE.
 
28
 */
 
29
 
 
30
/*
 
31
 * Authors:
 
32
 *   Kevin E. Martin <martin@xfree86.org>
 
33
 *   Rickard E. Faith <faith@valinux.com>
 
34
 *
 
35
 * References:
 
36
 *
 
37
 * !!!! FIXME !!!!
 
38
 *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
 
39
 *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
 
40
 *   1999.
 
41
 *
 
42
 *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
 
43
 *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
 
44
 *
 
45
 */
 
46
 
 
47
                                /* Driver data structures */
 
48
#include "radeon.h"
 
49
#include "radeon_macros.h"
 
50
#include "radeon_reg.h"
 
51
 
 
52
                                /* X and server generic header files */
 
53
#include "xf86.h"
 
54
 
 
55
/* Mono ARGB cursor colours (premultiplied). */
 
56
static CARD32 mono_cursor_color[] = {
 
57
        0x00000000, /* White, fully transparent. */
 
58
        0x00000000, /* Black, fully transparent. */
 
59
        0xffffffff, /* White, fully opaque. */
 
60
        0xff000000, /* Black, fully opaque. */
 
61
};
 
62
 
 
63
#define CURSOR_WIDTH    64
 
64
#define CURSOR_HEIGHT   64
 
65
 
 
66
/*
 
67
 * The cursor bits are always 32bpp.  On MSBFirst busses,
 
68
 * configure byte swapping to swap 32 bit units when writing
 
69
 * the cursor image.  Byte swapping must always be returned
 
70
 * to its previous value before returning.
 
71
 */
 
72
#if X_BYTE_ORDER == X_BIG_ENDIAN
 
73
 
 
74
#define CURSOR_SWAPPING_DECL_MMIO   unsigned char *RADEONMMIO = info->MMIO;
 
75
#define CURSOR_SWAPPING_DECL        CARD32  __surface_cntl;
 
76
#define CURSOR_SWAPPING_START() \
 
77
    OUTREG(RADEON_SURFACE_CNTL, \
 
78
           ((__surface_cntl = INREG(RADEON_SURFACE_CNTL)) | \
 
79
            RADEON_NONSURF_AP0_SWP_32BPP) & \
 
80
           ~RADEON_NONSURF_AP0_SWP_16BPP)
 
81
#define CURSOR_SWAPPING_END()   (OUTREG(RADEON_SURFACE_CNTL, __surface_cntl))
 
82
 
 
83
#else
 
84
 
 
85
#define CURSOR_SWAPPING_DECL_MMIO
 
86
#define CURSOR_SWAPPING_DECL
 
87
#define CURSOR_SWAPPING_START()
 
88
#define CURSOR_SWAPPING_END()
 
89
 
 
90
#endif
 
91
 
 
92
/* Set cursor foreground and background colors */
 
93
static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
 
94
{
 
95
    RADEONInfoPtr  info       = RADEONPTR(pScrn);
 
96
    CARD32        *pixels     = (CARD32 *)(pointer)(info->FB + info->cursor_start);
 
97
    int            pixel, i;
 
98
    CURSOR_SWAPPING_DECL_MMIO
 
99
    CURSOR_SWAPPING_DECL
 
100
 
 
101
#ifdef ARGB_CURSOR
 
102
    /* Don't recolour cursors set with SetCursorARGB. */
 
103
    if (info->cursor_argb)
 
104
       return;
 
105
#endif
 
106
    
 
107
    fg |= 0xff000000;
 
108
    bg |= 0xff000000;
 
109
    
 
110
    /* Don't recolour the image if we don't have to. */
 
111
    if (fg == info->cursor_fg && bg == info->cursor_bg)
 
112
       return;
 
113
 
 
114
    CURSOR_SWAPPING_START();
 
115
    
 
116
    /* Note: We assume that the pixels are either fully opaque or fully
 
117
     * transparent, so we won't premultiply them, and we can just
 
118
     * check for non-zero pixel values; those are either fg or bg
 
119
     */
 
120
    for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++)
 
121
       if ((pixel = *pixels))
 
122
           *pixels = (pixel == info->cursor_fg) ? fg : bg;
 
123
 
 
124
    CURSOR_SWAPPING_END();
 
125
    info->cursor_fg = fg;
 
126
    info->cursor_bg = bg;
 
127
}
 
128
 
 
129
 
 
130
/* Set cursor position to (x,y) with offset into cursor bitmap at
 
131
 * (xorigin,yorigin)
 
132
 */
 
133
static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
 
134
{
 
135
    RADEONInfoPtr      info       = RADEONPTR(pScrn);
 
136
    unsigned char     *RADEONMMIO = info->MMIO;
 
137
    xf86CursorInfoPtr  cursor     = info->cursor;
 
138
    int                xorigin    = 0;
 
139
    int                yorigin    = 0;
 
140
    int                total_y    = pScrn->frameY1 - pScrn->frameY0;
 
141
    int                X2         = pScrn->frameX0 + x;
 
142
    int                Y2         = pScrn->frameY0 + y;
 
143
    int                stride     = 256;
 
144
 
 
145
    if (x < 0)                        xorigin = -x+1;
 
146
    if (y < 0)                        yorigin = -y+1;
 
147
    if (y > total_y)                  y       = total_y;
 
148
    if (info->Flags & V_DBLSCAN)      y       *= 2;
 
149
    if (xorigin >= cursor->MaxWidth)  xorigin = cursor->MaxWidth - 1;
 
150
    if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
 
151
 
 
152
    if (info->Clone) {
 
153
        int X0 = 0;
 
154
        int Y0 = 0;
 
155
 
 
156
        if ((info->CurCloneMode->VDisplay == pScrn->currentMode->VDisplay) &&
 
157
            (info->CurCloneMode->HDisplay == pScrn->currentMode->HDisplay)) {
 
158
            Y2 = y;
 
159
            X2 = x;
 
160
            X0 = pScrn->frameX0;
 
161
            Y0 = pScrn->frameY0;
 
162
        } else {
 
163
            if (y < 0)
 
164
                Y2 = pScrn->frameY0;
 
165
 
 
166
            if (x < 0)
 
167
                X2 = pScrn->frameX0;
 
168
 
 
169
            if (Y2 >= info->CurCloneMode->VDisplay + info->CloneFrameY0) {
 
170
                Y0 = Y2 - info->CurCloneMode->VDisplay;
 
171
                Y2 = info->CurCloneMode->VDisplay - 1;
 
172
            } else if (Y2 < info->CloneFrameY0) {
 
173
                Y0 = Y2;
 
174
                Y2 = 0;
 
175
            } else {
 
176
                Y2 -= info->CloneFrameY0;
 
177
                Y0 = info->CloneFrameY0;
 
178
            }
 
179
 
 
180
            if (X2 >= info->CurCloneMode->HDisplay + info->CloneFrameX0) {
 
181
                X0 = X2 - info->CurCloneMode->HDisplay;
 
182
                X2 = info->CurCloneMode->HDisplay - 1;
 
183
            } else if (X2 < info->CloneFrameX0) {
 
184
                X0 = X2;
 
185
                X2 = 0;
 
186
            } else {
 
187
                X2 -= info->CloneFrameX0;
 
188
                X0 = info->CloneFrameX0;
 
189
            }
 
190
 
 
191
            if (info->CurCloneMode->Flags & V_DBLSCAN)
 
192
                Y2 *= 2;
 
193
        }
 
194
 
 
195
        if ((X0 >= 0 || Y0 >= 0) &&
 
196
            ((info->CloneFrameX0 != X0) || (info->CloneFrameY0 != Y0))) {
 
197
            RADEONDoAdjustFrame(pScrn, X0, Y0, TRUE);
 
198
            info->CloneFrameX0 = X0;
 
199
            info->CloneFrameY0 = Y0;
 
200
        }
 
201
    }
 
202
 
 
203
    if (!info->IsSecondary) {
 
204
        OUTREG(RADEON_CUR_HORZ_VERT_OFF,  (RADEON_CUR_LOCK
 
205
                                           | (xorigin << 16)
 
206
                                           | yorigin));
 
207
        OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK
 
208
                                           | ((xorigin ? 0 : x) << 16)
 
209
                                           | (yorigin ? 0 : y)));
 
210
        OUTREG(RADEON_CUR_OFFSET, info->cursor_start + yorigin * stride);
 
211
    } else {
 
212
        OUTREG(RADEON_CUR2_HORZ_VERT_OFF,  (RADEON_CUR2_LOCK
 
213
                                            | (xorigin << 16)
 
214
                                            | yorigin));
 
215
        OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK
 
216
                                            | ((xorigin ? 0 : x) << 16)
 
217
                                            | (yorigin ? 0 : y)));
 
218
        OUTREG(RADEON_CUR2_OFFSET,
 
219
               info->cursor_start + pScrn->fbOffset + yorigin * stride);
 
220
    }
 
221
 
 
222
    if (info->Clone) {
 
223
        xorigin = 0;
 
224
        yorigin = 0;
 
225
        if (X2 < 0) xorigin = -X2 + 1;
 
226
        if (Y2 < 0) yorigin = -Y2 + 1;
 
227
        if (xorigin >= cursor->MaxWidth)  xorigin = cursor->MaxWidth - 1;
 
228
        if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
 
229
 
 
230
        OUTREG(RADEON_CUR2_HORZ_VERT_OFF,  (RADEON_CUR2_LOCK
 
231
                                            | (xorigin << 16)
 
232
                                            | yorigin));
 
233
        OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK
 
234
                                            | ((xorigin ? 0 : X2) << 16)
 
235
                                            | (yorigin ? 0 : Y2)));
 
236
        OUTREG(RADEON_CUR2_OFFSET,
 
237
               info->cursor_start + pScrn->fbOffset + yorigin * stride);
 
238
    }
 
239
}
 
240
 
 
241
/* Copy cursor image from `image' to video memory.  RADEONSetCursorPosition
 
242
 * will be called after this, so we can ignore xorigin and yorigin.
 
243
 */
 
244
static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
 
245
{
 
246
    RADEONInfoPtr  info       = RADEONPTR(pScrn);
 
247
    unsigned char *RADEONMMIO = info->MMIO;
 
248
    CARD8         *s          = (CARD8 *)(pointer)image;
 
249
    CARD32        *d          = (CARD32 *)(pointer)(info->FB + info->cursor_start);
 
250
    CARD32         save1      = 0;
 
251
    CARD32         save2      = 0;
 
252
    CARD8          chunk;
 
253
    CARD32         i, j;
 
254
    CURSOR_SWAPPING_DECL
 
255
 
 
256
    if (!info->IsSecondary) {
 
257
        save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
 
258
        save1 |= (CARD32) (2 << 20);
 
259
        OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN);
 
260
    }
 
261
 
 
262
    if (info->IsSecondary || info->Clone) {
 
263
        save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20);
 
264
        save2 |= (CARD32) (2 << 20);
 
265
        OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN);
 
266
    }
 
267
 
 
268
#ifdef ARGB_CURSOR
 
269
    info->cursor_argb = FALSE;
 
270
#endif
 
271
 
 
272
    /*
 
273
     * Convert the bitmap to ARGB32.
 
274
     *
 
275
     * HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 always places
 
276
     * source in the low bit of the pair and mask in the high bit,
 
277
     * and MSBFirst machines set HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
 
278
     * (which actually bit swaps the image) to make the bits LSBFirst
 
279
     */
 
280
    CURSOR_SWAPPING_START();
 
281
#define ARGB_PER_CHUNK  (8 * sizeof (chunk) / 2)
 
282
    for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT / ARGB_PER_CHUNK; i++) {
 
283
        chunk = *s++;
 
284
        for (j = 0; j < ARGB_PER_CHUNK; j++, chunk >>= 2)
 
285
            *d++ = mono_cursor_color[chunk & 3];
 
286
    }
 
287
    CURSOR_SWAPPING_END();
 
288
    
 
289
    info->cursor_bg = mono_cursor_color[2];
 
290
    info->cursor_fg = mono_cursor_color[3];
 
291
 
 
292
    if (!info->IsSecondary)
 
293
        OUTREG(RADEON_CRTC_GEN_CNTL, save1);
 
294
 
 
295
    if (info->IsSecondary || info->Clone)
 
296
        OUTREG(RADEON_CRTC2_GEN_CNTL, save2);
 
297
 
 
298
}
 
299
 
 
300
/* Hide hardware cursor. */
 
301
static void RADEONHideCursor(ScrnInfoPtr pScrn)
 
302
{
 
303
    RADEONInfoPtr  info       = RADEONPTR(pScrn);
 
304
    unsigned char *RADEONMMIO = info->MMIO;
 
305
 
 
306
    if (info->IsSecondary || info->Clone)
 
307
        OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN);
 
308
 
 
309
    if (!info->IsSecondary)
 
310
        OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN);
 
311
}
 
312
 
 
313
/* Show hardware cursor. */
 
314
static void RADEONShowCursor(ScrnInfoPtr pScrn)
 
315
{
 
316
    RADEONInfoPtr  info       = RADEONPTR(pScrn);
 
317
    unsigned char *RADEONMMIO = info->MMIO;
 
318
 
 
319
    if (info->IsSecondary || info->Clone)
 
320
        OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN,
 
321
                ~RADEON_CRTC2_CUR_EN);
 
322
 
 
323
    if (!info->IsSecondary)
 
324
        OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN,
 
325
                ~RADEON_CRTC_CUR_EN);
 
326
}
 
327
 
 
328
/* Determine if hardware cursor is in use. */
 
329
static Bool RADEONUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
 
330
{
 
331
    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
 
332
    RADEONInfoPtr  info  = RADEONPTR(pScrn);
 
333
 
 
334
    return info->cursor_start ? TRUE : FALSE;
 
335
}
 
336
 
 
337
#ifdef ARGB_CURSOR
 
338
#include "cursorstr.h"
 
339
 
 
340
static Bool RADEONUseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs)
 
341
{
 
342
    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
 
343
    RADEONInfoPtr  info  = RADEONPTR(pScrn);
 
344
 
 
345
    if (info->cursor_start &&
 
346
        pCurs->bits->height <= CURSOR_HEIGHT && pCurs->bits->width <= CURSOR_WIDTH)
 
347
        return TRUE;
 
348
    return FALSE;
 
349
}
 
350
 
 
351
static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
 
352
{
 
353
    RADEONInfoPtr  info       = RADEONPTR(pScrn);
 
354
    unsigned char *RADEONMMIO = info->MMIO;
 
355
    CARD32        *d          = (CARD32 *)(pointer)(info->FB + info->cursor_start);
 
356
    int            x, y, w, h;
 
357
    CARD32         save1      = 0;
 
358
    CARD32         save2      = 0;
 
359
    CARD32        *image = pCurs->bits->argb;
 
360
    CARD32        *i;
 
361
    CURSOR_SWAPPING_DECL
 
362
 
 
363
    if (!image)
 
364
        return; /* XXX can't happen */
 
365
    
 
366
    if (!info->IsSecondary) {
 
367
        save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
 
368
        save1 |= (CARD32) (2 << 20);
 
369
        OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN);
 
370
    }
 
371
 
 
372
    if (info->IsSecondary || info->Clone) {
 
373
        save2 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
 
374
        save2 |= (CARD32) (2 << 20);
 
375
        OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN);
 
376
    }
 
377
 
 
378
#ifdef ARGB_CURSOR
 
379
    info->cursor_argb = TRUE;
 
380
#endif
 
381
    
 
382
    CURSOR_SWAPPING_START();
 
383
 
 
384
    w = pCurs->bits->width;
 
385
    if (w > CURSOR_WIDTH)
 
386
        w = CURSOR_WIDTH;
 
387
    h = pCurs->bits->height;
 
388
    if (h > CURSOR_HEIGHT)
 
389
        h = CURSOR_HEIGHT;
 
390
    for (y = 0; y < h; y++)
 
391
    {
 
392
        i = image;
 
393
        image += pCurs->bits->width;
 
394
        for (x = 0; x < w; x++)
 
395
            *d++ = *i++;
 
396
        /* pad to the right with transparent */
 
397
        for (; x < CURSOR_WIDTH; x++)
 
398
            *d++ = 0;
 
399
    }
 
400
    /* pad below with transparent */
 
401
    for (; y < CURSOR_HEIGHT; y++)
 
402
        for (x = 0; x < CURSOR_WIDTH; x++)
 
403
            *d++ = 0;
 
404
 
 
405
    CURSOR_SWAPPING_END ();
 
406
 
 
407
    if (!info->IsSecondary)
 
408
        OUTREG(RADEON_CRTC_GEN_CNTL, save1);
 
409
 
 
410
    if (info->IsSecondary || info->Clone)
 
411
        OUTREG(RADEON_CRTC2_GEN_CNTL, save2);
 
412
 
 
413
}
 
414
 
 
415
#endif
 
416
    
 
417
 
 
418
/* Initialize hardware cursor support. */
 
419
Bool RADEONCursorInit(ScreenPtr pScreen)
 
420
{
 
421
    ScrnInfoPtr        pScrn   = xf86Screens[pScreen->myNum];
 
422
    RADEONInfoPtr      info    = RADEONPTR(pScrn);
 
423
    xf86CursorInfoPtr  cursor;
 
424
    FBAreaPtr          fbarea;
 
425
    int                width;
 
426
    int                width_bytes;
 
427
    int                height;
 
428
    int                size_bytes;
 
429
 
 
430
    if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE;
 
431
 
 
432
    cursor->MaxWidth          = CURSOR_WIDTH;
 
433
    cursor->MaxHeight         = CURSOR_HEIGHT;
 
434
    cursor->Flags             = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
 
435
                                 | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
 
436
#if X_BYTE_ORDER == X_BIG_ENDIAN
 
437
                                 /* this is a lie -- 
 
438
                                  * HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
 
439
                                  * actually inverts the bit order, so
 
440
                                  * this switches to LSBFIRST
 
441
                                  */
 
442
                                 | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
 
443
#endif
 
444
                                 | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1);
 
445
 
 
446
    cursor->SetCursorColors   = RADEONSetCursorColors;
 
447
    cursor->SetCursorPosition = RADEONSetCursorPosition;
 
448
    cursor->LoadCursorImage   = RADEONLoadCursorImage;
 
449
    cursor->HideCursor        = RADEONHideCursor;
 
450
    cursor->ShowCursor        = RADEONShowCursor;
 
451
    cursor->UseHWCursor       = RADEONUseHWCursor;
 
452
 
 
453
#ifdef ARGB_CURSOR
 
454
    cursor->UseHWCursorARGB   = RADEONUseHWCursorARGB;
 
455
    cursor->LoadCursorARGB    = RADEONLoadCursorARGB;
 
456
#endif
 
457
    size_bytes                = CURSOR_WIDTH * 4 * CURSOR_HEIGHT;
 
458
    width                     = pScrn->displayWidth;
 
459
    width_bytes               = width * (pScrn->bitsPerPixel / 8);
 
460
    height                    = (size_bytes + width_bytes - 1) / width_bytes;
 
461
    fbarea                    = xf86AllocateOffscreenArea(pScreen,
 
462
                                                          width,
 
463
                                                          height,
 
464
                                                          256,
 
465
                                                          NULL,
 
466
                                                          NULL,
 
467
                                                          NULL);
 
468
 
 
469
    if (!fbarea) {
 
470
        info->cursor_start    = 0;
 
471
        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 
472
                   "Hardware cursor disabled"
 
473
                   " due to insufficient offscreen memory\n");
 
474
    } else {
 
475
        info->cursor_start    = RADEON_ALIGN((fbarea->box.x1 + 
 
476
                                              fbarea->box.y1 * width) *
 
477
                                             info->CurrentLayout.pixel_bytes,
 
478
                                             256);
 
479
        info->cursor_end      = info->cursor_start + size_bytes;
 
480
    }
 
481
 
 
482
    RADEONTRACE(("RADEONCursorInit (0x%08x-0x%08x)\n",
 
483
                 info->cursor_start, info->cursor_end));
 
484
 
 
485
    return xf86InitCursor(pScreen, cursor);
 
486
}