1 /* $XConsortium: cfbpixmap.c,v 5.14 94/04/17 20:28:56 dpw Exp $ */
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 /* pixmap management
50    written by drewry, september 1986
51 
52    on a monchrome device, a pixmap is a bitmap.
53 */
54 
55 #include "Xmd.h"
56 #include "servermd.h"
57 #include "scrnintstr.h"
58 #include "pixmapstr.h"
59 #include "mi.h"
60 #include "cfb.h"
61 #include "cfbmskbits.h"
62 
63 extern unsigned long endtab[];
64 
65 PixmapPtr
cfbCreatePixmap(pScreen,width,height,depth)66 cfbCreatePixmap (pScreen, width, height, depth)
67     ScreenPtr	pScreen;
68     int		width;
69     int		height;
70     int		depth;
71 {
72     PixmapPtr pPixmap;
73     int datasize;
74     int paddedWidth;
75 
76     paddedWidth = PixmapBytePad(width, depth);
77     datasize = height * paddedWidth;
78     pPixmap = AllocatePixmap(pScreen, datasize);
79     if (!pPixmap)
80 	return NullPixmap;
81     pPixmap->drawable.type = DRAWABLE_PIXMAP;
82     pPixmap->drawable.class = 0;
83     pPixmap->drawable.pScreen = pScreen;
84     pPixmap->drawable.depth = depth;
85     pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth);
86     pPixmap->drawable.id = 0;
87     pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
88     pPixmap->drawable.x = 0;
89     pPixmap->drawable.y = 0;
90     pPixmap->drawable.width = width;
91     pPixmap->drawable.height = height;
92     pPixmap->devKind = paddedWidth;
93     pPixmap->refcnt = 1;
94 #ifdef PIXPRIV
95     pPixmap->devPrivate.ptr = datasize ?
96 		(pointer)((char *)pPixmap + pScreen->totalPixmapSize) : NULL;
97 #else
98     pPixmap->devPrivate.ptr = (pointer)(pPixmap + 1);
99 #endif
100     return pPixmap;
101 }
102 
103 Bool
cfbDestroyPixmap(pPixmap)104 cfbDestroyPixmap(pPixmap)
105     PixmapPtr pPixmap;
106 {
107     if(--pPixmap->refcnt)
108 	return TRUE;
109     xfree(pPixmap);
110     return TRUE;
111 }
112 
113 PixmapPtr
cfbCopyPixmap(pSrc)114 cfbCopyPixmap(pSrc)
115     register PixmapPtr	pSrc;
116 {
117     register PixmapPtr	pDst;
118     int		size;
119     ScreenPtr pScreen;
120 
121     size = pSrc->drawable.height * pSrc->devKind;
122     pScreen = pSrc->drawable.pScreen;
123     pDst = (*pScreen->CreatePixmap) (pScreen, pSrc->drawable.width,
124 				pSrc->drawable.height, pSrc->drawable.depth);
125     if (!pDst)
126 	return NullPixmap;
127     memmove((char *)pDst->devPrivate.ptr, (char *)pSrc->devPrivate.ptr, size);
128     return pDst;
129 }
130 
131 
132 /* replicates a pattern to be a full 32 bits wide.
133    relies on the fact that each scnaline is longword padded.
134    doesn't do anything if pixmap is not a factor of 32 wide.
135    changes width field of pixmap if successful, so that the fast
136 	cfbXRotatePixmap code gets used if we rotate the pixmap later.
137 	cfbYRotatePixmap code gets used if we rotate the pixmap later.
138 
139    calculate number of times to repeat
140    for each scanline of pattern
141       zero out area to be filled with replicate
142       left shift and or in original as many times as needed
143 */
144 void
cfbPadPixmap(pPixmap)145 cfbPadPixmap(pPixmap)
146     PixmapPtr pPixmap;
147 {
148     register int width = (pPixmap->drawable.width) * (pPixmap->drawable.bitsPerPixel);
149     register int h;
150     register unsigned long mask;
151     register unsigned long *p;
152     register unsigned long bits; /* real pattern bits */
153     register int i;
154     int rep;                    /* repeat count for pattern */
155 
156     if (width >= PGSZ)
157         return;
158 
159     rep = PGSZ/width;
160     if (rep*width != PGSZ)
161         return;
162 
163     mask = endtab[width];
164 
165     p = (unsigned long *)(pPixmap->devPrivate.ptr);
166     for (h=0; h < pPixmap->drawable.height; h++)
167     {
168         *p &= mask;
169         bits = *p;
170         for(i=1; i<rep; i++)
171         {
172 #if (BITMAP_BIT_ORDER == MSBFirst)
173             bits >>= width;
174 #else
175 	    bits <<= width;
176 #endif
177             *p |= bits;
178         }
179         p++;
180     }
181     pPixmap->drawable.width = PGSZ/(pPixmap->drawable.bitsPerPixel);
182 }
183 
184 
185 #ifdef notdef
186 /*
187  * cfb debugging routine -- assumes pixmap is 1 byte deep
188  */
cfbdumppixmap(pPix)189 static cfbdumppixmap(pPix)
190     PixmapPtr	pPix;
191 {
192     unsigned int *pw;
193     char *psrc, *pdst;
194     int	i, j;
195     char	line[66];
196 
197     ErrorF(  "pPixmap: 0x%x\n", pPix);
198     ErrorF(  "%d wide %d high\n", pPix->drawable.width, pPix->drawable.height);
199     if (pPix->drawable.width > 64)
200     {
201 	ErrorF(  "too wide to see\n");
202 	return;
203     }
204 
205     pw = (unsigned int *) pPix->devPrivate.ptr;
206     psrc = (char *) pw;
207 
208 /*
209     for ( i=0; i<pPix->drawable.height; ++i )
210 	ErrorF( "0x%x\n", pw[i] );
211 */
212 
213     for ( i = 0; i < pPix->drawable.height; ++i ) {
214 	pdst = line;
215 	for(j = 0; j < pPix->drawable.width; j++) {
216 	    *pdst++ = *psrc++ ? 'X' : ' ' ;
217 	}
218 	*pdst++ = '\n';
219 	*pdst++ = '\0';
220 	ErrorF( "%s", line);
221     }
222 }
223 #endif /* notdef */
224 
225 /* Rotates pixmap pPix by w pixels to the right on the screen. Assumes that
226  * words are PGSZ bits wide, and that the least significant bit appears on the
227  * left.
228  */
229 void
cfbXRotatePixmap(pPix,rw)230 cfbXRotatePixmap(pPix, rw)
231     PixmapPtr	pPix;
232     register int rw;
233 {
234     register unsigned long	*pw, *pwFinal;
235     register unsigned long	t;
236     int				rot;
237 
238     if (pPix == NullPixmap)
239         return;
240 
241     switch (((DrawablePtr) pPix)->bitsPerPixel) {
242 	case PSZ:
243 	    break;
244 	case 1:
245 	    mfbXRotatePixmap(pPix, rw);
246 	    return;
247 	default:
248 	    ErrorF("cfbXRotatePixmap: unsupported bitsPerPixel %d\n", ((DrawablePtr) pPix)->bitsPerPixel);
249 	    return;
250     }
251     pw = (unsigned long *)pPix->devPrivate.ptr;
252     modulus (rw, (int) pPix->drawable.width, rot);
253     if(pPix->drawable.width == PPW)
254     {
255         pwFinal = pw + pPix->drawable.height;
256 	while(pw < pwFinal)
257 	{
258 	    t = *pw;
259 	    *pw++ = SCRRIGHT(t, rot) |
260 		    (SCRLEFT(t, (PPW-rot)) & cfbendtab[rot]);
261 	}
262     }
263     else
264     {
265         ErrorF("cfb internal error: trying to rotate odd-sized pixmap.\n");
266 #ifdef notdef
267 	register unsigned long *pwTmp;
268 	int size, tsize;
269 
270 	tsize = PixmapBytePad(pPix->drawable.width - rot, pPix->drawable.depth);
271 	pwTmp = (unsigned long *) ALLOCATE_LOCAL(pPix->drawable.height * tsize);
272 	if (!pwTmp)
273 	    return;
274 	/* divide pw (the pixmap) in two vertically at (w - rot) and swap */
275 	tsize >>= 2;
276 	size = pPix->devKind >> SIZE0F(PixelGroup);
277 	cfbQuickBlt((long *)pw, (long *)pwTmp,
278 		    0, 0, 0, 0,
279 		    (int)pPix->drawable.width - rot, (int)pPix->drawable.height,
280 		    size, tsize);
281 	cfbQuickBlt((long *)pw, (long *)pw,
282 		    (int)pPix->drawable.width - rot, 0, 0, 0,
283 		    rot, (int)pPix->drawable.height,
284 		    size, size);
285 	cfbQuickBlt((long *)pwTmp, (long *)pw,
286 		    0, 0, rot, 0,
287 		    (int)pPix->drawable.width - rot, (int)pPix->drawable.height,
288 		    tsize, size);
289 	DEALLOCATE_LOCAL(pwTmp);
290 #endif
291     }
292 }
293 
294 /* Rotates pixmap pPix by h lines.  Assumes that h is always less than
295    pPix->drawable.height
296    works on any width.
297  */
298 void
cfbYRotatePixmap(pPix,rh)299 cfbYRotatePixmap(pPix, rh)
300     register PixmapPtr	pPix;
301     int	rh;
302 {
303     int nbyDown;	/* bytes to move down to row 0; also offset of
304 			   row rh */
305     int nbyUp;		/* bytes to move up to line rh; also
306 			   offset of first line moved down to 0 */
307     char *pbase;
308     char *ptmp;
309     int	rot;
310 
311     if (pPix == NullPixmap)
312 	return;
313     switch (((DrawablePtr) pPix)->bitsPerPixel) {
314 	case PSZ:
315 	    break;
316 	case 1:
317 	    mfbYRotatePixmap(pPix, rh);
318 	    return;
319 	default:
320 	    ErrorF("cfbYRotatePixmap: unsupported bitsPerPixel %d\n", ((DrawablePtr) pPix)->bitsPerPixel);
321 	    return;
322     }
323 
324     modulus (rh, (int) pPix->drawable.height, rot);
325     pbase = (char *)pPix->devPrivate.ptr;
326 
327     nbyDown = rot * pPix->devKind;
328     nbyUp = (pPix->devKind * pPix->drawable.height) - nbyDown;
329     if(!(ptmp = (char *)ALLOCATE_LOCAL(nbyUp)))
330 	return;
331 
332     memmove(ptmp, pbase, nbyUp);		/* save the low rows */
333     memmove(pbase, pbase+nbyUp, nbyDown);	/* slide the top rows down */
334     memmove(pbase+nbyDown, ptmp, nbyUp);	/* move lower rows up to row rot */
335     DEALLOCATE_LOCAL(ptmp);
336 }
337 
338 void
cfbCopyRotatePixmap(psrcPix,ppdstPix,xrot,yrot)339 cfbCopyRotatePixmap(psrcPix, ppdstPix, xrot, yrot)
340     register PixmapPtr psrcPix, *ppdstPix;
341     int	xrot, yrot;
342 {
343     register PixmapPtr pdstPix;
344 
345     if ((pdstPix = *ppdstPix) &&
346 	(pdstPix->devKind == psrcPix->devKind) &&
347 	(pdstPix->drawable.height == psrcPix->drawable.height))
348     {
349 	memmove((char *)pdstPix->devPrivate.ptr,
350 		(char *)psrcPix->devPrivate.ptr,
351 	      psrcPix->drawable.height * psrcPix->devKind);
352 	pdstPix->drawable.width = psrcPix->drawable.width;
353 	pdstPix->drawable.depth = psrcPix->drawable.depth;
354 	pdstPix->drawable.bitsPerPixel = psrcPix->drawable.bitsPerPixel;
355 	pdstPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
356     }
357     else
358     {
359 	if (pdstPix)
360 	    /* FIX XBUG 6168 */
361 	    (*pdstPix->drawable.pScreen->DestroyPixmap)(pdstPix);
362 	*ppdstPix = pdstPix = cfbCopyPixmap(psrcPix);
363 	if (!pdstPix)
364 	    return;
365     }
366     cfbPadPixmap(pdstPix);
367     if (xrot)
368 	cfbXRotatePixmap(pdstPix, xrot);
369     if (yrot)
370 	cfbYRotatePixmap(pdstPix, yrot);
371 }
372