]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/xserver.git/blob - fb/fboverlay.c
Imported Upstream version 1.11.4
[glsdk/xserver.git] / fb / fboverlay.c
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;
54     
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)
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;
114 Bool
115 fbOverlayCreateScreenResources(ScreenPtr pScreen)
117     int                 i;
118     FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
119     PixmapPtr           pPixmap;
120     pointer             pbits;
121     int                 width;
122     int                 depth;
123     BoxRec              box;
124     
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;
153 void
154 fbOverlayPaintKey (DrawablePtr  pDrawable,
155                    RegionPtr    pRegion,
156                    CARD32       pixel,
157                    int          layer)
159     fbFillRegionSolid (pDrawable, pRegion, 0, 
160                        fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
163 /*
164  * Track visible region for each layer
165  */
166 void
167 fbOverlayUpdateLayerRegion (ScreenPtr   pScreen,
168                             int         layer,
169                             RegionPtr   prgn)
171     FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
172     int                 i;
173     RegionRec           rgnNew;
174     
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     }
205 /*
206  * Copy only areas in each layer containing real bits
207  */
208 void
209 fbOverlayCopyWindow(WindowPtr   pWin,
210                     DDXPointRec ptOldOrg,
211                     RegionPtr   prgnSrc)
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)
267     fbOverlayUpdateLayerRegion (pWin->drawable.pScreen,
268                                 fbOverlayWindowLayer (pWin),
269                                 prgn);
270     miWindowExposures(pWin, prgn, other_exposed);
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)
286     return fbSetupScreen (pScreen,
287                           pbits1,
288                           xsize,
289                           ysize,
290                           dpix,
291                           dpiy,
292                           width1,
293                           bpp1);
296 static Bool
297 fb24_32OverlayCreateScreenResources(ScreenPtr pScreen)
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;
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)
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;
349  
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;
358         
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     }
384    
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;
403     
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);
415     
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;