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 */
26 #ifdef HAVE_DIX_CONFIG_H
27 #include <dix-config.h>
28 #endif
30 #include <stdlib.h>
32 #include "fb.h"
33 #include "fboverlay.h"
34 #include "shmint.h"
36 static DevPrivateKeyRec fbOverlayScreenPrivateKeyRec;
37 #define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec)
39 DevPrivateKey fbOverlayGetScreenPrivateKey(void)
40 {
41 return fbOverlayScreenPrivateKey;
42 }
44 /*
45 * Replace this if you want something supporting
46 * multiple overlays with the same depth
47 */
48 Bool
49 fbOverlayCreateWindow(WindowPtr pWin)
50 {
51 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
52 int i;
53 PixmapPtr pPixmap;
55 if (pWin->drawable.class != InputOutput)
56 return TRUE;
58 if (pWin->drawable.bitsPerPixel == 32)
59 pWin->drawable.bitsPerPixel = fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp;
61 for (i = 0; i < pScrPriv->nlayers; i++)
62 {
63 pPixmap = pScrPriv->layer[i].u.run.pixmap;
64 if (pWin->drawable.depth == pPixmap->drawable.depth)
65 {
66 dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(), pPixmap);
67 /*
68 * Make sure layer keys are written correctly by
69 * having non-root layers set to full while the
70 * root layer is set to empty. This will cause
71 * all of the layers to get painted when the root
72 * is mapped
73 */
74 if (!pWin->parent)
75 {
76 RegionEmpty(&pScrPriv->layer[i].u.run.region);
77 }
78 return TRUE;
79 }
80 }
81 return FALSE;
82 }
84 Bool
85 fbOverlayCloseScreen (int iScreen, ScreenPtr pScreen)
86 {
87 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
88 int i;
90 for (i = 0; i < pScrPriv->nlayers; i++)
91 {
92 (*pScreen->DestroyPixmap)(pScrPriv->layer[i].u.run.pixmap);
93 RegionUninit(&pScrPriv->layer[i].u.run.region);
94 }
95 return TRUE;
96 }
98 /*
99 * Return layer containing this window
100 */
101 int
102 fbOverlayWindowLayer(WindowPtr pWin)
103 {
104 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
105 int i;
107 for (i = 0; i < pScrPriv->nlayers; i++)
108 if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey()) ==
109 (pointer) pScrPriv->layer[i].u.run.pixmap)
110 return i;
111 return 0;
112 }
114 Bool
115 fbOverlayCreateScreenResources(ScreenPtr pScreen)
116 {
117 int i;
118 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
119 PixmapPtr pPixmap;
120 pointer pbits;
121 int width;
122 int depth;
123 BoxRec box;
125 if (!miCreateScreenResources(pScreen))
126 return FALSE;
128 box.x1 = 0;
129 box.y1 = 0;
130 box.x2 = pScreen->width;
131 box.y2 = pScreen->height;
132 for (i = 0; i < pScrPriv->nlayers; i++)
133 {
134 pbits = pScrPriv->layer[i].u.init.pbits;
135 width = pScrPriv->layer[i].u.init.width;
136 depth = pScrPriv->layer[i].u.init.depth;
137 pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
138 if (!pPixmap)
139 return FALSE;
140 if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width,
141 pScreen->height, depth,
142 BitsPerPixel(depth),
143 PixmapBytePad(width, depth),
144 pbits))
145 return FALSE;
146 pScrPriv->layer[i].u.run.pixmap = pPixmap;
147 RegionInit(&pScrPriv->layer[i].u.run.region, &box, 0);
148 }
149 pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap;
150 return TRUE;
151 }
153 void
154 fbOverlayPaintKey (DrawablePtr pDrawable,
155 RegionPtr pRegion,
156 CARD32 pixel,
157 int layer)
158 {
159 fbFillRegionSolid (pDrawable, pRegion, 0,
160 fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
161 }
163 /*
164 * Track visible region for each layer
165 */
166 void
167 fbOverlayUpdateLayerRegion (ScreenPtr pScreen,
168 int layer,
169 RegionPtr prgn)
170 {
171 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
172 int i;
173 RegionRec rgnNew;
175 if (!prgn || !RegionNotEmpty(prgn))
176 return;
177 for (i = 0; i < pScrPriv->nlayers; i++)
178 {
179 if (i == layer)
180 {
181 /* add new piece to this fb */
182 RegionUnion(&pScrPriv->layer[i].u.run.region,
183 &pScrPriv->layer[i].u.run.region,
184 prgn);
185 }
186 else if (RegionNotEmpty(&pScrPriv->layer[i].u.run.region))
187 {
188 /* paint new piece with chroma key */
189 RegionNull(&rgnNew);
190 RegionIntersect(&rgnNew, prgn,
191 &pScrPriv->layer[i].u.run.region);
192 (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable,
193 &rgnNew,
194 pScrPriv->layer[i].key,
195 i);
196 RegionUninit(&rgnNew);
197 /* remove piece from other fbs */
198 RegionSubtract(&pScrPriv->layer[i].u.run.region,
199 &pScrPriv->layer[i].u.run.region,
200 prgn);
201 }
202 }
203 }
205 /*
206 * Copy only areas in each layer containing real bits
207 */
208 void
209 fbOverlayCopyWindow(WindowPtr pWin,
210 DDXPointRec ptOldOrg,
211 RegionPtr prgnSrc)
212 {
213 ScreenPtr pScreen = pWin->drawable.pScreen;
214 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
215 RegionRec rgnDst;
216 int dx, dy;
217 int i;
218 RegionRec layerRgn[FB_OVERLAY_MAX];
219 PixmapPtr pPixmap;
221 dx = ptOldOrg.x - pWin->drawable.x;
222 dy = ptOldOrg.y - pWin->drawable.y;
224 /*
225 * Clip to existing bits
226 */
227 RegionTranslate(prgnSrc, -dx, -dy);
228 RegionNull(&rgnDst);
229 RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
230 RegionTranslate(&rgnDst, dx, dy);
231 /*
232 * Compute the portion of each fb affected by this copy
233 */
234 for (i = 0; i < pScrPriv->nlayers; i++)
235 {
236 RegionNull(&layerRgn[i]);
237 RegionIntersect(&layerRgn[i], &rgnDst,
238 &pScrPriv->layer[i].u.run.region);
239 if (RegionNotEmpty(&layerRgn[i]))
240 {
241 RegionTranslate(&layerRgn[i], -dx, -dy);
242 pPixmap = pScrPriv->layer[i].u.run.pixmap;
243 miCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
244 0,
245 &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0,
246 (void *)(long) i);
247 }
248 }
249 /*
250 * Update regions
251 */
252 for (i = 0; i < pScrPriv->nlayers; i++)
253 {
254 if (RegionNotEmpty(&layerRgn[i]))
255 fbOverlayUpdateLayerRegion (pScreen, i, &layerRgn[i]);
257 RegionUninit(&layerRgn[i]);
258 }
259 RegionUninit(&rgnDst);
260 }
262 void
263 fbOverlayWindowExposures (WindowPtr pWin,
264 RegionPtr prgn,
265 RegionPtr other_exposed)
266 {
267 fbOverlayUpdateLayerRegion (pWin->drawable.pScreen,
268 fbOverlayWindowLayer (pWin),
269 prgn);
270 miWindowExposures(pWin, prgn, other_exposed);
271 }
273 Bool
274 fbOverlaySetupScreen(ScreenPtr pScreen,
275 pointer pbits1,
276 pointer pbits2,
277 int xsize,
278 int ysize,
279 int dpix,
280 int dpiy,
281 int width1,
282 int width2,
283 int bpp1,
284 int bpp2)
285 {
286 return fbSetupScreen (pScreen,
287 pbits1,
288 xsize,
289 ysize,
290 dpix,
291 dpiy,
292 width1,
293 bpp1);
294 }
296 static Bool
297 fb24_32OverlayCreateScreenResources(ScreenPtr pScreen)
298 {
299 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
300 int pitch;
301 Bool retval;
302 int i;
304 if((retval = fbOverlayCreateScreenResources(pScreen))) {
305 for (i = 0; i < pScrPriv->nlayers; i++)
306 {
307 /* fix the screen pixmap */
308 PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap;
309 if (pPix->drawable.bitsPerPixel == 32) {
310 pPix->drawable.bitsPerPixel = 24;
311 pitch = BitmapBytePad(pPix->drawable.width * 24);
312 pPix->devKind = pitch;
313 }
314 }
315 }
317 return retval;
318 }
320 Bool
321 fbOverlayFinishScreenInit(ScreenPtr pScreen,
322 pointer pbits1,
323 pointer pbits2,
324 int xsize,
325 int ysize,
326 int dpix,
327 int dpiy,
328 int width1,
329 int width2,
330 int bpp1,
331 int bpp2,
332 int depth1,
333 int depth2)
334 {
335 VisualPtr visuals;
336 DepthPtr depths;
337 int nvisuals;
338 int ndepths;
339 int bpp = 0, imagebpp = 32;
340 VisualID defaultVisual;
341 FbOverlayScrPrivPtr pScrPriv;
343 if (!dixRegisterPrivateKey(&fbOverlayScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
344 return FALSE;
346 pScrPriv = malloc(sizeof (FbOverlayScrPrivRec));
347 if (!pScrPriv)
348 return FALSE;
350 if (bpp1 == 32 || bpp2 == 32)
351 bpp = 32;
352 else if (bpp1 == 24 || bpp2 == 24)
353 bpp = 24;
355 if (bpp == 24)
356 {
357 int f;
359 imagebpp = 32;
360 /*
361 * Check to see if we're advertising a 24bpp image format,
362 * in which case windows will use it in preference to a 32 bit
363 * format.
364 */
365 for (f = 0; f < screenInfo.numPixmapFormats; f++)
366 {
367 if (screenInfo.formats[f].bitsPerPixel == 24)
368 {
369 imagebpp = 24;
370 break;
371 }
372 }
373 }
374 if (imagebpp == 32)
375 {
376 fbGetScreenPrivate(pScreen)->win32bpp = bpp;
377 fbGetScreenPrivate(pScreen)->pix32bpp = bpp;
378 }
379 else
380 {
381 fbGetScreenPrivate(pScreen)->win32bpp = 32;
382 fbGetScreenPrivate(pScreen)->pix32bpp = 32;
383 }
385 if (!fbInitVisuals (&visuals, &depths, &nvisuals, &ndepths, &depth1,
386 &defaultVisual, ((unsigned long)1<<(bpp1-1)) |
387 ((unsigned long)1<<(bpp2-1)), 8)) {
388 free(pScrPriv);
389 return FALSE;
390 }
391 if (! miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0,
392 depth1, ndepths, depths,
393 defaultVisual, nvisuals, visuals)) {
394 free(pScrPriv);
395 return FALSE;
396 }
397 /* MI thinks there's no frame buffer */
398 #ifdef MITSHM
399 ShmRegisterFbFuncs(pScreen);
400 #endif
401 pScreen->minInstalledCmaps = 1;
402 pScreen->maxInstalledCmaps = 2;
404 pScrPriv->nlayers = 2;
405 pScrPriv->PaintKey = fbOverlayPaintKey;
406 pScrPriv->CopyWindow = fbCopyWindowProc;
407 pScrPriv->layer[0].u.init.pbits = pbits1;
408 pScrPriv->layer[0].u.init.width = width1;
409 pScrPriv->layer[0].u.init.depth = depth1;
411 pScrPriv->layer[1].u.init.pbits = pbits2;
412 pScrPriv->layer[1].u.init.width = width2;
413 pScrPriv->layer[1].u.init.depth = depth2;
414 dixSetPrivate(&pScreen->devPrivates, fbOverlayScreenPrivateKey, pScrPriv);
416 /* overwrite miCloseScreen with our own */
417 pScreen->CloseScreen = fbOverlayCloseScreen;
418 pScreen->CreateScreenResources = fbOverlayCreateScreenResources;
419 pScreen->CreateWindow = fbOverlayCreateWindow;
420 pScreen->WindowExposures = fbOverlayWindowExposures;
421 pScreen->CopyWindow = fbOverlayCopyWindow;
422 if (bpp == 24 && imagebpp == 32)
423 {
424 pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader;
425 pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources;
426 }
428 return TRUE;
429 }