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