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#ifdef HAVE_DIX_CONFIG_H 26#include <dix-config.h> 27#endif 28 29#include <stdlib.h> 30 31#include "fb.h" 32#include "fboverlay.h" 33#include "shmint.h" 34 35static DevPrivateKeyRec fbOverlayScreenPrivateKeyRec; 36 37#define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec) 38 39DevPrivateKey 40fbOverlayGetScreenPrivateKey(void) 41{ 42 return fbOverlayScreenPrivateKey; 43} 44 45/* 46 * Replace this if you want something supporting 47 * multiple overlays with the same depth 48 */ 49Bool 50fbOverlayCreateWindow(WindowPtr pWin) 51{ 52 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); 53 int i; 54 PixmapPtr pPixmap; 55 56 if (pWin->drawable.class != InputOutput) 57 return TRUE; 58 59 for (i = 0; i < pScrPriv->nlayers; i++) { 60 pPixmap = pScrPriv->layer[i].u.run.pixmap; 61 if (pWin->drawable.depth == pPixmap->drawable.depth) { 62 dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin), pPixmap); 63 /* 64 * Make sure layer keys are written correctly by 65 * having non-root layers set to full while the 66 * root layer is set to empty. This will cause 67 * all of the layers to get painted when the root 68 * is mapped 69 */ 70 if (!pWin->parent) { 71 RegionEmpty(&pScrPriv->layer[i].u.run.region); 72 } 73 return TRUE; 74 } 75 } 76 return FALSE; 77} 78 79Bool 80fbOverlayCloseScreen(ScreenPtr pScreen) 81{ 82 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 83 int i; 84 85 for (i = 0; i < pScrPriv->nlayers; i++) { 86 (*pScreen->DestroyPixmap) (pScrPriv->layer[i].u.run.pixmap); 87 RegionUninit(&pScrPriv->layer[i].u.run.region); 88 } 89 return TRUE; 90} 91 92/* 93 * Return layer containing this window 94 */ 95int 96fbOverlayWindowLayer(WindowPtr pWin) 97{ 98 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); 99 int i; 100 101 for (i = 0; i < pScrPriv->nlayers; i++) 102 if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin)) == 103 (void *) pScrPriv->layer[i].u.run.pixmap) 104 return i; 105 return 0; 106} 107 108Bool 109fbOverlayCreateScreenResources(ScreenPtr pScreen) 110{ 111 int i; 112 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 113 PixmapPtr pPixmap; 114 void *pbits; 115 int width; 116 int depth; 117 BoxRec box; 118 119 if (!miCreateScreenResources(pScreen)) 120 return FALSE; 121 122 box.x1 = 0; 123 box.y1 = 0; 124 box.x2 = pScreen->width; 125 box.y2 = pScreen->height; 126 for (i = 0; i < pScrPriv->nlayers; i++) { 127 pbits = pScrPriv->layer[i].u.init.pbits; 128 width = pScrPriv->layer[i].u.init.width; 129 depth = pScrPriv->layer[i].u.init.depth; 130 pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0); 131 if (!pPixmap) 132 return FALSE; 133 if (!(*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width, 134 pScreen->height, depth, 135 BitsPerPixel(depth), 136 PixmapBytePad(width, depth), 137 pbits)) 138 return FALSE; 139 pScrPriv->layer[i].u.run.pixmap = pPixmap; 140 RegionInit(&pScrPriv->layer[i].u.run.region, &box, 0); 141 } 142 pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap; 143 return TRUE; 144} 145 146void 147fbOverlayPaintKey(DrawablePtr pDrawable, 148 RegionPtr pRegion, CARD32 pixel, int layer) 149{ 150 fbFillRegionSolid(pDrawable, pRegion, 0, 151 fbReplicatePixel(pixel, pDrawable->bitsPerPixel)); 152} 153 154/* 155 * Track visible region for each layer 156 */ 157void 158fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn) 159{ 160 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 161 int i; 162 RegionRec rgnNew; 163 164 if (!prgn || !RegionNotEmpty(prgn)) 165 return; 166 for (i = 0; i < pScrPriv->nlayers; i++) { 167 if (i == layer) { 168 /* add new piece to this fb */ 169 RegionUnion(&pScrPriv->layer[i].u.run.region, 170 &pScrPriv->layer[i].u.run.region, prgn); 171 } 172 else if (RegionNotEmpty(&pScrPriv->layer[i].u.run.region)) { 173 /* paint new piece with chroma key */ 174 RegionNull(&rgnNew); 175 RegionIntersect(&rgnNew, prgn, &pScrPriv->layer[i].u.run.region); 176 (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable, 177 &rgnNew, pScrPriv->layer[i].key, i); 178 RegionUninit(&rgnNew); 179 /* remove piece from other fbs */ 180 RegionSubtract(&pScrPriv->layer[i].u.run.region, 181 &pScrPriv->layer[i].u.run.region, prgn); 182 } 183 } 184} 185 186/* 187 * Copy only areas in each layer containing real bits 188 */ 189void 190fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 191{ 192 ScreenPtr pScreen = pWin->drawable.pScreen; 193 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); 194 RegionRec rgnDst; 195 int dx, dy; 196 int i; 197 RegionRec layerRgn[FB_OVERLAY_MAX]; 198 PixmapPtr pPixmap; 199 200 dx = ptOldOrg.x - pWin->drawable.x; 201 dy = ptOldOrg.y - pWin->drawable.y; 202 203 /* 204 * Clip to existing bits 205 */ 206 RegionTranslate(prgnSrc, -dx, -dy); 207 RegionNull(&rgnDst); 208 RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 209 RegionTranslate(&rgnDst, dx, dy); 210 /* 211 * Compute the portion of each fb affected by this copy 212 */ 213 for (i = 0; i < pScrPriv->nlayers; i++) { 214 RegionNull(&layerRgn[i]); 215 RegionIntersect(&layerRgn[i], &rgnDst, 216 &pScrPriv->layer[i].u.run.region); 217 if (RegionNotEmpty(&layerRgn[i])) { 218 RegionTranslate(&layerRgn[i], -dx, -dy); 219 pPixmap = pScrPriv->layer[i].u.run.pixmap; 220 miCopyRegion(&pPixmap->drawable, &pPixmap->drawable, 221 0, 222 &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0, 223 (void *) (long) i); 224 } 225 } 226 /* 227 * Update regions 228 */ 229 for (i = 0; i < pScrPriv->nlayers; i++) { 230 if (RegionNotEmpty(&layerRgn[i])) 231 fbOverlayUpdateLayerRegion(pScreen, i, &layerRgn[i]); 232 233 RegionUninit(&layerRgn[i]); 234 } 235 RegionUninit(&rgnDst); 236} 237 238void 239fbOverlayWindowExposures(WindowPtr pWin, RegionPtr prgn) 240{ 241 fbOverlayUpdateLayerRegion(pWin->drawable.pScreen, 242 fbOverlayWindowLayer(pWin), prgn); 243 miWindowExposures(pWin, prgn); 244} 245 246Bool 247fbOverlaySetupScreen(ScreenPtr pScreen, 248 void *pbits1, 249 void *pbits2, 250 int xsize, 251 int ysize, 252 int dpix, 253 int dpiy, int width1, int width2, int bpp1, int bpp2) 254{ 255 return fbSetupScreen(pScreen, 256 pbits1, xsize, ysize, dpix, dpiy, width1, bpp1); 257} 258 259Bool 260fbOverlayFinishScreenInit(ScreenPtr pScreen, 261 void *pbits1, 262 void *pbits2, 263 int xsize, 264 int ysize, 265 int dpix, 266 int dpiy, 267 int width1, 268 int width2, 269 int bpp1, int bpp2, int depth1, int depth2) 270{ 271 VisualPtr visuals; 272 DepthPtr depths; 273 int nvisuals; 274 int ndepths; 275 VisualID defaultVisual; 276 FbOverlayScrPrivPtr pScrPriv; 277 278 if (!dixRegisterPrivateKey 279 (&fbOverlayScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 280 return FALSE; 281 282 if (bpp1 == 24 || bpp2 == 24) 283 return FALSE; 284 285 pScrPriv = malloc(sizeof(FbOverlayScrPrivRec)); 286 if (!pScrPriv) 287 return FALSE; 288 289 if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1, 290 &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) | 291 ((unsigned long) 1 << (bpp2 - 1)), 8)) { 292 free(pScrPriv); 293 return FALSE; 294 } 295 if (!miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0, 296 depth1, ndepths, depths, 297 defaultVisual, nvisuals, visuals)) { 298 free(pScrPriv); 299 return FALSE; 300 } 301 /* MI thinks there's no frame buffer */ 302#ifdef MITSHM 303 ShmRegisterFbFuncs(pScreen); 304#endif 305 pScreen->minInstalledCmaps = 1; 306 pScreen->maxInstalledCmaps = 2; 307 308 pScrPriv->nlayers = 2; 309 pScrPriv->PaintKey = fbOverlayPaintKey; 310 pScrPriv->CopyWindow = fbCopyWindowProc; 311 pScrPriv->layer[0].u.init.pbits = pbits1; 312 pScrPriv->layer[0].u.init.width = width1; 313 pScrPriv->layer[0].u.init.depth = depth1; 314 315 pScrPriv->layer[1].u.init.pbits = pbits2; 316 pScrPriv->layer[1].u.init.width = width2; 317 pScrPriv->layer[1].u.init.depth = depth2; 318 dixSetPrivate(&pScreen->devPrivates, fbOverlayScreenPrivateKey, pScrPriv); 319 320 /* overwrite miCloseScreen with our own */ 321 pScreen->CloseScreen = fbOverlayCloseScreen; 322 pScreen->CreateScreenResources = fbOverlayCreateScreenResources; 323 pScreen->CreateWindow = fbOverlayCreateWindow; 324 pScreen->WindowExposures = fbOverlayWindowExposures; 325 pScreen->CopyWindow = fbOverlayCopyWindow; 326 327 return TRUE; 328} 329