1706f2543Smrg/* 2706f2543Smrg * 3706f2543Smrg * Copyright © 2000 SuSE, Inc. 4706f2543Smrg * 5706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 7706f2543Smrg * the above copyright notice appear in all copies and that both that 8706f2543Smrg * copyright notice and this permission notice appear in supporting 9706f2543Smrg * documentation, and that the name of SuSE not be used in advertising or 10706f2543Smrg * publicity pertaining to distribution of the software without specific, 11706f2543Smrg * written prior permission. SuSE makes no representations about the 12706f2543Smrg * suitability of this software for any purpose. It is provided "as is" 13706f2543Smrg * without express or implied warranty. 14706f2543Smrg * 15706f2543Smrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 16706f2543Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 17706f2543Smrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18706f2543Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 19706f2543Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 20706f2543Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21706f2543Smrg * 22706f2543Smrg * Author: Keith Packard, SuSE, Inc. 23706f2543Smrg */ 24706f2543Smrg 25706f2543Smrg 26706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 27706f2543Smrg#include <dix-config.h> 28706f2543Smrg#endif 29706f2543Smrg 30706f2543Smrg#include <stdlib.h> 31706f2543Smrg 32706f2543Smrg#include "fb.h" 33706f2543Smrg#include "fboverlay.h" 34706f2543Smrg#include "shmint.h" 35706f2543Smrg 36706f2543Smrgstatic DevPrivateKeyRec fbOverlayScreenPrivateKeyRec; 37706f2543Smrg#define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec) 38706f2543Smrg 39706f2543SmrgDevPrivateKey fbOverlayGetScreenPrivateKey(void) 40706f2543Smrg{ 41706f2543Smrg return fbOverlayScreenPrivateKey; 42706f2543Smrg} 43706f2543Smrg 44706f2543Smrg/* 45706f2543Smrg * Replace this if you want something supporting 46706f2543Smrg * multiple overlays with the same depth 47706f2543Smrg */ 48706f2543SmrgBool 49706f2543SmrgfbOverlayCreateWindow(WindowPtr pWin) 50706f2543Smrg{ 51706f2543Smrg FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); 52706f2543Smrg int i; 53706f2543Smrg PixmapPtr pPixmap; 54706f2543Smrg 55706f2543Smrg if (pWin->drawable.class != InputOutput) 56706f2543Smrg return TRUE; 57706f2543Smrg 58706f2543Smrg#ifdef FB_SCREEN_PRIVATE 59706f2543Smrg if (pWin->drawable.bitsPerPixel == 32) 60706f2543Smrg pWin->drawable.bitsPerPixel = fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp; 61706f2543Smrg#endif 62706f2543Smrg 63706f2543Smrg for (i = 0; i < pScrPriv->nlayers; i++) 64706f2543Smrg { 65706f2543Smrg pPixmap = pScrPriv->layer[i].u.run.pixmap; 66706f2543Smrg if (pWin->drawable.depth == pPixmap->drawable.depth) 67706f2543Smrg { 68706f2543Smrg dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(), pPixmap); 69706f2543Smrg /* 70706f2543Smrg * Make sure layer keys are written correctly by 71706f2543Smrg * having non-root layers set to full while the 72706f2543Smrg * root layer is set to empty. This will cause 73706f2543Smrg * all of the layers to get painted when the root 74706f2543Smrg * is mapped 75706f2543Smrg */ 76706f2543Smrg if (!pWin->parent) 77706f2543Smrg { 78706f2543Smrg RegionEmpty(&pScrPriv->layer[i].u.run.region); 79706f2543Smrg } 80706f2543Smrg return TRUE; 81706f2543Smrg } 82706f2543Smrg } 83706f2543Smrg return FALSE; 84706f2543Smrg} 85706f2543Smrg 86706f2543SmrgBool 87706f2543SmrgfbOverlayCloseScreen (int iScreen, ScreenPtr pScreen) 88706f2543Smrg{ 89706f2543Smrg FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 90706f2543Smrg int i; 91706f2543Smrg 92706f2543Smrg for (i = 0; i < pScrPriv->nlayers; i++) 93706f2543Smrg { 94706f2543Smrg (*pScreen->DestroyPixmap)(pScrPriv->layer[i].u.run.pixmap); 95706f2543Smrg RegionUninit(&pScrPriv->layer[i].u.run.region); 96706f2543Smrg } 97706f2543Smrg return TRUE; 98706f2543Smrg} 99706f2543Smrg 100706f2543Smrg/* 101706f2543Smrg * Return layer containing this window 102706f2543Smrg */ 103706f2543Smrgint 104706f2543SmrgfbOverlayWindowLayer(WindowPtr pWin) 105706f2543Smrg{ 106706f2543Smrg FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); 107706f2543Smrg int i; 108706f2543Smrg 109706f2543Smrg for (i = 0; i < pScrPriv->nlayers; i++) 110706f2543Smrg if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey()) == 111706f2543Smrg (pointer) pScrPriv->layer[i].u.run.pixmap) 112706f2543Smrg return i; 113706f2543Smrg return 0; 114706f2543Smrg} 115706f2543Smrg 116706f2543SmrgBool 117706f2543SmrgfbOverlayCreateScreenResources(ScreenPtr pScreen) 118706f2543Smrg{ 119706f2543Smrg int i; 120706f2543Smrg FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 121706f2543Smrg PixmapPtr pPixmap; 122706f2543Smrg pointer pbits; 123706f2543Smrg int width; 124706f2543Smrg int depth; 125706f2543Smrg BoxRec box; 126706f2543Smrg 127706f2543Smrg if (!miCreateScreenResources(pScreen)) 128706f2543Smrg return FALSE; 129706f2543Smrg 130706f2543Smrg box.x1 = 0; 131706f2543Smrg box.y1 = 0; 132706f2543Smrg box.x2 = pScreen->width; 133706f2543Smrg box.y2 = pScreen->height; 134706f2543Smrg for (i = 0; i < pScrPriv->nlayers; i++) 135706f2543Smrg { 136706f2543Smrg pbits = pScrPriv->layer[i].u.init.pbits; 137706f2543Smrg width = pScrPriv->layer[i].u.init.width; 138706f2543Smrg depth = pScrPriv->layer[i].u.init.depth; 139706f2543Smrg pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0); 140706f2543Smrg if (!pPixmap) 141706f2543Smrg return FALSE; 142706f2543Smrg if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width, 143706f2543Smrg pScreen->height, depth, 144706f2543Smrg BitsPerPixel(depth), 145706f2543Smrg PixmapBytePad(width, depth), 146706f2543Smrg pbits)) 147706f2543Smrg return FALSE; 148706f2543Smrg pScrPriv->layer[i].u.run.pixmap = pPixmap; 149706f2543Smrg RegionInit(&pScrPriv->layer[i].u.run.region, &box, 0); 150706f2543Smrg } 151706f2543Smrg pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap; 152706f2543Smrg return TRUE; 153706f2543Smrg} 154706f2543Smrg 155706f2543Smrgvoid 156706f2543SmrgfbOverlayPaintKey (DrawablePtr pDrawable, 157706f2543Smrg RegionPtr pRegion, 158706f2543Smrg CARD32 pixel, 159706f2543Smrg int layer) 160706f2543Smrg{ 161706f2543Smrg fbFillRegionSolid (pDrawable, pRegion, 0, 162706f2543Smrg fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); 163706f2543Smrg} 164706f2543Smrg 165706f2543Smrg/* 166706f2543Smrg * Track visible region for each layer 167706f2543Smrg */ 168706f2543Smrgvoid 169706f2543SmrgfbOverlayUpdateLayerRegion (ScreenPtr pScreen, 170706f2543Smrg int layer, 171706f2543Smrg RegionPtr prgn) 172706f2543Smrg{ 173706f2543Smrg FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 174706f2543Smrg int i; 175706f2543Smrg RegionRec rgnNew; 176706f2543Smrg 177706f2543Smrg if (!prgn || !RegionNotEmpty(prgn)) 178706f2543Smrg return; 179706f2543Smrg for (i = 0; i < pScrPriv->nlayers; i++) 180706f2543Smrg { 181706f2543Smrg if (i == layer) 182706f2543Smrg { 183706f2543Smrg /* add new piece to this fb */ 184706f2543Smrg RegionUnion(&pScrPriv->layer[i].u.run.region, 185706f2543Smrg &pScrPriv->layer[i].u.run.region, 186706f2543Smrg prgn); 187706f2543Smrg } 188706f2543Smrg else if (RegionNotEmpty(&pScrPriv->layer[i].u.run.region)) 189706f2543Smrg { 190706f2543Smrg /* paint new piece with chroma key */ 191706f2543Smrg RegionNull(&rgnNew); 192706f2543Smrg RegionIntersect(&rgnNew, prgn, 193706f2543Smrg &pScrPriv->layer[i].u.run.region); 194706f2543Smrg (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable, 195706f2543Smrg &rgnNew, 196706f2543Smrg pScrPriv->layer[i].key, 197706f2543Smrg i); 198706f2543Smrg RegionUninit(&rgnNew); 199706f2543Smrg /* remove piece from other fbs */ 200706f2543Smrg RegionSubtract(&pScrPriv->layer[i].u.run.region, 201706f2543Smrg &pScrPriv->layer[i].u.run.region, 202706f2543Smrg prgn); 203706f2543Smrg } 204706f2543Smrg } 205706f2543Smrg} 206706f2543Smrg 207706f2543Smrg/* 208706f2543Smrg * Copy only areas in each layer containing real bits 209706f2543Smrg */ 210706f2543Smrgvoid 211706f2543SmrgfbOverlayCopyWindow(WindowPtr pWin, 212706f2543Smrg DDXPointRec ptOldOrg, 213706f2543Smrg RegionPtr prgnSrc) 214706f2543Smrg{ 215706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 216706f2543Smrg FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 217706f2543Smrg RegionRec rgnDst; 218706f2543Smrg int dx, dy; 219706f2543Smrg int i; 220706f2543Smrg RegionRec layerRgn[FB_OVERLAY_MAX]; 221706f2543Smrg PixmapPtr pPixmap; 222706f2543Smrg 223706f2543Smrg dx = ptOldOrg.x - pWin->drawable.x; 224706f2543Smrg dy = ptOldOrg.y - pWin->drawable.y; 225706f2543Smrg 226706f2543Smrg /* 227706f2543Smrg * Clip to existing bits 228706f2543Smrg */ 229706f2543Smrg RegionTranslate(prgnSrc, -dx, -dy); 230706f2543Smrg RegionNull(&rgnDst); 231706f2543Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 232706f2543Smrg RegionTranslate(&rgnDst, dx, dy); 233706f2543Smrg /* 234706f2543Smrg * Compute the portion of each fb affected by this copy 235706f2543Smrg */ 236706f2543Smrg for (i = 0; i < pScrPriv->nlayers; i++) 237706f2543Smrg { 238706f2543Smrg RegionNull(&layerRgn[i]); 239706f2543Smrg RegionIntersect(&layerRgn[i], &rgnDst, 240706f2543Smrg &pScrPriv->layer[i].u.run.region); 241706f2543Smrg if (RegionNotEmpty(&layerRgn[i])) 242706f2543Smrg { 243706f2543Smrg RegionTranslate(&layerRgn[i], -dx, -dy); 244706f2543Smrg pPixmap = pScrPriv->layer[i].u.run.pixmap; 245706f2543Smrg miCopyRegion (&pPixmap->drawable, &pPixmap->drawable, 246706f2543Smrg 0, 247706f2543Smrg &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0, 248706f2543Smrg (void *)(long) i); 249706f2543Smrg } 250706f2543Smrg } 251706f2543Smrg /* 252706f2543Smrg * Update regions 253706f2543Smrg */ 254706f2543Smrg for (i = 0; i < pScrPriv->nlayers; i++) 255706f2543Smrg { 256706f2543Smrg if (RegionNotEmpty(&layerRgn[i])) 257706f2543Smrg fbOverlayUpdateLayerRegion (pScreen, i, &layerRgn[i]); 258706f2543Smrg 259706f2543Smrg RegionUninit(&layerRgn[i]); 260706f2543Smrg } 261706f2543Smrg RegionUninit(&rgnDst); 262706f2543Smrg} 263706f2543Smrg 264706f2543Smrgvoid 265706f2543SmrgfbOverlayWindowExposures (WindowPtr pWin, 266706f2543Smrg RegionPtr prgn, 267706f2543Smrg RegionPtr other_exposed) 268706f2543Smrg{ 269706f2543Smrg fbOverlayUpdateLayerRegion (pWin->drawable.pScreen, 270706f2543Smrg fbOverlayWindowLayer (pWin), 271706f2543Smrg prgn); 272706f2543Smrg miWindowExposures(pWin, prgn, other_exposed); 273706f2543Smrg} 274706f2543Smrg 275706f2543SmrgBool 276706f2543SmrgfbOverlaySetupScreen(ScreenPtr pScreen, 277706f2543Smrg pointer pbits1, 278706f2543Smrg pointer pbits2, 279706f2543Smrg int xsize, 280706f2543Smrg int ysize, 281706f2543Smrg int dpix, 282706f2543Smrg int dpiy, 283706f2543Smrg int width1, 284706f2543Smrg int width2, 285706f2543Smrg int bpp1, 286706f2543Smrg int bpp2) 287706f2543Smrg{ 288706f2543Smrg return fbSetupScreen (pScreen, 289706f2543Smrg pbits1, 290706f2543Smrg xsize, 291706f2543Smrg ysize, 292706f2543Smrg dpix, 293706f2543Smrg dpiy, 294706f2543Smrg width1, 295706f2543Smrg bpp1); 296706f2543Smrg} 297706f2543Smrg 298706f2543Smrgstatic Bool 299706f2543Smrgfb24_32OverlayCreateScreenResources(ScreenPtr pScreen) 300706f2543Smrg{ 301706f2543Smrg FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 302706f2543Smrg int pitch; 303706f2543Smrg Bool retval; 304706f2543Smrg int i; 305706f2543Smrg 306706f2543Smrg if((retval = fbOverlayCreateScreenResources(pScreen))) { 307706f2543Smrg for (i = 0; i < pScrPriv->nlayers; i++) 308706f2543Smrg { 309706f2543Smrg /* fix the screen pixmap */ 310706f2543Smrg PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap; 311706f2543Smrg if (pPix->drawable.bitsPerPixel == 32) { 312706f2543Smrg pPix->drawable.bitsPerPixel = 24; 313706f2543Smrg pitch = BitmapBytePad(pPix->drawable.width * 24); 314706f2543Smrg pPix->devKind = pitch; 315706f2543Smrg } 316706f2543Smrg } 317706f2543Smrg } 318706f2543Smrg 319706f2543Smrg return retval; 320706f2543Smrg} 321706f2543Smrg 322706f2543SmrgBool 323706f2543SmrgfbOverlayFinishScreenInit(ScreenPtr pScreen, 324706f2543Smrg pointer pbits1, 325706f2543Smrg pointer pbits2, 326706f2543Smrg int xsize, 327706f2543Smrg int ysize, 328706f2543Smrg int dpix, 329706f2543Smrg int dpiy, 330706f2543Smrg int width1, 331706f2543Smrg int width2, 332706f2543Smrg int bpp1, 333706f2543Smrg int bpp2, 334706f2543Smrg int depth1, 335706f2543Smrg int depth2) 336706f2543Smrg{ 337706f2543Smrg VisualPtr visuals; 338706f2543Smrg DepthPtr depths; 339706f2543Smrg int nvisuals; 340706f2543Smrg int ndepths; 341706f2543Smrg int bpp = 0, imagebpp = 32; 342706f2543Smrg VisualID defaultVisual; 343706f2543Smrg FbOverlayScrPrivPtr pScrPriv; 344706f2543Smrg 345706f2543Smrg if (!dixRegisterPrivateKey(&fbOverlayScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 346706f2543Smrg return FALSE; 347706f2543Smrg 348706f2543Smrg pScrPriv = malloc(sizeof (FbOverlayScrPrivRec)); 349706f2543Smrg if (!pScrPriv) 350706f2543Smrg return FALSE; 351706f2543Smrg 352706f2543Smrg#ifdef FB_24_32BIT 353706f2543Smrg if (bpp1 == 32 || bpp2 == 32) 354706f2543Smrg bpp = 32; 355706f2543Smrg else if (bpp1 == 24 || bpp2 == 24) 356706f2543Smrg bpp = 24; 357706f2543Smrg 358706f2543Smrg if (bpp == 24) 359706f2543Smrg { 360706f2543Smrg int f; 361706f2543Smrg 362706f2543Smrg imagebpp = 32; 363706f2543Smrg /* 364706f2543Smrg * Check to see if we're advertising a 24bpp image format, 365706f2543Smrg * in which case windows will use it in preference to a 32 bit 366706f2543Smrg * format. 367706f2543Smrg */ 368706f2543Smrg for (f = 0; f < screenInfo.numPixmapFormats; f++) 369706f2543Smrg { 370706f2543Smrg if (screenInfo.formats[f].bitsPerPixel == 24) 371706f2543Smrg { 372706f2543Smrg imagebpp = 24; 373706f2543Smrg break; 374706f2543Smrg } 375706f2543Smrg } 376706f2543Smrg } 377706f2543Smrg#endif 378706f2543Smrg#ifdef FB_SCREEN_PRIVATE 379706f2543Smrg if (imagebpp == 32) 380706f2543Smrg { 381706f2543Smrg fbGetScreenPrivate(pScreen)->win32bpp = bpp; 382706f2543Smrg fbGetScreenPrivate(pScreen)->pix32bpp = bpp; 383706f2543Smrg } 384706f2543Smrg else 385706f2543Smrg { 386706f2543Smrg fbGetScreenPrivate(pScreen)->win32bpp = 32; 387706f2543Smrg fbGetScreenPrivate(pScreen)->pix32bpp = 32; 388706f2543Smrg } 389706f2543Smrg#endif 390706f2543Smrg 391706f2543Smrg if (!fbInitVisuals (&visuals, &depths, &nvisuals, &ndepths, &depth1, 392706f2543Smrg &defaultVisual, ((unsigned long)1<<(bpp1-1)) | 393706f2543Smrg ((unsigned long)1<<(bpp2-1)), 8)) { 394706f2543Smrg free(pScrPriv); 395706f2543Smrg return FALSE; 396706f2543Smrg } 397706f2543Smrg if (! miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0, 398706f2543Smrg depth1, ndepths, depths, 399706f2543Smrg defaultVisual, nvisuals, visuals)) { 400706f2543Smrg free(pScrPriv); 401706f2543Smrg return FALSE; 402706f2543Smrg } 403706f2543Smrg /* MI thinks there's no frame buffer */ 404706f2543Smrg#ifdef MITSHM 405706f2543Smrg ShmRegisterFbFuncs(pScreen); 406706f2543Smrg#endif 407706f2543Smrg pScreen->minInstalledCmaps = 1; 408706f2543Smrg pScreen->maxInstalledCmaps = 2; 409706f2543Smrg 410706f2543Smrg pScrPriv->nlayers = 2; 411706f2543Smrg pScrPriv->PaintKey = fbOverlayPaintKey; 412706f2543Smrg pScrPriv->CopyWindow = fbCopyWindowProc; 413706f2543Smrg pScrPriv->layer[0].u.init.pbits = pbits1; 414706f2543Smrg pScrPriv->layer[0].u.init.width = width1; 415706f2543Smrg pScrPriv->layer[0].u.init.depth = depth1; 416706f2543Smrg 417706f2543Smrg pScrPriv->layer[1].u.init.pbits = pbits2; 418706f2543Smrg pScrPriv->layer[1].u.init.width = width2; 419706f2543Smrg pScrPriv->layer[1].u.init.depth = depth2; 420706f2543Smrg dixSetPrivate(&pScreen->devPrivates, fbOverlayScreenPrivateKey, pScrPriv); 421706f2543Smrg 422706f2543Smrg /* overwrite miCloseScreen with our own */ 423706f2543Smrg pScreen->CloseScreen = fbOverlayCloseScreen; 424706f2543Smrg pScreen->CreateScreenResources = fbOverlayCreateScreenResources; 425706f2543Smrg pScreen->CreateWindow = fbOverlayCreateWindow; 426706f2543Smrg pScreen->WindowExposures = fbOverlayWindowExposures; 427706f2543Smrg pScreen->CopyWindow = fbOverlayCopyWindow; 428706f2543Smrg#ifdef FB_24_32BIT 429706f2543Smrg if (bpp == 24 && imagebpp == 32) 430706f2543Smrg { 431706f2543Smrg pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader; 432706f2543Smrg pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources; 433706f2543Smrg } 434706f2543Smrg#endif 435706f2543Smrg 436706f2543Smrg return TRUE; 437706f2543Smrg} 438