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

« back to all changes in this revision

Viewing changes to exa/exa_accel.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_DIX_CONFIG_H
 
26
#include <dix-config.h>
 
27
#endif
 
28
#include "exa_priv.h"
 
29
#include <X11/fonts/fontstruct.h>
 
30
#include "dixfontstr.h"
 
31
#include "exa.h"
 
32
#include "cw.h"
 
33
 
 
34
static void
 
35
exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
 
36
             DDXPointPtr ppt, int *pwidth, int fSorted)
 
37
{
 
38
    ScreenPtr       pScreen = pDrawable->pScreen;
 
39
    ExaScreenPriv (pScreen);
 
40
    RegionPtr       pClip = fbGetCompositeClip(pGC);
 
41
    PixmapPtr       pPixmap;
 
42
    BoxPtr          pextent, pbox;
 
43
    int             nbox;
 
44
    int             extentX1, extentX2, extentY1, extentY2;
 
45
    int             fullX1, fullX2, fullY1;
 
46
    int             partX1, partX2;
 
47
    int             off_x, off_y;
 
48
    ExaMigrationRec pixmaps[1];
 
49
 
 
50
    pixmaps[0].as_dst = TRUE;
 
51
    pixmaps[0].as_src = FALSE;
 
52
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
53
 
 
54
    if (pExaScr->swappedOut ||
 
55
        pGC->fillStyle != FillSolid ||
 
56
        pDrawable->width > pExaScr->info->maxX ||
 
57
        pDrawable->height > pExaScr->info->maxY)
 
58
    {
 
59
        exaDoMigration (pixmaps, 1, FALSE);
 
60
        ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
 
61
        return;
 
62
    } else {
 
63
        exaDoMigration (pixmaps, 1, TRUE);
 
64
    }
 
65
 
 
66
    if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) ||
 
67
        !(*pExaScr->info->PrepareSolid) (pPixmap,
 
68
                                         pGC->alu,
 
69
                                         pGC->planemask,
 
70
                                         pGC->fgPixel))
 
71
    {
 
72
        ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
 
73
        return;
 
74
    }
 
75
 
 
76
    pextent = REGION_EXTENTS(pGC->pScreen, pClip);
 
77
    extentX1 = pextent->x1;
 
78
    extentY1 = pextent->y1;
 
79
    extentX2 = pextent->x2;
 
80
    extentY2 = pextent->y2;
 
81
    while (n--)
 
82
    {
 
83
        fullX1 = ppt->x;
 
84
        fullY1 = ppt->y;
 
85
        fullX2 = fullX1 + (int) *pwidth;
 
86
        ppt++;
 
87
        pwidth++;
 
88
 
 
89
        if (fullY1 < extentY1 || extentY2 <= fullY1)
 
90
            continue;
 
91
 
 
92
        if (fullX1 < extentX1)
 
93
            fullX1 = extentX1;
 
94
 
 
95
        if (fullX2 > extentX2)
 
96
            fullX2 = extentX2;
 
97
 
 
98
        if (fullX1 >= fullX2)
 
99
            continue;
 
100
 
 
101
        nbox = REGION_NUM_RECTS (pClip);
 
102
        if (nbox == 1)
 
103
        {
 
104
            (*pExaScr->info->Solid) (pPixmap,
 
105
                                     fullX1 + off_x, fullY1 + off_y,
 
106
                                     fullX2 + off_x, fullY1 + 1 + off_y);
 
107
        }
 
108
        else
 
109
        {
 
110
            pbox = REGION_RECTS(pClip);
 
111
            while(nbox--)
 
112
            {
 
113
                if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
 
114
                {
 
115
                    partX1 = pbox->x1;
 
116
                    if (partX1 < fullX1)
 
117
                        partX1 = fullX1;
 
118
                    partX2 = pbox->x2;
 
119
                    if (partX2 > fullX2)
 
120
                        partX2 = fullX2;
 
121
                    if (partX2 > partX1)
 
122
                        (*pExaScr->info->Solid) (pPixmap,
 
123
                                                 partX1 + off_x, fullY1 + off_y,
 
124
                                                 partX2 + off_x, fullY1 + 1 + off_y);
 
125
                }
 
126
                pbox++;
 
127
            }
 
128
        }
 
129
    }
 
130
    (*pExaScr->info->DoneSolid) (pPixmap);
 
131
    exaDrawableDirty (pDrawable);
 
132
    exaMarkSync(pScreen);
 
133
}
 
134
 
 
135
static void
 
136
exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
 
137
             int w, int h, int leftPad, int format, char *bits)
 
138
{
 
139
    ExaScreenPriv (pDrawable->pScreen);
 
140
    PixmapPtr pPix;
 
141
    ExaMigrationRec pixmaps[1];
 
142
    RegionPtr pClip;
 
143
    BoxPtr pbox;
 
144
    int nbox;
 
145
    int xoff, yoff;
 
146
    int src_stride, bpp = pDrawable->bitsPerPixel;
 
147
 
 
148
    if (pExaScr->swappedOut || pExaScr->info->UploadToScreen == NULL)
 
149
        goto migrate_and_fallback;
 
150
 
 
151
    /* Don't bother with under 8bpp, XYPixmaps. */
 
152
    if (format != ZPixmap || bpp < 8)
 
153
        goto migrate_and_fallback;
 
154
 
 
155
    /* Only accelerate copies: no rop or planemask. */
 
156
    if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
 
157
        goto migrate_and_fallback;
 
158
 
 
159
    pixmaps[0].as_dst = TRUE;
 
160
    pixmaps[0].as_src = FALSE;
 
161
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
162
    exaDoMigration (pixmaps, 1, TRUE);
 
163
    pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
 
164
 
 
165
    if (pPix == NULL)
 
166
        goto fallback;
 
167
 
 
168
    x += pDrawable->x;
 
169
    y += pDrawable->y;
 
170
 
 
171
    pClip = fbGetCompositeClip(pGC);
 
172
    src_stride = PixmapBytePad(w, pDrawable->depth);
 
173
    for (nbox = REGION_NUM_RECTS(pClip),
 
174
         pbox = REGION_RECTS(pClip);
 
175
         nbox--;
 
176
         pbox++)
 
177
    {
 
178
        int x1 = x;
 
179
        int y1 = y;
 
180
        int x2 = x + w;
 
181
        int y2 = y + h;
 
182
        char *src;
 
183
        Bool ok;
 
184
 
 
185
        if (x1 < pbox->x1)
 
186
            x1 = pbox->x1;
 
187
        if (y1 < pbox->y1)
 
188
            y1 = pbox->y1;
 
189
        if (x2 > pbox->x2)
 
190
            x2 = pbox->x2;
 
191
        if (y2 > pbox->y2)
 
192
            y2 = pbox->y2;
 
193
        if (x1 >= x2 || y1 >= y2)
 
194
            continue;
 
195
 
 
196
        src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
 
197
        ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
 
198
                                           x2 - x1, y2 - y1, src, src_stride);
 
199
        /* If we fail to accelerate the upload, fall back to using unaccelerated
 
200
         * fb calls.
 
201
         */
 
202
        if (!ok) {
 
203
            FbStip *dst;
 
204
            FbStride dst_stride;
 
205
            int dstBpp;
 
206
            int dstXoff, dstYoff;
 
207
 
 
208
            exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
 
209
 
 
210
            fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
 
211
                              dstXoff, dstYoff);
 
212
 
 
213
            fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
 
214
                      src_stride / sizeof(FbStip),
 
215
                      (x1 - x) * bpp,
 
216
                      dst + (y1 + yoff) * dst_stride,
 
217
                      dst_stride,
 
218
                      (x1 + xoff) * bpp,
 
219
                      (x2 - x1) * bpp,
 
220
                      y2 - y1,
 
221
                      GXcopy, FB_ALLONES, bpp);
 
222
 
 
223
            exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
 
224
        }
 
225
    }
 
226
 
 
227
    return;
 
228
 
 
229
migrate_and_fallback:
 
230
    pixmaps[0].as_dst = TRUE;
 
231
    pixmaps[0].as_src = FALSE;
 
232
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
233
    exaDoMigration (pixmaps, 1, FALSE);
 
234
 
 
235
fallback:
 
236
    ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
 
237
}
 
238
 
 
239
static Bool inline
 
240
exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
 
241
                   GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
 
242
{
 
243
    ExaScreenPriv (pDstDrawable->pScreen);
 
244
    PixmapPtr pSrcPixmap, pDstPixmap;
 
245
    int src_off_x, src_off_y, dst_off_x, dst_off_y;
 
246
    int dirsetup;
 
247
 
 
248
    /* Need to get both pixmaps to call the driver routines */
 
249
    pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y);
 
250
    pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y);
 
251
    if (!pSrcPixmap || !pDstPixmap)
 
252
        return FALSE;
 
253
 
 
254
    /*
 
255
     * Now the case of a chip that only supports xdir = ydir = 1 or
 
256
     * xdir = ydir = -1, but we have xdir != ydir.
 
257
     */
 
258
    dirsetup = 0;       /* No direction set up yet. */
 
259
    for (; nbox; pbox++, nbox--) {
 
260
        if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
 
261
            /* Do a xdir = ydir = -1 blit instead. */
 
262
            if (dirsetup != -1) {
 
263
                if (dirsetup != 0)
 
264
                    pExaScr->info->DoneCopy(pDstPixmap);
 
265
                dirsetup = -1;
 
266
                if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
 
267
                                                   pDstPixmap,
 
268
                                                   -1, -1,
 
269
                                                   pGC ? pGC->alu : GXcopy,
 
270
                                                   pGC ? pGC->planemask :
 
271
                                                         FB_ALLONES))
 
272
                    return FALSE;
 
273
            }
 
274
            (*pExaScr->info->Copy)(pDstPixmap,
 
275
                                   src_off_x + pbox->x1 + dx,
 
276
                                   src_off_y + pbox->y1 + dy,
 
277
                                   dst_off_x + pbox->x1,
 
278
                                   dst_off_y + pbox->y1,
 
279
                                   pbox->x2 - pbox->x1,
 
280
                                   pbox->y2 - pbox->y1);
 
281
        } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
 
282
            /* Do a xdir = ydir = 1 blit instead. */
 
283
            if (dirsetup != 1) {
 
284
                if (dirsetup != 0)
 
285
                    pExaScr->info->DoneCopy(pDstPixmap);
 
286
                dirsetup = 1;
 
287
                if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
 
288
                                                   pDstPixmap,
 
289
                                                   1, 1,
 
290
                                                   pGC ? pGC->alu : GXcopy,
 
291
                                                   pGC ? pGC->planemask :
 
292
                                                         FB_ALLONES))
 
293
                    return FALSE;
 
294
            }
 
295
            (*pExaScr->info->Copy)(pDstPixmap,
 
296
                                   src_off_x + pbox->x1 + dx,
 
297
                                   src_off_y + pbox->y1 + dy,
 
298
                                   dst_off_x + pbox->x1,
 
299
                                   dst_off_y + pbox->y1,
 
300
                                   pbox->x2 - pbox->x1,
 
301
                                   pbox->y2 - pbox->y1);
 
302
        } else if (dx >= 0) {
 
303
            /*
 
304
             * xdir = 1, ydir = -1.
 
305
             * Perform line-by-line xdir = ydir = 1 blits, going up.
 
306
             */
 
307
            int i;
 
308
            if (dirsetup != 1) {
 
309
                if (dirsetup != 0)
 
310
                    pExaScr->info->DoneCopy(pDstPixmap);
 
311
                dirsetup = 1;
 
312
                if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
 
313
                                                   pDstPixmap,
 
314
                                                   1, 1,
 
315
                                                   pGC ? pGC->alu : GXcopy,
 
316
                                                   pGC ? pGC->planemask :
 
317
                                                         FB_ALLONES))
 
318
                    return FALSE;
 
319
            }
 
320
            for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
 
321
                (*pExaScr->info->Copy)(pDstPixmap,
 
322
                                       src_off_x + pbox->x1 + dx,
 
323
                                       src_off_y + pbox->y1 + dy + i,
 
324
                                       dst_off_x + pbox->x1,
 
325
                                       dst_off_y + pbox->y1 + i,
 
326
                                       pbox->x2 - pbox->x1, 1);
 
327
        } else {
 
328
            /*
 
329
             * xdir = -1, ydir = 1.
 
330
             * Perform line-by-line xdir = ydir = -1 blits, going down.
 
331
             */
 
332
            int i;
 
333
            if (dirsetup != -1) {
 
334
                if (dirsetup != 0)
 
335
                    pExaScr->info->DoneCopy(pDstPixmap);
 
336
                dirsetup = -1;
 
337
                if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
 
338
                                                   pDstPixmap,
 
339
                                                   -1, -1,
 
340
                                                   pGC ? pGC->alu : GXcopy,
 
341
                                                   pGC ? pGC->planemask :
 
342
                                                         FB_ALLONES))
 
343
                    return FALSE;
 
344
            }
 
345
            for (i = 0; i < pbox->y2 - pbox->y1; i++)
 
346
                (*pExaScr->info->Copy)(pDstPixmap,
 
347
                                       src_off_x + pbox->x1 + dx,
 
348
                                       src_off_y + pbox->y1 + dy + i,
 
349
                                       dst_off_x + pbox->x1,
 
350
                                       dst_off_y + pbox->y1 + i,
 
351
                                       pbox->x2 - pbox->x1, 1);
 
352
        }
 
353
    }
 
354
    if (dirsetup != 0)
 
355
        pExaScr->info->DoneCopy(pDstPixmap);
 
356
    exaMarkSync(pDstDrawable->pScreen);
 
357
    exaDrawableDirty(pDstDrawable);
 
358
    return TRUE;
 
359
}
 
360
 
 
361
void
 
362
exaCopyNtoN (DrawablePtr    pSrcDrawable,
 
363
             DrawablePtr    pDstDrawable,
 
364
             GCPtr          pGC,
 
365
             BoxPtr         pbox,
 
366
             int            nbox,
 
367
             int            dx,
 
368
             int            dy,
 
369
             Bool           reverse,
 
370
             Bool           upsidedown,
 
371
             Pixel          bitplane,
 
372
             void           *closure)
 
373
{
 
374
    ExaScreenPriv (pDstDrawable->pScreen);
 
375
    PixmapPtr pSrcPixmap, pDstPixmap;
 
376
    int     src_off_x, src_off_y;
 
377
    int     dst_off_x, dst_off_y;
 
378
    ExaMigrationRec pixmaps[2];
 
379
 
 
380
    pixmaps[0].as_dst = TRUE;
 
381
    pixmaps[0].as_src = FALSE;
 
382
    pixmaps[0].pPix = exaGetDrawablePixmap (pDstDrawable);
 
383
    pixmaps[1].as_dst = FALSE;
 
384
    pixmaps[1].as_src = TRUE;
 
385
    pixmaps[1].pPix = exaGetDrawablePixmap (pSrcDrawable);
 
386
 
 
387
    /* Respect maxX/maxY in a trivial way: don't set up drawing when we might
 
388
     * violate the limits.  The proper solution would be a temporary pixmap
 
389
     * adjusted so that the drawing happened within limits.
 
390
     */
 
391
    if (pSrcDrawable->width > pExaScr->info->maxX ||
 
392
        pSrcDrawable->height > pExaScr->info->maxY ||
 
393
        pDstDrawable->width > pExaScr->info->maxX ||
 
394
        pDstDrawable->height > pExaScr->info->maxY)
 
395
    {
 
396
        exaDoMigration (pixmaps, 2, FALSE);
 
397
        goto fallback;
 
398
    } else {
 
399
        exaDoMigration (pixmaps, 2, TRUE);
 
400
    }
 
401
 
 
402
    /* Mixed directions must be handled specially if the card is lame */
 
403
    if (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS && (dx*dy) < 0) {
 
404
        if (!exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
 
405
                               dx, dy))
 
406
            goto fallback;
 
407
        return;
 
408
    }
 
409
 
 
410
    if ((pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y)) &&
 
411
        (pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y)) &&
 
412
        (*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap,
 
413
                                       dx, dy,
 
414
                                       pGC ? pGC->alu : GXcopy,
 
415
                                       pGC ? pGC->planemask : FB_ALLONES))
 
416
    {
 
417
        while (nbox--)
 
418
        {
 
419
            (*pExaScr->info->Copy) (pDstPixmap,
 
420
                                    pbox->x1 + dx + src_off_x,
 
421
                                    pbox->y1 + dy + src_off_y,
 
422
                                    pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
 
423
                                    pbox->x2 - pbox->x1,
 
424
                                    pbox->y2 - pbox->y1);
 
425
            pbox++;
 
426
        }
 
427
        (*pExaScr->info->DoneCopy) (pDstPixmap);
 
428
        exaMarkSync(pDstDrawable->pScreen);
 
429
        exaDrawableDirty (pDstDrawable);
 
430
        return;
 
431
    }
 
432
 
 
433
fallback:
 
434
    EXA_FALLBACK(("from 0x%lx to 0x%lx\n", (long)pSrcDrawable,
 
435
                  (long)pDstDrawable));
 
436
    exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST);
 
437
    exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC);
 
438
    fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC,
 
439
                pbox, nbox, dx, dy, reverse, upsidedown,
 
440
                bitplane, closure);
 
441
    exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
 
442
    exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
 
443
}
 
444
 
 
445
RegionPtr
 
446
exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
 
447
            int srcx, int srcy, int width, int height, int dstx, int dsty)
 
448
{
 
449
    ExaScreenPriv (pDstDrawable->pScreen);
 
450
 
 
451
    if (pExaScr->swappedOut) {
 
452
        return  ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC,
 
453
                                 srcx, srcy, width, height, dstx, dsty);
 
454
    }
 
455
 
 
456
    return  fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
 
457
                      srcx, srcy, width, height,
 
458
                      dstx, dsty, exaCopyNtoN, 0, NULL);
 
459
}
 
460
 
 
461
static void
 
462
exaPolyFillRect(DrawablePtr pDrawable,
 
463
                GCPtr       pGC,
 
464
                int         nrect,
 
465
                xRectangle  *prect)
 
466
{
 
467
    ExaScreenPriv (pDrawable->pScreen);
 
468
    RegionPtr       pClip = fbGetCompositeClip(pGC);
 
469
    PixmapPtr       pPixmap;
 
470
    register BoxPtr pbox;
 
471
    BoxPtr          pextent;
 
472
    int             extentX1, extentX2, extentY1, extentY2;
 
473
    int             fullX1, fullX2, fullY1, fullY2;
 
474
    int             partX1, partX2, partY1, partY2;
 
475
    int             xoff, yoff;
 
476
    int             xorg, yorg;
 
477
    int             n;
 
478
    ExaMigrationRec pixmaps[1];
 
479
 
 
480
    pixmaps[0].as_dst = TRUE;
 
481
    pixmaps[0].as_src = FALSE;
 
482
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
483
 
 
484
    if (pExaScr->swappedOut ||
 
485
        pGC->fillStyle != FillSolid ||
 
486
        pDrawable->width > pExaScr->info->maxX ||
 
487
        pDrawable->height > pExaScr->info->maxY)
 
488
    {
 
489
        exaDoMigration (pixmaps, 1, FALSE);
 
490
        ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
 
491
        return;
 
492
    } else {
 
493
        exaDoMigration (pixmaps, 1, TRUE);
 
494
    }
 
495
 
 
496
    if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
 
497
        !(*pExaScr->info->PrepareSolid) (pPixmap,
 
498
                                         pGC->alu,
 
499
                                         pGC->planemask,
 
500
                                         pGC->fgPixel))
 
501
    {
 
502
        ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
 
503
        return;
 
504
    }
 
505
 
 
506
    xorg = pDrawable->x;
 
507
    yorg = pDrawable->y;
 
508
 
 
509
    pextent = REGION_EXTENTS(pGC->pScreen, pClip);
 
510
    extentX1 = pextent->x1;
 
511
    extentY1 = pextent->y1;
 
512
    extentX2 = pextent->x2;
 
513
    extentY2 = pextent->y2;
 
514
    while (nrect--)
 
515
    {
 
516
        fullX1 = prect->x + xorg;
 
517
        fullY1 = prect->y + yorg;
 
518
        fullX2 = fullX1 + (int) prect->width;
 
519
        fullY2 = fullY1 + (int) prect->height;
 
520
        prect++;
 
521
 
 
522
        if (fullX1 < extentX1)
 
523
            fullX1 = extentX1;
 
524
 
 
525
        if (fullY1 < extentY1)
 
526
            fullY1 = extentY1;
 
527
 
 
528
        if (fullX2 > extentX2)
 
529
            fullX2 = extentX2;
 
530
 
 
531
        if (fullY2 > extentY2)
 
532
            fullY2 = extentY2;
 
533
 
 
534
        if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
 
535
            continue;
 
536
        n = REGION_NUM_RECTS (pClip);
 
537
        if (n == 1)
 
538
        {
 
539
            (*pExaScr->info->Solid) (pPixmap,
 
540
                                     fullX1 + xoff, fullY1 + yoff,
 
541
                                     fullX2 + xoff, fullY2 + yoff);
 
542
        }
 
543
        else
 
544
        {
 
545
            pbox = REGION_RECTS(pClip);
 
546
            /*
 
547
             * clip the rectangle to each box in the clip region
 
548
             * this is logically equivalent to calling Intersect()
 
549
             */
 
550
            while(n--)
 
551
            {
 
552
                partX1 = pbox->x1;
 
553
                if (partX1 < fullX1)
 
554
                    partX1 = fullX1;
 
555
                partY1 = pbox->y1;
 
556
                if (partY1 < fullY1)
 
557
                    partY1 = fullY1;
 
558
                partX2 = pbox->x2;
 
559
                if (partX2 > fullX2)
 
560
                    partX2 = fullX2;
 
561
                partY2 = pbox->y2;
 
562
                if (partY2 > fullY2)
 
563
                    partY2 = fullY2;
 
564
 
 
565
                pbox++;
 
566
 
 
567
                if (partX1 < partX2 && partY1 < partY2)
 
568
                    (*pExaScr->info->Solid) (pPixmap,
 
569
                                             partX1 + xoff, partY1 + yoff,
 
570
                                             partX2 + xoff, partY2 + yoff);
 
571
            }
 
572
        }
 
573
    }
 
574
    (*pExaScr->info->DoneSolid) (pPixmap);
 
575
    exaDrawableDirty (pDrawable);
 
576
    exaMarkSync(pDrawable->pScreen);
 
577
}
 
578
 
 
579
static void
 
580
exaSolidBoxClipped (DrawablePtr pDrawable,
 
581
                    RegionPtr   pClip,
 
582
                    FbBits      pm,
 
583
                    FbBits      fg,
 
584
                    int         x1,
 
585
                    int         y1,
 
586
                    int         x2,
 
587
                    int         y2)
 
588
{
 
589
    ExaScreenPriv (pDrawable->pScreen);
 
590
    PixmapPtr   pPixmap;
 
591
    BoxPtr      pbox;
 
592
    int         nbox;
 
593
    int         xoff, yoff;
 
594
    int         partX1, partX2, partY1, partY2;
 
595
    ExaMigrationRec pixmaps[1];
 
596
 
 
597
    pixmaps[0].as_dst = TRUE;
 
598
    pixmaps[0].as_src = FALSE;
 
599
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
600
 
 
601
    if (pExaScr->swappedOut ||
 
602
        pDrawable->width > pExaScr->info->maxX ||
 
603
        pDrawable->height > pExaScr->info->maxY)
 
604
    {
 
605
        EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable));
 
606
        exaDoMigration (pixmaps, 1, FALSE);
 
607
        goto fallback;
 
608
    } else {
 
609
        exaDoMigration (pixmaps, 1, TRUE);
 
610
    }
 
611
 
 
612
    if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
 
613
        !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg))
 
614
    {
 
615
fallback:
 
616
        EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable));
 
617
        exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
 
618
        fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
 
619
        fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
 
620
                           fbAnd (GXcopy, fg, pm),
 
621
                           fbXor (GXcopy, fg, pm));
 
622
        exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
 
623
        return;
 
624
    }
 
625
    for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
 
626
         nbox--;
 
627
         pbox++)
 
628
    {
 
629
        partX1 = pbox->x1;
 
630
        if (partX1 < x1)
 
631
            partX1 = x1;
 
632
 
 
633
        partX2 = pbox->x2;
 
634
        if (partX2 > x2)
 
635
            partX2 = x2;
 
636
 
 
637
        if (partX2 <= partX1)
 
638
            continue;
 
639
 
 
640
        partY1 = pbox->y1;
 
641
        if (partY1 < y1)
 
642
            partY1 = y1;
 
643
 
 
644
        partY2 = pbox->y2;
 
645
        if (partY2 > y2)
 
646
            partY2 = y2;
 
647
 
 
648
        if (partY2 <= partY1)
 
649
            continue;
 
650
 
 
651
        (*pExaScr->info->Solid) (pPixmap,
 
652
                                 partX1 + xoff, partY1 + yoff,
 
653
                                 partX2 + xoff, partY2 + yoff);
 
654
    }
 
655
    (*pExaScr->info->DoneSolid) (pPixmap);
 
656
    exaDrawableDirty (pDrawable);
 
657
    exaMarkSync(pDrawable->pScreen);
 
658
}
 
659
 
 
660
static void
 
661
exaImageGlyphBlt (DrawablePtr   pDrawable,
 
662
                  GCPtr         pGC,
 
663
                  int           x,
 
664
                  int           y,
 
665
                  unsigned int  nglyph,
 
666
                  CharInfoPtr   *ppciInit,
 
667
                  pointer       pglyphBase)
 
668
{
 
669
    FbGCPrivPtr     pPriv = fbGetGCPrivate(pGC);
 
670
    CharInfoPtr     *ppci;
 
671
    CharInfoPtr     pci;
 
672
    unsigned char   *pglyph;            /* pointer bits in glyph */
 
673
    int             gWidth, gHeight;    /* width and height of glyph */
 
674
    FbStride        gStride;            /* stride of glyph */
 
675
    Bool            opaque;
 
676
    int             n;
 
677
    int             gx, gy;
 
678
    void            (*glyph) (FbBits *,
 
679
                              FbStride,
 
680
                              int,
 
681
                              FbStip *,
 
682
                              FbBits,
 
683
                              int,
 
684
                              int);
 
685
    FbBits          *dst;
 
686
    FbStride        dstStride;
 
687
    int             dstBpp;
 
688
    int             dstXoff, dstYoff;
 
689
    FbBits          depthMask;
 
690
 
 
691
    depthMask = FbFullMask(pDrawable->depth);
 
692
    if ((pGC->planemask & depthMask) != depthMask)
 
693
    {
 
694
        ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
 
695
        return;
 
696
    }
 
697
    glyph = NULL;
 
698
    switch (pDrawable->bitsPerPixel) {
 
699
    case 8:     glyph = fbGlyph8; break;
 
700
    case 16:    glyph = fbGlyph16; break;
 
701
    case 24:    glyph = fbGlyph24; break;
 
702
    case 32:    glyph = fbGlyph32; break;
 
703
    }
 
704
 
 
705
    x += pDrawable->x;
 
706
    y += pDrawable->y;
 
707
 
 
708
    if (TERMINALFONT (pGC->font) && !glyph)
 
709
    {
 
710
        opaque = TRUE;
 
711
    }
 
712
    else
 
713
    {
 
714
        int             xBack, widthBack;
 
715
        int             yBack, heightBack;
 
716
 
 
717
        ppci = ppciInit;
 
718
        n = nglyph;
 
719
        widthBack = 0;
 
720
        while (n--)
 
721
            widthBack += (*ppci++)->metrics.characterWidth;
 
722
 
 
723
        xBack = x;
 
724
        if (widthBack < 0)
 
725
        {
 
726
            xBack += widthBack;
 
727
            widthBack = -widthBack;
 
728
        }
 
729
        yBack = y - FONTASCENT(pGC->font);
 
730
        heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
 
731
        exaSolidBoxClipped (pDrawable,
 
732
                            fbGetCompositeClip(pGC),
 
733
                            pGC->planemask,
 
734
                            pGC->bgPixel,
 
735
                            xBack,
 
736
                            yBack,
 
737
                            xBack + widthBack,
 
738
                            yBack + heightBack);
 
739
        opaque = FALSE;
 
740
    }
 
741
 
 
742
    EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable));
 
743
    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
 
744
    exaPrepareAccessGC (pGC);
 
745
 
 
746
    fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
 
747
 
 
748
    ppci = ppciInit;
 
749
    while (nglyph--)
 
750
    {
 
751
        pci = *ppci++;
 
752
        pglyph = FONTGLYPHBITS(pglyphBase, pci);
 
753
        gWidth = GLYPHWIDTHPIXELS(pci);
 
754
        gHeight = GLYPHHEIGHTPIXELS(pci);
 
755
        if (gWidth && gHeight)
 
756
        {
 
757
            gx = x + pci->metrics.leftSideBearing;
 
758
            gy = y - pci->metrics.ascent;
 
759
            if (glyph && gWidth <= sizeof (FbStip) * 8 &&
 
760
                fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
 
761
            {
 
762
                (*glyph) (dst + (gy + dstYoff) * dstStride,
 
763
                          dstStride,
 
764
                          dstBpp,
 
765
                          (FbStip *) pglyph,
 
766
                          pPriv->fg,
 
767
                          gx + dstXoff,
 
768
                          gHeight);
 
769
            }
 
770
            else
 
771
            {
 
772
                gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
 
773
                fbPutXYImage (pDrawable,
 
774
                              fbGetCompositeClip(pGC),
 
775
                              pPriv->fg,
 
776
                              pPriv->bg,
 
777
                              pPriv->pm,
 
778
                              GXcopy,
 
779
                              opaque,
 
780
 
 
781
                              gx,
 
782
                              gy,
 
783
                              gWidth, gHeight,
 
784
 
 
785
                              (FbStip *) pglyph,
 
786
                              gStride,
 
787
                              0);
 
788
            }
 
789
        }
 
790
        x += pci->metrics.characterWidth;
 
791
    }
 
792
    exaFinishAccessGC (pGC);
 
793
    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
 
794
}
 
795
 
 
796
const GCOps exaOps = {
 
797
    exaFillSpans,
 
798
    ExaCheckSetSpans,
 
799
    exaPutImage,
 
800
    exaCopyArea,
 
801
    ExaCheckCopyPlane,
 
802
    ExaCheckPolyPoint,
 
803
    ExaCheckPolylines,
 
804
    ExaCheckPolySegment,
 
805
    miPolyRectangle,
 
806
    ExaCheckPolyArc,
 
807
    miFillPolygon,
 
808
    exaPolyFillRect,
 
809
    miPolyFillArc,
 
810
    miPolyText8,
 
811
    miPolyText16,
 
812
    miImageText8,
 
813
    miImageText16,
 
814
    exaImageGlyphBlt,
 
815
    ExaCheckPolyGlyphBlt,
 
816
    ExaCheckPushPixels,
 
817
#ifdef NEED_LINEHELPER
 
818
    ,NULL
 
819
#endif
 
820
};
 
821
 
 
822
void
 
823
exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 
824
{
 
825
    RegionRec   rgnDst;
 
826
    int         dx, dy;
 
827
    PixmapPtr   pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
 
828
 
 
829
    dx = ptOldOrg.x - pWin->drawable.x;
 
830
    dy = ptOldOrg.y - pWin->drawable.y;
 
831
    REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
 
832
 
 
833
    REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
 
834
 
 
835
    REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
 
836
#ifdef COMPOSITE
 
837
    if (pPixmap->screen_x || pPixmap->screen_y)
 
838
        REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
 
839
                          -pPixmap->screen_x, -pPixmap->screen_y);
 
840
#endif
 
841
 
 
842
    fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
 
843
                  NULL,
 
844
                  &rgnDst, dx, dy, exaCopyNtoN, 0, NULL);
 
845
 
 
846
    REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
 
847
}
 
848
 
 
849
static void
 
850
exaFillRegionSolid (DrawablePtr pDrawable,
 
851
                    RegionPtr   pRegion,
 
852
                    Pixel       pixel)
 
853
{
 
854
    ExaScreenPriv(pDrawable->pScreen);
 
855
    PixmapPtr pPixmap;
 
856
    int xoff, yoff;
 
857
    ExaMigrationRec pixmaps[1];
 
858
 
 
859
    pixmaps[0].as_dst = TRUE;
 
860
    pixmaps[0].as_src = FALSE;
 
861
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
862
 
 
863
    if (pDrawable->width > pExaScr->info->maxX ||
 
864
        pDrawable->height > pExaScr->info->maxY)
 
865
    {
 
866
        exaDoMigration (pixmaps, 1, FALSE);
 
867
        goto fallback;
 
868
    } else {
 
869
        exaDoMigration (pixmaps, 1, TRUE);
 
870
    }
 
871
 
 
872
    if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
 
873
        (*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel))
 
874
    {
 
875
        int     nbox = REGION_NUM_RECTS (pRegion);
 
876
        BoxPtr  pBox = REGION_RECTS (pRegion);
 
877
 
 
878
        while (nbox--)
 
879
        {
 
880
            (*pExaScr->info->Solid) (pPixmap,
 
881
                                     pBox->x1 + xoff, pBox->y1 + yoff,
 
882
                                     pBox->x2 + xoff, pBox->y2 + yoff);
 
883
            pBox++;
 
884
        }
 
885
        (*pExaScr->info->DoneSolid) (pPixmap);
 
886
        exaMarkSync(pDrawable->pScreen);
 
887
        exaDrawableDirty (pDrawable);
 
888
    }
 
889
    else
 
890
    {
 
891
fallback:
 
892
        EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable));
 
893
        exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
 
894
        fbFillRegionSolid (pDrawable, pRegion, 0,
 
895
                           fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
 
896
        exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
 
897
    }
 
898
}
 
899
 
 
900
/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
 
901
 * Based on fbFillRegionTiled(), fbTile().
 
902
 */
 
903
static void
 
904
exaFillRegionTiled (DrawablePtr pDrawable,
 
905
                    RegionPtr   pRegion,
 
906
                    PixmapPtr   pTile)
 
907
{
 
908
    ExaScreenPriv(pDrawable->pScreen);
 
909
    PixmapPtr pPixmap;
 
910
    int xoff, yoff;
 
911
    int tileWidth, tileHeight;
 
912
    ExaMigrationRec pixmaps[2];
 
913
 
 
914
    tileWidth = pTile->drawable.width;
 
915
    tileHeight = pTile->drawable.height;
 
916
 
 
917
    /* If we're filling with a solid color, grab it out and go to
 
918
     * FillRegionSolid, saving numerous copies.
 
919
     */
 
920
    if (tileWidth == 1 && tileHeight == 1) {
 
921
        exaFillRegionSolid(pDrawable, pRegion, exaGetPixmapFirstPixel (pTile));
 
922
        return;
 
923
    }
 
924
 
 
925
    pixmaps[0].as_dst = TRUE;
 
926
    pixmaps[0].as_src = FALSE;
 
927
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
928
    pixmaps[1].as_dst = FALSE;
 
929
    pixmaps[1].as_src = TRUE;
 
930
    pixmaps[1].pPix = pTile;
 
931
 
 
932
    if (pDrawable->width > pExaScr->info->maxX ||
 
933
        pDrawable->height > pExaScr->info->maxY ||
 
934
        tileWidth > pExaScr->info->maxX ||
 
935
        tileHeight > pExaScr->info->maxY)
 
936
    {
 
937
        exaDoMigration (pixmaps, 2, FALSE);
 
938
        goto fallback;
 
939
    } else {
 
940
        exaDoMigration (pixmaps, 2, TRUE);
 
941
    }
 
942
 
 
943
    pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
 
944
    if (!pPixmap)
 
945
        goto fallback;
 
946
 
 
947
    if (!exaPixmapIsOffscreen(pTile))
 
948
        goto fallback;
 
949
 
 
950
    if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy,
 
951
                                       FB_ALLONES))
 
952
    {
 
953
        int nbox = REGION_NUM_RECTS (pRegion);
 
954
        BoxPtr pBox = REGION_RECTS (pRegion);
 
955
 
 
956
        while (nbox--)
 
957
        {
 
958
            int height = pBox->y2 - pBox->y1;
 
959
            int dstY = pBox->y1;
 
960
            int tileY;
 
961
 
 
962
            tileY = (dstY - pDrawable->y) % tileHeight;
 
963
            while (height > 0) {
 
964
                int width = pBox->x2 - pBox->x1;
 
965
                int dstX = pBox->x1;
 
966
                int tileX;
 
967
                int h = tileHeight - tileY;
 
968
 
 
969
                if (h > height)
 
970
                    h = height;
 
971
                height -= h;
 
972
 
 
973
                tileX = (dstX - pDrawable->x) % tileWidth;
 
974
                while (width > 0) {
 
975
                    int w = tileWidth - tileX;
 
976
                    if (w > width)
 
977
                        w = width;
 
978
                    width -= w;
 
979
 
 
980
                    (*pExaScr->info->Copy) (pPixmap,
 
981
                                            tileX, tileY,
 
982
                                            dstX + xoff, dstY + yoff,
 
983
                                            w, h);
 
984
                    dstX += w;
 
985
                    tileX = 0;
 
986
                }
 
987
                dstY += h;
 
988
                tileY = 0;
 
989
            }
 
990
            pBox++;
 
991
        }
 
992
        (*pExaScr->info->DoneCopy) (pPixmap);
 
993
        exaMarkSync(pDrawable->pScreen);
 
994
        exaDrawableDirty (pDrawable);
 
995
        return;
 
996
    }
 
997
 
 
998
fallback:
 
999
    EXA_FALLBACK(("from 0x%lx to 0x%lx\n", (long)pTile, (long)pDrawable));
 
1000
    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
 
1001
    exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
 
1002
    fbFillRegionTiled (pDrawable, pRegion, pTile);
 
1003
    exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
 
1004
    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
 
1005
}
 
1006
 
 
1007
void
 
1008
exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
 
1009
{
 
1010
    ExaScreenPriv (pWin->drawable.pScreen);
 
1011
    if (!REGION_NUM_RECTS(pRegion))
 
1012
        return;
 
1013
    if (!pExaScr->swappedOut) {
 
1014
        switch (what) {
 
1015
        case PW_BACKGROUND:
 
1016
            switch (pWin->backgroundState) {
 
1017
            case None:
 
1018
                return;
 
1019
            case ParentRelative:
 
1020
                do {
 
1021
                    pWin = pWin->parent;
 
1022
                } while (pWin->backgroundState == ParentRelative);
 
1023
                (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
 
1024
                                                                 what);
 
1025
                return;
 
1026
            case BackgroundPixel:
 
1027
                exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel);
 
1028
                return;
 
1029
            case BackgroundPixmap:
 
1030
                exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap);
 
1031
                return;
 
1032
            }
 
1033
            break;
 
1034
        case PW_BORDER:
 
1035
            if (pWin->borderIsPixel) {
 
1036
                exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel);
 
1037
                return;
 
1038
            } else {
 
1039
                exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap);
 
1040
                return;
 
1041
            }
 
1042
            break;
 
1043
        }
 
1044
    }
 
1045
    ExaCheckPaintWindow (pWin, pRegion, what);
 
1046
}
 
1047
 
 
1048
/**
 
1049
 * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
 
1050
 *
 
1051
 * This is probably the only case we actually care about.  The rest fall through
 
1052
 * to migration and ExaCheckGetImage, which hopefully will result in migration
 
1053
 * pushing the pixmap out of framebuffer.
 
1054
 */
 
1055
void
 
1056
exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
 
1057
             unsigned int format, unsigned long planeMask, char *d)
 
1058
{
 
1059
    ExaScreenPriv (pDrawable->pScreen);
 
1060
    ExaMigrationRec pixmaps[1];
 
1061
    PixmapPtr pPix;
 
1062
    int xoff, yoff;
 
1063
    Bool ok;
 
1064
 
 
1065
    if (pExaScr->swappedOut || pExaScr->info->DownloadFromScreen == NULL)
 
1066
        goto fallback;
 
1067
 
 
1068
    /* Only cover the ZPixmap, solid copy case. */
 
1069
    if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
 
1070
        goto fallback;
 
1071
 
 
1072
    /* Only try to handle the 8bpp and up cases, since we don't want to think
 
1073
     * about <8bpp.
 
1074
     */
 
1075
    if (pDrawable->bitsPerPixel < 8)
 
1076
        goto fallback;
 
1077
 
 
1078
    /* Migrate, but assume that we could accelerate the download. It is up to
 
1079
     * the migration scheme to ensure that this case doesn't result in bad
 
1080
     * moving of pixmaps.
 
1081
     */
 
1082
    pixmaps[0].as_dst = FALSE;
 
1083
    pixmaps[0].as_src = TRUE;
 
1084
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
1085
    exaDoMigration (pixmaps, 1, TRUE);
 
1086
    pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
 
1087
    if (pPix == NULL)
 
1088
        goto fallback;
 
1089
 
 
1090
    xoff += pDrawable->x;
 
1091
    yoff += pDrawable->y;
 
1092
 
 
1093
    ok = pExaScr->info->DownloadFromScreen(pPix, x + xoff, y + yoff, w, h, d,
 
1094
                                           PixmapBytePad(w, pDrawable->depth));
 
1095
    if (ok) {
 
1096
        exaWaitSync(pDrawable->pScreen);
 
1097
        return;
 
1098
    }
 
1099
 
 
1100
fallback:
 
1101
    pixmaps[0].as_dst = FALSE;
 
1102
    pixmaps[0].as_src = TRUE;
 
1103
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
1104
    exaDoMigration (pixmaps, 1, FALSE);
 
1105
 
 
1106
    ExaCheckGetImage (pDrawable, x, y, w, h, format, planeMask, d);
 
1107
}
 
1108
 
 
1109
/**
 
1110
 * GetSpans isn't accelerated yet, but performs migration so that we'll
 
1111
 * hopefully avoid the read-from-framebuffer cost.
 
1112
 */
 
1113
void
 
1114
exaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth,
 
1115
             int nspans, char *pdstStart)
 
1116
{
 
1117
    ExaMigrationRec pixmaps[1];
 
1118
 
 
1119
    pixmaps[0].as_dst = FALSE;
 
1120
    pixmaps[0].as_src = TRUE;
 
1121
    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
 
1122
    exaDoMigration (pixmaps, 1, FALSE);
 
1123
 
 
1124
    ExaCheckGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
 
1125
}