~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

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
}