dmxpixmap.c revision 706f2543
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 dmxInitPixmap(ScreenPtr pScreen) 51{ 52 if (!dixRegisterPrivateKey(&dmxPixPrivateKeyRec, PRIVATE_PIXMAP, sizeof(dmxPixPrivRec))) 53 return FALSE; 54 55 return TRUE; 56} 57 58/** Create a pixmap on the back-end server. */ 59void dmxBECreatePixmap(PixmapPtr pPixmap) 60{ 61 ScreenPtr pScreen = pPixmap->drawable.pScreen; 62 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 63 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); 64 65 /* Make sure we haven't already created this pixmap. This can 66 * happen when the pixmap is used elsewhere (e.g., as a background 67 * or border for a window) and the refcnt > 1. 68 */ 69 if (pPixPriv->pixmap) 70 return; 71 72 if (pPixmap->drawable.width && pPixmap->drawable.height) { 73 pPixPriv->pixmap = XCreatePixmap(dmxScreen->beDisplay, 74 dmxScreen->scrnWin, 75 pPixmap->drawable.width, 76 pPixmap->drawable.height, 77 pPixmap->drawable.depth); 78 dmxSync(dmxScreen, FALSE); 79 } 80} 81 82/** Create a pixmap for \a pScreen with the specified \a width, \a 83 * height, and \a depth. */ 84PixmapPtr dmxCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, 85 unsigned usage_hint) 86{ 87 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 88 PixmapPtr pPixmap; 89 int bpp; 90 dmxPixPrivPtr pPixPriv; 91 92#if 0 93 DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen); 94 if (pScreen->CreatePixmap) 95 ret = pScreen->CreatePixmap(pPixmap); 96#endif 97 98 /* Create pixmap on back-end server */ 99 if (depth == 24) bpp = 32; 100 else bpp = depth; 101 102 pPixmap = AllocatePixmap(pScreen, 0); 103 if (!pPixmap) 104 return NullPixmap; 105 106 pPixmap->drawable.type = DRAWABLE_PIXMAP; 107 pPixmap->drawable.class = 0; 108 pPixmap->drawable.pScreen = pScreen; 109 pPixmap->drawable.depth = depth; 110 pPixmap->drawable.bitsPerPixel = bpp; 111 pPixmap->drawable.id = 0; 112 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 113 pPixmap->drawable.x = 0; 114 pPixmap->drawable.y = 0; 115 pPixmap->drawable.width = width; 116 pPixmap->drawable.height = height; 117 pPixmap->devKind = PixmapBytePad(width, bpp); 118 pPixmap->refcnt = 1; 119 pPixmap->usage_hint = usage_hint; 120 121 pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); 122 pPixPriv->pixmap = (Pixmap)0; 123 pPixPriv->detachedImage = NULL; 124 125 /* Create the pixmap on the back-end server */ 126 if (dmxScreen->beDisplay) { 127 dmxBECreatePixmap(pPixmap); 128 } 129 130#if 0 131 DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen); 132#endif 133 134 return pPixmap; 135} 136 137/** Destroy the pixmap on the back-end server. */ 138Bool dmxBEFreePixmap(PixmapPtr pPixmap) 139{ 140 ScreenPtr pScreen = pPixmap->drawable.pScreen; 141 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 142 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); 143 144 if (pPixPriv->pixmap) { 145 XFreePixmap(dmxScreen->beDisplay, pPixPriv->pixmap); 146 pPixPriv->pixmap = (Pixmap)0; 147 return TRUE; 148 } 149 150 return FALSE; 151} 152 153/** Destroy the pixmap pointed to by \a pPixmap. */ 154Bool dmxDestroyPixmap(PixmapPtr pPixmap) 155{ 156 ScreenPtr pScreen = pPixmap->drawable.pScreen; 157 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 158 Bool ret = TRUE; 159 160#if 0 161 DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen); 162#endif 163 164 if (--pPixmap->refcnt) 165 return TRUE; 166 167 /* Destroy pixmap on back-end server */ 168 if (dmxScreen->beDisplay) { 169 if (dmxBEFreePixmap(pPixmap)) { 170 /* Also make sure that we destroy any detached image */ 171 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); 172 if (pPixPriv->detachedImage) 173 XDestroyImage(pPixPriv->detachedImage); 174 dmxSync(dmxScreen, FALSE); 175 } 176 } 177 FreePixmap(pPixmap); 178 179#if 0 180 if (pScreen->DestroyPixmap) 181 ret = pScreen->DestroyPixmap(pPixmap); 182 DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen); 183#endif 184 185 return ret; 186} 187 188/** Create and return a region based on the pixmap pointed to by \a 189 * pPixmap. */ 190RegionPtr dmxBitmapToRegion(PixmapPtr pPixmap) 191{ 192 DMXScreenInfo *dmxScreen = &dmxScreens[pPixmap->drawable.pScreen->myNum]; 193 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); 194 XImage *ximage; 195 RegionPtr pReg, pTmpReg; 196 int x, y; 197 unsigned long previousPixel, currentPixel; 198 BoxRec Box; 199 Bool overlap; 200 201 if (!dmxScreen->beDisplay) { 202 pReg = RegionCreate(NullBox, 1); 203 return pReg; 204 } 205 206 ximage = XGetImage(dmxScreen->beDisplay, pPixPriv->pixmap, 0, 0, 207 pPixmap->drawable.width, pPixmap->drawable.height, 208 1, XYPixmap); 209 210 pReg = RegionCreate(NullBox, 1); 211 pTmpReg = RegionCreate(NullBox, 1); 212 if(!pReg || !pTmpReg) { 213 XDestroyImage(ximage); 214 return NullRegion; 215 } 216 217 for (y = 0; y < pPixmap->drawable.height; y++) { 218 Box.y1 = y; 219 Box.y2 = y + 1; 220 previousPixel = 0L; 221 for (x = 0; x < pPixmap->drawable.width; x++) { 222 currentPixel = XGetPixel(ximage, x, y); 223 if (previousPixel != currentPixel) { 224 if (previousPixel == 0L) { 225 /* left edge */ 226 Box.x1 = x; 227 } else if (currentPixel == 0L) { 228 /* right edge */ 229 Box.x2 = x; 230 RegionReset(pTmpReg, &Box); 231 RegionAppend(pReg, pTmpReg); 232 } 233 previousPixel = currentPixel; 234 } 235 } 236 if (previousPixel != 0L) { 237 /* right edge because of the end of pixmap */ 238 Box.x2 = pPixmap->drawable.width; 239 RegionReset(pTmpReg, &Box); 240 RegionAppend(pReg, pTmpReg); 241 } 242 } 243 244 RegionDestroy(pTmpReg); 245 XDestroyImage(ximage); 246 247 RegionValidate(pReg, &overlap); 248 249 dmxSync(dmxScreen, FALSE); 250 return pReg; 251} 252