xref: /OK3568_Linux_fs/external/xserver/fb/fboverlay.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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