xref: /OK3568_Linux_fs/external/xserver/hw/dmx/dmxpixmap.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * All Rights Reserved.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining
7*4882a593Smuzhiyun  * a copy of this software and associated documentation files (the
8*4882a593Smuzhiyun  * "Software"), to deal in the Software without restriction, including
9*4882a593Smuzhiyun  * without limitation on the rights to use, copy, modify, merge,
10*4882a593Smuzhiyun  * publish, distribute, sublicense, and/or sell copies of the Software,
11*4882a593Smuzhiyun  * and to permit persons to whom the Software is furnished to do so,
12*4882a593Smuzhiyun  * subject to the following conditions:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the
15*4882a593Smuzhiyun  * next paragraph) shall be included in all copies or substantial
16*4882a593Smuzhiyun  * portions of the Software.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*4882a593Smuzhiyun  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22*4882a593Smuzhiyun  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23*4882a593Smuzhiyun  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25*4882a593Smuzhiyun  * SOFTWARE.
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun  * Authors:
30*4882a593Smuzhiyun  *   Kevin E. Martin <kem@redhat.com>
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /** \file
35*4882a593Smuzhiyun  * Provides pixmap support. */
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #ifdef HAVE_DMX_CONFIG_H
38*4882a593Smuzhiyun #include <dmx-config.h>
39*4882a593Smuzhiyun #endif
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include "dmx.h"
42*4882a593Smuzhiyun #include "dmxsync.h"
43*4882a593Smuzhiyun #include "dmxpixmap.h"
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #include "pixmapstr.h"
46*4882a593Smuzhiyun #include "servermd.h"
47*4882a593Smuzhiyun #include "privates.h"
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun /** Initialize a private area in \a pScreen for pixmap information. */
50*4882a593Smuzhiyun Bool
dmxInitPixmap(ScreenPtr pScreen)51*4882a593Smuzhiyun dmxInitPixmap(ScreenPtr pScreen)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun     if (!dixRegisterPrivateKey
54*4882a593Smuzhiyun         (&dmxPixPrivateKeyRec, PRIVATE_PIXMAP, sizeof(dmxPixPrivRec)))
55*4882a593Smuzhiyun         return FALSE;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun     return TRUE;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /** Create a pixmap on the back-end server. */
61*4882a593Smuzhiyun void
dmxBECreatePixmap(PixmapPtr pPixmap)62*4882a593Smuzhiyun dmxBECreatePixmap(PixmapPtr pPixmap)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun     ScreenPtr pScreen = pPixmap->drawable.pScreen;
65*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
66*4882a593Smuzhiyun     dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun     /* Make sure we haven't already created this pixmap.  This can
69*4882a593Smuzhiyun      * happen when the pixmap is used elsewhere (e.g., as a background
70*4882a593Smuzhiyun      * or border for a window) and the refcnt > 1.
71*4882a593Smuzhiyun      */
72*4882a593Smuzhiyun     if (pPixPriv->pixmap)
73*4882a593Smuzhiyun         return;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun     if (pPixmap->drawable.width && pPixmap->drawable.height) {
76*4882a593Smuzhiyun         pPixPriv->pixmap = XCreatePixmap(dmxScreen->beDisplay,
77*4882a593Smuzhiyun                                          dmxScreen->scrnWin,
78*4882a593Smuzhiyun                                          pPixmap->drawable.width,
79*4882a593Smuzhiyun                                          pPixmap->drawable.height,
80*4882a593Smuzhiyun                                          pPixmap->drawable.depth);
81*4882a593Smuzhiyun         dmxSync(dmxScreen, FALSE);
82*4882a593Smuzhiyun     }
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun /** Create a pixmap for \a pScreen with the specified \a width, \a
86*4882a593Smuzhiyun  *  height, and \a depth. */
87*4882a593Smuzhiyun PixmapPtr
dmxCreatePixmap(ScreenPtr pScreen,int width,int height,int depth,unsigned usage_hint)88*4882a593Smuzhiyun dmxCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
89*4882a593Smuzhiyun                 unsigned usage_hint)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
92*4882a593Smuzhiyun     PixmapPtr pPixmap;
93*4882a593Smuzhiyun     int bpp;
94*4882a593Smuzhiyun     dmxPixPrivPtr pPixPriv;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun #if 0
97*4882a593Smuzhiyun     DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
98*4882a593Smuzhiyun     if (pScreen->CreatePixmap)
99*4882a593Smuzhiyun         ret = pScreen->CreatePixmap(pPixmap);
100*4882a593Smuzhiyun #endif
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun     /* Create pixmap on back-end server */
103*4882a593Smuzhiyun     if (depth == 24)
104*4882a593Smuzhiyun         bpp = 32;
105*4882a593Smuzhiyun     else
106*4882a593Smuzhiyun         bpp = depth;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun     pPixmap = AllocatePixmap(pScreen, 0);
109*4882a593Smuzhiyun     if (!pPixmap)
110*4882a593Smuzhiyun         return NullPixmap;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun     pPixmap->drawable.type = DRAWABLE_PIXMAP;
113*4882a593Smuzhiyun     pPixmap->drawable.class = 0;
114*4882a593Smuzhiyun     pPixmap->drawable.pScreen = pScreen;
115*4882a593Smuzhiyun     pPixmap->drawable.depth = depth;
116*4882a593Smuzhiyun     pPixmap->drawable.bitsPerPixel = bpp;
117*4882a593Smuzhiyun     pPixmap->drawable.id = 0;
118*4882a593Smuzhiyun     pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
119*4882a593Smuzhiyun     pPixmap->drawable.x = 0;
120*4882a593Smuzhiyun     pPixmap->drawable.y = 0;
121*4882a593Smuzhiyun     pPixmap->drawable.width = width;
122*4882a593Smuzhiyun     pPixmap->drawable.height = height;
123*4882a593Smuzhiyun     pPixmap->devKind = PixmapBytePad(width, bpp);
124*4882a593Smuzhiyun     pPixmap->refcnt = 1;
125*4882a593Smuzhiyun     pPixmap->usage_hint = usage_hint;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun     pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
128*4882a593Smuzhiyun     pPixPriv->pixmap = (Pixmap) 0;
129*4882a593Smuzhiyun     pPixPriv->detachedImage = NULL;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     /* Create the pixmap on the back-end server */
132*4882a593Smuzhiyun     if (dmxScreen->beDisplay) {
133*4882a593Smuzhiyun         dmxBECreatePixmap(pPixmap);
134*4882a593Smuzhiyun     }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun #if 0
137*4882a593Smuzhiyun     DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
138*4882a593Smuzhiyun #endif
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun     return pPixmap;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun /** Destroy the pixmap on the back-end server. */
144*4882a593Smuzhiyun Bool
dmxBEFreePixmap(PixmapPtr pPixmap)145*4882a593Smuzhiyun dmxBEFreePixmap(PixmapPtr pPixmap)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun     ScreenPtr pScreen = pPixmap->drawable.pScreen;
148*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
149*4882a593Smuzhiyun     dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun     if (pPixPriv->pixmap) {
152*4882a593Smuzhiyun         XFreePixmap(dmxScreen->beDisplay, pPixPriv->pixmap);
153*4882a593Smuzhiyun         pPixPriv->pixmap = (Pixmap) 0;
154*4882a593Smuzhiyun         return TRUE;
155*4882a593Smuzhiyun     }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun     return FALSE;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun /** Destroy the pixmap pointed to by \a pPixmap. */
161*4882a593Smuzhiyun Bool
dmxDestroyPixmap(PixmapPtr pPixmap)162*4882a593Smuzhiyun dmxDestroyPixmap(PixmapPtr pPixmap)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun     ScreenPtr pScreen = pPixmap->drawable.pScreen;
165*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
166*4882a593Smuzhiyun     Bool ret = TRUE;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun #if 0
169*4882a593Smuzhiyun     DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
170*4882a593Smuzhiyun #endif
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun     if (--pPixmap->refcnt)
173*4882a593Smuzhiyun         return TRUE;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun     /* Destroy pixmap on back-end server */
176*4882a593Smuzhiyun     if (dmxScreen->beDisplay) {
177*4882a593Smuzhiyun         if (dmxBEFreePixmap(pPixmap)) {
178*4882a593Smuzhiyun             /* Also make sure that we destroy any detached image */
179*4882a593Smuzhiyun             dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun             if (pPixPriv->detachedImage)
182*4882a593Smuzhiyun                 XDestroyImage(pPixPriv->detachedImage);
183*4882a593Smuzhiyun             dmxSync(dmxScreen, FALSE);
184*4882a593Smuzhiyun         }
185*4882a593Smuzhiyun     }
186*4882a593Smuzhiyun     FreePixmap(pPixmap);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun #if 0
189*4882a593Smuzhiyun     if (pScreen->DestroyPixmap)
190*4882a593Smuzhiyun         ret = pScreen->DestroyPixmap(pPixmap);
191*4882a593Smuzhiyun     DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
192*4882a593Smuzhiyun #endif
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun     return ret;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun /** Create and return a region based on the pixmap pointed to by \a
198*4882a593Smuzhiyun  *  pPixmap. */
199*4882a593Smuzhiyun RegionPtr
dmxBitmapToRegion(PixmapPtr pPixmap)200*4882a593Smuzhiyun dmxBitmapToRegion(PixmapPtr pPixmap)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pPixmap->drawable.pScreen->myNum];
203*4882a593Smuzhiyun     dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
204*4882a593Smuzhiyun     XImage *ximage;
205*4882a593Smuzhiyun     RegionPtr pReg, pTmpReg;
206*4882a593Smuzhiyun     int x, y;
207*4882a593Smuzhiyun     unsigned long previousPixel, currentPixel;
208*4882a593Smuzhiyun     BoxRec Box = { 0, };
209*4882a593Smuzhiyun     Bool overlap;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun     if (!dmxScreen->beDisplay) {
212*4882a593Smuzhiyun         pReg = RegionCreate(NullBox, 1);
213*4882a593Smuzhiyun         return pReg;
214*4882a593Smuzhiyun     }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun     ximage = XGetImage(dmxScreen->beDisplay, pPixPriv->pixmap, 0, 0,
217*4882a593Smuzhiyun                        pPixmap->drawable.width, pPixmap->drawable.height,
218*4882a593Smuzhiyun                        1, XYPixmap);
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun     pReg = RegionCreate(NullBox, 1);
221*4882a593Smuzhiyun     pTmpReg = RegionCreate(NullBox, 1);
222*4882a593Smuzhiyun     if (!pReg || !pTmpReg) {
223*4882a593Smuzhiyun         XDestroyImage(ximage);
224*4882a593Smuzhiyun         return NullRegion;
225*4882a593Smuzhiyun     }
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun     for (y = 0; y < pPixmap->drawable.height; y++) {
228*4882a593Smuzhiyun         Box.y1 = y;
229*4882a593Smuzhiyun         Box.y2 = y + 1;
230*4882a593Smuzhiyun         previousPixel = 0L;
231*4882a593Smuzhiyun         for (x = 0; x < pPixmap->drawable.width; x++) {
232*4882a593Smuzhiyun             currentPixel = XGetPixel(ximage, x, y);
233*4882a593Smuzhiyun             if (previousPixel != currentPixel) {
234*4882a593Smuzhiyun                 if (previousPixel == 0L) {
235*4882a593Smuzhiyun                     /* left edge */
236*4882a593Smuzhiyun                     Box.x1 = x;
237*4882a593Smuzhiyun                 }
238*4882a593Smuzhiyun                 else if (currentPixel == 0L) {
239*4882a593Smuzhiyun                     /* right edge */
240*4882a593Smuzhiyun                     Box.x2 = x;
241*4882a593Smuzhiyun                     RegionReset(pTmpReg, &Box);
242*4882a593Smuzhiyun                     RegionAppend(pReg, pTmpReg);
243*4882a593Smuzhiyun                 }
244*4882a593Smuzhiyun                 previousPixel = currentPixel;
245*4882a593Smuzhiyun             }
246*4882a593Smuzhiyun         }
247*4882a593Smuzhiyun         if (previousPixel != 0L) {
248*4882a593Smuzhiyun             /* right edge because of the end of pixmap */
249*4882a593Smuzhiyun             Box.x2 = pPixmap->drawable.width;
250*4882a593Smuzhiyun             RegionReset(pTmpReg, &Box);
251*4882a593Smuzhiyun             RegionAppend(pReg, pTmpReg);
252*4882a593Smuzhiyun         }
253*4882a593Smuzhiyun     }
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun     RegionDestroy(pTmpReg);
256*4882a593Smuzhiyun     XDestroyImage(ximage);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun     RegionValidate(pReg, &overlap);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun     dmxSync(dmxScreen, FALSE);
261*4882a593Smuzhiyun     return pReg;
262*4882a593Smuzhiyun }
263