~ubuntu-branches/ubuntu/edgy/xorg-server/edgy-updates

« back to all changes in this revision

Viewing changes to hw/xfree86/exa/exapict.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Parra Novo
  • Date: 2006-07-25 20:06:28 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060725200628-gjmmd9gxfxdc4ejs
Tags: 1:1.1.1-0ubuntu1
* New Upstream version
* Changed Build-Depends from mesa-swrast-source to mesa-swx11-source,
  following Debian package nomenclature
* Re-did 12_security_policy_in_etc.diff for 1.1.1
* Dropped 15_security_allocate_local.diff (applied upstream)
* Dropped 16_SECURITY_setuid.diff (applied upstream)
* Dropped 000_ubuntu_fix_read_kernel_mapping.patch (applied upstream)
* Dropped 002_ubuntu_fix_for_certain_intel_chipsets.patch (applied upstream)
* Updated versioned Build-Depends on mesa-swx11-source to version
  6.5.0.cvs.20060725-0ubuntu1
* Added arrayobj.c, arrayobj.h, bitset.h & rbadaptors.h to
  GL/symlink-mesa.sh (linked from mesa-swx11-source)
* Added arrayobj.c to default build target on GL/mesa/main

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2001 Keith Packard
3
 
 *
4
 
 * Partly based on code that is Copyright © The XFree86 Project Inc.
5
 
 *
6
 
 * Permission to use, copy, modify, distribute, and sell this software and its
7
 
 * documentation for any purpose is hereby granted without fee, provided that
8
 
 * the above copyright notice appear in all copies and that both that
9
 
 * copyright notice and this permission notice appear in supporting
10
 
 * documentation, and that the name of Keith Packard not be used in
11
 
 * advertising or publicity pertaining to distribution of the software without
12
 
 * specific, written prior permission.  Keith Packard makes no
13
 
 * representations about the suitability of this software for any purpose.  It
14
 
 * is provided "as is" without express or implied warranty.
15
 
 *
16
 
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
 
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
 
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
 
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
 
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
 
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
 
 * PERFORMANCE OF THIS SOFTWARE.
23
 
 */
24
 
 
25
 
#ifdef HAVE_CONFIG_H
26
 
#include <xorg-config.h>
27
 
#endif
28
 
#include "exaPriv.h"
29
 
 
30
 
#ifdef RENDER
31
 
#include "mipict.h"
32
 
 
33
 
#include "xf86str.h"
34
 
#include "xf86.h"
35
 
 
36
 
 
37
 
#if DEBUG_TRACE_FALL
38
 
static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n)
39
 
{
40
 
    char format[20];
41
 
    char size[20];
42
 
    char loc;
43
 
    int temp;
44
 
 
45
 
    if (!pict) {
46
 
        snprintf(string, n, "None");
47
 
        return;
48
 
    }
49
 
 
50
 
    switch (pict->format)
51
 
    {
52
 
    case PICT_a8r8g8b8:
53
 
        snprintf(format, 20, "ARGB8888");
54
 
        break;
55
 
    case PICT_r5g6b5:
56
 
        snprintf(format, 20, "RGB565  ");
57
 
        break;
58
 
    case PICT_x1r5g5b5:
59
 
        snprintf(format, 20, "RGB555  ");
60
 
        break;
61
 
    case PICT_a8:
62
 
        snprintf(format, 20, "A8      ");
63
 
        break;
64
 
    case PICT_a1:
65
 
        snprintf(format, 20, "A1      ");
66
 
        break;
67
 
    default:
68
 
        snprintf(format, 20, "0x%x", (int)pict->format);
69
 
        break;
70
 
    }
71
 
 
72
 
    loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
73
 
 
74
 
    snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
75
 
             pict->pDrawable->height, pict->repeat ?
76
 
             " R" : "");
77
 
 
78
 
    snprintf(string, n, "0x%lx:%c fmt %s (%s)", (long)pict->pDrawable, loc, format, size);
79
 
}
80
 
 
81
 
static void
82
 
exaPrintCompositeFallback(CARD8 op,
83
 
                          PicturePtr pSrc,
84
 
                          PicturePtr pMask,
85
 
                          PicturePtr pDst)
86
 
{
87
 
    char sop[20];
88
 
    char srcdesc[40], maskdesc[40], dstdesc[40];
89
 
 
90
 
    switch(op)
91
 
    {
92
 
    case PictOpSrc:
93
 
        sprintf(sop, "Src");
94
 
        break;
95
 
    case PictOpOver:
96
 
        sprintf(sop, "Over");
97
 
        break;
98
 
    default:
99
 
        sprintf(sop, "0x%x", (int)op);
100
 
        break;
101
 
    }
102
 
 
103
 
    exaCompositeFallbackPictDesc(pSrc, srcdesc, 40);
104
 
    exaCompositeFallbackPictDesc(pMask, maskdesc, 40);
105
 
    exaCompositeFallbackPictDesc(pDst, dstdesc, 40);
106
 
 
107
 
    ErrorF("Composite fallback: op %s, \n"
108
 
           "                    src  %s, \n"
109
 
           "                    mask %s, \n"
110
 
           "                    dst  %s, \n",
111
 
           sop, srcdesc, maskdesc, dstdesc);
112
 
}
113
 
#endif
114
 
 
115
 
static Bool
116
 
exaGetPixelFromRGBA(CARD32      *pixel,
117
 
                    CARD16      red,
118
 
                    CARD16      green,
119
 
                    CARD16      blue,
120
 
                    CARD16      alpha,
121
 
                    CARD32      format)
122
 
{
123
 
    int rbits, bbits, gbits, abits;
124
 
    int rshift, bshift, gshift, ashift;
125
 
 
126
 
    *pixel = 0;
127
 
 
128
 
    if (!PICT_FORMAT_COLOR(format))
129
 
        return FALSE;
130
 
 
131
 
    rbits = PICT_FORMAT_R(format);
132
 
    gbits = PICT_FORMAT_G(format);
133
 
    bbits = PICT_FORMAT_B(format);
134
 
    abits = PICT_FORMAT_A(format);
135
 
 
136
 
    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
137
 
        bshift = 0;
138
 
        gshift = bbits;
139
 
        rshift = gshift + gbits;
140
 
        ashift = rshift + rbits;
141
 
    } else {  /* PICT_TYPE_ABGR */
142
 
        rshift = 0;
143
 
        gshift = rbits;
144
 
        bshift = gshift + gbits;
145
 
        ashift = bshift + bbits;
146
 
    }
147
 
 
148
 
    *pixel |=  ( blue >> (16 - bbits)) << bshift;
149
 
    *pixel |=  (  red >> (16 - rbits)) << rshift;
150
 
    *pixel |=  (green >> (16 - gbits)) << gshift;
151
 
    *pixel |=  (alpha >> (16 - abits)) << ashift;
152
 
 
153
 
    return TRUE;
154
 
}
155
 
 
156
 
 
157
 
static Bool
158
 
exaGetRGBAFromPixel(CARD32      pixel,
159
 
                    CARD16      *red,
160
 
                    CARD16      *green,
161
 
                    CARD16      *blue,
162
 
                    CARD16      *alpha,
163
 
                    CARD32      format)
164
 
{
165
 
    int rbits, bbits, gbits, abits;
166
 
    int rshift, bshift, gshift, ashift;
167
 
 
168
 
    if (!PICT_FORMAT_COLOR(format))
169
 
        return FALSE;
170
 
 
171
 
    rbits = PICT_FORMAT_R(format);
172
 
    gbits = PICT_FORMAT_G(format);
173
 
    bbits = PICT_FORMAT_B(format);
174
 
    abits = PICT_FORMAT_A(format);
175
 
 
176
 
    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
177
 
        bshift = 0;
178
 
        gshift = bbits;
179
 
        rshift = gshift + gbits;
180
 
        ashift = rshift + rbits;
181
 
    } else {  /* PICT_TYPE_ABGR */
182
 
        rshift = 0;
183
 
        gshift = rbits;
184
 
        bshift = gshift + gbits;
185
 
        ashift = bshift + bbits;
186
 
    }
187
 
 
188
 
    *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
189
 
    while (rbits < 16) {
190
 
        *red |= *red >> rbits;
191
 
        rbits <<= 1;
192
 
    }
193
 
 
194
 
    *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
195
 
    while (gbits < 16) {
196
 
        *green |= *green >> gbits;
197
 
        gbits <<= 1;
198
 
    }
199
 
 
200
 
    *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
201
 
    while (bbits < 16) {
202
 
        *blue |= *blue >> bbits;
203
 
        bbits <<= 1;
204
 
    }
205
 
 
206
 
    if (abits) {
207
 
        *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits);
208
 
        while (abits < 16) {
209
 
            *alpha |= *alpha >> abits;
210
 
            abits <<= 1;
211
 
        }
212
 
    } else
213
 
        *alpha = 0xffff;
214
 
 
215
 
    return TRUE;
216
 
}
217
 
 
218
 
static int
219
 
exaTryDriverSolidFill(PicturePtr        pSrc,
220
 
                      PicturePtr        pDst,
221
 
                      INT16             xSrc,
222
 
                      INT16             ySrc,
223
 
                      INT16             xDst,
224
 
                      INT16             yDst,
225
 
                      CARD16            width,
226
 
                      CARD16            height)
227
 
{
228
 
    ExaScreenPriv (pDst->pDrawable->pScreen);
229
 
    RegionRec region;
230
 
    BoxPtr pbox;
231
 
    int nbox;
232
 
    int dst_off_x, dst_off_y;
233
 
    PixmapPtr pSrcPix, pDstPix;
234
 
    CARD32 pixel;
235
 
    CARD16 red, green, blue, alpha;
236
 
 
237
 
    xDst += pDst->pDrawable->x;
238
 
    yDst += pDst->pDrawable->y;
239
 
    xSrc += pSrc->pDrawable->x;
240
 
    ySrc += pSrc->pDrawable->y;
241
 
 
242
 
    if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
243
 
                                   xSrc, ySrc, 0, 0, xDst, yDst,
244
 
                                   width, height))
245
 
        return 1;
246
 
 
247
 
    exaDrawableUseMemory(pSrc->pDrawable);
248
 
    exaDrawableUseScreen(pDst->pDrawable);
249
 
 
250
 
    pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
251
 
    if (!pDstPix) {
252
 
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
253
 
        return 0;
254
 
    }
255
 
 
256
 
    if (pSrc->pDrawable->type == DRAWABLE_WINDOW)
257
 
        pSrcPix = (*pSrc->pDrawable->pScreen->GetWindowPixmap)(
258
 
            (WindowPtr) (pSrc->pDrawable));
259
 
    else
260
 
        pSrcPix = (PixmapPtr) (pSrc->pDrawable);
261
 
 
262
 
 
263
 
    exaPrepareAccess(&pSrcPix->drawable, EXA_PREPARE_SRC);
264
 
    switch (pSrcPix->drawable.bitsPerPixel) {
265
 
    case 32:
266
 
        pixel = *(CARD32 *)(pSrcPix->devPrivate.ptr);
267
 
        break;
268
 
    case 16:
269
 
        pixel = *(CARD16 *)(pSrcPix->devPrivate.ptr);
270
 
        break;
271
 
    default:
272
 
        pixel = *(CARD8 *)(pSrcPix->devPrivate.ptr);
273
 
        break;
274
 
    }
275
 
    if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha,
276
 
                         pSrc->format))
277
 
    {
278
 
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
279
 
        return -1;
280
 
    }
281
 
    exaFinishAccess(&pSrcPix->drawable, EXA_PREPARE_SRC);
282
 
 
283
 
    exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
284
 
                        pDst->format);
285
 
 
286
 
    if (!(*pExaScr->info->accel.PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
287
 
    {
288
 
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
289
 
        return -1;
290
 
    }
291
 
 
292
 
    nbox = REGION_NUM_RECTS(&region);
293
 
    pbox = REGION_RECTS(&region);
294
 
    while (nbox--)
295
 
    {
296
 
        (*pExaScr->info->accel.Solid) (pDstPix,
297
 
                                       pbox->x1 + dst_off_x,
298
 
                                       pbox->y1 + dst_off_y,
299
 
                                       pbox->x2 + dst_off_x,
300
 
                                       pbox->y2 + dst_off_y);
301
 
        pbox++;
302
 
    }
303
 
 
304
 
    (*pExaScr->info->accel.DoneSolid) (pDstPix);
305
 
    exaMarkSync(pDst->pDrawable->pScreen);
306
 
    exaDrawableDirty (pDst->pDrawable);
307
 
 
308
 
    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
309
 
    return 1;
310
 
}
311
 
 
312
 
static int
313
 
exaTryDriverComposite(CARD8             op,
314
 
                      PicturePtr        pSrc,
315
 
                      PicturePtr        pMask,
316
 
                      PicturePtr        pDst,
317
 
                      INT16             xSrc,
318
 
                      INT16             ySrc,
319
 
                      INT16             xMask,
320
 
                      INT16             yMask,
321
 
                      INT16             xDst,
322
 
                      INT16             yDst,
323
 
                      CARD16            width,
324
 
                      CARD16            height)
325
 
{
326
 
    ExaScreenPriv (pDst->pDrawable->pScreen);
327
 
    RegionRec region;
328
 
    BoxPtr pbox;
329
 
    int nbox;
330
 
    int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
331
 
    PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
332
 
    struct _Pixmap scratch;
333
 
 
334
 
    /* Bail if we might exceed coord limits by rendering from/to these.  We
335
 
     * should really be making some scratch pixmaps with offsets and coords
336
 
     * adjusted to deal with this, but it hasn't been done yet.
337
 
     */
338
 
    if (pSrc->pDrawable->width > pExaScr->info->card.maxX ||
339
 
        pSrc->pDrawable->height > pExaScr->info->card.maxY ||
340
 
        pDst->pDrawable->width > pExaScr->info->card.maxX ||
341
 
        pDst->pDrawable->height > pExaScr->info->card.maxY || 
342
 
        (pMask && (pMask->pDrawable->width > pExaScr->info->card.maxX ||
343
 
                   pMask->pDrawable->height > pExaScr->info->card.maxY)))
344
 
    {
345
 
        return -1;
346
 
    }
347
 
 
348
 
    xDst += pDst->pDrawable->x;
349
 
    yDst += pDst->pDrawable->y;
350
 
 
351
 
    if (pMask) {
352
 
        xMask += pMask->pDrawable->x;
353
 
        yMask += pMask->pDrawable->y;
354
 
    }
355
 
 
356
 
    xSrc += pSrc->pDrawable->x;
357
 
    ySrc += pSrc->pDrawable->y;
358
 
 
359
 
    if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
360
 
                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
361
 
                                   width, height))
362
 
        return 1;
363
 
 
364
 
    if (pExaScr->info->accel.CheckComposite &&
365
 
        !(*pExaScr->info->accel.CheckComposite) (op, pSrc, pMask, pDst))
366
 
    {
367
 
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
368
 
        return -1;
369
 
    }
370
 
 
371
 
    exaDrawableUseScreen(pSrc->pDrawable);
372
 
    if (pMask != NULL)
373
 
     exaDrawableUseScreen(pMask->pDrawable);
374
 
    exaDrawableUseScreen(pDst->pDrawable);
375
 
 
376
 
    pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
377
 
    if (pMask)
378
 
        pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x,
379
 
                                          &mask_off_y);
380
 
    pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
381
 
 
382
 
    if (!pDstPix) {
383
 
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
384
 
        return 0;
385
 
    }
386
 
 
387
 
    if (!pSrcPix && (!pMask || pMaskPix) && pExaScr->info->accel.UploadToScratch) {
388
 
        if (pSrc->pDrawable->type == DRAWABLE_WINDOW)
389
 
            pSrcPix = (*pSrc->pDrawable->pScreen->GetWindowPixmap) (
390
 
                (WindowPtr) pSrc->pDrawable);
391
 
        else
392
 
            pSrcPix = (PixmapPtr) pSrc->pDrawable;
393
 
        if ((*pExaScr->info->accel.UploadToScratch) (pSrcPix, &scratch))
394
 
            pSrcPix = &scratch;
395
 
    } else if (pSrcPix && pMask && !pMaskPix && pExaScr->info->accel.UploadToScratch) {
396
 
        if (pMask->pDrawable->type == DRAWABLE_WINDOW)
397
 
            pMaskPix = (*pMask->pDrawable->pScreen->GetWindowPixmap) (
398
 
                (WindowPtr) pMask->pDrawable);
399
 
        else
400
 
            pMaskPix = (PixmapPtr) pMask->pDrawable;
401
 
        if ((*pExaScr->info->accel.UploadToScratch) (pMaskPix, &scratch))
402
 
            pMaskPix = &scratch;
403
 
    }
404
 
 
405
 
    if (!pSrcPix || (pMask && !pMaskPix)) {
406
 
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
407
 
        return 0;
408
 
    }
409
 
 
410
 
    if (!(*pExaScr->info->accel.PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
411
 
                                                   pMaskPix, pDstPix))
412
 
    {
413
 
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
414
 
        return -1;
415
 
    }
416
 
 
417
 
    nbox = REGION_NUM_RECTS(&region);
418
 
    pbox = REGION_RECTS(&region);
419
 
 
420
 
    xMask -= xDst;
421
 
    yMask -= yDst;
422
 
 
423
 
    xSrc -= xDst;
424
 
    ySrc -= yDst;
425
 
 
426
 
    while (nbox--)
427
 
    {
428
 
        (*pExaScr->info->accel.Composite) (pDstPix,
429
 
                                           pbox->x1 + xSrc + src_off_x,
430
 
                                           pbox->y1 + ySrc + src_off_y,
431
 
                                           pbox->x1 + xMask + mask_off_x,
432
 
                                           pbox->y1 + yMask + mask_off_y,
433
 
                                           pbox->x1 + dst_off_x,
434
 
                                           pbox->y1 + dst_off_y,
435
 
                                           pbox->x2 - pbox->x1,
436
 
                                           pbox->y2 - pbox->y1);
437
 
        pbox++;
438
 
    }
439
 
 
440
 
    (*pExaScr->info->accel.DoneComposite) (pDstPix);
441
 
    exaMarkSync(pDst->pDrawable->pScreen);
442
 
    exaDrawableDirty (pDst->pDrawable);
443
 
 
444
 
    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
445
 
    return 1;
446
 
}
447
 
 
448
 
 
449
 
void
450
 
exaComposite(CARD8      op,
451
 
             PicturePtr pSrc,
452
 
             PicturePtr pMask,
453
 
             PicturePtr pDst,
454
 
             INT16      xSrc,
455
 
             INT16      ySrc,
456
 
             INT16      xMask,
457
 
             INT16      yMask,
458
 
             INT16      xDst,
459
 
             INT16      yDst,
460
 
             CARD16     width,
461
 
             CARD16     height)
462
 
{
463
 
    ExaScreenPriv (pDst->pDrawable->pScreen);
464
 
    int ret = -1;
465
 
    ScrnInfoPtr pScrn = XF86SCRNINFO(pDst->pDrawable->pScreen);
466
 
    Bool saveSrcRepeat = pSrc->repeat;
467
 
    Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
468
 
 
469
 
    if (!pScrn->vtSema) {
470
 
        exaDrawableDirty(pDst->pDrawable);
471
 
        pExaScr->SavedComposite(op, pSrc, pMask, pDst, xSrc, ySrc,
472
 
                                xMask, yMask, xDst, yDst, width, height);
473
 
        return;
474
 
    }
475
 
 
476
 
    /* simplify the drivers by reducing here */
477
 
    switch (op) {
478
 
        case PictOpDisjointClear:
479
 
        case PictOpConjointClear:
480
 
            op = PictOpClear;
481
 
            break;    
482
 
        case PictOpDisjointSrc:
483
 
        case PictOpConjointSrc:
484
 
            op = PictOpSrc;
485
 
            break;    
486
 
        case PictOpDisjointDst:
487
 
        case PictOpConjointDst:
488
 
        case PictOpDst:
489
 
            return;    
490
 
        default:
491
 
            break;
492
 
    }
493
 
 
494
 
    /* Remove repeat in source if useless */
495
 
    if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
496
 
        (xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
497
 
        (ySrc + height) <= pSrc->pDrawable->height)
498
 
            pSrc->repeat = 0;
499
 
 
500
 
    if (!pMask && pSrc->pDrawable)
501
 
    {
502
 
        if (op == PictOpSrc)
503
 
        {
504
 
            if (pSrc->pDrawable->width == 1 &&
505
 
                pSrc->pDrawable->height == 1 && pSrc->repeat)
506
 
            {
507
 
                ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
508
 
                                            width, height);
509
 
                if (ret == 1)
510
 
                    goto bail;
511
 
            }
512
 
            else if (!pSrc->repeat && !pSrc->transform &&
513
 
                     pSrc->format == pDst->format)
514
 
            {
515
 
                RegionRec       region;
516
 
 
517
 
                xDst += pDst->pDrawable->x;
518
 
                yDst += pDst->pDrawable->y;
519
 
                xSrc += pSrc->pDrawable->x;
520
 
                ySrc += pSrc->pDrawable->y;
521
 
 
522
 
                if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
523
 
                                               xSrc, ySrc, xMask, yMask, xDst,
524
 
                                               yDst, width, height))
525
 
                    goto bail;
526
 
 
527
 
 
528
 
                exaCopyNtoN (pSrc->pDrawable, pDst->pDrawable, NULL,
529
 
                             REGION_RECTS(&region), REGION_NUM_RECTS(&region),
530
 
                             xSrc - xDst, ySrc - yDst,
531
 
                             FALSE, FALSE, 0, NULL);
532
 
                REGION_UNINIT(pDst->pDrawable->pScreen, &region);
533
 
                goto bail;
534
 
            }
535
 
        }
536
 
    }
537
 
 
538
 
    /* Remove repeat in mask if useless */
539
 
    if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 &&
540
 
        (xMask + width) <= pMask->pDrawable->width && yMask >= 0 &&
541
 
        (yMask + height) <= pMask->pDrawable->height)
542
 
            pMask->repeat = 0;
543
 
 
544
 
 
545
 
    if (pSrc->pDrawable && (!pMask || pMask->pDrawable) &&
546
 
        pExaScr->info->accel.PrepareComposite &&
547
 
        !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
548
 
    {
549
 
        ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
550
 
                                    yMask, xDst, yDst, width, height);
551
 
        if (ret == 1)
552
 
            goto bail;
553
 
    }
554
 
 
555
 
    if (ret != 0) {
556
 
        /* failure to accelerate was not due to pixmaps being in the wrong
557
 
         * locations.
558
 
         */
559
 
      exaDrawableUseMemory(pSrc->pDrawable);
560
 
      if (pMask != NULL)
561
 
        exaDrawableUseMemory(pMask->pDrawable);
562
 
      exaDrawableUseMemory(pDst->pDrawable);
563
 
    }
564
 
 
565
 
#if DEBUG_TRACE_FALL
566
 
    exaPrintCompositeFallback (op, pSrc, pMask, pDst);
567
 
#endif
568
 
 
569
 
    ExaCheckComposite (op, pSrc, pMask, pDst, xSrc, ySrc,
570
 
                      xMask, yMask, xDst, yDst, width, height);
571
 
 
572
 
 bail:
573
 
    pSrc->repeat = saveSrcRepeat;
574
 
    if (pMask)
575
 
        pMask->repeat = saveMaskRepeat;
576
 
}
577
 
#endif
578
 
 
579
 
#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
580
 
 
581
 
/* exaGlyphs is a slight variation on miGlyphs, to support acceleration.  The
582
 
 * issue is that miGlyphs' use of ModifyPixmapHeader makes it impossible to
583
 
 * migrate these pixmaps.  So, instead we create a pixmap at the beginning of
584
 
 * the loop and upload each glyph into the pixmap before compositing.
585
 
 */
586
 
void
587
 
exaGlyphs (CARD8        op,
588
 
          PicturePtr    pSrc,
589
 
          PicturePtr    pDst,
590
 
          PictFormatPtr maskFormat,
591
 
          INT16         xSrc,
592
 
          INT16         ySrc,
593
 
          int           nlist,
594
 
          GlyphListPtr  list,
595
 
          GlyphPtr      *glyphs)
596
 
{
597
 
    ExaScreenPriv (pDst->pDrawable->pScreen);
598
 
    PixmapPtr   pPixmap = NULL, pScratchPixmap = NULL;
599
 
    PicturePtr  pPicture;
600
 
    PixmapPtr   pMaskPixmap = NULL;
601
 
    PicturePtr  pMask;
602
 
    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
603
 
    int         width = 0, height = 0;
604
 
    int         x, y;
605
 
    int         xDst = list->xOff, yDst = list->yOff;
606
 
    int         n;
607
 
    GlyphPtr    glyph;
608
 
    int         error;
609
 
    BoxRec      extents;
610
 
    CARD32      component_alpha;
611
 
 
612
 
    /* If the driver doesn't support accelerated composite, there's no point in
613
 
     * going to this extra work.  Assume that no driver will be able to do
614
 
     * component-alpha, which is likely accurate (at least until we make a CA
615
 
     * helper).
616
 
     */
617
 
    if (!pExaScr->info->accel.PrepareComposite ||
618
 
        (maskFormat && NeedsComponent(maskFormat->format))) {
619
 
        miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
620
 
        return;
621
 
    }
622
 
 
623
 
    if (maskFormat)
624
 
    {
625
 
        GCPtr       pGC;
626
 
        xRectangle  rect;
627
 
        
628
 
        miGlyphExtents (nlist, list, glyphs, &extents);
629
 
        
630
 
        if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
631
 
            return;
632
 
        width = extents.x2 - extents.x1;
633
 
        height = extents.y2 - extents.y1;
634
 
        pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
635
 
                                                maskFormat->depth);
636
 
        if (!pMaskPixmap)
637
 
            return;
638
 
        component_alpha = NeedsComponent(maskFormat->format);
639
 
        pMask = CreatePicture (0, &pMaskPixmap->drawable,
640
 
                               maskFormat, CPComponentAlpha, &component_alpha,
641
 
                               serverClient, &error);
642
 
        if (!pMask)
643
 
        {
644
 
            (*pScreen->DestroyPixmap) (pMaskPixmap);
645
 
            return;
646
 
        }
647
 
        pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
648
 
        ValidateGC (&pMaskPixmap->drawable, pGC);
649
 
        rect.x = 0;
650
 
        rect.y = 0;
651
 
        rect.width = width;
652
 
        rect.height = height;
653
 
        (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
654
 
        FreeScratchGC (pGC);
655
 
        x = -extents.x1;
656
 
        y = -extents.y1;
657
 
    }
658
 
    else
659
 
    {
660
 
        pMask = pDst;
661
 
        x = 0;
662
 
        y = 0;
663
 
    }
664
 
 
665
 
    while (nlist--)
666
 
    {
667
 
        GCPtr pGC;
668
 
        int maxwidth = 0, maxheight = 0, i;
669
 
 
670
 
        x += list->xOff;
671
 
        y += list->yOff;
672
 
        n = list->len;
673
 
        for (i = 0; i < n; i++) {
674
 
            if (glyphs[i]->info.width > maxwidth)
675
 
                maxwidth = glyphs[i]->info.width;
676
 
            if (glyphs[i]->info.height > maxheight)
677
 
                maxheight = glyphs[i]->info.height;
678
 
        }
679
 
        if (maxwidth == 0 || maxheight == 0) {
680
 
            while (n--)
681
 
            {
682
 
                glyph = *glyphs++;
683
 
                x += glyph->info.xOff;
684
 
                y += glyph->info.yOff;
685
 
            }
686
 
            list++;
687
 
            continue;
688
 
        }
689
 
 
690
 
        /* Get a scratch pixmap to wrap the original glyph data */
691
 
        pScratchPixmap = GetScratchPixmapHeader (pScreen, glyphs[0]->info.width,
692
 
                                                 glyphs[0]->info.height, 
693
 
                                                 list->format->depth,
694
 
                                                 list->format->depth, 
695
 
                                                 0, (pointer) (glyphs[0] + 1));
696
 
        if (!pScratchPixmap)
697
 
            return;
698
 
 
699
 
        /* Create the (real) temporary pixmap to store the current glyph in */
700
 
        pPixmap = (*pScreen->CreatePixmap) (pScreen, maxwidth, maxheight,
701
 
                                            list->format->depth);
702
 
        if (!pPixmap) {
703
 
            FreeScratchPixmapHeader (pScratchPixmap);
704
 
            return;
705
 
        }
706
 
 
707
 
        /* Create a temporary picture to wrap the temporary pixmap, so it can be
708
 
         * used as a source for Composite.
709
 
         */
710
 
        component_alpha = NeedsComponent(list->format->format);
711
 
        pPicture = CreatePicture (0, &pPixmap->drawable, list->format,
712
 
                                  CPComponentAlpha, &component_alpha, 
713
 
                                  serverClient, &error);
714
 
        if (!pPicture) {
715
 
            (*pScreen->DestroyPixmap) (pPixmap);
716
 
            FreeScratchPixmapHeader (pScratchPixmap);
717
 
            return;
718
 
        }
719
 
 
720
 
        /* Get a scratch GC with which to copy the glyph data from scratch to
721
 
         * temporary
722
 
         */
723
 
        pGC = GetScratchGC (list->format->depth, pScreen);
724
 
        ValidateGC (&pPixmap->drawable, pGC);
725
 
 
726
 
        /* Give the temporary pixmap an initial kick towards the screen, so
727
 
         * it'll stick there.
728
 
         */
729
 
        exaPixmapUseScreen (pPixmap);
730
 
 
731
 
        while (n--)
732
 
        {
733
 
            glyph = *glyphs++;
734
 
            
735
 
            (*pScreen->ModifyPixmapHeader) (pScratchPixmap, 
736
 
                                            glyph->info.width,
737
 
                                            glyph->info.height,
738
 
                                            0, 0, -1, (pointer) (glyph + 1));
739
 
            pScratchPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
740
 
 
741
 
            /* Copy the glyph data into the proper pixmap instead of a fake.
742
 
             * First we try to use UploadToScreen, if we can, then we fall back
743
 
             * to a plain exaCopyArea in case of failure.
744
 
             */
745
 
            if (!pExaScr->info->accel.UploadToScreen ||
746
 
                !exaPixmapIsOffscreen(pPixmap) ||
747
 
                !(*pExaScr->info->accel.UploadToScreen) (pPixmap, 0, 0,
748
 
                                        glyph->info.width,
749
 
                                        glyph->info.height,
750
 
                                        pScratchPixmap->devPrivate.ptr,
751
 
                                        pScratchPixmap->devKind))
752
 
            {
753
 
                exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC,
754
 
                             0, 0, glyph->info.width, glyph->info.height, 0, 0);
755
 
            } else {
756
 
                exaDrawableDirty (&pPixmap->drawable);
757
 
            }
758
 
 
759
 
            if (maskFormat)
760
 
            {
761
 
                CompositePicture (PictOpAdd,
762
 
                                  pPicture,
763
 
                                  NULL,
764
 
                                  pMask,
765
 
                                  0, 0,
766
 
                                  0, 0,
767
 
                                  x - glyph->info.x,
768
 
                                  y - glyph->info.y,
769
 
                                  glyph->info.width,
770
 
                                  glyph->info.height);
771
 
            }
772
 
            else
773
 
            {
774
 
                CompositePicture (op,
775
 
                                  pSrc,
776
 
                                  pPicture,
777
 
                                  pDst,
778
 
                                  xSrc + (x - glyph->info.x) - xDst,
779
 
                                  ySrc + (y - glyph->info.y) - yDst,
780
 
                                  0, 0,
781
 
                                  x - glyph->info.x,
782
 
                                  y - glyph->info.y,
783
 
                                  glyph->info.width,
784
 
                                  glyph->info.height);
785
 
            }
786
 
            x += glyph->info.xOff;
787
 
            y += glyph->info.yOff;
788
 
        }
789
 
        list++;
790
 
        FreeScratchGC (pGC);
791
 
        FreePicture ((pointer) pPicture, 0);
792
 
        (*pScreen->DestroyPixmap) (pPixmap);
793
 
        FreeScratchPixmapHeader (pScratchPixmap);
794
 
    }
795
 
    if (maskFormat)
796
 
    {
797
 
        x = extents.x1;
798
 
        y = extents.y1;
799
 
        CompositePicture (op,
800
 
                          pSrc,
801
 
                          pMask,
802
 
                          pDst,
803
 
                          xSrc + x - xDst,
804
 
                          ySrc + y - yDst,
805
 
                          0, 0,
806
 
                          x, y,
807
 
                          width, height);
808
 
        FreePicture ((pointer) pMask, (XID) 0);
809
 
        (*pScreen->DestroyPixmap) (pMaskPixmap);
810
 
    }
811
 
}