3 * Copyright © 2000 SuSE, Inc.
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.
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.
22 * Author: Keith Packard, SuSE, Inc.
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
32 #include "fboverlay.h"
35 static DevPrivateKeyRec fbOverlayScreenPrivateKeyRec
;
37 #define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec)
40 fbOverlayGetScreenPrivateKey(void)
42 return fbOverlayScreenPrivateKey
;
46 * Replace this if you want something supporting
47 * multiple overlays with the same depth
50 fbOverlayCreateWindow(WindowPtr pWin
)
52 FbOverlayScrPrivPtr pScrPriv
= fbOverlayGetScrPriv(pWin
->drawable
.pScreen
);
56 if (pWin
->drawable
.class != InputOutput
)
59 if (pWin
->drawable
.bitsPerPixel
== 32)
60 pWin
->drawable
.bitsPerPixel
=
61 fbGetScreenPrivate(pWin
->drawable
.pScreen
)->win32bpp
;
63 for (i
= 0; i
< pScrPriv
->nlayers
; i
++) {
64 pPixmap
= pScrPriv
->layer
[i
].u
.run
.pixmap
;
65 if (pWin
->drawable
.depth
== pPixmap
->drawable
.depth
) {
66 dixSetPrivate(&pWin
->devPrivates
, fbGetWinPrivateKey(pWin
), pPixmap
);
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
75 RegionEmpty(&pScrPriv
->layer
[i
].u
.run
.region
);
84 fbOverlayCloseScreen(ScreenPtr pScreen
)
86 FbOverlayScrPrivPtr pScrPriv
= fbOverlayGetScrPriv(pScreen
);
89 for (i
= 0; i
< pScrPriv
->nlayers
; i
++) {
90 (*pScreen
->DestroyPixmap
) (pScrPriv
->layer
[i
].u
.run
.pixmap
);
91 RegionUninit(&pScrPriv
->layer
[i
].u
.run
.region
);
97 * Return layer containing this window
100 fbOverlayWindowLayer(WindowPtr pWin
)
102 FbOverlayScrPrivPtr pScrPriv
= fbOverlayGetScrPriv(pWin
->drawable
.pScreen
);
105 for (i
= 0; i
< pScrPriv
->nlayers
; i
++)
106 if (dixLookupPrivate(&pWin
->devPrivates
, fbGetWinPrivateKey(pWin
)) ==
107 (pointer
) pScrPriv
->layer
[i
].u
.run
.pixmap
)
113 fbOverlayCreateScreenResources(ScreenPtr pScreen
)
116 FbOverlayScrPrivPtr pScrPriv
= fbOverlayGetScrPriv(pScreen
);
123 if (!miCreateScreenResources(pScreen
))
128 box
.x2
= pScreen
->width
;
129 box
.y2
= pScreen
->height
;
130 for (i
= 0; i
< pScrPriv
->nlayers
; i
++) {
131 pbits
= pScrPriv
->layer
[i
].u
.init
.pbits
;
132 width
= pScrPriv
->layer
[i
].u
.init
.width
;
133 depth
= pScrPriv
->layer
[i
].u
.init
.depth
;
134 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, 0, 0, depth
, 0);
137 if (!(*pScreen
->ModifyPixmapHeader
) (pPixmap
, pScreen
->width
,
138 pScreen
->height
, depth
,
140 PixmapBytePad(width
, depth
),
143 pScrPriv
->layer
[i
].u
.run
.pixmap
= pPixmap
;
144 RegionInit(&pScrPriv
->layer
[i
].u
.run
.region
, &box
, 0);
146 pScreen
->devPrivate
= pScrPriv
->layer
[0].u
.run
.pixmap
;
151 fbOverlayPaintKey(DrawablePtr pDrawable
,
152 RegionPtr pRegion
, CARD32 pixel
, int layer
)
154 fbFillRegionSolid(pDrawable
, pRegion
, 0,
155 fbReplicatePixel(pixel
, pDrawable
->bitsPerPixel
));
159 * Track visible region for each layer
162 fbOverlayUpdateLayerRegion(ScreenPtr pScreen
, int layer
, RegionPtr prgn
)
164 FbOverlayScrPrivPtr pScrPriv
= fbOverlayGetScrPriv(pScreen
);
168 if (!prgn
|| !RegionNotEmpty(prgn
))
170 for (i
= 0; i
< pScrPriv
->nlayers
; i
++) {
172 /* add new piece to this fb */
173 RegionUnion(&pScrPriv
->layer
[i
].u
.run
.region
,
174 &pScrPriv
->layer
[i
].u
.run
.region
, prgn
);
176 else if (RegionNotEmpty(&pScrPriv
->layer
[i
].u
.run
.region
)) {
177 /* paint new piece with chroma key */
179 RegionIntersect(&rgnNew
, prgn
, &pScrPriv
->layer
[i
].u
.run
.region
);
180 (*pScrPriv
->PaintKey
) (&pScrPriv
->layer
[i
].u
.run
.pixmap
->drawable
,
181 &rgnNew
, pScrPriv
->layer
[i
].key
, i
);
182 RegionUninit(&rgnNew
);
183 /* remove piece from other fbs */
184 RegionSubtract(&pScrPriv
->layer
[i
].u
.run
.region
,
185 &pScrPriv
->layer
[i
].u
.run
.region
, prgn
);
191 * Copy only areas in each layer containing real bits
194 fbOverlayCopyWindow(WindowPtr pWin
, DDXPointRec ptOldOrg
, RegionPtr prgnSrc
)
196 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
197 FbOverlayScrPrivPtr pScrPriv
= fbOverlayGetScrPriv(pScreen
);
201 RegionRec layerRgn
[FB_OVERLAY_MAX
];
204 dx
= ptOldOrg
.x
- pWin
->drawable
.x
;
205 dy
= ptOldOrg
.y
- pWin
->drawable
.y
;
208 * Clip to existing bits
210 RegionTranslate(prgnSrc
, -dx
, -dy
);
212 RegionIntersect(&rgnDst
, &pWin
->borderClip
, prgnSrc
);
213 RegionTranslate(&rgnDst
, dx
, dy
);
215 * Compute the portion of each fb affected by this copy
217 for (i
= 0; i
< pScrPriv
->nlayers
; i
++) {
218 RegionNull(&layerRgn
[i
]);
219 RegionIntersect(&layerRgn
[i
], &rgnDst
,
220 &pScrPriv
->layer
[i
].u
.run
.region
);
221 if (RegionNotEmpty(&layerRgn
[i
])) {
222 RegionTranslate(&layerRgn
[i
], -dx
, -dy
);
223 pPixmap
= pScrPriv
->layer
[i
].u
.run
.pixmap
;
224 miCopyRegion(&pPixmap
->drawable
, &pPixmap
->drawable
,
226 &layerRgn
[i
], dx
, dy
, pScrPriv
->CopyWindow
, 0,
233 for (i
= 0; i
< pScrPriv
->nlayers
; i
++) {
234 if (RegionNotEmpty(&layerRgn
[i
]))
235 fbOverlayUpdateLayerRegion(pScreen
, i
, &layerRgn
[i
]);
237 RegionUninit(&layerRgn
[i
]);
239 RegionUninit(&rgnDst
);
243 fbOverlayWindowExposures(WindowPtr pWin
,
244 RegionPtr prgn
, RegionPtr other_exposed
)
246 fbOverlayUpdateLayerRegion(pWin
->drawable
.pScreen
,
247 fbOverlayWindowLayer(pWin
), prgn
);
248 miWindowExposures(pWin
, prgn
, other_exposed
);
252 fbOverlaySetupScreen(ScreenPtr pScreen
,
258 int dpiy
, int width1
, int width2
, int bpp1
, int bpp2
)
260 return fbSetupScreen(pScreen
,
261 pbits1
, xsize
, ysize
, dpix
, dpiy
, width1
, bpp1
);
265 fb24_32OverlayCreateScreenResources(ScreenPtr pScreen
)
267 FbOverlayScrPrivPtr pScrPriv
= fbOverlayGetScrPriv(pScreen
);
272 if ((retval
= fbOverlayCreateScreenResources(pScreen
))) {
273 for (i
= 0; i
< pScrPriv
->nlayers
; i
++) {
274 /* fix the screen pixmap */
275 PixmapPtr pPix
= (PixmapPtr
) pScrPriv
->layer
[i
].u
.run
.pixmap
;
277 if (pPix
->drawable
.bitsPerPixel
== 32) {
278 pPix
->drawable
.bitsPerPixel
= 24;
279 pitch
= BitmapBytePad(pPix
->drawable
.width
* 24);
280 pPix
->devKind
= pitch
;
289 fbOverlayFinishScreenInit(ScreenPtr pScreen
,
298 int bpp1
, int bpp2
, int depth1
, int depth2
)
304 int bpp
= 0, imagebpp
= 32;
305 VisualID defaultVisual
;
306 FbOverlayScrPrivPtr pScrPriv
;
308 if (!dixRegisterPrivateKey
309 (&fbOverlayScreenPrivateKeyRec
, PRIVATE_SCREEN
, 0))
312 pScrPriv
= malloc(sizeof(FbOverlayScrPrivRec
));
316 if (bpp1
== 32 || bpp2
== 32)
318 else if (bpp1
== 24 || bpp2
== 24)
326 * Check to see if we're advertising a 24bpp image format,
327 * in which case windows will use it in preference to a 32 bit
330 for (f
= 0; f
< screenInfo
.numPixmapFormats
; f
++) {
331 if (screenInfo
.formats
[f
].bitsPerPixel
== 24) {
337 if (imagebpp
== 32) {
338 fbGetScreenPrivate(pScreen
)->win32bpp
= bpp
;
339 fbGetScreenPrivate(pScreen
)->pix32bpp
= bpp
;
342 fbGetScreenPrivate(pScreen
)->win32bpp
= 32;
343 fbGetScreenPrivate(pScreen
)->pix32bpp
= 32;
346 if (!fbInitVisuals(&visuals
, &depths
, &nvisuals
, &ndepths
, &depth1
,
347 &defaultVisual
, ((unsigned long) 1 << (bpp1
- 1)) |
348 ((unsigned long) 1 << (bpp2
- 1)), 8)) {
352 if (!miScreenInit(pScreen
, 0, xsize
, ysize
, dpix
, dpiy
, 0,
353 depth1
, ndepths
, depths
,
354 defaultVisual
, nvisuals
, visuals
)) {
358 /* MI thinks there's no frame buffer */
360 ShmRegisterFbFuncs(pScreen
);
362 pScreen
->minInstalledCmaps
= 1;
363 pScreen
->maxInstalledCmaps
= 2;
365 pScrPriv
->nlayers
= 2;
366 pScrPriv
->PaintKey
= fbOverlayPaintKey
;
367 pScrPriv
->CopyWindow
= fbCopyWindowProc
;
368 pScrPriv
->layer
[0].u
.init
.pbits
= pbits1
;
369 pScrPriv
->layer
[0].u
.init
.width
= width1
;
370 pScrPriv
->layer
[0].u
.init
.depth
= depth1
;
372 pScrPriv
->layer
[1].u
.init
.pbits
= pbits2
;
373 pScrPriv
->layer
[1].u
.init
.width
= width2
;
374 pScrPriv
->layer
[1].u
.init
.depth
= depth2
;
375 dixSetPrivate(&pScreen
->devPrivates
, fbOverlayScreenPrivateKey
, pScrPriv
);
377 /* overwrite miCloseScreen with our own */
378 pScreen
->CloseScreen
= fbOverlayCloseScreen
;
379 pScreen
->CreateScreenResources
= fbOverlayCreateScreenResources
;
380 pScreen
->CreateWindow
= fbOverlayCreateWindow
;
381 pScreen
->WindowExposures
= fbOverlayWindowExposures
;
382 pScreen
->CopyWindow
= fbOverlayCopyWindow
;
383 if (bpp
== 24 && imagebpp
== 32) {
384 pScreen
->ModifyPixmapHeader
= fb24_32ModifyPixmapHeader
;
385 pScreen
->CreateScreenResources
= fb24_32OverlayCreateScreenResources
;