Bug Summary

File:mi/mibitblt.c
Location:line 669, column 1
Description:Potential memory leak

Annotated Source Code

1/***********************************************************
2
3Copyright 1987, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27 All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Digital not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45******************************************************************/
46/* Author: Todd Newman (aided and abetted by Mr. Drewry) */
47
48#ifdef HAVE_DIX_CONFIG_H1
49#include <dix-config.h>
50#endif
51
52#include <X11/X.h>
53#include <X11/Xprotostr.h>
54
55#include "misc.h"
56#include "gcstruct.h"
57#include "pixmapstr.h"
58#include "windowstr.h"
59#include "scrnintstr.h"
60#include "mi.h"
61#include "regionstr.h"
62#include <X11/Xmd.h>
63#include "servermd.h"
64
65#ifndef HAVE_FFS1
66extern int ffs(int);
67#endif
68
69/* MICOPYAREA -- public entry for the CopyArea request
70 * For each rectangle in the source region
71 * get the pixels with GetSpans
72 * set them in the destination with SetSpans
73 * We let SetSpans worry about clipping to the destination.
74 */
75_X_COLD__attribute__((__cold__)) RegionPtr
76miCopyArea(DrawablePtr pSrcDrawable,
77 DrawablePtr pDstDrawable,
78 GCPtr pGC,
79 int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut)
80{
81 DDXPointPtr ppt, pptFirst;
82 unsigned int *pwidthFirst, *pwidth, *pbits;
83 BoxRec srcBox, *prect;
84
85 /* may be a new region, or just a copy */
86 RegionPtr prgnSrcClip;
87
88 /* non-0 if we've created a src clip */
89 RegionPtr prgnExposed;
90 int realSrcClip = 0;
91 int srcx, srcy, dstx, dsty, i, j, y, width, height, xMin, xMax, yMin, yMax;
92 unsigned int *ordering;
93 int numRects;
94 BoxPtr boxes;
95
96 srcx = xIn + pSrcDrawable->x;
97 srcy = yIn + pSrcDrawable->y;
98
99 /* If the destination isn't realized, this is easy */
100 if (pDstDrawable->type == DRAWABLE_WINDOW0 &&
101 !((WindowPtr) pDstDrawable)->realized)
102 return NULL((void*)0);
103
104 /* clip the source */
105 if (pSrcDrawable->type == DRAWABLE_PIXMAP1) {
106 BoxRec box;
107
108 box.x1 = pSrcDrawable->x;
109 box.y1 = pSrcDrawable->y;
110 box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
111 box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
112
113 prgnSrcClip = RegionCreate(&box, 1);
114 realSrcClip = 1;
115 }
116 else {
117 if (pGC->subWindowMode == IncludeInferiors1) {
118 prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable);
119 realSrcClip = 1;
120 }
121 else
122 prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList;
123 }
124
125 /* If the src drawable is a window, we need to translate the srcBox so
126 * that we can compare it with the window's clip region later on. */
127 srcBox.x1 = srcx;
128 srcBox.y1 = srcy;
129 srcBox.x2 = srcx + widthSrc;
130 srcBox.y2 = srcy + heightSrc;
131
132 dstx = xOut;
133 dsty = yOut;
134 if (pGC->miTranslate) {
135 dstx += pDstDrawable->x;
136 dsty += pDstDrawable->y;
137 }
138
139 pptFirst = ppt = malloc(heightSrc * sizeof(DDXPointRec));
140 pwidthFirst = pwidth = malloc(heightSrc * sizeof(unsigned int));
141 numRects = RegionNumRects(prgnSrcClip);
142 boxes = RegionRects(prgnSrcClip);
143 ordering = malloc(numRects * sizeof(unsigned int));
144 if (!pptFirst || !pwidthFirst || !ordering) {
145 free(ordering);
146 free(pwidthFirst);
147 free(pptFirst);
148 return NULL((void*)0);
149 }
150
151 /* If not the same drawable then order of move doesn't matter.
152 Following assumes that boxes are sorted from top
153 to bottom and left to right.
154 */
155 if ((pSrcDrawable != pDstDrawable) &&
156 ((pGC->subWindowMode != IncludeInferiors1) ||
157 (pSrcDrawable->type == DRAWABLE_PIXMAP1) ||
158 (pDstDrawable->type == DRAWABLE_PIXMAP1)))
159 for (i = 0; i < numRects; i++)
160 ordering[i] = i;
161 else { /* within same drawable, must sequence moves carefully! */
162 if (dsty <= srcBox.y1) { /* Scroll up or stationary vertical.
163 Vertical order OK */
164 if (dstx <= srcBox.x1) /* Scroll left or stationary horizontal.
165 Horizontal order OK as well */
166 for (i = 0; i < numRects; i++)
167 ordering[i] = i;
168 else { /* scroll right. must reverse horizontal banding of rects. */
169 for (i = 0, j = 1, xMax = 0; i < numRects; j = i + 1, xMax = i) {
170 /* find extent of current horizontal band */
171 y = boxes[i].y1; /* band has this y coordinate */
172 while ((j < numRects) && (boxes[j].y1 == y))
173 j++;
174 /* reverse the horizontal band in the output ordering */
175 for (j--; j >= xMax; j--, i++)
176 ordering[i] = j;
177 }
178 }
179 }
180 else { /* Scroll down. Must reverse vertical banding. */
181 if (dstx < srcBox.x1) { /* Scroll left. Horizontal order OK. */
182 for (i = numRects - 1, j = i - 1, yMin = i, yMax = 0;
183 i >= 0; j = i - 1, yMin = i) {
184 /* find extent of current horizontal band */
185 y = boxes[i].y1; /* band has this y coordinate */
186 while ((j >= 0) && (boxes[j].y1 == y))
187 j--;
188 /* reverse the horizontal band in the output ordering */
189 for (j++; j <= yMin; j++, i--, yMax++)
190 ordering[yMax] = j;
191 }
192 }
193 else /* Scroll right or horizontal stationary.
194 Reverse horizontal order as well (if stationary, horizontal
195 order can be swapped without penalty and this is faster
196 to compute). */
197 for (i = 0, j = numRects - 1; i < numRects; i++, j--)
198 ordering[i] = j;
199 }
200 }
201
202 for (i = 0; i < numRects; i++) {
203 prect = &boxes[ordering[i]];
204 xMin = max(prect->x1, srcBox.x1)(((prect->x1) > (srcBox.x1)) ? (prect->x1) : (srcBox
.x1))
;
205 xMax = min(prect->x2, srcBox.x2)(((prect->x2) < (srcBox.x2)) ? (prect->x2) : (srcBox
.x2))
;
206 yMin = max(prect->y1, srcBox.y1)(((prect->y1) > (srcBox.y1)) ? (prect->y1) : (srcBox
.y1))
;
207 yMax = min(prect->y2, srcBox.y2)(((prect->y2) < (srcBox.y2)) ? (prect->y2) : (srcBox
.y2))
;
208 /* is there anything visible here? */
209 if (xMax <= xMin || yMax <= yMin)
210 continue;
211
212 ppt = pptFirst;
213 pwidth = pwidthFirst;
214 y = yMin;
215 height = yMax - yMin;
216 width = xMax - xMin;
217
218 for (j = 0; j < height; j++) {
219 /* We must untranslate before calling GetSpans */
220 ppt->x = xMin;
221 ppt++->y = y++;
222 *pwidth++ = width;
223 }
224 pbits = malloc(height * PixmapBytePad(width, pSrcDrawable->depth)((PixmapWidthPaddingInfo[pSrcDrawable->depth].notPower2 ? (
((int)(width) * PixmapWidthPaddingInfo[pSrcDrawable->depth
].bytesPerPixel + PixmapWidthPaddingInfo[pSrcDrawable->depth
].bytesPerPixel) >> PixmapWidthPaddingInfo[pSrcDrawable
->depth].padBytesLog2) : ((int)((width) + PixmapWidthPaddingInfo
[pSrcDrawable->depth].padRoundUp) >> PixmapWidthPaddingInfo
[pSrcDrawable->depth].padPixelsLog2)) << PixmapWidthPaddingInfo
[pSrcDrawable->depth].padBytesLog2)
);
225 if (pbits) {
226 (*pSrcDrawable->pScreen->GetSpans) (pSrcDrawable, width, pptFirst,
227 (int *) pwidthFirst, height,
228 (char *) pbits);
229 ppt = pptFirst;
230 pwidth = pwidthFirst;
231 xMin -= (srcx - dstx);
232 y = yMin - (srcy - dsty);
233 for (j = 0; j < height; j++) {
234 ppt->x = xMin;
235 ppt++->y = y++;
236 *pwidth++ = width;
237 }
238
239 (*pGC->ops->SetSpans) (pDstDrawable, pGC, (char *) pbits, pptFirst,
240 (int *) pwidthFirst, height, TRUE1);
241 free(pbits);
242 }
243 }
244 prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
245 widthSrc, heightSrc, xOut, yOut);
246 if (realSrcClip)
247 RegionDestroy(prgnSrcClip);
248
249 free(ordering);
250 free(pwidthFirst);
251 free(pptFirst);
252 return prgnExposed;
253}
254
255/* MIGETPLANE -- gets a bitmap representing one plane of pDraw
256 * A helper used for CopyPlane and XY format GetImage
257 * No clever strategy here, we grab a scanline at a time, pull out the
258 * bits and then stuff them in a 1 bit deep map.
259 */
260/*
261 * This should be replaced with something more general. mi shouldn't have to
262 * care about such things as scanline padding et alia.
263 */
264_X_COLD__attribute__((__cold__)) static MiBitsCARD32 *
265miGetPlane(DrawablePtr pDraw, int planeNum, /* number of the bitPlane */
266 int sx, int sy, int w, int h, MiBitsCARD32 * result)
267{
268 int i, j, k, width, bitsPerPixel, widthInBytes;
269 DDXPointRec pt = { 0, 0 };
270 MiBitsCARD32 pixel;
271 MiBitsCARD32 bit;
272 unsigned char *pCharsOut = NULL((void*)0);
273
274#if BITMAP_SCANLINE_UNIT32 == 8
275#define OUT_TYPECARD32 unsigned char
276#endif
277#if BITMAP_SCANLINE_UNIT32 == 16
278#define OUT_TYPECARD32 CARD16
279#endif
280#if BITMAP_SCANLINE_UNIT32 == 32
281#define OUT_TYPECARD32 CARD32
282#endif
283#if BITMAP_SCANLINE_UNIT32 == 64
284#define OUT_TYPECARD32 CARD64
285#endif
286
287 OUT_TYPECARD32 *pOut;
288 int delta = 0;
289
290 sx += pDraw->x;
291 sy += pDraw->y;
292 widthInBytes = BitmapBytePad(w)(((int)((w) + 32 - 1) >> 5) << 2);
293 if (!result)
4
Assuming 'result' is null
5
Taking true branch
294 result = calloc(h, widthInBytes);
6
Memory is allocated
295 if (!result)
7
Assuming 'result' is non-null
8
Taking false branch
296 return NULL((void*)0);
297 bitsPerPixel = pDraw->bitsPerPixel;
298 pOut = (OUT_TYPECARD32 *) result;
299 if (bitsPerPixel == 1) {
9
Assuming 'bitsPerPixel' is not equal to 1
10
Taking false branch
300 pCharsOut = (unsigned char *) result;
301 width = w;
302 }
303 else {
304 delta = (widthInBytes / (BITMAP_SCANLINE_UNIT32 / 8)) -
305 (w / BITMAP_SCANLINE_UNIT32);
306 width = 1;
307#if IMAGE_BYTE_ORDER0 == MSBFirst1
308 planeNum += (32 - bitsPerPixel);
309#endif
310 }
311 pt.y = sy;
312 for (i = h; --i >= 0; pt.y++) {
11
Loop condition is false. Execution continues on line 356
313 pt.x = sx;
314 if (bitsPerPixel == 1) {
315 (*pDraw->pScreen->GetSpans) (pDraw, width, &pt, &width, 1,
316 (char *) pCharsOut);
317 pCharsOut += widthInBytes;
318 }
319 else {
320 k = 0;
321 for (j = w; --j >= 0; pt.x++) {
322 /* Fetch the next pixel */
323 (*pDraw->pScreen->GetSpans) (pDraw, width, &pt, &width, 1,
324 (char *) &pixel);
325 /*
326 * Now get the bit and insert into a bitmap in XY format.
327 */
328 bit = (pixel >> planeNum) & 1;
329#if 0
330 /* XXX assuming bit order == byte order */
331#if BITMAP_BIT_ORDER0 == LSBFirst0
332 bit <<= k;
333#else
334 bit <<= ((BITMAP_SCANLINE_UNIT32 - 1) - k);
335#endif
336#else
337 /* XXX assuming byte order == LSBFirst */
338 if (screenInfo.bitmapBitOrder == LSBFirst0)
339 bit <<= k;
340 else
341 bit <<= ((screenInfo.bitmapScanlineUnit - 1) -
342 (k % screenInfo.bitmapScanlineUnit)) +
343 ((k / screenInfo.bitmapScanlineUnit) *
344 screenInfo.bitmapScanlineUnit);
345#endif
346 *pOut |= (OUT_TYPECARD32) bit;
347 k++;
348 if (k == BITMAP_SCANLINE_UNIT32) {
349 pOut++;
350 k = 0;
351 }
352 }
353 pOut += delta;
354 }
355 }
356 return result;
357
358}
359
360/* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw.
361 * Drawing through the clip mask we SetSpans() the bits into a
362 * bitmap and stipple those bits onto the destination drawable by doing a
363 * PolyFillRect over the whole drawable,
364 * then we invert the bitmap by copying it onto itself with an alu of
365 * GXinvert, invert the foreground/background colors of the gc, and draw
366 * the background bits.
367 * Note how the clipped out bits of the bitmap are always the background
368 * color so that the stipple never causes FillRect to draw them.
369 */
370_X_COLD__attribute__((__cold__)) static void
371miOpqStipDrawable(DrawablePtr pDraw, GCPtr pGC, RegionPtr prgnSrc,
372 MiBitsCARD32 * pbits, int srcx, int w, int h, int dstx, int dsty)
373{
374 int oldfill, i;
375 unsigned long oldfg;
376 int *pwidth, *pwidthFirst;
377 ChangeGCVal gcv[6];
378 PixmapPtr pStipple, pPixmap;
379 DDXPointRec oldOrg;
380 GCPtr pGCT;
381 DDXPointPtr ppt, pptFirst;
382 xRectangle rect;
383 RegionPtr prgnSrcClip;
384
385 pPixmap = (*pDraw->pScreen->CreatePixmap)
386 (pDraw->pScreen, w + srcx, h, 1, CREATE_PIXMAP_USAGE_SCRATCH1);
387 if (!pPixmap)
388 return;
389
390 /* Put the image into a 1 bit deep pixmap */
391 pGCT = GetScratchGC(1, pDraw->pScreen);
392 if (!pGCT) {
393 (*pDraw->pScreen->DestroyPixmap) (pPixmap);
394 return;
395 }
396 /* First set the whole pixmap to 0 */
397 gcv[0].val = 0;
398 ChangeGC(NullClient((ClientPtr) 0), pGCT, GCBackground(1L<<3), gcv);
399 ValidateGC((DrawablePtr) pPixmap, pGCT);
400 miClearDrawable((DrawablePtr) pPixmap, pGCT);
401 ppt = pptFirst = malloc(h * sizeof(DDXPointRec));
402 pwidth = pwidthFirst = malloc(h * sizeof(int));
403 if (!pptFirst || !pwidthFirst) {
404 free(pwidthFirst);
405 free(pptFirst);
406 FreeScratchGC(pGCT);
407 return;
408 }
409
410 /* we need a temporary region because ChangeClip must be assumed
411 to destroy what it's sent. note that this means we don't
412 have to free prgnSrcClip ourselves.
413 */
414 prgnSrcClip = RegionCreate(NULL((void*)0), 0);
415 RegionCopy(prgnSrcClip, prgnSrc);
416 RegionTranslate(prgnSrcClip, srcx, 0);
417 (*pGCT->funcs->ChangeClip) (pGCT, CT_REGION2, prgnSrcClip, 0);
418 ValidateGC((DrawablePtr) pPixmap, pGCT);
419
420 /* Since we know pDraw is always a pixmap, we never need to think
421 * about translation here */
422 for (i = 0; i < h; i++) {
423 ppt->x = 0;
424 ppt++->y = i;
425 *pwidth++ = w + srcx;
426 }
427
428 (*pGCT->ops->SetSpans) ((DrawablePtr) pPixmap, pGCT, (char *) pbits,
429 pptFirst, pwidthFirst, h, TRUE1);
430 free(pwidthFirst);
431 free(pptFirst);
432
433 /* Save current values from the client GC */
434 oldfill = pGC->fillStyle;
435 pStipple = pGC->stipple;
436 if (pStipple)
437 pStipple->refcnt++;
438 oldOrg = pGC->patOrg;
439
440 /* Set a new stipple in the drawable */
441 gcv[0].val = FillStippled2;
442 gcv[1].ptr = pPixmap;
443 gcv[2].val = dstx - srcx;
444 gcv[3].val = dsty;
445
446 ChangeGC(NullClient((ClientPtr) 0), pGC,
447 GCFillStyle(1L<<8) | GCStipple(1L<<11) | GCTileStipXOrigin(1L<<12) | GCTileStipYOrigin(1L<<13),
448 gcv);
449 ValidateGC(pDraw, pGC);
450
451 /* Fill the drawable with the stipple. This will draw the
452 * foreground color whereever 1 bits are set, leaving everything
453 * with 0 bits untouched. Note that the part outside the clip
454 * region is all 0s. */
455 rect.x = dstx;
456 rect.y = dsty;
457 rect.width = w;
458 rect.height = h;
459 (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
460
461 /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only
462 * within the clipping region, the part outside is still all 0s */
463 gcv[0].val = GXinvert0xa;
464 ChangeGC(NullClient((ClientPtr) 0), pGCT, GCFunction(1L<<0), gcv);
465 ValidateGC((DrawablePtr) pPixmap, pGCT);
466 (*pGCT->ops->CopyArea) ((DrawablePtr) pPixmap, (DrawablePtr) pPixmap,
467 pGCT, 0, 0, w + srcx, h, 0, 0);
468
469 /* Swap foreground and background colors on the GC for the drawable.
470 * Now when we fill the drawable, we will fill in the "Background"
471 * values */
472 oldfg = pGC->fgPixel;
473 gcv[0].val = pGC->bgPixel;
474 gcv[1].val = oldfg;
475 gcv[2].ptr = pPixmap;
476 ChangeGC(NullClient((ClientPtr) 0), pGC, GCForeground(1L<<2) | GCBackground(1L<<3) | GCStipple(1L<<11), gcv);
477 ValidateGC(pDraw, pGC);
478 /* PolyFillRect might have bashed the rectangle */
479 rect.x = dstx;
480 rect.y = dsty;
481 rect.width = w;
482 rect.height = h;
483 (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
484
485 /* Now put things back */
486 if (pStipple)
487 pStipple->refcnt--;
488 gcv[0].val = oldfg;
489 gcv[1].val = pGC->fgPixel;
490 gcv[2].val = oldfill;
491 gcv[3].ptr = pStipple;
492 gcv[4].val = oldOrg.x;
493 gcv[5].val = oldOrg.y;
494 ChangeGC(NullClient((ClientPtr) 0), pGC,
495 GCForeground(1L<<2) | GCBackground(1L<<3) | GCFillStyle(1L<<8) | GCStipple(1L<<11) |
496 GCTileStipXOrigin(1L<<12) | GCTileStipYOrigin(1L<<13), gcv);
497
498 ValidateGC(pDraw, pGC);
499 /* put what we hope is a smaller clip region back in the scratch gc */
500 (*pGCT->funcs->ChangeClip) (pGCT, CT_NONE0, NULL((void*)0), 0);
501 FreeScratchGC(pGCT);
502 (*pDraw->pScreen->DestroyPixmap) (pPixmap);
503
504}
505
506/* MICOPYPLANE -- public entry for the CopyPlane request.
507 * strategy:
508 * First build up a bitmap out of the bits requested
509 * build a source clip
510 * Use the bitmap we've built up as a Stipple for the destination
511 */
512_X_COLD__attribute__((__cold__)) RegionPtr
513miCopyPlane(DrawablePtr pSrcDrawable,
514 DrawablePtr pDstDrawable,
515 GCPtr pGC,
516 int srcx,
517 int srcy,
518 int width, int height, int dstx, int dsty, unsigned long bitPlane)
519{
520 MiBitsCARD32 *ptile;
521 BoxRec box;
522 RegionPtr prgnSrc, prgnExposed;
523
524 /* incorporate the source clip */
525
526 box.x1 = srcx + pSrcDrawable->x;
527 box.y1 = srcy + pSrcDrawable->y;
528 box.x2 = box.x1 + width;
529 box.y2 = box.y1 + height;
530 /* clip to visible drawable */
531 if (box.x1 < pSrcDrawable->x)
532 box.x1 = pSrcDrawable->x;
533 if (box.y1 < pSrcDrawable->y)
534 box.y1 = pSrcDrawable->y;
535 if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
536 box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
537 if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
538 box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
539 if (box.x1 > box.x2)
540 box.x2 = box.x1;
541 if (box.y1 > box.y2)
542 box.y2 = box.y1;
543 prgnSrc = RegionCreate(&box, 1);
544
545 if (pSrcDrawable->type != DRAWABLE_PIXMAP1) {
546 /* clip to visible drawable */
547
548 if (pGC->subWindowMode == IncludeInferiors1) {
549 RegionPtr clipList = NotClippedByChildren((WindowPtr) pSrcDrawable);
550
551 RegionIntersect(prgnSrc, prgnSrc, clipList);
552 RegionDestroy(clipList);
553 }
554 else
555 RegionIntersect(prgnSrc, prgnSrc,
556 &((WindowPtr) pSrcDrawable)->clipList);
557 }
558
559 box = *RegionExtents(prgnSrc);
560 RegionTranslate(prgnSrc, -box.x1, -box.y1);
561
562 if ((box.x2 > box.x1) && (box.y2 > box.y1)) {
563 /* minimize the size of the data extracted */
564 /* note that we convert the plane mask bitPlane into a plane number */
565 box.x1 -= pSrcDrawable->x;
566 box.x2 -= pSrcDrawable->x;
567 box.y1 -= pSrcDrawable->y;
568 box.y2 -= pSrcDrawable->y;
569 ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1,
570 box.x1, box.y1,
571 box.x2 - box.x1, box.y2 - box.y1, (MiBitsCARD32 *) NULL((void*)0));
572 if (ptile) {
573 miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0,
574 box.x2 - box.x1, box.y2 - box.y1,
575 dstx + box.x1 - srcx, dsty + box.y1 - srcy);
576 free(ptile);
577 }
578 }
579 prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
580 width, height, dstx, dsty);
581 RegionDestroy(prgnSrc);
582 return prgnExposed;
583}
584
585/* MIGETIMAGE -- public entry for the GetImage Request
586 * We're getting the image into a memory buffer. While we have to use GetSpans
587 * to read a line from the device (since we don't know what that looks like),
588 * we can just write into the destination buffer
589 *
590 * two different strategies are used, depending on whether we're getting the
591 * image in Z format or XY format
592 * Z format:
593 * Line at a time, GetSpans a line into the destination buffer, then if the
594 * planemask is not all ones, we do a SetSpans into a temporary buffer (to get
595 * bits turned off) and then another GetSpans to get stuff back (because
596 * pixmaps are opaque, and we are passed in the memory to write into). This is
597 * pretty ugly and slow but works. Life is hard.
598 * XY format:
599 * get the single plane specified in planemask
600 */
601_X_COLD__attribute__((__cold__)) void
602miGetImage(DrawablePtr pDraw, int sx, int sy, int w, int h,
603 unsigned int format, unsigned long planeMask, char *pDst)
604{
605 unsigned char depth;
606 int i, linelength, width, srcx, srcy;
607 DDXPointRec pt = { 0, 0 };
608 PixmapPtr pPixmap = NULL((void*)0);
609 GCPtr pGC = NULL((void*)0);
610
611 depth = pDraw->depth;
612 if (format == ZPixmap2) {
1
Assuming 'format' is not equal to 2
2
Taking false branch
613 if ((((1LL << depth) - 1) & planeMask) != (1LL << depth) - 1) {
614 ChangeGCVal gcv;
615 xPoint xpt;
616
617 pGC = GetScratchGC(depth, pDraw->pScreen);
618 if (!pGC)
619 return;
620 pPixmap = (*pDraw->pScreen->CreatePixmap)
621 (pDraw->pScreen, w, 1, depth, CREATE_PIXMAP_USAGE_SCRATCH1);
622 if (!pPixmap) {
623 FreeScratchGC(pGC);
624 return;
625 }
626 /*
627 * Clear the pixmap before doing anything else
628 */
629 ValidateGC((DrawablePtr) pPixmap, pGC);
630 xpt.x = xpt.y = 0;
631 width = w;
632 (*pGC->ops->FillSpans) ((DrawablePtr) pPixmap, pGC, 1, &xpt, &width,
633 TRUE1);
634
635 /* alu is already GXCopy */
636 gcv.val = (XID) planeMask;
637 ChangeGC(NullClient((ClientPtr) 0), pGC, GCPlaneMask(1L<<1), &gcv);
638 ValidateGC((DrawablePtr) pPixmap, pGC);
639 }
640
641 linelength = PixmapBytePad(w, depth)((PixmapWidthPaddingInfo[depth].notPower2 ? (((int)(w) * PixmapWidthPaddingInfo
[depth].bytesPerPixel + PixmapWidthPaddingInfo[depth].bytesPerPixel
) >> PixmapWidthPaddingInfo[depth].padBytesLog2) : ((int
)((w) + PixmapWidthPaddingInfo[depth].padRoundUp) >> PixmapWidthPaddingInfo
[depth].padPixelsLog2)) << PixmapWidthPaddingInfo[depth
].padBytesLog2)
;
642 srcx = sx + pDraw->x;
643 srcy = sy + pDraw->y;
644 for (i = 0; i < h; i++) {
645 pt.x = srcx;
646 pt.y = srcy + i;
647 width = w;
648 (*pDraw->pScreen->GetSpans) (pDraw, w, &pt, &width, 1, pDst);
649 if (pPixmap) {
650 pt.x = 0;
651 pt.y = 0;
652 width = w;
653 (*pGC->ops->SetSpans) ((DrawablePtr) pPixmap, pGC, pDst,
654 &pt, &width, 1, TRUE1);
655 (*pDraw->pScreen->GetSpans) ((DrawablePtr) pPixmap, w, &pt,
656 &width, 1, pDst);
657 }
658 pDst += linelength;
659 }
660 if (pPixmap) {
661 (*pGC->pScreen->DestroyPixmap) (pPixmap);
662 FreeScratchGC(pGC);
663 }
664 }
665 else {
666 (void) miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h,
3
Calling 'miGetPlane'
12
Returned allocated memory
667 (MiBitsCARD32 *) pDst);
668 }
669}
13
Potential memory leak
670
671/* MIPUTIMAGE -- public entry for the PutImage request
672 * Here we benefit from knowing the format of the bits pointed to by pImage,
673 * even if we don't know how pDraw represents them.
674 * Three different strategies are used depending on the format
675 * XYBitmap Format:
676 * we just use the Opaque Stipple helper function to cover the destination
677 * Note that this covers all the planes of the drawable with the
678 * foreground color (masked with the GC planemask) where there are 1 bits
679 * and the background color (masked with the GC planemask) where there are
680 * 0 bits
681 * XYPixmap format:
682 * what we're called with is a series of XYBitmaps, but we only want
683 * each XYPixmap to update 1 plane, instead of updating all of them.
684 * we set the foreground color to be all 1s and the background to all 0s
685 * then for each plane, we set the plane mask to only effect that one
686 * plane and recursive call ourself with the format set to XYBitmap
687 * (This clever idea courtesy of RGD.)
688 * ZPixmap format:
689 * This part is simple, just call SetSpans
690 */
691_X_COLD__attribute__((__cold__)) void
692miPutImage(DrawablePtr pDraw, GCPtr pGC, int depth,
693 int x, int y, int w, int h, int leftPad, int format, char *pImage)
694{
695 DDXPointPtr pptFirst, ppt;
696 int *pwidthFirst, *pwidth;
697 RegionPtr prgnSrc;
698 BoxRec box;
699 unsigned long oldFg, oldBg;
700 ChangeGCVal gcv[3];
701 unsigned long oldPlanemask;
702 unsigned long i;
703 long bytesPer;
704
705 if (!w || !h)
706 return;
707 switch (format) {
708 case XYBitmap0:
709
710 box.x1 = 0;
711 box.y1 = 0;
712 box.x2 = w;
713 box.y2 = h;
714 prgnSrc = RegionCreate(&box, 1);
715
716 miOpqStipDrawable(pDraw, pGC, prgnSrc, (MiBitsCARD32 *) pImage,
717 leftPad, w, h, x, y);
718 RegionDestroy(prgnSrc);
719 break;
720
721 case XYPixmap1:
722 depth = pGC->depth;
723 oldPlanemask = pGC->planemask;
724 oldFg = pGC->fgPixel;
725 oldBg = pGC->bgPixel;
726 gcv[0].val = (XID) ~0;
727 gcv[1].val = (XID) 0;
728 ChangeGC(NullClient((ClientPtr) 0), pGC, GCForeground(1L<<2) | GCBackground(1L<<3), gcv);
729 bytesPer = (long) h *BitmapBytePad(w + leftPad)(((int)((w + leftPad) + 32 - 1) >> 5) << 2);
730
731 for (i = (unsigned long) 1 << (depth - 1); i != 0; i >>= 1, pImage += bytesPer) {
732 if (i & oldPlanemask) {
733 gcv[0].val = (XID) i;
734 ChangeGC(NullClient((ClientPtr) 0), pGC, GCPlaneMask(1L<<1), gcv);
735 ValidateGC(pDraw, pGC);
736 (*pGC->ops->PutImage) (pDraw, pGC, 1, x, y, w, h, leftPad,
737 XYBitmap0, (char *) pImage);
738 }
739 }
740 gcv[0].val = (XID) oldPlanemask;
741 gcv[1].val = (XID) oldFg;
742 gcv[2].val = (XID) oldBg;
743 ChangeGC(NullClient((ClientPtr) 0), pGC, GCPlaneMask(1L<<1) | GCForeground(1L<<2) | GCBackground(1L<<3),
744 gcv);
745 ValidateGC(pDraw, pGC);
746 break;
747
748 case ZPixmap2:
749 ppt = pptFirst = malloc(h * sizeof(DDXPointRec));
750 pwidth = pwidthFirst = malloc(h * sizeof(int));
751 if (!pptFirst || !pwidthFirst) {
752 free(pwidthFirst);
753 free(pptFirst);
754 return;
755 }
756 if (pGC->miTranslate) {
757 x += pDraw->x;
758 y += pDraw->y;
759 }
760
761 for (i = 0; i < h; i++) {
762 ppt->x = x;
763 ppt->y = y + i;
764 ppt++;
765 *pwidth++ = w;
766 }
767
768 (*pGC->ops->SetSpans) (pDraw, pGC, (char *) pImage, pptFirst,
769 pwidthFirst, h, TRUE1);
770 free(pwidthFirst);
771 free(pptFirst);
772 break;
773 }
774}