17aca9224b7222305925c6b337ed03572e610cbb
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * Kevin E. Martin <kem@redhat.com>
35 * Provides pixmap support. */
37 #ifdef HAVE_DMX_CONFIG_H
38 #include <dmx-config.h>
43 #include "dmxpixmap.h"
45 #include "pixmapstr.h"
49 /** Initialize a private area in \a pScreen for pixmap information. */
51 dmxInitPixmap(ScreenPtr pScreen
)
53 if (!dixRegisterPrivateKey
54 (&dmxPixPrivateKeyRec
, PRIVATE_PIXMAP
, sizeof(dmxPixPrivRec
)))
60 /** Create a pixmap on the back-end server. */
62 dmxBECreatePixmap(PixmapPtr pPixmap
)
64 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
65 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
66 dmxPixPrivPtr pPixPriv
= DMX_GET_PIXMAP_PRIV(pPixmap
);
68 /* Make sure we haven't already created this pixmap. This can
69 * happen when the pixmap is used elsewhere (e.g., as a background
70 * or border for a window) and the refcnt > 1.
75 if (pPixmap
->drawable
.width
&& pPixmap
->drawable
.height
) {
76 pPixPriv
->pixmap
= XCreatePixmap(dmxScreen
->beDisplay
,
78 pPixmap
->drawable
.width
,
79 pPixmap
->drawable
.height
,
80 pPixmap
->drawable
.depth
);
81 dmxSync(dmxScreen
, FALSE
);
85 /** Create a pixmap for \a pScreen with the specified \a width, \a
86 * height, and \a depth. */
88 dmxCreatePixmap(ScreenPtr pScreen
, int width
, int height
, int depth
,
91 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
94 dmxPixPrivPtr pPixPriv
;
97 DMX_UNWRAP(CreatePixmap
, dmxScreen
, pScreen
);
98 if (pScreen
->CreatePixmap
)
99 ret
= pScreen
->CreatePixmap(pPixmap
);
102 /* Create pixmap on back-end server */
108 pPixmap
= AllocatePixmap(pScreen
, 0);
112 pPixmap
->drawable
.type
= DRAWABLE_PIXMAP
;
113 pPixmap
->drawable
.class = 0;
114 pPixmap
->drawable
.pScreen
= pScreen
;
115 pPixmap
->drawable
.depth
= depth
;
116 pPixmap
->drawable
.bitsPerPixel
= bpp
;
117 pPixmap
->drawable
.id
= 0;
118 pPixmap
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
119 pPixmap
->drawable
.x
= 0;
120 pPixmap
->drawable
.y
= 0;
121 pPixmap
->drawable
.width
= width
;
122 pPixmap
->drawable
.height
= height
;
123 pPixmap
->devKind
= PixmapBytePad(width
, bpp
);
125 pPixmap
->usage_hint
= usage_hint
;
127 pPixPriv
= DMX_GET_PIXMAP_PRIV(pPixmap
);
128 pPixPriv
->pixmap
= (Pixmap
) 0;
129 pPixPriv
->detachedImage
= NULL
;
131 /* Create the pixmap on the back-end server */
132 if (dmxScreen
->beDisplay
) {
133 dmxBECreatePixmap(pPixmap
);
137 DMX_WRAP(CreatePixmap
, dmxCreatePixmap
, dmxScreen
, pScreen
);
143 /** Destroy the pixmap on the back-end server. */
145 dmxBEFreePixmap(PixmapPtr pPixmap
)
147 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
148 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
149 dmxPixPrivPtr pPixPriv
= DMX_GET_PIXMAP_PRIV(pPixmap
);
151 if (pPixPriv
->pixmap
) {
152 XFreePixmap(dmxScreen
->beDisplay
, pPixPriv
->pixmap
);
153 pPixPriv
->pixmap
= (Pixmap
) 0;
160 /** Destroy the pixmap pointed to by \a pPixmap. */
162 dmxDestroyPixmap(PixmapPtr pPixmap
)
164 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
165 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
169 DMX_UNWRAP(DestroyPixmap
, dmxScreen
, pScreen
);
172 if (--pPixmap
->refcnt
)
175 /* Destroy pixmap on back-end server */
176 if (dmxScreen
->beDisplay
) {
177 if (dmxBEFreePixmap(pPixmap
)) {
178 /* Also make sure that we destroy any detached image */
179 dmxPixPrivPtr pPixPriv
= DMX_GET_PIXMAP_PRIV(pPixmap
);
181 if (pPixPriv
->detachedImage
)
182 XDestroyImage(pPixPriv
->detachedImage
);
183 dmxSync(dmxScreen
, FALSE
);
189 if (pScreen
->DestroyPixmap
)
190 ret
= pScreen
->DestroyPixmap(pPixmap
);
191 DMX_WRAP(DestroyPixmap
, dmxDestroyPixmap
, dmxScreen
, pScreen
);
197 /** Create and return a region based on the pixmap pointed to by \a
200 dmxBitmapToRegion(PixmapPtr pPixmap
)
202 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pPixmap
->drawable
.pScreen
->myNum
];
203 dmxPixPrivPtr pPixPriv
= DMX_GET_PIXMAP_PRIV(pPixmap
);
205 RegionPtr pReg
, pTmpReg
;
207 unsigned long previousPixel
, currentPixel
;
211 if (!dmxScreen
->beDisplay
) {
212 pReg
= RegionCreate(NullBox
, 1);
216 ximage
= XGetImage(dmxScreen
->beDisplay
, pPixPriv
->pixmap
, 0, 0,
217 pPixmap
->drawable
.width
, pPixmap
->drawable
.height
,
220 pReg
= RegionCreate(NullBox
, 1);
221 pTmpReg
= RegionCreate(NullBox
, 1);
222 if (!pReg
|| !pTmpReg
) {
223 XDestroyImage(ximage
);
227 for (y
= 0; y
< pPixmap
->drawable
.height
; y
++) {
231 for (x
= 0; x
< pPixmap
->drawable
.width
; x
++) {
232 currentPixel
= XGetPixel(ximage
, x
, y
);
233 if (previousPixel
!= currentPixel
) {
234 if (previousPixel
== 0L) {
238 else if (currentPixel
== 0L) {
241 RegionReset(pTmpReg
, &Box
);
242 RegionAppend(pReg
, pTmpReg
);
244 previousPixel
= currentPixel
;
247 if (previousPixel
!= 0L) {
248 /* right edge because of the end of pixmap */
249 Box
.x2
= pPixmap
->drawable
.width
;
250 RegionReset(pTmpReg
, &Box
);
251 RegionAppend(pReg
, pTmpReg
);
255 RegionDestroy(pTmpReg
);
256 XDestroyImage(ximage
);
258 RegionValidate(pReg
, &overlap
);
260 dmxSync(dmxScreen
, FALSE
);