~gerchanovsky/xorg-server/trusty

« back to all changes in this revision

Viewing changes to composite/compalloc.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2016-01-13 00:01:28 UTC
  • Revision ID: package-import@ubuntu.com-20160113000128-oc1wb1mr1zfjqlm5
Tags: upstream-1.17.2
ImportĀ upstreamĀ versionĀ 1.17.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice (including the next
 
12
 * paragraph) shall be included in all copies or substantial portions of the
 
13
 * Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
21
 * DEALINGS IN THE SOFTWARE.
 
22
 *
 
23
 * Copyright Ā© 2003 Keith Packard
 
24
 *
 
25
 * Permission to use, copy, modify, distribute, and sell this software and its
 
26
 * documentation for any purpose is hereby granted without fee, provided that
 
27
 * the above copyright notice appear in all copies and that both that
 
28
 * copyright notice and this permission notice appear in supporting
 
29
 * documentation, and that the name of Keith Packard not be used in
 
30
 * advertising or publicity pertaining to distribution of the software without
 
31
 * specific, written prior permission.  Keith Packard makes no
 
32
 * representations about the suitability of this software for any purpose.  It
 
33
 * is provided "as is" without express or implied warranty.
 
34
 *
 
35
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
36
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
37
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
38
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
39
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
40
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
41
 * PERFORMANCE OF THIS SOFTWARE.
 
42
 */
 
43
 
 
44
#ifdef HAVE_DIX_CONFIG_H
 
45
#include <dix-config.h>
 
46
#endif
 
47
 
 
48
#include "compint.h"
 
49
 
 
50
static void
 
51
compScreenUpdate(ScreenPtr pScreen)
 
52
{
 
53
    compCheckTree(pScreen);
 
54
    compPaintChildrenToWindow(pScreen->root);
 
55
}
 
56
 
 
57
static void
 
58
compBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask)
 
59
{
 
60
    CompScreenPtr cs = GetCompScreen(pScreen);
 
61
 
 
62
    pScreen->BlockHandler = cs->BlockHandler;
 
63
    compScreenUpdate(pScreen);
 
64
    (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
 
65
 
 
66
    /* Next damage will restore the block handler */
 
67
    cs->BlockHandler = NULL;
 
68
}
 
69
 
 
70
static void
 
71
compReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure)
 
72
{
 
73
    WindowPtr pWin = (WindowPtr) closure;
 
74
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
75
    CompScreenPtr cs = GetCompScreen(pScreen);
 
76
    CompWindowPtr cw = GetCompWindow(pWin);
 
77
 
 
78
    if (!cs->BlockHandler) {
 
79
        cs->BlockHandler = pScreen->BlockHandler;
 
80
        pScreen->BlockHandler = compBlockHandler;
 
81
    }
 
82
    cw->damaged = TRUE;
 
83
 
 
84
    /* Mark the ancestors */
 
85
    pWin = pWin->parent;
 
86
    while (pWin) {
 
87
        if (pWin->damagedDescendants)
 
88
            break;
 
89
        pWin->damagedDescendants = TRUE;
 
90
        pWin = pWin->parent;
 
91
    }
 
92
}
 
93
 
 
94
static void
 
95
compDestroyDamage(DamagePtr pDamage, void *closure)
 
96
{
 
97
    WindowPtr pWin = (WindowPtr) closure;
 
98
    CompWindowPtr cw = GetCompWindow(pWin);
 
99
 
 
100
    cw->damage = 0;
 
101
}
 
102
 
 
103
static Bool
 
104
compMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin)
 
105
{
 
106
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
107
    WindowPtr pLayerWin = pWin;
 
108
 
 
109
    if (!pWin->viewable)
 
110
        return FALSE;
 
111
 
 
112
    (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
 
113
    (*pScreen->MarkWindow) (pLayerWin->parent);
 
114
 
 
115
    *ppLayerWin = pLayerWin;
 
116
 
 
117
    return TRUE;
 
118
}
 
119
 
 
120
static void
 
121
compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin)
 
122
{
 
123
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
124
 
 
125
    (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
 
126
    (*pScreen->HandleExposures) (pLayerWin->parent);
 
127
    if (pScreen->PostValidateTree)
 
128
        (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
 
129
}
 
130
 
 
131
/*
 
132
 * Redirect one window for one client
 
133
 */
 
134
int
 
135
compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
 
136
{
 
137
    CompWindowPtr cw = GetCompWindow(pWin);
 
138
    CompClientWindowPtr ccw;
 
139
    CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
 
140
    WindowPtr pLayerWin;
 
141
    Bool anyMarked = FALSE;
 
142
 
 
143
    if (pWin == cs->pOverlayWin) {
 
144
        return Success;
 
145
    }
 
146
 
 
147
    if (!pWin->parent)
 
148
        return BadMatch;
 
149
 
 
150
    /*
 
151
     * Only one Manual update is allowed
 
152
     */
 
153
    if (cw && update == CompositeRedirectManual)
 
154
        for (ccw = cw->clients; ccw; ccw = ccw->next)
 
155
            if (ccw->update == CompositeRedirectManual)
 
156
                return BadAccess;
 
157
 
 
158
    /*
 
159
     * Allocate per-client per-window structure
 
160
     * The client *could* allocate multiple, but while supported,
 
161
     * it is not expected to be common
 
162
     */
 
163
    ccw = malloc(sizeof(CompClientWindowRec));
 
164
    if (!ccw)
 
165
        return BadAlloc;
 
166
    ccw->id = FakeClientID(pClient->index);
 
167
    ccw->update = update;
 
168
    /*
 
169
     * Now make sure there's a per-window structure to hang this from
 
170
     */
 
171
    if (!cw) {
 
172
        cw = malloc(sizeof(CompWindowRec));
 
173
        if (!cw) {
 
174
            free(ccw);
 
175
            return BadAlloc;
 
176
        }
 
177
        cw->damage = DamageCreate(compReportDamage,
 
178
                                  compDestroyDamage,
 
179
                                  DamageReportNonEmpty,
 
180
                                  FALSE, pWin->drawable.pScreen, pWin);
 
181
        if (!cw->damage) {
 
182
            free(ccw);
 
183
            free(cw);
 
184
            return BadAlloc;
 
185
        }
 
186
 
 
187
        anyMarked = compMarkWindows(pWin, &pLayerWin);
 
188
 
 
189
        RegionNull(&cw->borderClip);
 
190
        cw->update = CompositeRedirectAutomatic;
 
191
        cw->clients = 0;
 
192
        cw->oldx = COMP_ORIGIN_INVALID;
 
193
        cw->oldy = COMP_ORIGIN_INVALID;
 
194
        cw->damageRegistered = FALSE;
 
195
        cw->damaged = FALSE;
 
196
        cw->pOldPixmap = NullPixmap;
 
197
        dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
 
198
    }
 
199
    ccw->next = cw->clients;
 
200
    cw->clients = ccw;
 
201
    if (!AddResource(ccw->id, CompositeClientWindowType, pWin))
 
202
        return BadAlloc;
 
203
    if (ccw->update == CompositeRedirectManual) {
 
204
        if (!anyMarked)
 
205
            anyMarked = compMarkWindows(pWin, &pLayerWin);
 
206
 
 
207
        if (cw->damageRegistered) {
 
208
            DamageUnregister(cw->damage);
 
209
            cw->damageRegistered = FALSE;
 
210
        }
 
211
        cw->update = CompositeRedirectManual;
 
212
    }
 
213
    else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) {
 
214
        if (!anyMarked)
 
215
            anyMarked = compMarkWindows(pWin, &pLayerWin);
 
216
    }
 
217
 
 
218
    if (!compCheckRedirect(pWin)) {
 
219
        FreeResource(ccw->id, RT_NONE);
 
220
        return BadAlloc;
 
221
    }
 
222
 
 
223
    if (anyMarked)
 
224
        compHandleMarkedWindows(pWin, pLayerWin);
 
225
 
 
226
    return Success;
 
227
}
 
228
 
 
229
void
 
230
compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap)
 
231
{
 
232
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
233
    WindowPtr pParent = pWin->parent;
 
234
 
 
235
    if (pParent->drawable.depth == pWin->drawable.depth) {
 
236
        GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
 
237
        int bw = (int) pWin->borderWidth;
 
238
        int x = bw;
 
239
        int y = bw;
 
240
        int w = pWin->drawable.width;
 
241
        int h = pWin->drawable.height;
 
242
 
 
243
        if (pGC) {
 
244
            ChangeGCVal val;
 
245
 
 
246
            val.val = IncludeInferiors;
 
247
            ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
 
248
            ValidateGC(&pWin->drawable, pGC);
 
249
            (*pGC->ops->CopyArea) (&pPixmap->drawable,
 
250
                                   &pWin->drawable, pGC, x, y, w, h, 0, 0);
 
251
            FreeScratchGC(pGC);
 
252
        }
 
253
    }
 
254
}
 
255
 
 
256
/*
 
257
 * Free one of the per-client per-window resources, clearing
 
258
 * redirect and the per-window pointer as appropriate
 
259
 */
 
260
void
 
261
compFreeClientWindow(WindowPtr pWin, XID id)
 
262
{
 
263
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
264
    CompWindowPtr cw = GetCompWindow(pWin);
 
265
    CompClientWindowPtr ccw, *prev;
 
266
    Bool anyMarked = FALSE;
 
267
    WindowPtr pLayerWin;
 
268
    PixmapPtr pPixmap = NULL;
 
269
 
 
270
    if (!cw)
 
271
        return;
 
272
    for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) {
 
273
        if (ccw->id == id) {
 
274
            *prev = ccw->next;
 
275
            if (ccw->update == CompositeRedirectManual)
 
276
                cw->update = CompositeRedirectAutomatic;
 
277
            free(ccw);
 
278
            break;
 
279
        }
 
280
    }
 
281
    if (!cw->clients) {
 
282
        anyMarked = compMarkWindows(pWin, &pLayerWin);
 
283
 
 
284
        if (pWin->redirectDraw != RedirectDrawNone) {
 
285
            pPixmap = (*pScreen->GetWindowPixmap) (pWin);
 
286
            compSetParentPixmap(pWin);
 
287
        }
 
288
 
 
289
        if (cw->damage)
 
290
            DamageDestroy(cw->damage);
 
291
 
 
292
        RegionUninit(&cw->borderClip);
 
293
 
 
294
        dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
 
295
        free(cw);
 
296
    }
 
297
    else if (cw->update == CompositeRedirectAutomatic &&
 
298
             !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) {
 
299
        anyMarked = compMarkWindows(pWin, &pLayerWin);
 
300
 
 
301
        DamageRegister(&pWin->drawable, cw->damage);
 
302
        cw->damageRegistered = TRUE;
 
303
        pWin->redirectDraw = RedirectDrawAutomatic;
 
304
        DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
 
305
    }
 
306
 
 
307
    if (anyMarked)
 
308
        compHandleMarkedWindows(pWin, pLayerWin);
 
309
 
 
310
    if (pPixmap) {
 
311
        compRestoreWindow(pWin, pPixmap);
 
312
        (*pScreen->DestroyPixmap) (pPixmap);
 
313
    }
 
314
}
 
315
 
 
316
/*
 
317
 * This is easy, just free the appropriate resource.
 
318
 */
 
319
 
 
320
int
 
321
compUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
 
322
{
 
323
    CompWindowPtr cw = GetCompWindow(pWin);
 
324
    CompClientWindowPtr ccw;
 
325
 
 
326
    if (!cw)
 
327
        return BadValue;
 
328
 
 
329
    for (ccw = cw->clients; ccw; ccw = ccw->next)
 
330
        if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) {
 
331
            FreeResource(ccw->id, RT_NONE);
 
332
            return Success;
 
333
        }
 
334
    return BadValue;
 
335
}
 
336
 
 
337
/*
 
338
 * Redirect all subwindows for one client
 
339
 */
 
340
 
 
341
int
 
342
compRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
 
343
{
 
344
    CompSubwindowsPtr csw = GetCompSubwindows(pWin);
 
345
    CompClientWindowPtr ccw;
 
346
    WindowPtr pChild;
 
347
 
 
348
    /*
 
349
     * Only one Manual update is allowed
 
350
     */
 
351
    if (csw && update == CompositeRedirectManual)
 
352
        for (ccw = csw->clients; ccw; ccw = ccw->next)
 
353
            if (ccw->update == CompositeRedirectManual)
 
354
                return BadAccess;
 
355
    /*
 
356
     * Allocate per-client per-window structure
 
357
     * The client *could* allocate multiple, but while supported,
 
358
     * it is not expected to be common
 
359
     */
 
360
    ccw = malloc(sizeof(CompClientWindowRec));
 
361
    if (!ccw)
 
362
        return BadAlloc;
 
363
    ccw->id = FakeClientID(pClient->index);
 
364
    ccw->update = update;
 
365
    /*
 
366
     * Now make sure there's a per-window structure to hang this from
 
367
     */
 
368
    if (!csw) {
 
369
        csw = malloc(sizeof(CompSubwindowsRec));
 
370
        if (!csw) {
 
371
            free(ccw);
 
372
            return BadAlloc;
 
373
        }
 
374
        csw->update = CompositeRedirectAutomatic;
 
375
        csw->clients = 0;
 
376
        dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
 
377
    }
 
378
    /*
 
379
     * Redirect all existing windows
 
380
     */
 
381
    for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) {
 
382
        int ret = compRedirectWindow(pClient, pChild, update);
 
383
 
 
384
        if (ret != Success) {
 
385
            for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
 
386
                (void) compUnredirectWindow(pClient, pChild, update);
 
387
            if (!csw->clients) {
 
388
                free(csw);
 
389
                dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
 
390
            }
 
391
            free(ccw);
 
392
            return ret;
 
393
        }
 
394
    }
 
395
    /*
 
396
     * Hook into subwindows list
 
397
     */
 
398
    ccw->next = csw->clients;
 
399
    csw->clients = ccw;
 
400
    if (!AddResource(ccw->id, CompositeClientSubwindowsType, pWin))
 
401
        return BadAlloc;
 
402
    if (ccw->update == CompositeRedirectManual) {
 
403
        csw->update = CompositeRedirectManual;
 
404
        /*
 
405
         * tell damage extension that damage events for this client are
 
406
         * critical output
 
407
         */
 
408
        DamageExtSetCritical(pClient, TRUE);
 
409
        pWin->inhibitBGPaint = TRUE;
 
410
    }
 
411
    return Success;
 
412
}
 
413
 
 
414
/*
 
415
 * Free one of the per-client per-subwindows resources,
 
416
 * which frees one redirect per subwindow
 
417
 */
 
418
void
 
419
compFreeClientSubwindows(WindowPtr pWin, XID id)
 
420
{
 
421
    CompSubwindowsPtr csw = GetCompSubwindows(pWin);
 
422
    CompClientWindowPtr ccw, *prev;
 
423
    WindowPtr pChild;
 
424
 
 
425
    if (!csw)
 
426
        return;
 
427
    for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) {
 
428
        if (ccw->id == id) {
 
429
            ClientPtr pClient = clients[CLIENT_ID(id)];
 
430
 
 
431
            *prev = ccw->next;
 
432
            if (ccw->update == CompositeRedirectManual) {
 
433
                /*
 
434
                 * tell damage extension that damage events for this client are
 
435
                 * critical output
 
436
                 */
 
437
                DamageExtSetCritical(pClient, FALSE);
 
438
                csw->update = CompositeRedirectAutomatic;
 
439
                pWin->inhibitBGPaint = FALSE;
 
440
                if (pWin->mapped)
 
441
                    (*pWin->drawable.pScreen->ClearToBackground) (pWin, 0, 0, 0,
 
442
                                                                  0, TRUE);
 
443
            }
 
444
 
 
445
            /*
 
446
             * Unredirect all existing subwindows
 
447
             */
 
448
            for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
 
449
                (void) compUnredirectWindow(pClient, pChild, ccw->update);
 
450
 
 
451
            free(ccw);
 
452
            break;
 
453
        }
 
454
    }
 
455
 
 
456
    /*
 
457
     * Check if all of the per-client records are gone
 
458
     */
 
459
    if (!csw->clients) {
 
460
        dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
 
461
        free(csw);
 
462
    }
 
463
}
 
464
 
 
465
/*
 
466
 * This is easy, just free the appropriate resource.
 
467
 */
 
468
 
 
469
int
 
470
compUnredirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
 
471
{
 
472
    CompSubwindowsPtr csw = GetCompSubwindows(pWin);
 
473
    CompClientWindowPtr ccw;
 
474
 
 
475
    if (!csw)
 
476
        return BadValue;
 
477
    for (ccw = csw->clients; ccw; ccw = ccw->next)
 
478
        if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) {
 
479
            FreeResource(ccw->id, RT_NONE);
 
480
            return Success;
 
481
        }
 
482
    return BadValue;
 
483
}
 
484
 
 
485
/*
 
486
 * Add redirection information for one subwindow (during reparent)
 
487
 */
 
488
 
 
489
int
 
490
compRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
 
491
{
 
492
    CompSubwindowsPtr csw = GetCompSubwindows(pParent);
 
493
    CompClientWindowPtr ccw;
 
494
 
 
495
    if (!csw)
 
496
        return Success;
 
497
    for (ccw = csw->clients; ccw; ccw = ccw->next) {
 
498
        int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)],
 
499
                                     pWin, ccw->update);
 
500
 
 
501
        if (ret != Success)
 
502
            return ret;
 
503
    }
 
504
    return Success;
 
505
}
 
506
 
 
507
/*
 
508
 * Remove redirection information for one subwindow (during reparent)
 
509
 */
 
510
 
 
511
int
 
512
compUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
 
513
{
 
514
    CompSubwindowsPtr csw = GetCompSubwindows(pParent);
 
515
    CompClientWindowPtr ccw;
 
516
 
 
517
    if (!csw)
 
518
        return Success;
 
519
    for (ccw = csw->clients; ccw; ccw = ccw->next) {
 
520
        int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)],
 
521
                                       pWin, ccw->update);
 
522
 
 
523
        if (ret != Success)
 
524
            return ret;
 
525
    }
 
526
    return Success;
 
527
}
 
528
 
 
529
static PixmapPtr
 
530
compNewPixmap(WindowPtr pWin, int x, int y, int w, int h)
 
531
{
 
532
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
533
    WindowPtr pParent = pWin->parent;
 
534
    PixmapPtr pPixmap;
 
535
 
 
536
    pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
 
537
                                        CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
 
538
 
 
539
    if (!pPixmap)
 
540
        return 0;
 
541
 
 
542
    pPixmap->screen_x = x;
 
543
    pPixmap->screen_y = y;
 
544
 
 
545
    if (pParent->drawable.depth == pWin->drawable.depth) {
 
546
        GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
 
547
 
 
548
        if (pGC) {
 
549
            ChangeGCVal val;
 
550
 
 
551
            val.val = IncludeInferiors;
 
552
            ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
 
553
            ValidateGC(&pPixmap->drawable, pGC);
 
554
            (*pGC->ops->CopyArea) (&pParent->drawable,
 
555
                                   &pPixmap->drawable,
 
556
                                   pGC,
 
557
                                   x - pParent->drawable.x,
 
558
                                   y - pParent->drawable.y, w, h, 0, 0);
 
559
            FreeScratchGC(pGC);
 
560
        }
 
561
    }
 
562
    else {
 
563
        PictFormatPtr pSrcFormat = PictureWindowFormat(pParent);
 
564
        PictFormatPtr pDstFormat = PictureWindowFormat(pWin);
 
565
        XID inferiors = IncludeInferiors;
 
566
        int error;
 
567
 
 
568
        PicturePtr pSrcPicture = CreatePicture(None,
 
569
                                               &pParent->drawable,
 
570
                                               pSrcFormat,
 
571
                                               CPSubwindowMode,
 
572
                                               &inferiors,
 
573
                                               serverClient, &error);
 
574
 
 
575
        PicturePtr pDstPicture = CreatePicture(None,
 
576
                                               &pPixmap->drawable,
 
577
                                               pDstFormat,
 
578
                                               0, 0,
 
579
                                               serverClient, &error);
 
580
 
 
581
        if (pSrcPicture && pDstPicture) {
 
582
            CompositePicture(PictOpSrc,
 
583
                             pSrcPicture,
 
584
                             NULL,
 
585
                             pDstPicture,
 
586
                             x - pParent->drawable.x,
 
587
                             y - pParent->drawable.y, 0, 0, 0, 0, w, h);
 
588
        }
 
589
        if (pSrcPicture)
 
590
            FreePicture(pSrcPicture, 0);
 
591
        if (pDstPicture)
 
592
            FreePicture(pDstPicture, 0);
 
593
    }
 
594
    return pPixmap;
 
595
}
 
596
 
 
597
Bool
 
598
compAllocPixmap(WindowPtr pWin)
 
599
{
 
600
    int bw = (int) pWin->borderWidth;
 
601
    int x = pWin->drawable.x - bw;
 
602
    int y = pWin->drawable.y - bw;
 
603
    int w = pWin->drawable.width + (bw << 1);
 
604
    int h = pWin->drawable.height + (bw << 1);
 
605
    PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h);
 
606
    CompWindowPtr cw = GetCompWindow(pWin);
 
607
 
 
608
    if (!pPixmap)
 
609
        return FALSE;
 
610
    if (cw->update == CompositeRedirectAutomatic)
 
611
        pWin->redirectDraw = RedirectDrawAutomatic;
 
612
    else
 
613
        pWin->redirectDraw = RedirectDrawManual;
 
614
 
 
615
    compSetPixmap(pWin, pPixmap);
 
616
    cw->oldx = COMP_ORIGIN_INVALID;
 
617
    cw->oldy = COMP_ORIGIN_INVALID;
 
618
    cw->damageRegistered = FALSE;
 
619
    if (cw->update == CompositeRedirectAutomatic) {
 
620
        DamageRegister(&pWin->drawable, cw->damage);
 
621
        cw->damageRegistered = TRUE;
 
622
    }
 
623
 
 
624
    /* Make sure our borderClip is up to date */
 
625
    RegionUninit(&cw->borderClip);
 
626
    RegionCopy(&cw->borderClip, &pWin->borderClip);
 
627
    cw->borderClipX = pWin->drawable.x;
 
628
    cw->borderClipY = pWin->drawable.y;
 
629
 
 
630
    return TRUE;
 
631
}
 
632
 
 
633
void
 
634
compSetParentPixmap(WindowPtr pWin)
 
635
{
 
636
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
637
    PixmapPtr pParentPixmap;
 
638
    CompWindowPtr cw = GetCompWindow(pWin);
 
639
 
 
640
    if (cw->damageRegistered) {
 
641
        DamageUnregister(cw->damage);
 
642
        cw->damageRegistered = FALSE;
 
643
        DamageEmpty(cw->damage);
 
644
    }
 
645
    /*
 
646
     * Move the parent-constrained border clip region back into
 
647
     * the window so that ValidateTree will handle the unmap
 
648
     * case correctly.  Unmap adds the window borderClip to the
 
649
     * parent exposed area; regions beyond the parent cause crashes
 
650
     */
 
651
    RegionCopy(&pWin->borderClip, &cw->borderClip);
 
652
    pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
 
653
    pWin->redirectDraw = RedirectDrawNone;
 
654
    compSetPixmap(pWin, pParentPixmap);
 
655
}
 
656
 
 
657
/*
 
658
 * Make sure the pixmap is the right size and offset.  Allocate a new
 
659
 * pixmap to change size, adjust origin to change offset, leaving the
 
660
 * old pixmap in cw->pOldPixmap so bits can be recovered
 
661
 */
 
662
Bool
 
663
compReallocPixmap(WindowPtr pWin, int draw_x, int draw_y,
 
664
                  unsigned int w, unsigned int h, int bw)
 
665
{
 
666
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
667
    PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
 
668
    PixmapPtr pNew;
 
669
    CompWindowPtr cw = GetCompWindow(pWin);
 
670
    int pix_x, pix_y;
 
671
    int pix_w, pix_h;
 
672
 
 
673
    assert(cw && pWin->redirectDraw != RedirectDrawNone);
 
674
    cw->oldx = pOld->screen_x;
 
675
    cw->oldy = pOld->screen_y;
 
676
    pix_x = draw_x - bw;
 
677
    pix_y = draw_y - bw;
 
678
    pix_w = w + (bw << 1);
 
679
    pix_h = h + (bw << 1);
 
680
    if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) {
 
681
        pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h);
 
682
        if (!pNew)
 
683
            return FALSE;
 
684
        cw->pOldPixmap = pOld;
 
685
        compSetPixmap(pWin, pNew);
 
686
    }
 
687
    else {
 
688
        pNew = pOld;
 
689
        cw->pOldPixmap = 0;
 
690
    }
 
691
    pNew->screen_x = pix_x;
 
692
    pNew->screen_y = pix_y;
 
693
    return TRUE;
 
694
}