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

« back to all changes in this revision

Viewing changes to afb/afbbitblt.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
/* $XFree86: xc/programs/Xserver/afb/afbbitblt.c,v 3.5tsi Exp $ */
 
2
/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */
 
3
/***********************************************************
 
4
 
 
5
Copyright (c) 1987  X Consortium
 
6
 
 
7
Permission is hereby granted, free of charge, to any person obtaining a copy
 
8
of this software and associated documentation files (the "Software"), to deal
 
9
in the Software without restriction, including without limitation the rights
 
10
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
11
copies of the Software, and to permit persons to whom the Software is
 
12
furnished to do so, subject to the following conditions:
 
13
 
 
14
The above copyright notice and this permission notice shall be included in
 
15
all copies or substantial portions of the Software.
 
16
 
 
17
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
18
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
19
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
20
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
21
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
22
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
Except as contained in this notice, the name of the X Consortium shall not be
 
25
used in advertising or otherwise to promote the sale, use or other dealings
 
26
in this Software without prior written authorization from the X Consortium.
 
27
 
 
28
 
 
29
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
30
 
 
31
                        All Rights Reserved
 
32
 
 
33
Permission to use, copy, modify, and distribute this software and its
 
34
documentation for any purpose and without fee is hereby granted,
 
35
provided that the above copyright notice appear in all copies and that
 
36
both that copyright notice and this permission notice appear in
 
37
supporting documentation, and that the name of Digital not be
 
38
used in advertising or publicity pertaining to distribution of the
 
39
software without specific, written prior permission.
 
40
 
 
41
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
42
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
43
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
44
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
45
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
46
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
47
SOFTWARE.
 
48
 
 
49
******************************************************************/
 
50
/* $XConsortium: afbbitblt.c,v 5.25 94/04/17 20:28:16 dpw Exp $ */
 
51
 
 
52
#ifdef HAVE_DIX_CONFIG_H
 
53
#include <dix-config.h>
 
54
#endif
 
55
 
 
56
#include <X11/X.h>
 
57
#include <X11/Xprotostr.h>
 
58
 
 
59
#include "regionstr.h"
 
60
#include "gcstruct.h"
 
61
#include "windowstr.h"
 
62
#include "pixmapstr.h"
 
63
#include "scrnintstr.h"
 
64
 
 
65
#include "mi.h"
 
66
 
 
67
#include "afb.h"
 
68
#include "maskbits.h"
 
69
 
 
70
 
 
71
static unsigned char afbRropsOS[AFB_MAX_DEPTH];
 
72
 
 
73
/* CopyArea and CopyPlane for a monchrome frame buffer
 
74
 
 
75
 
 
76
        clip the source rectangle to the source's available bits.  (this
 
77
avoids copying unnecessary pieces that will just get exposed anyway.)
 
78
this becomes the new shape of the destination.
 
79
        clip the destination region to the composite clip in the
 
80
GC.  this requires translating the destination region to (dstx, dsty).
 
81
        build a list of source points, one for each rectangle in the
 
82
destination.  this is a simple translation.
 
83
        go do the multiple rectangle copies
 
84
        do graphics exposures
 
85
*/
 
86
/** Optimized for drawing pixmaps into windows, especially when drawing into
 
87
 ** unobscured windows.  Calls to the general-purpose region code were
 
88
 ** replaced with rectangle-to-rectangle clipping comparisions.  This is
 
89
 ** possible, since the pixmap is a single rectangle.  In an unobscured
 
90
 ** window, the destination clip is also a single rectangle, and region
 
91
 ** code can be avoided entirely.  This is a big savings, since the region
 
92
 ** code uses XAlloc() and makes many function calls.
 
93
 **
 
94
 ** In addition, if source is a pixmap, there is no need to call the
 
95
 ** expensive miHandleExposures() routine.  Instead, we simply return NULL.
 
96
 **
 
97
 ** Previously, drawing a pixmap into an unobscured window executed at least
 
98
 ** 8 XAlloc()'s, 30 function calls, and hundreds of lines of code.
 
99
 **
 
100
 ** Now, the same operation requires no XAlloc()'s, no region function calls,
 
101
 ** and much less overhead.  Nice for drawing lots of small pixmaps.
 
102
 */
 
103
 
 
104
void
 
105
afbDoBitblt(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
 
106
        DrawablePtr pSrc, pDst;
 
107
        int alu;
 
108
        RegionPtr prgnDst;
 
109
        DDXPointPtr pptSrc;
 
110
        unsigned long planemask;
 
111
{
 
112
        switch (alu) {
 
113
                case GXcopy:
 
114
                        afbDoBitbltCopy(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
 
115
                        break;
 
116
                case GXxor:
 
117
                        afbDoBitbltXor(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
 
118
                        break;
 
119
                case GXcopyInverted:
 
120
                        afbDoBitbltCopyInverted(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
 
121
                        break;
 
122
                case GXor:
 
123
                        afbDoBitbltOr(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
 
124
                        break;
 
125
                default:
 
126
                        afbDoBitbltGeneral(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
 
127
                        break;
 
128
        }
 
129
}
 
130
 
 
131
RegionPtr
 
132
afbCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height,
 
133
                                 dstx, dsty)
 
134
        DrawablePtr pSrcDrawable;
 
135
        DrawablePtr pDstDrawable;
 
136
        GC *pGC;
 
137
        int srcx, srcy;
 
138
        int width, height;
 
139
        int dstx, dsty;
 
140
{
 
141
        void (*doBitBlt)();
 
142
 
 
143
        switch (pGC->alu) {
 
144
                case GXcopy:
 
145
                        doBitBlt = afbDoBitbltCopy;
 
146
                        break;
 
147
                case GXxor:
 
148
                        doBitBlt = afbDoBitbltXor;
 
149
                        break;
 
150
                case GXcopyInverted:
 
151
                        doBitBlt = afbDoBitbltCopyInverted;
 
152
                        break;
 
153
                case GXor:
 
154
                        doBitBlt = afbDoBitbltOr;
 
155
                        break;
 
156
                default:
 
157
                        doBitBlt = afbDoBitbltGeneral;
 
158
                        break;
 
159
        }
 
160
 
 
161
        return(afbBitBlt(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
 
162
                         width, height, dstx, dsty, doBitBlt, pGC->planemask));
 
163
}
 
164
 
 
165
RegionPtr
 
166
afbBitBlt(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height,
 
167
                          dstx, dsty, doBitBlt, planemask)
 
168
        register DrawablePtr pSrcDrawable;
 
169
        register DrawablePtr pDstDrawable;
 
170
        register GC *pGC;
 
171
        int srcx, srcy;
 
172
        int width, height;
 
173
        int dstx, dsty;
 
174
        void (*doBitBlt)();
 
175
        unsigned long planemask;
 
176
{
 
177
        RegionPtr prgnSrcClip = NULL;           /* may be a new region, or just a copy */
 
178
        Bool freeSrcClip = FALSE;
 
179
 
 
180
        RegionPtr prgnExposed;
 
181
        RegionRec rgnDst;
 
182
        DDXPointPtr pptSrc;
 
183
        register DDXPointPtr ppt;
 
184
        register BoxPtr pbox;
 
185
        int i;
 
186
        register int dx;
 
187
        register int dy;
 
188
        xRectangle origSource;
 
189
        DDXPointRec origDest;
 
190
        int numRects;
 
191
        BoxRec fastBox;
 
192
        int fastClip = 0;                                       /* for fast clipping with pixmap source */
 
193
        int fastExpose = 0;                             /* for fast exposures with pixmap source */
 
194
 
 
195
        origSource.x = srcx;
 
196
        origSource.y = srcy;
 
197
        origSource.width = width;
 
198
        origSource.height = height;
 
199
        origDest.x = dstx;
 
200
        origDest.y = dsty;
 
201
 
 
202
        if ((pSrcDrawable != pDstDrawable) && pSrcDrawable->pScreen->SourceValidate)
 
203
                (*pSrcDrawable->pScreen->SourceValidate)(pSrcDrawable, srcx, srcy, width,
 
204
                                                                                                                          height);
 
205
 
 
206
        srcx += pSrcDrawable->x;
 
207
        srcy += pSrcDrawable->y;
 
208
 
 
209
        /* clip the source */
 
210
 
 
211
        if (pSrcDrawable->type == DRAWABLE_PIXMAP)
 
212
                if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
 
213
                        prgnSrcClip = pGC->pCompositeClip;
 
214
                else
 
215
                        fastClip = 1;
 
216
        else if (pGC->subWindowMode == IncludeInferiors)
 
217
                if (!((WindowPtr)pSrcDrawable)->parent)
 
218
                        /*
 
219
                         * special case bitblt from root window in
 
220
                         * IncludeInferiors mode; just like from a pixmap
 
221
                         */
 
222
                        fastClip = 1;
 
223
                else if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
 
224
                        prgnSrcClip = pGC->pCompositeClip;
 
225
                else {
 
226
                        prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
 
227
                        freeSrcClip = TRUE;
 
228
                }
 
229
        else
 
230
                prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
 
231
 
 
232
        fastBox.x1 = srcx;
 
233
        fastBox.y1 = srcy;
 
234
        fastBox.x2 = srcx + width;
 
235
        fastBox.y2 = srcy + height;
 
236
 
 
237
        /* Don't create a source region if we are doing a fast clip */
 
238
        if (fastClip) {
 
239
                fastExpose = 1;
 
240
                /*
 
241
                 * clip the source; if regions extend beyond the source size,
 
242
                 * make sure exposure events get sent
 
243
                 */
 
244
                if (fastBox.x1 < pSrcDrawable->x) {
 
245
                        fastBox.x1 = pSrcDrawable->x;
 
246
                        fastExpose = 0;
 
247
                }
 
248
                if (fastBox.y1 < pSrcDrawable->y) {
 
249
                        fastBox.y1 = pSrcDrawable->y;
 
250
                        fastExpose = 0;
 
251
                }
 
252
                if (fastBox.x2 > pSrcDrawable->x + (int)pSrcDrawable->width) {
 
253
                        fastBox.x2 = pSrcDrawable->x + (int)pSrcDrawable->width;
 
254
                        fastExpose = 0;
 
255
                }
 
256
                if (fastBox.y2 > pSrcDrawable->y + (int)pSrcDrawable->height) {
 
257
                        fastBox.y2 = pSrcDrawable->y + (int)pSrcDrawable->height;
 
258
                        fastExpose = 0;
 
259
                }
 
260
        } else {
 
261
                REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
 
262
                REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
 
263
        }
 
264
 
 
265
        dstx += pDstDrawable->x;
 
266
        dsty += pDstDrawable->y;
 
267
 
 
268
        if (pDstDrawable->type == DRAWABLE_WINDOW)
 
269
                if (!((WindowPtr)pDstDrawable)->realized) {
 
270
                        if (!fastClip)
 
271
                                REGION_UNINIT(pGC->pScreen, &rgnDst);
 
272
                        if (freeSrcClip)
 
273
                                REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 
274
                        return NULL;
 
275
                }
 
276
 
 
277
        dx = srcx - dstx;
 
278
        dy = srcy - dsty;
 
279
 
 
280
        /* Translate and clip the dst to the destination composite clip */
 
281
        if (fastClip) {
 
282
                RegionPtr cclip;
 
283
 
 
284
                /* Translate the region directly */
 
285
                fastBox.x1 -= dx;
 
286
                fastBox.x2 -= dx;
 
287
                fastBox.y1 -= dy;
 
288
                fastBox.y2 -= dy;
 
289
 
 
290
                /* If the destination composite clip is one rectangle we can
 
291
                   do the clip directly.  Otherwise we have to create a full
 
292
                   blown region and call intersect */
 
293
                cclip = pGC->pCompositeClip;
 
294
                if (REGION_NUM_RECTS(cclip) == 1) {
 
295
                        BoxPtr pBox = REGION_RECTS(cclip);
 
296
 
 
297
                        if (fastBox.x1 < pBox->x1)
 
298
                                fastBox.x1 = pBox->x1;
 
299
                        if (fastBox.x2 > pBox->x2)
 
300
                                fastBox.x2 = pBox->x2;
 
301
                        if (fastBox.y1 < pBox->y1)
 
302
                                fastBox.y1 = pBox->y1;
 
303
                        if (fastBox.y2 > pBox->y2)
 
304
                                fastBox.y2 = pBox->y2;
 
305
 
 
306
                        /* Check to see if the region is empty */
 
307
                        if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) {
 
308
                                REGION_NULL(pGC->pScreen, &rgnDst);
 
309
                        } else {
 
310
                                REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
 
311
                        }
 
312
                } else {
 
313
                        /* We must turn off fastClip now, since we must create
 
314
                           a full blown region.  It is intersected with the
 
315
                           composite clip below. */
 
316
                        fastClip = 0;
 
317
                        REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1);
 
318
                }
 
319
        } else
 
320
                REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
 
321
 
 
322
        if (!fastClip) {
 
323
                REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst,
 
324
                 pGC->pCompositeClip);
 
325
        }
 
326
 
 
327
        /* Do bit blitting */
 
328
        numRects = REGION_NUM_RECTS(&rgnDst);
 
329
        if (numRects && width && height) {
 
330
                if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects *
 
331
                                                                                                  sizeof(DDXPointRec)))) {
 
332
                        REGION_UNINIT(pGC->pScreen, &rgnDst);
 
333
                        if (freeSrcClip)
 
334
                                REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 
335
                        return NULL;
 
336
                }
 
337
                pbox = REGION_RECTS(&rgnDst);
 
338
                ppt = pptSrc;
 
339
                for (i = numRects; --i >= 0; pbox++, ppt++) {
 
340
                        ppt->x = pbox->x1 + dx;
 
341
                        ppt->y = pbox->y1 + dy;
 
342
                }
 
343
 
 
344
                (*doBitBlt)(pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc,
 
345
                                         planemask);
 
346
 
 
347
                DEALLOCATE_LOCAL(pptSrc);
 
348
        }
 
349
 
 
350
        prgnExposed = NULL;
 
351
        if (pGC->fExpose)  {
 
352
                /* Pixmap sources generate a NoExposed (we return NULL to do this) */
 
353
                if (!fastExpose)
 
354
                        prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
 
355
                                                                                                          origSource.x, origSource.y,
 
356
                                                                                                          (int)origSource.width,
 
357
                                                                                                          (int)origSource.height, origDest.x,
 
358
                                                                                                          origDest.y, (unsigned long)0);
 
359
        }
 
360
        REGION_UNINIT(pGC->pScreen, &rgnDst);
 
361
        if (freeSrcClip)
 
362
                REGION_DESTROY(pGC->pScreen, prgnSrcClip);
 
363
        return prgnExposed;
 
364
}
 
365
 
 
366
RegionPtr
 
367
afbCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height,
 
368
                         dstx, dsty, plane)
 
369
DrawablePtr pSrcDrawable, pDstDrawable;
 
370
register GC *pGC;
 
371
int srcx, srcy;
 
372
int width, height;
 
373
int dstx, dsty;
 
374
unsigned long plane;
 
375
{
 
376
        int alu;
 
377
        RegionPtr               prgnExposed = NULL;
 
378
        unsigned long old_planemask;
 
379
 
 
380
        if (pDstDrawable->depth == 1) {
 
381
                old_planemask = pGC->planemask;
 
382
                pGC->planemask = plane;
 
383
                if ((pGC->fgPixel & 1) == 1 && (pGC->bgPixel & 1) == 0) {
 
384
                        prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
 
385
                                                         pGC, srcx, srcy, width, height, dstx, dsty);
 
386
                } else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)) {
 
387
                        unsigned char rop;
 
388
 
 
389
                        afbReduceRop(pGC->alu, pGC->fgPixel, 1, 1, &rop);
 
390
                        alu = pGC->alu;
 
391
                        pGC->alu = rop;
 
392
                        prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable, pGC,
 
393
                                                                                                                        srcx, srcy, width, height, dstx,
 
394
                                                                                                                        dsty);
 
395
                        pGC->alu = alu;
 
396
                } else { /* need to invert the src */
 
397
                        alu = pGC->alu;
 
398
                        pGC->alu = afbInverseAlu[alu];
 
399
                        prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable, pGC,
 
400
                                                                                                                        srcx, srcy, width, height, dstx,
 
401
                                                                                                                        dsty);
 
402
                        pGC->alu = alu;
 
403
                }
 
404
                pGC->planemask = old_planemask;
 
405
        } else {
 
406
                int free_pixmap = FALSE;
 
407
                PixmapPtr pBitmap = (PixmapPtr)pSrcDrawable;
 
408
                ScreenPtr pScreen = pSrcDrawable->pScreen;
 
409
                GCPtr pGC1 = NULL;
 
410
 
 
411
                if (pSrcDrawable == pDstDrawable ||
 
412
                        pSrcDrawable->type == DRAWABLE_WINDOW || pSrcDrawable->depth != 1) {
 
413
                        /* Copy a plane from source drawable to a tmp 1-bit deep pixmap */
 
414
                        /* XXX: Range check width and height */
 
415
                        pBitmap = (*pScreen->CreatePixmap)(pScreen, width, height, 1);
 
416
 
 
417
                        if (!pBitmap)
 
418
                                return(NULL);
 
419
                        pGC1 = GetScratchGC(1, pScreen);
 
420
                        if (!pGC1) {
 
421
                                (*pScreen->DestroyPixmap)(pBitmap);
 
422
                                return(NULL);
 
423
                        }
 
424
                        ValidateGC((DrawablePtr)pBitmap, pGC1);
 
425
                        (void)afbBitBlt(pSrcDrawable, (DrawablePtr)pBitmap, pGC1, srcx, srcy,
 
426
                                                                  width, height, 0, 0, afbDoBitbltCopy, plane);
 
427
                        free_pixmap = TRUE;
 
428
                }
 
429
#if 0
 
430
                else {
 
431
                        /* XXX: could cope with N-deep pixmap source case without using tmp
 
432
                         * src bitmap by setting up a scratch pixmap header and fiddle
 
433
                         * around with the pbits pointer.
 
434
                         */
 
435
                }
 
436
#endif
 
437
                afbReduceOpaqueStipple(pGC->fgPixel, pGC->bgPixel, pGC->planemask,
 
438
                                                                                pGC->depth, afbRropsOS);
 
439
                (void)afbBitBlt((DrawablePtr)pBitmap, pDstDrawable, pGC, 0, 0, width,
 
440
                                                          height, dstx, dsty, afbCopy1ToN, pGC->planemask);
 
441
                if (free_pixmap) {
 
442
                        (*pScreen->DestroyPixmap)(pBitmap);
 
443
                        FreeScratchGC(pGC1);
 
444
                }
 
445
 
 
446
                if (pGC->fExpose)
 
447
                        prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx,
 
448
                                                                                                          srcy, width, height, dstx, dsty,
 
449
                                                                                                          plane);
 
450
        }
 
451
        return prgnExposed;
 
452
}
 
453
 
 
454
void
 
455
afbCopy1ToN(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
 
456
        DrawablePtr pSrc, pDst;
 
457
        int alu;
 
458
        RegionPtr prgnDst;
 
459
        DDXPointPtr pptSrc;
 
460
        unsigned long planemask;
 
461
{
 
462
        int numRects = REGION_NUM_RECTS(prgnDst);
 
463
        BoxPtr pbox = REGION_RECTS(prgnDst);
 
464
        int r;
 
465
 
 
466
        for (r = 0; r < numRects; r++, pbox++, pptSrc++) {
 
467
                int dx = pptSrc->x;
 
468
                int dy = pptSrc->y;
 
469
 
 
470
                if (alu == GXcopy)
 
471
                        afbOpaqueStippleAreaCopy(pDst, 1, pbox, alu, (PixmapPtr)pSrc, dx, dy,
 
472
                                                                                          afbRropsOS, planemask);
 
473
                else
 
474
                        afbOpaqueStippleAreaGeneral(pDst, 1, pbox, alu, (PixmapPtr)pSrc, dx,
 
475
                                                                                                  dy, afbRropsOS, planemask);
 
476
        }
 
477
}