~brandontschaefer/+junk/break-x

« back to all changes in this revision

Viewing changes to fb/fboverlay.c

  • Committer: Brandon Schaefer
  • Date: 2014-09-30 19:38:40 UTC
  • Revision ID: brandon.schaefer@canonical.com-20140930193840-a65z6qk8ze02cgsb
* Init commit to back this up

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
 
24
 
 
25
#ifdef HAVE_DIX_CONFIG_H
 
26
#include <dix-config.h>
 
27
#endif
 
28
 
 
29
#include <stdlib.h>
 
30
 
 
31
#include "fb.h"
 
32
#include "fboverlay.h"
 
33
#include "shmint.h"
 
34
 
 
35
static DevPrivateKeyRec fbOverlayScreenPrivateKeyRec;
 
36
 
 
37
#define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec)
 
38
 
 
39
DevPrivateKey
 
40
fbOverlayGetScreenPrivateKey(void)
 
41
{
 
42
    return fbOverlayScreenPrivateKey;
 
43
}
 
44
 
 
45
/*
 
46
 * Replace this if you want something supporting
 
47
 * multiple overlays with the same depth
 
48
 */
 
49
Bool
 
50
fbOverlayCreateWindow(WindowPtr pWin)
 
51
{
 
52
    FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
 
53
    int i;
 
54
    PixmapPtr pPixmap;
 
55
 
 
56
    if (pWin->drawable.class != InputOutput)
 
57
        return TRUE;
 
58
 
 
59
    if (pWin->drawable.bitsPerPixel == 32)
 
60
        pWin->drawable.bitsPerPixel =
 
61
            fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp;
 
62
 
 
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);
 
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
                RegionEmpty(&pScrPriv->layer[i].u.run.region);
 
76
            }
 
77
            return TRUE;
 
78
        }
 
79
    }
 
80
    return FALSE;
 
81
}
 
82
 
 
83
Bool
 
84
fbOverlayCloseScreen(ScreenPtr pScreen)
 
85
{
 
86
    FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
 
87
    int i;
 
88
 
 
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);
 
92
    }
 
93
    return TRUE;
 
94
}
 
95
 
 
96
/*
 
97
 * Return layer containing this window
 
98
 */
 
99
int
 
100
fbOverlayWindowLayer(WindowPtr pWin)
 
101
{
 
102
    FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
 
103
    int i;
 
104
 
 
105
    for (i = 0; i < pScrPriv->nlayers; i++)
 
106
        if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin)) ==
 
107
            (void *) pScrPriv->layer[i].u.run.pixmap)
 
108
            return i;
 
109
    return 0;
 
110
}
 
111
 
 
112
Bool
 
113
fbOverlayCreateScreenResources(ScreenPtr pScreen)
 
114
{
 
115
    int i;
 
116
    FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
 
117
    PixmapPtr pPixmap;
 
118
    void *pbits;
 
119
    int width;
 
120
    int depth;
 
121
    BoxRec box;
 
122
 
 
123
    if (!miCreateScreenResources(pScreen))
 
124
        return FALSE;
 
125
 
 
126
    box.x1 = 0;
 
127
    box.y1 = 0;
 
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);
 
135
        if (!pPixmap)
 
136
            return FALSE;
 
137
        if (!(*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width,
 
138
                                             pScreen->height, depth,
 
139
                                             BitsPerPixel(depth),
 
140
                                             PixmapBytePad(width, depth),
 
141
                                             pbits))
 
142
            return FALSE;
 
143
        pScrPriv->layer[i].u.run.pixmap = pPixmap;
 
144
        RegionInit(&pScrPriv->layer[i].u.run.region, &box, 0);
 
145
    }
 
146
    pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap;
 
147
    return TRUE;
 
148
}
 
149
 
 
150
void
 
151
fbOverlayPaintKey(DrawablePtr pDrawable,
 
152
                  RegionPtr pRegion, CARD32 pixel, int layer)
 
153
{
 
154
    fbFillRegionSolid(pDrawable, pRegion, 0,
 
155
                      fbReplicatePixel(pixel, pDrawable->bitsPerPixel));
 
156
}
 
157
 
 
158
/*
 
159
 * Track visible region for each layer
 
160
 */
 
161
void
 
162
fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn)
 
163
{
 
164
    FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
 
165
    int i;
 
166
    RegionRec rgnNew;
 
167
 
 
168
    if (!prgn || !RegionNotEmpty(prgn))
 
169
        return;
 
170
    for (i = 0; i < pScrPriv->nlayers; i++) {
 
171
        if (i == layer) {
 
172
            /* add new piece to this fb */
 
173
            RegionUnion(&pScrPriv->layer[i].u.run.region,
 
174
                        &pScrPriv->layer[i].u.run.region, prgn);
 
175
        }
 
176
        else if (RegionNotEmpty(&pScrPriv->layer[i].u.run.region)) {
 
177
            /* paint new piece with chroma key */
 
178
            RegionNull(&rgnNew);
 
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);
 
186
        }
 
187
    }
 
188
}
 
189
 
 
190
/*
 
191
 * Copy only areas in each layer containing real bits
 
192
 */
 
193
void
 
194
fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 
195
{
 
196
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
197
    FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
 
198
    RegionRec rgnDst;
 
199
    int dx, dy;
 
200
    int i;
 
201
    RegionRec layerRgn[FB_OVERLAY_MAX];
 
202
    PixmapPtr pPixmap;
 
203
 
 
204
    dx = ptOldOrg.x - pWin->drawable.x;
 
205
    dy = ptOldOrg.y - pWin->drawable.y;
 
206
 
 
207
    /*
 
208
     * Clip to existing bits
 
209
     */
 
210
    RegionTranslate(prgnSrc, -dx, -dy);
 
211
    RegionNull(&rgnDst);
 
212
    RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
 
213
    RegionTranslate(&rgnDst, dx, dy);
 
214
    /*
 
215
     * Compute the portion of each fb affected by this copy
 
216
     */
 
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,
 
225
                         0,
 
226
                         &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0,
 
227
                         (void *) (long) i);
 
228
        }
 
229
    }
 
230
    /*
 
231
     * Update regions
 
232
     */
 
233
    for (i = 0; i < pScrPriv->nlayers; i++) {
 
234
        if (RegionNotEmpty(&layerRgn[i]))
 
235
            fbOverlayUpdateLayerRegion(pScreen, i, &layerRgn[i]);
 
236
 
 
237
        RegionUninit(&layerRgn[i]);
 
238
    }
 
239
    RegionUninit(&rgnDst);
 
240
}
 
241
 
 
242
void
 
243
fbOverlayWindowExposures(WindowPtr pWin,
 
244
                         RegionPtr prgn, RegionPtr other_exposed)
 
245
{
 
246
    fbOverlayUpdateLayerRegion(pWin->drawable.pScreen,
 
247
                               fbOverlayWindowLayer(pWin), prgn);
 
248
    miWindowExposures(pWin, prgn, other_exposed);
 
249
}
 
250
 
 
251
Bool
 
252
fbOverlaySetupScreen(ScreenPtr pScreen,
 
253
                     void *pbits1,
 
254
                     void *pbits2,
 
255
                     int xsize,
 
256
                     int ysize,
 
257
                     int dpix,
 
258
                     int dpiy, int width1, int width2, int bpp1, int bpp2)
 
259
{
 
260
    return fbSetupScreen(pScreen,
 
261
                         pbits1, xsize, ysize, dpix, dpiy, width1, bpp1);
 
262
}
 
263
 
 
264
static Bool
 
265
fb24_32OverlayCreateScreenResources(ScreenPtr pScreen)
 
266
{
 
267
    FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
 
268
    int pitch;
 
269
    Bool retval;
 
270
    int i;
 
271
 
 
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;
 
276
 
 
277
            if (pPix->drawable.bitsPerPixel == 32) {
 
278
                pPix->drawable.bitsPerPixel = 24;
 
279
                pitch = BitmapBytePad(pPix->drawable.width * 24);
 
280
                pPix->devKind = pitch;
 
281
            }
 
282
        }
 
283
    }
 
284
 
 
285
    return retval;
 
286
}
 
287
 
 
288
Bool
 
289
fbOverlayFinishScreenInit(ScreenPtr pScreen,
 
290
                          void *pbits1,
 
291
                          void *pbits2,
 
292
                          int xsize,
 
293
                          int ysize,
 
294
                          int dpix,
 
295
                          int dpiy,
 
296
                          int width1,
 
297
                          int width2,
 
298
                          int bpp1, int bpp2, int depth1, int depth2)
 
299
{
 
300
    VisualPtr visuals;
 
301
    DepthPtr depths;
 
302
    int nvisuals;
 
303
    int ndepths;
 
304
    int bpp = 0, imagebpp = 32;
 
305
    VisualID defaultVisual;
 
306
    FbOverlayScrPrivPtr pScrPriv;
 
307
 
 
308
    if (!dixRegisterPrivateKey
 
309
        (&fbOverlayScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
 
310
        return FALSE;
 
311
 
 
312
    pScrPriv = malloc(sizeof(FbOverlayScrPrivRec));
 
313
    if (!pScrPriv)
 
314
        return FALSE;
 
315
 
 
316
    if (bpp1 == 32 || bpp2 == 32)
 
317
        bpp = 32;
 
318
    else if (bpp1 == 24 || bpp2 == 24)
 
319
        bpp = 24;
 
320
 
 
321
    if (bpp == 24) {
 
322
        int f;
 
323
 
 
324
        imagebpp = 32;
 
325
        /*
 
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
 
328
         * format.
 
329
         */
 
330
        for (f = 0; f < screenInfo.numPixmapFormats; f++) {
 
331
            if (screenInfo.formats[f].bitsPerPixel == 24) {
 
332
                imagebpp = 24;
 
333
                break;
 
334
            }
 
335
        }
 
336
    }
 
337
    if (imagebpp == 32) {
 
338
        fbGetScreenPrivate(pScreen)->win32bpp = bpp;
 
339
        fbGetScreenPrivate(pScreen)->pix32bpp = bpp;
 
340
    }
 
341
    else {
 
342
        fbGetScreenPrivate(pScreen)->win32bpp = 32;
 
343
        fbGetScreenPrivate(pScreen)->pix32bpp = 32;
 
344
    }
 
345
 
 
346
    if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1,
 
347
                       &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) |
 
348
                       ((unsigned long) 1 << (bpp2 - 1)), 8)) {
 
349
        free(pScrPriv);
 
350
        return FALSE;
 
351
    }
 
352
    if (!miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0,
 
353
                      depth1, ndepths, depths,
 
354
                      defaultVisual, nvisuals, visuals)) {
 
355
        free(pScrPriv);
 
356
        return FALSE;
 
357
    }
 
358
    /* MI thinks there's no frame buffer */
 
359
#ifdef MITSHM
 
360
    ShmRegisterFbFuncs(pScreen);
 
361
#endif
 
362
    pScreen->minInstalledCmaps = 1;
 
363
    pScreen->maxInstalledCmaps = 2;
 
364
 
 
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;
 
371
 
 
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);
 
376
 
 
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;
 
386
    }
 
387
 
 
388
    return TRUE;
 
389
}