1/* 2 * 3 * Copyright © 2000 SuSE, Inc. 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of SuSE not be used in advertising or 10 * publicity pertaining to distribution of the software without specific, 11 * written prior permission. SuSE makes no representations about the 12 * suitability of this software for any purpose. It is provided "as is" 13 * without express or implied warranty. 14 * 15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Author: Keith Packard, SuSE, Inc. 23 */ 24 25 26#ifdef HAVE_DIX_CONFIG_H 27#include <dix-config.h> 28#endif 29 30#include <stdlib.h> 31 32#include "fb.h" 33#include "fboverlay.h" 34#include "shmint.h" 35 36static DevPrivateKeyRec fbOverlayScreenPrivateKeyRec; 37#define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec) 38 39DevPrivateKey fbOverlayGetScreenPrivateKey(void) 40{ 41 return fbOverlayScreenPrivateKey; 42} 43 44/* 45 * Replace this if you want something supporting 46 * multiple overlays with the same depth 47 */ 48Bool 49fbOverlayCreateWindow(WindowPtr pWin) 50{ 51 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); 52 int i; 53 PixmapPtr pPixmap; 54 55 if (pWin->drawable.class != InputOutput) 56 return TRUE; 57 58#ifdef FB_SCREEN_PRIVATE 59 if (pWin->drawable.bitsPerPixel == 32) 60 pWin->drawable.bitsPerPixel = fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp; 61#endif 62 63 for (i = 0; i < pScrPriv->nlayers; i++) 64 { 65 pPixmap = pScrPriv->layer[i].u.run.pixmap; 66 if (pWin->drawable.depth == pPixmap->drawable.depth) 67 { 68 dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(), pPixmap); 69 /* 70 * Make sure layer keys are written correctly by 71 * having non-root layers set to full while the 72 * root layer is set to empty. This will cause 73 * all of the layers to get painted when the root 74 * is mapped 75 */ 76 if (!pWin->parent) 77 { 78 RegionEmpty(&pScrPriv->layer[i].u.run.region); 79 } 80 return TRUE; 81 } 82 } 83 return FALSE; 84} 85 86Bool 87fbOverlayCloseScreen (int iScreen, ScreenPtr pScreen) 88{ 89 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 90 int i; 91 92 for (i = 0; i < pScrPriv->nlayers; i++) 93 { 94 (*pScreen->DestroyPixmap)(pScrPriv->layer[i].u.run.pixmap); 95 RegionUninit(&pScrPriv->layer[i].u.run.region); 96 } 97 return TRUE; 98} 99 100/* 101 * Return layer containing this window 102 */ 103int 104fbOverlayWindowLayer(WindowPtr pWin) 105{ 106 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); 107 int i; 108 109 for (i = 0; i < pScrPriv->nlayers; i++) 110 if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey()) == 111 (pointer) pScrPriv->layer[i].u.run.pixmap) 112 return i; 113 return 0; 114} 115 116Bool 117fbOverlayCreateScreenResources(ScreenPtr pScreen) 118{ 119 int i; 120 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 121 PixmapPtr pPixmap; 122 pointer pbits; 123 int width; 124 int depth; 125 BoxRec box; 126 127 if (!miCreateScreenResources(pScreen)) 128 return FALSE; 129 130 box.x1 = 0; 131 box.y1 = 0; 132 box.x2 = pScreen->width; 133 box.y2 = pScreen->height; 134 for (i = 0; i < pScrPriv->nlayers; i++) 135 { 136 pbits = pScrPriv->layer[i].u.init.pbits; 137 width = pScrPriv->layer[i].u.init.width; 138 depth = pScrPriv->layer[i].u.init.depth; 139 pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0); 140 if (!pPixmap) 141 return FALSE; 142 if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width, 143 pScreen->height, depth, 144 BitsPerPixel(depth), 145 PixmapBytePad(width, depth), 146 pbits)) 147 return FALSE; 148 pScrPriv->layer[i].u.run.pixmap = pPixmap; 149 RegionInit(&pScrPriv->layer[i].u.run.region, &box, 0); 150 } 151 pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap; 152 return TRUE; 153} 154 155void 156fbOverlayPaintKey (DrawablePtr pDrawable, 157 RegionPtr pRegion, 158 CARD32 pixel, 159 int layer) 160{ 161 fbFillRegionSolid (pDrawable, pRegion, 0, 162 fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); 163} 164 165/* 166 * Track visible region for each layer 167 */ 168void 169fbOverlayUpdateLayerRegion (ScreenPtr pScreen, 170 int layer, 171 RegionPtr prgn) 172{ 173 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 174 int i; 175 RegionRec rgnNew; 176 177 if (!prgn || !RegionNotEmpty(prgn)) 178 return; 179 for (i = 0; i < pScrPriv->nlayers; i++) 180 { 181 if (i == layer) 182 { 183 /* add new piece to this fb */ 184 RegionUnion(&pScrPriv->layer[i].u.run.region, 185 &pScrPriv->layer[i].u.run.region, 186 prgn); 187 } 188 else if (RegionNotEmpty(&pScrPriv->layer[i].u.run.region)) 189 { 190 /* paint new piece with chroma key */ 191 RegionNull(&rgnNew); 192 RegionIntersect(&rgnNew, prgn, 193 &pScrPriv->layer[i].u.run.region); 194 (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable, 195 &rgnNew, 196 pScrPriv->layer[i].key, 197 i); 198 RegionUninit(&rgnNew); 199 /* remove piece from other fbs */ 200 RegionSubtract(&pScrPriv->layer[i].u.run.region, 201 &pScrPriv->layer[i].u.run.region, 202 prgn); 203 } 204 } 205} 206 207/* 208 * Copy only areas in each layer containing real bits 209 */ 210void 211fbOverlayCopyWindow(WindowPtr pWin, 212 DDXPointRec ptOldOrg, 213 RegionPtr prgnSrc) 214{ 215 ScreenPtr pScreen = pWin->drawable.pScreen; 216 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 217 RegionRec rgnDst; 218 int dx, dy; 219 int i; 220 RegionRec layerRgn[FB_OVERLAY_MAX]; 221 PixmapPtr pPixmap; 222 223 dx = ptOldOrg.x - pWin->drawable.x; 224 dy = ptOldOrg.y - pWin->drawable.y; 225 226 /* 227 * Clip to existing bits 228 */ 229 RegionTranslate(prgnSrc, -dx, -dy); 230 RegionNull(&rgnDst); 231 RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 232 RegionTranslate(&rgnDst, dx, dy); 233 /* 234 * Compute the portion of each fb affected by this copy 235 */ 236 for (i = 0; i < pScrPriv->nlayers; i++) 237 { 238 RegionNull(&layerRgn[i]); 239 RegionIntersect(&layerRgn[i], &rgnDst, 240 &pScrPriv->layer[i].u.run.region); 241 if (RegionNotEmpty(&layerRgn[i])) 242 { 243 RegionTranslate(&layerRgn[i], -dx, -dy); 244 pPixmap = pScrPriv->layer[i].u.run.pixmap; 245 miCopyRegion (&pPixmap->drawable, &pPixmap->drawable, 246 0, 247 &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0, 248 (void *)(long) i); 249 } 250 } 251 /* 252 * Update regions 253 */ 254 for (i = 0; i < pScrPriv->nlayers; i++) 255 { 256 if (RegionNotEmpty(&layerRgn[i])) 257 fbOverlayUpdateLayerRegion (pScreen, i, &layerRgn[i]); 258 259 RegionUninit(&layerRgn[i]); 260 } 261 RegionUninit(&rgnDst); 262} 263 264void 265fbOverlayWindowExposures (WindowPtr pWin, 266 RegionPtr prgn, 267 RegionPtr other_exposed) 268{ 269 fbOverlayUpdateLayerRegion (pWin->drawable.pScreen, 270 fbOverlayWindowLayer (pWin), 271 prgn); 272 miWindowExposures(pWin, prgn, other_exposed); 273} 274 275Bool 276fbOverlaySetupScreen(ScreenPtr pScreen, 277 pointer pbits1, 278 pointer pbits2, 279 int xsize, 280 int ysize, 281 int dpix, 282 int dpiy, 283 int width1, 284 int width2, 285 int bpp1, 286 int bpp2) 287{ 288 return fbSetupScreen (pScreen, 289 pbits1, 290 xsize, 291 ysize, 292 dpix, 293 dpiy, 294 width1, 295 bpp1); 296} 297 298static Bool 299fb24_32OverlayCreateScreenResources(ScreenPtr pScreen) 300{ 301 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 302 int pitch; 303 Bool retval; 304 int i; 305 306 if((retval = fbOverlayCreateScreenResources(pScreen))) { 307 for (i = 0; i < pScrPriv->nlayers; i++) 308 { 309 /* fix the screen pixmap */ 310 PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap; 311 if (pPix->drawable.bitsPerPixel == 32) { 312 pPix->drawable.bitsPerPixel = 24; 313 pitch = BitmapBytePad(pPix->drawable.width * 24); 314 pPix->devKind = pitch; 315 } 316 } 317 } 318 319 return retval; 320} 321 322Bool 323fbOverlayFinishScreenInit(ScreenPtr pScreen, 324 pointer pbits1, 325 pointer pbits2, 326 int xsize, 327 int ysize, 328 int dpix, 329 int dpiy, 330 int width1, 331 int width2, 332 int bpp1, 333 int bpp2, 334 int depth1, 335 int depth2) 336{ 337 VisualPtr visuals; 338 DepthPtr depths; 339 int nvisuals; 340 int ndepths; 341 int bpp = 0, imagebpp = 32; 342 VisualID defaultVisual; 343 FbOverlayScrPrivPtr pScrPriv; 344 345 if (!dixRegisterPrivateKey(&fbOverlayScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 346 return FALSE; 347 348 pScrPriv = malloc(sizeof (FbOverlayScrPrivRec)); 349 if (!pScrPriv) 350 return FALSE; 351 352#ifdef FB_24_32BIT 353 if (bpp1 == 32 || bpp2 == 32) 354 bpp = 32; 355 else if (bpp1 == 24 || bpp2 == 24) 356 bpp = 24; 357 358 if (bpp == 24) 359 { 360 int f; 361 362 imagebpp = 32; 363 /* 364 * Check to see if we're advertising a 24bpp image format, 365 * in which case windows will use it in preference to a 32 bit 366 * format. 367 */ 368 for (f = 0; f < screenInfo.numPixmapFormats; f++) 369 { 370 if (screenInfo.formats[f].bitsPerPixel == 24) 371 { 372 imagebpp = 24; 373 break; 374 } 375 } 376 } 377#endif 378#ifdef FB_SCREEN_PRIVATE 379 if (imagebpp == 32) 380 { 381 fbGetScreenPrivate(pScreen)->win32bpp = bpp; 382 fbGetScreenPrivate(pScreen)->pix32bpp = bpp; 383 } 384 else 385 { 386 fbGetScreenPrivate(pScreen)->win32bpp = 32; 387 fbGetScreenPrivate(pScreen)->pix32bpp = 32; 388 } 389#endif 390 391 if (!fbInitVisuals (&visuals, &depths, &nvisuals, &ndepths, &depth1, 392 &defaultVisual, ((unsigned long)1<<(bpp1-1)) | 393 ((unsigned long)1<<(bpp2-1)), 8)) { 394 free(pScrPriv); 395 return FALSE; 396 } 397 if (! miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0, 398 depth1, ndepths, depths, 399 defaultVisual, nvisuals, visuals)) { 400 free(pScrPriv); 401 return FALSE; 402 } 403 /* MI thinks there's no frame buffer */ 404#ifdef MITSHM 405 ShmRegisterFbFuncs(pScreen); 406#endif 407 pScreen->minInstalledCmaps = 1; 408 pScreen->maxInstalledCmaps = 2; 409 410 pScrPriv->nlayers = 2; 411 pScrPriv->PaintKey = fbOverlayPaintKey; 412 pScrPriv->CopyWindow = fbCopyWindowProc; 413 pScrPriv->layer[0].u.init.pbits = pbits1; 414 pScrPriv->layer[0].u.init.width = width1; 415 pScrPriv->layer[0].u.init.depth = depth1; 416 417 pScrPriv->layer[1].u.init.pbits = pbits2; 418 pScrPriv->layer[1].u.init.width = width2; 419 pScrPriv->layer[1].u.init.depth = depth2; 420 dixSetPrivate(&pScreen->devPrivates, fbOverlayScreenPrivateKey, pScrPriv); 421 422 /* overwrite miCloseScreen with our own */ 423 pScreen->CloseScreen = fbOverlayCloseScreen; 424 pScreen->CreateScreenResources = fbOverlayCreateScreenResources; 425 pScreen->CreateWindow = fbOverlayCreateWindow; 426 pScreen->WindowExposures = fbOverlayWindowExposures; 427 pScreen->CopyWindow = fbOverlayCopyWindow; 428#ifdef FB_24_32BIT 429 if (bpp == 24 && imagebpp == 32) 430 { 431 pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader; 432 pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources; 433 } 434#endif 435 436 return TRUE; 437} 438