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