Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / dmxpixmap.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
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:
13 *
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.
17 *
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
25 * SOFTWARE.
26 */
27
28/*
29 * Authors:
30 * Kevin E. Martin <kem@redhat.com>
31 *
32 */
33
34/** \file
35 * Provides pixmap support. */
36
37#ifdef HAVE_DMX_CONFIG_H
38#include <dmx-config.h>
39#endif
40
41#include "dmx.h"
42#include "dmxsync.h"
43#include "dmxpixmap.h"
44
45#include "pixmapstr.h"
46#include "servermd.h"
47#include "privates.h"
48
49/** Initialize a private area in \a pScreen for pixmap information. */
50Bool
51dmxInitPixmap(ScreenPtr pScreen)
52{
53 if (!dixRegisterPrivateKey
54 (&dmxPixPrivateKeyRec, PRIVATE_PIXMAP, sizeof(dmxPixPrivRec)))
55 return FALSE;
56
57 return TRUE;
58}
59
60/** Create a pixmap on the back-end server. */
61void
62dmxBECreatePixmap(PixmapPtr pPixmap)
63{
64 ScreenPtr pScreen = pPixmap->drawable.pScreen;
65 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
66 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
67
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.
71 */
72 if (pPixPriv->pixmap)
73 return;
74
75 if (pPixmap->drawable.width && pPixmap->drawable.height) {
76 pPixPriv->pixmap = XCreatePixmap(dmxScreen->beDisplay,
77 dmxScreen->scrnWin,
78 pPixmap->drawable.width,
79 pPixmap->drawable.height,
80 pPixmap->drawable.depth);
81 dmxSync(dmxScreen, FALSE);
82 }
83}
84
85/** Create a pixmap for \a pScreen with the specified \a width, \a
86 * height, and \a depth. */
87PixmapPtr
88dmxCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
89 unsigned usage_hint)
90{
91 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
92 PixmapPtr pPixmap;
93 int bpp;
94 dmxPixPrivPtr pPixPriv;
95
96#if 0
97 DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
98 if (pScreen->CreatePixmap)
99 ret = pScreen->CreatePixmap(pPixmap);
100#endif
101
102 /* Create pixmap on back-end server */
103 if (depth == 24)
104 bpp = 32;
105 else
106 bpp = depth;
107
108 pPixmap = AllocatePixmap(pScreen, 0);
109 if (!pPixmap)
110 return NullPixmap;
111
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);
124 pPixmap->refcnt = 1;
125 pPixmap->usage_hint = usage_hint;
126
127 pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
128 pPixPriv->pixmap = (Pixmap) 0;
129 pPixPriv->detachedImage = NULL;
130
131 /* Create the pixmap on the back-end server */
132 if (dmxScreen->beDisplay) {
133 dmxBECreatePixmap(pPixmap);
134 }
135
136#if 0
137 DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
138#endif
139
140 return pPixmap;
141}
142
143/** Destroy the pixmap on the back-end server. */
144Bool
145dmxBEFreePixmap(PixmapPtr pPixmap)
146{
147 ScreenPtr pScreen = pPixmap->drawable.pScreen;
148 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
149 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
150
151 if (pPixPriv->pixmap) {
152 XFreePixmap(dmxScreen->beDisplay, pPixPriv->pixmap);
153 pPixPriv->pixmap = (Pixmap) 0;
154 return TRUE;
155 }
156
157 return FALSE;
158}
159
160/** Destroy the pixmap pointed to by \a pPixmap. */
161Bool
162dmxDestroyPixmap(PixmapPtr pPixmap)
163{
164 ScreenPtr pScreen = pPixmap->drawable.pScreen;
165 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
166 Bool ret = TRUE;
167
168#if 0
169 DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
170#endif
171
172 if (--pPixmap->refcnt)
173 return TRUE;
174
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);
180
181 if (pPixPriv->detachedImage)
182 XDestroyImage(pPixPriv->detachedImage);
183 dmxSync(dmxScreen, FALSE);
184 }
185 }
186 FreePixmap(pPixmap);
187
188#if 0
189 if (pScreen->DestroyPixmap)
190 ret = pScreen->DestroyPixmap(pPixmap);
191 DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
192#endif
193
194 return ret;
195}
196
197/** Create and return a region based on the pixmap pointed to by \a
198 * pPixmap. */
199RegionPtr
200dmxBitmapToRegion(PixmapPtr pPixmap)
201{
202 DMXScreenInfo *dmxScreen = &dmxScreens[pPixmap->drawable.pScreen->myNum];
203 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
204 XImage *ximage;
205 RegionPtr pReg, pTmpReg;
206 int x, y;
207 unsigned long previousPixel, currentPixel;
208 BoxRec Box;
209 Bool overlap;
210
211 if (!dmxScreen->beDisplay) {
212 pReg = RegionCreate(NullBox, 1);
213 return pReg;
214 }
215
216 ximage = XGetImage(dmxScreen->beDisplay, pPixPriv->pixmap, 0, 0,
217 pPixmap->drawable.width, pPixmap->drawable.height,
218 1, XYPixmap);
219
220 pReg = RegionCreate(NullBox, 1);
221 pTmpReg = RegionCreate(NullBox, 1);
222 if (!pReg || !pTmpReg) {
223 XDestroyImage(ximage);
224 return NullRegion;
225 }
226
227 for (y = 0; y < pPixmap->drawable.height; y++) {
228 Box.y1 = y;
229 Box.y2 = y + 1;
230 previousPixel = 0L;
231 for (x = 0; x < pPixmap->drawable.width; x++) {
232 currentPixel = XGetPixel(ximage, x, y);
233 if (previousPixel != currentPixel) {
234 if (previousPixel == 0L) {
235 /* left edge */
236 Box.x1 = x;
237 }
238 else if (currentPixel == 0L) {
239 /* right edge */
240 Box.x2 = x;
241 RegionReset(pTmpReg, &Box);
242 RegionAppend(pReg, pTmpReg);
243 }
244 previousPixel = currentPixel;
245 }
246 }
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);
252 }
253 }
254
255 RegionDestroy(pTmpReg);
256 XDestroyImage(ximage);
257
258 RegionValidate(pReg, &overlap);
259
260 dmxSync(dmxScreen, FALSE);
261 return pReg;
262}