1
/* $XFree86: xc/programs/Xserver/afb/afbbitblt.c,v 3.5tsi Exp $ */
2
/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */
3
/***********************************************************
5
Copyright (c) 1987 X Consortium
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:
14
The above copyright notice and this permission notice shall be included in
15
all copies or substantial portions of the Software.
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.
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.
29
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
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.
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
49
******************************************************************/
50
/* $XConsortium: afbbitblt.c,v 5.25 94/04/17 20:28:16 dpw Exp $ */
52
#ifdef HAVE_DIX_CONFIG_H
53
#include <dix-config.h>
57
#include <X11/Xprotostr.h>
59
#include "regionstr.h"
61
#include "windowstr.h"
62
#include "pixmapstr.h"
63
#include "scrnintstr.h"
71
static unsigned char afbRropsOS[AFB_MAX_DEPTH];
73
/* CopyArea and CopyPlane for a monchrome frame buffer
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
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.
94
** In addition, if source is a pixmap, there is no need to call the
95
** expensive miHandleExposures() routine. Instead, we simply return NULL.
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.
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.
105
afbDoBitblt(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
106
DrawablePtr pSrc, pDst;
110
unsigned long planemask;
114
afbDoBitbltCopy(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
117
afbDoBitbltXor(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
120
afbDoBitbltCopyInverted(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
123
afbDoBitbltOr(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
126
afbDoBitbltGeneral(pSrc, pDst, alu, prgnDst, pptSrc, planemask);
132
afbCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height,
134
DrawablePtr pSrcDrawable;
135
DrawablePtr pDstDrawable;
145
doBitBlt = afbDoBitbltCopy;
148
doBitBlt = afbDoBitbltXor;
151
doBitBlt = afbDoBitbltCopyInverted;
154
doBitBlt = afbDoBitbltOr;
157
doBitBlt = afbDoBitbltGeneral;
161
return(afbBitBlt(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
162
width, height, dstx, dsty, doBitBlt, pGC->planemask));
166
afbBitBlt(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height,
167
dstx, dsty, doBitBlt, planemask)
168
register DrawablePtr pSrcDrawable;
169
register DrawablePtr pDstDrawable;
175
unsigned long planemask;
177
RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */
178
Bool freeSrcClip = FALSE;
180
RegionPtr prgnExposed;
183
register DDXPointPtr ppt;
184
register BoxPtr pbox;
188
xRectangle origSource;
189
DDXPointRec origDest;
192
int fastClip = 0; /* for fast clipping with pixmap source */
193
int fastExpose = 0; /* for fast exposures with pixmap source */
197
origSource.width = width;
198
origSource.height = height;
202
if ((pSrcDrawable != pDstDrawable) && pSrcDrawable->pScreen->SourceValidate)
203
(*pSrcDrawable->pScreen->SourceValidate)(pSrcDrawable, srcx, srcy, width,
206
srcx += pSrcDrawable->x;
207
srcy += pSrcDrawable->y;
209
/* clip the source */
211
if (pSrcDrawable->type == DRAWABLE_PIXMAP)
212
if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
213
prgnSrcClip = pGC->pCompositeClip;
216
else if (pGC->subWindowMode == IncludeInferiors)
217
if (!((WindowPtr)pSrcDrawable)->parent)
219
* special case bitblt from root window in
220
* IncludeInferiors mode; just like from a pixmap
223
else if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
224
prgnSrcClip = pGC->pCompositeClip;
226
prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
230
prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
234
fastBox.x2 = srcx + width;
235
fastBox.y2 = srcy + height;
237
/* Don't create a source region if we are doing a fast clip */
241
* clip the source; if regions extend beyond the source size,
242
* make sure exposure events get sent
244
if (fastBox.x1 < pSrcDrawable->x) {
245
fastBox.x1 = pSrcDrawable->x;
248
if (fastBox.y1 < pSrcDrawable->y) {
249
fastBox.y1 = pSrcDrawable->y;
252
if (fastBox.x2 > pSrcDrawable->x + (int)pSrcDrawable->width) {
253
fastBox.x2 = pSrcDrawable->x + (int)pSrcDrawable->width;
256
if (fastBox.y2 > pSrcDrawable->y + (int)pSrcDrawable->height) {
257
fastBox.y2 = pSrcDrawable->y + (int)pSrcDrawable->height;
261
REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
262
REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
265
dstx += pDstDrawable->x;
266
dsty += pDstDrawable->y;
268
if (pDstDrawable->type == DRAWABLE_WINDOW)
269
if (!((WindowPtr)pDstDrawable)->realized) {
271
REGION_UNINIT(pGC->pScreen, &rgnDst);
273
REGION_DESTROY(pGC->pScreen, prgnSrcClip);
280
/* Translate and clip the dst to the destination composite clip */
284
/* Translate the region directly */
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);
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;
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);
310
REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
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. */
317
REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1);
320
REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
323
REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst,
324
pGC->pCompositeClip);
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);
334
REGION_DESTROY(pGC->pScreen, prgnSrcClip);
337
pbox = REGION_RECTS(&rgnDst);
339
for (i = numRects; --i >= 0; pbox++, ppt++) {
340
ppt->x = pbox->x1 + dx;
341
ppt->y = pbox->y1 + dy;
344
(*doBitBlt)(pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc,
347
DEALLOCATE_LOCAL(pptSrc);
352
/* Pixmap sources generate a NoExposed (we return NULL to do this) */
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);
360
REGION_UNINIT(pGC->pScreen, &rgnDst);
362
REGION_DESTROY(pGC->pScreen, prgnSrcClip);
367
afbCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height,
369
DrawablePtr pSrcDrawable, pDstDrawable;
377
RegionPtr prgnExposed = NULL;
378
unsigned long old_planemask;
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)) {
389
afbReduceRop(pGC->alu, pGC->fgPixel, 1, 1, &rop);
392
prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable, pGC,
393
srcx, srcy, width, height, dstx,
396
} else { /* need to invert the src */
398
pGC->alu = afbInverseAlu[alu];
399
prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable, pGC,
400
srcx, srcy, width, height, dstx,
404
pGC->planemask = old_planemask;
406
int free_pixmap = FALSE;
407
PixmapPtr pBitmap = (PixmapPtr)pSrcDrawable;
408
ScreenPtr pScreen = pSrcDrawable->pScreen;
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);
419
pGC1 = GetScratchGC(1, pScreen);
421
(*pScreen->DestroyPixmap)(pBitmap);
424
ValidateGC((DrawablePtr)pBitmap, pGC1);
425
(void)afbBitBlt(pSrcDrawable, (DrawablePtr)pBitmap, pGC1, srcx, srcy,
426
width, height, 0, 0, afbDoBitbltCopy, plane);
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.
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);
442
(*pScreen->DestroyPixmap)(pBitmap);
447
prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx,
448
srcy, width, height, dstx, dsty,
455
afbCopy1ToN(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
456
DrawablePtr pSrc, pDst;
460
unsigned long planemask;
462
int numRects = REGION_NUM_RECTS(prgnDst);
463
BoxPtr pbox = REGION_RECTS(prgnDst);
466
for (r = 0; r < numRects; r++, pbox++, pptSrc++) {
471
afbOpaqueStippleAreaCopy(pDst, 1, pbox, alu, (PixmapPtr)pSrc, dx, dy,
472
afbRropsOS, planemask);
474
afbOpaqueStippleAreaGeneral(pDst, 1, pbox, alu, (PixmapPtr)pSrc, dx,
475
dy, afbRropsOS, planemask);