]> git.cworth.org Git - cworth.org/blob - src/exa/i965/synchronous_composite/EXA-no-gettimeofday/opannotate.source
Add synchronous composite blog entry
[cworth.org] / src / exa / i965 / synchronous_composite / EXA-no-gettimeofday / opannotate.source
1 /* 
2  * Command line: opannotate --source 
3  * 
4  * Interpretation of command line:
5  * Output annotated source file with samples
6  * Output all files
7  * 
8  * CPU: Core 2, speed 2133.49 MHz (estimated)
9  * Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
10  */
11 /* 
12  * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i830_accel.c"
13  * 
14  *  31562 34.3831
15  */
16
17
18                :/*
19                : * XXX So far, for GXxor this is about 40% of the speed of SW, but CPU
20                : * utilisation falls from 95% to < 5%.
21                : */
22                :
23                :#ifdef HAVE_CONFIG_H
24                :#include "config.h"
25                :#endif
26                :
27                :/**************************************************************************
28                :
29                :Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
30                :All Rights Reserved.
31                :
32                :Permission is hereby granted, free of charge, to any person obtaining a
33                :copy of this software and associated documentation files (the
34                :"Software"), to deal in the Software without restriction, including
35                :without limitation the rights to use, copy, modify, merge, publish,
36                :distribute, sub license, and/or sell copies of the Software, and to
37                :permit persons to whom the Software is furnished to do so, subject to
38                :the following conditions:
39                :
40                :The above copyright notice and this permission notice (including the
41                :next paragraph) shall be included in all copies or substantial portions
42                :of the Software.
43                :
44                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
45                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
46                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
47                :IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
48                :ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
49                :TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
50                :SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
51                :
52                :**************************************************************************/
53                :/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_accel.c,v 1.8 2003/04/24 18:00:24 eich Exp $ */
54                :
55                :/*
56                : * Reformatted with GNU indent (2.2.8), using the following options:
57                : *
58                : *    -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
59                : *    -lp -npcs -psl -sob -ss -br -ce -sc -hnl
60                : *
61                : * This provides a good match with the original i810 code and preferred
62                : * XFree86 formatting conventions.
63                : *
64                : * When editing this driver, please follow the existing formatting, and edit
65                : * with <TAB> characters expanded at 8-column intervals.
66                : */
67                :
68                :/*
69                : * Authors:
70                : *   Keith Whitwell <keith@tungstengraphics.com>
71                : *
72                : */
73                :
74                :#include "xf86.h"
75                :#include "xaarop.h"
76                :#include "i830.h"
77                :#include "i810_reg.h"
78                :#include "i830_debug.h"
79                :
80                :unsigned long
81                :intel_get_pixmap_offset(PixmapPtr pPix)
82     15  0.0163 :{ /* intel_get_pixmap_offset total:     77  0.0839 */
83                :    ScreenPtr pScreen = pPix->drawable.pScreen;
84                :    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
85     27  0.0294 :    I830Ptr pI830 = I830PTR(pScrn);
86                :
87                :#ifdef I830_USE_EXA
88     24  0.0261 :    if (pI830->useEXA)
89      4  0.0044 :        return exaGetPixmapOffset(pPix);
90                :#endif
91                :    return (unsigned long)pPix->devPrivate.ptr - (unsigned long)pI830->FbBase;
92      7  0.0076 :}
93                :
94                :unsigned long
95                :intel_get_pixmap_pitch(PixmapPtr pPix)
96     12  0.0131 :{ /* intel_get_pixmap_pitch total:     83  0.0904 */
97                :    ScreenPtr pScreen = pPix->drawable.pScreen;
98                :    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
99                :    I830Ptr pI830 = I830PTR(pScrn);
100                :
101                :#ifdef I830_USE_EXA
102     57  0.0621 :    if (pI830->useEXA)
103      4  0.0044 :        return exaGetPixmapPitch(pPix);
104                :#endif
105                :#ifdef I830_USE_XAA
106                :    return (unsigned long)pPix->devKind;
107                :#endif
108     10  0.0109 :}
109                :
110                :int
111                :I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
112     10  0.0109 :{ /* I830WaitLpRing total:  31130 33.9125 */
113      2  0.0022 :   I830Ptr pI830 = I830PTR(pScrn);
114      1  0.0011 :   I830RingBuffer *ring = pI830->LpRing;
115                :   int iters = 0;
116                :   unsigned int start = 0;
117                :   unsigned int now = 0;
118                :   int last_head = 0;
119                :   unsigned int first = 0;
120                :
121                :   /* If your system hasn't moved the head pointer in 2 seconds, I'm going to
122                :    * call it crashed.
123                :    */
124                :   if (timeout_millis == 0)
125                :      timeout_millis = 2000;
126                :
127                :   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
128                :      ErrorF("I830WaitLpRing %d\n", n);
129                :      first = GetTimeInMillis();
130                :   }
131                :
132    383  0.4172 :   while (ring->space < n) {
133    217  0.2364 :      ring->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
134  30204 32.9038 :      ring->space = ring->head - (ring->tail + 8);
135                :
136                :      if (ring->space < 0)
137    145  0.1580 :         ring->space += ring->mem->size;
138                :
139     93  0.1013 :      iters++;
140                :      if ((iters & 0xfff) == 0) {
141                :          now = GetTimeInMillis();
142                :          if (start == 0 || now < start || ring->head != last_head) {
143                :              if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
144                :                  if (now > start)
145                :                      ErrorF("space: %d wanted %d\n", ring->space, n);
146                :              start = now;
147                :              last_head = ring->head;
148                :          } else if (now - start > timeout_millis) {
149                :              ErrorF("Error in I830WaitLpRing(), timeout for %d seconds\n",
150                :                     timeout_millis/1000);
151                :              if (IS_I965G(pI830))
152                :                  i965_dump_error_state(pScrn);
153                :              else
154                :                  i830_dump_error_state(pScrn);
155                :              ErrorF("space: %d wanted %d\n", ring->space, n);
156                :#ifdef XF86DRI
157                :              if (pI830->directRenderingEnabled) {
158                :                  DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
159                :                  DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]);
160                :              }
161                :#endif
162                :#ifdef I830_USE_XAA
163                :              pI830->AccelInfoRec = NULL;       /* Stops recursive behavior */
164                :#endif
165                :#ifdef I830_USE_EXA
166                :              pI830->EXADriverPtr = NULL;
167                :#endif
168      1  0.0011 :              FatalError("lockup\n");
169                :          }
170                :      }
171                :      DELAY(10);
172                :   }
173                :
174                :   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
175                :      now = GetTimeInMillis();
176                :      if (now - first) {
177                :         ErrorF("Elapsed %u ms\n", now - first);
178                :         ErrorF("space: %d wanted %d\n", ring->space, n);
179                :      }
180                :   }
181                :
182                :   return iters;
183     74  0.0806 :}
184                :
185                :void
186                :I830Sync(ScrnInfoPtr pScrn)
187      6  0.0065 :{ /* I830Sync total:    272  0.2963 */
188      2  0.0022 :   I830Ptr pI830 = I830PTR(pScrn);
189                :   int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE;
190                :
191                :   if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
192                :      ErrorF("I830Sync\n");
193                :
194                :#ifdef XF86DRI
195                :   /* VT switching tries to do this.
196                :    */
197                :   if (!pI830->LockHeld && pI830->directRenderingEnabled) {
198                :      return;
199                :   }
200                :#endif
201                :
202      1  0.0011 :   if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) return;
203                :
204      6  0.0065 :   if (IS_I965G(pI830))
205                :      flags = 0;
206                :
207                :   /* Send a flush instruction and then wait till the ring is empty.
208                :    * This is stronger than waiting for the blitter to finish as it also
209                :    * flushes the internal graphics caches.
210                :    */
211                :   
212                :   {
213      3  0.0033 :      BEGIN_LP_RING(2);
214     11  0.0120 :      OUT_RING(MI_FLUSH | flags);
215     11  0.0120 :      OUT_RING(MI_NOOP);                /* pad to quadword */
216     17  0.0185 :      ADVANCE_LP_RING();
217                :   }
218                :
219    168  0.1830 :   I830WaitLpRing(pScrn, pI830->LpRing->mem->size - 8, 0);
220                :
221     37  0.0403 :   pI830->LpRing->space = pI830->LpRing->mem->size - 8;
222      1  0.0011 :   pI830->nextColorExpandBuf = 0;
223      9  0.0098 :}
224                :
225                :void
226                :I830EmitFlush(ScrnInfoPtr pScrn)
227                :{
228                :   I830Ptr pI830 = I830PTR(pScrn);
229                :   int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE;
230                :
231                :   if (IS_I965G(pI830))
232                :      flags = 0;
233                :
234                :   {
235                :       BEGIN_LP_RING(2);
236                :       OUT_RING(MI_FLUSH | flags);
237                :       OUT_RING(MI_NOOP);               /* pad to quadword */
238                :       ADVANCE_LP_RING();
239                :   }
240                :}
241                :
242                :void
243                :I830SelectBuffer(ScrnInfoPtr pScrn, int buffer)
244                :{
245                :   I830Ptr pI830 = I830PTR(pScrn);
246                :
247                :   switch (buffer) {
248                :#ifdef XF86DRI
249                :   case I830_SELECT_BACK:
250                :      pI830->bufferOffset = pI830->back_buffer->offset;
251                :      break;
252                :   case I830_SELECT_THIRD:
253                :      pI830->bufferOffset = pI830->third_buffer->offset;
254                :      break;
255                :   case I830_SELECT_DEPTH:
256                :      pI830->bufferOffset = pI830->depth_buffer->offset;
257                :      break;
258                :#endif
259                :   default:
260                :   case I830_SELECT_FRONT:
261                :      pI830->bufferOffset = pScrn->fbOffset;
262                :      break;
263                :   }
264                :
265                :   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
266                :      ErrorF("I830SelectBuffer %d --> offset %x\n",
267                :             buffer, pI830->bufferOffset);
268                :}
269                :
270                :void
271                :I830RefreshRing(ScrnInfoPtr pScrn)
272                :{
273                :   I830Ptr pI830 = I830PTR(pScrn);
274                :
275                :   pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
276                :   pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
277                :   pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
278                :   if (pI830->LpRing->space < 0)
279                :      pI830->LpRing->space += pI830->LpRing->mem->size;
280                :   i830MarkSync(pScrn);
281                :}
282                :
283                :/* The following function sets up the supported acceleration. Call it
284                : * from the FbInit() function in the SVGA driver, or before ScreenInit
285                : * in a monolithic server.
286                : */
287                :Bool
288                :I830AccelInit(ScreenPtr pScreen)
289                :{
290                :#ifdef I830_USE_EXA
291                :    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
292                :    I830Ptr pI830 = I830PTR(pScrn);
293                :
294                :    if (pI830->useEXA)
295                :        return I830EXAInit(pScreen);
296                :#endif
297                :#ifdef I830_USE_XAA
298                :    return I830XAAInit(pScreen);
299                :#endif
300                :    return FALSE;
301                :}
302 /* 
303  * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i965_render.c"
304  * 
305  *  12731 13.8689
306  */
307
308
309                :/*
310                : * Copyright Â© 2006 Intel Corporation
311                : *
312                : * Permission is hereby granted, free of charge, to any person obtaining a
313                : * copy of this software and associated documentation files (the "Software"),
314                : * to deal in the Software without restriction, including without limitation
315                : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
316                : * and/or sell copies of the Software, and to permit persons to whom the
317                : * Software is furnished to do so, subject to the following conditions:
318                : *
319                : * The above copyright notice and this permission notice (including the next
320                : * paragraph) shall be included in all copies or substantial portions of the
321                : * Software.
322                : *
323                : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
324                : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
325                : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
326                : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
327                : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
328                : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
329                : * SOFTWARE.
330                : *
331                : * Authors:
332                : *    Wang Zhenyu <zhenyu.z.wang@intel.com>
333                : *    Eric Anholt <eric@anholt.net>
334                : *
335                : */
336                :
337                :#ifdef HAVE_CONFIG_H
338                :#include "config.h"
339                :#endif
340                :
341                :#include <assert.h>
342                :#include "xf86.h"
343                :#include "i830.h"
344                :#include "i915_reg.h"
345                :
346                :/* bring in brw structs */
347                :#include "brw_defines.h"
348                :#include "brw_structs.h"
349                :
350                :#ifdef I830DEBUG
351                :#define DEBUG_I830FALLBACK 1
352                :#endif
353                :
354                :#ifdef DEBUG_I830FALLBACK
355                :#define I830FALLBACK(s, arg...)                         \
356                :do {                                                    \
357                :        DPRINTF(PFX, "EXA fallback: " s "\n", ##arg);   \
358                :        return FALSE;                                   \
359                :} while(0)
360                :#else
361                :#define I830FALLBACK(s, arg...)                         \
362                :do {                                                    \
363                :        return FALSE;                                   \
364                :} while(0)
365                :#endif
366                :
367                :struct blendinfo {
368                :    Bool dst_alpha;
369                :    Bool src_alpha;
370                :    CARD32 src_blend;
371                :    CARD32 dst_blend;
372                :};
373                :
374                :struct formatinfo {
375                :    int fmt;
376                :    CARD32 card_fmt;
377                :};
378                :
379                :// refer vol2, 3d rasterization 3.8.1
380                :
381                :/* defined in brw_defines.h */
382                :static struct blendinfo i965_blend_op[] = {
383                :    /* Clear */
384                :    {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ZERO},
385                :    /* Src */
386                :    {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ZERO},
387                :    /* Dst */
388                :    {0, 0, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_ONE},
389                :    /* Over */
390                :    {0, 1, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_INV_SRC_ALPHA},
391                :    /* OverReverse */
392                :    {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ONE},
393                :    /* In */
394                :    {1, 0, BRW_BLENDFACTOR_DST_ALPHA,     BRW_BLENDFACTOR_ZERO},
395                :    /* InReverse */
396                :    {0, 1, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_SRC_ALPHA},
397                :    /* Out */
398                :    {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ZERO},
399                :    /* OutReverse */
400                :    {0, 1, BRW_BLENDFACTOR_ZERO,          BRW_BLENDFACTOR_INV_SRC_ALPHA},
401                :    /* Atop */
402                :    {1, 1, BRW_BLENDFACTOR_DST_ALPHA,     BRW_BLENDFACTOR_INV_SRC_ALPHA},
403                :    /* AtopReverse */
404                :    {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_SRC_ALPHA},
405                :    /* Xor */
406                :    {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA},
407                :    /* Add */
408                :    {0, 0, BRW_BLENDFACTOR_ONE,           BRW_BLENDFACTOR_ONE},
409                :};
410                :
411                :/* FIXME: surface format defined in brw_defines.h, shared Sampling engine
412                : * 1.7.2
413                : */
414                :static struct formatinfo i965_tex_formats[] = {
415                :    {PICT_a8r8g8b8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
416                :    {PICT_x8r8g8b8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
417                :    {PICT_a8b8g8r8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
418                :    {PICT_x8b8g8r8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
419                :    {PICT_r5g6b5,   BRW_SURFACEFORMAT_B5G6R5_UNORM   },
420                :    {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM },
421                :    {PICT_a8,       BRW_SURFACEFORMAT_A8_UNORM   },
422                :};
423                :
424                :static void i965_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format,
425                :                                CARD32 *sblend, CARD32 *dblend)
426                :{
427                :
428                :    *sblend = i965_blend_op[op].src_blend;
429                :    *dblend = i965_blend_op[op].dst_blend;
430                :
431                :    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
432                :     * it as always 1.
433                :     */
434                :    if (PICT_FORMAT_A(dst_format) == 0 && i965_blend_op[op].dst_alpha) {
435                :        if (*sblend == BRW_BLENDFACTOR_DST_ALPHA)
436                :            *sblend = BRW_BLENDFACTOR_ONE;
437                :        else if (*sblend == BRW_BLENDFACTOR_INV_DST_ALPHA)
438                :            *sblend = BRW_BLENDFACTOR_ZERO;
439                :    }
440                :
441                :    /* If the source alpha is being used, then we should only be in a case where
442                :     * the source blend factor is 0, and the source blend value is the mask
443                :     * channels multiplied by the source picture's alpha.
444                :     */
445                :    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format)
446                :            && i965_blend_op[op].src_alpha) {
447                :        if (*dblend == BRW_BLENDFACTOR_SRC_ALPHA) {
448                :            *dblend = BRW_BLENDFACTOR_SRC_COLOR;
449                :        } else if (*dblend == BRW_BLENDFACTOR_INV_SRC_ALPHA) {
450                :            *dblend = BRW_BLENDFACTOR_INV_SRC_COLOR;
451                :        }
452                :    }
453                :
454                :}
455                :
456                :static Bool i965_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
457      8  0.0087 :{ /* i965_get_dest_format total:     28  0.0305 */
458     10  0.0109 :    switch (pDstPicture->format) {
459                :    case PICT_a8r8g8b8:
460                :    case PICT_x8r8g8b8:
461      1  0.0011 :        *dst_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
462                :        break;
463                :    case PICT_r5g6b5:
464                :        *dst_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
465                :        break;
466                :    case PICT_a1r5g5b5:
467                :        *dst_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
468                :        break;
469                :    case PICT_x1r5g5b5:
470                :        *dst_format = BRW_SURFACEFORMAT_B5G5R5X1_UNORM;
471                :        break;
472                :    /* COLR_BUF_8BIT is special for YUV surfaces.  While we may end up being
473                :     * able to use it depending on how the hardware implements it, disable it
474                :     * for now while we don't know what exactly it does (what channel does it
475                :     * read from?
476                :     */
477                :    /*
478                :    case PICT_a8:
479                :        *dst_format = COLR_BUF_8BIT;
480                :        break;
481                :    */
482                :    case PICT_a4r4g4b4:
483                :    case PICT_x4r4g4b4:
484                :        *dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
485                :        break;
486                :    default:
487                :        I830FALLBACK("Unsupported dest format 0x%x\n",
488                :                     (int)pDstPicture->format);
489                :    }
490                :
491                :    return TRUE;
492      9  0.0098 :}
493                :
494                :static Bool i965_check_composite_texture(PicturePtr pPict, int unit)
495     28  0.0305 :{ /* i965_check_composite_texture total:     73  0.0795 */
496      3  0.0033 :    int w = pPict->pDrawable->width;
497                :    int h = pPict->pDrawable->height;
498                :    int i;
499                :
500     15  0.0163 :    if ((w > 0x7ff) || (h > 0x7ff))
501                :        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
502                :
503                :    for (i = 0; i < sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]);
504                :         i++)
505                :    {
506      9  0.0098 :        if (i965_tex_formats[i].fmt == pPict->format)
507                :            break;
508                :    }
509      7  0.0076 :    if (i == sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]))
510                :        I830FALLBACK("Unsupported picture format 0x%x\n",
511                :                     (int)pPict->format);
512                :
513      4  0.0044 :    if (pPict->repeat && pPict->repeatType != RepeatNormal)
514                :        I830FALLBACK("extended repeat (%d) not supported\n",
515                :                     pPict->repeatType);
516                :
517                :    if (pPict->filter != PictFilterNearest &&
518                :        pPict->filter != PictFilterBilinear)
519                :    {
520                :        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
521                :    }
522                :
523                :    return TRUE;
524      7  0.0076 :}
525                :
526                :Bool
527                :i965_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
528                :                     PicturePtr pDstPicture)
529      9  0.0098 :{ /* i965_check_composite total:     54  0.0588 */
530                :    CARD32 tmp1;
531                :
532                :    /* Check for unsupported compositing operations. */
533                :    if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0]))
534                :        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
535                :
536      4  0.0044 :    if (pMaskPicture && pMaskPicture->componentAlpha &&
537                :            PICT_FORMAT_RGB(pMaskPicture->format)) {
538                :        /* Check if it's component alpha that relies on a source alpha and on
539                :         * the source value.  We can only get one of those into the single
540                :         * source value that we get to blend with.
541                :         */
542     11  0.0120 :        if (i965_blend_op[op].src_alpha &&
543                :            (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO))
544                :        {
545                :            I830FALLBACK("Component alpha not supported with source "
546                :                         "alpha and source value blending.\n");
547                :        }
548                :    } 
549                :
550      9  0.0098 :    if (!i965_check_composite_texture(pSrcPicture, 0))
551                :        I830FALLBACK("Check Src picture texture\n");
552      2  0.0022 :    if (pMaskPicture != NULL && !i965_check_composite_texture(pMaskPicture, 1))
553                :        I830FALLBACK("Check Mask picture texture\n");
554                :
555      9  0.0098 :    if (!i965_get_dest_format(pDstPicture, &tmp1))
556                :        I830FALLBACK("Get Color buffer format\n");
557                :
558                :    return TRUE;
559                :
560     10  0.0109 :}
561                :
562                :#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
563                :#define MIN(a,b) ((a) < (b) ? (a) : (b))
564                :#define BRW_GRF_BLOCKS(nreg)    ((nreg + 15) / 16 - 1)
565                :
566                :static int urb_vs_start, urb_vs_size;
567                :static int urb_gs_start, urb_gs_size;
568                :static int urb_clip_start, urb_clip_size;
569                :static int urb_sf_start, urb_sf_size;
570                :static int urb_cs_start, urb_cs_size;
571                :
572                :static struct brw_surface_state *dest_surf_state, dest_surf_state_local;
573                :static struct brw_surface_state *src_surf_state, src_surf_state_local;
574                :static struct brw_surface_state *mask_surf_state, mask_surf_state_local;
575                :static struct brw_sampler_state *src_sampler_state, src_sampler_state_local;
576                :static struct brw_sampler_state *mask_sampler_state, mask_sampler_state_local;
577                :static struct brw_sampler_default_color *default_color_state;
578                :
579                :static struct brw_vs_unit_state *vs_state, vs_state_local;
580                :static struct brw_sf_unit_state *sf_state, sf_state_local;
581                :static struct brw_wm_unit_state *wm_state, wm_state_local;
582                :static struct brw_cc_unit_state *cc_state, cc_state_local;
583                :static struct brw_cc_viewport *cc_viewport;
584                :
585                :static struct brw_instruction *sf_kernel;
586                :static struct brw_instruction *ps_kernel;
587                :static struct brw_instruction *sip_kernel;
588                :
589                :static CARD32 *binding_table;
590                :static int binding_table_entries;
591                :
592                :static int dest_surf_offset, src_surf_offset, mask_surf_offset;
593                :static int src_sampler_offset, mask_sampler_offset,vs_offset;
594                :static int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
595                :static int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
596                :static int wm_scratch_offset;
597                :static int binding_table_offset;
598                :static int default_color_offset;
599                :static int next_offset, total_state_size;
600                :static char *state_base;
601                :static int state_base_offset;
602                :static float *vb;
603                :static int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/
604                :
605                :static CARD32 src_blend, dst_blend;
606                :
607                :static const CARD32 sip_kernel_static[][4] = {
608                :/*    wait (1) a0<1>UW a145<0,1,0>UW { align1 +  } */
609                :    { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
610                :/*    nop (4) g0<1>UD { align1 +  } */
611                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
612                :/*    nop (4) g0<1>UD { align1 +  } */
613                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
614                :/*    nop (4) g0<1>UD { align1 +  } */
615                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
616                :/*    nop (4) g0<1>UD { align1 +  } */
617                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
618                :/*    nop (4) g0<1>UD { align1 +  } */
619                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
620                :/*    nop (4) g0<1>UD { align1 +  } */
621                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
622                :/*    nop (4) g0<1>UD { align1 +  } */
623                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
624                :/*    nop (4) g0<1>UD { align1 +  } */
625                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
626                :/*    nop (4) g0<1>UD { align1 +  } */
627                :    { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
628                :};
629                :
630                :/*
631                : * this program computes dA/dx and dA/dy for the texture coordinates along
632                : * with the base texture coordinate. It was extracted from the Mesa driver
633                : */
634                :
635                :#define SF_KERNEL_NUM_GRF  16
636                :#define SF_MAX_THREADS     1
637                :
638                :static const CARD32 sf_kernel_static[][4] = {
639                :#include "exa_sf_prog.h"
640                :};
641                :
642                :static const CARD32 sf_kernel_static_mask[][4] = {
643                :#include "exa_sf_mask_prog.h"
644                :};
645                :
646                :static const CARD32 sf_kernel_static_rotation[][4] = {
647                :#include "exa_sf_rotation_prog.h"
648                :};
649                :
650                :/* ps kernels */
651                :#define PS_KERNEL_NUM_GRF   32
652                :#define PS_MAX_THREADS     32
653                :
654                :static const CARD32 ps_kernel_static_nomask [][4] = {
655                :#include "exa_wm_nomask_prog.h"
656                :};
657                :
658                :static const CARD32 ps_kernel_static_maskca [][4] = {
659                :#include "exa_wm_maskca_prog.h"
660                :};
661                :
662                :static const CARD32 ps_kernel_static_maskca_srcalpha [][4] = {
663                :#include "exa_wm_maskca_srcalpha_prog.h"
664                :};
665                :
666                :static const CARD32 ps_kernel_static_masknoca [][4] = {
667                :#include "exa_wm_masknoca_prog.h"
668                :};
669                :
670                :static const CARD32 ps_kernel_static_rotation [][4] = {
671                :#include "exa_wm_rotation_prog.h"
672                :};
673                :
674                :static CARD32 
675                :i965_get_card_format(PicturePtr pPict)
676     27  0.0294 :{ /* i965_get_card_format total:     32  0.0349 */
677                :    int i;
678                :
679      4  0.0044 :    for (i = 0; i < sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]);
680                :         i++)
681                :    {
682      1  0.0011 :        if (i965_tex_formats[i].fmt == pPict->format)
683                :            break;
684                :    }
685                :    return i965_tex_formats[i].card_fmt;
686                :}
687                :
688                :static Bool
689                :i965_check_rotation_transform(PictTransformPtr t)
690                :{
691                :    /* XXX this is arbitrary */
692                :    int a, b;
693                :    a = xFixedToInt(t->matrix[0][1]);
694                :    b = xFixedToInt(t->matrix[1][0]);
695                :    if (a == -1 && b == 1)
696                :        return TRUE;
697                :    else if (a == 1 && b == -1)
698                :        return TRUE;
699                :    else
700                :        return FALSE;
701                :}
702                :
703                :Bool
704                :i965_prepare_composite(int op, PicturePtr pSrcPicture,
705                :                       PicturePtr pMaskPicture, PicturePtr pDstPicture,
706                :                       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
707      3  0.0033 :{ /* i965_prepare_composite total:   9782 10.6564 */
708     29  0.0316 :    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
709      7  0.0076 :    I830Ptr pI830 = I830PTR(pScrn);
710                :    CARD32 src_offset, src_pitch;
711                :    CARD32 mask_offset = 0, mask_pitch = 0;
712                :    CARD32 dst_format, dst_offset, dst_pitch;
713                :    Bool rotation_program = FALSE;
714                :
715                :    IntelEmitInvarientState(pScrn);
716      6  0.0065 :    *pI830->last_3d = LAST_3D_RENDER;
717                :
718      6  0.0065 :    src_offset = intel_get_pixmap_offset(pSrc);
719                :    src_pitch = intel_get_pixmap_pitch(pSrc);
720      2  0.0022 :    dst_offset = intel_get_pixmap_offset(pDst);
721      3  0.0033 :    dst_pitch = intel_get_pixmap_pitch(pDst);
722                :    if (pMask) {
723      2  0.0022 :        mask_offset = intel_get_pixmap_offset(pMask);
724      6  0.0065 :        mask_pitch = intel_get_pixmap_pitch(pMask);
725                :    }
726      8  0.0087 :    pI830->scale_units[0][0] = pSrc->drawable.width;
727     24  0.0261 :    pI830->scale_units[0][1] = pSrc->drawable.height;
728                :
729      1  0.0011 :    pI830->transform[0] = pSrcPicture->transform;
730                :
731                :    if (!pMask) {
732                :        pI830->transform[1] = NULL;
733                :        pI830->scale_units[1][0] = -1;
734                :        pI830->scale_units[1][1] = -1;
735                :        if (pI830->transform[0] && 
736                :                i965_check_rotation_transform(pI830->transform[0]))
737                :            rotation_program = TRUE;
738                :    } else {
739                :        pI830->transform[1] = pMaskPicture->transform;
740                :        if (pI830->transform[1])
741                :            I830FALLBACK("i965 mask transform not implemented!\n");
742      3  0.0033 :        pI830->scale_units[1][0] = pMask->drawable.width;
743      3  0.0033 :        pI830->scale_units[1][1] = pMask->drawable.height;
744                :    }
745                :
746                :    /* setup 3d pipeline state */
747                :
748      1  0.0011 :    binding_table_entries = 2; /* default no mask */
749                :
750                :    /* Set up our layout of state in framebuffer.  First the general state: */
751                :    next_offset = 0;
752      1  0.0011 :    vs_offset = ALIGN(next_offset, 64);
753                :    next_offset = vs_offset + sizeof(*vs_state);
754                :
755                :    sf_offset = ALIGN(next_offset, 32);
756                :    next_offset = sf_offset + sizeof(*sf_state);
757                :
758                :    wm_offset = ALIGN(next_offset, 32);
759                :    next_offset = wm_offset + sizeof(*wm_state);
760                :
761                :    wm_scratch_offset = ALIGN(next_offset, 1024);
762                :    next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
763                :
764                :    cc_offset = ALIGN(next_offset, 32);
765                :    next_offset = cc_offset + sizeof(*cc_state);
766                :
767                :    /* keep current sf_kernel, which will send one setup urb entry to
768                :     * PS kernel
769                :     */
770      1  0.0011 :    sf_kernel_offset = ALIGN(next_offset, 64);
771                :    if (pMask)
772                :        next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask);
773                :    else if (rotation_program)
774                :        next_offset = sf_kernel_offset + sizeof (sf_kernel_static_rotation);
775                :    else 
776                :        next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
777                :
778                :    ps_kernel_offset = ALIGN(next_offset, 64);
779                :    if (pMask) {
780                :        if (pMaskPicture->componentAlpha && 
781                :                PICT_FORMAT_RGB(pMaskPicture->format)) {
782                :            if (i965_blend_op[op].src_alpha) {
783                :                next_offset = ps_kernel_offset + 
784                :                    sizeof(ps_kernel_static_maskca_srcalpha);
785                :            } else {
786                :                next_offset = ps_kernel_offset + 
787                :                    sizeof(ps_kernel_static_maskca);
788                :            }
789                :        } else
790      1  0.0011 :            next_offset = ps_kernel_offset + 
791                :                          sizeof(ps_kernel_static_masknoca);
792                :    } else if (rotation_program) {
793                :        next_offset = ps_kernel_offset + sizeof (ps_kernel_static_rotation);
794                :    } else {
795      1  0.0011 :        next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
796                :    }
797                :
798     13  0.0142 :    sip_kernel_offset = ALIGN(next_offset, 64);
799                :    next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
800                :
801                :    /* needed? */
802      3  0.0033 :    cc_viewport_offset = ALIGN(next_offset, 32);
803                :    next_offset = cc_viewport_offset + sizeof(*cc_viewport);
804                :
805                :    /* for texture sampler */
806      3  0.0033 :    src_sampler_offset = ALIGN(next_offset, 32);
807      2  0.0022 :    next_offset = src_sampler_offset + sizeof(*src_sampler_state);
808                :
809      3  0.0033 :    if (pMask) {
810                :        mask_sampler_offset = ALIGN(next_offset, 32);
811      1  0.0011 :        next_offset = mask_sampler_offset + sizeof(*mask_sampler_state);
812                :    }
813                :    /* Align VB to native size of elements, for safety */
814     10  0.0109 :    vb_offset = ALIGN(next_offset, 8);
815                :    next_offset = vb_offset + vb_size;
816                :
817                :    /* And then the general state: */
818      2  0.0022 :    dest_surf_offset = ALIGN(next_offset, 32);
819                :    next_offset = dest_surf_offset + sizeof(*dest_surf_state);
820                :
821      2  0.0022 :    src_surf_offset = ALIGN(next_offset, 32);
822      1  0.0011 :    next_offset = src_surf_offset + sizeof(*src_surf_state);
823                :
824      1  0.0011 :    if (pMask) {
825      1  0.0011 :        mask_surf_offset = ALIGN(next_offset, 32);
826                :        next_offset = mask_surf_offset + sizeof(*mask_surf_state);
827      3  0.0033 :        binding_table_entries = 3;
828                :    }
829                :
830      3  0.0033 :    binding_table_offset = ALIGN(next_offset, 32);
831                :    next_offset = binding_table_offset + (binding_table_entries * 4);
832                :
833      4  0.0044 :    default_color_offset = ALIGN(next_offset, 32);
834      2  0.0022 :    next_offset = default_color_offset + sizeof(*default_color_state);
835                :
836      3  0.0033 :    total_state_size = next_offset;
837                :    assert(total_state_size < pI830->exa_965_state->size);
838                :
839      3  0.0033 :    state_base_offset = pI830->exa_965_state->offset;
840      9  0.0098 :    state_base_offset = ALIGN(state_base_offset, 64);
841                :    state_base = (char *)(pI830->FbBase + state_base_offset);
842                :
843                :    sf_kernel = (void *)(state_base + sf_kernel_offset);
844      1  0.0011 :    ps_kernel = (void *)(state_base + ps_kernel_offset);
845                :    sip_kernel = (void *)(state_base + sip_kernel_offset);
846                :
847      1  0.0011 :    cc_viewport = (void *)(state_base + cc_viewport_offset);
848                :
849      1  0.0011 :    binding_table = (void *)(state_base + binding_table_offset);
850                :
851      2  0.0022 :    vb = (void *)(state_base + vb_offset);
852                :
853      5  0.0054 :    default_color_state = (void*)(state_base + default_color_offset);
854                :
855                :    /* Set up a default static partitioning of the URB, which is supposed to
856                :     * allow anything we would want to do, at potentially lower performance.
857                :     */
858                :#define URB_CS_ENTRY_SIZE     0
859                :#define URB_CS_ENTRIES        0
860                :
861                :#define URB_VS_ENTRY_SIZE     1   // each 512-bit row
862                :#define URB_VS_ENTRIES        8   // we needs at least 8 entries
863                :
864                :#define URB_GS_ENTRY_SIZE     0
865                :#define URB_GS_ENTRIES        0
866                :
867                :#define URB_CLIP_ENTRY_SIZE   0
868                :#define URB_CLIP_ENTRIES      0
869                :
870                :#define URB_SF_ENTRY_SIZE     2
871                :#define URB_SF_ENTRIES        1
872                :
873                :    urb_vs_start = 0;
874      1  0.0011 :    urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
875                :    urb_gs_start = urb_vs_start + urb_vs_size;
876                :    urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
877                :    urb_clip_start = urb_gs_start + urb_gs_size;
878                :    urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
879      1  0.0011 :    urb_sf_start = urb_clip_start + urb_clip_size;
880                :    urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
881      2  0.0022 :    urb_cs_start = urb_sf_start + urb_sf_size;
882      1  0.0011 :    urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
883                :
884                :    /* Because we only have a single static buffer for our state currently,
885                :     * we have to sync before updating it every time.
886                :     */
887      3  0.0033 :    i830WaitSync(pScrn);
888                :
889     17  0.0185 :    memset (cc_viewport, 0, sizeof (*cc_viewport));
890     17  0.0185 :    cc_viewport->min_depth = -1.e35;
891     19  0.0207 :    cc_viewport->max_depth = 1.e35;
892                :
893                :    /* Color calculator state */
894      7  0.0076 :    cc_state = &cc_state_local;
895     32  0.0349 :    memset(cc_state, 0, sizeof(*cc_state));
896     34  0.0370 :    cc_state->cc0.stencil_enable = 0;   /* disable stencil */
897                :    cc_state->cc2.depth_test = 0;       /* disable depth test */
898                :    cc_state->cc2.logicop_enable = 0;   /* disable logic op */
899                :    cc_state->cc3.ia_blend_enable = 1;  /* blend alpha just like colors */
900                :    cc_state->cc3.blend_enable = 1;     /* enable color blend */
901      6  0.0065 :    cc_state->cc3.alpha_test = 0;       /* disable alpha test */
902     12  0.0131 :    cc_state->cc4.cc_viewport_state_offset = (state_base_offset +
903                :                                              cc_viewport_offset) >> 5;
904                :    cc_state->cc5.dither_enable = 0;    /* disable dither */
905      2  0.0022 :    cc_state->cc5.logicop_func = 0xc;   /* COPY */
906                :    cc_state->cc5.statistics_enable = 1;
907      1  0.0011 :    cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
908     38  0.0414 :    i965_get_blend_cntl(op, pMaskPicture, pDstPicture->format,
909                :                        &src_blend, &dst_blend);
910                :    /* XXX: alpha blend factor should be same as color, but check
911                :     * for CA case in future
912                :     */
913     24  0.0261 :    cc_state->cc5.ia_src_blend_factor = src_blend;
914      9  0.0098 :    cc_state->cc5.ia_dest_blend_factor = dst_blend;
915                :    cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
916      6  0.0065 :    cc_state->cc6.src_blend_factor = src_blend;
917     10  0.0109 :    cc_state->cc6.dest_blend_factor = dst_blend;
918                :    cc_state->cc6.clamp_post_alpha_blend = 1;
919      4  0.0044 :    cc_state->cc6.clamp_pre_alpha_blend = 1;
920      1  0.0011 :    cc_state->cc6.clamp_range = 0;  /* clamp range [0,1] */
921                :
922      1  0.0011 :    cc_state = (void *)(state_base + cc_offset);
923     51  0.0556 :    memcpy (cc_state, &cc_state_local, sizeof (cc_state_local));
924                :
925                :    /* Upload system kernel */
926     10  0.0109 :    memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
927                :
928                :    /* Set up the state buffer for the destination surface */
929      8  0.0087 :    dest_surf_state = &dest_surf_state_local;
930     42  0.0458 :    memset(dest_surf_state, 0, sizeof(*dest_surf_state));
931      1  0.0011 :    dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
932      8  0.0087 :    dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
933      4  0.0044 :    i965_get_dest_format(pDstPicture, &dst_format);
934     34  0.0370 :    dest_surf_state->ss0.surface_format = dst_format;
935                :
936                :    dest_surf_state->ss0.writedisable_alpha = 0;
937                :    dest_surf_state->ss0.writedisable_red = 0;
938                :    dest_surf_state->ss0.writedisable_green = 0;
939                :    dest_surf_state->ss0.writedisable_blue = 0;
940     27  0.0294 :    dest_surf_state->ss0.color_blend = 1;
941                :    dest_surf_state->ss0.vert_line_stride = 0;
942                :    dest_surf_state->ss0.vert_line_stride_ofs = 0;
943                :    dest_surf_state->ss0.mipmap_layout_mode = 0;
944                :    dest_surf_state->ss0.render_cache_read_mode = 0;
945                :
946                :    dest_surf_state->ss1.base_addr = dst_offset;
947      4  0.0044 :    dest_surf_state->ss2.height = pDst->drawable.height - 1;
948     40  0.0436 :    dest_surf_state->ss2.width = pDst->drawable.width - 1;
949                :    dest_surf_state->ss2.mip_count = 0;
950                :    dest_surf_state->ss2.render_target_rotation = 0;
951     23  0.0251 :    dest_surf_state->ss3.pitch = dst_pitch - 1;
952                :
953      1  0.0011 :    dest_surf_state = (void *)(state_base + dest_surf_offset);
954     31  0.0338 :    memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
955                :
956                :    /* Set up the source surface state buffer */
957                :    src_surf_state = &src_surf_state_local;
958     48  0.0523 :    memset(src_surf_state, 0, sizeof(*src_surf_state));
959      5  0.0054 :    src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
960     20  0.0218 :    src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
961                :
962                :    src_surf_state->ss0.writedisable_alpha = 0;
963      3  0.0033 :    src_surf_state->ss0.writedisable_red = 0;
964                :    src_surf_state->ss0.writedisable_green = 0;
965                :    src_surf_state->ss0.writedisable_blue = 0;
966     31  0.0338 :    src_surf_state->ss0.color_blend = 1;
967                :    src_surf_state->ss0.vert_line_stride = 0;
968                :    src_surf_state->ss0.vert_line_stride_ofs = 0;
969                :    src_surf_state->ss0.mipmap_layout_mode = 0;
970                :    src_surf_state->ss0.render_cache_read_mode = 0;
971                :
972      3  0.0033 :    src_surf_state->ss1.base_addr = src_offset;
973      7  0.0076 :    src_surf_state->ss2.width = pSrc->drawable.width - 1;
974      6  0.0065 :    src_surf_state->ss2.height = pSrc->drawable.height - 1;
975                :    src_surf_state->ss2.mip_count = 0;
976     30  0.0327 :    src_surf_state->ss2.render_target_rotation = 0;
977     15  0.0163 :    src_surf_state->ss3.pitch = src_pitch - 1;
978                :
979                :    src_surf_state = (void *)(state_base + src_surf_offset);
980     28  0.0305 :    memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
981                :
982                :    /* setup mask surface */
983      1  0.0011 :    if (pMask) {
984                :        mask_surf_state = &mask_surf_state_local;
985     35  0.0381 :        memset(mask_surf_state, 0, sizeof(*mask_surf_state));
986      6  0.0065 :        mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
987     18  0.0196 :        mask_surf_state->ss0.surface_format =
988                :            i965_get_card_format(pMaskPicture);
989                :
990                :        mask_surf_state->ss0.writedisable_alpha = 0;
991      8  0.0087 :        mask_surf_state->ss0.writedisable_red = 0;
992                :        mask_surf_state->ss0.writedisable_green = 0;
993                :        mask_surf_state->ss0.writedisable_blue = 0;
994     20  0.0218 :        mask_surf_state->ss0.color_blend = 1;
995                :        mask_surf_state->ss0.vert_line_stride = 0;
996                :        mask_surf_state->ss0.vert_line_stride_ofs = 0;
997                :        mask_surf_state->ss0.mipmap_layout_mode = 0;
998                :        mask_surf_state->ss0.render_cache_read_mode = 0;
999                :
1000                :        mask_surf_state->ss1.base_addr = mask_offset;
1001     11  0.0120 :        mask_surf_state->ss2.width = pMask->drawable.width - 1;
1002      4  0.0044 :        mask_surf_state->ss2.height = pMask->drawable.height - 1;
1003                :        mask_surf_state->ss2.mip_count = 0;
1004     31  0.0338 :        mask_surf_state->ss2.render_target_rotation = 0;
1005      8  0.0087 :        mask_surf_state->ss3.pitch = mask_pitch - 1;
1006                :
1007                :        mask_surf_state = (void *)(state_base + mask_surf_offset);
1008     38  0.0414 :        memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
1009                :    }
1010                :
1011                :    /* Set up a binding table for our surfaces.  Only the PS will use it */
1012      8  0.0087 :    binding_table[0] = state_base_offset + dest_surf_offset;
1013      1  0.0011 :    binding_table[1] = state_base_offset + src_surf_offset;
1014                :    if (pMask)
1015      3  0.0033 :        binding_table[2] = state_base_offset + mask_surf_offset;
1016                :
1017                :    /* PS kernel use this sampler */
1018                :    src_sampler_state = &src_sampler_state_local;
1019      3  0.0033 :    memset(src_sampler_state, 0, sizeof(*src_sampler_state));
1020                :    src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
1021     58  0.0632 :    switch(pSrcPicture->filter) {
1022                :    case PictFilterNearest:
1023      4  0.0044 :        src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
1024     38  0.0414 :        src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
1025                :        break;
1026                :    case PictFilterBilinear:
1027                :        src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
1028                :        src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
1029                :        break;
1030                :    default:
1031                :        I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter);
1032                :    }
1033                :
1034     40  0.0436 :    memset(default_color_state, 0, sizeof(*default_color_state));
1035      1  0.0011 :    default_color_state->color[0] = 0.0; /* R */
1036      4  0.0044 :    default_color_state->color[1] = 0.0; /* G */
1037                :    default_color_state->color[2] = 0.0; /* B */
1038                :    default_color_state->color[3] = 0.0; /* A */
1039                :
1040      3  0.0033 :    src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
1041                :
1042      3  0.0033 :    if (!pSrcPicture->repeat) {
1043                :        src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
1044      1  0.0011 :        src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
1045                :        src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
1046                :        src_sampler_state->ss2.default_color_pointer =
1047                :            (state_base_offset + default_color_offset) >> 5;
1048                :    } else {
1049      8  0.0087 :        src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP;
1050                :        src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
1051     85  0.0926 :        src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
1052                :    }
1053      3  0.0033 :    src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
1054                :
1055      6  0.0065 :    src_sampler_state = (void *)(state_base + src_sampler_offset);
1056     32  0.0349 :    memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
1057                :
1058      3  0.0033 :    if (pMask) {
1059                :        mask_sampler_state = &mask_sampler_state_local;
1060                :        memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
1061      3  0.0033 :        mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
1062     45  0.0490 :        switch(pMaskPicture->filter) {
1063                :        case PictFilterNearest:
1064      5  0.0054 :            mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
1065     41  0.0447 :            mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
1066                :            break;
1067                :        case PictFilterBilinear:
1068                :            mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
1069                :            mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
1070                :            break;
1071                :        default:
1072                :            I830FALLBACK("Bad filter 0x%x\n", pMaskPicture->filter);
1073                :        }
1074                :
1075     34  0.0370 :        if (!pMaskPicture->repeat) {
1076      3  0.0033 :            mask_sampler_state->ss1.r_wrap_mode =
1077                :                BRW_TEXCOORDMODE_CLAMP_BORDER;
1078     40  0.0436 :            mask_sampler_state->ss1.s_wrap_mode =
1079                :                BRW_TEXCOORDMODE_CLAMP_BORDER;
1080     22  0.0240 :            mask_sampler_state->ss1.t_wrap_mode =
1081                :                BRW_TEXCOORDMODE_CLAMP_BORDER;
1082      7  0.0076 :            mask_sampler_state->ss2.default_color_pointer =
1083                :                (state_base_offset + default_color_offset)>>5;
1084                :        } else {
1085                :            mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP;
1086                :            mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
1087                :            mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
1088                :        }
1089                :        mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
1090                :
1091      5  0.0054 :        mask_sampler_state = (void *)(state_base + mask_sampler_offset);
1092     27  0.0294 :        memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
1093                :    }
1094                :
1095                :    /* Set up the vertex shader to be disabled (passthrough) */
1096      4  0.0044 :    vs_state = &vs_state_local;
1097      8  0.0087 :    memset(vs_state, 0, sizeof(*vs_state));
1098      1  0.0011 :    vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
1099      1  0.0011 :    vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
1100     46  0.0501 :    vs_state->vs6.vs_enable = 0;
1101                :    vs_state->vs6.vert_cache_disable = 1;
1102                :
1103      6  0.0065 :    vs_state = (void *)(state_base + vs_offset);
1104     22  0.0240 :    memcpy (vs_state, &vs_state_local, sizeof (vs_state_local));
1105                :
1106                :    /* Set up the SF kernel to do coord interp: for each attribute,
1107                :     * calculate dA/dx and dA/dy.  Hand these interpolation coefficients
1108                :     * back to SF which then hands pixels off to WM.
1109                :     */
1110      4  0.0044 :    if (pMask)
1111      5  0.0054 :        memcpy(sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static));
1112                :    else if (rotation_program)
1113                :        memcpy(sf_kernel, sf_kernel_static_rotation, 
1114                :                sizeof (sf_kernel_static_rotation));
1115                :    else
1116                :        memcpy(sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
1117                :
1118      3  0.0033 :    sf_state = &sf_state_local;
1119     45  0.0490 :    memset(sf_state, 0, sizeof(*sf_state));
1120    102  0.1111 :    sf_state->thread0.kernel_start_pointer =
1121                :        (state_base_offset + sf_kernel_offset) >> 6;
1122      1  0.0011 :    sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
1123     50  0.0545 :    sf_state->sf1.single_program_flow = 1;
1124                :    sf_state->sf1.binding_table_entry_count = 0;
1125                :    sf_state->sf1.thread_priority = 0;
1126                :    sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
1127                :    sf_state->sf1.illegal_op_exception_enable = 1;
1128      7  0.0076 :    sf_state->sf1.mask_stack_exception_enable = 1;
1129                :    sf_state->sf1.sw_exception_enable = 1;
1130     45  0.0490 :    sf_state->thread2.per_thread_scratch_space = 0;
1131                :    /* scratch space is not used in our kernel */
1132      4  0.0044 :    sf_state->thread2.scratch_space_base_pointer = 0;
1133      3  0.0033 :    sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
1134      8  0.0087 :    sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
1135      9  0.0098 :    sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
1136                :    /* don't smash vertex header, read start from dw8 */
1137      4  0.0044 :    sf_state->thread3.urb_entry_read_offset = 1;
1138      3  0.0033 :    sf_state->thread3.dispatch_grf_start_reg = 3;
1139     10  0.0109 :    sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
1140      1  0.0011 :    sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
1141      6  0.0065 :    sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
1142                :    sf_state->thread4.stats_enable = 1;
1143                :    sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
1144     32  0.0349 :    sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
1145     40  0.0436 :    sf_state->sf6.scissor = 0;
1146      5  0.0054 :    sf_state->sf7.trifan_pv = 2;
1147      5  0.0054 :    sf_state->sf6.dest_org_vbias = 0x8;
1148     54  0.0588 :    sf_state->sf6.dest_org_hbias = 0x8;
1149                :
1150      3  0.0033 :    sf_state = (void *)(state_base + sf_offset);
1151     14  0.0153 :    memcpy (sf_state, &sf_state_local, sizeof (sf_state_local));
1152                :
1153                :   /* Set up the PS kernel (dispatched by WM) */
1154                :    if (pMask) {
1155      5  0.0054 :        if (pMaskPicture->componentAlpha && 
1156                :                PICT_FORMAT_RGB(pMaskPicture->format)) {
1157      3  0.0033 :            if (i965_blend_op[op].src_alpha) 
1158      3  0.0033 :                memcpy(ps_kernel, ps_kernel_static_maskca_srcalpha,
1159                :                        sizeof (ps_kernel_static_maskca_srcalpha));
1160                :            else
1161      2  0.0022 :                memcpy(ps_kernel, ps_kernel_static_maskca,
1162                :                        sizeof (ps_kernel_static_maskca));
1163                :        } else
1164      8  0.0087 :            memcpy(ps_kernel, ps_kernel_static_masknoca,
1165                :                   sizeof (ps_kernel_static_masknoca));
1166                :    } else if (rotation_program) {
1167      1  0.0011 :        memcpy(ps_kernel, ps_kernel_static_rotation,
1168                :               sizeof (ps_kernel_static_rotation));
1169                :    } else {
1170      1  0.0011 :        memcpy(ps_kernel, ps_kernel_static_nomask,
1171                :               sizeof (ps_kernel_static_nomask));
1172                :    }
1173                :
1174     13  0.0142 :    wm_state = &wm_state_local;
1175     90  0.0980 :    memset(wm_state, 0, sizeof (*wm_state));
1176     90  0.0980 :    wm_state->thread0.kernel_start_pointer =
1177                :        (state_base_offset + ps_kernel_offset) >> 6;
1178     21  0.0229 :    wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
1179                :    wm_state->thread1.single_program_flow = 1;
1180                :    if (!pMask)
1181      1  0.0011 :        wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
1182                :    else
1183     18  0.0196 :        wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */
1184                :
1185      6  0.0065 :    wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
1186                :                                                    wm_scratch_offset)>>10;
1187     33  0.0359 :    wm_state->thread2.per_thread_scratch_space = 0;
1188                :    wm_state->thread3.const_urb_entry_read_length = 0;
1189      1  0.0011 :    wm_state->thread3.const_urb_entry_read_offset = 0;
1190                :    /* Each pair of attributes (src/mask coords) is one URB entry */
1191                :    if (pMask)
1192      7  0.0076 :        wm_state->thread3.urb_entry_read_length = 2;
1193                :    else
1194      2  0.0022 :        wm_state->thread3.urb_entry_read_length = 1;
1195      4  0.0044 :    wm_state->thread3.urb_entry_read_offset = 0;
1196                :    /* wm kernel use urb from 3, see wm_program in compiler module */
1197     19  0.0207 :    wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
1198                :
1199     10  0.0109 :    wm_state->wm4.stats_enable = 1;  /* statistic */
1200      7  0.0076 :    wm_state->wm4.sampler_state_pointer = (state_base_offset +
1201                :                                           src_sampler_offset) >> 5;
1202     19  0.0207 :    wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
1203      6  0.0065 :    wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
1204                :    wm_state->wm5.thread_dispatch_enable = 1;
1205                :    /* just use 16-pixel dispatch (4 subspans), don't need to change kernel
1206                :     * start point
1207                :     */
1208      2  0.0022 :    wm_state->wm5.enable_16_pix = 1;
1209                :    wm_state->wm5.enable_8_pix = 0;
1210     20  0.0218 :    wm_state->wm5.early_depth_test = 1;
1211                :
1212      3  0.0033 :    wm_state = (void *)(state_base + wm_offset);
1213     35  0.0381 :    memcpy (wm_state, &wm_state_local, sizeof (wm_state_local));
1214                :
1215                :    /* Begin the long sequence of commands needed to set up the 3D
1216                :     * rendering pipe
1217                :     */
1218                :    {
1219      2  0.0022 :        BEGIN_LP_RING(2);
1220      3  0.0033 :        OUT_RING(MI_FLUSH |
1221                :                 MI_STATE_INSTRUCTION_CACHE_FLUSH |
1222                :                 BRW_MI_GLOBAL_SNAPSHOT_RESET);
1223      4  0.0044 :        OUT_RING(MI_NOOP);
1224     37  0.0403 :        ADVANCE_LP_RING();
1225                :    }
1226                :    {
1227   2751  2.9969 :        BEGIN_LP_RING(12);
1228                :
1229                :        /* Match Mesa driver setup */
1230      5  0.0054 :        OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
1231                :
1232     10  0.0109 :        OUT_RING(BRW_CS_URB_STATE | 0);
1233      5  0.0054 :        OUT_RING((0 << 4) |  /* URB Entry Allocation Size */
1234                :                 (0 << 0));  /* Number of URB Entries */
1235                :
1236                :        /* Zero out the two base address registers so all offsets are
1237                :         * absolute.
1238                :         */
1239      4  0.0044 :        OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
1240      1  0.0011 :        OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
1241      2  0.0022 :        OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
1242      5  0.0054 :        OUT_RING(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
1243                :        /* general state max addr, disabled */
1244      4  0.0044 :        OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
1245                :        /* media object state max addr, disabled */
1246      7  0.0076 :        OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
1247                :
1248                :        /* Set system instruction pointer */
1249      4  0.0044 :        OUT_RING(BRW_STATE_SIP | 0);
1250     13  0.0142 :        OUT_RING(state_base_offset + sip_kernel_offset);
1251      8  0.0087 :        OUT_RING(MI_NOOP);
1252    106  0.1155 :        ADVANCE_LP_RING();
1253                :    }
1254                :    {
1255   1204  1.3116 :        BEGIN_LP_RING(26);
1256                :        /* Pipe control */
1257      2  0.0022 :        OUT_RING(BRW_PIPE_CONTROL |
1258                :                 BRW_PIPE_CONTROL_NOWRITE |
1259                :                 BRW_PIPE_CONTROL_IS_FLUSH |
1260                :                 2);
1261     15  0.0163 :        OUT_RING(0);                           /* Destination address */
1262      6  0.0065 :        OUT_RING(0);                           /* Immediate data low DW */
1263      3  0.0033 :        OUT_RING(0);                           /* Immediate data high DW */
1264                :
1265                :        /* Binding table pointers */
1266      3  0.0033 :        OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
1267      6  0.0065 :        OUT_RING(0); /* vs */
1268      5  0.0054 :        OUT_RING(0); /* gs */
1269      5  0.0054 :        OUT_RING(0); /* clip */
1270     10  0.0109 :        OUT_RING(0); /* sf */
1271                :        /* Only the PS uses the binding table */
1272     16  0.0174 :        OUT_RING(state_base_offset + binding_table_offset); /* ps */
1273                :
1274                :        /* The drawing rectangle clipping is always on.  Set it to values that
1275                :         * shouldn't do any clipping.
1276                :         */
1277     22  0.0240 :        OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */
1278     12  0.0131 :        OUT_RING(0x00000000);   /* ymin, xmin */
1279     61  0.0665 :        OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
1280                :                 DRAW_XMAX(pDst->drawable.width - 1)); /* ymax, xmax */
1281     41  0.0447 :        OUT_RING(0x00000000);   /* yorigin, xorigin */
1282                :
1283                :        /* skip the depth buffer */
1284                :        /* skip the polygon stipple */
1285                :        /* skip the polygon stipple offset */
1286                :        /* skip the line stipple */
1287                :
1288                :        /* Set the pointers to the 3d pipeline state */
1289                :        OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
1290     29  0.0316 :        OUT_RING(state_base_offset + vs_offset);  /* 32 byte aligned */
1291     11  0.0120 :        OUT_RING(BRW_GS_DISABLE);   /* disable GS, resulting in passthrough */
1292    102  0.1111 :        OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */
1293    383  0.4172 :        OUT_RING(state_base_offset + sf_offset);  /* 32 byte aligned */
1294     26  0.0283 :        OUT_RING(state_base_offset + wm_offset);  /* 32 byte aligned */
1295     17  0.0185 :        OUT_RING(state_base_offset + cc_offset);  /* 64 byte aligned */
1296                :
1297                :        /* URB fence */
1298                :        OUT_RING(BRW_URB_FENCE |
1299                :                 UF0_CS_REALLOC |
1300                :                 UF0_SF_REALLOC |
1301                :                 UF0_CLIP_REALLOC |
1302                :                 UF0_GS_REALLOC |
1303                :                 UF0_VS_REALLOC |
1304                :                 1);
1305     39  0.0425 :        OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
1306                :                 ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
1307                :                 ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
1308     28  0.0305 :        OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
1309                :                 ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
1310                :
1311                :        /* Constant buffer state */
1312     11  0.0120 :        OUT_RING(BRW_CS_URB_STATE | 0);
1313      3  0.0033 :        OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) |
1314                :                 (URB_CS_ENTRIES << 0));
1315     62  0.0675 :        ADVANCE_LP_RING();
1316                :    }
1317                :    {
1318    702  0.7647 :        int nelem = pMask ? 3: 2;
1319     12  0.0131 :        BEGIN_LP_RING(pMask?12:10);
1320                :        /* Set up the pointer to our vertex buffer */
1321      4  0.0044 :        OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3);
1322      2  0.0022 :        OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
1323                :                 VB0_VERTEXDATA |
1324                :                 ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT));
1325     10  0.0109 :        OUT_RING(state_base_offset + vb_offset);
1326      2  0.0022 :        OUT_RING(3);
1327      7  0.0076 :        OUT_RING(0); // ignore for VERTEXDATA, but still there
1328                :
1329                :        /* Set up our vertex elements, sourced from the single vertex buffer.
1330                :         */
1331      9  0.0098 :        OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));
1332                :        /* vertex coordinates */
1333      5  0.0054 :        OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
1334                :                 VE0_VALID |
1335                :                 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
1336                :                 (0 << VE0_OFFSET_SHIFT));
1337      2  0.0022 :        OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
1338                :                 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
1339                :                 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
1340                :                 (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
1341                :                 (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
1342                :        /* u0, v0 */
1343      2  0.0022 :        OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
1344                :                 VE0_VALID |
1345                :                 (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
1346                :                 (8 << VE0_OFFSET_SHIFT)); /* offset vb in bytes */
1347     14  0.0153 :        OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
1348                :                 (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
1349                :                 (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
1350                :                 (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
1351                :                 (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
1352                :        /* u1, v1 */
1353      1  0.0011 :        if (pMask) {
1354      4  0.0044 :            OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
1355                :                     VE0_VALID |
1356                :                     (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
1357                :                     (16 << VE0_OFFSET_SHIFT));
1358      1  0.0011 :            OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
1359                :                     (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
1360                :                     (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
1361                :                     (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
1362                :                     (10 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
1363                :        }
1364                :
1365     66  0.0719 :        ADVANCE_LP_RING();
1366                :    }
1367                :
1368                :#ifdef I830DEBUG
1369                :    ErrorF("try to sync to show any errors...");
1370                :    I830Sync(pScrn);
1371                :#endif
1372                :    return TRUE;
1373   1196  1.3029 :}
1374                :
1375                :void
1376                :i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
1377                :               int dstX, int dstY, int w, int h)
1378    707  0.7702 :{ /* i965_composite total:   2800  3.0503 */
1379     38  0.0414 :    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
1380      3  0.0033 :    I830Ptr pI830 = I830PTR(pScrn);
1381                :    Bool has_mask;
1382                :    float src_x[3], src_y[3], mask_x[3], mask_y[3];
1383                :    int i;
1384                :
1385     22  0.0240 :    i830_get_transformed_coordinates(srcX, srcY,
1386                :                                     pI830->transform[0],
1387                :                                     &src_x[0], &src_y[0]);
1388      5  0.0054 :    i830_get_transformed_coordinates(srcX, srcY + h,
1389                :                                     pI830->transform[0],
1390                :                                     &src_x[1], &src_y[1]);
1391     15  0.0163 :    i830_get_transformed_coordinates(srcX + w, srcY + h,
1392                :                                     pI830->transform[0],
1393                :                                     &src_x[2], &src_y[2]);
1394                :
1395     18  0.0196 :    if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
1396                :        has_mask = FALSE;
1397                :    } else {
1398                :        has_mask = TRUE;
1399      1  0.0011 :        i830_get_transformed_coordinates(maskX, maskY,
1400                :                                         pI830->transform[1],
1401                :                                         &mask_x[0], &mask_y[0]);
1402      8  0.0087 :        i830_get_transformed_coordinates(maskX, maskY + h,
1403                :                                         pI830->transform[1],
1404                :                                         &mask_x[1], &mask_y[1]);
1405     33  0.0359 :        i830_get_transformed_coordinates(maskX + w, maskY + h,
1406                :                                         pI830->transform[1],
1407                :                                         &mask_x[2], &mask_y[2]);
1408                :    }
1409                :
1410                :    /* Wait for any existing composite rectangles to land before we overwrite
1411                :     * the VB with the next one.
1412                :     */
1413      7  0.0076 :    i830WaitSync(pScrn);
1414                :
1415                :    i = 0;
1416                :    /* rect (x2,y2) */
1417      6  0.0065 :    vb[i++] = (float)(dstX + w);
1418      7  0.0076 :    vb[i++] = (float)(dstY + h);
1419      4  0.0044 :    vb[i++] = src_x[2] / pI830->scale_units[0][0];
1420      8  0.0087 :    vb[i++] = src_y[2] / pI830->scale_units[0][1];
1421                :    if (has_mask) {
1422     77  0.0839 :        vb[i++] = mask_x[2] / pI830->scale_units[1][0];
1423     88  0.0959 :        vb[i++] = mask_y[2] / pI830->scale_units[1][1];
1424                :    }
1425                :
1426                :    /* rect (x1,y2) */
1427      2  0.0022 :    vb[i++] = (float)dstX;
1428      1  0.0011 :    vb[i++] = (float)(dstY + h);
1429      3  0.0033 :    vb[i++] = src_x[1] / pI830->scale_units[0][0];
1430     14  0.0153 :    vb[i++] = src_y[1] / pI830->scale_units[0][1];
1431      2  0.0022 :    if (has_mask) {
1432      7  0.0076 :        vb[i++] = mask_x[1] / pI830->scale_units[1][0];
1433     72  0.0784 :        vb[i++] = mask_y[1] / pI830->scale_units[1][1];
1434                :    }
1435                :
1436                :    /* rect (x1,y1) */
1437      2  0.0022 :    vb[i++] = (float)dstX;
1438      3  0.0033 :    vb[i++] = (float)dstY;
1439      3  0.0033 :    vb[i++] = src_x[0] / pI830->scale_units[0][0];
1440      5  0.0054 :    vb[i++] = src_y[0] / pI830->scale_units[0][1];
1441                :    if (has_mask) {
1442      7  0.0076 :        vb[i++] = mask_x[0] / pI830->scale_units[1][0];
1443     11  0.0120 :        vb[i++] = mask_y[0] / pI830->scale_units[1][1];
1444                :    }
1445                :
1446                :    {
1447      2  0.0022 :      BEGIN_LP_RING(6);
1448      3  0.0033 :      OUT_RING(BRW_3DPRIMITIVE |
1449                :               BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
1450                :               (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) |
1451                :               (0 << 9) |  /* CTG - indirect vertex count */
1452                :               4);
1453      4  0.0044 :      OUT_RING(3);  /* vertex count per instance */
1454                :      OUT_RING(0); /* start vertex offset */
1455      3  0.0033 :      OUT_RING(1); /* single instance */
1456      4  0.0044 :      OUT_RING(0); /* start instance location */
1457      3  0.0033 :      OUT_RING(0); /* index buffer offset, ignored */
1458      4  0.0044 :      ADVANCE_LP_RING();
1459                :    }
1460                :#ifdef I830DEBUG
1461                :    ErrorF("sync after 3dprimitive");
1462                :    I830Sync(pScrn);
1463                :#endif
1464                :    /* we must be sure that the pipeline is flushed before next exa draw,
1465                :       because that will be new state, binding state and instructions*/
1466                :    {
1467    804  0.8759 :        BEGIN_LP_RING(4);
1468                :        OUT_RING(BRW_PIPE_CONTROL |
1469                :            BRW_PIPE_CONTROL_NOWRITE |
1470                :            BRW_PIPE_CONTROL_WC_FLUSH |
1471                :            BRW_PIPE_CONTROL_IS_FLUSH |
1472                :            (1 << 10) |  /* XXX texture cache flush for BLC/CTG */
1473                :            2);
1474      2  0.0022 :        OUT_RING(0); /* Destination address */
1475      5  0.0054 :        OUT_RING(0); /* Immediate data low DW */
1476      5  0.0054 :        OUT_RING(0); /* Immediate data high DW */
1477      7  0.0076 :        ADVANCE_LP_RING();
1478                :    }
1479                :
1480                :    /* Mark sync so we can wait for it before setting up the VB on the next
1481                :     * rectangle.
1482                :     */
1483    773  0.8421 :    i830MarkSync(pScrn);
1484      2  0.0022 :}
1485 /* 
1486  * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa.c"
1487  * 
1488  *    854  0.9303
1489  */
1490
1491
1492                :/*
1493                : * Copyright Â© 2001 Keith Packard
1494                : *
1495                : * Partly based on code that is Copyright Â© The XFree86 Project Inc.
1496                : *
1497                : * Permission to use, copy, modify, distribute, and sell this software and its
1498                : * documentation for any purpose is hereby granted without fee, provided that
1499                : * the above copyright notice appear in all copies and that both that
1500                : * copyright notice and this permission notice appear in supporting
1501                : * documentation, and that the name of Keith Packard not be used in
1502                : * advertising or publicity pertaining to distribution of the software without
1503                : * specific, written prior permission.  Keith Packard makes no
1504                : * representations about the suitability of this software for any purpose.  It
1505                : * is provided "as is" without express or implied warranty.
1506                : *
1507                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1508                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1509                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1510                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1511                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1512                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1513                : * PERFORMANCE OF THIS SOFTWARE.
1514                : */
1515                :
1516                :/** @file
1517                : * This file covers the initialization and teardown of EXA, and has various
1518                : * functions not responsible for performing rendering, pixmap migration, or
1519                : * memory management.
1520                : */
1521                :
1522                :#ifdef HAVE_DIX_CONFIG_H
1523                :#include <dix-config.h>
1524                :#endif
1525                :
1526                :#ifdef MITSHM
1527                :#include "shmint.h"
1528                :#endif
1529                :
1530                :#include <stdlib.h>
1531                :
1532                :#include "exa_priv.h"
1533                :#include <X11/fonts/fontstruct.h>
1534                :#include "dixfontstr.h"
1535                :#include "exa.h"
1536                :#include "cw.h"
1537                :
1538                :static int exaGeneration;
1539                :int exaScreenPrivateIndex;
1540                :int exaPixmapPrivateIndex;
1541                :
1542                :/**
1543                : * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
1544                : * the beginning of the given pixmap.
1545                : *
1546                : * Note that drivers are free to, and often do, munge this offset as necessary
1547                : * for handing to the hardware -- for example, translating it into a different
1548                : * aperture.  This function may need to be extended in the future if we grow
1549                : * support for having multiple card-accessible offscreen, such as an AGP memory
1550                : * pool alongside the framebuffer pool.
1551                : */
1552                :unsigned long
1553                :exaGetPixmapOffset(PixmapPtr pPix)
1554     11  0.0120 :{ /* exaGetPixmapOffset total:     35  0.0381 */
1555      3  0.0033 :    ExaScreenPriv (pPix->drawable.pScreen);
1556      6  0.0065 :    ExaPixmapPriv (pPix);
1557                :    void *ptr;
1558                :
1559                :    /* Return the offscreen pointer if we've hidden the data. */
1560      5  0.0054 :    if (pPix->devPrivate.ptr == NULL)
1561                :        ptr = pExaPixmap->fb_ptr;
1562                :    else
1563                :        ptr = pPix->devPrivate.ptr;
1564                :
1565                :    return ((unsigned long)ptr - (unsigned long)pExaScr->info->memoryBase);
1566     10  0.0109 :}
1567                :
1568                :/**
1569                : * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap.
1570                : *
1571                : * This is a helper to make driver code more obvious, due to the rather obscure
1572                : * naming of the pitch field in the pixmap.
1573                : */
1574                :unsigned long
1575                :exaGetPixmapPitch(PixmapPtr pPix)
1576      2  0.0022 :{ /* exaGetPixmapPitch total:      7  0.0076 */
1577                :    return pPix->devKind;
1578      5  0.0054 :}
1579                :
1580                :/**
1581                : * exaGetPixmapSize() returns the size in bytes of the given pixmap in video
1582                : * memory. Only valid when the pixmap is currently in framebuffer.
1583                : */
1584                :unsigned long
1585                :exaGetPixmapSize(PixmapPtr pPix)
1586                :{
1587                :    ExaPixmapPrivPtr pExaPixmap;
1588                :
1589                :    pExaPixmap = ExaGetPixmapPriv(pPix);
1590                :    if (pExaPixmap != NULL)
1591                :        return pExaPixmap->fb_size;
1592                :    return 0;
1593                :}
1594                :
1595                :/**
1596                : * exaGetDrawablePixmap() returns a backing pixmap for a given drawable.
1597                : *
1598                : * @param pDrawable the drawable being requested.
1599                : *
1600                : * This function returns the backing pixmap for a drawable, whether it is a
1601                : * redirected window, unredirected window, or already a pixmap.  Note that
1602                : * coordinate translation is needed when drawing to the backing pixmap of a
1603                : * redirected window, and the translation coordinates are provided by calling
1604                : * exaGetOffscreenPixmap() on the drawable.
1605                : */
1606                :PixmapPtr
1607                :exaGetDrawablePixmap(DrawablePtr pDrawable)
1608     53  0.0577 :{ /* exaGetDrawablePixmap total:    111  0.1209 */
1609      5  0.0054 :     if (pDrawable->type == DRAWABLE_WINDOW)
1610                :        return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable);
1611                :     else
1612     30  0.0327 :        return (PixmapPtr) pDrawable;
1613     23  0.0251 :}       
1614                :
1615                :/**
1616                : * Sets the offsets to add to coordinates to make them address the same bits in
1617                : * the backing drawable. These coordinates are nonzero only for redirected
1618                : * windows.
1619                : */
1620                :void
1621                :exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
1622                :                      int *xp, int *yp)
1623      8  0.0087 :{ /* exaGetDrawableDeltas total:     52  0.0566 */
1624                :#ifdef COMPOSITE
1625     21  0.0229 :    if (pDrawable->type == DRAWABLE_WINDOW) {
1626                :        *xp = -pPixmap->screen_x;
1627                :        *yp = -pPixmap->screen_y;
1628                :        return;
1629                :    }
1630                :#endif
1631                :
1632      4  0.0044 :    *xp = 0;
1633      1  0.0011 :    *yp = 0;
1634     18  0.0196 :}
1635                :
1636                :/**
1637                : * exaPixmapDirty() marks a pixmap as dirty, allowing for
1638                : * optimizations in pixmap migration when no changes have occurred.
1639                : */
1640                :void
1641                :exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
1642     20  0.0218 :{ /* exaPixmapDirty total:     90  0.0980 */
1643      6  0.0065 :    ExaPixmapPriv(pPix);
1644                :    BoxRec box;
1645                :    RegionPtr pDamageReg;
1646                :    RegionRec region;
1647                :
1648     11  0.0120 :    if (!pExaPixmap)
1649                :        return;
1650                :        
1651      3  0.0033 :    box.x1 = max(x1, 0);
1652                :    box.y1 = max(y1, 0);
1653      6  0.0065 :    box.x2 = min(x2, pPix->drawable.width);
1654     13  0.0142 :    box.y2 = min(y2, pPix->drawable.height);
1655                :
1656      4  0.0044 :    if (box.x1 >= box.x2 || box.y1 >= box.y2)
1657                :        return;
1658                :
1659      4  0.0044 :    pDamageReg = DamageRegion(pExaPixmap->pDamage);
1660                :
1661      5  0.0054 :    REGION_INIT(pScreen, &region, &box, 1);
1662      6  0.0065 :    REGION_UNION(pScreen, pDamageReg, pDamageReg, &region);
1663      4  0.0044 :    REGION_UNINIT(pScreen, &region);
1664      8  0.0087 :}
1665                :
1666                :static Bool
1667                :exaDestroyPixmap (PixmapPtr pPixmap)
1668      3  0.0033 :{ /* exaDestroyPixmap total:      4  0.0044 */
1669                :    if (pPixmap->refcnt == 1)
1670                :    {
1671                :        ExaPixmapPriv (pPixmap);
1672                :        if (pExaPixmap->area)
1673                :        {
1674                :            DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
1675                :                        (void*)pPixmap->drawable.id,
1676                :                         ExaGetPixmapPriv(pPixmap)->area->offset,
1677                :                         pPixmap->drawable.width,
1678                :                         pPixmap->drawable.height));
1679                :            /* Free the offscreen area */
1680                :            exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
1681      1  0.0011 :            pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
1682                :            pPixmap->devKind = pExaPixmap->sys_pitch;
1683                :        }
1684                :        REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validReg);
1685                :    }
1686                :    return fbDestroyPixmap (pPixmap);
1687                :}
1688                :
1689                :static int
1690                :exaLog2(int val)
1691                :{
1692                :    int bits;
1693                :
1694                :    if (val <= 0)
1695                :        return 0;
1696                :    for (bits = 0; val != 0; bits++)
1697                :        val >>= 1;
1698                :    return bits - 1;
1699                :}
1700                :
1701                :/**
1702                : * exaCreatePixmap() creates a new pixmap.
1703                : *
1704                : * If width and height are 0, this won't be a full-fledged pixmap and it will
1705                : * get ModifyPixmapHeader() called on it later.  So, we mark it as pinned, because
1706                : * ModifyPixmapHeader() would break migration.  These types of pixmaps are used
1707                : * for scratch pixmaps, or to represent the visible screen.
1708                : */
1709                :static PixmapPtr
1710                :exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
1711      4  0.0044 :{ /* exaCreatePixmap total:     19  0.0207 */
1712                :    PixmapPtr           pPixmap;
1713                :    ExaPixmapPrivPtr    pExaPixmap;
1714                :    int                 bpp;
1715      1  0.0011 :    ExaScreenPriv(pScreen);
1716                :
1717                :    if (w > 32767 || h > 32767)
1718                :        return NullPixmap;
1719                :
1720      3  0.0033 :    pPixmap = fbCreatePixmap (pScreen, w, h, depth);
1721                :    if (!pPixmap)
1722                :        return NULL;
1723      1  0.0011 :    pExaPixmap = ExaGetPixmapPriv(pPixmap);
1724                :
1725                :    bpp = pPixmap->drawable.bitsPerPixel;
1726                :
1727                :    /* Glyphs have w/h equal to zero, and may not be migrated. See exaGlyphs. */
1728      1  0.0011 :    if (!w || !h)
1729                :        pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1730                :    else
1731      2  0.0022 :        pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
1732                :
1733                :    pExaPixmap->area = NULL;
1734                :
1735                :    pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
1736                :    pExaPixmap->sys_pitch = pPixmap->devKind;
1737                :
1738                :    pExaPixmap->fb_ptr = NULL;
1739      1  0.0011 :    if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
1740                :        pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8;
1741                :    else
1742      1  0.0011 :        pExaPixmap->fb_pitch = w * bpp / 8;
1743      4  0.0044 :    pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
1744                :                                     pExaScr->info->pixmapPitchAlign);
1745                :    pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
1746                :
1747                :    if (pExaPixmap->fb_pitch > 32767) {
1748                :        fbDestroyPixmap(pPixmap);
1749                :        return NULL;
1750                :    }
1751                :
1752                :    /* Set up damage tracking */
1753                :    pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE,
1754                :                                        pScreen, pPixmap);
1755                :
1756                :    if (pExaPixmap->pDamage == NULL) {
1757                :        fbDestroyPixmap (pPixmap);
1758                :        return NULL;
1759                :    }
1760                :
1761                :    DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
1762                :    DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
1763                :
1764                :    /* None of the pixmap bits are valid initially */
1765      1  0.0011 :    REGION_NULL(pScreen, &pExaPixmap->validReg);
1766                :
1767                :    return pPixmap;
1768                :}
1769                :
1770                :/**
1771                : * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen
1772                : * memory, meaning that acceleration could probably be done to it, and that it
1773                : * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
1774                : * with the CPU.
1775                : *
1776                : * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
1777                : * deal with moving pixmaps in and out of system memory), EXA will give drivers
1778                : * pixmaps as arguments for which exaPixmapIsOffscreen() is TRUE.
1779                : *
1780                : * @return TRUE if the given drawable is in framebuffer memory.
1781                : */
1782                :Bool
1783                :exaPixmapIsOffscreen(PixmapPtr p)
1784     44  0.0479 :{ /* exaPixmapIsOffscreen total:    267  0.2909 */
1785                :    ScreenPtr   pScreen = p->drawable.pScreen;
1786     53  0.0577 :    ExaScreenPriv(pScreen);
1787                :
1788                :    /* If the devPrivate.ptr is NULL, it's offscreen but we've hidden the data.
1789                :     */
1790     36  0.0392 :    if (p->devPrivate.ptr == NULL)
1791                :        return TRUE;
1792                :
1793     80  0.0872 :    if (pExaScr->info->PixmapIsOffscreen)
1794                :        return pExaScr->info->PixmapIsOffscreen(p);
1795                :
1796     27  0.0294 :    return ((unsigned long) ((CARD8 *) p->devPrivate.ptr -
1797                :                             (CARD8 *) pExaScr->info->memoryBase) <
1798                :            pExaScr->info->memorySize);
1799     27  0.0294 :}
1800                :
1801                :/**
1802                : * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapIsOffscreen().
1803                : */
1804                :Bool
1805                :exaDrawableIsOffscreen (DrawablePtr pDrawable)
1806                :{
1807                :    return exaPixmapIsOffscreen (exaGetDrawablePixmap (pDrawable));
1808                :}
1809                :
1810                :/**
1811                : * Returns the pixmap which backs a drawable, and the offsets to add to
1812                : * coordinates to make them address the same bits in the backing drawable.
1813                : */
1814                :PixmapPtr
1815                :exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
1816     17  0.0185 :{ /* exaGetOffscreenPixmap total:     69  0.0752 */
1817      6  0.0065 :    PixmapPtr   pPixmap = exaGetDrawablePixmap (pDrawable);
1818                :
1819     16  0.0174 :    exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp);
1820                :
1821     15  0.0163 :    if (exaPixmapIsOffscreen (pPixmap))
1822                :        return pPixmap;
1823                :    else
1824                :        return NULL;
1825     15  0.0163 :}
1826                :
1827                :/**
1828                : * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
1829                : *
1830                : * It deals with waiting for synchronization with the card, determining if
1831                : * PrepareAccess() is necessary, and working around PrepareAccess() failure.
1832                : */
1833                :void
1834                :exaPrepareAccess(DrawablePtr pDrawable, int index)
1835                :{ /* exaPrepareAccess total:      1  0.0011 */
1836                :    ScreenPtr       pScreen = pDrawable->pScreen;
1837                :    ExaScreenPriv  (pScreen);
1838                :    PixmapPtr       pPixmap;
1839                :
1840                :    pPixmap = exaGetDrawablePixmap (pDrawable);
1841                :
1842                :    if (exaPixmapIsOffscreen (pPixmap))
1843                :        exaWaitSync (pDrawable->pScreen);
1844                :    else
1845                :        return;
1846                :
1847                :    /* Unhide pixmap pointer */
1848                :    if (pPixmap->devPrivate.ptr == NULL) {
1849                :        ExaPixmapPriv (pPixmap);
1850                :
1851                :        pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
1852                :    }
1853                :
1854      1  0.0011 :    if (pExaScr->info->PrepareAccess == NULL)
1855                :        return;
1856                :
1857                :    if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
1858                :        ExaPixmapPriv (pPixmap);
1859                :        if (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED)
1860                :            FatalError("Driver failed PrepareAccess on a pinned pixmap\n");
1861                :        exaMoveOutPixmap (pPixmap);
1862                :    }
1863                :}
1864                :
1865                :/**
1866                : * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
1867                : *
1868                : * It deals with calling the driver's FinishAccess() only if necessary.
1869                : */
1870                :void
1871                :exaFinishAccess(DrawablePtr pDrawable, int index)
1872                :{ /* exaFinishAccess total:      1  0.0011 */
1873                :    ScreenPtr       pScreen = pDrawable->pScreen;
1874      1  0.0011 :    ExaScreenPriv  (pScreen);
1875                :    PixmapPtr       pPixmap;
1876                :    ExaPixmapPrivPtr pExaPixmap;
1877                :
1878                :    pPixmap = exaGetDrawablePixmap (pDrawable);
1879                :
1880                :    pExaPixmap = ExaGetPixmapPriv(pPixmap);
1881                :
1882                :    /* Rehide pixmap pointer if we're doing that. */
1883                :    if (pExaPixmap != NULL && pExaScr->hideOffscreenPixmapData &&
1884                :        pExaPixmap->fb_ptr == pPixmap->devPrivate.ptr)
1885                :    {
1886                :        pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
1887                :    }
1888                :
1889                :    if (pExaScr->info->FinishAccess == NULL)
1890                :        return;
1891                :
1892                :    if (!exaPixmapIsOffscreen (pPixmap))
1893                :        return;
1894                :
1895                :    (*pExaScr->info->FinishAccess) (pPixmap, index);
1896                :}
1897                :
1898                :/**
1899                : * exaValidateGC() sets the ops to EXA's implementations, which may be
1900                : * accelerated or may sync the card and fall back to fb.
1901                : */
1902                :static void
1903                :exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
1904      2  0.0022 :{ /* exaValidateGC total:      8  0.0087 */
1905                :    /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
1906                :     * Preempt fbValidateGC by doing its work and masking the change out, so
1907                :     * that we can do the Prepare/FinishAccess.
1908                :     */
1909                :#ifdef FB_24_32BIT
1910      1  0.0011 :    if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
1911                :        (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
1912                :        fbGetRotatedPixmap(pGC) = 0;
1913                :    }
1914                :        
1915                :    if (pGC->fillStyle == FillTiled) {
1916                :        PixmapPtr       pOldTile, pNewTile;
1917                :
1918                :        pOldTile = pGC->tile.pixmap;
1919                :        if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
1920                :        {
1921                :            pNewTile = fbGetRotatedPixmap(pGC);
1922                :            if (!pNewTile ||
1923                :                pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
1924                :            {
1925                :                if (pNewTile)
1926                :                    (*pGC->pScreen->DestroyPixmap) (pNewTile);
1927                :                /* fb24_32ReformatTile will do direct access of a newly-
1928                :                 * allocated pixmap.  This isn't a problem yet, since we don't
1929                :                 * put pixmaps in FB until at least one accelerated EXA op.
1930                :                 */
1931                :                exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
1932                :                pNewTile = fb24_32ReformatTile (pOldTile,
1933                :                                                pDrawable->bitsPerPixel);
1934                :                exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height);
1935                :                exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
1936                :            }
1937                :            if (pNewTile)
1938                :            {
1939                :                fbGetRotatedPixmap(pGC) = pOldTile;
1940                :                pGC->tile.pixmap = pNewTile;
1941                :                changes |= GCTile;
1942                :            }
1943                :        }
1944                :    }
1945                :#endif
1946                :    if (changes & GCTile) {
1947                :        if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
1948                :                                             pDrawable->bitsPerPixel))
1949                :        {
1950                :            /* XXX This fixes corruption with tiled pixmaps, but may just be a
1951                :             * workaround for broken drivers
1952                :             */
1953                :            exaMoveOutPixmap(pGC->tile.pixmap);
1954                :            fbPadPixmap (pGC->tile.pixmap);
1955                :            exaPixmapDirty(pGC->tile.pixmap, 0, 0,
1956                :                           pGC->tile.pixmap->drawable.width,
1957                :                           pGC->tile.pixmap->drawable.height);
1958                :        }
1959                :        /* Mask out the GCTile change notification, now that we've done FB's
1960                :         * job for it.
1961                :         */
1962                :        changes &= ~GCTile;
1963                :    }
1964                :
1965      1  0.0011 :    fbValidateGC (pGC, changes, pDrawable);
1966                :
1967      1  0.0011 :    pGC->ops = (GCOps *) &exaOps;
1968      3  0.0033 :}
1969                :
1970                :static GCFuncs  exaGCFuncs = {
1971                :    exaValidateGC,
1972                :    miChangeGC,
1973                :    miCopyGC,
1974                :    miDestroyGC,
1975                :    miChangeClip,
1976                :    miDestroyClip,
1977                :    miCopyClip
1978                :};
1979                :
1980                :/**
1981                : * exaCreateGC makes a new GC and hooks up its funcs handler, so that
1982                : * exaValidateGC() will get called.
1983                : */
1984                :static int
1985                :exaCreateGC (GCPtr pGC)
1986                :{
1987                :    if (!fbCreateGC (pGC))
1988                :        return FALSE;
1989                :
1990                :    pGC->funcs = &exaGCFuncs;
1991                :
1992                :    return TRUE;
1993                :}
1994                :
1995                :/**
1996                : * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
1997                : * screen private, before calling down to the next CloseSccreen.
1998                : */
1999                :static Bool
2000                :exaCloseScreen(int i, ScreenPtr pScreen)
2001                :{
2002                :    ExaScreenPriv(pScreen);
2003                :#ifdef RENDER
2004                :    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
2005                :#endif
2006                :
2007                :    pScreen->CreateGC = pExaScr->SavedCreateGC;
2008                :    pScreen->CloseScreen = pExaScr->SavedCloseScreen;
2009                :    pScreen->GetImage = pExaScr->SavedGetImage;
2010                :    pScreen->GetSpans = pExaScr->SavedGetSpans;
2011                :    pScreen->PaintWindowBackground = pExaScr->SavedPaintWindowBackground;
2012                :    pScreen->PaintWindowBorder = pExaScr->SavedPaintWindowBorder;
2013                :    pScreen->CreatePixmap = pExaScr->SavedCreatePixmap;
2014                :    pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap;
2015                :    pScreen->CopyWindow = pExaScr->SavedCopyWindow;
2016                :#ifdef RENDER
2017                :    if (ps) {
2018                :        ps->Composite = pExaScr->SavedComposite;
2019                :        ps->Glyphs = pExaScr->SavedGlyphs;
2020                :    }
2021                :#endif
2022                :
2023                :    xfree (pExaScr);
2024                :
2025                :    return (*pScreen->CloseScreen) (i, pScreen);
2026                :}
2027                :
2028                :/**
2029                : * This function allocates a driver structure for EXA drivers to fill in.  By
2030                : * having EXA allocate the structure, the driver structure can be extended
2031                : * without breaking ABI between EXA and the drivers.  The driver's
2032                : * responsibility is to check beforehand that the EXA module has a matching
2033                : * major number and sufficient minor.  Drivers are responsible for freeing the
2034                : * driver structure using xfree().
2035                : *
2036                : * @return a newly allocated, zero-filled driver structure
2037                : */
2038                :ExaDriverPtr
2039                :exaDriverAlloc(void)
2040                :{
2041                :    return xcalloc(1, sizeof(ExaDriverRec));
2042                :}
2043                :
2044                :/**
2045                : * @param pScreen screen being initialized
2046                : * @param pScreenInfo EXA driver record
2047                : *
2048                : * exaDriverInit sets up EXA given a driver record filled in by the driver.
2049                : * pScreenInfo should have been allocated by exaDriverAlloc().  See the
2050                : * comments in _ExaDriver for what must be filled in and what is optional.
2051                : *
2052                : * @return TRUE if EXA was successfully initialized.
2053                : */
2054                :Bool
2055                :exaDriverInit (ScreenPtr                pScreen,
2056                :               ExaDriverPtr     pScreenInfo)
2057                :{
2058                :    ExaScreenPrivPtr pExaScr;
2059                :#ifdef RENDER
2060                :    PictureScreenPtr ps;
2061                :#endif
2062                :
2063                :    if (pScreenInfo->exa_major != EXA_VERSION_MAJOR ||
2064                :        pScreenInfo->exa_minor > EXA_VERSION_MINOR)
2065                :    {
2066                :        LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements "
2067                :                   "(%d.%d) are incompatible with EXA version (%d.%d)\n",
2068                :                   pScreen->myNum,
2069                :                   pScreenInfo->exa_major, pScreenInfo->exa_minor,
2070                :                   EXA_VERSION_MAJOR, EXA_VERSION_MINOR);
2071                :        return FALSE;
2072                :    }
2073                :
2074                :#ifdef RENDER
2075                :    ps = GetPictureScreenIfSet(pScreen);
2076                :#endif
2077                :    if (exaGeneration != serverGeneration)
2078                :    {
2079                :        exaScreenPrivateIndex = AllocateScreenPrivateIndex();
2080                :        exaPixmapPrivateIndex = AllocatePixmapPrivateIndex();
2081                :        exaGeneration = serverGeneration;
2082                :    }
2083                :
2084                :    pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1);
2085                :
2086                :    if (!pExaScr) {
2087                :        LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n",
2088                :                   pScreen->myNum);
2089                :        return FALSE;
2090                :    }
2091                :
2092                :    pExaScr->info = pScreenInfo;
2093                :
2094                :    pScreen->devPrivates[exaScreenPrivateIndex].ptr = (pointer) pExaScr;
2095                :
2096                :    pExaScr->migration = ExaMigrationAlways;
2097                :
2098                :    exaDDXDriverInit(pScreen);
2099                :
2100                :    /*
2101                :     * Replace various fb screen functions
2102                :     */
2103                :    pExaScr->SavedCloseScreen = pScreen->CloseScreen;
2104                :    pScreen->CloseScreen = exaCloseScreen;
2105                :
2106                :    pExaScr->SavedCreateGC = pScreen->CreateGC;
2107                :    pScreen->CreateGC = exaCreateGC;
2108                :
2109                :    pExaScr->SavedGetImage = pScreen->GetImage;
2110                :    pScreen->GetImage = exaGetImage;
2111                :
2112                :    pExaScr->SavedGetSpans = pScreen->GetSpans;
2113                :    pScreen->GetSpans = exaGetSpans;
2114                :
2115                :    pExaScr->SavedCopyWindow = pScreen->CopyWindow;
2116                :    pScreen->CopyWindow = exaCopyWindow;
2117                :
2118                :    pExaScr->SavedPaintWindowBackground = pScreen->PaintWindowBackground;
2119                :    pScreen->PaintWindowBackground = exaPaintWindow;
2120                :
2121                :    pExaScr->SavedPaintWindowBorder = pScreen->PaintWindowBorder;
2122                :    pScreen->PaintWindowBorder = exaPaintWindow;
2123                :
2124                :    pScreen->BackingStoreFuncs.SaveAreas = ExaCheckSaveAreas;
2125                :    pScreen->BackingStoreFuncs.RestoreAreas = ExaCheckRestoreAreas;
2126                :#ifdef RENDER
2127                :    if (ps) {
2128                :        pExaScr->SavedComposite = ps->Composite;
2129                :        ps->Composite = exaComposite;
2130                :
2131                :        pExaScr->SavedRasterizeTrapezoid = ps->RasterizeTrapezoid;
2132                :        ps->RasterizeTrapezoid = exaRasterizeTrapezoid;
2133                :
2134                :        pExaScr->SavedAddTriangles = ps->AddTriangles;
2135                :        ps->AddTriangles = exaAddTriangles;
2136                :
2137                :        pExaScr->SavedGlyphs = ps->Glyphs;
2138                :        ps->Glyphs = exaGlyphs;
2139                :    }
2140                :#endif
2141                :
2142                :#ifdef MITSHM
2143                :    /* Re-register with the MI funcs, which don't allow shared pixmaps.
2144                :     * Shared pixmaps are almost always a performance loss for us, but this
2145                :     * still allows for SHM PutImage.
2146                :     */
2147                :    ShmRegisterFuncs(pScreen, NULL);
2148                :#endif
2149                :    /*
2150                :     * Hookup offscreen pixmaps
2151                :     */
2152                :    if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
2153                :        pExaScr->info->offScreenBase < pExaScr->info->memorySize)
2154                :    {
2155                :        if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex,
2156                :                                   sizeof (ExaPixmapPrivRec))) {
2157                :            LogMessage(X_WARNING,
2158                :                       "EXA(%d): Failed to allocate pixmap private\n",
2159                :                       pScreen->myNum);
2160                :            return FALSE;
2161                :        }
2162                :        pExaScr->SavedCreatePixmap = pScreen->CreatePixmap;
2163                :        pScreen->CreatePixmap = exaCreatePixmap;
2164                :
2165                :        pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap;
2166                :        pScreen->DestroyPixmap = exaDestroyPixmap;
2167                :
2168                :        LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %d bytes\n",
2169                :                   pScreen->myNum,
2170                :                   pExaScr->info->memorySize - pExaScr->info->offScreenBase);
2171                :    }
2172                :    else
2173                :    {
2174                :        LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum);
2175                :        if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex, 0))
2176                :            return FALSE;
2177                :    }
2178                :
2179                :    DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase,
2180                :                pExaScr->info->memorySize));
2181                :    if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) {
2182                :        if (!exaOffscreenInit (pScreen)) {
2183                :            LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n",
2184                :                       pScreen->myNum);
2185                :            return FALSE;
2186                :        }
2187                :    }
2188                :
2189                :    LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
2190                :               " operations:\n", pScreen->myNum);
2191                :    assert(pScreenInfo->PrepareSolid != NULL);
2192                :    LogMessage(X_INFO, "        Solid\n");
2193                :    assert(pScreenInfo->PrepareCopy != NULL);
2194                :    LogMessage(X_INFO, "        Copy\n");
2195                :    if (pScreenInfo->PrepareComposite != NULL) {
2196                :        LogMessage(X_INFO, "        Composite (RENDER acceleration)\n");
2197                :    }
2198                :    if (pScreenInfo->UploadToScreen != NULL) {
2199                :        LogMessage(X_INFO, "        UploadToScreen\n");
2200                :    }
2201                :    if (pScreenInfo->DownloadFromScreen != NULL) {
2202                :        LogMessage(X_INFO, "        DownloadFromScreen\n");
2203                :    }
2204                :
2205                :    return TRUE;
2206                :}
2207                :
2208                :/**
2209                : * exaDriverFini tears down EXA on a given screen.
2210                : *
2211                : * @param pScreen screen being torn down.
2212                : */
2213                :void
2214                :exaDriverFini (ScreenPtr pScreen)
2215                :{
2216                :    /*right now does nothing*/
2217                :}
2218                :
2219                :/**
2220                : * exaMarkSync() should be called after any asynchronous drawing by the hardware.
2221                : *
2222                : * @param pScreen screen which drawing occurred on
2223                : *
2224                : * exaMarkSync() sets a flag to indicate that some asynchronous drawing has
2225                : * happened and a WaitSync() will be necessary before relying on the contents of
2226                : * offscreen memory from the CPU's perspective.  It also calls an optional
2227                : * driver MarkSync() callback, the return value of which may be used to do partial
2228                : * synchronization with the hardware in the future.
2229                : */
2230                :void exaMarkSync(ScreenPtr pScreen)
2231     22  0.0240 :{ /* exaMarkSync total:     88  0.0959 */
2232     10  0.0109 :    ExaScreenPriv(pScreen);
2233                :
2234     13  0.0142 :    pExaScr->info->needsSync = TRUE;
2235     34  0.0370 :    if (pExaScr->info->MarkSync != NULL) {
2236                :        pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen);
2237                :    }
2238      9  0.0098 :}
2239                :
2240                :/**
2241                : * exaWaitSync() ensures that all drawing has been completed.
2242                : *
2243                : * @param pScreen screen being synchronized.
2244                : *
2245                : * Calls down into the driver to ensure that all previous drawing has completed.
2246                : * It should always be called before relying on the framebuffer contents
2247                : * reflecting previous drawing, from a CPU perspective.
2248                : */
2249                :void exaWaitSync(ScreenPtr pScreen)
2250      9  0.0098 :{ /* exaWaitSync total:    102  0.1111 */
2251      5  0.0054 :    ExaScreenPriv(pScreen);
2252                :
2253     45  0.0490 :    if (pExaScr->info->needsSync && !pExaScr->swappedOut) {
2254      4  0.0044 :        (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker);
2255     22  0.0240 :        pExaScr->info->needsSync = FALSE;
2256                :    }
2257     17  0.0185 :}
2258 /* 
2259  * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa_render.c"
2260  * 
2261  *    785  0.8552
2262  */
2263
2264
2265                :/*
2266                : * Copyright Â© 2001 Keith Packard
2267                : *
2268                : * Partly based on code that is Copyright Â© The XFree86 Project Inc.
2269                : *
2270                : * Permission to use, copy, modify, distribute, and sell this software and its
2271                : * documentation for any purpose is hereby granted without fee, provided that
2272                : * the above copyright notice appear in all copies and that both that
2273                : * copyright notice and this permission notice appear in supporting
2274                : * documentation, and that the name of Keith Packard not be used in
2275                : * advertising or publicity pertaining to distribution of the software without
2276                : * specific, written prior permission.  Keith Packard makes no
2277                : * representations about the suitability of this software for any purpose.  It
2278                : * is provided "as is" without express or implied warranty.
2279                : *
2280                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2281                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
2282                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2283                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2284                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2285                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2286                : * PERFORMANCE OF THIS SOFTWARE.
2287                : */
2288                :
2289                :#ifdef HAVE_DIX_CONFIG_H
2290                :#include <dix-config.h>
2291                :#endif
2292                :
2293                :#include <stdlib.h>
2294                :
2295                :#include "exa_priv.h"
2296                :
2297                :#ifdef RENDER
2298                :#include "mipict.h"
2299                :
2300                :#if DEBUG_TRACE_FALL
2301                :static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n)
2302                :{
2303                :    char format[20];
2304                :    char size[20];
2305                :    char loc;
2306                :    int temp;
2307                :
2308                :    if (!pict) {
2309                :        snprintf(string, n, "None");
2310                :        return;
2311                :    }
2312                :
2313                :    switch (pict->format)
2314                :    {
2315                :    case PICT_a8r8g8b8:
2316                :        snprintf(format, 20, "ARGB8888");
2317                :        break;
2318                :    case PICT_r5g6b5:
2319                :        snprintf(format, 20, "RGB565  ");
2320                :        break;
2321                :    case PICT_x1r5g5b5:
2322                :        snprintf(format, 20, "RGB555  ");
2323                :        break;
2324                :    case PICT_a8:
2325                :        snprintf(format, 20, "A8      ");
2326                :        break;
2327                :    case PICT_a1:
2328                :        snprintf(format, 20, "A1      ");
2329                :        break;
2330                :    default:
2331                :        snprintf(format, 20, "0x%x", (int)pict->format);
2332                :        break;
2333                :    }
2334                :
2335                :    loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
2336                :
2337                :    snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
2338                :             pict->pDrawable->height, pict->repeat ?
2339                :             " R" : "");
2340                :
2341                :    snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, size);
2342                :}
2343                :
2344                :static void
2345                :exaPrintCompositeFallback(CARD8 op,
2346                :                          PicturePtr pSrc,
2347                :                          PicturePtr pMask,
2348                :                          PicturePtr pDst)
2349                :{
2350                :    char sop[20];
2351                :    char srcdesc[40], maskdesc[40], dstdesc[40];
2352                :
2353                :    switch(op)
2354                :    {
2355                :    case PictOpSrc:
2356                :        sprintf(sop, "Src");
2357                :        break;
2358                :    case PictOpOver:
2359                :        sprintf(sop, "Over");
2360                :        break;
2361                :    default:
2362                :        sprintf(sop, "0x%x", (int)op);
2363                :        break;
2364                :    }
2365                :
2366                :    exaCompositeFallbackPictDesc(pSrc, srcdesc, 40);
2367                :    exaCompositeFallbackPictDesc(pMask, maskdesc, 40);
2368                :    exaCompositeFallbackPictDesc(pDst, dstdesc, 40);
2369                :
2370                :    ErrorF("Composite fallback: op %s, \n"
2371                :           "                    src  %s, \n"
2372                :           "                    mask %s, \n"
2373                :           "                    dst  %s, \n",
2374                :           sop, srcdesc, maskdesc, dstdesc);
2375                :}
2376                :#endif /* DEBUG_TRACE_FALL */
2377                :
2378                :static Bool
2379                :exaOpReadsDestination (CARD8 op)
2380      1  0.0011 :{ /* exaOpReadsDestination total:      4  0.0044 */
2381                :    /* FALSE (does not read destination) is the list of ops in the protocol
2382                :     * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
2383                :     * That's just Clear and Src.  ReduceCompositeOp() will already have
2384                :     * converted con/disjoint clear/src to Clear or Src.
2385                :     */
2386      3  0.0033 :    switch (op) {
2387                :    case PictOpClear:
2388                :    case PictOpSrc:
2389                :        return FALSE;
2390                :    default:
2391                :        return TRUE;
2392                :    }
2393                :}
2394                :
2395                :
2396                :static Bool
2397                :exaGetPixelFromRGBA(CARD32      *pixel,
2398                :                    CARD16      red,
2399                :                    CARD16      green,
2400                :                    CARD16      blue,
2401                :                    CARD16      alpha,
2402                :                    CARD32      format)
2403                :{
2404                :    int rbits, bbits, gbits, abits;
2405                :    int rshift, bshift, gshift, ashift;
2406                :
2407                :    *pixel = 0;
2408                :
2409                :    if (!PICT_FORMAT_COLOR(format))
2410                :        return FALSE;
2411                :
2412                :    rbits = PICT_FORMAT_R(format);
2413                :    gbits = PICT_FORMAT_G(format);
2414                :    bbits = PICT_FORMAT_B(format);
2415                :    abits = PICT_FORMAT_A(format);
2416                :
2417                :    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
2418                :        bshift = 0;
2419                :        gshift = bbits;
2420                :        rshift = gshift + gbits;
2421                :        ashift = rshift + rbits;
2422                :    } else {  /* PICT_TYPE_ABGR */
2423                :        rshift = 0;
2424                :        gshift = rbits;
2425                :        bshift = gshift + gbits;
2426                :        ashift = bshift + bbits;
2427                :    }
2428                :
2429                :    *pixel |=  ( blue >> (16 - bbits)) << bshift;
2430                :    *pixel |=  (  red >> (16 - rbits)) << rshift;
2431                :    *pixel |=  (green >> (16 - gbits)) << gshift;
2432                :    *pixel |=  (alpha >> (16 - abits)) << ashift;
2433                :
2434                :    return TRUE;
2435                :}
2436                :
2437                :static Bool
2438                :exaGetRGBAFromPixel(CARD32      pixel,
2439                :                    CARD16      *red,
2440                :                    CARD16      *green,
2441                :                    CARD16      *blue,
2442                :                    CARD16      *alpha,
2443                :                    CARD32      format)
2444                :{
2445                :    int rbits, bbits, gbits, abits;
2446                :    int rshift, bshift, gshift, ashift;
2447                :
2448                :    if (!PICT_FORMAT_COLOR(format))
2449                :        return FALSE;
2450                :
2451                :    rbits = PICT_FORMAT_R(format);
2452                :    gbits = PICT_FORMAT_G(format);
2453                :    bbits = PICT_FORMAT_B(format);
2454                :    abits = PICT_FORMAT_A(format);
2455                :
2456                :    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
2457                :        bshift = 0;
2458                :        gshift = bbits;
2459                :        rshift = gshift + gbits;
2460                :        ashift = rshift + rbits;
2461                :    } else {  /* PICT_TYPE_ABGR */
2462                :        rshift = 0;
2463                :        gshift = rbits;
2464                :        bshift = gshift + gbits;
2465                :        ashift = bshift + bbits;
2466                :    }
2467                :
2468                :    *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
2469                :    while (rbits < 16) {
2470                :        *red |= *red >> rbits;
2471                :        rbits <<= 1;
2472                :    }
2473                :
2474                :    *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
2475                :    while (gbits < 16) {
2476                :        *green |= *green >> gbits;
2477                :        gbits <<= 1;
2478                :    }
2479                :
2480                :    *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
2481                :    while (bbits < 16) {
2482                :        *blue |= *blue >> bbits;
2483                :        bbits <<= 1;
2484                :    }
2485                :
2486                :    if (abits) {
2487                :        *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits);
2488                :        while (abits < 16) {
2489                :            *alpha |= *alpha >> abits;
2490                :            abits <<= 1;
2491                :        }
2492                :    } else
2493                :        *alpha = 0xffff;
2494                :
2495                :    return TRUE;
2496                :}
2497                :
2498                :static int
2499                :exaTryDriverSolidFill(PicturePtr        pSrc,
2500                :                      PicturePtr        pDst,
2501                :                      INT16             xSrc,
2502                :                      INT16             ySrc,
2503                :                      INT16             xDst,
2504                :                      INT16             yDst,
2505                :                      CARD16            width,
2506                :                      CARD16            height)
2507                :{
2508                :    ExaScreenPriv (pDst->pDrawable->pScreen);
2509                :    RegionRec region;
2510                :    BoxPtr pbox;
2511                :    int nbox;
2512                :    int dst_off_x, dst_off_y;
2513                :    PixmapPtr pSrcPix, pDstPix;
2514                :    CARD32 pixel;
2515                :    CARD16 red, green, blue, alpha;
2516                :    ExaMigrationRec pixmaps[1];
2517                :
2518                :    xDst += pDst->pDrawable->x;
2519                :    yDst += pDst->pDrawable->y;
2520                :    xSrc += pSrc->pDrawable->x;
2521                :    ySrc += pSrc->pDrawable->y;
2522                :
2523                :    if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
2524                :                                   xSrc, ySrc, 0, 0, xDst, yDst,
2525                :                                   width, height))
2526                :        return 1;
2527                :
2528                :    pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
2529                :    pixel = exaGetPixmapFirstPixel (pSrcPix);
2530                :
2531                :    pixmaps[0].as_dst = TRUE;
2532                :    pixmaps[0].as_src = FALSE;
2533                :    pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable);
2534                :    exaDoMigration(pixmaps, 1, TRUE);
2535                :
2536                :    pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
2537                :    if (!pDstPix) {
2538                :        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2539                :        return 0;
2540                :    }
2541                :
2542                :    if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha,
2543                :                         pSrc->format))
2544                :    {
2545                :        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2546                :        return -1;
2547                :    }
2548                :
2549                :    if (!exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
2550                :                        pDst->format))
2551                :    {
2552                :        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2553                :        return -1;
2554                :    }
2555                :
2556                :    if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
2557                :    {
2558                :        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2559                :        return -1;
2560                :    }
2561                :
2562                :    nbox = REGION_NUM_RECTS(&region);
2563                :    pbox = REGION_RECTS(&region);
2564                :
2565                :    while (nbox--)
2566                :    {
2567                :        (*pExaScr->info->Solid) (pDstPix,
2568                :                                 pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
2569                :                                 pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
2570                :        pbox++;
2571                :    }
2572                :
2573                :    (*pExaScr->info->DoneSolid) (pDstPix);
2574                :    exaMarkSync(pDst->pDrawable->pScreen);
2575                :
2576                :    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2577                :    return 1;
2578                :}
2579                :
2580                :static int
2581                :exaTryDriverComposite(CARD8             op,
2582                :                      PicturePtr        pSrc,
2583                :                      PicturePtr        pMask,
2584                :                      PicturePtr        pDst,
2585                :                      INT16             xSrc,
2586                :                      INT16             ySrc,
2587                :                      INT16             xMask,
2588                :                      INT16             yMask,
2589                :                      INT16             xDst,
2590                :                      INT16             yDst,
2591                :                      CARD16            width,
2592                :                      CARD16            height)
2593     49  0.0534 :{ /* exaTryDriverComposite total:    348  0.3791 */
2594     23  0.0251 :    ExaScreenPriv (pDst->pDrawable->pScreen);
2595                :    RegionRec region;
2596                :    BoxPtr pbox;
2597                :    int nbox;
2598                :    int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
2599                :    PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
2600                :    struct _Pixmap scratch;
2601                :    ExaMigrationRec pixmaps[3];
2602                :
2603     10  0.0109 :    pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
2604      5  0.0054 :    pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
2605      2  0.0022 :    if (pMask)
2606      2  0.0022 :        pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
2607                :
2608                :    /* Bail if we might exceed coord limits by rendering from/to these.  We
2609                :     * should really be making some scratch pixmaps with offsets and coords
2610                :     * adjusted to deal with this, but it hasn't been done yet.
2611                :     */
2612     24  0.0261 :    if (pSrcPix->drawable.width > pExaScr->info->maxX ||
2613                :        pSrcPix->drawable.height > pExaScr->info->maxY ||
2614                :        pDstPix->drawable.width > pExaScr->info->maxX ||
2615                :        pDstPix->drawable.height > pExaScr->info->maxY || 
2616                :        (pMask && (pMaskPix->drawable.width > pExaScr->info->maxX ||
2617                :                   pMaskPix->drawable.height > pExaScr->info->maxY)))
2618                :    {
2619                :        return -1;
2620                :    }
2621                :
2622     14  0.0153 :    xDst += pDst->pDrawable->x;
2623      2  0.0022 :    yDst += pDst->pDrawable->y;
2624                :
2625                :    if (pMask) {
2626      7  0.0076 :        xMask += pMask->pDrawable->x;
2627     10  0.0109 :        yMask += pMask->pDrawable->y;
2628                :    }
2629                :
2630      9  0.0098 :    xSrc += pSrc->pDrawable->x;
2631      2  0.0022 :    ySrc += pSrc->pDrawable->y;
2632                :
2633     23  0.0251 :    if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
2634                :                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
2635                :                                   width, height))
2636                :        return 1;
2637                :
2638     38  0.0414 :    if (pExaScr->info->CheckComposite &&
2639                :        !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst))
2640                :    {
2641                :        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2642                :        return -1;
2643                :    }
2644                :
2645                :    pixmaps[0].as_dst = TRUE;
2646                :    pixmaps[0].as_src = exaOpReadsDestination(op);
2647      1  0.0011 :    pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable);
2648                :    pixmaps[1].as_dst = FALSE;
2649                :    pixmaps[1].as_src = TRUE;
2650      3  0.0033 :    pixmaps[1].pPix = exaGetDrawablePixmap (pSrc->pDrawable);
2651                :    if (pMask) {
2652                :        pixmaps[2].as_dst = FALSE;
2653                :        pixmaps[2].as_src = TRUE;
2654      6  0.0065 :        pixmaps[2].pPix = exaGetDrawablePixmap (pMask->pDrawable);
2655      2  0.0022 :        exaDoMigration(pixmaps, 3, TRUE);
2656                :    } else {
2657      2  0.0022 :        exaDoMigration(pixmaps, 2, TRUE);
2658                :    }
2659                :
2660      4  0.0044 :    pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
2661                :    if (pMask)
2662      3  0.0033 :        pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x,
2663                :                                          &mask_off_y);
2664      2  0.0022 :    pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
2665                :
2666                :    if (!pDstPix) {
2667                :        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2668                :        return 0;
2669                :    }
2670                :
2671      1  0.0011 :    if (!pSrcPix && (!pMask || pMaskPix) && pExaScr->info->UploadToScratch) {
2672                :        pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
2673                :        if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
2674                :            pSrcPix = &scratch;
2675                :    } else if (pSrcPix && pMask && !pMaskPix && pExaScr->info->UploadToScratch) {
2676                :        pMaskPix = exaGetDrawablePixmap (pMask->pDrawable);
2677                :        if ((*pExaScr->info->UploadToScratch) (pMaskPix, &scratch))
2678                :            pMaskPix = &scratch;
2679                :    }
2680                :
2681      2  0.0022 :    if (!pSrcPix || (pMask && !pMaskPix)) {
2682                :        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2683                :        return 0;
2684                :    }
2685                :
2686      9  0.0098 :    if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
2687                :                                             pMaskPix, pDstPix))
2688                :    {
2689      5  0.0054 :        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2690                :        return -1;
2691                :    }
2692                :
2693      1  0.0011 :    nbox = REGION_NUM_RECTS(&region);
2694                :    pbox = REGION_RECTS(&region);
2695                :
2696                :    xMask -= xDst;
2697     16  0.0174 :    yMask -= yDst;
2698                :
2699                :    xSrc -= xDst;
2700                :    ySrc -= yDst;
2701                :
2702      5  0.0054 :    while (nbox--)
2703                :    {
2704     26  0.0283 :        (*pExaScr->info->Composite) (pDstPix,
2705                :                                     pbox->x1 + xSrc + src_off_x,
2706                :                                     pbox->y1 + ySrc + src_off_y,
2707                :                                     pbox->x1 + xMask + mask_off_x,
2708                :                                     pbox->y1 + yMask + mask_off_y,
2709                :                                     pbox->x1 + dst_off_x,
2710                :                                     pbox->y1 + dst_off_y,
2711                :                                     pbox->x2 - pbox->x1,
2712                :                                     pbox->y2 - pbox->y1);
2713                :        pbox++;
2714                :    }
2715      3  0.0033 :    (*pExaScr->info->DoneComposite) (pDstPix);
2716     12  0.0131 :    exaMarkSync(pDst->pDrawable->pScreen);
2717                :
2718      7  0.0076 :    REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2719                :    return 1;
2720     18  0.0196 :}
2721                :
2722                :/**
2723                : * exaTryMagicTwoPassCompositeHelper implements PictOpOver using two passes of
2724                : * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
2725                : * alpha and limited 1-tmu cards.
2726                : *
2727                : * From http://anholt.livejournal.com/32058.html:
2728                : *
2729                : * The trouble is that component-alpha rendering requires two different sources
2730                : * for blending: one for the source value to the blender, which is the
2731                : * per-channel multiplication of source and mask, and one for the source alpha
2732                : * for multiplying with the destination channels, which is the multiplication
2733                : * of the source channels by the mask alpha. So the equation for Over is:
2734                : *
2735                : * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
2736                : * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
2737                : * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
2738                : * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
2739                : *
2740                : * But we can do some simpler operations, right? How about PictOpOutReverse,
2741                : * which has a source factor of 0 and dest factor of (1 - source alpha). We
2742                : * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
2743                : * blenders pretty easily. So we can do a component-alpha OutReverse, which
2744                : * gets us:
2745                : *
2746                : * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
2747                : * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
2748                : * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
2749                : * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
2750                : *
2751                : * OK. And if an op doesn't use the source alpha value for the destination
2752                : * factor, then we can do the channel multiplication in the texture blenders
2753                : * to get the source value, and ignore the source alpha that we wouldn't use.
2754                : * We've supported this in the Radeon driver for a long time. An example would
2755                : * be PictOpAdd, which does:
2756                : *
2757                : * dst.A = src.A * mask.A + dst.A
2758                : * dst.R = src.R * mask.R + dst.R
2759                : * dst.G = src.G * mask.G + dst.G
2760                : * dst.B = src.B * mask.B + dst.B
2761                : *
2762                : * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
2763                : * after it, we get:
2764                : *
2765                : * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
2766                : * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
2767                : * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
2768                : * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
2769                : */
2770                :
2771                :static int
2772                :exaTryMagicTwoPassCompositeHelper(CARD8 op,
2773                :                                  PicturePtr pSrc,
2774                :                                  PicturePtr pMask,
2775                :                                  PicturePtr pDst,
2776                :                                  INT16 xSrc,
2777                :                                  INT16 ySrc,
2778                :                                  INT16 xMask,
2779                :                                  INT16 yMask,
2780                :                                  INT16 xDst,
2781                :                                  INT16 yDst,
2782                :                                  CARD16 width,
2783                :                                  CARD16 height)
2784                :{
2785                :    ExaScreenPriv (pDst->pDrawable->pScreen);
2786                :    DrawablePtr pDstDraw = pDst->pDrawable;
2787                :    PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDstDraw);
2788                :    int xoff, yoff;
2789                :
2790                :    assert(op == PictOpOver);
2791                :
2792                :    if (pExaScr->info->CheckComposite &&
2793                :        (!(*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
2794                :                                           pDst) ||
2795                :         !(*pExaScr->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))
2796                :    {
2797                :        return -1;
2798                :    }
2799                :
2800                :    /* Now, we think we should be able to accelerate this operation. First,
2801                :     * composite the destination to be the destination times the source alpha
2802                :     * factors.
2803                :     */
2804                :    exaComposite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
2805                :                 xDst, yDst, width, height);
2806                :
2807                :    exaGetDrawableDeltas(pDstDraw, pDstPixmap, &xoff, &yoff);
2808                :    xoff += pDstDraw->x;
2809                :    yoff += pDstDraw->y;
2810                :    exaPixmapDirty(pDstPixmap, xDst + xoff, yDst + yoff, xDst + xoff + width,
2811                :                   yDst + yoff + height);
2812                :
2813                :    /* Then, add in the source value times the destination alpha factors (1.0).
2814                :     */
2815                :    exaComposite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
2816                :                 xDst, yDst, width, height);
2817                :
2818                :    return 1;
2819                :}
2820                :
2821                :void
2822                :exaComposite(CARD8      op,
2823                :             PicturePtr pSrc,
2824                :             PicturePtr pMask,
2825                :             PicturePtr pDst,
2826                :             INT16      xSrc,
2827                :             INT16      ySrc,
2828                :             INT16      xMask,
2829                :             INT16      yMask,
2830                :             INT16      xDst,
2831                :             INT16      yDst,
2832                :             CARD16     width,
2833                :             CARD16     height)
2834     48  0.0523 :{ /* exaComposite total:    354  0.3856 */
2835     39  0.0425 :    ExaScreenPriv (pDst->pDrawable->pScreen);
2836                :    int ret = -1;
2837      5  0.0054 :    Bool saveSrcRepeat = pSrc->repeat;
2838      3  0.0033 :    Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
2839                :    ExaMigrationRec pixmaps[3];
2840                :    int npixmaps = 1;
2841                :    PixmapPtr pSrcPixmap = NULL;
2842                :
2843                :    pixmaps[0].as_dst = TRUE;
2844                :    pixmaps[0].as_src = exaOpReadsDestination(op);
2845      2  0.0022 :    pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable);
2846                :
2847      4  0.0044 :    if (pSrc->pDrawable) {
2848      3  0.0033 :        pSrcPixmap = exaGetDrawablePixmap (pSrc->pDrawable);
2849                :        pixmaps[npixmaps].as_dst = FALSE;
2850                :        pixmaps[npixmaps].as_src = TRUE;
2851                :        pixmaps[npixmaps].pPix = pSrcPixmap;
2852                :        npixmaps++;
2853                :    }
2854                :
2855      1  0.0011 :    if (pMask && pMask->pDrawable) {
2856                :        pixmaps[npixmaps].as_dst = FALSE;
2857                :        pixmaps[npixmaps].as_src = TRUE;
2858                :        pixmaps[npixmaps].pPix = exaGetDrawablePixmap (pMask->pDrawable);
2859                :        npixmaps++;
2860                :    }
2861                :
2862                :    /* We currently don't support acceleration of gradients, or other pictures
2863                :     * with a NULL pDrawable.
2864                :     */
2865     14  0.0153 :    if (pExaScr->swappedOut ||
2866                :        pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL))
2867                :    {
2868                :        goto fallback;
2869                :    }
2870                :
2871                :    /* Remove repeat in source if useless */
2872     18  0.0196 :    if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
2873                :        (xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
2874                :        (ySrc + height) <= pSrc->pDrawable->height)
2875                :            pSrc->repeat = 0;
2876                :
2877      3  0.0033 :    if (!pMask)
2878                :    {
2879      3  0.0033 :      if ((op == PictOpSrc &&
2880                :           ((pSrc->format == pDst->format) ||
2881                :            (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
2882                :            (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
2883                :          (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
2884                :           pSrc->format == pDst->format &&
2885                :           (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))
2886                :        {
2887                :            if (pSrc->pDrawable->width == 1 &&
2888                :                pSrc->pDrawable->height == 1 &&
2889                :                pSrc->repeat)
2890                :            {
2891                :                ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
2892                :                                            width, height);
2893                :                if (ret == 1)
2894                :                    goto done;
2895                :            }
2896                :            else if (pSrcPixmap && !pSrc->repeat && !pSrc->transform)
2897                :            {
2898                :                RegionRec       region;
2899                :
2900                :                xDst += pDst->pDrawable->x;
2901                :                yDst += pDst->pDrawable->y;
2902                :                xSrc += pSrc->pDrawable->x;
2903                :                ySrc += pSrc->pDrawable->y;
2904                :
2905                :                if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
2906                :                                               xSrc, ySrc, xMask, yMask, xDst,
2907                :                                               yDst, width, height))
2908                :                    goto done;
2909                :
2910                :
2911                :                exaCopyNtoN (pSrc->pDrawable, pDst->pDrawable, NULL,
2912                :                             REGION_RECTS(&region), REGION_NUM_RECTS(&region),
2913                :                             xSrc - xDst, ySrc - yDst,
2914                :                             FALSE, FALSE, 0, NULL);
2915                :                REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2916                :                goto done;
2917                :            }
2918                :            else if (pSrcPixmap && !pSrc->transform &&
2919                :                     pSrc->repeatType == RepeatNormal)
2920                :            {
2921                :                RegionRec region;
2922                :                DDXPointRec srcOrg;
2923                :
2924                :                /* Let's see if the driver can do the repeat in one go */
2925                :                if (pExaScr->info->PrepareComposite && !pSrc->alphaMap &&
2926                :                    !pDst->alphaMap)
2927                :                {
2928                :                    ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc,
2929                :                                                ySrc, xMask, yMask, xDst, yDst,
2930                :                                                width, height);
2931                :                    if (ret == 1)
2932                :                        goto done;
2933                :                }
2934                :
2935                :                /* Now see if we can use exaFillRegionTiled() */
2936                :                xDst += pDst->pDrawable->x;
2937                :                yDst += pDst->pDrawable->y;
2938                :                xSrc += pSrc->pDrawable->x;
2939                :                ySrc += pSrc->pDrawable->y;
2940                :
2941                :                if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst, xSrc,
2942                :                                               ySrc, xMask, yMask, xDst, yDst,
2943                :                                               width, height))
2944                :                    goto done;
2945                :
2946                :                srcOrg.x = (xSrc - xDst) % pSrcPixmap->drawable.width;
2947                :                srcOrg.y = (ySrc - yDst) % pSrcPixmap->drawable.height;
2948                :
2949                :                ret = exaFillRegionTiled(pDst->pDrawable, &region, pSrcPixmap,
2950                :                                         &srcOrg, FB_ALLONES, GXcopy);
2951                :
2952                :                REGION_UNINIT(pDst->pDrawable->pScreen, &region);
2953                :
2954                :                if (ret)
2955                :                    goto done;
2956                :            }
2957                :        }
2958                :    }
2959                :
2960                :    /* Remove repeat in mask if useless */
2961     12  0.0131 :    if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 &&
2962                :        (xMask + width) <= pMask->pDrawable->width && yMask >= 0 &&
2963                :        (yMask + height) <= pMask->pDrawable->height)
2964                :            pMask->repeat = 0;
2965                :
2966     37  0.0403 :    if (pExaScr->info->PrepareComposite &&
2967                :        (!pSrc->repeat || pSrc->repeatType == RepeatNormal) &&
2968                :        (!pMask || !pMask->repeat || pMask->repeatType == RepeatNormal) &&
2969                :        !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
2970                :    {
2971                :        Bool isSrcSolid;
2972                :
2973     59  0.0643 :        ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
2974                :                                    yMask, xDst, yDst, width, height);
2975      3  0.0033 :        if (ret == 1)
2976                :            goto done;
2977                :
2978                :        /* For generic masks and solid src pictures, mach64 can do Over in two
2979                :         * passes, similar to the component-alpha case.
2980                :         */
2981      8  0.0087 :        isSrcSolid = pSrc->pDrawable->width == 1 &&
2982                :                     pSrc->pDrawable->height == 1 &&
2983                :                     pSrc->repeat;
2984                :
2985                :        /* If we couldn't do the Composite in a single pass, and it was a
2986                :         * component-alpha Over, see if we can do it in two passes with
2987                :         * an OutReverse and then an Add.
2988                :         */
2989      2  0.0022 :        if (ret == -1 && op == PictOpOver && pMask &&
2990                :            (pMask->componentAlpha || isSrcSolid)) {
2991                :            ret = exaTryMagicTwoPassCompositeHelper(op, pSrc, pMask, pDst,
2992                :                                                    xSrc, ySrc,
2993                :                                                    xMask, yMask, xDst, yDst,
2994                :                                                    width, height);
2995                :            if (ret == 1)
2996                :                goto done;
2997                :        }
2998                :    }
2999                :
3000                :fallback:
3001                :    return;
3002                :#if DEBUG_TRACE_FALL
3003                :    exaPrintCompositeFallback (op, pSrc, pMask, pDst);
3004                :#endif
3005                :
3006                :    exaDoMigration(pixmaps, npixmaps, FALSE);
3007                :    ExaCheckComposite (op, pSrc, pMask, pDst, xSrc, ySrc,
3008                :                      xMask, yMask, xDst, yDst, width, height);
3009                :
3010                :done:
3011     15  0.0163 :    pSrc->repeat = saveSrcRepeat;
3012      3  0.0033 :    if (pMask)
3013     18  0.0196 :        pMask->repeat = saveMaskRepeat;
3014      6  0.0065 :}
3015                :#endif
3016                :
3017                :#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
3018                :
3019                :/**
3020                : * exaRasterizeTrapezoid is just a wrapper around the software implementation.
3021                : *
3022                : * The trapezoid specification is basically too hard to be done in hardware (at
3023                : * the very least, without programmability), so we just do the appropriate
3024                : * Prepare/FinishAccess for it before using fbtrap.c.
3025                : */
3026                :void
3027                :exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid  *trap,
3028                :                       int x_off, int y_off)
3029                :{ /* exaRasterizeTrapezoid total:      2  0.0022 */
3030                :    DrawablePtr pDraw = pPicture->pDrawable;
3031                :    ExaMigrationRec pixmaps[1];
3032                :    int xoff, yoff;
3033                :
3034                :    pixmaps[0].as_dst = TRUE;
3035                :    pixmaps[0].as_src = TRUE;
3036      1  0.0011 :    pixmaps[0].pPix = exaGetDrawablePixmap (pDraw);
3037      1  0.0011 :    exaDoMigration(pixmaps, 1, FALSE);
3038                :
3039                :    exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
3040                :    fbRasterizeTrapezoid(pPicture, trap, x_off, y_off);
3041                :    exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff);
3042                :    exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff,
3043                :                   pDraw->x + xoff + pDraw->width,
3044                :                   pDraw->y + yoff + pDraw->height);
3045                :    exaFinishAccess(pDraw, EXA_PREPARE_DEST);
3046                :}
3047                :
3048                :/**
3049                : * exaAddTriangles does migration and syncing before dumping down to the
3050                : * software implementation.
3051                : */
3052                :void
3053                :exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri,
3054                :                 xTriangle *tris)
3055                :{
3056                :    DrawablePtr pDraw = pPicture->pDrawable;
3057                :    ExaMigrationRec pixmaps[1];
3058                :    int xoff, yoff;
3059                :
3060                :    pixmaps[0].as_dst = TRUE;
3061                :    pixmaps[0].as_src = TRUE;
3062                :    pixmaps[0].pPix = exaGetDrawablePixmap (pDraw);
3063                :    exaDoMigration(pixmaps, 1, FALSE);
3064                :
3065                :    exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
3066                :    fbAddTriangles(pPicture, x_off, y_off, ntri, tris);
3067                :    exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff);
3068                :    exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff,
3069                :                   pDraw->x + xoff + pDraw->width,
3070                :                   pDraw->y + yoff + pDraw->height);
3071                :    exaFinishAccess(pDraw, EXA_PREPARE_DEST);
3072                :}
3073                :
3074                :/**
3075                : * Returns TRUE if the glyphs in the lists intersect.  Only checks based on
3076                : * bounding box, which appears to be good enough to catch most cases at least.
3077                : */
3078                :static Bool
3079                :exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs)
3080                :{
3081                :    int x1, x2, y1, y2;
3082                :    int n;
3083                :    GlyphPtr glyph;
3084                :    int x, y;
3085                :    BoxRec extents;
3086                :    Bool first = TRUE;
3087                :    
3088                :    x = 0;
3089                :    y = 0;
3090                :    while (nlist--) {
3091                :        x += list->xOff;
3092                :        y += list->yOff;
3093                :        n = list->len;
3094                :        list++;
3095                :        while (n--) {
3096                :            glyph = *glyphs++;
3097                :
3098                :            if (glyph->info.width == 0 || glyph->info.height == 0) {
3099                :                x += glyph->info.xOff;
3100                :                y += glyph->info.yOff;
3101                :                continue;
3102                :            }
3103                :
3104                :            x1 = x - glyph->info.x;
3105                :            if (x1 < MINSHORT)
3106                :                x1 = MINSHORT;
3107                :            y1 = y - glyph->info.y;
3108                :            if (y1 < MINSHORT)
3109                :                y1 = MINSHORT;
3110                :            x2 = x1 + glyph->info.width;
3111                :            if (x2 > MAXSHORT)
3112                :                x2 = MAXSHORT;
3113                :            y2 = y1 + glyph->info.height;
3114                :            if (y2 > MAXSHORT)
3115                :                y2 = MAXSHORT;
3116                :
3117                :            if (first) {
3118                :                extents.x1 = x1;
3119                :                extents.y1 = y1;
3120                :                extents.x2 = x2;
3121                :                extents.y2 = y2;
3122                :                first = FALSE;
3123                :            } else {
3124                :                if (x1 < extents.x2 && x2 > extents.x1 &&
3125                :                    y1 < extents.y2 && y2 > extents.y1)
3126                :                {
3127                :                    return TRUE;
3128                :                }
3129                :
3130                :                if (x1 < extents.x1)
3131                :                    extents.x1 = x1;
3132                :                if (x2 > extents.x2)
3133                :                    extents.x2 = x2;
3134                :                if (y1 < extents.y1)
3135                :                    extents.y1 = y1;
3136                :                if (y2 > extents.y2)
3137                :                    extents.y2 = y2;
3138                :            }
3139                :            x += glyph->info.xOff;
3140                :            y += glyph->info.yOff;
3141                :        }
3142                :    }
3143                :
3144                :    return FALSE;
3145                :}
3146                :
3147                :/* exaGlyphs is a slight variation on miGlyphs, to support acceleration.  The
3148                : * issue is that miGlyphs' use of ModifyPixmapHeader makes it impossible to
3149                : * migrate these pixmaps.  So, instead we create a pixmap at the beginning of
3150                : * the loop and upload each glyph into the pixmap before compositing.
3151                : */
3152                :void
3153                :exaGlyphs (CARD8        op,
3154                :          PicturePtr    pSrc,
3155                :          PicturePtr    pDst,
3156                :          PictFormatPtr maskFormat,
3157                :          INT16         xSrc,
3158                :          INT16         ySrc,
3159                :          int           nlist,
3160                :          GlyphListPtr  list,
3161                :          GlyphPtr      *glyphs)
3162      1  0.0011 :{ /* exaGlyphs total:    185  0.2015 */
3163                :    ExaScreenPriv (pDst->pDrawable->pScreen);
3164                :    PixmapPtr   pPixmap = NULL;
3165                :    PicturePtr  pPicture;
3166                :    PixmapPtr   pMaskPixmap = NULL;
3167      1  0.0011 :    PixmapPtr   pDstPixmap = exaGetDrawablePixmap(pDst->pDrawable);
3168                :    PicturePtr  pMask;
3169                :    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
3170                :    int         width = 0, height = 0;
3171                :    int         x, y, x1, y1, xoff, yoff;
3172      1  0.0011 :    int         xDst = list->xOff, yDst = list->yOff;
3173                :    int         n;
3174                :    int         error;
3175                :    BoxRec      extents;
3176                :    CARD32      component_alpha;
3177                :
3178                :    /* If we have a mask format but it's the same as all the glyphs and
3179                :     * the glyphs don't intersect, we can avoid accumulating the glyphs in the
3180                :     * temporary picture.
3181                :     */
3182                :    if (maskFormat != NULL) {
3183                :        Bool sameFormat = TRUE;
3184                :        int i;
3185                :
3186      1  0.0011 :        for (i = 0; i < nlist; i++) {
3187                :            if (maskFormat->format != list[i].format->format) {
3188                :                sameFormat = FALSE;
3189                :                break;
3190                :            }
3191                :        }
3192                :        if (sameFormat) {
3193                :            if (!exaGlyphsIntersect(nlist, list, glyphs)) {
3194                :                maskFormat = NULL;
3195                :            }
3196                :        }
3197                :    }
3198                :
3199                :    /* If the driver doesn't support accelerated composite, there's no point in
3200                :     * going to this extra work.  Assume that any driver that supports Composite
3201                :     * will be able to support component alpha using the two-pass helper.
3202                :     */
3203                :    if (!pExaScr->info->PrepareComposite)
3204                :    {
3205                :        miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
3206                :        return;
3207                :    }
3208                :
3209                :    if (maskFormat)
3210                :    {
3211                :        GCPtr       pGC;
3212                :        xRectangle  rect;
3213                :        
3214      1  0.0011 :        miGlyphExtents (nlist, list, glyphs, &extents);
3215                :
3216                :        extents.x1 = max(extents.x1, 0);
3217                :        extents.y1 = max(extents.y1, 0);
3218                :        extents.x2 = min(extents.x2, pDst->pDrawable->width);
3219      1  0.0011 :        extents.y2 = min(extents.y2, pDst->pDrawable->height);
3220                :
3221                :        if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
3222                :            return;
3223                :        width = extents.x2 - extents.x1;
3224                :        height = extents.y2 - extents.y1;
3225                :        pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
3226                :                                                maskFormat->depth);
3227                :        if (!pMaskPixmap)
3228                :            return;
3229                :        component_alpha = NeedsComponent(maskFormat->format);
3230      1  0.0011 :        pMask = CreatePicture (0, &pMaskPixmap->drawable,
3231                :                               maskFormat, CPComponentAlpha, &component_alpha,
3232                :                               serverClient, &error);
3233                :        if (!pMask)
3234                :        {
3235                :            (*pScreen->DestroyPixmap) (pMaskPixmap);
3236                :            return;
3237                :        }
3238                :        ValidatePicture(pMask);
3239                :        pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
3240                :        ValidateGC (&pMaskPixmap->drawable, pGC);
3241                :        rect.x = 0;
3242                :        rect.y = 0;
3243                :        rect.width = width;
3244                :        rect.height = height;
3245      1  0.0011 :        (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
3246                :        exaPixmapDirty(pMaskPixmap, 0, 0, width, height);
3247                :        FreeScratchGC (pGC);
3248                :        x = -extents.x1;
3249                :        y = -extents.y1;
3250                :    }
3251                :    else
3252                :    {
3253                :        pMask = pDst;
3254                :        x = 0;
3255                :        y = 0;
3256                :    }
3257                :
3258                :    exaGetDrawableDeltas(pDst->pDrawable, pDstPixmap, &xoff, &yoff);
3259                :
3260                :    while (nlist--)
3261                :    {
3262                :        GCPtr pGC = NULL;
3263                :        int maxwidth = 0, maxheight = 0, i;
3264                :        ExaMigrationRec pixmaps[1];
3265                :        PixmapPtr pScratchPixmap = NULL;
3266                :
3267                :        x += list->xOff;
3268                :        y += list->yOff;
3269                :        n = list->len;
3270                :        for (i = 0; i < n; i++) {
3271     14  0.0153 :            if (glyphs[i]->info.width > maxwidth)
3272                :                maxwidth = glyphs[i]->info.width;
3273                :            if (glyphs[i]->info.height > maxheight)
3274                :                maxheight = glyphs[i]->info.height;
3275                :        }
3276      1  0.0011 :        if (maxwidth == 0 || maxheight == 0) {
3277                :            while (n--)
3278                :            {
3279                :                GlyphPtr glyph;
3280                :
3281                :                glyph = *glyphs++;
3282                :                x += glyph->info.xOff;
3283                :                y += glyph->info.yOff;
3284                :            }
3285                :            list++;
3286                :            continue;
3287                :        }
3288                :
3289                :        /* Create the (real) temporary pixmap to store the current glyph in */
3290      1  0.0011 :        pPixmap = (*pScreen->CreatePixmap) (pScreen, maxwidth, maxheight,
3291                :                                            list->format->depth);
3292                :        if (!pPixmap)
3293                :            return;
3294                :
3295                :        /* Create a temporary picture to wrap the temporary pixmap, so it can be
3296                :         * used as a source for Composite.
3297                :         */
3298                :        component_alpha = NeedsComponent(list->format->format);
3299                :        pPicture = CreatePicture (0, &pPixmap->drawable, list->format,
3300                :                                  CPComponentAlpha, &component_alpha, 
3301                :                                  serverClient, &error);
3302                :        if (!pPicture) {
3303                :            (*pScreen->DestroyPixmap) (pPixmap);
3304                :            return;
3305                :        }
3306                :        ValidatePicture(pPicture);
3307                :
3308                :        /* Give the temporary pixmap an initial kick towards the screen, so
3309                :         * it'll stick there.
3310                :         */
3311                :        pixmaps[0].as_dst = TRUE;
3312                :        pixmaps[0].as_src = TRUE;
3313                :        pixmaps[0].pPix = pPixmap;
3314                :        exaDoMigration (pixmaps, 1, pExaScr->info->PrepareComposite != NULL);
3315                :
3316      1  0.0011 :        while (n--)
3317                :        {
3318      1  0.0011 :            GlyphPtr glyph = *glyphs++;
3319                :            pointer glyphdata = (pointer) (glyph + 1);
3320      5  0.0054 :            DrawablePtr pCmpDrw = (maskFormat ? pMask : pDst)->pDrawable;
3321                :
3322                :            x1 = x - glyph->info.x;
3323      8  0.0087 :            y1 = y - glyph->info.y;
3324                :
3325      7  0.0076 :            if (x1 >= pCmpDrw->width || y1 >= pCmpDrw->height ||
3326                :                (x1 + glyph->info.width) <= 0 || (y1 + glyph->info.height) <= 0)
3327                :                goto nextglyph;
3328                :
3329      2  0.0022 :            (*pScreen->ModifyPixmapHeader) (pScratchPixmap, 
3330                :                                            glyph->info.width,
3331                :                                            glyph->info.height,
3332                :                                            0, 0, -1, glyphdata);
3333                :
3334                :            /* Copy the glyph data into the proper pixmap instead of a fake.
3335                :             * First we try to use UploadToScreen, if we can, then we fall back
3336                :             * to a plain exaCopyArea in case of failure.
3337                :             */
3338      5  0.0054 :            if (pExaScr->info->UploadToScreen &&
3339                :                exaPixmapIsOffscreen(pPixmap) &&
3340                :                (*pExaScr->info->UploadToScreen) (pPixmap, 0, 0,
3341                :                                        glyph->info.width,
3342                :                                        glyph->info.height,
3343                :                                        glyphdata,
3344                :                                        PixmapBytePad(glyph->info.width,
3345                :                                                      list->format->depth)))
3346                :            {
3347                :                exaMarkSync (pScreen);
3348                :            } else {
3349                :                /* Set up the scratch pixmap/GC for doing a CopyArea. */
3350                :                if (pScratchPixmap == NULL) {
3351                :                    /* Get a scratch pixmap to wrap the original glyph data */
3352      2  0.0022 :                    pScratchPixmap = GetScratchPixmapHeader (pScreen,
3353                :                                                        glyph->info.width,
3354                :                                                        glyph->info.height, 
3355                :                                                        list->format->depth,
3356                :                                                        list->format->depth, 
3357                :                                                        -1, glyphdata);
3358                :                    if (!pScratchPixmap) {
3359                :                        FreePicture(pPicture, 0);
3360                :                        (*pScreen->DestroyPixmap) (pPixmap);
3361                :                        return;
3362                :                    }
3363                :        
3364                :                    /* Get a scratch GC with which to copy the glyph data from
3365                :                     * scratch to temporary
3366                :                     */
3367                :                    pGC = GetScratchGC (list->format->depth, pScreen);
3368      1  0.0011 :                    ValidateGC (&pPixmap->drawable, pGC);
3369                :                } else {
3370      2  0.0022 :                    (*pScreen->ModifyPixmapHeader) (pScratchPixmap, 
3371                :                                                    glyph->info.width,
3372                :                                                    glyph->info.height,
3373                :                                                    0, 0, -1, glyphdata);
3374      5  0.0054 :                    pScratchPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
3375                :                }
3376                :
3377      7  0.0076 :                exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC,
3378                :                             0, 0, glyph->info.width, glyph->info.height, 0, 0);
3379                :            }
3380                :
3381      5  0.0054 :            exaPixmapDirty (pPixmap, 0, 0,
3382                :                            glyph->info.width, glyph->info.height);
3383                :
3384      5  0.0054 :            if (maskFormat)
3385                :            {
3386      4  0.0044 :                exaComposite (PictOpAdd, pPicture, NULL, pMask, 0, 0, 0, 0,
3387                :                              x1, y1, glyph->info.width, glyph->info.height);
3388      2  0.0022 :                exaPixmapDirty(pMaskPixmap, x1, y1, x1 + glyph->info.width,
3389                :                               y1 + glyph->info.height);
3390                :            }
3391                :            else
3392                :            {
3393     13  0.0142 :                exaComposite (op, pSrc, pPicture, pDst,
3394                :                              xSrc + x1 - xDst, ySrc + y1 - yDst,
3395                :                              0, 0, x1, y1, glyph->info.width,
3396                :                              glyph->info.height);
3397     11  0.0120 :                x1 += pDst->pDrawable->x + xoff;
3398      5  0.0054 :                y1 += pDst->pDrawable->y + yoff;
3399      3  0.0033 :                exaPixmapDirty(pDstPixmap, x1, y1, x1 + glyph->info.width,
3400                :                               y1 + glyph->info.height);
3401                :            }
3402                :nextglyph:
3403      3  0.0033 :            x += glyph->info.xOff;
3404      2  0.0022 :            y += glyph->info.yOff;
3405                :        }
3406                :        list++;
3407                :        if (pGC != NULL)
3408                :            FreeScratchGC (pGC);
3409      1  0.0011 :        FreePicture ((pointer) pPicture, 0);
3410                :        (*pScreen->DestroyPixmap) (pPixmap);
3411                :        if (pScratchPixmap != NULL)
3412                :            FreeScratchPixmapHeader (pScratchPixmap);
3413                :    }
3414                :    if (maskFormat)
3415                :    {
3416                :        x = extents.x1;
3417                :        y = extents.y1;
3418      1  0.0011 :        exaComposite (op, pSrc, pMask, pDst, xSrc + x - xDst, ySrc + y - yDst,
3419                :                      0, 0, x, y, width, height);
3420                :        FreePicture ((pointer) pMask, (XID) 0);
3421                :        (*pScreen->DestroyPixmap) (pMaskPixmap);
3422                :    }
3423                :}
3424 /* 
3425  * Total samples for file : "interp.c"
3426  * 
3427  *    753  0.8203
3428  */
3429
3430 <credited to line zero>    753  0.8203 :
3431  /* __i686.get_pc_thunk.cx total:      1  0.0011 */
3432  /* __i686.get_pc_thunk.bx total:     44  0.0479 */
3433  /* _nl_load_locale_from_archive total:      1  0.0011 */
3434  /* _itoa_word total:      1  0.0011 */
3435  /* __find_specmb total:      2  0.0022 */
3436  /* _IO_old_init total:      1  0.0011 */
3437  /* _IO_str_init_static_internal total:      1  0.0011 */
3438  /* _int_free total:    227  0.2473 */
3439  /* _int_malloc total:    460  0.5011 */
3440  /* _int_realloc total:     10  0.0109 */
3441  /* __close_nocancel total:      1  0.0011 */
3442  /* __read_nocancel total:      3  0.0033 */
3443  /* __xstat32_conv total:      1  0.0011 */
3444 /* 
3445  * Total samples for file : "exa_unaccel.c"
3446  * 
3447  *    590  0.6427
3448  */
3449
3450 <credited to line zero>    590  0.6427 :
3451  /* __i686.get_pc_thunk.cx total:     14  0.0153 */
3452  /* __i686.get_pc_thunk.bx total:    576  0.6275 */
3453 /* 
3454  * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa_offscreen.c"
3455  * 
3456  *    534  0.5817
3457  */
3458
3459
3460                :/*
3461                : * Copyright Â© 2003 Anders Carlsson
3462                : *
3463                : * Permission to use, copy, modify, distribute, and sell this software and its
3464                : * documentation for any purpose is hereby granted without fee, provided that
3465                : * the above copyright notice appear in all copies and that both that
3466                : * copyright notice and this permission notice appear in supporting
3467                : * documentation, and that the name of Anders Carlsson not be used in
3468                : * advertising or publicity pertaining to distribution of the software without
3469                : * specific, written prior permission.  Anders Carlsson makes no
3470                : * representations about the suitability of this software for any purpose.  It
3471                : * is provided "as is" without express or implied warranty.
3472                : *
3473                : * ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3474                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
3475                : * EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3476                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
3477                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
3478                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
3479                : * PERFORMANCE OF THIS SOFTWARE.
3480                : */
3481                :
3482                :/** @file
3483                : * This allocator allocates blocks of memory by maintaining a list of areas
3484                : * and a score for each area.  As an area is marked used, its score is
3485                : * incremented, and periodically all of the areas have their scores decayed by
3486                : * a fraction.  When allocating, the contiguous block of areas with the minimum
3487                : * score is found and evicted in order to make room for the new allocation.
3488                : */
3489                :
3490                :#include "exa_priv.h"
3491                :
3492                :#include <limits.h>
3493                :#include <assert.h>
3494                :#include <stdlib.h>
3495                :
3496                :#if DEBUG_OFFSCREEN
3497                :#define DBG_OFFSCREEN(a) ErrorF a
3498                :#else
3499                :#define DBG_OFFSCREEN(a)
3500                :#endif
3501                :
3502                :#if DEBUG_OFFSCREEN
3503                :static void
3504                :ExaOffscreenValidate (ScreenPtr pScreen)
3505                :{
3506                :    ExaScreenPriv (pScreen);
3507                :    ExaOffscreenArea *prev = 0, *area;
3508                :
3509                :    assert (pExaScr->info->offScreenAreas->base_offset == 
3510                :            pExaScr->info->offScreenBase);
3511                :    for (area = pExaScr->info->offScreenAreas; area; area = area->next)
3512                :    {
3513                :        assert (area->offset >= area->base_offset &&
3514                :                area->offset < (area->base_offset + area->size));
3515                :        if (prev)
3516                :            assert (prev->base_offset + prev->size == area->base_offset);
3517                :        prev = area;
3518                :    }
3519                :    assert (prev->base_offset + prev->size == pExaScr->info->memorySize);
3520                :}
3521                :#else
3522                :#define ExaOffscreenValidate(s)
3523                :#endif
3524                :
3525                :static ExaOffscreenArea *
3526                :ExaOffscreenKickOut (ScreenPtr pScreen, ExaOffscreenArea *area)
3527                :{
3528                :    if (area->save)
3529                :        (*area->save) (pScreen, area);
3530                :    return exaOffscreenFree (pScreen, area);
3531                :}
3532                :
3533                :/**
3534                : * exaOffscreenAlloc allocates offscreen memory
3535                : *
3536                : * @param pScreen current screen
3537                : * @param size size in bytes of the allocation
3538                : * @param align byte alignment requirement for the offset of the allocated area
3539                : * @param locked whether the allocated area is locked and can't be kicked out
3540                : * @param save callback for when the area is evicted from memory
3541                : * @param privdata private data for the save callback.
3542                : *
3543                : * Allocates offscreen memory from the device associated with pScreen.  size
3544                : * and align deteremine where and how large the allocated area is, and locked
3545                : * will mark whether it should be held in card memory.  privdata may be any
3546                : * pointer for the save callback when the area is removed.
3547                : *
3548                : * Note that locked areas do get evicted on VT switch unless the driver
3549                : * requested version 2.1 or newer behavior.  In that case, the save callback is
3550                : * still called.
3551                : */
3552                :ExaOffscreenArea *
3553                :exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
3554                :                   Bool locked,
3555                :                   ExaOffscreenSaveProc save,
3556                :                   pointer privData)
3557      2  0.0022 :{ /* exaOffscreenAlloc total:     68  0.0741 */
3558                :    ExaOffscreenArea *area, *begin, *best;
3559      1  0.0011 :    ExaScreenPriv (pScreen);
3560                :    int tmp, real_size = 0, best_score;
3561                :#if DEBUG_OFFSCREEN
3562                :    static int number = 0;
3563                :    ErrorF("================= ============ allocating a new pixmap %d\n", ++number);
3564                :#endif
3565                :
3566                :    ExaOffscreenValidate (pScreen);
3567      1  0.0011 :    if (!align)
3568                :        align = 1;
3569                :
3570                :    if (!size)
3571                :    {
3572                :        DBG_OFFSCREEN (("Alloc 0x%x -> EMPTY\n", size));
3573                :        return NULL;
3574                :    }
3575                :
3576                :    /* throw out requests that cannot fit */
3577      2  0.0022 :    if (size > (pExaScr->info->memorySize - pExaScr->info->offScreenBase))
3578                :    {
3579                :        DBG_OFFSCREEN (("Alloc 0x%x vs (0x%lx) -> TOBIG\n", size,
3580                :                        pExaScr->info->memorySize -
3581                :                        pExaScr->info->offScreenBase));
3582                :        return NULL;
3583                :    }
3584                :
3585                :    /* Try to find a free space that'll fit. */
3586     11  0.0120 :    for (area = pExaScr->info->offScreenAreas; area; area = area->next)
3587                :    {
3588                :        /* skip allocated areas */
3589     11  0.0120 :        if (area->state != ExaOffscreenAvail)
3590                :            continue;
3591                :
3592                :        /* adjust size to match alignment requirement */
3593                :        real_size = size;
3594      2  0.0022 :        tmp = area->base_offset % align;
3595     31  0.0338 :        if (tmp)
3596                :            real_size += (align - tmp);
3597                :
3598                :        /* does it fit? */
3599                :        if (real_size <= area->size)
3600                :            break;
3601                :    }
3602                :
3603                :    if (!area)
3604                :    {
3605                :        /*
3606                :         * Kick out existing users to make space.
3607                :         *
3608                :         * First, locate a region which can hold the desired object.
3609                :         */
3610                :
3611                :        /* prev points at the first object to boot */
3612                :        best = NULL;
3613                :        best_score = INT_MAX;
3614                :        for (begin = pExaScr->info->offScreenAreas; begin != NULL;
3615                :             begin = begin->next)
3616                :        {
3617                :            int avail, score;
3618                :            ExaOffscreenArea *scan;
3619                :
3620                :            if (begin->state == ExaOffscreenLocked)
3621                :                continue;
3622                :
3623                :            /* adjust size needed to account for alignment loss for this area */
3624                :            real_size = size;
3625                :            tmp = begin->base_offset % align;
3626                :            if (tmp)
3627                :                real_size += (align - tmp);
3628                :
3629                :            avail = 0;
3630                :            score = 0;
3631                :            /* now see if we can make room here, and how "costly" it'll be. */
3632                :            for (scan = begin; scan != NULL; scan = scan->next)
3633                :            {
3634                :                if (scan->state == ExaOffscreenLocked) {
3635                :                    /* Can't make room here, start after this locked area. */
3636                :                    begin = scan;
3637                :                    break;
3638                :                }
3639                :                /* Score should only be non-zero for ExaOffscreenRemovable */
3640                :                score += scan->score;
3641                :                avail += scan->size;
3642                :                if (avail >= real_size)
3643                :                    break;
3644                :            }
3645                :            /* Is it the best option we've found so far? */
3646                :            if (avail >= real_size && score < best_score) {
3647                :                best = begin;
3648                :                best_score = score;
3649                :            }
3650                :        }
3651                :        area = best;
3652                :        if (!area)
3653                :        {
3654                :            DBG_OFFSCREEN (("Alloc 0x%x -> NOSPACE\n", size));
3655                :            /* Could not allocate memory */
3656                :            ExaOffscreenValidate (pScreen);
3657                :            return NULL;
3658                :        }
3659                :
3660                :        /* adjust size needed to account for alignment loss for this area */
3661                :        real_size = size;
3662                :        tmp = area->base_offset % align;
3663                :        if (tmp)
3664                :            real_size += (align - tmp);
3665                :
3666                :        /*
3667                :         * Kick out first area if in use
3668                :         */
3669                :        if (area->state != ExaOffscreenAvail)
3670                :            area = ExaOffscreenKickOut (pScreen, area);
3671                :        /*
3672                :         * Now get the system to merge the other needed areas together
3673                :         */
3674                :        while (area->size < real_size)
3675                :        {
3676                :            assert (area->next && area->next->state == ExaOffscreenRemovable);
3677                :            (void) ExaOffscreenKickOut (pScreen, area->next);
3678                :        }
3679                :    }
3680                :
3681                :    /* save extra space in new area */
3682      1  0.0011 :    if (real_size < area->size)
3683                :    {
3684                :        ExaOffscreenArea   *new_area = xalloc (sizeof (ExaOffscreenArea));
3685                :        if (!new_area)
3686                :            return NULL;
3687                :        new_area->base_offset = area->base_offset + real_size;
3688                :        new_area->offset = new_area->base_offset;
3689                :        new_area->size = area->size - real_size;
3690                :        new_area->state = ExaOffscreenAvail;
3691                :        new_area->save = NULL;
3692                :        new_area->score = 0;
3693                :        new_area->next = area->next;
3694      1  0.0011 :        area->next = new_area;
3695                :        area->size = real_size;
3696                :    }
3697                :    /*
3698                :     * Mark this area as in use
3699                :     */
3700                :    if (locked)
3701                :        area->state = ExaOffscreenLocked;
3702                :    else
3703                :        area->state = ExaOffscreenRemovable;
3704                :    area->privData = privData;
3705                :    area->save = save;
3706                :    area->score = 0;
3707                :    area->offset = (area->base_offset + align - 1);
3708      5  0.0054 :    area->offset -= area->offset % align;
3709                :
3710                :    ExaOffscreenValidate (pScreen);
3711                :
3712                :    DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x (0x%x)\n", size,
3713                :                    area->base_offset, area->offset));
3714                :    return area;
3715                :}
3716                :
3717                :/**
3718                : * Ejects all offscreen areas, and uninitializes the offscreen memory manager.
3719                : */
3720                :void
3721                :ExaOffscreenSwapOut (ScreenPtr pScreen)
3722                :{
3723                :    ExaScreenPriv (pScreen);
3724                :
3725                :    ExaOffscreenValidate (pScreen);
3726                :    /* loop until a single free area spans the space */
3727                :    for (;;)
3728                :    {
3729                :        ExaOffscreenArea *area = pExaScr->info->offScreenAreas;
3730                :
3731                :        if (!area)
3732                :            break;
3733                :        if (area->state == ExaOffscreenAvail)
3734                :        {
3735                :            area = area->next;
3736                :            if (!area)
3737                :                break;
3738                :        }
3739                :        assert (area->state != ExaOffscreenAvail);
3740                :        (void) ExaOffscreenKickOut (pScreen, area);
3741                :        ExaOffscreenValidate (pScreen);
3742                :    }
3743                :    ExaOffscreenValidate (pScreen);
3744                :    ExaOffscreenFini (pScreen);
3745                :}
3746                :
3747                :/** Ejects all pixmaps managed by EXA. */
3748                :static void
3749                :ExaOffscreenEjectPixmaps (ScreenPtr pScreen)
3750                :{
3751                :    ExaScreenPriv (pScreen);
3752                :
3753                :    ExaOffscreenValidate (pScreen);
3754                :    /* loop until a single free area spans the space */
3755                :    for (;;)
3756                :    {
3757                :        ExaOffscreenArea *area;
3758                :
3759                :        for (area = pExaScr->info->offScreenAreas; area != NULL;
3760                :             area = area->next)
3761                :        {
3762                :            if (area->state == ExaOffscreenRemovable &&
3763                :                area->save == exaPixmapSave)
3764                :            {
3765                :                (void) ExaOffscreenKickOut (pScreen, area);
3766                :                ExaOffscreenValidate (pScreen);
3767                :                break;
3768                :            }
3769                :        }
3770                :        if (area == NULL)
3771                :            break;
3772                :    }
3773                :    ExaOffscreenValidate (pScreen);
3774                :}
3775                :
3776                :void
3777                :ExaOffscreenSwapIn (ScreenPtr pScreen)
3778                :{
3779                :    exaOffscreenInit (pScreen);
3780                :}
3781                :
3782                :/**
3783                : * Prepares EXA for disabling of FB access, or restoring it.
3784                : *
3785                : * In version 2.1, the disabling results in pixmaps being ejected, while other
3786                : * allocations remain.  With this plus the prevention of migration while
3787                : * swappedOut is set, EXA by itself should not cause any access of the
3788                : * framebuffer to occur while swapped out.  Any remaining issues are the
3789                : * responsibility of the driver.
3790                : *
3791                : * Prior to version 2.1, all allocations, including locked ones, are ejected
3792                : * when access is disabled, and the allocator is torn down while swappedOut
3793                : * is set.  This is more drastic, and caused implementation difficulties for
3794                : * many drivers that could otherwise handle the lack of FB access while
3795                : * swapped out.
3796                : */
3797                :void
3798                :exaEnableDisableFBAccess (int index, Bool enable)
3799                :{
3800                :    ScreenPtr pScreen = screenInfo.screens[index];
3801                :    ExaScreenPriv (pScreen);
3802                :
3803                :    if (!enable && pExaScr->disableFbCount++ == 0) {
3804                :        if (pExaScr->info->exa_minor < 1)
3805                :            ExaOffscreenSwapOut (pScreen);
3806                :        else
3807                :            ExaOffscreenEjectPixmaps (pScreen);
3808                :        pExaScr->swappedOut = TRUE;
3809                :    }
3810                :    
3811                :    if (enable && --pExaScr->disableFbCount == 0) {
3812                :        if (pExaScr->info->exa_minor < 1)
3813                :            ExaOffscreenSwapIn (pScreen);
3814                :        pExaScr->swappedOut = FALSE;
3815                :    }
3816                :}
3817                :
3818                :/* merge the next free area into this one */
3819                :static void
3820                :ExaOffscreenMerge (ExaOffscreenArea *area)
3821      1  0.0011 :{ /* ExaOffscreenMerge total:      3  0.0033 */
3822                :    ExaOffscreenArea    *next = area->next;
3823                :
3824                :    /* account for space */
3825                :    area->size += next->size;
3826                :    /* frob pointer */
3827      1  0.0011 :    area->next = next->next;
3828                :    xfree (next);
3829      1  0.0011 :}
3830                :
3831                :/**
3832                : * exaOffscreenFree frees an allocation.
3833                : *
3834                : * @param pScreen current screen
3835                : * @param area offscreen area to free
3836                : *
3837                : * exaOffscreenFree frees an allocation created by exaOffscreenAlloc.  Note that
3838                : * the save callback of the area is not called, and it is up to the driver to
3839                : * do any cleanup necessary as a result.
3840                : *
3841                : * @return pointer to the newly freed area. This behavior should not be relied
3842                : * on.
3843                : */
3844                :ExaOffscreenArea *
3845                :exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area)
3846                :{ /* exaOffscreenFree total:     11  0.0120 */
3847                :    ExaScreenPriv(pScreen);
3848                :    ExaOffscreenArea    *next = area->next;
3849                :    ExaOffscreenArea    *prev;
3850                :
3851                :    DBG_OFFSCREEN (("Free 0x%x -> 0x%x (0x%x)\n", area->size,
3852                :                    area->base_offset, area->offset));
3853                :    ExaOffscreenValidate (pScreen);
3854                :
3855                :    area->state = ExaOffscreenAvail;
3856                :    area->save = NULL;
3857                :    area->score = 0;
3858                :    /*
3859                :     * Find previous area
3860                :     */
3861                :    if (area == pExaScr->info->offScreenAreas)
3862                :        prev = NULL;
3863                :    else
3864      2  0.0022 :        for (prev = pExaScr->info->offScreenAreas; prev; prev = prev->next)
3865      8  0.0087 :            if (prev->next == area)
3866                :                break;
3867                :
3868                :    /* link with next area if free */
3869                :    if (next && next->state == ExaOffscreenAvail)
3870      1  0.0011 :        ExaOffscreenMerge (area);
3871                :
3872                :    /* link with prev area if free */
3873                :    if (prev && prev->state == ExaOffscreenAvail)
3874                :    {
3875                :        area = prev;
3876                :        ExaOffscreenMerge (area);
3877                :    }
3878                :
3879                :    ExaOffscreenValidate (pScreen);
3880                :    DBG_OFFSCREEN(("\tdone freeing\n"));
3881                :    return area;
3882                :}
3883                :
3884                :void
3885                :ExaOffscreenMarkUsed (PixmapPtr pPixmap)
3886     11  0.0120 :{ /* ExaOffscreenMarkUsed total:    452  0.4924 */
3887      4  0.0044 :    ExaPixmapPriv (pPixmap);
3888     17  0.0185 :    ExaScreenPriv (pPixmap->drawable.pScreen);
3889                :    static int iter = 0;
3890                :
3891      9  0.0098 :    if (!pExaPixmap || !pExaPixmap->area)
3892                :        return;
3893                :
3894                :    /* The numbers here are arbitrary.  We may want to tune these. */
3895                :    pExaPixmap->area->score += 100;
3896     19  0.0207 :    if (++iter == 10) {
3897                :        ExaOffscreenArea *area;
3898     79  0.0861 :        for (area = pExaScr->info->offScreenAreas; area != NULL;
3899     27  0.0294 :             area = area->next)
3900                :        {
3901     77  0.0839 :            if (area->state == ExaOffscreenRemovable)
3902    198  0.2157 :                area->score = (area->score * 7) / 8;
3903                :        }
3904                :        iter = 0;
3905                :    }
3906     11  0.0120 :}
3907                :
3908                :/**
3909                : * exaOffscreenInit initializes the offscreen memory manager.
3910                : *
3911                : * @param pScreen current screen
3912                : *
3913                : * exaOffscreenInit is called by exaDriverInit to set up the memory manager for
3914                : * the screen, if any offscreen memory is available.
3915                : */
3916                :Bool
3917                :exaOffscreenInit (ScreenPtr pScreen)
3918                :{
3919                :    ExaScreenPriv (pScreen);
3920                :    ExaOffscreenArea *area;
3921                :
3922                :    /* Allocate a big free area */
3923                :    area = xalloc (sizeof (ExaOffscreenArea));
3924                :
3925                :    if (!area)
3926                :        return FALSE;
3927                :
3928                :    area->state = ExaOffscreenAvail;
3929                :    area->base_offset = pExaScr->info->offScreenBase;
3930                :    area->offset = area->base_offset;
3931                :    area->size = pExaScr->info->memorySize - area->base_offset;
3932                :    area->save = NULL;
3933                :    area->next = NULL;
3934                :    area->score = 0;
3935                :
3936                :    /* Add it to the free areas */
3937                :    pExaScr->info->offScreenAreas = area;
3938                :
3939                :    ExaOffscreenValidate (pScreen);
3940                :
3941                :    return TRUE;
3942                :}
3943                :
3944                :void
3945                :ExaOffscreenFini (ScreenPtr pScreen)
3946                :{
3947                :    ExaScreenPriv (pScreen);
3948                :    ExaOffscreenArea *area;
3949                :
3950                :    /* just free all of the area records */
3951                :    while ((area = pExaScr->info->offScreenAreas))
3952                :    {
3953                :        pExaScr->info->offScreenAreas = area->next;
3954                :        xfree (area);
3955                :    }
3956                :}
3957 /* 
3958  * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-region.c"
3959  * 
3960  *    480  0.5229
3961  */
3962
3963
3964                :/***********************************************************
3965                :
3966                :Copyright 1987, 1988, 1989, 1998  The Open Group
3967                :
3968                :Permission to use, copy, modify, distribute, and sell this software and its
3969                :documentation for any purpose is hereby granted without fee, provided that
3970                :the above copyright notice appear in all copies and that both that
3971                :copyright notice and this permission notice appear in supporting
3972                :documentation.
3973                :
3974                :The above copyright notice and this permission notice shall be included in
3975                :all copies or substantial portions of the Software.
3976                :
3977                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3978                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3979                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
3980                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
3981                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3982                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3983                :
3984                :Except as contained in this notice, the name of The Open Group shall not be
3985                :used in advertising or otherwise to promote the sale, use or other dealings
3986                :in this Software without prior written authorization from The Open Group.
3987                :
3988                :Copyright 1987, 1988, 1989 by
3989                :Digital Equipment Corporation, Maynard, Massachusetts.
3990                :
3991                :                        All Rights Reserved
3992                :
3993                :Permission to use, copy, modify, and distribute this software and its
3994                :documentation for any purpose and without fee is hereby granted,
3995                :provided that the above copyright notice appear in all copies and that
3996                :both that copyright notice and this permission notice appear in
3997                :supporting documentation, and that the name of Digital not be
3998                :used in advertising or publicity pertaining to distribution of the
3999                :software without specific, written prior permission.
4000                :
4001                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
4002                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4003                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4004                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4005                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4006                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4007                :SOFTWARE.
4008                :
4009                :******************************************************************/
4010                :
4011                :#include <config.h>
4012                :#include <stdlib.h>
4013                :#include <limits.h>
4014                :#include <string.h>
4015                :#include <stdio.h>
4016                :
4017                :#include "pixman-private.h"
4018                :#include "pixman.h"
4019                :
4020                :typedef struct pixman_region16_point {
4021                :    int x, y;
4022                :} pixman_region16_point_t;
4023                :
4024                :#define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
4025                :/* not a region */
4026                :#define PIXREGION_NAR(reg)      ((reg)->data == pixman_brokendata)
4027                :#define PIXREGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
4028                :#define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
4029                :#define PIXREGION_RECTS(reg) ((reg)->data ? (pixman_box16_t *)((reg)->data + 1) \
4030                :                                       : &(reg)->extents)
4031                :#define PIXREGION_BOXPTR(reg) ((pixman_box16_t *)((reg)->data + 1))
4032                :#define PIXREGION_BOX(reg,i) (&PIXREGION_BOXPTR(reg)[i])
4033                :#define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects)
4034                :#define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1)
4035                :#define PIXREGION_SZOF(n) (sizeof(pixman_region16_data_t) + ((n) * sizeof(pixman_box16_t)))
4036                :
4037                :
4038                :#undef assert
4039                :#ifdef DEBUG_PIXREGION
4040                :#define assert(expr) {if (!(expr)) \
4041                :                FatalError("Assertion failed file %s, line %d: expr\n", \
4042                :                        __FILE__, __LINE__); }
4043                :#else
4044                :#define assert(expr)
4045                :#endif
4046                :
4047                :#define good(reg) assert(pixman_region_selfcheck(reg))
4048                :
4049                :#undef MIN
4050                :#define MIN(a,b) ((a) < (b) ? (a) : (b))
4051                :#undef MAX
4052                :#define MAX(a,b) ((a) > (b) ? (a) : (b))
4053                :
4054                :static const pixman_box16_t _pixman_region_emptyBox = {0, 0, 0, 0};
4055                :static const pixman_region16_data_t _pixman_region_emptyData = {0, 0};
4056                :static const pixman_region16_data_t _pixman_brokendata = {0, 0};
4057                :
4058                :static pixman_box16_t *pixman_region_emptyBox = (pixman_box16_t *)&_pixman_region_emptyBox;
4059                :static pixman_region16_data_t *pixman_region_emptyData = (pixman_region16_data_t *)&_pixman_region_emptyData;
4060                :static pixman_region16_data_t *pixman_brokendata = (pixman_region16_data_t *)&_pixman_brokendata;
4061                :
4062                :/* This function exists only to make it possible to preserve the X ABI - it should
4063                : * go away at first opportunity.
4064                : *
4065                : * The problem is that the X ABI exports the three structs and has used
4066                : * them through macros. So the X server calls this function with
4067                : * the addresses of those structs which makes the existing code continue to
4068                : * work.
4069                : */
4070                :void
4071                :pixman_region_set_static_pointers (pixman_box16_t *empty_box,
4072                :                                   pixman_region16_data_t *empty_data,
4073                :                                   pixman_region16_data_t *broken_data)
4074                :{
4075                :    pixman_region_emptyBox = empty_box;
4076                :    pixman_region_emptyData = empty_data;
4077                :    pixman_brokendata = broken_data;
4078                :}
4079                :
4080                :static pixman_bool_t
4081                :pixman_break (pixman_region16_t *pReg);
4082                :
4083                :/*
4084                : * The functions in this file implement the Region abstraction used extensively
4085                : * throughout the X11 sample server. A Region is simply a set of disjoint
4086                : * (non-overlapping) rectangles, plus an "extent" rectangle which is the
4087                : * smallest single rectangle that contains all the non-overlapping rectangles.
4088                : *
4089                : * A Region is implemented as a "y-x-banded" array of rectangles.  This array
4090                : * imposes two degrees of order.  First, all rectangles are sorted by top side
4091                : * y coordinate first (y1), and then by left side x coordinate (x1).
4092                : *
4093                : * Furthermore, the rectangles are grouped into "bands".  Each rectangle in a
4094                : * band has the same top y coordinate (y1), and each has the same bottom y
4095                : * coordinate (y2).  Thus all rectangles in a band differ only in their left
4096                : * and right side (x1 and x2).  Bands are implicit in the array of rectangles:
4097                : * there is no separate list of band start pointers.
4098                : *
4099                : * The y-x band representation does not minimize rectangles.  In particular,
4100                : * if a rectangle vertically crosses a band (the rectangle has scanlines in
4101                : * the y1 to y2 area spanned by the band), then the rectangle may be broken
4102                : * down into two or more smaller rectangles stacked one atop the other.
4103                : *
4104                : *  -----------                             -----------
4105                : *  |         |                             |         |             band 0
4106                : *  |         |  --------                   -----------  --------
4107                : *  |         |  |      |  in y-x banded    |         |  |      |   band 1
4108                : *  |         |  |      |  form is          |         |  |      |
4109                : *  -----------  |      |                   -----------  --------
4110                : *               |      |                                |      |   band 2
4111                : *               --------                                --------
4112                : *
4113                : * An added constraint on the rectangles is that they must cover as much
4114                : * horizontal area as possible: no two rectangles within a band are allowed
4115                : * to touch.
4116                : *
4117                : * Whenever possible, bands will be merged together to cover a greater vertical
4118                : * distance (and thus reduce the number of rectangles). Two bands can be merged
4119                : * only if the bottom of one touches the top of the other and they have
4120                : * rectangles in the same places (of the same width, of course).
4121                : *
4122                : * Adam de Boor wrote most of the original region code.  Joel McCormack
4123                : * substantially modified or rewrote most of the core arithmetic routines, and
4124                : * added pixman_region_validate in order to support several speed improvements to
4125                : * pixman_region_validateTree.  Bob Scheifler changed the representation to be more
4126                : * compact when empty or a single rectangle, and did a bunch of gratuitous
4127                : * reformatting. Carl Worth did further gratuitous reformatting while re-merging
4128                : * the server and client region code into libpixregion.
4129                : */
4130                :
4131                :/*  true iff two Boxes overlap */
4132                :#define EXTENTCHECK(r1,r2) \
4133                :      (!( ((r1)->x2 <= (r2)->x1)  || \
4134                :          ((r1)->x1 >= (r2)->x2)  || \
4135                :          ((r1)->y2 <= (r2)->y1)  || \
4136                :          ((r1)->y1 >= (r2)->y2) ) )
4137                :
4138                :/* true iff (x,y) is in Box */
4139                :#define INBOX(r,x,y) \
4140                :      ( ((r)->x2 >  x) && \
4141                :        ((r)->x1 <= x) && \
4142                :        ((r)->y2 >  y) && \
4143                :        ((r)->y1 <= y) )
4144                :
4145                :/* true iff Box r1 contains Box r2 */
4146                :#define SUBSUMES(r1,r2) \
4147                :      ( ((r1)->x1 <= (r2)->x1) && \
4148                :        ((r1)->x2 >= (r2)->x2) && \
4149                :        ((r1)->y1 <= (r2)->y1) && \
4150                :        ((r1)->y2 >= (r2)->y2) )
4151                :
4152                :#define allocData(n) malloc(PIXREGION_SZOF(n))
4153                :#define freeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
4154                :
4155                :#define RECTALLOC_BAIL(pReg,n,bail) \
4156                :if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
4157                :    if (!pixman_rect_alloc(pReg, n)) { goto bail; }
4158                :
4159                :#define RECTALLOC(pReg,n) \
4160                :if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
4161                :    if (!pixman_rect_alloc(pReg, n)) { return FALSE; }
4162                :
4163                :#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2)      \
4164                :{                                               \
4165                :    pNextRect->x1 = nx1;                        \
4166                :    pNextRect->y1 = ny1;                        \
4167                :    pNextRect->x2 = nx2;                        \
4168                :    pNextRect->y2 = ny2;                        \
4169                :    pNextRect++;                                \
4170                :}
4171                :
4172                :#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2)                 \
4173                :{                                                                       \
4174                :    if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
4175                :    {                                                                   \
4176                :        if (!pixman_rect_alloc(pReg, 1))                                        \
4177                :            return FALSE;                                               \
4178                :        pNextRect = PIXREGION_TOP(pReg);                                        \
4179                :    }                                                                   \
4180                :    ADDRECT(pNextRect,nx1,ny1,nx2,ny2);                                 \
4181                :    pReg->data->numRects++;                                             \
4182                :    assert(pReg->data->numRects<=pReg->data->size);                     \
4183                :}
4184                :
4185                :#define DOWNSIZE(reg,numRects)                                           \
4186                :if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
4187                :{                                                                        \
4188                :    pixman_region16_data_t * NewData;                                                    \
4189                :    NewData = (pixman_region16_data_t *)realloc((reg)->data, PIXREGION_SZOF(numRects));  \
4190                :    if (NewData)                                                         \
4191                :    {                                                                    \
4192                :        NewData->size = (numRects);                                      \
4193                :        (reg)->data = NewData;                                           \
4194                :    }                                                                    \
4195                :}
4196                :
4197                :pixman_bool_t
4198                :pixman_region_equal(reg1, reg2)
4199                :    pixman_region16_t * reg1;
4200                :    pixman_region16_t * reg2;
4201                :{
4202                :    int i;
4203                :    pixman_box16_t *rects1;
4204                :    pixman_box16_t *rects2;
4205                :
4206                :    if (reg1->extents.x1 != reg2->extents.x1) return FALSE;
4207                :    if (reg1->extents.x2 != reg2->extents.x2) return FALSE;
4208                :    if (reg1->extents.y1 != reg2->extents.y1) return FALSE;
4209                :    if (reg1->extents.y2 != reg2->extents.y2) return FALSE;
4210                :    if (PIXREGION_NUM_RECTS(reg1) != PIXREGION_NUM_RECTS(reg2)) return FALSE;
4211                :
4212                :    rects1 = PIXREGION_RECTS(reg1);
4213                :    rects2 = PIXREGION_RECTS(reg2);
4214                :    for (i = 0; i != PIXREGION_NUM_RECTS(reg1); i++) {
4215                :        if (rects1[i].x1 != rects2[i].x1) return FALSE;
4216                :        if (rects1[i].x2 != rects2[i].x2) return FALSE;
4217                :        if (rects1[i].y1 != rects2[i].y1) return FALSE;
4218                :        if (rects1[i].y2 != rects2[i].y2) return FALSE;
4219                :    }
4220                :    return TRUE;
4221                :}
4222                :
4223                :int
4224                :pixman_region16_print(rgn)
4225                :    pixman_region16_t * rgn;
4226                :{
4227                :    int num, size;
4228                :    int i;
4229                :    pixman_box16_t * rects;
4230                :
4231                :    num = PIXREGION_NUM_RECTS(rgn);
4232                :    size = PIXREGION_SIZE(rgn);
4233                :    rects = PIXREGION_RECTS(rgn);
4234                :    fprintf(stderr, "num: %d size: %d\n", num, size);
4235                :    fprintf(stderr, "extents: %d %d %d %d\n",
4236                :           rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
4237                :    for (i = 0; i < num; i++)
4238                :        fprintf(stderr, "%d %d %d %d \n",
4239                :                rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
4240                :    fprintf(stderr, "\n");
4241                :    return(num);
4242                :}
4243                :
4244                :
4245                :void
4246                :pixman_region_init (pixman_region16_t *region)
4247      8  0.0087 :{ /* pixman_region_init total:     13  0.0142 */
4248      3  0.0033 :    region->extents = *pixman_region_emptyBox;
4249                :    region->data = pixman_region_emptyData;
4250      2  0.0022 :}
4251                :
4252                :void
4253                :pixman_region_init_rect (pixman_region16_t *region,
4254                :                         int x, int y, unsigned int width, unsigned int height)
4255      2  0.0022 :{ /* pixman_region_init_rect total:      3  0.0033 */
4256                :    region->extents.x1 = x;
4257                :    region->extents.y1 = y;
4258                :    region->extents.x2 = x + width;
4259      1  0.0011 :    region->extents.y2 = y + height;
4260                :    region->data = NULL;
4261                :}
4262                :
4263                :void
4264                :pixman_region_init_with_extents (pixman_region16_t *region, pixman_box16_t *extents)
4265      1  0.0011 :{ /* pixman_region_init_with_extents total:      2  0.0022 */
4266      1  0.0011 :    region->extents = *extents;
4267                :    region->data = NULL;
4268                :}
4269                :
4270                :void
4271                :pixman_region_fini (pixman_region16_t *region)
4272     41  0.0447 :{ /* pixman_region_fini total:     44  0.0479 */
4273                :    good (region);
4274      1  0.0011 :    freeData (region);
4275      2  0.0022 :}
4276                :
4277                :int
4278                :pixman_region_n_rects (pixman_region16_t *region)
4279     14  0.0153 :{ /* pixman_region_n_rects total:     38  0.0414 */
4280     16  0.0174 :    return PIXREGION_NUM_RECTS (region);
4281      8  0.0087 :}
4282                :
4283                :pixman_box16_t *
4284                :pixman_region_rects (pixman_region16_t *region)
4285                :{
4286                :    return PIXREGION_RECTS (region);
4287                :}
4288                :
4289                :pixman_box16_t *
4290                :pixman_region_rectangles (pixman_region16_t *region,
4291                :                          int               *n_rects)
4292     41  0.0447 :{ /* pixman_region_rectangles total:     82  0.0893 */
4293                :    if (n_rects)
4294                :        *n_rects = PIXREGION_NUM_RECTS (region);
4295                :
4296     17  0.0185 :    return PIXREGION_RECTS (region);
4297     24  0.0261 :}
4298                :
4299                :static pixman_bool_t
4300                :pixman_break (pixman_region16_t *region)
4301                :{
4302                :    freeData (region);
4303                :    region->extents = *pixman_region_emptyBox;
4304                :    region->data = pixman_brokendata;
4305                :    return FALSE;
4306                :}
4307                :
4308                :static pixman_bool_t
4309                :pixman_rect_alloc (pixman_region16_t * region, int n)
4310      7  0.0076 :{ /* pixman_rect_alloc total:     16  0.0174 */
4311                :    pixman_region16_data_t *data;
4312                :
4313                :    if (!region->data)
4314                :    {
4315                :        n++;
4316                :        region->data = allocData(n);
4317                :        if (!region->data)
4318                :            return pixman_break (region);
4319                :        region->data->numRects = 1;
4320                :        *PIXREGION_BOXPTR(region) = region->extents;
4321                :    }
4322      1  0.0011 :    else if (!region->data->size)
4323                :    {
4324      4  0.0044 :        region->data = allocData(n);
4325      1  0.0011 :        if (!region->data)
4326                :            return pixman_break (region);
4327      1  0.0011 :        region->data->numRects = 0;
4328                :    }
4329                :    else
4330                :    {
4331                :        if (n == 1)
4332                :        {
4333                :            n = region->data->numRects;
4334                :            if (n > 500) /* XXX pick numbers out of a hat */
4335                :                n = 250;
4336                :        }
4337                :        n += region->data->numRects;
4338                :        data = (pixman_region16_data_t *)realloc(region->data, PIXREGION_SZOF(n));
4339                :        if (!data)
4340                :            return pixman_break (region);
4341                :        region->data = data;
4342                :    }
4343                :    region->data->size = n;
4344                :    return TRUE;
4345      2  0.0022 :}
4346                :
4347                :pixman_bool_t
4348                :pixman_region_copy (pixman_region16_t *dst, pixman_region16_t *src)
4349      4  0.0044 :{ /* pixman_region_copy total:     15  0.0163 */
4350                :    good(dst);
4351                :    good(src);
4352                :    if (dst == src)
4353                :        return TRUE;
4354      2  0.0022 :    dst->extents = src->extents;
4355      1  0.0011 :    if (!src->data || !src->data->size)
4356                :    {
4357      6  0.0065 :        freeData(dst);
4358      1  0.0011 :        dst->data = src->data;
4359                :        return TRUE;
4360                :    }
4361                :    if (!dst->data || (dst->data->size < src->data->numRects))
4362                :    {
4363                :        freeData(dst);
4364                :        dst->data = allocData(src->data->numRects);
4365                :        if (!dst->data)
4366                :            return pixman_break (dst);
4367                :        dst->data->size = src->data->numRects;
4368                :    }
4369                :    dst->data->numRects = src->data->numRects;
4370                :    memmove((char *)PIXREGION_BOXPTR(dst),(char *)PIXREGION_BOXPTR(src),
4371                :          dst->data->numRects * sizeof(pixman_box16_t));
4372                :    return TRUE;
4373      1  0.0011 :}
4374                :
4375                :/*======================================================================
4376                : *          Generic Region Operator
4377                : *====================================================================*/
4378                :
4379                :/*-
4380                : *-----------------------------------------------------------------------
4381                : * pixman_coalesce --
4382                : *      Attempt to merge the boxes in the current band with those in the
4383                : *      previous one.  We are guaranteed that the current band extends to
4384                : *      the end of the rects array.  Used only by pixman_op.
4385                : *
4386                : * Results:
4387                : *      The new index for the previous band.
4388                : *
4389                : * Side Effects:
4390                : *      If coalescing takes place:
4391                : *          - rectangles in the previous band will have their y2 fields
4392                : *            altered.
4393                : *          - region->data->numRects will be decreased.
4394                : *
4395                : *-----------------------------------------------------------------------
4396                : */
4397                :static inline int
4398                :pixman_coalesce (
4399                :    pixman_region16_t * region,         /* Region to coalesce                */
4400                :    int                 prevStart,      /* Index of start of previous band   */
4401                :    int                 curStart)       /* Index of start of current band    */
4402                :{
4403                :    pixman_box16_t *    pPrevBox;       /* Current box in previous band      */
4404                :    pixman_box16_t *    pCurBox;        /* Current box in current band       */
4405                :    int         numRects;       /* Number rectangles in both bands   */
4406                :    int y2;             /* Bottom of current band            */
4407                :    /*
4408                :     * Figure out how many rectangles are in the band.
4409                :     */
4410                :    numRects = curStart - prevStart;
4411                :    assert(numRects == region->data->numRects - curStart);
4412                :
4413                :    if (!numRects) return curStart;
4414                :
4415                :    /*
4416                :     * The bands may only be coalesced if the bottom of the previous
4417                :     * matches the top scanline of the current.
4418                :     */
4419                :    pPrevBox = PIXREGION_BOX(region, prevStart);
4420                :    pCurBox = PIXREGION_BOX(region, curStart);
4421                :    if (pPrevBox->y2 != pCurBox->y1) return curStart;
4422                :
4423                :    /*
4424                :     * Make sure the bands have boxes in the same places. This
4425                :     * assumes that boxes have been added in such a way that they
4426                :     * cover the most area possible. I.e. two boxes in a band must
4427                :     * have some horizontal space between them.
4428                :     */
4429                :    y2 = pCurBox->y2;
4430                :
4431                :    do {
4432                :        if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {
4433                :            return (curStart);
4434                :        }
4435                :        pPrevBox++;
4436                :        pCurBox++;
4437                :        numRects--;
4438                :    } while (numRects);
4439                :
4440                :    /*
4441                :     * The bands may be merged, so set the bottom y of each box
4442                :     * in the previous band to the bottom y of the current band.
4443                :     */
4444                :    numRects = curStart - prevStart;
4445                :    region->data->numRects -= numRects;
4446                :    do {
4447                :        pPrevBox--;
4448                :        pPrevBox->y2 = y2;
4449                :        numRects--;
4450                :    } while (numRects);
4451                :    return prevStart;
4452                :}
4453                :
4454                :/* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */
4455                :
4456                :#define Coalesce(newReg, prevBand, curBand)                             \
4457                :    if (curBand - prevBand == newReg->data->numRects - curBand) {       \
4458                :        prevBand = pixman_coalesce(newReg, prevBand, curBand);          \
4459                :    } else {                                                            \
4460                :        prevBand = curBand;                                             \
4461                :    }
4462                :
4463                :/*-
4464                : *-----------------------------------------------------------------------
4465                : * pixman_region_appendNonO --
4466                : *      Handle a non-overlapping band for the union and subtract operations.
4467                : *      Just adds the (top/bottom-clipped) rectangles into the region.
4468                : *      Doesn't have to check for subsumption or anything.
4469                : *
4470                : * Results:
4471                : *      None.
4472                : *
4473                : * Side Effects:
4474                : *      region->data->numRects is incremented and the rectangles overwritten
4475                : *      with the rectangles we're passed.
4476                : *
4477                : *-----------------------------------------------------------------------
4478                : */
4479                :
4480                :static inline pixman_bool_t
4481                :pixman_region_appendNonO (
4482                :    pixman_region16_t * region,
4483                :    pixman_box16_t *    r,
4484                :    pixman_box16_t *            rEnd,
4485                :    int         y1,
4486                :    int         y2)
4487                :{
4488                :    pixman_box16_t *    pNextRect;
4489                :    int newRects;
4490                :
4491                :    newRects = rEnd - r;
4492                :
4493                :    assert(y1 < y2);
4494                :    assert(newRects != 0);
4495                :
4496                :    /* Make sure we have enough space for all rectangles to be added */
4497                :    RECTALLOC(region, newRects);
4498                :    pNextRect = PIXREGION_TOP(region);
4499                :    region->data->numRects += newRects;
4500                :    do {
4501                :        assert(r->x1 < r->x2);
4502                :        ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
4503                :        r++;
4504                :    } while (r != rEnd);
4505                :
4506                :    return TRUE;
4507                :}
4508                :
4509                :#define FindBand(r, rBandEnd, rEnd, ry1)                    \
4510                :{                                                           \
4511                :    ry1 = r->y1;                                            \
4512                :    rBandEnd = r+1;                                         \
4513                :    while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) {   \
4514                :        rBandEnd++;                                         \
4515                :    }                                                       \
4516                :}
4517                :
4518                :#define AppendRegions(newReg, r, rEnd)                                  \
4519                :{                                                                       \
4520                :    int newRects;                                                       \
4521                :    if ((newRects = rEnd - r)) {                                        \
4522                :        RECTALLOC(newReg, newRects);                                    \
4523                :        memmove((char *)PIXREGION_TOP(newReg),(char *)r,                        \
4524                :              newRects * sizeof(pixman_box16_t));                               \
4525                :        newReg->data->numRects += newRects;                             \
4526                :    }                                                                   \
4527                :}
4528                :
4529                :/*-
4530                : *-----------------------------------------------------------------------
4531                : * pixman_op --
4532                : *      Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse,
4533                : *      pixman_region_subtract, pixman_region_intersect....  Both regions MUST have at least one
4534                : *      rectangle, and cannot be the same object.
4535                : *
4536                : * Results:
4537                : *      TRUE if successful.
4538                : *
4539                : * Side Effects:
4540                : *      The new region is overwritten.
4541                : *      pOverlap set to TRUE if overlapFunc ever returns TRUE.
4542                : *
4543                : * Notes:
4544                : *      The idea behind this function is to view the two regions as sets.
4545                : *      Together they cover a rectangle of area that this function divides
4546                : *      into horizontal bands where points are covered only by one region
4547                : *      or by both. For the first case, the nonOverlapFunc is called with
4548                : *      each the band and the band's upper and lower extents. For the
4549                : *      second, the overlapFunc is called to process the entire band. It
4550                : *      is responsible for clipping the rectangles in the band, though
4551                : *      this function provides the boundaries.
4552                : *      At the end of each band, the new region is coalesced, if possible,
4553                : *      to reduce the number of rectangles in the region.
4554                : *
4555                : *-----------------------------------------------------------------------
4556                : */
4557                :
4558                :typedef pixman_bool_t (*OverlapProcPtr)(
4559                :    pixman_region16_t    *region,
4560                :    pixman_box16_t *r1,
4561                :    pixman_box16_t *r1End,
4562                :    pixman_box16_t *r2,
4563                :    pixman_box16_t *r2End,
4564                :    short        y1,
4565                :    short        y2,
4566                :    int          *pOverlap);
4567                :
4568                :static pixman_bool_t
4569                :pixman_op(
4570                :    pixman_region16_t *newReg,              /* Place to store result         */
4571                :    pixman_region16_t *       reg1,                 /* First region in operation     */
4572                :    pixman_region16_t *       reg2,                 /* 2d region in operation        */
4573                :    OverlapProcPtr  overlapFunc,            /* Function to call for over-
4574                :                                             * lapping bands                 */
4575                :    int     appendNon1,             /* Append non-overlapping bands  */
4576                :                                            /* in region 1 ? */
4577                :    int     appendNon2,             /* Append non-overlapping bands  */
4578                :                                            /* in region 2 ? */
4579                :    int     *pOverlap)
4580      7  0.0076 :{ /* pixman_op total:    146  0.1591 */
4581                :    pixman_box16_t * r1;                            /* Pointer into first region     */
4582                :    pixman_box16_t * r2;                            /* Pointer into 2d region        */
4583                :    pixman_box16_t *        r1End;                  /* End of 1st region             */
4584                :    pixman_box16_t *        r2End;                  /* End of 2d region              */
4585                :    short           ybot;                   /* Bottom of intersection        */
4586                :    short           ytop;                   /* Top of intersection           */
4587                :    pixman_region16_data_t *        oldData;                /* Old data for newReg           */
4588                :    int             prevBand;               /* Index of start of
4589                :                                             * previous band in newReg       */
4590                :    int             curBand;                /* Index of start of current
4591                :                                             * band in newReg                */
4592                :    pixman_box16_t * r1BandEnd;             /* End of current band in r1     */
4593                :    pixman_box16_t * r2BandEnd;             /* End of current band in r2     */
4594                :    short           top;                    /* Top of non-overlapping band   */
4595                :    short           bot;                    /* Bottom of non-overlapping band*/
4596                :    int    r1y1;                    /* Temps for r1->y1 and r2->y1   */
4597                :    int    r2y1;
4598                :    int             newSize;
4599                :    int             numRects;
4600                :
4601                :    /*
4602                :     * Break any region computed from a broken region
4603                :     */
4604      3  0.0033 :    if (PIXREGION_NAR (reg1) || PIXREGION_NAR(reg2))
4605                :        return pixman_break (newReg);
4606                :
4607                :    /*
4608                :     * Initialization:
4609                :     *  set r1, r2, r1End and r2End appropriately, save the rectangles
4610                :     * of the destination region until the end in case it's one of
4611                :     * the two source regions, then mark the "new" region empty, allocating
4612                :     * another array of rectangles for it to use.
4613                :     */
4614                :
4615      3  0.0033 :    r1 = PIXREGION_RECTS(reg1);
4616      2  0.0022 :    newSize = PIXREGION_NUM_RECTS(reg1);
4617                :    r1End = r1 + newSize;
4618      4  0.0044 :    numRects = PIXREGION_NUM_RECTS(reg2);
4619      1  0.0011 :    r2 = PIXREGION_RECTS(reg2);
4620                :    r2End = r2 + numRects;
4621                :    assert(r1 != r1End);
4622                :    assert(r2 != r2End);
4623                :
4624                :    oldData = (pixman_region16_data_t *)NULL;
4625      1  0.0011 :    if (((newReg == reg1) && (newSize > 1)) ||
4626                :        ((newReg == reg2) && (numRects > 1)))
4627                :    {
4628      1  0.0011 :        oldData = newReg->data;
4629      1  0.0011 :        newReg->data = pixman_region_emptyData;
4630                :    }
4631                :    /* guess at new size */
4632                :    if (numRects > newSize)
4633                :        newSize = numRects;
4634                :    newSize <<= 1;
4635      1  0.0011 :    if (!newReg->data)
4636      2  0.0022 :        newReg->data = pixman_region_emptyData;
4637                :    else if (newReg->data->size)
4638                :        newReg->data->numRects = 0;
4639                :    if (newSize > newReg->data->size) {
4640                :        if (!pixman_rect_alloc(newReg, newSize)) {
4641                :            if (oldData)
4642                :                free (oldData);
4643                :            return FALSE;
4644                :        }
4645                :    }
4646                :
4647                :    /*
4648                :     * Initialize ybot.
4649                :     * In the upcoming loop, ybot and ytop serve different functions depending
4650                :     * on whether the band being handled is an overlapping or non-overlapping
4651                :     * band.
4652                :     *  In the case of a non-overlapping band (only one of the regions
4653                :     * has points in the band), ybot is the bottom of the most recent
4654                :     * intersection and thus clips the top of the rectangles in that band.
4655                :     * ytop is the top of the next intersection between the two regions and
4656                :     * serves to clip the bottom of the rectangles in the current band.
4657                :     *  For an overlapping band (where the two regions intersect), ytop clips
4658                :     * the top of the rectangles of both regions and ybot clips the bottoms.
4659                :     */
4660                :
4661      2  0.0022 :    ybot = MIN(r1->y1, r2->y1);
4662                :
4663                :    /*
4664                :     * prevBand serves to mark the start of the previous band so rectangles
4665                :     * can be coalesced into larger rectangles. qv. pixman_coalesce, above.
4666                :     * In the beginning, there is no previous band, so prevBand == curBand
4667                :     * (curBand is set later on, of course, but the first band will always
4668                :     * start at index 0). prevBand and curBand must be indices because of
4669                :     * the possible expansion, and resultant moving, of the new region's
4670                :     * array of rectangles.
4671                :     */
4672                :    prevBand = 0;
4673                :
4674                :    do {
4675                :        /*
4676                :         * This algorithm proceeds one source-band (as opposed to a
4677                :         * destination band, which is determined by where the two regions
4678                :         * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
4679                :         * rectangle after the last one in the current band for their
4680                :         * respective regions.
4681                :         */
4682                :        assert(r1 != r1End);
4683                :        assert(r2 != r2End);
4684                :
4685      2  0.0022 :        FindBand(r1, r1BandEnd, r1End, r1y1);
4686      9  0.0098 :        FindBand(r2, r2BandEnd, r2End, r2y1);
4687                :
4688                :        /*
4689                :         * First handle the band that doesn't intersect, if any.
4690                :         *
4691                :         * Note that attention is restricted to one band in the
4692                :         * non-intersecting region at once, so if a region has n
4693                :         * bands between the current position and the next place it overlaps
4694                :         * the other, this entire loop will be passed through n times.
4695                :         */
4696      3  0.0033 :        if (r1y1 < r2y1) {
4697                :            if (appendNon1) {
4698                :                top = MAX(r1y1, ybot);
4699                :                bot = MIN(r1->y2, r2y1);
4700                :                if (top != bot) {
4701                :                    curBand = newReg->data->numRects;
4702                :                    pixman_region_appendNonO(newReg, r1, r1BandEnd, top, bot);
4703                :                    Coalesce(newReg, prevBand, curBand);
4704                :                }
4705                :            }
4706                :            ytop = r2y1;
4707                :        } else if (r2y1 < r1y1) {
4708      1  0.0011 :            if (appendNon2) {
4709      1  0.0011 :                top = MAX(r2y1, ybot);
4710                :                bot = MIN(r2->y2, r1y1);
4711                :                if (top != bot) {
4712                :                    curBand = newReg->data->numRects;
4713                :                    pixman_region_appendNonO(newReg, r2, r2BandEnd, top, bot);
4714                :                    Coalesce(newReg, prevBand, curBand);
4715                :                }
4716                :            }
4717                :            ytop = r1y1;
4718                :        } else {
4719                :            ytop = r1y1;
4720                :        }
4721                :
4722                :        /*
4723                :         * Now see if we've hit an intersecting band. The two bands only
4724                :         * intersect if ybot > ytop
4725                :         */
4726      2  0.0022 :        ybot = MIN(r1->y2, r2->y2);
4727      6  0.0065 :        if (ybot > ytop) {
4728      4  0.0044 :            curBand = newReg->data->numRects;
4729      4  0.0044 :            (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,
4730                :                            pOverlap);
4731      9  0.0098 :            Coalesce(newReg, prevBand, curBand);
4732                :        }
4733                :
4734                :        /*
4735                :         * If we've finished with a band (y2 == ybot) we skip forward
4736                :         * in the region to the next band.
4737                :         */
4738      1  0.0011 :        if (r1->y2 == ybot) r1 = r1BandEnd;
4739      3  0.0033 :        if (r2->y2 == ybot) r2 = r2BandEnd;
4740                :
4741      5  0.0054 :    } while (r1 != r1End && r2 != r2End);
4742                :
4743                :    /*
4744                :     * Deal with whichever region (if any) still has rectangles left.
4745                :     *
4746                :     * We only need to worry about banding and coalescing for the very first
4747                :     * band left.  After that, we can just group all remaining boxes,
4748                :     * regardless of how many bands, into one final append to the list.
4749                :     */
4750                :
4751                :    if ((r1 != r1End) && appendNon1) {
4752                :        /* Do first nonOverlap1Func call, which may be able to coalesce */
4753      1  0.0011 :        FindBand(r1, r1BandEnd, r1End, r1y1);
4754                :        curBand = newReg->data->numRects;
4755      2  0.0022 :        pixman_region_appendNonO(newReg, r1, r1BandEnd, MAX(r1y1, ybot), r1->y2);
4756      3  0.0033 :        Coalesce(newReg, prevBand, curBand);
4757                :        /* Just append the rest of the boxes  */
4758      1  0.0011 :        AppendRegions(newReg, r1BandEnd, r1End);
4759                :
4760                :    } else if ((r2 != r2End) && appendNon2) {
4761                :        /* Do first nonOverlap2Func call, which may be able to coalesce */
4762                :        FindBand(r2, r2BandEnd, r2End, r2y1);
4763                :        curBand = newReg->data->numRects;
4764                :        pixman_region_appendNonO(newReg, r2, r2BandEnd, MAX(r2y1, ybot), r2->y2);
4765                :        Coalesce(newReg, prevBand, curBand);
4766                :        /* Append rest of boxes */
4767      7  0.0076 :        AppendRegions(newReg, r2BandEnd, r2End);
4768                :    }
4769                :
4770      2  0.0022 :    if (oldData)
4771                :        free(oldData);
4772                :
4773      8  0.0087 :    if (!(numRects = newReg->data->numRects))
4774                :    {
4775                :        freeData(newReg);
4776                :        newReg->data = pixman_region_emptyData;
4777                :    }
4778      1  0.0011 :    else if (numRects == 1)
4779                :    {
4780                :        newReg->extents = *PIXREGION_BOXPTR(newReg);
4781                :        freeData(newReg);
4782                :        newReg->data = (pixman_region16_data_t *)NULL;
4783                :    }
4784                :    else
4785                :    {
4786      1  0.0011 :        DOWNSIZE(newReg, numRects);
4787                :    }
4788                :
4789                :    return TRUE;
4790                :}
4791                :
4792                :/*-
4793                : *-----------------------------------------------------------------------
4794                : * pixman_set_extents --
4795                : *      Reset the extents of a region to what they should be. Called by
4796                : *      pixman_region_subtract and pixman_region_intersect as they can't figure it out along the
4797                : *      way or do so easily, as pixman_region_union can.
4798                : *
4799                : * Results:
4800                : *      None.
4801                : *
4802                : * Side Effects:
4803                : *      The region's 'extents' structure is overwritten.
4804                : *
4805                : *-----------------------------------------------------------------------
4806                : */
4807                :static void
4808                :pixman_set_extents (pixman_region16_t *region)
4809                :{
4810                :    pixman_box16_t *box, *boxEnd;
4811                :
4812                :    if (!region->data)
4813                :        return;
4814                :    if (!region->data->size)
4815                :    {
4816                :        region->extents.x2 = region->extents.x1;
4817                :        region->extents.y2 = region->extents.y1;
4818                :        return;
4819                :    }
4820                :
4821                :    box = PIXREGION_BOXPTR(region);
4822                :    boxEnd = PIXREGION_END(region);
4823                :
4824                :    /*
4825                :     * Since box is the first rectangle in the region, it must have the
4826                :     * smallest y1 and since boxEnd is the last rectangle in the region,
4827                :     * it must have the largest y2, because of banding. Initialize x1 and
4828                :     * x2 from  box and boxEnd, resp., as good things to initialize them
4829                :     * to...
4830                :     */
4831                :    region->extents.x1 = box->x1;
4832                :    region->extents.y1 = box->y1;
4833                :    region->extents.x2 = boxEnd->x2;
4834                :    region->extents.y2 = boxEnd->y2;
4835                :
4836                :    assert(region->extents.y1 < region->extents.y2);
4837                :    while (box <= boxEnd) {
4838                :        if (box->x1 < region->extents.x1)
4839                :            region->extents.x1 = box->x1;
4840                :        if (box->x2 > region->extents.x2)
4841                :            region->extents.x2 = box->x2;
4842                :        box++;
4843                :    };
4844                :
4845                :    assert(region->extents.x1 < region->extents.x2);
4846                :}
4847                :
4848                :/*======================================================================
4849                : *          Region Intersection
4850                : *====================================================================*/
4851                :/*-
4852                : *-----------------------------------------------------------------------
4853                : * pixman_region_intersectO --
4854                : *      Handle an overlapping band for pixman_region_intersect.
4855                : *
4856                : * Results:
4857                : *      TRUE if successful.
4858                : *
4859                : * Side Effects:
4860                : *      Rectangles may be added to the region.
4861                : *
4862                : *-----------------------------------------------------------------------
4863                : */
4864                :/*ARGSUSED*/
4865                :static pixman_bool_t
4866                :pixman_region_intersectO (pixman_region16_t *region,
4867                :                          pixman_box16_t    *r1,
4868                :                          pixman_box16_t    *r1End,
4869                :                          pixman_box16_t    *r2,
4870                :                          pixman_box16_t    *r2End,
4871                :                          short              y1,
4872                :                          short              y2,
4873                :                          int               *pOverlap)
4874                :{
4875                :    int         x1;
4876                :    int         x2;
4877                :    pixman_box16_t *    pNextRect;
4878                :
4879                :    pNextRect = PIXREGION_TOP(region);
4880                :
4881                :    assert(y1 < y2);
4882                :    assert(r1 != r1End && r2 != r2End);
4883                :
4884                :    do {
4885                :        x1 = MAX(r1->x1, r2->x1);
4886                :        x2 = MIN(r1->x2, r2->x2);
4887                :
4888                :        /*
4889                :         * If there's any overlap between the two rectangles, add that
4890                :         * overlap to the new region.
4891                :         */
4892                :        if (x1 < x2)
4893                :            NEWRECT(region, pNextRect, x1, y1, x2, y2);
4894                :
4895                :        /*
4896                :         * Advance the pointer(s) with the leftmost right side, since the next
4897                :         * rectangle on that list may still overlap the other region's
4898                :         * current rectangle.
4899                :         */
4900                :        if (r1->x2 == x2) {
4901                :            r1++;
4902                :        }
4903                :        if (r2->x2 == x2) {
4904                :            r2++;
4905                :        }
4906                :    } while ((r1 != r1End) && (r2 != r2End));
4907                :
4908                :    return TRUE;
4909                :}
4910                :
4911                :pixman_bool_t
4912                :pixman_region_intersect (pixman_region16_t *    newReg,
4913                :                         pixman_region16_t *    reg1,
4914                :                         pixman_region16_t *    reg2)
4915      4  0.0044 :{ /* pixman_region_intersect total:     13  0.0142 */
4916                :    good(reg1);
4917                :    good(reg2);
4918                :    good(newReg);
4919                :   /* check for trivial reject */
4920      4  0.0044 :    if (PIXREGION_NIL(reg1)  || PIXREGION_NIL(reg2) ||
4921                :        !EXTENTCHECK(&reg1->extents, &reg2->extents))
4922                :    {
4923                :        /* Covers about 20% of all cases */
4924                :        freeData(newReg);
4925                :        newReg->extents.x2 = newReg->extents.x1;
4926                :        newReg->extents.y2 = newReg->extents.y1;
4927                :        if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2))
4928                :        {
4929                :            newReg->data = pixman_brokendata;
4930                :            return FALSE;
4931                :        }
4932                :        else
4933                :            newReg->data = pixman_region_emptyData;
4934                :    }
4935                :    else if (!reg1->data && !reg2->data)
4936                :    {
4937                :        /* Covers about 80% of cases that aren't trivially rejected */
4938      1  0.0011 :        newReg->extents.x1 = MAX(reg1->extents.x1, reg2->extents.x1);
4939      1  0.0011 :        newReg->extents.y1 = MAX(reg1->extents.y1, reg2->extents.y1);
4940      1  0.0011 :        newReg->extents.x2 = MIN(reg1->extents.x2, reg2->extents.x2);
4941                :        newReg->extents.y2 = MIN(reg1->extents.y2, reg2->extents.y2);
4942                :        freeData(newReg);
4943                :        newReg->data = (pixman_region16_data_t *)NULL;
4944                :    }
4945                :    else if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))
4946                :    {
4947                :        return pixman_region_copy(newReg, reg1);
4948                :    }
4949                :    else if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))
4950                :    {
4951                :        return pixman_region_copy(newReg, reg2);
4952                :    }
4953                :    else if (reg1 == reg2)
4954                :    {
4955                :        return pixman_region_copy(newReg, reg1);
4956                :    }
4957                :    else
4958                :    {
4959                :        /* General purpose intersection */
4960                :        int overlap; /* result ignored */
4961                :        if (!pixman_op(newReg, reg1, reg2, pixman_region_intersectO, FALSE, FALSE,
4962                :                        &overlap))
4963                :            return FALSE;
4964                :        pixman_set_extents(newReg);
4965                :    }
4966                :
4967                :    good(newReg);
4968                :    return(TRUE);
4969      2  0.0022 :}
4970                :
4971                :#define MERGERECT(r)                                            \
4972                :{                                                               \
4973                :    if (r->x1 <= x2) {                                          \
4974                :        /* Merge with current rectangle */                      \
4975                :        if (r->x1 < x2) *pOverlap = TRUE;                               \
4976                :        if (x2 < r->x2) x2 = r->x2;                             \
4977                :    } else {                                                    \
4978                :        /* Add current rectangle, start new one */              \
4979                :        NEWRECT(region, pNextRect, x1, y1, x2, y2);             \
4980                :        x1 = r->x1;                                             \
4981                :        x2 = r->x2;                                             \
4982                :    }                                                           \
4983                :    r++;                                                        \
4984                :}
4985                :
4986                :/*======================================================================
4987                : *          Region Union
4988                : *====================================================================*/
4989                :
4990                :/*-
4991                : *-----------------------------------------------------------------------
4992                : * pixman_region_unionO --
4993                : *      Handle an overlapping band for the union operation. Picks the
4994                : *      left-most rectangle each time and merges it into the region.
4995                : *
4996                : * Results:
4997                : *      TRUE if successful.
4998                : *
4999                : * Side Effects:
5000                : *      region is overwritten.
5001                : *      pOverlap is set to TRUE if any boxes overlap.
5002                : *
5003                : *-----------------------------------------------------------------------
5004                : */
5005                :static pixman_bool_t
5006                :pixman_region_unionO (
5007                :    pixman_region16_t    *region,
5008                :    pixman_box16_t *r1,
5009                :    pixman_box16_t *r1End,
5010                :    pixman_box16_t *r2,
5011                :    pixman_box16_t *r2End,
5012                :    short         y1,
5013                :    short         y2,
5014                :    int           *pOverlap)
5015     11  0.0120 :{ /* pixman_region_unionO total:     39  0.0425 */
5016                :    pixman_box16_t *     pNextRect;
5017                :    int        x1;     /* left and right side of current union */
5018                :    int        x2;
5019                :
5020                :    assert (y1 < y2);
5021                :    assert(r1 != r1End && r2 != r2End);
5022                :
5023      6  0.0065 :    pNextRect = PIXREGION_TOP(region);
5024                :
5025                :    /* Start off current rectangle */
5026                :    if (r1->x1 < r2->x1)
5027                :    {
5028                :        x1 = r1->x1;
5029                :        x2 = r1->x2;
5030                :        r1++;
5031                :    }
5032                :    else
5033                :    {
5034      1  0.0011 :        x1 = r2->x1;
5035      2  0.0022 :        x2 = r2->x2;
5036                :        r2++;
5037                :    }
5038      3  0.0033 :    while (r1 != r1End && r2 != r2End)
5039                :    {
5040                :        if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
5041                :    }
5042                :
5043                :    /* Finish off whoever (if any) is left */
5044                :    if (r1 != r1End)
5045                :    {
5046                :        do
5047                :        {
5048      8  0.0087 :            MERGERECT(r1);
5049      2  0.0022 :        } while (r1 != r1End);
5050                :    }
5051                :    else if (r2 != r2End)
5052                :    {
5053                :        do
5054                :        {
5055                :            MERGERECT(r2);
5056                :        } while (r2 != r2End);
5057                :    }
5058                :
5059                :    /* Add current rectangle */
5060      4  0.0044 :    NEWRECT(region, pNextRect, x1, y1, x2, y2);
5061                :
5062                :    return TRUE;
5063      2  0.0022 :}
5064                :
5065                :/* Convenience function for performing union of region with a
5066                : * single rectangle
5067                : */
5068                :pixman_bool_t
5069                :pixman_region_union_rect (pixman_region16_t *dest,
5070                :                          pixman_region16_t *source,
5071                :                          int x, int y,
5072                :                          unsigned int width, unsigned int height)
5073                :{
5074                :    pixman_region16_t region;
5075                :
5076                :    if (!width || !height)
5077                :        return pixman_region_copy (dest, source);
5078                :    region.data = NULL;
5079                :    region.extents.x1 = x;
5080                :    region.extents.y1 = y;
5081                :    region.extents.x2 = x + width;
5082                :    region.extents.y2 = y + height;
5083                :
5084                :    return pixman_region_union (dest, source, &region);
5085                :}
5086                :
5087                :pixman_bool_t
5088                :pixman_region_union (pixman_region16_t *newReg,
5089                :                     pixman_region16_t *reg1,
5090                :                     pixman_region16_t *reg2)
5091     17  0.0185 :{ /* pixman_region_union total:     87  0.0948 */
5092                :    int overlap; /* result ignored */
5093                :
5094                :    /* Return TRUE if some overlap
5095                :     * between reg1, reg2
5096                :     */
5097                :    good(reg1);
5098                :    good(reg2);
5099                :    good(newReg);
5100                :    /*  checks all the simple cases */
5101                :
5102                :    /*
5103                :     * Region 1 and 2 are the same
5104                :     */
5105                :    if (reg1 == reg2)
5106                :    {
5107                :        return pixman_region_copy(newReg, reg1);
5108                :    }
5109                :
5110                :    /*
5111                :     * Region 1 is empty
5112                :     */
5113      7  0.0076 :    if (PIXREGION_NIL(reg1))
5114                :    {
5115                :        if (PIXREGION_NAR(reg1))
5116                :            return pixman_break (newReg);
5117      1  0.0011 :        if (newReg != reg2)
5118      1  0.0011 :            return pixman_region_copy(newReg, reg2);
5119                :        return TRUE;
5120                :    }
5121                :
5122                :    /*
5123                :     * Region 2 is empty
5124                :     */
5125      9  0.0098 :    if (PIXREGION_NIL(reg2))
5126                :    {
5127                :        if (PIXREGION_NAR(reg2))
5128                :            return pixman_break (newReg);
5129                :        if (newReg != reg1)
5130                :            return pixman_region_copy(newReg, reg1);
5131                :        return TRUE;
5132                :    }
5133                :
5134                :    /*
5135                :     * Region 1 completely subsumes region 2
5136                :     */
5137      8  0.0087 :    if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))
5138                :    {
5139      7  0.0076 :        if (newReg != reg1)
5140                :            return pixman_region_copy(newReg, reg1);
5141                :        return TRUE;
5142                :    }
5143                :
5144                :    /*
5145                :     * Region 2 completely subsumes region 1
5146                :     */
5147      2  0.0022 :    if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))
5148                :    {
5149                :        if (newReg != reg2)
5150      1  0.0011 :            return pixman_region_copy(newReg, reg2);
5151                :        return TRUE;
5152                :    }
5153                :
5154      3  0.0033 :    if (!pixman_op(newReg, reg1, reg2, pixman_region_unionO, TRUE, TRUE, &overlap))
5155                :        return FALSE;
5156                :
5157      1  0.0011 :    newReg->extents.x1 = MIN(reg1->extents.x1, reg2->extents.x1);
5158      3  0.0033 :    newReg->extents.y1 = MIN(reg1->extents.y1, reg2->extents.y1);
5159      7  0.0076 :    newReg->extents.x2 = MAX(reg1->extents.x2, reg2->extents.x2);
5160      8  0.0087 :    newReg->extents.y2 = MAX(reg1->extents.y2, reg2->extents.y2);
5161                :    good(newReg);
5162      5  0.0054 :    return TRUE;
5163      7  0.0076 :}
5164                :
5165                :/*======================================================================
5166                : *          Batch Rectangle Union
5167                : *====================================================================*/
5168                :
5169                :/*-
5170                : *-----------------------------------------------------------------------
5171                : * pixman_region_append --
5172                : *
5173                : *      "Append" the rgn rectangles onto the end of dstrgn, maintaining
5174                : *      knowledge of YX-banding when it's easy.  Otherwise, dstrgn just
5175                : *      becomes a non-y-x-banded random collection of rectangles, and not
5176                : *      yet a true region.  After a sequence of appends, the caller must
5177                : *      call pixman_region_validate to ensure that a valid region is
5178                : *      constructed.
5179                : *
5180                : * Results:
5181                : *      TRUE if successful.
5182                : *
5183                : * Side Effects:
5184                : *      dstrgn is modified if rgn has rectangles.
5185                : *
5186                : */
5187                :pixman_bool_t
5188                :pixman_region_append (pixman_region16_t * dstrgn,
5189                :                      pixman_region16_t * rgn)
5190                :{
5191                :    int numRects, dnumRects, size;
5192                :    pixman_box16_t *new, *old;
5193                :    int prepend;
5194                :
5195                :    if (PIXREGION_NAR(rgn))
5196                :        return pixman_break (dstrgn);
5197                :
5198                :    if (!rgn->data && (dstrgn->data == pixman_region_emptyData))
5199                :    {
5200                :        dstrgn->extents = rgn->extents;
5201                :        dstrgn->data = (pixman_region16_data_t *)NULL;
5202                :        return TRUE;
5203                :    }
5204                :
5205                :    numRects = PIXREGION_NUM_RECTS(rgn);
5206                :    if (!numRects)
5207                :        return TRUE;
5208                :    prepend = FALSE;
5209                :    size = numRects;
5210                :    dnumRects = PIXREGION_NUM_RECTS(dstrgn);
5211                :    if (!dnumRects && (size < 200))
5212                :        size = 200; /* XXX pick numbers out of a hat */
5213                :    RECTALLOC(dstrgn, size);
5214                :    old = PIXREGION_RECTS(rgn);
5215                :    if (!dnumRects)
5216                :        dstrgn->extents = rgn->extents;
5217                :    else if (dstrgn->extents.x2 > dstrgn->extents.x1)
5218                :    {
5219                :        pixman_box16_t *first, *last;
5220                :
5221                :        first = old;
5222                :        last = PIXREGION_BOXPTR(dstrgn) + (dnumRects - 1);
5223                :        if ((first->y1 > last->y2) ||
5224                :            ((first->y1 == last->y1) && (first->y2 == last->y2) &&
5225                :             (first->x1 > last->x2)))
5226                :        {
5227                :            if (rgn->extents.x1 < dstrgn->extents.x1)
5228                :                dstrgn->extents.x1 = rgn->extents.x1;
5229                :            if (rgn->extents.x2 > dstrgn->extents.x2)
5230                :                dstrgn->extents.x2 = rgn->extents.x2;
5231                :            dstrgn->extents.y2 = rgn->extents.y2;
5232                :        }
5233                :        else
5234                :        {
5235                :            first = PIXREGION_BOXPTR(dstrgn);
5236                :            last = old + (numRects - 1);
5237                :            if ((first->y1 > last->y2) ||
5238                :                ((first->y1 == last->y1) && (first->y2 == last->y2) &&
5239                :                 (first->x1 > last->x2)))
5240                :            {
5241                :                prepend = TRUE;
5242                :                if (rgn->extents.x1 < dstrgn->extents.x1)
5243                :                    dstrgn->extents.x1 = rgn->extents.x1;
5244                :                if (rgn->extents.x2 > dstrgn->extents.x2)
5245                :                    dstrgn->extents.x2 = rgn->extents.x2;
5246                :                dstrgn->extents.y1 = rgn->extents.y1;
5247                :            }
5248                :            else
5249                :                dstrgn->extents.x2 = dstrgn->extents.x1;
5250                :        }
5251                :    }
5252                :    if (prepend)
5253                :    {
5254                :        new = PIXREGION_BOX(dstrgn, numRects);
5255                :        if (dnumRects == 1)
5256                :            *new = *PIXREGION_BOXPTR(dstrgn);
5257                :        else
5258                :            memmove((char *)new,(char *)PIXREGION_BOXPTR(dstrgn),
5259                :                  dnumRects * sizeof(pixman_box16_t));
5260                :        new = PIXREGION_BOXPTR(dstrgn);
5261                :    }
5262                :    else
5263                :        new = PIXREGION_BOXPTR(dstrgn) + dnumRects;
5264                :    if (numRects == 1)
5265                :        *new = *old;
5266                :    else
5267                :        memmove((char *)new, (char *)old, numRects * sizeof(pixman_box16_t));
5268                :    dstrgn->data->numRects += numRects;
5269                :    return TRUE;
5270                :}
5271                :
5272                :#define ExchangeRects(a, b) \
5273                :{                           \
5274                :    pixman_box16_t     t;           \
5275                :    t = rects[a];           \
5276                :    rects[a] = rects[b];    \
5277                :    rects[b] = t;           \
5278                :}
5279                :
5280                :static void
5281                :QuickSortRects(
5282                :    pixman_box16_t     rects[],
5283                :    int        numRects)
5284                :{
5285                :    int y1;
5286                :    int x1;
5287                :    int        i, j;
5288                :    pixman_box16_t *r;
5289                :
5290                :    /* Always called with numRects > 1 */
5291                :
5292                :    do
5293                :    {
5294                :        if (numRects == 2)
5295                :        {
5296                :            if (rects[0].y1 > rects[1].y1 ||
5297                :                    (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
5298                :                ExchangeRects(0, 1);
5299                :            return;
5300                :        }
5301                :
5302                :        /* Choose partition element, stick in location 0 */
5303                :        ExchangeRects(0, numRects >> 1);
5304                :        y1 = rects[0].y1;
5305                :        x1 = rects[0].x1;
5306                :
5307                :        /* Partition array */
5308                :        i = 0;
5309                :        j = numRects;
5310                :        do
5311                :        {
5312                :            r = &(rects[i]);
5313                :            do
5314                :            {
5315                :                r++;
5316                :                i++;
5317                :            } while (i != numRects &&
5318                :                     (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
5319                :            r = &(rects[j]);
5320                :            do
5321                :            {
5322                :                r--;
5323                :                j--;
5324                :            } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
5325                :            if (i < j)
5326                :                ExchangeRects(i, j);
5327                :        } while (i < j);
5328                :
5329                :        /* Move partition element back to middle */
5330                :        ExchangeRects(0, j);
5331                :
5332                :        /* Recurse */
5333                :        if (numRects-j-1 > 1)
5334                :            QuickSortRects(&rects[j+1], numRects-j-1);
5335                :        numRects = j;
5336                :    } while (numRects > 1);
5337                :}
5338                :
5339                :/*-
5340                : *-----------------------------------------------------------------------
5341                : * pixman_region_validate --
5342                : *
5343                : *      Take a ``region'' which is a non-y-x-banded random collection of
5344                : *      rectangles, and compute a nice region which is the union of all the
5345                : *      rectangles.
5346                : *
5347                : * Results:
5348                : *      TRUE if successful.
5349                : *
5350                : * Side Effects:
5351                : *      The passed-in ``region'' may be modified.
5352                : *      pOverlap set to TRUE if any retangles overlapped,
5353                : *      else FALSE;
5354                : *
5355                : * Strategy:
5356                : *      Step 1. Sort the rectangles into ascending order with primary key y1
5357                : *              and secondary key x1.
5358                : *
5359                : *      Step 2. Split the rectangles into the minimum number of proper y-x
5360                : *              banded regions.  This may require horizontally merging
5361                : *              rectangles, and vertically coalescing bands.  With any luck,
5362                : *              this step in an identity transformation (ala the Box widget),
5363                : *              or a coalescing into 1 box (ala Menus).
5364                : *
5365                : *      Step 3. Merge the separate regions down to a single region by calling
5366                : *              pixman_region_union.  Maximize the work each pixman_region_union call does by using
5367                : *              a binary merge.
5368                : *
5369                : *-----------------------------------------------------------------------
5370                : */
5371                :
5372                :pixman_bool_t
5373                :pixman_region_validate(pixman_region16_t * badreg,
5374                :                       int *pOverlap)
5375                :{
5376                :    /* Descriptor for regions under construction  in Step 2. */
5377                :    typedef struct {
5378                :        pixman_region16_t   reg;
5379                :        int         prevBand;
5380                :        int         curBand;
5381                :    } RegionInfo;
5382                :
5383                :             int        numRects;   /* Original numRects for badreg         */
5384                :             RegionInfo *ri;        /* Array of current regions             */
5385                :             int        numRI;      /* Number of entries used in ri         */
5386                :             int        sizeRI;     /* Number of entries available in ri    */
5387                :             int        i;          /* Index into rects                     */
5388                :    int j;          /* Index into ri                        */
5389                :    RegionInfo *rit;       /* &ri[j]                                */
5390                :    pixman_region16_t *  reg;        /* ri[j].reg                           */
5391                :    pixman_box16_t *    box;        /* Current box in rects                 */
5392                :    pixman_box16_t *    riBox;      /* Last box in ri[j].reg                */
5393                :    pixman_region16_t *  hreg;       /* ri[j_half].reg                      */
5394                :    pixman_bool_t ret = TRUE;
5395                :
5396                :    *pOverlap = FALSE;
5397                :    if (!badreg->data)
5398                :    {
5399                :        good(badreg);
5400                :        return TRUE;
5401                :    }
5402                :    numRects = badreg->data->numRects;
5403                :    if (!numRects)
5404                :    {
5405                :        if (PIXREGION_NAR(badreg))
5406                :            return FALSE;
5407                :        good(badreg);
5408                :        return TRUE;
5409                :    }
5410                :    if (badreg->extents.x1 < badreg->extents.x2)
5411                :    {
5412                :        if ((numRects) == 1)
5413                :        {
5414                :            freeData(badreg);
5415                :            badreg->data = (pixman_region16_data_t *) NULL;
5416                :        }
5417                :        else
5418                :        {
5419                :            DOWNSIZE(badreg, numRects);
5420                :        }
5421                :        good(badreg);
5422                :        return TRUE;
5423                :    }
5424                :
5425                :    /* Step 1: Sort the rects array into ascending (y1, x1) order */
5426                :    QuickSortRects(PIXREGION_BOXPTR(badreg), numRects);
5427                :
5428                :    /* Step 2: Scatter the sorted array into the minimum number of regions */
5429                :
5430                :    /* Set up the first region to be the first rectangle in badreg */
5431                :    /* Note that step 2 code will never overflow the ri[0].reg rects array */
5432                :    ri = (RegionInfo *) malloc(4 * sizeof(RegionInfo));
5433                :    if (!ri)
5434                :        return pixman_break (badreg);
5435                :    sizeRI = 4;
5436                :    numRI = 1;
5437                :    ri[0].prevBand = 0;
5438                :    ri[0].curBand = 0;
5439                :    ri[0].reg = *badreg;
5440                :    box = PIXREGION_BOXPTR(&ri[0].reg);
5441                :    ri[0].reg.extents = *box;
5442                :    ri[0].reg.data->numRects = 1;
5443                :
5444                :    /* Now scatter rectangles into the minimum set of valid regions.  If the
5445                :       next rectangle to be added to a region would force an existing rectangle
5446                :       in the region to be split up in order to maintain y-x banding, just
5447                :       forget it.  Try the next region.  If it doesn't fit cleanly into any
5448                :       region, make a new one. */
5449                :
5450                :    for (i = numRects; --i > 0;)
5451                :    {
5452                :        box++;
5453                :        /* Look for a region to append box to */
5454                :        for (j = numRI, rit = ri; --j >= 0; rit++)
5455                :        {
5456                :            reg = &rit->reg;
5457                :            riBox = PIXREGION_END(reg);
5458                :
5459                :            if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
5460                :            {
5461                :                /* box is in same band as riBox.  Merge or append it */
5462                :                if (box->x1 <= riBox->x2)
5463                :                {
5464                :                    /* Merge it with riBox */
5465                :                    if (box->x1 < riBox->x2) *pOverlap = TRUE;
5466                :                    if (box->x2 > riBox->x2) riBox->x2 = box->x2;
5467                :                }
5468                :                else
5469                :                {
5470                :                    RECTALLOC_BAIL(reg, 1, bail);
5471                :                    *PIXREGION_TOP(reg) = *box;
5472                :                    reg->data->numRects++;
5473                :                }
5474                :                goto NextRect;   /* So sue me */
5475                :            }
5476                :            else if (box->y1 >= riBox->y2)
5477                :            {
5478                :                /* Put box into new band */
5479                :                if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
5480                :                if (reg->extents.x1 > box->x1)   reg->extents.x1 = box->x1;
5481                :                Coalesce(reg, rit->prevBand, rit->curBand);
5482                :                rit->curBand = reg->data->numRects;
5483                :                RECTALLOC_BAIL(reg, 1, bail);
5484                :                *PIXREGION_TOP(reg) = *box;
5485                :                reg->data->numRects++;
5486                :                goto NextRect;
5487                :            }
5488                :            /* Well, this region was inappropriate.  Try the next one. */
5489                :        } /* for j */
5490                :
5491                :        /* Uh-oh.  No regions were appropriate.  Create a new one. */
5492                :        if (sizeRI == numRI)
5493                :        {
5494                :            /* Oops, allocate space for new region information */
5495                :            sizeRI <<= 1;
5496                :            rit = (RegionInfo *) realloc(ri, sizeRI * sizeof(RegionInfo));
5497                :            if (!rit)
5498                :                goto bail;
5499                :            ri = rit;
5500                :            rit = &ri[numRI];
5501                :        }
5502                :        numRI++;
5503                :        rit->prevBand = 0;
5504                :        rit->curBand = 0;
5505                :        rit->reg.extents = *box;
5506                :        rit->reg.data = (pixman_region16_data_t *)NULL;
5507                :        if (!pixman_rect_alloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
5508                :            goto bail;
5509                :NextRect: ;
5510                :    } /* for i */
5511                :
5512                :    /* Make a final pass over each region in order to Coalesce and set
5513                :       extents.x2 and extents.y2 */
5514                :
5515                :    for (j = numRI, rit = ri; --j >= 0; rit++)
5516                :    {
5517                :        reg = &rit->reg;
5518                :        riBox = PIXREGION_END(reg);
5519                :        reg->extents.y2 = riBox->y2;
5520                :        if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
5521                :        Coalesce(reg, rit->prevBand, rit->curBand);
5522                :        if (reg->data->numRects == 1) /* keep unions happy below */
5523                :        {
5524                :            freeData(reg);
5525                :            reg->data = (pixman_region16_data_t *)NULL;
5526                :        }
5527                :    }
5528                :
5529                :    /* Step 3: Union all regions into a single region */
5530                :    while (numRI > 1)
5531                :    {
5532                :        int half = numRI/2;
5533                :        for (j = numRI & 1; j < (half + (numRI & 1)); j++)
5534                :        {
5535                :            reg = &ri[j].reg;
5536                :            hreg = &ri[j+half].reg;
5537                :            if (!pixman_op(reg, reg, hreg, pixman_region_unionO, TRUE, TRUE, pOverlap))
5538                :                ret = FALSE;
5539                :            if (hreg->extents.x1 < reg->extents.x1)
5540                :                reg->extents.x1 = hreg->extents.x1;
5541                :            if (hreg->extents.y1 < reg->extents.y1)
5542                :                reg->extents.y1 = hreg->extents.y1;
5543                :            if (hreg->extents.x2 > reg->extents.x2)
5544                :                reg->extents.x2 = hreg->extents.x2;
5545                :            if (hreg->extents.y2 > reg->extents.y2)
5546                :                reg->extents.y2 = hreg->extents.y2;
5547                :            freeData(hreg);
5548                :        }
5549                :        numRI -= half;
5550                :    }
5551                :    *badreg = ri[0].reg;
5552                :    free(ri);
5553                :    good(badreg);
5554                :    return ret;
5555                :bail:
5556                :    for (i = 0; i < numRI; i++)
5557                :        freeData(&ri[i].reg);
5558                :    free (ri);
5559                :    return pixman_break (badreg);
5560                :}
5561                :
5562                :/*======================================================================
5563                : *                Region Subtraction
5564                : *====================================================================*/
5565                :
5566                :/*-
5567                : *-----------------------------------------------------------------------
5568                : * pixman_region_subtractO --
5569                : *      Overlapping band subtraction. x1 is the left-most point not yet
5570                : *      checked.
5571                : *
5572                : * Results:
5573                : *      TRUE if successful.
5574                : *
5575                : * Side Effects:
5576                : *      region may have rectangles added to it.
5577                : *
5578                : *-----------------------------------------------------------------------
5579                : */
5580                :/*ARGSUSED*/
5581                :static pixman_bool_t
5582                :pixman_region_subtractO (
5583                :    pixman_region16_t * region,
5584                :    pixman_box16_t *    r1,
5585                :    pixman_box16_t *            r1End,
5586                :    pixman_box16_t *    r2,
5587                :    pixman_box16_t *            r2End,
5588                :    short       y1,
5589                :             short      y2,
5590                :    int         *pOverlap)
5591                :{
5592                :    pixman_box16_t *    pNextRect;
5593                :    int         x1;
5594                :
5595                :    x1 = r1->x1;
5596                :
5597                :    assert(y1<y2);
5598                :    assert(r1 != r1End && r2 != r2End);
5599                :
5600                :    pNextRect = PIXREGION_TOP(region);
5601                :
5602                :    do
5603                :    {
5604                :        if (r2->x2 <= x1)
5605                :        {
5606                :            /*
5607                :             * Subtrahend entirely to left of minuend: go to next subtrahend.
5608                :             */
5609                :            r2++;
5610                :        }
5611                :        else if (r2->x1 <= x1)
5612                :        {
5613                :            /*
5614                :             * Subtrahend preceeds minuend: nuke left edge of minuend.
5615                :             */
5616                :            x1 = r2->x2;
5617                :            if (x1 >= r1->x2)
5618                :            {
5619                :                /*
5620                :                 * Minuend completely covered: advance to next minuend and
5621                :                 * reset left fence to edge of new minuend.
5622                :                 */
5623                :                r1++;
5624                :                if (r1 != r1End)
5625                :                    x1 = r1->x1;
5626                :            }
5627                :            else
5628                :            {
5629                :                /*
5630                :                 * Subtrahend now used up since it doesn't extend beyond
5631                :                 * minuend
5632                :                 */
5633                :                r2++;
5634                :            }
5635                :        }
5636                :        else if (r2->x1 < r1->x2)
5637                :        {
5638                :            /*
5639                :             * Left part of subtrahend covers part of minuend: add uncovered
5640                :             * part of minuend to region and skip to next subtrahend.
5641                :             */
5642                :            assert(x1<r2->x1);
5643                :            NEWRECT(region, pNextRect, x1, y1, r2->x1, y2);
5644                :
5645                :            x1 = r2->x2;
5646                :            if (x1 >= r1->x2)
5647                :            {
5648                :                /*
5649                :                 * Minuend used up: advance to new...
5650                :                 */
5651                :                r1++;
5652                :                if (r1 != r1End)
5653                :                    x1 = r1->x1;
5654                :            }
5655                :            else
5656                :            {
5657                :                /*
5658                :                 * Subtrahend used up
5659                :                 */
5660                :                r2++;
5661                :            }
5662                :        }
5663                :        else
5664                :        {
5665                :            /*
5666                :             * Minuend used up: add any remaining piece before advancing.
5667                :             */
5668                :            if (r1->x2 > x1)
5669                :                NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
5670                :            r1++;
5671                :            if (r1 != r1End)
5672                :                x1 = r1->x1;
5673                :        }
5674                :    } while ((r1 != r1End) && (r2 != r2End));
5675                :
5676                :    /*
5677                :     * Add remaining minuend rectangles to region.
5678                :     */
5679                :    while (r1 != r1End)
5680                :    {
5681                :        assert(x1<r1->x2);
5682                :        NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
5683                :        r1++;
5684                :        if (r1 != r1End)
5685                :            x1 = r1->x1;
5686                :    }
5687                :    return TRUE;
5688                :}
5689                :
5690                :/*-
5691                : *-----------------------------------------------------------------------
5692                : * pixman_region_subtract --
5693                : *      Subtract regS from regM and leave the result in regD.
5694                : *      S stands for subtrahend, M for minuend and D for difference.
5695                : *
5696                : * Results:
5697                : *      TRUE if successful.
5698                : *
5699                : * Side Effects:
5700                : *      regD is overwritten.
5701                : *
5702                : *-----------------------------------------------------------------------
5703                : */
5704                :pixman_bool_t
5705                :pixman_region_subtract(pixman_region16_t *      regD,
5706                :                       pixman_region16_t *      regM,
5707                :                       pixman_region16_t *      regS)
5708                :{
5709                :    int overlap; /* result ignored */
5710                :
5711                :    good(regM);
5712                :    good(regS);
5713                :    good(regD);
5714                :   /* check for trivial rejects */
5715                :    if (PIXREGION_NIL(regM) || PIXREGION_NIL(regS) ||
5716                :        !EXTENTCHECK(&regM->extents, &regS->extents))
5717                :    {
5718                :        if (PIXREGION_NAR (regS))
5719                :            return pixman_break (regD);
5720                :        return pixman_region_copy(regD, regM);
5721                :    }
5722                :    else if (regM == regS)
5723                :    {
5724                :        freeData(regD);
5725                :        regD->extents.x2 = regD->extents.x1;
5726                :        regD->extents.y2 = regD->extents.y1;
5727                :        regD->data = pixman_region_emptyData;
5728                :        return TRUE;
5729                :    }
5730                :
5731                :    /* Add those rectangles in region 1 that aren't in region 2,
5732                :       do yucky substraction for overlaps, and
5733                :       just throw away rectangles in region 2 that aren't in region 1 */
5734                :    if (!pixman_op(regD, regM, regS, pixman_region_subtractO, TRUE, FALSE, &overlap))
5735                :        return FALSE;
5736                :
5737                :    /*
5738                :     * Can't alter RegD's extents before we call pixman_op because
5739                :     * it might be one of the source regions and pixman_op depends
5740                :     * on the extents of those regions being unaltered. Besides, this
5741                :     * way there's no checking against rectangles that will be nuked
5742                :     * due to coalescing, so we have to examine fewer rectangles.
5743                :     */
5744                :    pixman_set_extents(regD);
5745                :    good(regD);
5746                :    return TRUE;
5747                :}
5748                :
5749                :/*======================================================================
5750                : *          Region Inversion
5751                : *====================================================================*/
5752                :
5753                :/*-
5754                : *-----------------------------------------------------------------------
5755                : * pixman_region_inverse --
5756                : *      Take a region and a box and return a region that is everything
5757                : *      in the box but not in the region. The careful reader will note
5758                : *      that this is the same as subtracting the region from the box...
5759                : *
5760                : * Results:
5761                : *      TRUE.
5762                : *
5763                : * Side Effects:
5764                : *      newReg is overwritten.
5765                : *
5766                : *-----------------------------------------------------------------------
5767                : */
5768                :pixman_bool_t
5769                :pixman_region_inverse(pixman_region16_t *         newReg,       /* Destination region */
5770                :                      pixman_region16_t *         reg1,         /* Region to invert */
5771                :                      pixman_box16_t *            invRect)      /* Bounding box for inversion */
5772                :{
5773                :    pixman_region16_t     invReg;       /* Quick and dirty region made from the
5774                :                                 * bounding box */
5775                :    int   overlap;      /* result ignored */
5776                :
5777                :    good(reg1);
5778                :    good(newReg);
5779                :   /* check for trivial rejects */
5780                :    if (PIXREGION_NIL(reg1) || !EXTENTCHECK(invRect, &reg1->extents))
5781                :    {
5782                :        if (PIXREGION_NAR(reg1))
5783                :            return pixman_break (newReg);
5784                :        newReg->extents = *invRect;
5785                :        freeData(newReg);
5786                :        newReg->data = (pixman_region16_data_t *)NULL;
5787                :        return TRUE;
5788                :    }
5789                :
5790                :    /* Add those rectangles in region 1 that aren't in region 2,
5791                :       do yucky substraction for overlaps, and
5792                :       just throw away rectangles in region 2 that aren't in region 1 */
5793                :    invReg.extents = *invRect;
5794                :    invReg.data = (pixman_region16_data_t *)NULL;
5795                :    if (!pixman_op(newReg, &invReg, reg1, pixman_region_subtractO, TRUE, FALSE, &overlap))
5796                :        return FALSE;
5797                :
5798                :    /*
5799                :     * Can't alter newReg's extents before we call pixman_op because
5800                :     * it might be one of the source regions and pixman_op depends
5801                :     * on the extents of those regions being unaltered. Besides, this
5802                :     * way there's no checking against rectangles that will be nuked
5803                :     * due to coalescing, so we have to examine fewer rectangles.
5804                :     */
5805                :    pixman_set_extents(newReg);
5806                :    good(newReg);
5807                :    return TRUE;
5808                :}
5809                :
5810                :/*
5811                : *   RectIn(region, rect)
5812                : *   This routine takes a pointer to a region and a pointer to a box
5813                : *   and determines if the box is outside/inside/partly inside the region.
5814                : *
5815                : *   The idea is to travel through the list of rectangles trying to cover the
5816                : *   passed box with them. Anytime a piece of the rectangle isn't covered
5817                : *   by a band of rectangles, partOut is set TRUE. Any time a rectangle in
5818                : *   the region covers part of the box, partIn is set TRUE. The process ends
5819                : *   when either the box has been completely covered (we reached a band that
5820                : *   doesn't overlap the box, partIn is TRUE and partOut is false), the
5821                : *   box has been partially covered (partIn == partOut == TRUE -- because of
5822                : *   the banding, the first time this is true we know the box is only
5823                : *   partially in the region) or is outside the region (we reached a band
5824                : *   that doesn't overlap the box at all and partIn is false)
5825                : */
5826                :
5827                :pixman_region_overlap_t
5828                :pixman_region_contains_rectangle(pixman_region16_t *  region,
5829                :                                 pixman_box16_t *     prect)
5830                :{
5831                :    int x;
5832                :    int y;
5833                :    pixman_box16_t *     pbox;
5834                :    pixman_box16_t *     pboxEnd;
5835                :    int                 partIn, partOut;
5836                :    int                 numRects;
5837                :
5838                :    good(region);
5839                :    numRects = PIXREGION_NUM_RECTS(region);
5840                :    /* useful optimization */
5841                :    if (!numRects || !EXTENTCHECK(&region->extents, prect))
5842                :        return(PIXMAN_REGION_OUT);
5843                :
5844                :    if (numRects == 1)
5845                :    {
5846                :        /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */
5847                :        if (SUBSUMES(&region->extents, prect))
5848                :            return(PIXMAN_REGION_IN);
5849                :        else
5850                :            return(PIXMAN_REGION_PART);
5851                :    }
5852                :
5853                :    partOut = FALSE;
5854                :    partIn = FALSE;
5855                :
5856                :    /* (x,y) starts at upper left of rect, moving to the right and down */
5857                :    x = prect->x1;
5858                :    y = prect->y1;
5859                :
5860                :    /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */
5861                :    for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
5862                :         pbox != pboxEnd;
5863                :         pbox++)
5864                :    {
5865                :
5866                :        if (pbox->y2 <= y)
5867                :           continue;    /* getting up to speed or skipping remainder of band */
5868                :
5869                :        if (pbox->y1 > y)
5870                :        {
5871                :           partOut = TRUE;      /* missed part of rectangle above */
5872                :           if (partIn || (pbox->y1 >= prect->y2))
5873                :              break;
5874                :           y = pbox->y1;        /* x guaranteed to be == prect->x1 */
5875                :        }
5876                :
5877                :        if (pbox->x2 <= x)
5878                :           continue;            /* not far enough over yet */
5879                :
5880                :        if (pbox->x1 > x)
5881                :        {
5882                :           partOut = TRUE;      /* missed part of rectangle to left */
5883                :           if (partIn)
5884                :              break;
5885                :        }
5886                :
5887                :        if (pbox->x1 < prect->x2)
5888                :        {
5889                :            partIn = TRUE;      /* definitely overlap */
5890                :            if (partOut)
5891                :               break;
5892                :        }
5893                :
5894                :        if (pbox->x2 >= prect->x2)
5895                :        {
5896                :           y = pbox->y2;        /* finished with this band */
5897                :           if (y >= prect->y2)
5898                :              break;
5899                :           x = prect->x1;       /* reset x out to left again */
5900                :        }
5901                :        else
5902                :        {
5903                :            /*
5904                :             * Because boxes in a band are maximal width, if the first box
5905                :             * to overlap the rectangle doesn't completely cover it in that
5906                :             * band, the rectangle must be partially out, since some of it
5907                :             * will be uncovered in that band. partIn will have been set true
5908                :             * by now...
5909                :             */
5910                :            partOut = TRUE;
5911                :            break;
5912                :        }
5913                :    }
5914                :
5915                :    if (partIn)
5916                :    {
5917                :        if (y < prect->y2)
5918                :            return PIXMAN_REGION_PART;
5919                :        else
5920                :            return PIXMAN_REGION_IN;
5921                :    }
5922                :    else
5923                :    {
5924                :        return PIXMAN_REGION_OUT;
5925                :    }
5926                :}
5927                :
5928                :/* pixman_region_translate (region, x, y)
5929                :   translates in place
5930                :*/
5931                :
5932                :void
5933                :pixman_region_translate (pixman_region16_t * region, int x, int y)
5934      1  0.0011 :{ /* pixman_region_translate total:      7  0.0076 */
5935                :    int x1, x2, y1, y2;
5936                :    int nbox;
5937                :    pixman_box16_t * pbox;
5938                :
5939                :    good(region);
5940                :    region->extents.x1 = x1 = region->extents.x1 + x;
5941      1  0.0011 :    region->extents.y1 = y1 = region->extents.y1 + y;
5942                :    region->extents.x2 = x2 = region->extents.x2 + x;
5943      1  0.0011 :    region->extents.y2 = y2 = region->extents.y2 + y;
5944      1  0.0011 :    if (((x1 - SHRT_MIN)|(y1 - SHRT_MIN)|(SHRT_MAX - x2)|(SHRT_MAX - y2)) >= 0)
5945                :    {
5946      1  0.0011 :        if (region->data && (nbox = region->data->numRects))
5947                :        {
5948                :            for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
5949                :            {
5950                :                pbox->x1 += x;
5951                :                pbox->y1 += y;
5952                :                pbox->x2 += x;
5953                :                pbox->y2 += y;
5954                :            }
5955                :        }
5956                :        return;
5957                :    }
5958                :    if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|(SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0)
5959                :    {
5960                :        region->extents.x2 = region->extents.x1;
5961                :        region->extents.y2 = region->extents.y1;
5962                :        freeData(region);
5963                :        region->data = pixman_region_emptyData;
5964                :        return;
5965                :    }
5966                :    if (x1 < SHRT_MIN)
5967                :        region->extents.x1 = SHRT_MIN;
5968                :    else if (x2 > SHRT_MAX)
5969                :        region->extents.x2 = SHRT_MAX;
5970                :    if (y1 < SHRT_MIN)
5971                :        region->extents.y1 = SHRT_MIN;
5972                :    else if (y2 > SHRT_MAX)
5973                :        region->extents.y2 = SHRT_MAX;
5974                :    if (region->data && (nbox = region->data->numRects))
5975                :    {
5976                :        pixman_box16_t * pboxout;
5977                :
5978                :        for (pboxout = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
5979                :        {
5980                :            pboxout->x1 = x1 = pbox->x1 + x;
5981                :            pboxout->y1 = y1 = pbox->y1 + y;
5982                :            pboxout->x2 = x2 = pbox->x2 + x;
5983                :            pboxout->y2 = y2 = pbox->y2 + y;
5984                :            if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|
5985                :                 (SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0)
5986                :            {
5987                :                region->data->numRects--;
5988                :                continue;
5989                :            }
5990                :            if (x1 < SHRT_MIN)
5991                :                pboxout->x1 = SHRT_MIN;
5992                :            else if (x2 > SHRT_MAX)
5993                :                pboxout->x2 = SHRT_MAX;
5994                :            if (y1 < SHRT_MIN)
5995                :                pboxout->y1 = SHRT_MIN;
5996                :            else if (y2 > SHRT_MAX)
5997                :                pboxout->y2 = SHRT_MAX;
5998                :            pboxout++;
5999                :        }
6000                :        if (pboxout != pbox)
6001                :        {
6002                :            if (region->data->numRects == 1)
6003                :            {
6004                :                region->extents = *PIXREGION_BOXPTR(region);
6005                :                freeData(region);
6006                :                region->data = (pixman_region16_data_t *)NULL;
6007                :            }
6008                :            else
6009                :                pixman_set_extents(region);
6010                :        }
6011                :    }
6012      2  0.0022 :}
6013                :
6014                :/* XXX: Do we need this?
6015                :static pixman_bool_t
6016                :pixman_region16_data_copy(pixman_region16_t * dst, pixman_region16_t * src)
6017                :{
6018                :    good(dst);
6019                :    good(src);
6020                :    if (dst->data)
6021                :        return TRUE;
6022                :    if (dst == src)
6023                :        return TRUE;
6024                :    if (!src->data || !src->data->size)
6025                :    {
6026                :        freeData(dst);
6027                :        dst->data = (pixman_region16_data_t *)NULL;
6028                :        return TRUE;
6029                :    }
6030                :    if (!dst->data || (dst->data->size < src->data->numRects))
6031                :    {
6032                :        freeData(dst);
6033                :        dst->data = allocData(src->data->numRects);
6034                :        if (!dst->data)
6035                :            return pixman_break (dst);
6036                :    }
6037                :    dst->data->size = src->data->size;
6038                :    dst->data->numRects = src->data->numRects;
6039                :    return TRUE;
6040                :}
6041                :*/
6042                :
6043                :void
6044                :pixman_region_reset(pixman_region16_t *region, pixman_box16_t *box)
6045                :{
6046                :    good(region);
6047                :    assert(box->x1<=box->x2);
6048                :    assert(box->y1<=box->y2);
6049                :    region->extents = *box;
6050                :    freeData(region);
6051                :    region->data = (pixman_region16_data_t *)NULL;
6052                :}
6053                :
6054                :/* box is "return" value */
6055                :int
6056                :pixman_region_contains_point(pixman_region16_t * region,
6057                :                             int x, int y,
6058                :                             pixman_box16_t * box)
6059                :{
6060                :    pixman_box16_t *pbox, *pboxEnd;
6061                :    int numRects;
6062                :
6063                :    good(region);
6064                :    numRects = PIXREGION_NUM_RECTS(region);
6065                :    if (!numRects || !INBOX(&region->extents, x, y))
6066                :        return(FALSE);
6067                :    if (numRects == 1)
6068                :    {
6069                :        *box = region->extents;
6070                :        return(TRUE);
6071                :    }
6072                :    for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
6073                :         pbox != pboxEnd;
6074                :         pbox++)
6075                :    {
6076                :        if (y >= pbox->y2)
6077                :           continue;            /* not there yet */
6078                :        if ((y < pbox->y1) || (x < pbox->x1))
6079                :           break;               /* missed it */
6080                :        if (x >= pbox->x2)
6081                :           continue;            /* not there yet */
6082                :        *box = *pbox;
6083                :        return(TRUE);
6084                :    }
6085                :    return(FALSE);
6086                :}
6087                :
6088                :int
6089                :pixman_region_not_empty(pixman_region16_t * region)
6090      9  0.0098 :{ /* pixman_region_not_empty total:     17  0.0185 */
6091                :    good(region);
6092      5  0.0054 :    return(!PIXREGION_NIL(region));
6093      3  0.0033 :}
6094                :
6095                :/* XXX: Do we need this?
6096                :static int
6097                :pixman_region16_broken(pixman_region16_t * region)
6098                :{
6099                :    good(region);
6100                :    return (PIXREGION_NAR(region));
6101                :}
6102                :*/
6103                :
6104                :void
6105                :pixman_region_empty(pixman_region16_t * region)
6106                :{
6107                :    good(region);
6108                :    freeData(region);
6109                :    region->extents.x2 = region->extents.x1;
6110                :    region->extents.y2 = region->extents.y1;
6111                :    region->data = pixman_region_emptyData;
6112                :}
6113                :
6114                :pixman_box16_t *
6115                :pixman_region_extents(pixman_region16_t * region)
6116                :{
6117                :    good(region);
6118                :    return(&region->extents);
6119                :}
6120                :
6121                :#define ExchangeSpans(a, b)                                 \
6122                :{                                                           \
6123                :    pixman_region16_point_t tpt;                                            \
6124                :    int    tw;                                              \
6125                :                                                            \
6126                :    tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt;    \
6127                :    tw = widths[a]; widths[a] = widths[b]; widths[b] = tw;  \
6128                :}
6129                :
6130                :/* ||| I should apply the merge sort code to rectangle sorting above, and see
6131                :   if mapping time can be improved.  But right now I've been at work 12 hours,
6132                :   so forget it.
6133                :*/
6134                :
6135                :static void QuickSortSpans(
6136                :    pixman_region16_point_t spans[],
6137                :    int     widths[],
6138                :    int     numSpans)
6139                :{
6140                :    int     y;
6141                :    int     i, j, m;
6142                :    pixman_region16_point_t *r;
6143                :
6144                :    /* Always called with numSpans > 1 */
6145                :    /* Sorts only by y, doesn't bother to sort by x */
6146                :
6147                :    do
6148                :    {
6149                :        if (numSpans < 9)
6150                :        {
6151                :            /* Do insertion sort */
6152                :            int yprev;
6153                :
6154                :            yprev = spans[0].y;
6155                :            i = 1;
6156                :            do
6157                :            { /* while i != numSpans */
6158                :                y = spans[i].y;
6159                :                if (yprev > y)
6160                :                {
6161                :                    /* spans[i] is out of order.  Move into proper location. */
6162                :                    pixman_region16_point_t tpt;
6163                :                    int     tw, k;
6164                :
6165                :                    for (j = 0; y >= spans[j].y; j++) {}
6166                :                    tpt = spans[i];
6167                :                    tw  = widths[i];
6168                :                    for (k = i; k != j; k--)
6169                :                    {
6170                :                        spans[k] = spans[k-1];
6171                :                        widths[k] = widths[k-1];
6172                :                    }
6173                :                    spans[j] = tpt;
6174                :                    widths[j] = tw;
6175                :                    y = spans[i].y;
6176                :                } /* if out of order */
6177                :                yprev = y;
6178                :                i++;
6179                :            } while (i != numSpans);
6180                :            return;
6181                :        }
6182                :
6183                :        /* Choose partition element, stick in location 0 */
6184                :        m = numSpans / 2;
6185                :        if (spans[m].y > spans[0].y)            ExchangeSpans(m, 0);
6186                :        if (spans[m].y > spans[numSpans-1].y)   ExchangeSpans(m, numSpans-1);
6187                :        if (spans[m].y > spans[0].y)            ExchangeSpans(m, 0);
6188                :        y = spans[0].y;
6189                :
6190                :        /* Partition array */
6191                :        i = 0;
6192                :        j = numSpans;
6193                :        do
6194                :        {
6195                :            r = &(spans[i]);
6196                :            do
6197                :            {
6198                :                r++;
6199                :                i++;
6200                :            } while (i != numSpans && r->y < y);
6201                :            r = &(spans[j]);
6202                :            do
6203                :            {
6204                :                r--;
6205                :                j--;
6206                :            } while (y < r->y);
6207                :            if (i < j)
6208                :                ExchangeSpans(i, j);
6209                :        } while (i < j);
6210                :
6211                :        /* Move partition element back to middle */
6212                :        ExchangeSpans(0, j);
6213                :
6214                :        /* Recurse */
6215                :        if (numSpans-j-1 > 1)
6216                :            QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
6217                :        numSpans = j;
6218                :    } while (numSpans > 1);
6219                :}
6220                :
6221                :#define NextBand()                                                  \
6222                :{                                                                   \
6223                :    clipy1 = pboxBandStart->y1;                                     \
6224                :    clipy2 = pboxBandStart->y2;                                     \
6225                :    pboxBandEnd = pboxBandStart + 1;                                \
6226                :    while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) {  \
6227                :        pboxBandEnd++;                                              \
6228                :    }                                                               \
6229                :    for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \
6230                :}
6231                :
6232                :/*
6233                :    Clip a list of scanlines to a region.  The caller has allocated the
6234                :    space.  FSorted is non-zero if the scanline origins are in ascending
6235                :    order.
6236                :    returns the number of new, clipped scanlines.
6237                :*/
6238                :
6239                :#ifdef XXX_DO_WE_NEED_THIS
6240                :static int
6241                :pixman_region16_clip_spans(
6242                :    pixman_region16_t           *prgnDst,
6243                :    pixman_region16_point_t     *ppt,
6244                :    int                 *pwidth,
6245                :    int                 nspans,
6246                :    pixman_region16_point_t     *pptNew,
6247                :    int                 *pwidthNew,
6248                :    int                 fSorted)
6249                :{
6250                :    pixman_region16_point_t     *pptLast;
6251                :    int                 *pwidthNewStart;        /* the vengeance of Xerox! */
6252                :    int y, x1, x2;
6253                :    int numRects;
6254                :
6255                :    good(prgnDst);
6256                :    pptLast = ppt + nspans;
6257                :    pwidthNewStart = pwidthNew;
6258                :
6259                :    if (!prgnDst->data)
6260                :    {
6261                :        /* Do special fast code with clip boundaries in registers(?) */
6262                :        /* It doesn't pay much to make use of fSorted in this case,
6263                :           so we lump everything together. */
6264                :
6265                :           int clipx1, clipx2, clipy1, clipy2;
6266                :
6267                :        clipx1 = prgnDst->extents.x1;
6268                :        clipy1 = prgnDst->extents.y1;
6269                :        clipx2 = prgnDst->extents.x2;
6270                :        clipy2 = prgnDst->extents.y2;
6271                :
6272                :        for (; ppt != pptLast; ppt++, pwidth++)
6273                :        {
6274                :            y = ppt->y;
6275                :            x1 = ppt->x;
6276                :            if (clipy1 <= y && y < clipy2)
6277                :            {
6278                :                x2 = x1 + *pwidth;
6279                :                if (x1 < clipx1)    x1 = clipx1;
6280                :                if (x2 > clipx2)    x2 = clipx2;
6281                :                if (x1 < x2)
6282                :                {
6283                :                    /* part of span in clip rectangle */
6284                :                    pptNew->x = x1;
6285                :                    pptNew->y = y;
6286                :                    *pwidthNew = x2 - x1;
6287                :                    pptNew++;
6288                :                    pwidthNew++;
6289                :                }
6290                :            }
6291                :        } /* end for */
6292                :
6293                :    }
6294                :    else if ((numRects = prgnDst->data->numRects))
6295                :    {
6296                :        /* Have to clip against many boxes */
6297                :        pixman_box16_t *pboxBandStart, *pboxBandEnd;
6298                :        pixman_box16_t *pbox;
6299                :        pixman_box16_t *pboxLast;
6300                :        int     clipy1, clipy2;
6301                :
6302                :        /* In this case, taking advantage of sorted spans gains more than
6303                :           the sorting costs. */
6304                :        if ((! fSorted) && (nspans > 1))
6305                :            QuickSortSpans(ppt, pwidth, nspans);
6306                :
6307                :        pboxBandStart = PIXREGION_BOXPTR(prgnDst);
6308                :        pboxLast = pboxBandStart + numRects;
6309                :
6310                :        NextBand();
6311                :
6312                :        for (; ppt != pptLast; )
6313                :        {
6314                :            y = ppt->y;
6315                :            if (y < clipy2)
6316                :            {
6317                :                /* span is in the current band */
6318                :                pbox = pboxBandStart;
6319                :                x1 = ppt->x;
6320                :                x2 = x1 + *pwidth;
6321                :                do
6322                :                { /* For each box in band */
6323                :                    int    newx1, newx2;
6324                :
6325                :                    newx1 = x1;
6326                :                    newx2 = x2;
6327                :                    if (newx1 < pbox->x1)   newx1 = pbox->x1;
6328                :                    if (newx2 > pbox->x2)   newx2 = pbox->x2;
6329                :                    if (newx1 < newx2)
6330                :                    {
6331                :                        /* Part of span in clip rectangle */
6332                :                        pptNew->x = newx1;
6333                :                        pptNew->y = y;
6334                :                        *pwidthNew = newx2 - newx1;
6335                :                        pptNew++;
6336                :                        pwidthNew++;
6337                :                    }
6338                :                    pbox++;
6339                :                } while (pbox != pboxBandEnd);
6340                :                ppt++;
6341                :                pwidth++;
6342                :            }
6343                :            else
6344                :            {
6345                :                /* Move to next band, adjust ppt as needed */
6346                :                pboxBandStart = pboxBandEnd;
6347                :                if (pboxBandStart == pboxLast)
6348                :                    break; /* We're completely done */
6349                :                NextBand();
6350                :            }
6351                :        }
6352                :    }
6353                :    return (pwidthNew - pwidthNewStart);
6354                :}
6355                :
6356                :/* find the band in a region with the most rectangles */
6357                :static int
6358                :pixman_region16_find_max_band(pixman_region16_t * prgn)
6359                :{
6360                :    int nbox;
6361                :    pixman_box16_t * pbox;
6362                :    int nThisBand;
6363                :    int nMaxBand = 0;
6364                :    short yThisBand;
6365                :
6366                :    good(prgn);
6367                :    nbox = PIXREGION_NUM_RECTS(prgn);
6368                :    pbox = PIXREGION_RECTS(prgn);
6369                :
6370                :    while(nbox > 0)
6371                :    {
6372                :        yThisBand = pbox->y1;
6373                :        nThisBand = 0;
6374                :        while((nbox > 0) && (pbox->y1 == yThisBand))
6375                :        {
6376                :            nbox--;
6377                :            pbox++;
6378                :            nThisBand++;
6379                :        }
6380                :        if (nThisBand > nMaxBand)
6381                :            nMaxBand = nThisBand;
6382                :    }
6383                :    return (nMaxBand);
6384                :}
6385                :#endif /* XXX_DO_WE_NEED_THIS */
6386                :
6387                :
6388                :pixman_bool_t
6389                :pixman_region_selfcheck (reg)
6390                :    pixman_region16_t * reg;
6391                :{
6392                :    int i, numRects;
6393                :
6394                :    if ((reg->extents.x1 > reg->extents.x2) ||
6395                :        (reg->extents.y1 > reg->extents.y2))
6396                :        return FALSE;
6397                :    numRects = PIXREGION_NUM_RECTS(reg);
6398                :    if (!numRects)
6399                :        return ((reg->extents.x1 == reg->extents.x2) &&
6400                :                (reg->extents.y1 == reg->extents.y2) &&
6401                :                (reg->data->size || (reg->data == pixman_region_emptyData)));
6402                :    else if (numRects == 1)
6403                :        return (!reg->data);
6404                :    else
6405                :    {
6406                :        pixman_box16_t * pboxP, * pboxN;
6407                :        pixman_box16_t box;
6408                :
6409                :        pboxP = PIXREGION_RECTS(reg);
6410                :        box = *pboxP;
6411                :        box.y2 = pboxP[numRects-1].y2;
6412                :        pboxN = pboxP + 1;
6413                :        for (i = numRects; --i > 0; pboxP++, pboxN++)
6414                :        {
6415                :            if ((pboxN->x1 >= pboxN->x2) ||
6416                :                (pboxN->y1 >= pboxN->y2))
6417                :                return FALSE;
6418                :            if (pboxN->x1 < box.x1)
6419                :                box.x1 = pboxN->x1;
6420                :            if (pboxN->x2 > box.x2)
6421                :                box.x2 = pboxN->x2;
6422                :            if ((pboxN->y1 < pboxP->y1) ||
6423                :                ((pboxN->y1 == pboxP->y1) &&
6424                :                 ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2))))
6425                :                return FALSE;
6426                :        }
6427                :        return ((box.x1 == reg->extents.x1) &&
6428                :                (box.x2 == reg->extents.x2) &&
6429                :                (box.y1 == reg->extents.y1) &&
6430                :                (box.y2 == reg->extents.y2));
6431                :    }
6432                :}
6433                :
6434                :pixman_bool_t
6435                :pixman_region_init_rects (pixman_region16_t *region,
6436                :                          pixman_box16_t *boxes, int count)
6437                :{
6438                :    int overlap;
6439                :
6440                :    if (count == 1) {
6441                :       pixman_region_init_rect(region,
6442                :                               boxes[0].x1,
6443                :                               boxes[0].y1,
6444                :                               boxes[0].x2 - boxes[0].x1,
6445                :                               boxes[0].y2 - boxes[0].y1);
6446                :       return TRUE;
6447                :    }
6448                :
6449                :    pixman_region_init(region);
6450                :    if (!pixman_rect_alloc(region, count))
6451                :        return FALSE;
6452                :
6453                :    /* Copy in the rects */
6454                :    memcpy (PIXREGION_RECTS(region), boxes, sizeof(pixman_box16_t) * count);
6455                :    region->data->numRects = count;
6456                :
6457                :    /* Validate */
6458                :    region->extents.x1 = region->extents.x2 = 0;
6459                :    return pixman_region_validate (region, &overlap);
6460                :}
6461 /* 
6462  * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa_migration.c"
6463  * 
6464  *    335  0.3649
6465  */
6466
6467
6468                :/*
6469                : * Copyright Â© 2006 Intel Corporation
6470                : *
6471                : * Permission is hereby granted, free of charge, to any person obtaining a
6472                : * copy of this software and associated documentation files (the "Software"),
6473                : * to deal in the Software without restriction, including without limitation
6474                : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
6475                : * and/or sell copies of the Software, and to permit persons to whom the
6476                : * Software is furnished to do so, subject to the following conditions:
6477                : *
6478                : * The above copyright notice and this permission notice (including the next
6479                : * paragraph) shall be included in all copies or substantial portions of the
6480                : * Software.
6481                : *
6482                : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6483                : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6484                : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6485                : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6486                : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6487                : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6488                : * SOFTWARE.
6489                : *
6490                : * Authors:
6491                : *    Eric Anholt <eric@anholt.net>
6492                : *    Michel Dänzer <michel@tungstengraphics.com>
6493                : *
6494                : */
6495                :
6496                :#ifdef HAVE_DIX_CONFIG_H
6497                :#include <dix-config.h>
6498                :#endif
6499                :
6500                :#include <string.h>
6501                :
6502                :#include "exa_priv.h"
6503                :#include <X11/fonts/fontstruct.h>
6504                :#include "dixfontstr.h"
6505                :#include "exa.h"
6506                :#include "cw.h"
6507                :
6508                :#if DEBUG_MIGRATE
6509                :#define DBG_MIGRATE(a) ErrorF a
6510                :#else
6511                :#define DBG_MIGRATE(a)
6512                :#endif
6513                :
6514                :/**
6515                : * Returns TRUE if the pixmap is not movable.  This is the case where it's a
6516                : * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch
6517                : * pixmap created by some other X Server internals (the score says it's
6518                : * pinned).
6519                : */
6520                :static Bool
6521                :exaPixmapIsPinned (PixmapPtr pPix)
6522     11  0.0120 :{ /* exaPixmapIsPinned total:     45  0.0490 */
6523      7  0.0076 :    ExaPixmapPriv (pPix);
6524                :
6525     25  0.0272 :    return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
6526      2  0.0022 :}
6527                :
6528                :/**
6529                : * The fallback path for UTS/DFS failing is to just memcpy.  exaCopyDirtyToSys
6530                : * and exaCopyDirtyToFb both needed to do this loop.
6531                : */
6532                :static void
6533                :exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
6534                :              CARD8 *dst, int dst_pitch)
6535                : {
6536                :    int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
6537                :    int bytes = (pbox->x2 - pbox->x1) * cpp;
6538                :
6539                :    src += pbox->y1 * src_pitch + pbox->x1 * cpp;
6540                :    dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
6541                :
6542                :    for (i = pbox->y2 - pbox->y1; i; i--) {
6543                :        memcpy (dst, src, bytes);
6544                :        src += src_pitch;
6545                :        dst += dst_pitch;
6546                :    }
6547                :}
6548                : 
6549                :/**
6550                : * Returns TRUE if the pixmap is dirty (has been modified in its current
6551                : * location compared to the other), or lacks a private for tracking
6552                : * dirtiness.
6553                : */
6554                :static Bool
6555                :exaPixmapIsDirty (PixmapPtr pPix)
6556                :{
6557                :    ExaPixmapPriv (pPix);
6558                :
6559                :    return pExaPixmap == NULL ||
6560                :        REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage));
6561                :}
6562                :
6563                :/**
6564                : * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score
6565                : * to be considered "should be in framebuffer".  That's just anything that has
6566                : * had more acceleration than fallbacks, or has no score yet.
6567                : *
6568                : * Only valid if using a migration scheme that tracks score.
6569                : */
6570                :static Bool
6571                :exaPixmapShouldBeInFB (PixmapPtr pPix)
6572                :{
6573                :    ExaPixmapPriv (pPix);
6574                :
6575                :    if (exaPixmapIsPinned (pPix))
6576                :        return TRUE;
6577                :
6578                :    return pExaPixmap->score >= 0;
6579                :}
6580                :
6581                :/**
6582                : * If the pixmap is currently dirty, this copies at least the dirty area from
6583                : * the framebuffer  memory copy to the system memory copy.  Both areas must be
6584                : * allocated.
6585                : */
6586                :static void
6587                :exaCopyDirtyToSys (PixmapPtr pPixmap)
6588                :{
6589                :    ExaScreenPriv (pPixmap->drawable.pScreen);
6590                :    ExaPixmapPriv (pPixmap);
6591                :    RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage);
6592                :    CARD8 *save_ptr;
6593                :    int save_pitch;
6594                :    BoxPtr pBox = REGION_RECTS(pRegion);
6595                :    int nbox = REGION_NUM_RECTS(pRegion);
6596                :    Bool do_sync = FALSE;
6597                :
6598                :    save_ptr = pPixmap->devPrivate.ptr;
6599                :    save_pitch = pPixmap->devKind;
6600                :    pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
6601                :    pPixmap->devKind = pExaPixmap->fb_pitch;
6602                :
6603                :    while (nbox--) {
6604                :        pBox->x1 = max(pBox->x1, 0);
6605                :        pBox->y1 = max(pBox->y1, 0);
6606                :        pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
6607                :        pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
6608                :
6609                :        if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
6610                :            continue;
6611                :
6612                :        if (pExaScr->info->DownloadFromScreen == NULL ||
6613                :            !pExaScr->info->DownloadFromScreen (pPixmap,
6614                :                                                pBox->x1, pBox->y1,
6615                :                                                pBox->x2 - pBox->x1,
6616                :                                                pBox->y2 - pBox->y1,
6617                :                                                pExaPixmap->sys_ptr
6618                :                                                + pBox->y1 * pExaPixmap->sys_pitch
6619                :                                                + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8,
6620                :                                                pExaPixmap->sys_pitch))
6621                :        {
6622                :            exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
6623                :            exaMemcpyBox (pPixmap, pBox,
6624                :                          pExaPixmap->fb_ptr, pExaPixmap->fb_pitch,
6625                :                          pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
6626                :            exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
6627                :        }
6628                :        else
6629                :            do_sync = TRUE;
6630                :
6631                :        pBox++;
6632                :    }
6633                :
6634                :    /* Make sure the bits have actually landed, since we don't necessarily sync
6635                :     * when accessing pixmaps in system memory.
6636                :     */
6637                :    if (do_sync)
6638                :        exaWaitSync (pPixmap->drawable.pScreen);
6639                :
6640                :    pPixmap->devPrivate.ptr = save_ptr;
6641                :    pPixmap->devKind = save_pitch;
6642                :
6643                :    /* The previously damaged bits are now no longer damaged but valid */
6644                :    REGION_UNION(pPixmap->drawable.pScreen,
6645                :                 &pExaPixmap->validReg, &pExaPixmap->validReg, pRegion);
6646                :    DamageEmpty (pExaPixmap->pDamage);
6647                :}
6648                :
6649                :/**
6650                : * If the pixmap is currently dirty, this copies at least the dirty area from
6651                : * the system memory copy to the framebuffer memory copy.  Both areas must be
6652                : * allocated.
6653                : */
6654                :static void
6655                :exaCopyDirtyToFb (PixmapPtr pPixmap)
6656                :{
6657                :    ExaScreenPriv (pPixmap->drawable.pScreen);
6658                :    ExaPixmapPriv (pPixmap);
6659                :    RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage);
6660                :    CARD8 *save_ptr;
6661                :    int save_pitch;
6662                :    BoxPtr pBox = REGION_RECTS(pRegion);
6663                :    int nbox = REGION_NUM_RECTS(pRegion);
6664                :    Bool do_sync = FALSE;
6665                :
6666                :    save_ptr = pPixmap->devPrivate.ptr;
6667                :    save_pitch = pPixmap->devKind;
6668                :    pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
6669                :    pPixmap->devKind = pExaPixmap->fb_pitch;
6670                :
6671                :    while (nbox--) {
6672                :        pBox->x1 = max(pBox->x1, 0);
6673                :        pBox->y1 = max(pBox->y1, 0);
6674                :        pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
6675                :        pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
6676                :
6677                :        if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
6678                :            continue;
6679                :
6680                :        if (pExaScr->info->UploadToScreen == NULL ||
6681                :            !pExaScr->info->UploadToScreen (pPixmap,
6682                :                                            pBox->x1, pBox->y1,
6683                :                                            pBox->x2 - pBox->x1,
6684                :                                            pBox->y2 - pBox->y1,
6685                :                                            pExaPixmap->sys_ptr
6686                :                                            + pBox->y1 * pExaPixmap->sys_pitch
6687                :                                            + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8,
6688                :                                            pExaPixmap->sys_pitch))
6689                :        {
6690                :            exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
6691                :            exaMemcpyBox (pPixmap, pBox,
6692                :                          pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
6693                :                          pExaPixmap->fb_ptr, pExaPixmap->fb_pitch);
6694                :            exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
6695                :        }
6696                :        else
6697                :            do_sync = TRUE;
6698                :
6699                :        pBox++;
6700                :    }
6701                :
6702                :    if (do_sync)
6703                :        exaMarkSync (pPixmap->drawable.pScreen);
6704                :
6705                :    pPixmap->devPrivate.ptr = save_ptr;
6706                :    pPixmap->devKind = save_pitch;
6707                :
6708                :    /* The previously damaged bits are now no longer damaged but valid */
6709                :    REGION_UNION(pPixmap->drawable.pScreen,
6710                :                 &pExaPixmap->validReg, &pExaPixmap->validReg, pRegion);
6711                :    DamageEmpty (pExaPixmap->pDamage);
6712                :}
6713                :
6714                :/**
6715                : * Copies out important pixmap data and removes references to framebuffer area.
6716                : * Called when the memory manager decides it's time to kick the pixmap out of
6717                : * framebuffer entirely.
6718                : */
6719                :void
6720                :exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
6721                :{
6722                :    PixmapPtr pPixmap = area->privData;
6723                :    ExaPixmapPriv(pPixmap);
6724                :    RegionPtr pDamageReg = DamageRegion(pExaPixmap->pDamage);
6725                :
6726                :    DBG_MIGRATE (("Save %p (%p) (%dx%d) (%c)\n", pPixmap,
6727                :                  (void*)(ExaGetPixmapPriv(pPixmap)->area ?
6728                :                          ExaGetPixmapPriv(pPixmap)->area->offset : 0),
6729                :                  pPixmap->drawable.width,
6730                :                  pPixmap->drawable.height,
6731                :                  exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
6732                :
6733                :    if (exaPixmapIsOffscreen(pPixmap)) {
6734                :        exaCopyDirtyToSys (pPixmap);
6735                :        pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
6736                :        pPixmap->devKind = pExaPixmap->sys_pitch;
6737                :        pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
6738                :    }
6739                :
6740                :    pExaPixmap->fb_ptr = NULL;
6741                :    pExaPixmap->area = NULL;
6742                :
6743                :    /* Mark all valid bits as damaged, so they'll get copied to FB next time */
6744                :    REGION_UNION(pPixmap->drawable.pScreen, pDamageReg, pDamageReg,
6745                :                 &pExaPixmap->validReg);
6746                :}
6747                :
6748                :/**
6749                : * Allocates a framebuffer copy of the pixmap if necessary, and then copies
6750                : * any necessary pixmap data into the framebuffer copy and points the pixmap at
6751                : * it.
6752                : *
6753                : * Note that when first allocated, a pixmap will have FALSE dirty flag.
6754                : * This is intentional because pixmap data starts out undefined.  So if we move
6755                : * it in due to the first operation against it being accelerated, it will have
6756                : * undefined framebuffer contents that we didn't have to upload.  If we do
6757                : * moveouts (and moveins) after the first movein, then we will only have to copy
6758                : * back and forth if the pixmap was written to after the last synchronization of
6759                : * the two copies.  Then, at exaPixmapSave (when the framebuffer copy goes away)
6760                : * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
6761                : * all the data, since it's almost surely all valid now.
6762                : */
6763                :void
6764                :exaMoveInPixmap (PixmapPtr pPixmap)
6765     30  0.0327 :{ /* exaMoveInPixmap total:    133  0.1449 */
6766      4  0.0044 :    ScreenPtr   pScreen = pPixmap->drawable.pScreen;
6767     23  0.0251 :    ExaScreenPriv (pScreen);
6768     23  0.0251 :    ExaPixmapPriv (pPixmap);
6769                :
6770                :    /* If we're VT-switched away, no touching card memory allowed. */
6771     16  0.0174 :    if (pExaScr->swappedOut)
6772                :        return;
6773                :
6774                :    /* If we're already in FB, our work is done. */
6775     12  0.0131 :    if (exaPixmapIsOffscreen(pPixmap))
6776                :        return;
6777                :
6778                :    /* If we're not allowed to move, then fail. */
6779                :    if (exaPixmapIsPinned(pPixmap))
6780                :        return;
6781                :
6782                :    /* Don't migrate in pixmaps which are less than 8bpp.  This avoids a lot of
6783                :     * fragility in EXA, and <8bpp is probably not used enough any more to care
6784                :     * (at least, not in acceleratd paths).
6785                :     */
6786      1  0.0011 :    if (pPixmap->drawable.bitsPerPixel < 8)
6787                :        return;
6788                :
6789                :    if (pExaPixmap->area == NULL) {
6790      2  0.0022 :        pExaPixmap->area =
6791                :            exaOffscreenAlloc (pScreen, pExaPixmap->fb_size,
6792                :                               pExaScr->info->pixmapOffsetAlign, FALSE,
6793                :                               exaPixmapSave, (pointer) pPixmap);
6794                :        if (pExaPixmap->area == NULL)
6795                :            return;
6796                :
6797                :        pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
6798                :                                       pExaPixmap->area->offset;
6799                :    }
6800                :
6801                :    DBG_MIGRATE (("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap,
6802                :                  (ExaGetPixmapPriv(pPixmap)->area ?
6803                :                   ExaGetPixmapPriv(pPixmap)->area->offset : 0),
6804                :                  pPixmap->drawable.width,
6805                :                  pPixmap->drawable.height,
6806                :                  exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
6807                :
6808                :    exaCopyDirtyToFb (pPixmap);
6809                :
6810                :    if (pExaScr->hideOffscreenPixmapData)
6811                :        pPixmap->devPrivate.ptr = NULL;
6812                :    else
6813      1  0.0011 :        pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
6814      1  0.0011 :    pPixmap->devKind = pExaPixmap->fb_pitch;
6815      2  0.0022 :    pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
6816      9  0.0098 :}
6817                :
6818                :/**
6819                : * Switches the current active location of the pixmap to system memory, copying
6820                : * updated data out if necessary.
6821                : */
6822                :void
6823                :exaMoveOutPixmap (PixmapPtr pPixmap)
6824                :{
6825                :    ExaPixmapPriv (pPixmap);
6826                :
6827                :    if (exaPixmapIsPinned(pPixmap))
6828                :        return;
6829                :
6830                :    if (exaPixmapIsOffscreen(pPixmap)) {
6831                :
6832                :        DBG_MIGRATE (("<- %p (%p) (%dx%d) (%c)\n", pPixmap,
6833                :                      (void*)(ExaGetPixmapPriv(pPixmap)->area ?
6834                :                              ExaGetPixmapPriv(pPixmap)->area->offset : 0),
6835                :                      pPixmap->drawable.width,
6836                :                      pPixmap->drawable.height,
6837                :                      exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
6838                :
6839                :        exaCopyDirtyToSys (pPixmap);
6840                :
6841                :        pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
6842                :        pPixmap->devKind = pExaPixmap->sys_pitch;
6843                :        pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
6844                :    }
6845                :}
6846                :
6847                :/**
6848                : * For the "greedy" migration scheme, pushes the pixmap toward being located in
6849                : * framebuffer memory.
6850                : */
6851                :static void
6852                :exaMigrateTowardFb (PixmapPtr pPixmap)
6853                :{
6854                :    ExaPixmapPriv (pPixmap);
6855                :
6856                :    if (pExaPixmap == NULL) {
6857                :        DBG_MIGRATE(("UseScreen: ignoring exa-uncontrolled pixmap %p (%s)\n",
6858                :                     (pointer)pPixmap,
6859                :                     exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
6860                :        return;
6861                :    }
6862                :
6863                :    if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
6864                :        DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
6865                :                     (pointer)pPixmap));
6866                :        return;
6867                :    }
6868                :
6869                :    DBG_MIGRATE(("UseScreen %p score %d\n",
6870                :                 (pointer)pPixmap, pExaPixmap->score));
6871                :
6872                :    if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
6873                :        exaMoveInPixmap(pPixmap);
6874                :        pExaPixmap->score = 0;
6875                :    }
6876                :
6877                :    if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
6878                :        pExaPixmap->score++;
6879                :
6880                :    if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
6881                :        !exaPixmapIsOffscreen(pPixmap))
6882                :    {
6883                :        exaMoveInPixmap (pPixmap);
6884                :    }
6885                :
6886                :    ExaOffscreenMarkUsed (pPixmap);
6887                :}
6888                :
6889                :/**
6890                : * For the "greedy" migration scheme, pushes the pixmap toward being located in
6891                : * system memory.
6892                : */
6893                :static void
6894                :exaMigrateTowardSys (PixmapPtr pPixmap)
6895                :{
6896                :    ExaPixmapPriv (pPixmap);
6897                :
6898                :    if (pExaPixmap == NULL) {
6899                :        DBG_MIGRATE(("UseMem: ignoring exa-uncontrolled pixmap %p (%s)\n",
6900                :                     (pointer)pPixmap,
6901                :                     exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
6902                :        return;
6903                :    }
6904                :
6905                :    DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)pPixmap, pExaPixmap->score));
6906                :
6907                :    if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
6908                :        return;
6909                :
6910                :    if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
6911                :        pExaPixmap->score = 0;
6912                :
6913                :    if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
6914                :        pExaPixmap->score--;
6915                :
6916                :    if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
6917                :        exaMoveOutPixmap (pPixmap);
6918                :}
6919                :
6920                :/**
6921                : * If the pixmap has both a framebuffer and system memory copy, this function
6922                : * asserts that both of them are the same.
6923                : */
6924                :static Bool
6925                :exaAssertNotDirty (PixmapPtr pPixmap)
6926                :{
6927                :    ExaPixmapPriv (pPixmap);
6928                :    CARD8 *dst, *src;
6929                :    RegionPtr pValidReg = &pExaPixmap->validReg;
6930                :    int dst_pitch, src_pitch, cpp, y, nbox = REGION_NUM_RECTS(pValidReg);
6931                :    BoxPtr pBox = REGION_RECTS(pValidReg);
6932                :    Bool ret = TRUE;
6933                :
6934                :    if (!nbox || exaPixmapIsPinned(pPixmap) || pExaPixmap->fb_ptr == NULL)
6935                :        return ret;
6936                :
6937                :    dst_pitch = pExaPixmap->sys_pitch;
6938                :    src_pitch = pExaPixmap->fb_pitch;
6939                :    cpp = pPixmap->drawable.bitsPerPixel / 8;
6940                :
6941                :    exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
6942                :    while (nbox--) {
6943                :            int rowbytes;
6944                :
6945                :            pBox->x1 = max(pBox->x1, 0);
6946                :            pBox->y1 = max(pBox->y1, 0);
6947                :            pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
6948                :            pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
6949                :
6950                :            if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
6951                :                continue;
6952                :
6953                :            rowbytes = (pBox->x2 - pBox->x1) * cpp;
6954                :            src = pExaPixmap->fb_ptr + pBox->y1 * src_pitch + pBox->x1 * cpp;
6955                :            dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
6956                :
6957                :            for (y = pBox->y1; y < pBox->y2;
6958                :                 y++, src += src_pitch, dst += dst_pitch) {
6959                :                if (memcmp(dst, src, rowbytes) != 0) {
6960                :                    ret = FALSE;
6961                :                    exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2,
6962                :                                   pBox->y2);
6963                :                    break;
6964                :                }
6965                :            }
6966                :    }
6967                :    exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
6968                :
6969                :    return ret;
6970                :}
6971                :
6972                :/**
6973                : * Performs migration of the pixmaps according to the operation information
6974                : * provided in pixmaps and can_accel and the migration scheme chosen in the
6975                : * config file.
6976                : */
6977                :void
6978                :exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
6979     12  0.0131 :{ /* exaDoMigration total:    166  0.1808 */
6980                :    ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
6981     17  0.0185 :    ExaScreenPriv(pScreen);
6982                :    int i, j;
6983                :
6984      3  0.0033 :    if (! can_accel)
6985                :        return;
6986                :
6987                :    /* If this debugging flag is set, check each pixmap for whether it is marked
6988                :     * as clean, and if so, actually check if that's the case.  This should help
6989                :     * catch issues with failing to mark a drawable as dirty.  While it will
6990                :     * catch them late (after the operation happened), it at least explains what
6991                :     * went wrong, and instrumenting the code to find what operation happened
6992                :     * to the pixmap last shouldn't be hard.
6993                :     */
6994      9  0.0098 :    if (pExaScr->checkDirtyCorrectness) {
6995      1  0.0011 :        for (i = 0; i < npixmaps; i++) {
6996                :            if (!exaPixmapIsDirty (pixmaps[i].pPix) &&
6997                :                !exaAssertNotDirty (pixmaps[i].pPix))
6998                :                ErrorF("%s: Pixmap %d dirty but not marked as such!\n", __func__, i);
6999                :        }
7000                :    }
7001                :    /* If anything is pinned in system memory, we won't be able to
7002                :     * accelerate.
7003                :     */
7004     16  0.0174 :    for (i = 0; i < npixmaps; i++) {
7005     22  0.0240 :        if (exaPixmapIsPinned (pixmaps[i].pPix) &&
7006                :            !exaPixmapIsOffscreen (pixmaps[i].pPix))
7007                :        {
7008                :            return;
7009                :            EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix,
7010                :                      pixmaps[i].pPix->drawable.width,
7011                :                      pixmaps[i].pPix->drawable.height));
7012                :            can_accel = FALSE;
7013                :            break;
7014                :        }
7015                :    }
7016                :
7017      2  0.0022 :    if (pExaScr->migration == ExaMigrationSmart) {
7018                :        /* If we've got something as a destination that we shouldn't cause to
7019                :         * become newly dirtied, take the unaccelerated route.
7020                :         */
7021                :        for (i = 0; i < npixmaps; i++) {
7022                :            if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB (pixmaps[i].pPix) &&
7023                :                !exaPixmapIsDirty (pixmaps[i].pPix))
7024                :            {
7025                :                for (i = 0; i < npixmaps; i++) {
7026                :                    if (!exaPixmapIsDirty (pixmaps[i].pPix))
7027                :                        exaMoveOutPixmap (pixmaps[i].pPix);
7028                :                }
7029                :                return;
7030                :            }
7031                :        }
7032                :
7033                :        /* If we aren't going to accelerate, then we migrate everybody toward
7034                :         * system memory, and kick out if it's free.
7035                :         */
7036                :        if (!can_accel) {
7037                :            for (i = 0; i < npixmaps; i++) {
7038                :                exaMigrateTowardSys (pixmaps[i].pPix);
7039                :                if (!exaPixmapIsDirty (pixmaps[i].pPix))
7040                :                    exaMoveOutPixmap (pixmaps[i].pPix);
7041                :            }
7042                :            return;
7043                :        }
7044                :
7045                :        /* Finally, the acceleration path.  Move them all in. */
7046                :        for (i = 0; i < npixmaps; i++) {
7047                :            exaMigrateTowardFb(pixmaps[i].pPix);
7048                :            exaMoveInPixmap(pixmaps[i].pPix);
7049                :        }
7050                :    } else if (pExaScr->migration == ExaMigrationGreedy) {
7051                :        /* If we can't accelerate, either because the driver can't or because one of
7052                :         * the pixmaps is pinned in system memory, then we migrate everybody toward
7053                :         * system memory.
7054                :         *
7055                :         * We also migrate toward system if all pixmaps involved are currently in
7056                :         * system memory -- this can mitigate thrashing when there are significantly
7057                :         * more pixmaps active than would fit in memory.
7058                :         *
7059                :         * If not, then we migrate toward FB so that hopefully acceleration can
7060                :         * happen.
7061                :         */
7062                :        if (!can_accel) {
7063                :            for (i = 0; i < npixmaps; i++)
7064                :                exaMigrateTowardSys (pixmaps[i].pPix);
7065                :            return;
7066                :        }
7067                :
7068                :        for (i = 0; i < npixmaps; i++) {
7069                :            if (exaPixmapIsOffscreen(pixmaps[i].pPix)) {
7070                :                /* Found one in FB, so move all to FB. */
7071                :                for (j = 0; j < npixmaps; j++)
7072                :                    exaMigrateTowardFb(pixmaps[j].pPix);
7073                :                return;
7074                :            }
7075                :        }
7076                :
7077                :        /* Nobody's in FB, so move all away from FB. */
7078                :        for (i = 0; i < npixmaps; i++)
7079                :            exaMigrateTowardSys(pixmaps[i].pPix);
7080      3  0.0033 :    } else if (pExaScr->migration == ExaMigrationAlways) {
7081                :        /* Always move the pixmaps out if we can't accelerate.  If we can
7082                :         * accelerate, try to move them all in.  If that fails, then move them
7083                :         * back out.
7084                :         */
7085                :        if (!can_accel) {
7086                :            for (i = 0; i < npixmaps; i++)
7087                :                exaMoveOutPixmap(pixmaps[i].pPix);
7088                :            return;
7089                :        }
7090                :
7091                :        /* Now, try to move them all into FB */
7092     21  0.0229 :        for (i = 0; i < npixmaps; i++) {
7093     18  0.0196 :            exaMoveInPixmap(pixmaps[i].pPix);
7094     11  0.0120 :            ExaOffscreenMarkUsed (pixmaps[i].pPix);
7095                :        }
7096                :
7097                :        /* If we couldn't fit everything in, then kick back out */
7098      6  0.0065 :        for (i = 0; i < npixmaps; i++) {
7099     17  0.0185 :            if (!exaPixmapIsOffscreen(pixmaps[i].pPix)) {
7100                :                return;
7101                :                EXA_FALLBACK(("Pixmap %p (%dx%d) not in fb\n", pixmaps[i].pPix,
7102                :                              pixmaps[i].pPix->drawable.width,
7103                :                              pixmaps[i].pPix->drawable.height));
7104                :                for (j = 0; j < npixmaps; j++)
7105                :                    exaMoveOutPixmap(pixmaps[j].pPix);
7106                :                break;
7107                :            }
7108                :        }
7109                :    }
7110      8  0.0087 :}
7111 /* 
7112  * Total samples for file : "/home/cworth/src/xorg/xserver/render/mipict.c"
7113  * 
7114  *    267  0.2909
7115  */
7116
7117
7118                :/*
7119                : *
7120                : * Copyright Â© 1999 Keith Packard
7121                : *
7122                : * Permission to use, copy, modify, distribute, and sell this software and its
7123                : * documentation for any purpose is hereby granted without fee, provided that
7124                : * the above copyright notice appear in all copies and that both that
7125                : * copyright notice and this permission notice appear in supporting
7126                : * documentation, and that the name of Keith Packard not be used in
7127                : * advertising or publicity pertaining to distribution of the software without
7128                : * specific, written prior permission.  Keith Packard makes no
7129                : * representations about the suitability of this software for any purpose.  It
7130                : * is provided "as is" without express or implied warranty.
7131                : *
7132                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
7133                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
7134                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
7135                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
7136                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
7137                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
7138                : * PERFORMANCE OF THIS SOFTWARE.
7139                : */
7140                :
7141                :#ifdef HAVE_DIX_CONFIG_H
7142                :#include <dix-config.h>
7143                :#endif
7144                :
7145                :#include "scrnintstr.h"
7146                :#include "gcstruct.h"
7147                :#include "pixmapstr.h"
7148                :#include "windowstr.h"
7149                :#include "mi.h"
7150                :#include "picturestr.h"
7151                :#include "mipict.h"
7152                :
7153                :#ifndef __GNUC__
7154                :#define __inline
7155                :#endif
7156                :
7157                :int
7158                :miCreatePicture (PicturePtr pPicture)
7159      1  0.0011 :{ /* miCreatePicture total:      2  0.0022 */
7160                :    return Success;
7161      1  0.0011 :}
7162                :
7163                :void
7164                :miDestroyPicture (PicturePtr pPicture)
7165      3  0.0033 :{ /* miDestroyPicture total:      4  0.0044 */
7166                :    if (pPicture->freeCompClip)
7167      1  0.0011 :        REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->pCompositeClip);
7168                :}
7169                :
7170                :void
7171                :miDestroyPictureClip (PicturePtr pPicture)
7172                :{
7173                :    switch (pPicture->clientClipType) {
7174                :    case CT_NONE:
7175                :        return;
7176                :    case CT_PIXMAP:
7177                :        (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip));
7178                :        break;
7179                :    default:
7180                :        /*
7181                :         * we know we'll never have a list of rectangles, since ChangeClip
7182                :         * immediately turns them into a region
7183                :         */
7184                :        REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->clientClip);
7185                :        break;
7186                :    }
7187                :    pPicture->clientClip = NULL;
7188                :    pPicture->clientClipType = CT_NONE;
7189                :}    
7190                :
7191                :int
7192                :miChangePictureClip (PicturePtr    pPicture,
7193                :                     int           type,
7194                :                     pointer       value,
7195                :                     int           n)
7196                :{ /* miChangePictureClip total:      1  0.0011 */
7197                :    ScreenPtr           pScreen = pPicture->pDrawable->pScreen;
7198      1  0.0011 :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
7199                :    pointer             clientClip;
7200                :    int                 clientClipType;
7201                :    
7202                :    switch (type) {
7203                :    case CT_PIXMAP:
7204                :        /* convert the pixmap to a region */
7205                :        clientClip = (pointer) BITMAP_TO_REGION(pScreen, (PixmapPtr) value);
7206                :        if (!clientClip)
7207                :            return BadAlloc;
7208                :        clientClipType = CT_REGION;
7209                :        (*pScreen->DestroyPixmap) ((PixmapPtr) value);
7210                :        break;
7211                :    case CT_REGION:
7212                :        clientClip = value;
7213                :        clientClipType = CT_REGION;
7214                :        break;
7215                :    case CT_NONE:
7216                :        clientClip = 0;
7217                :        clientClipType = CT_NONE;
7218                :        break;
7219                :    default:
7220                :        clientClip = (pointer) RECTS_TO_REGION(pScreen, n,
7221                :                                               (xRectangle *) value,
7222                :                                               type);
7223                :        if (!clientClip)
7224                :            return BadAlloc;
7225                :        clientClipType = CT_REGION;
7226                :        xfree(value);
7227                :        break;
7228                :    }
7229                :    (*ps->DestroyPictureClip) (pPicture);
7230                :    pPicture->clientClip = clientClip;
7231                :    pPicture->clientClipType = clientClipType;
7232                :    pPicture->stateChanges |= CPClipMask;
7233                :    return Success;
7234                :}
7235                :
7236                :void
7237                :miChangePicture (PicturePtr pPicture,
7238                :                 Mask       mask)
7239                :{ /* miChangePicture total:      1  0.0011 */
7240                :    return;
7241      1  0.0011 :}
7242                :
7243                :void
7244                :miValidatePicture (PicturePtr pPicture,
7245                :                   Mask       mask)
7246      3  0.0033 :{ /* miValidatePicture total:      9  0.0098 */
7247                :    DrawablePtr     pDrawable = pPicture->pDrawable;
7248                :
7249                :    if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) ||
7250                :        (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS)))
7251                :    {
7252      1  0.0011 :        if (pDrawable->type == DRAWABLE_WINDOW)
7253                :        {
7254                :            WindowPtr       pWin = (WindowPtr) pDrawable;
7255                :            RegionPtr       pregWin;
7256                :            Bool            freeTmpClip, freeCompClip;
7257                :
7258                :            if (pPicture->subWindowMode == IncludeInferiors)
7259                :            {
7260                :                pregWin = NotClippedByChildren(pWin);
7261                :                freeTmpClip = TRUE;
7262                :            }
7263                :            else
7264                :            {
7265                :                pregWin = &pWin->clipList;
7266                :                freeTmpClip = FALSE;
7267                :            }
7268                :            freeCompClip = pPicture->freeCompClip;
7269                :
7270                :            /*
7271                :             * if there is no client clip, we can get by with just keeping the
7272                :             * pointer we got, and remembering whether or not should destroy
7273                :             * (or maybe re-use) it later.  this way, we avoid unnecessary
7274                :             * copying of regions.  (this wins especially if many clients clip
7275                :             * by children and have no client clip.)
7276                :             */
7277                :            if (pPicture->clientClipType == CT_NONE)
7278                :            {
7279                :                if (freeCompClip)
7280                :                    REGION_DESTROY(pScreen, pPicture->pCompositeClip);
7281                :                pPicture->pCompositeClip = pregWin;
7282                :                pPicture->freeCompClip = freeTmpClip;
7283                :            }
7284                :            else
7285                :            {
7286                :                /*
7287                :                 * we need one 'real' region to put into the composite clip. if
7288                :                 * pregWin the current composite clip are real, we can get rid of
7289                :                 * one. if pregWin is real and the current composite clip isn't,
7290                :                 * use pregWin for the composite clip. if the current composite
7291                :                 * clip is real and pregWin isn't, use the current composite
7292                :                 * clip. if neither is real, create a new region.
7293                :                 */
7294                :
7295                :                REGION_TRANSLATE(pScreen, pPicture->clientClip,
7296                :                                 pDrawable->x + pPicture->clipOrigin.x,
7297                :                                 pDrawable->y + pPicture->clipOrigin.y);
7298                :
7299                :                if (freeCompClip)
7300                :                {
7301                :                    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
7302                :                                     pregWin, pPicture->clientClip);
7303                :                    if (freeTmpClip)
7304                :                        REGION_DESTROY(pScreen, pregWin);
7305                :                }
7306                :                else if (freeTmpClip)
7307                :                {
7308                :                    REGION_INTERSECT(pScreen, pregWin, pregWin, pPicture->clientClip);
7309                :                    pPicture->pCompositeClip = pregWin;
7310                :                }
7311                :                else
7312                :                {
7313                :                    pPicture->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
7314                :                    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
7315                :                                     pregWin, pPicture->clientClip);
7316                :                }
7317                :                pPicture->freeCompClip = TRUE;
7318                :                REGION_TRANSLATE(pScreen, pPicture->clientClip,
7319                :                                 -(pDrawable->x + pPicture->clipOrigin.x),
7320                :                                 -(pDrawable->y + pPicture->clipOrigin.y));
7321                :            }
7322                :        }       /* end of composite clip for a window */
7323                :        else
7324                :        {
7325                :            BoxRec          pixbounds;
7326                :
7327                :            /* XXX should we translate by drawable.x/y here ? */
7328                :            /* If you want pixmaps in offscreen memory, yes */
7329      1  0.0011 :            pixbounds.x1 = pDrawable->x;
7330                :            pixbounds.y1 = pDrawable->y;
7331                :            pixbounds.x2 = pDrawable->x + pDrawable->width;
7332                :            pixbounds.y2 = pDrawable->y + pDrawable->height;
7333                :
7334                :            if (pPicture->freeCompClip)
7335                :            {
7336                :                REGION_RESET(pScreen, pPicture->pCompositeClip, &pixbounds);
7337                :            }
7338                :            else
7339                :            {
7340                :                pPicture->freeCompClip = TRUE;
7341      3  0.0033 :                pPicture->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1);
7342                :            }
7343                :
7344                :            if (pPicture->clientClipType == CT_REGION)
7345                :            {
7346                :                if(pDrawable->x || pDrawable->y) {
7347                :                    REGION_TRANSLATE(pScreen, pPicture->clientClip,
7348                :                                     pDrawable->x + pPicture->clipOrigin.x, 
7349                :                                     pDrawable->y + pPicture->clipOrigin.y);
7350                :                    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
7351                :                                     pPicture->pCompositeClip, pPicture->clientClip);
7352                :                    REGION_TRANSLATE(pScreen, pPicture->clientClip,
7353                :                                     -(pDrawable->x + pPicture->clipOrigin.x), 
7354                :                                     -(pDrawable->y + pPicture->clipOrigin.y));
7355                :                } else {
7356                :                    REGION_TRANSLATE(pScreen, pPicture->pCompositeClip,
7357                :                                     -pPicture->clipOrigin.x, -pPicture->clipOrigin.y);
7358                :                    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
7359                :                                     pPicture->pCompositeClip, pPicture->clientClip);
7360                :                    REGION_TRANSLATE(pScreen, pPicture->pCompositeClip,
7361                :                                     pPicture->clipOrigin.x, pPicture->clipOrigin.y);
7362                :                }
7363                :            }
7364                :        }       /* end of composite clip for pixmap */
7365                :    }
7366      1  0.0011 :}
7367                :
7368                :int
7369                :miChangePictureTransform (PicturePtr    pPicture,
7370                :                          PictTransform *transform)
7371      1  0.0011 :{ /* miChangePictureTransform total:      1  0.0011 */
7372                :    return Success;
7373                :}
7374                :
7375                :int
7376                :miChangePictureFilter (PicturePtr pPicture,
7377                :                       int        filter,
7378                :                       xFixed     *params,
7379                :                       int        nparams)
7380      1  0.0011 :{ /* miChangePictureFilter total:      1  0.0011 */
7381                :    return Success;
7382                :}
7383                :
7384                :#define BOUND(v)        (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
7385                :
7386                :static inline pixman_bool_t
7387                :miClipPictureReg (pixman_region16_t *   pRegion,
7388                :                  pixman_region16_t *   pClip,
7389                :                  int           dx,
7390                :                  int           dy)
7391                :{
7392                :    if (pixman_region_n_rects(pRegion) == 1 &&
7393                :        pixman_region_n_rects(pClip) == 1)
7394                :    {
7395                :        pixman_box16_t *  pRbox = pixman_region_rectangles(pRegion, NULL);
7396                :        pixman_box16_t *  pCbox = pixman_region_rectangles(pClip, NULL);
7397                :        int     v;
7398                :        
7399                :        if (pRbox->x1 < (v = pCbox->x1 + dx))
7400                :            pRbox->x1 = BOUND(v);
7401                :        if (pRbox->x2 > (v = pCbox->x2 + dx))
7402                :            pRbox->x2 = BOUND(v);
7403                :        if (pRbox->y1 < (v = pCbox->y1 + dy))
7404                :            pRbox->y1 = BOUND(v);
7405                :        if (pRbox->y2 > (v = pCbox->y2 + dy))
7406                :            pRbox->y2 = BOUND(v);
7407                :        if (pRbox->x1 >= pRbox->x2 ||
7408                :            pRbox->y1 >= pRbox->y2)
7409                :        {
7410                :            pixman_region_init (pRegion);
7411                :        }
7412                :    }
7413                :    else if (!pixman_region_not_empty (pClip))
7414                :        return FALSE;
7415                :    else
7416                :    {
7417                :        if (dx || dy)
7418                :            pixman_region_translate (pRegion, -dx, -dy);
7419                :        if (!pixman_region_intersect (pRegion, pRegion, pClip))
7420                :            return FALSE;
7421                :        if (dx || dy)
7422                :            pixman_region_translate(pRegion, dx, dy);
7423                :    }
7424                :    return pixman_region_not_empty(pRegion);
7425                :}
7426                :
7427                :static __inline Bool
7428                :miClipPictureSrc (RegionPtr     pRegion,
7429                :                  PicturePtr    pPicture,
7430                :                  int           dx,
7431                :                  int           dy)
7432                :{
7433                :    /* XXX what to do with clipping from transformed pictures? */
7434                :    if (pPicture->transform || !pPicture->pDrawable)
7435                :        return TRUE;
7436                :    if (pPicture->repeat)
7437                :    {
7438                :        if (pPicture->clientClipType != CT_NONE)
7439                :        {
7440                :            pixman_region_translate ( pRegion, 
7441                :                             dx - pPicture->clipOrigin.x,
7442                :                             dy - pPicture->clipOrigin.y);
7443                :            if (!REGION_INTERSECT (pScreen, pRegion, pRegion, 
7444                :                                   (RegionPtr) pPicture->pCompositeClip)) // clientClip))
7445                :                return FALSE;
7446                :            pixman_region_translate ( pRegion, 
7447                :                             - (dx - pPicture->clipOrigin.x),
7448                :                             - (dy - pPicture->clipOrigin.y));
7449                :        }
7450                :        return TRUE;
7451                :    }
7452                :    else
7453                :    {
7454                :        return miClipPictureReg (pRegion,
7455                :                                 pPicture->pCompositeClip,
7456                :                                 dx,
7457                :                                 dy);
7458                :    }
7459                :}
7460                :
7461                :void
7462                :miCompositeSourceValidate (PicturePtr   pPicture,
7463                :                           INT16        x,
7464                :                           INT16        y,
7465                :                           CARD16       width,
7466                :                           CARD16       height)
7467     31  0.0338 :{ /* miCompositeSourceValidate total:    106  0.1155 */
7468      8  0.0087 :    DrawablePtr pDrawable = pPicture->pDrawable;
7469                :    ScreenPtr   pScreen;
7470                :
7471      4  0.0044 :    if (!pDrawable)
7472                :        return;
7473                :
7474     11  0.0120 :    pScreen = pDrawable->pScreen;
7475                :    
7476     18  0.0196 :    if (pScreen->SourceValidate)
7477                :    {
7478                :        x -= pPicture->pDrawable->x;
7479     12  0.0131 :        y -= pPicture->pDrawable->y;
7480      3  0.0033 :        if (pPicture->transform)
7481                :        {
7482                :            xPoint          points[4];
7483                :            int             i;
7484                :            int             xmin, ymin, xmax, ymax;
7485                :
7486                :#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; }
7487                :            VectorSet (0, x, y);
7488                :            VectorSet (1, x + width, y);
7489                :            VectorSet (2, x, y + height);
7490                :            VectorSet (3, x + width, y + height);
7491                :            xmin = ymin = 32767;
7492                :            xmax = ymax = -32737;
7493                :            for (i = 0; i < 4; i++)
7494                :            {
7495                :                PictVector  t;
7496                :                t.vector[0] = IntToxFixed (points[i].x);
7497                :                t.vector[1] = IntToxFixed (points[i].y);
7498                :                t.vector[2] = xFixed1;
7499                :                if (PictureTransformPoint (pPicture->transform, &t))
7500                :                {
7501                :                    int tx = xFixedToInt (t.vector[0]);
7502                :                    int ty = xFixedToInt (t.vector[1]);
7503                :                    if (tx < xmin) xmin = tx;
7504                :                    if (tx > xmax) xmax = tx;
7505                :                    if (ty < ymin) ymin = ty;
7506                :                    if (ty > ymax) ymax = ty;
7507                :                }
7508                :            }
7509                :            x = xmin;
7510                :            y = ymin;
7511                :            width = xmax - xmin;
7512                :            height = ymax - ymin;
7513                :        }
7514     10  0.0109 :        (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
7515                :    }
7516      9  0.0098 :}
7517                :
7518                :/*
7519                : * returns FALSE if the final region is empty.  Indistinguishable from
7520                : * an allocation failure, but rendering ignores those anyways.
7521                : */
7522                :
7523                :_X_EXPORT Bool
7524                :miComputeCompositeRegion (RegionPtr     pRegion,
7525                :                          PicturePtr    pSrc,
7526                :                          PicturePtr    pMask,
7527                :                          PicturePtr    pDst,
7528                :                          INT16         xSrc,
7529                :                          INT16         ySrc,
7530                :                          INT16         xMask,
7531                :                          INT16         yMask,
7532                :                          INT16         xDst,
7533                :                          INT16         yDst,
7534                :                          CARD16        width,
7535                :                          CARD16        height)
7536     28  0.0305 :{ /* miComputeCompositeRegion total:    296  0.3225 */
7537                :    
7538                :    int         v;
7539                :
7540      2  0.0022 :    pRegion->extents.x1 = xDst;
7541      9  0.0098 :    v = xDst + width;
7542     10  0.0109 :    pRegion->extents.x2 = BOUND(v);
7543                :    pRegion->extents.y1 = yDst;
7544      4  0.0044 :    v = yDst + height;
7545      9  0.0098 :    pRegion->extents.y2 = BOUND(v);
7546      2  0.0022 :    pRegion->data = 0;
7547                :    /* Check for empty operation */
7548      8  0.0087 :    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
7549                :        pRegion->extents.y1 >= pRegion->extents.y2)
7550                :    {
7551      1  0.0011 :        pixman_region_init (pRegion);
7552                :        return FALSE;
7553                :    }
7554                :    /* clip against dst */
7555      8  0.0087 :    if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0))
7556                :    {
7557                :        pixman_region_fini (pRegion);
7558                :        return FALSE;
7559                :    }
7560                :    if (pDst->alphaMap)
7561                :    {
7562                :        if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip,
7563                :                               -pDst->alphaOrigin.x,
7564                :                               -pDst->alphaOrigin.y))
7565                :        {
7566                :            pixman_region_fini (pRegion);
7567                :            return FALSE;
7568                :        }
7569                :    }
7570                :    /* clip against src */
7571     10  0.0109 :    if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
7572                :    {
7573                :        pixman_region_fini (pRegion);
7574                :        return FALSE;
7575                :    }
7576      5  0.0054 :    if (pSrc->alphaMap)
7577                :    {
7578                :        if (!miClipPictureSrc (pRegion, pSrc->alphaMap,
7579                :                               xDst - (xSrc + pSrc->alphaOrigin.x),
7580                :                               yDst - (ySrc + pSrc->alphaOrigin.y)))
7581                :        {
7582                :            pixman_region_fini (pRegion);
7583                :            return FALSE;
7584                :        }
7585                :    }
7586                :    /* clip against mask */
7587      5  0.0054 :    if (pMask)
7588                :    {
7589      2  0.0022 :        if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
7590                :        {
7591                :            pixman_region_fini (pRegion);
7592                :            return FALSE;
7593                :        }       
7594      3  0.0033 :        if (pMask->alphaMap)
7595                :        {
7596                :            if (!miClipPictureSrc (pRegion, pMask->alphaMap,
7597                :                                   xDst - (xMask + pMask->alphaOrigin.x),
7598                :                                   yDst - (yMask + pMask->alphaOrigin.y)))
7599                :            {
7600                :                pixman_region_fini (pRegion);
7601                :                return FALSE;
7602                :            }
7603                :        }
7604                :    }
7605                :
7606                :    
7607     23  0.0251 :    miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height);
7608                :    if (pMask)
7609      7  0.0076 :        miCompositeSourceValidate (pMask, xMask, yMask, width, height);
7610                :
7611                :    return TRUE;
7612      1  0.0011 :}
7613                :
7614                :void
7615                :miRenderColorToPixel (PictFormatPtr format,
7616                :                      xRenderColor  *color,
7617                :                      CARD32        *pixel)
7618                :{ /* miRenderColorToPixel total:      5  0.0054 */
7619                :    CARD32          r, g, b, a;
7620                :    miIndexedPtr    pIndexed;
7621                :
7622      1  0.0011 :    switch (format->type) {
7623                :    case PictTypeDirect:
7624      1  0.0011 :        r = color->red >> (16 - Ones (format->direct.redMask));
7625      1  0.0011 :        g = color->green >> (16 - Ones (format->direct.greenMask));
7626                :        b = color->blue >> (16 - Ones (format->direct.blueMask));
7627                :        a = color->alpha >> (16 - Ones (format->direct.alphaMask));
7628                :        r = r << format->direct.red;
7629                :        g = g << format->direct.green;
7630                :        b = b << format->direct.blue;
7631                :        a = a << format->direct.alpha;
7632      2  0.0022 :        *pixel = r|g|b|a;
7633                :        break;
7634                :    case PictTypeIndexed:
7635                :        pIndexed = (miIndexedPtr) (format->index.devPrivate);
7636                :        if (pIndexed->color)
7637                :        {
7638                :            r = color->red >> 11;
7639                :            g = color->green >> 11;
7640                :            b = color->blue >> 11;
7641                :            *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b);
7642                :        }
7643                :        else
7644                :        {
7645                :            r = color->red >> 8;
7646                :            g = color->green >> 8;
7647                :            b = color->blue >> 8;
7648                :            *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b);
7649                :        }
7650                :        break;
7651                :    }
7652                :}
7653                :
7654                :static CARD16
7655                :miFillColor (CARD32 pixel, int bits)
7656                :{
7657                :    while (bits < 16)
7658                :    {
7659                :        pixel |= pixel << bits;
7660                :        bits <<= 1;
7661                :    }
7662                :    return (CARD16) pixel;
7663                :}
7664                :
7665                :Bool
7666                :miIsSolidAlpha (PicturePtr pSrc)
7667                :{
7668                :    ScreenPtr   pScreen;
7669                :    char        line[1];
7670                :
7671                :    if (!pSrc->pDrawable)
7672                :        return FALSE;
7673                :
7674                :    pScreen = pSrc->pDrawable->pScreen;
7675                :    
7676                :    /* Alpha-only */
7677                :    if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
7678                :        return FALSE;
7679                :    /* repeat */
7680                :    if (!pSrc->repeat)
7681                :        return FALSE;
7682                :    /* 1x1 */
7683                :    if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
7684                :        return FALSE;
7685                :    line[0] = 1;
7686                :    (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
7687                :    switch (pSrc->pDrawable->bitsPerPixel) {
7688                :    case 1:
7689                :        return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
7690                :    case 4:
7691                :        return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
7692                :    case 8:
7693                :        return (CARD8) line[0] == 0xff;
7694                :    default:
7695                :        return FALSE;
7696                :    }
7697                :}
7698                :
7699                :void
7700                :miRenderPixelToColor (PictFormatPtr format,
7701                :                      CARD32        pixel,
7702                :                      xRenderColor  *color)
7703                :{
7704                :    CARD32          r, g, b, a;
7705                :    miIndexedPtr    pIndexed;
7706                :    
7707                :    switch (format->type) {
7708                :    case PictTypeDirect:
7709                :        r = (pixel >> format->direct.red) & format->direct.redMask;
7710                :        g = (pixel >> format->direct.green) & format->direct.greenMask;
7711                :        b = (pixel >> format->direct.blue) & format->direct.blueMask;
7712                :        a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
7713                :        color->red = miFillColor (r, Ones (format->direct.redMask));
7714                :        color->green = miFillColor (g, Ones (format->direct.greenMask));
7715                :        color->blue = miFillColor (b, Ones (format->direct.blueMask));
7716                :        color->alpha = miFillColor (a, Ones (format->direct.alphaMask));
7717                :        break;
7718                :    case PictTypeIndexed:
7719                :        pIndexed = (miIndexedPtr) (format->index.devPrivate);
7720                :        pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)];
7721                :        r = (pixel >> 16) & 0xff;
7722                :        g = (pixel >>  8) & 0xff;
7723                :        b = (pixel      ) & 0xff;
7724                :        color->red = miFillColor (r, 8);
7725                :        color->green = miFillColor (g, 8);
7726                :        color->blue = miFillColor (b, 8);
7727                :        color->alpha = 0xffff;
7728                :        break;
7729                :    }
7730                :}
7731                :
7732                :_X_EXPORT Bool
7733                :miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
7734                :{
7735                :    PictureScreenPtr    ps;
7736                :    
7737                :    if (!PictureInit (pScreen, formats, nformats))
7738                :        return FALSE;
7739                :    ps = GetPictureScreen(pScreen);
7740                :    ps->CreatePicture = miCreatePicture;
7741                :    ps->DestroyPicture = miDestroyPicture;
7742                :    ps->ChangePictureClip = miChangePictureClip;
7743                :    ps->DestroyPictureClip = miDestroyPictureClip;
7744                :    ps->ChangePicture = miChangePicture;
7745                :    ps->ValidatePicture = miValidatePicture;
7746                :    ps->InitIndexed = miInitIndexed;
7747                :    ps->CloseIndexed = miCloseIndexed;
7748                :    ps->UpdateIndexed = miUpdateIndexed;
7749                :    ps->ChangePictureTransform = miChangePictureTransform;
7750                :    ps->ChangePictureFilter = miChangePictureFilter;
7751                :    ps->RealizeGlyph = miRealizeGlyph;
7752                :    ps->UnrealizeGlyph = miUnrealizeGlyph;
7753                :
7754                :    /* MI rendering routines */
7755                :    ps->Composite       = 0;                    /* requires DDX support */
7756                :    ps->Glyphs          = miGlyphs;
7757                :    ps->CompositeRects  = miCompositeRects;
7758                :    ps->Trapezoids      = miTrapezoids;
7759                :    ps->Triangles       = miTriangles;
7760                :    ps->TriStrip        = miTriStrip;
7761                :    ps->TriFan          = miTriFan;
7762                :    
7763                :    ps->RasterizeTrapezoid = 0;                 /* requires DDX support */
7764                :    ps->AddTraps        = 0;                    /* requires DDX support */
7765                :    ps->AddTriangles    = 0;                    /* requires DDX support */
7766                :
7767                :    return TRUE;
7768                :}
7769 /* 
7770  * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i830_exa.c"
7771  * 
7772  *    254  0.2767
7773  */
7774
7775
7776                :/**************************************************************************
7777                :
7778                :Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
7779                :All Rights Reserved.
7780                :Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
7781                :  Based on code from i830_xaa.c.
7782                :
7783                :Permission is hereby granted, free of charge, to any person obtaining a
7784                :copy of this software and associated documentation files (the
7785                :"Software"), to deal in the Software without restriction, including
7786                :without limitation the rights to use, copy, modify, merge, publish,
7787                :distribute, sub license, and/or sell copies of the Software, and to
7788                :permit persons to whom the Software is furnished to do so, subject to
7789                :the following conditions:
7790                :
7791                :The above copyright notice and this permission notice (including the
7792                :next paragraph) shall be included in all copies or substantial portions
7793                :of the Software.
7794                :
7795                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7796                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7797                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
7798                :IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
7799                :ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7800                :TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
7801                :SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7802                :
7803                :**************************************************************************/
7804                :
7805                :#ifdef HAVE_CONFIG_H
7806                :#include "config.h"
7807                :#endif
7808                :
7809                :#include "xf86.h"
7810                :#include "xaarop.h"
7811                :#include "i830.h"
7812                :#include "i810_reg.h"
7813                :#include "i830_reg.h"
7814                :#include <string.h>
7815                :
7816                :#ifdef I830DEBUG
7817                :#define DEBUG_I830FALLBACK 1
7818                :#endif
7819                :
7820                :#define ALWAYS_SYNC             0
7821                :
7822                :#ifdef DEBUG_I830FALLBACK
7823                :#define I830FALLBACK(s, arg...)                         \
7824                :do {                                                    \
7825                :        DPRINTF(PFX, "EXA fallback: " s "\n", ##arg);   \
7826                :        return FALSE;                                   \
7827                :} while(0)
7828                :#else
7829                :#define I830FALLBACK(s, arg...)                         \
7830                :do {                                                    \
7831                :        return FALSE;                                   \
7832                :} while(0) 
7833                :#endif
7834                :
7835                :const int I830CopyROP[16] =
7836                :{
7837                :   ROP_0,               /* GXclear */
7838                :   ROP_DSa,             /* GXand */
7839                :   ROP_SDna,            /* GXandReverse */
7840                :   ROP_S,               /* GXcopy */
7841                :   ROP_DSna,            /* GXandInverted */
7842                :   ROP_D,               /* GXnoop */
7843                :   ROP_DSx,             /* GXxor */
7844                :   ROP_DSo,             /* GXor */
7845                :   ROP_DSon,            /* GXnor */
7846                :   ROP_DSxn,            /* GXequiv */
7847                :   ROP_Dn,              /* GXinvert*/
7848                :   ROP_SDno,            /* GXorReverse */
7849                :   ROP_Sn,              /* GXcopyInverted */
7850                :   ROP_DSno,            /* GXorInverted */
7851                :   ROP_DSan,            /* GXnand */
7852                :   ROP_1                /* GXset */
7853                :};
7854                :
7855                :const int I830PatternROP[16] =
7856                :{
7857                :    ROP_0,
7858                :    ROP_DPa,
7859                :    ROP_PDna,
7860                :    ROP_P,
7861                :    ROP_DPna,
7862                :    ROP_D,
7863                :    ROP_DPx,
7864                :    ROP_DPo,
7865                :    ROP_DPon,
7866                :    ROP_PDxn,
7867                :    ROP_Dn,
7868                :    ROP_PDno,
7869                :    ROP_Pn,
7870                :    ROP_DPno,
7871                :    ROP_DPan,
7872                :    ROP_1
7873                :};
7874                :
7875                :/**
7876                : * I830EXASync - wait for a command to finish
7877                : * @pScreen: current screen
7878                : * @marker: marker command to wait for
7879                : *
7880                : * Wait for the command specified by @marker to finish, then return.  We don't
7881                : * actually do marker waits, though we might in the future.  For now, just
7882                : * wait for a full idle.
7883                : */
7884                :static void
7885                :I830EXASync(ScreenPtr pScreen, int marker)
7886      4  0.0044 :{ /* I830EXASync total:     19  0.0207 */
7887                :    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
7888                :
7889      3  0.0033 :    I830Sync(pScrn);
7890     12  0.0131 :}
7891                :
7892                :/**
7893                : * I830EXAPrepareSolid - prepare for a Solid operation, if possible
7894                : */
7895                :static Bool
7896                :I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
7897                :{ /* I830EXAPrepareSolid total:     10  0.0109 */
7898                :    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
7899      2  0.0022 :    I830Ptr pI830 = I830PTR(pScrn);
7900                :    unsigned long offset, pitch;
7901                :
7902      1  0.0011 :    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
7903                :        I830FALLBACK("planemask is not solid");
7904                :
7905                :    if (pPixmap->drawable.bitsPerPixel == 24)
7906                :        I830FALLBACK("solid 24bpp unsupported!\n");
7907                :
7908                :    offset = exaGetPixmapOffset(pPixmap);
7909                :    pitch = exaGetPixmapPitch(pPixmap);
7910                :
7911      4  0.0044 :    if ( offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
7912                :        I830FALLBACK("pixmap offset not aligned");
7913      1  0.0011 :    if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
7914                :        I830FALLBACK("pixmap pitch not aligned");
7915                :
7916      1  0.0011 :    pI830->BR[13] = (pitch & 0xffff);
7917                :    switch (pPixmap->drawable.bitsPerPixel) {
7918                :        case 8:
7919                :            break;
7920                :        case 16:
7921                :            /* RGB565 */
7922                :            pI830->BR[13] |= (1 << 24);
7923                :            break;
7924                :        case 32:
7925                :            /* RGB8888 */
7926      1  0.0011 :            pI830->BR[13] |= ((1 << 24) | (1 << 25));
7927                :            break;
7928                :    }
7929                :    pI830->BR[13] |= (I830PatternROP[alu] & 0xff) << 16 ;
7930                :    pI830->BR[16] = fg;
7931                :    return TRUE;
7932                :}
7933                :
7934                :static void
7935                :I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
7936      2  0.0022 :{ /* I830EXASolid total:     38  0.0414 */
7937                :    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
7938                :    I830Ptr pI830 = I830PTR(pScrn);
7939                :    unsigned long offset;
7940                :
7941      1  0.0011 :    offset = exaGetPixmapOffset(pPixmap);  
7942                :    
7943                :    {
7944      1  0.0011 :        BEGIN_LP_RING(6);
7945                :        if (pPixmap->drawable.bitsPerPixel == 32)
7946      4  0.0044 :            OUT_RING(XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA
7947                :                        | XY_COLOR_BLT_WRITE_RGB);
7948                :        else
7949                :            OUT_RING(XY_COLOR_BLT_CMD);
7950                :
7951      1  0.0011 :        OUT_RING(pI830->BR[13]);
7952      3  0.0033 :        OUT_RING((y1 << 16) | (x1 & 0xffff));
7953                :        OUT_RING((y2 << 16) | (x2 & 0xffff));
7954                :        OUT_RING(offset);
7955                :        OUT_RING(pI830->BR[16]);
7956      3  0.0033 :        ADVANCE_LP_RING();
7957                :    }
7958     23  0.0251 :}
7959                :
7960                :static void
7961                :I830EXADoneSolid(PixmapPtr pPixmap)
7962                :{
7963                :#if ALWAYS_SYNC
7964                :    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
7965                :
7966                :    I830Sync(pScrn);
7967                :#endif
7968                :}
7969                :
7970                :/**
7971                : * TODO:
7972                : *   - support planemask using FULL_BLT_CMD?
7973                : */
7974                :static Bool
7975                :I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
7976                :                   int ydir, int alu, Pixel planemask)
7977                :{
7978                :    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
7979                :    I830Ptr pI830 = I830PTR(pScrn);
7980                :
7981                :    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))
7982                :        I830FALLBACK("planemask is not solid");
7983                :
7984                :    pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
7985                :    pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
7986                :
7987                :    pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
7988                :    pI830->BR[13] |= I830CopyROP[alu] << 16;
7989                :
7990                :    switch (pSrcPixmap->drawable.bitsPerPixel) {
7991                :    case 8:
7992                :        break;
7993                :    case 16:
7994                :        pI830->BR[13] |= (1 << 24);
7995                :        break;
7996                :    case 32:
7997                :        pI830->BR[13] |= ((1 << 25) | (1 << 24));
7998                :        break;
7999                :    }
8000                :    return TRUE;
8001                :}
8002                :
8003                :static void
8004                :I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
8005                :            int dst_y1, int w, int h)
8006                :{
8007                :    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
8008                :    I830Ptr pI830 = I830PTR(pScrn);
8009                :    int dst_x2, dst_y2;
8010                :    unsigned int dst_off;
8011                :
8012                :    dst_x2 = dst_x1 + w;
8013                :    dst_y2 = dst_y1 + h;
8014                :
8015                :    dst_off = exaGetPixmapOffset(pDstPixmap);
8016                :
8017                :    {
8018                :        BEGIN_LP_RING(8);
8019                :
8020                :        if (pDstPixmap->drawable.bitsPerPixel == 32)
8021                :            OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
8022                :                     XY_SRC_COPY_BLT_WRITE_RGB);
8023                :        else
8024                :            OUT_RING(XY_SRC_COPY_BLT_CMD);
8025                :
8026                :        OUT_RING(pI830->BR[13]);
8027                :        OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
8028                :        OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
8029                :        OUT_RING(dst_off);
8030                :        OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
8031                :        OUT_RING(pI830->copy_src_pitch);
8032                :        OUT_RING(pI830->copy_src_off);
8033                :
8034                :        ADVANCE_LP_RING();
8035                :    }
8036                :}
8037                :
8038                :static void
8039                :I830EXADoneCopy(PixmapPtr pDstPixmap)
8040                :{
8041                :#if ALWAYS_SYNC
8042                :    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
8043                :
8044                :    I830Sync(pScrn);
8045                :#endif
8046                :}
8047                :
8048                :#define xFixedToFloat(val) \
8049                :        ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
8050                :
8051                :/**
8052                : * Returns the floating-point coordinates transformed by the given transform.
8053                : *
8054                : * transform may be null.
8055                : */
8056                :void
8057                :i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
8058                :                                 float *x_out, float *y_out)
8059     68  0.0741 :{ /* i830_get_transformed_coordinates total:    187  0.2037 */
8060     13  0.0142 :    if (transform == NULL) {
8061     39  0.0425 :        *x_out = x;
8062     35  0.0381 :        *y_out = y;
8063                :    } else {
8064                :        PictVector v;
8065                :
8066                :        v.vector[0] = IntToxFixed(x);
8067                :        v.vector[1] = IntToxFixed(y);
8068                :        v.vector[2] = xFixed1;
8069                :        PictureTransformPoint(transform, &v);
8070                :        *x_out = xFixedToFloat(v.vector[0]);
8071                :        *y_out = xFixedToFloat(v.vector[1]);
8072                :    }
8073     32  0.0349 :}
8074                :
8075                :/**
8076                : * Uploads data from system memory to the framebuffer using a series of
8077                : * 8x8 pattern blits.
8078                : */
8079                :static Bool
8080                :i830_upload_to_screen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
8081                :                      int src_pitch)
8082                :{
8083                :    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
8084                :    I830Ptr pI830 = I830PTR(pScrn);
8085                :    const int uts_width_max = 16, uts_height_max = 16;
8086                :    int cpp = pDst->drawable.bitsPerPixel / 8;
8087                :    int sub_x, sub_y;
8088                :    CARD32 br13;
8089                :    CARD32 offset;
8090                :
8091                :    if (w > uts_width_max || h > uts_height_max)
8092                :        I830FALLBACK("too large for upload to screen (%d,%d)", w, h);
8093                :
8094                :    offset = exaGetPixmapOffset(pDst);
8095                :
8096                :    br13 = exaGetPixmapPitch(pDst);
8097                :    br13 |= ((I830PatternROP[GXcopy] & 0xff) << 16);
8098                :    switch (pDst->drawable.bitsPerPixel) {
8099                :    case 16:
8100                :        br13 |= 1 << 24;
8101                :        break;
8102                :    case 32:
8103                :        br13 |= 3 << 24;
8104                :        break;
8105                :    }
8106                :
8107                :    for (sub_y = 0; sub_y < uts_height_max && sub_y < h; sub_y += 8) {
8108                :        int sub_height;
8109                :
8110                :        if (sub_y + 8 > h)
8111                :            sub_height = h - sub_y;
8112                :        else
8113                :            sub_height = 8;
8114                :
8115                :        for (sub_x = 0; sub_x < uts_width_max && sub_x < w; sub_x += 8) {
8116                :            int sub_width, line;
8117                :            char *src_line = src + sub_y * src_pitch + sub_x * cpp;
8118                :
8119                :            if (sub_x + 8 > w)
8120                :                sub_width = w - sub_x;
8121                :            else
8122                :                sub_width = 8;
8123                :
8124                :            BEGIN_LP_RING(6 + (cpp * 8 * 8 / 4));
8125                :
8126                :            /* XXX We may need a pattern offset here for {x,y} % 8 != 0*/
8127                :            OUT_RING(XY_PAT_BLT_IMMEDIATE |
8128                :                     XY_SRC_COPY_BLT_WRITE_ALPHA |
8129                :                     XY_SRC_COPY_BLT_WRITE_RGB |
8130                :                     (3 + cpp * 8 * 8 / 4));
8131                :            OUT_RING(br13);
8132                :            OUT_RING(((y + sub_y) << 16) | (x + sub_x));
8133                :            OUT_RING(((y + sub_y + sub_height) << 16) |
8134                :                     (x + sub_x + sub_width));
8135                :            OUT_RING(offset);
8136                :
8137                :            /* Write out the lines with valid data, followed by any needed
8138                :             * padding
8139                :             */
8140                :            for (line = 0; line < sub_height; line++) {
8141                :                OUT_RING_COPY(sub_width * cpp, src_line);
8142                :                src_line += src_pitch;
8143                :                if (sub_width != 8)
8144                :                    OUT_RING_PAD((8 - sub_width) * cpp);
8145                :            }
8146                :            /* Write out any full padding lines to follow */
8147                :            if (sub_height != 8)
8148                :                OUT_RING_PAD(8 * cpp * (8 - sub_height));
8149                :
8150                :            OUT_RING(MI_NOOP);
8151                :            ADVANCE_LP_RING();
8152                :        }
8153                :    }
8154                :
8155                :    exaMarkSync(pDst->drawable.pScreen);
8156                :    /* exaWaitSync(pDst->drawable.pScreen); */
8157                :
8158                :    return TRUE;
8159                :}
8160                :
8161                :
8162                :/*
8163                : * TODO:
8164                : *   - Dual head?
8165                : */
8166                :Bool
8167                :I830EXAInit(ScreenPtr pScreen)
8168                :{
8169                :    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
8170                :    I830Ptr pI830 = I830PTR(pScrn);
8171                :
8172                :    pI830->EXADriverPtr = exaDriverAlloc();
8173                :    if (pI830->EXADriverPtr == NULL) {
8174                :        pI830->noAccel = TRUE;
8175                :        return FALSE;
8176                :    }
8177                :    memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr));
8178                :
8179                :    pI830->bufferOffset = 0;
8180                :    pI830->EXADriverPtr->exa_major = 2;
8181                :    pI830->EXADriverPtr->exa_minor = 1;
8182                :    pI830->EXADriverPtr->memoryBase = pI830->FbBase;
8183                :    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
8184                :    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
8185                :        pI830->exa_offscreen->size;
8186                :    pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
8187                :
8188                :    DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
8189                :                pI830->EXADriverPtr->memoryBase,
8190                :                pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize,
8191                :                pI830->EXADriverPtr->offScreenBase,
8192                :                pI830->EXADriverPtr->memorySize);
8193                :
8194                :
8195                :    /* Limits are described in the BLT engine chapter under Graphics Data Size
8196                :     * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
8197                :     * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
8198                :     *
8199                :     * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
8200                :     *
8201                :     * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
8202                :     * i965 limits 3D surface to 4kB-aligned offset if tiled.
8203                :     * i965 limits 3D surfaces to w,h of ?,8192.
8204                :     * i965 limits 3D surface to pitch of 1B - 128kB.
8205                :     * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
8206                :     * i965 limits 3D surface pitch alignment to 512B if tiled.
8207                :     * i965 limits 3D destination drawing rect to w,h of 8192,8192.
8208                :     *
8209                :     * i915 limits 3D textures to 4B-aligned offset if un-tiled.
8210                :     * i915 limits 3D textures to ~4kB-aligned offset if tiled.
8211                :     * i915 limits 3D textures to width,height of 2048,2048.
8212                :     * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
8213                :     * i915 limits 3D destination to ~4kB-aligned offset if tiled.
8214                :     * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
8215                :     * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
8216                :     * i915 limits 3D destination to POT aligned pitch if tiled.
8217                :     * i915 limits 3D destination drawing rect to w,h of 2048,2048.
8218                :     *
8219                :     * i845 limits 3D textures to 4B-aligned offset if un-tiled.
8220                :     * i845 limits 3D textures to ~4kB-aligned offset if tiled.
8221                :     * i845 limits 3D textures to width,height of 2048,2048.
8222                :     * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
8223                :     * i845 limits 3D destination to 4B-aligned offset if un-tiled.
8224                :     * i845 limits 3D destination to ~4kB-aligned offset if tiled.
8225                :     * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
8226                :     * i845 limits 3D destination drawing rect to w,h of 2048,2048.
8227                :     *
8228                :     * For the tiled issues, the only tiled buffer we draw to should be
8229                :     * the front, which will have an appropriate pitch/offset already set up,
8230                :     * so EXA doesn't need to worry.
8231                :     */
8232                :    if (IS_I965G(pI830)) {
8233                :        pI830->EXADriverPtr->pixmapOffsetAlign = 4 * 2;
8234                :        pI830->EXADriverPtr->pixmapPitchAlign = 16;
8235                :        pI830->EXADriverPtr->maxX = 8192;
8236                :        pI830->EXADriverPtr->maxY = 8192;
8237                :    } else {
8238                :        pI830->EXADriverPtr->pixmapOffsetAlign = 4;
8239                :        pI830->EXADriverPtr->pixmapPitchAlign = 16;
8240                :        pI830->EXADriverPtr->maxX = 2048;
8241                :        pI830->EXADriverPtr->maxY = 2048;
8242                :    }
8243                :
8244                :    /* Sync */
8245                :    pI830->EXADriverPtr->WaitMarker = I830EXASync;
8246                :
8247                :    /* Solid fill */
8248                :    pI830->EXADriverPtr->PrepareSolid = I830EXAPrepareSolid;
8249                :    pI830->EXADriverPtr->Solid = I830EXASolid;
8250                :    pI830->EXADriverPtr->DoneSolid = I830EXADoneSolid;
8251                :
8252                :    /* Copy */
8253                :    pI830->EXADriverPtr->PrepareCopy = I830EXAPrepareCopy;
8254                :    pI830->EXADriverPtr->Copy = I830EXACopy;
8255                :    pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy;
8256                :
8257                :    /* Composite */
8258                :    if (!IS_I9XX(pI830)) {
8259                :        pI830->EXADriverPtr->CheckComposite = i830_check_composite;
8260                :        pI830->EXADriverPtr->PrepareComposite = i830_prepare_composite;
8261                :        pI830->EXADriverPtr->Composite = i830_composite;
8262                :        pI830->EXADriverPtr->DoneComposite = i830_done_composite;
8263                :    } else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
8264                :               IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
8265                :    {
8266                :        pI830->EXADriverPtr->CheckComposite = i915_check_composite;
8267                :        pI830->EXADriverPtr->PrepareComposite = i915_prepare_composite;
8268                :        pI830->EXADriverPtr->Composite = i830_composite;
8269                :        pI830->EXADriverPtr->DoneComposite = i830_done_composite;
8270                :    } else {
8271                :        pI830->EXADriverPtr->CheckComposite = i965_check_composite;
8272                :        pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite;
8273                :        pI830->EXADriverPtr->Composite = i965_composite;
8274                :        pI830->EXADriverPtr->DoneComposite = i830_done_composite;
8275                :    }
8276                :
8277                :    /* UploadToScreen/DownloadFromScreen */
8278                :    if (0)
8279                :        pI830->EXADriverPtr->UploadToScreen = i830_upload_to_screen;
8280                :
8281                :    if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
8282                :        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
8283                :                   "EXA initialization failed; trying older version\n");
8284                :        pI830->EXADriverPtr->exa_minor = 0;
8285                :        if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
8286                :            xfree(pI830->EXADriverPtr);
8287                :            pI830->noAccel = TRUE;
8288                :            return FALSE;
8289                :        }
8290                :    }
8291                :
8292                :    I830SelectBuffer(pScrn, I830_SELECT_FRONT);
8293                :
8294                :    return TRUE;
8295                :}
8296                :
8297                :#ifdef XF86DRI
8298                :
8299                :#ifndef ExaOffscreenMarkUsed
8300                :extern void ExaOffscreenMarkUsed(PixmapPtr);
8301                :#endif
8302                :
8303                :unsigned long long
8304                :I830TexOffsetStart(PixmapPtr pPix)
8305                :{
8306                :    exaMoveInPixmap(pPix);
8307                :    ExaOffscreenMarkUsed(pPix);
8308                :
8309                :    return exaGetPixmapOffset(pPix);
8310                :}
8311                :#endif
8312 /* 
8313  * Total samples for file : "/home/cworth/src/xorg/xserver/miext/damage/damage.c"
8314  * 
8315  *    191  0.2081
8316  */
8317
8318
8319                :/*
8320                : * Copyright Â© 2003 Keith Packard
8321                : *
8322                : * Permission to use, copy, modify, distribute, and sell this software and its
8323                : * documentation for any purpose is hereby granted without fee, provided that
8324                : * the above copyright notice appear in all copies and that both that
8325                : * copyright notice and this permission notice appear in supporting
8326                : * documentation, and that the name of Keith Packard not be used in
8327                : * advertising or publicity pertaining to distribution of the software without
8328                : * specific, written prior permission.  Keith Packard makes no
8329                : * representations about the suitability of this software for any purpose.  It
8330                : * is provided "as is" without express or implied warranty.
8331                : *
8332                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
8333                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
8334                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
8335                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
8336                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
8337                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
8338                : * PERFORMANCE OF THIS SOFTWARE.
8339                : */
8340                :
8341                :#ifdef HAVE_DIX_CONFIG_H
8342                :#include <dix-config.h>
8343                :#endif
8344                :
8345                :#include <stdlib.h>
8346                :
8347                :#include    <X11/X.h>
8348                :#include    "scrnintstr.h"
8349                :#include    "windowstr.h"
8350                :#include    <X11/fonts/font.h>
8351                :#include    "dixfontstr.h"
8352                :#include    <X11/fonts/fontstruct.h>
8353                :#include    "mi.h"
8354                :#include    "regionstr.h"
8355                :#include    "globals.h"
8356                :#include    "gcstruct.h"
8357                :#include    "damage.h"
8358                :#include    "damagestr.h"
8359                :#ifdef COMPOSITE
8360                :#include    "cw.h"
8361                :#endif
8362                :
8363                :#define wrap(priv, real, mem, func) {\
8364                :    priv->mem = real->mem; \
8365                :    real->mem = func; \
8366                :}
8367                :
8368                :#define unwrap(priv, real, mem) {\
8369                :    real->mem = priv->mem; \
8370                :}
8371                :
8372                :#define BOX_SAME(a,b) \
8373                :    ((a)->x1 == (b)->x1 && \
8374                :     (a)->y1 == (b)->y1 && \
8375                :     (a)->x2 == (b)->x2 && \
8376                :     (a)->y2 == (b)->y2)
8377                :
8378                :#define DAMAGE_VALIDATE_ENABLE 0
8379                :#define DAMAGE_DEBUG_ENABLE 0
8380                :#if DAMAGE_DEBUG_ENABLE
8381                :#define DAMAGE_DEBUG(x) ErrorF x
8382                :#else
8383                :#define DAMAGE_DEBUG(x)
8384                :#endif
8385                :
8386                :#define getPixmapDamageRef(pPixmap) \
8387                :    ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr))
8388                :
8389                :#define pixmapDamage(pPixmap)           damagePixPriv(pPixmap)
8390                :
8391                :static int damageScrPrivateIndex;
8392                :static int damagePixPrivateIndex;
8393                :static int damageGCPrivateIndex;
8394                :static int damageWinPrivateIndex;
8395                :static int damageGeneration;
8396                :
8397                :static DamagePtr *
8398                :getDrawableDamageRef (DrawablePtr pDrawable)
8399      2  0.0022 :{ /* getDrawableDamageRef total:      6  0.0065 */
8400                :    PixmapPtr   pPixmap;
8401                :    
8402                :    if (pDrawable->type == DRAWABLE_WINDOW)
8403                :    {
8404                :        ScreenPtr   pScreen = pDrawable->pScreen;
8405                :
8406                :        pPixmap = 0;
8407                :        if (pScreen->GetWindowPixmap
8408                :#ifdef ROOTLESS_WORKAROUND
8409                :            && ((WindowPtr)pDrawable)->viewable
8410                :#endif
8411                :            )
8412                :            pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable);
8413                :
8414                :        if (!pPixmap)
8415                :        {
8416                :            damageScrPriv(pScreen);
8417                :
8418                :            return &pScrPriv->pScreenDamage;
8419                :        }
8420                :    }
8421                :    else
8422                :        pPixmap = (PixmapPtr) pDrawable;
8423                :    return getPixmapDamageRef (pPixmap);
8424      4  0.0044 :}
8425                :
8426                :#define getDrawableDamage(pDrawable)    (*getDrawableDamageRef (pDrawable))
8427                :#define getWindowDamage(pWin)           getDrawableDamage(&(pWin)->drawable)
8428                :
8429                :#define drawableDamage(pDrawable)       \
8430                :    DamagePtr   pDamage = getDrawableDamage(pDrawable)
8431                :
8432                :#define windowDamage(pWin)              drawableDamage(&(pWin)->drawable)
8433                :
8434                :#define winDamageRef(pWindow) \
8435                :    DamagePtr   *pPrev = (DamagePtr *) \
8436                :            &(pWindow->devPrivates[damageWinPrivateIndex].ptr)
8437                :
8438                :static void
8439                :DamageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion)
8440      1  0.0011 :{ /* DamageReportDamage total:      4  0.0044 */
8441                :    BoxRec tmpBox;
8442                :    RegionRec tmpRegion;
8443                :    Bool was_empty;
8444                :
8445                :    switch (pDamage->damageLevel) {
8446                :    case DamageReportRawRegion:
8447                :        (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure);
8448                :        break;
8449                :    case DamageReportDeltaRegion:
8450                :        REGION_NULL (pScreen, &tmpRegion);
8451                :        REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage);
8452                :        if (REGION_NOTEMPTY (pScreen, &tmpRegion)) {
8453                :            REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
8454                :                         pDamageRegion);
8455                :            (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure);
8456                :        }
8457                :        REGION_UNINIT(pScreen, &tmpRegion);
8458                :        break;
8459                :    case DamageReportBoundingBox:
8460                :        tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage);
8461                :        REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
8462                :                     pDamageRegion);
8463                :        if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) {
8464                :            (*pDamage->damageReport) (pDamage, &pDamage->damage,
8465                :                                      pDamage->closure);
8466                :        }
8467                :        break;
8468                :    case DamageReportNonEmpty:
8469                :        was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage);
8470      1  0.0011 :        REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
8471                :                     pDamageRegion);
8472                :        if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) {
8473                :            (*pDamage->damageReport) (pDamage, &pDamage->damage,
8474                :                                      pDamage->closure);
8475                :        }
8476                :        break;
8477                :    case DamageReportNone:
8478                :        REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
8479                :                     pDamageRegion);
8480                :        break;
8481                :    }
8482      2  0.0022 :}
8483                :
8484                :#if DAMAGE_DEBUG_ENABLE
8485                :static void
8486                :_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where)
8487                :#define damageDamageRegion(d,r,c,m) _damageDamageRegion(d,r,c,m,__FUNCTION__)
8488                :#else
8489                :static void
8490                :damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
8491                :                        int subWindowMode)
8492                :#endif
8493      1  0.0011 :{ /* damageDamageRegion total:     21  0.0229 */
8494                :    ScreenPtr       pScreen = pDrawable->pScreen;
8495                :    damageScrPriv(pScreen);
8496                :    drawableDamage(pDrawable);
8497                :    DamagePtr       pNext;
8498                :    RegionRec       clippedRec;
8499                :    RegionPtr       pDamageRegion;
8500                :    RegionRec       pixClip;
8501                :    int             draw_x, draw_y;
8502                :#ifdef COMPOSITE
8503                :    int             screen_x = 0, screen_y = 0;
8504                :#endif
8505                :
8506                :    /* short circuit for empty regions */
8507      1  0.0011 :    if (!REGION_NOTEMPTY(pScreen, pRegion))
8508                :        return;
8509                :    
8510                :#ifdef COMPOSITE
8511                :    /*
8512                :     * When drawing to a pixmap which is storing window contents,
8513                :     * the region presented is in pixmap relative coordinates which
8514                :     * need to be converted to screen relative coordinates
8515                :     */
8516                :    if (pDrawable->type != DRAWABLE_WINDOW)
8517                :    {
8518                :        screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x;
8519      2  0.0022 :        screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y;
8520                :    }
8521      2  0.0022 :    if (screen_x || screen_y)
8522                :        REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y);
8523                :#endif
8524                :        
8525                :    if (pDrawable->type == DRAWABLE_WINDOW &&
8526                :        ((WindowPtr)(pDrawable))->backingStore == NotUseful)
8527                :    {
8528                :        if (subWindowMode == ClipByChildren)
8529                :        {
8530                :            REGION_INTERSECT(pScreen, pRegion, pRegion,
8531                :                             &((WindowPtr)(pDrawable))->clipList);
8532                :        }
8533                :        else if (subWindowMode == IncludeInferiors)
8534                :        {
8535                :            RegionPtr pTempRegion =
8536                :                NotClippedByChildren((WindowPtr)(pDrawable));
8537                :            REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion);
8538                :            REGION_DESTROY(pScreen, pTempRegion);
8539                :        }
8540                :        /* If subWindowMode is set to an invalid value, don't perform
8541                :         * any drawable-based clipping. */
8542                :    }
8543                :        
8544                :
8545      2  0.0022 :    REGION_NULL (pScreen, &clippedRec);
8546      1  0.0011 :    for (; pDamage; pDamage = pNext)
8547                :    {
8548      1  0.0011 :        pNext = pDamage->pNext;
8549                :        /*
8550                :         * Check for internal damage and don't send events
8551                :         */
8552      1  0.0011 :        if (pScrPriv->internalLevel > 0 && !pDamage->isInternal)
8553                :        {
8554                :            DAMAGE_DEBUG (("non internal damage, skipping at %d\n",
8555                :                           pScrPriv->internalLevel));
8556                :            continue;
8557                :        }
8558                :        /*
8559                :         * Check for unrealized windows
8560                :         */
8561      1  0.0011 :        if (pDamage->pDrawable->type == DRAWABLE_WINDOW &&
8562                :            !((WindowPtr) (pDamage->pDrawable))->realized)
8563                :        {
8564                :#if 0
8565                :            DAMAGE_DEBUG (("damage while window unrealized\n"));
8566                :#endif
8567                :            continue;
8568                :        }
8569                :        
8570      1  0.0011 :        draw_x = pDamage->pDrawable->x;
8571                :        draw_y = pDamage->pDrawable->y;
8572                :#ifdef COMPOSITE
8573                :        /*
8574                :         * Need to move everyone to screen coordinates
8575                :         * XXX what about off-screen pixmaps with non-zero x/y?
8576                :         */
8577                :        if (pDamage->pDrawable->type != DRAWABLE_WINDOW)
8578                :        {
8579                :            draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x;
8580                :            draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y;
8581                :        }
8582                :#endif
8583                :        
8584                :        /*
8585                :         * Clip against border or pixmap bounds
8586                :         */
8587                :        
8588                :        pDamageRegion = pRegion;
8589                :        if (clip || pDamage->pDrawable != pDrawable)
8590                :        {
8591                :            pDamageRegion = &clippedRec;
8592                :            if (pDamage->pDrawable->type == DRAWABLE_WINDOW) {
8593                :                REGION_INTERSECT (pScreen, pDamageRegion, pRegion,
8594                :                    &((WindowPtr)(pDamage->pDrawable))->borderClip);
8595                :            } else {
8596                :                BoxRec  box;
8597                :                box.x1 = draw_x;
8598                :                box.y1 = draw_y;
8599                :                box.x2 = draw_x + pDamage->pDrawable->width;
8600                :                box.y2 = draw_y + pDamage->pDrawable->height;
8601      1  0.0011 :                REGION_INIT(pScreen, &pixClip, &box, 1);
8602                :                REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip);
8603      2  0.0022 :                REGION_UNINIT(pScreen, &pixClip);
8604                :            }
8605                :            /*
8606                :             * Short circuit empty results
8607                :             */
8608                :            if (!REGION_NOTEMPTY(pScreen, pDamageRegion))
8609                :                continue;
8610                :        }
8611                :        
8612                :        DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
8613                :                       where,
8614                :                       pDamageRegion->extents.x2 - pDamageRegion->extents.x1,
8615                :                       pDamageRegion->extents.y2 - pDamageRegion->extents.y1,
8616                :                       pDamageRegion->extents.x1, pDamageRegion->extents.y1,
8617                :                       pDrawable->id, pDamage->pDrawable->id));
8618                :        
8619                :        /*
8620                :         * Move region to target coordinate space
8621                :         */
8622                :        if (draw_x || draw_y)
8623                :            REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y);
8624                :
8625                :        /* If the damage rec has been flagged to report damage after the op has
8626                :         * completed, then union it into the delayed damage region, which will
8627                :         * be used for reporting after calling down, and skip the reporting 
8628                :         */
8629      1  0.0011 :        if (!pDamage->reportAfter) {
8630                :            DamageReportDamage (pDamage, pDamageRegion);
8631                :        } else {
8632      1  0.0011 :            REGION_UNION(pScreen, &pDamage->pendingDamage,
8633                :                         &pDamage->pendingDamage, pDamageRegion);
8634                :        }
8635                :
8636                :        /*
8637                :         * translate original region back
8638                :         */
8639      1  0.0011 :        if (pDamageRegion == pRegion && (draw_x || draw_y))
8640                :            REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y);
8641                :    }
8642                :#ifdef COMPOSITE
8643                :    if (screen_x || screen_y)
8644                :        REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y);
8645                :#endif
8646                :    
8647                :    REGION_UNINIT (pScreen, &clippedRec);
8648      2  0.0022 :}
8649                :
8650                :static void
8651                :damageReportPostOp (DrawablePtr pDrawable)
8652                :{ /* damageReportPostOp total:      3  0.0033 */
8653                :    drawableDamage(pDrawable);
8654                :
8655                :    for (; pDamage != NULL; pDamage = pDamage->pNext)
8656                :    {
8657      2  0.0022 :        if (pDamage->reportAfter) {
8658                :            DamageReportDamage (pDamage, &pDamage->pendingDamage);
8659      1  0.0011 :            REGION_EMPTY (pScreen, &pDamage->pendingDamage);
8660                :        }
8661                :    }
8662                :    
8663                :}
8664                :
8665                :#if DAMAGE_DEBUG_ENABLE
8666                :#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
8667                :static void
8668                :_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where)
8669                :#else
8670                :static void
8671                :damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode)
8672                :#endif
8673      2  0.0022 :{ /* damageDamageBox total:      3  0.0033 */
8674                :    RegionRec   region;
8675                :
8676                :    REGION_INIT (pDrawable->pScreen, &region, pBox, 1);
8677                :#if DAMAGE_DEBUG_ENABLE
8678                :    _damageDamageRegion (pDrawable, &region, TRUE, subWindowMode, where);
8679                :#else
8680      1  0.0011 :    damageDamageRegion (pDrawable, &region, TRUE, subWindowMode);
8681                :#endif
8682                :    REGION_UNINIT (pDrawable->pScreen, &region);
8683                :}
8684                :
8685                :static void damageValidateGC(GCPtr, unsigned long, DrawablePtr);
8686                :static void damageChangeGC(GCPtr, unsigned long);
8687                :static void damageCopyGC(GCPtr, unsigned long, GCPtr);
8688                :static void damageDestroyGC(GCPtr);
8689                :static void damageChangeClip(GCPtr, int, pointer, int);
8690                :static void damageDestroyClip(GCPtr);
8691                :static void damageCopyClip(GCPtr, GCPtr);
8692                :
8693                :static GCFuncs damageGCFuncs = {
8694                :    damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC,
8695                :    damageChangeClip, damageDestroyClip, damageCopyClip
8696                :};
8697                :
8698                :static GCOps damageGCOps;
8699                :
8700                :static Bool
8701                :damageCreateGC(GCPtr pGC)
8702                :{
8703                :    ScreenPtr pScreen = pGC->pScreen;
8704                :    damageScrPriv(pScreen);
8705                :    damageGCPriv(pGC);
8706                :    Bool ret;
8707                :
8708                :    pGC->pCompositeClip = 0;
8709                :    unwrap (pScrPriv, pScreen, CreateGC);
8710                :    if((ret = (*pScreen->CreateGC) (pGC))) {
8711                :        pGCPriv->ops = NULL;
8712                :        pGCPriv->funcs = pGC->funcs;
8713                :        pGC->funcs = &damageGCFuncs;
8714                :    }
8715                :    wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
8716                :
8717                :    return ret;
8718                :}
8719                :
8720                :#ifdef NOTUSED
8721                :static void
8722                :damageWrapGC (GCPtr pGC)
8723                :{
8724                :    damageGCPriv(pGC);
8725                :
8726                :    pGCPriv->ops = NULL;
8727                :    pGCPriv->funcs = pGC->funcs;
8728                :    pGC->funcs = &damageGCFuncs;
8729                :}
8730                :
8731                :static void
8732                :damageUnwrapGC (GCPtr pGC)
8733                :{
8734                :    damageGCPriv(pGC);
8735                :
8736                :    pGC->funcs = pGCPriv->funcs;
8737                :    if (pGCPriv->ops)
8738                :        pGC->ops = pGCPriv->ops;
8739                :}
8740                :#endif
8741                :
8742                :#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
8743                :    damageGCPriv(pGC);  \
8744                :    GCFuncs *oldFuncs = pGC->funcs; \
8745                :    unwrap(pGCPriv, pGC, funcs);  \
8746                :    unwrap(pGCPriv, pGC, ops); \
8747                :
8748                :#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
8749                :    wrap(pGCPriv, pGC, funcs, oldFuncs); \
8750                :    wrap(pGCPriv, pGC, ops, &damageGCOps)
8751                :
8752                :#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
8753                :    damageGCPriv(pGC); \
8754                :    unwrap(pGCPriv, pGC, funcs); \
8755                :    if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
8756                :
8757                :#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
8758                :    wrap(pGCPriv, pGC, funcs, &damageGCFuncs);  \
8759                :    if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
8760                :
8761                :static void
8762                :damageValidateGC(GCPtr         pGC,
8763                :                 unsigned long changes,
8764                :                 DrawablePtr   pDrawable)
8765      2  0.0022 :{ /* damageValidateGC total:      7  0.0076 */
8766      1  0.0011 :    DAMAGE_GC_FUNC_PROLOGUE (pGC);
8767      1  0.0011 :    (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
8768                :    pGCPriv->ops = pGC->ops;  /* just so it's not NULL */
8769      3  0.0033 :    DAMAGE_GC_FUNC_EPILOGUE (pGC);
8770                :}
8771                :
8772                :static void
8773                :damageDestroyGC(GCPtr pGC)
8774                :{
8775                :    DAMAGE_GC_FUNC_PROLOGUE (pGC);
8776                :    (*pGC->funcs->DestroyGC)(pGC);
8777                :    DAMAGE_GC_FUNC_EPILOGUE (pGC);
8778                :}
8779                :
8780                :static void
8781                :damageChangeGC (GCPtr           pGC,
8782                :                unsigned long   mask)
8783      2  0.0022 :{ /* damageChangeGC total:      9  0.0098 */
8784      4  0.0044 :    DAMAGE_GC_FUNC_PROLOGUE (pGC);
8785      1  0.0011 :    (*pGC->funcs->ChangeGC) (pGC, mask);
8786      2  0.0022 :    DAMAGE_GC_FUNC_EPILOGUE (pGC);
8787                :}
8788                :
8789                :static void
8790                :damageCopyGC (GCPtr         pGCSrc,
8791                :              unsigned long mask,
8792                :              GCPtr         pGCDst)
8793                :{
8794                :    DAMAGE_GC_FUNC_PROLOGUE (pGCDst);
8795                :    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
8796                :    DAMAGE_GC_FUNC_EPILOGUE (pGCDst);
8797                :}
8798                :
8799                :static void
8800                :damageChangeClip (GCPtr     pGC,
8801                :                  int       type,
8802                :                  pointer   pvalue,
8803                :                  int       nrects)
8804      1  0.0011 :{ /* damageChangeClip total:      1  0.0011 */
8805                :    DAMAGE_GC_FUNC_PROLOGUE (pGC);
8806                :    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
8807                :    DAMAGE_GC_FUNC_EPILOGUE (pGC);
8808                :}
8809                :
8810                :static void
8811                :damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
8812                :{
8813                :    DAMAGE_GC_FUNC_PROLOGUE (pgcDst);
8814                :    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
8815                :    DAMAGE_GC_FUNC_EPILOGUE (pgcDst);
8816                :}
8817                :
8818                :static void
8819                :damageDestroyClip(GCPtr pGC)
8820                :{
8821                :    DAMAGE_GC_FUNC_PROLOGUE (pGC);
8822                :    (* pGC->funcs->DestroyClip)(pGC);
8823                :    DAMAGE_GC_FUNC_EPILOGUE (pGC);
8824                :}
8825                :
8826                :#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
8827                :    BoxPtr extents = &pGC->pCompositeClip->extents;\
8828                :    if(box.x1 < extents->x1) box.x1 = extents->x1; \
8829                :    if(box.x2 > extents->x2) box.x2 = extents->x2; \
8830                :    if(box.y1 < extents->y1) box.y1 = extents->y1; \
8831                :    if(box.y2 > extents->y2) box.y2 = extents->y2; \
8832                :    }
8833                :
8834                :#define TRANSLATE_BOX(box, pDrawable) { \
8835                :    box.x1 += pDrawable->x; \
8836                :    box.x2 += pDrawable->x; \
8837                :    box.y1 += pDrawable->y; \
8838                :    box.y2 += pDrawable->y; \
8839                :    }
8840                :
8841                :#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
8842                :    TRANSLATE_BOX(box, pDrawable); \
8843                :    TRIM_BOX(box, pGC); \
8844                :    }
8845                :
8846                :#define BOX_NOT_EMPTY(box) \
8847                :    (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
8848                :
8849                :#define checkGCDamage(d,g)      (getDrawableDamage(d) && \
8850                :                                 (!g->pCompositeClip ||\
8851                :                                  REGION_NOTEMPTY(d->pScreen, \
8852                :                                                  g->pCompositeClip)))
8853                :
8854                :#ifdef RENDER
8855                :
8856                :#define TRIM_PICTURE_BOX(box, pDst) { \
8857                :    BoxPtr extents = &pDst->pCompositeClip->extents;\
8858                :    if(box.x1 < extents->x1) box.x1 = extents->x1; \
8859                :    if(box.x2 > extents->x2) box.x2 = extents->x2; \
8860                :    if(box.y1 < extents->y1) box.y1 = extents->y1; \
8861                :    if(box.y2 > extents->y2) box.y2 = extents->y2; \
8862                :    }
8863                :    
8864                :#define checkPictureDamage(p)   (getDrawableDamage(p->pDrawable) && \
8865                :                                 REGION_NOTEMPTY(pScreen, p->pCompositeClip))
8866                :
8867                :static void
8868                :damageComposite (CARD8      op,
8869                :                   PicturePtr pSrc,
8870                :                   PicturePtr pMask,
8871                :                   PicturePtr pDst,
8872                :                   INT16      xSrc,
8873                :                   INT16      ySrc,
8874                :                   INT16      xMask,
8875                :                   INT16      yMask,
8876                :                   INT16      xDst,
8877                :                   INT16      yDst,
8878                :                   CARD16     width,
8879                :                   CARD16     height)
8880      1  0.0011 :{ /* damageComposite total:      6  0.0065 */
8881                :    ScreenPtr           pScreen = pDst->pDrawable->pScreen;
8882                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
8883                :    damageScrPriv(pScreen);
8884                :
8885      1  0.0011 :    if (checkPictureDamage (pDst))
8886                :    {
8887                :        BoxRec  box;
8888                :
8889                :        box.x1 = xDst + pDst->pDrawable->x;
8890                :        box.y1 = yDst + pDst->pDrawable->y;
8891                :        box.x2 = box.x1 + width;
8892                :        box.y2 = box.y1 + height;
8893                :        TRIM_PICTURE_BOX(box, pDst);
8894                :        if (BOX_NOT_EMPTY(box))
8895      1  0.0011 :            damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
8896                :    }
8897                :    unwrap (pScrPriv, ps, Composite);
8898                :    (*ps->Composite) (op,
8899                :                       pSrc,
8900                :                       pMask,
8901                :                       pDst,
8902                :                       xSrc,
8903                :                       ySrc,
8904                :                       xMask,
8905                :                       yMask,
8906                :                       xDst,
8907                :                       yDst,
8908                :                       width,
8909                :                       height);
8910      3  0.0033 :    damageReportPostOp (pDst->pDrawable);
8911                :    wrap (pScrPriv, ps, Composite, damageComposite);
8912                :}
8913                :
8914                :static void
8915                :damageGlyphs (CARD8             op,
8916                :                PicturePtr      pSrc,
8917                :                PicturePtr      pDst,
8918                :                PictFormatPtr   maskFormat,
8919                :                INT16           xSrc,
8920                :                INT16           ySrc,
8921                :                int             nlist,
8922                :                GlyphListPtr    list,
8923                :                GlyphPtr        *glyphs)
8924                :{ /* damageGlyphs total:     61  0.0665 */
8925                :    ScreenPtr           pScreen = pDst->pDrawable->pScreen;
8926                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
8927                :    damageScrPriv(pScreen);
8928                :
8929                :    if (checkPictureDamage (pDst))
8930                :    {
8931                :        int             nlistTmp = nlist;
8932                :        GlyphListPtr    listTmp = list;
8933                :        GlyphPtr        *glyphsTmp = glyphs;
8934                :        int             x, y;
8935                :        int             n;
8936                :        GlyphPtr        glyph;
8937                :        BoxRec          box;
8938                :        int             x1, y1, x2, y2;
8939                :
8940                :        box.x1 = 32767;
8941                :        box.y1 = 32767;
8942                :        box.x2 = -32767;
8943                :        box.y2 = -32767;
8944                :        x = pDst->pDrawable->x;
8945                :        y = pDst->pDrawable->y;
8946      1  0.0011 :        while (nlistTmp--)
8947                :        {
8948      1  0.0011 :            x += listTmp->xOff;
8949                :            y += listTmp->yOff;
8950                :            n = listTmp->len;
8951      1  0.0011 :            while (n--)
8952                :            {
8953      2  0.0022 :                glyph = *glyphsTmp++;
8954     31  0.0338 :                x1 = x - glyph->info.x;
8955      3  0.0033 :                y1 = y - glyph->info.y;
8956      1  0.0011 :                x2 = x1 + glyph->info.width;
8957      1  0.0011 :                y2 = y1 + glyph->info.height;
8958                :                if (x1 < box.x1)
8959                :                    box.x1 = x1;
8960      1  0.0011 :                if (y1 < box.y1)
8961                :                    box.y1 = y1;
8962      5  0.0054 :                if (x2 > box.x2)
8963      2  0.0022 :                    box.x2 = x2;
8964      2  0.0022 :                if (y2 > box.y2)
8965      1  0.0011 :                    box.y2 = y2;
8966      2  0.0022 :                x += glyph->info.xOff;
8967      2  0.0022 :                y += glyph->info.yOff;
8968                :            }
8969                :            listTmp++;
8970                :        }
8971      1  0.0011 :        TRIM_PICTURE_BOX (box, pDst);
8972                :        if (BOX_NOT_EMPTY(box))
8973      1  0.0011 :            damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
8974                :    }
8975      1  0.0011 :    unwrap (pScrPriv, ps, Glyphs);
8976      1  0.0011 :    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
8977                :    damageReportPostOp (pDst->pDrawable);
8978                :    wrap (pScrPriv, ps, Glyphs, damageGlyphs);
8979      1  0.0011 :}
8980                :#endif
8981                :
8982                :/**********************************************************/
8983                :
8984                :
8985                :static void
8986                :damageFillSpans(DrawablePtr pDrawable,
8987                :                GC          *pGC,
8988                :                int         npt,
8989                :                DDXPointPtr ppt,
8990                :                int         *pwidth,
8991                :                int         fSorted)
8992                :{
8993                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
8994                :
8995                :    if (npt && checkGCDamage (pDrawable, pGC))
8996                :    {
8997                :        int         nptTmp = npt;
8998                :        DDXPointPtr pptTmp = ppt;
8999                :        int         *pwidthTmp = pwidth;
9000                :        BoxRec      box;
9001                :
9002                :        box.x1 = pptTmp->x;
9003                :        box.x2 = box.x1 + *pwidthTmp;
9004                :        box.y2 = box.y1 = pptTmp->y;
9005                :
9006                :        while(--nptTmp) 
9007                :        {
9008                :           pptTmp++;
9009                :           pwidthTmp++;
9010                :           if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
9011                :           if(box.x2 < (pptTmp->x + *pwidthTmp))
9012                :                box.x2 = pptTmp->x + *pwidthTmp;
9013                :           if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
9014                :           else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
9015                :        }
9016                :
9017                :        box.y2++;
9018                :
9019                :        if(!pGC->miTranslate) {
9020                :           TRANSLATE_BOX(box, pDrawable);
9021                :        }
9022                :        TRIM_BOX(box, pGC); 
9023                :
9024                :        if(BOX_NOT_EMPTY(box))
9025                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9026                :    }
9027                :    
9028                :    (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted);
9029                :
9030                :    damageReportPostOp (pDrawable);
9031                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9032                :}
9033                :
9034                :static void
9035                :damageSetSpans(DrawablePtr  pDrawable,
9036                :               GCPtr        pGC,
9037                :               char         *pcharsrc,
9038                :               DDXPointPtr  ppt,
9039                :               int          *pwidth,
9040                :               int          npt,
9041                :               int          fSorted)
9042                :{
9043                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9044                :
9045                :    if (npt && checkGCDamage (pDrawable, pGC))
9046                :    {
9047                :        DDXPointPtr pptTmp = ppt;
9048                :        int         *pwidthTmp = pwidth;
9049                :        int         nptTmp = npt;
9050                :        BoxRec      box;
9051                :
9052                :        box.x1 = pptTmp->x;
9053                :        box.x2 = box.x1 + *pwidthTmp;
9054                :        box.y2 = box.y1 = pptTmp->y;
9055                :
9056                :        while(--nptTmp) 
9057                :        {
9058                :           pptTmp++;
9059                :           pwidthTmp++;
9060                :           if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
9061                :           if(box.x2 < (pptTmp->x + *pwidthTmp))
9062                :                box.x2 = pptTmp->x + *pwidthTmp;
9063                :           if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
9064                :           else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
9065                :        }
9066                :
9067                :        box.y2++;
9068                :
9069                :        if(!pGC->miTranslate) {
9070                :           TRANSLATE_BOX(box, pDrawable);
9071                :        }
9072                :        TRIM_BOX(box, pGC); 
9073                :
9074                :        if(BOX_NOT_EMPTY(box))
9075                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9076                :    }
9077                :    (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
9078                :    damageReportPostOp (pDrawable);
9079                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9080                :}
9081                :
9082                :static void
9083                :damagePutImage(DrawablePtr  pDrawable,
9084                :               GCPtr        pGC,
9085                :               int          depth,
9086                :               int          x,
9087                :               int          y,
9088                :               int          w,
9089                :               int          h,
9090                :               int          leftPad,
9091                :               int          format,
9092                :               char         *pImage)
9093                :{
9094                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9095                :    if (checkGCDamage (pDrawable, pGC))
9096                :    {
9097                :        BoxRec box;
9098                :
9099                :        box.x1 = x + pDrawable->x;
9100                :        box.x2 = box.x1 + w;
9101                :        box.y1 = y + pDrawable->y;
9102                :        box.y2 = box.y1 + h;
9103                :
9104                :        TRIM_BOX(box, pGC);
9105                :        if(BOX_NOT_EMPTY(box))
9106                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9107                :    }
9108                :    (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
9109                :                leftPad, format, pImage);
9110                :    damageReportPostOp (pDrawable);
9111                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9112                :}
9113                :
9114                :static RegionPtr
9115                :damageCopyArea(DrawablePtr   pSrc,
9116                :               DrawablePtr  pDst,
9117                :               GC           *pGC,
9118                :               int          srcx,
9119                :               int          srcy,
9120                :               int          width,
9121                :               int          height,
9122                :               int          dstx,
9123                :               int          dsty)
9124                :{
9125                :    RegionPtr ret;
9126                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
9127                :    
9128                :    /* The driver will only call SourceValidate() when pSrc != pDst,
9129                :     * but the software sprite (misprite.c) always need to know when a
9130                :     * drawable is copied so it can remove the sprite. See #1030. */
9131                :    if ((pSrc == pDst) && pSrc->pScreen->SourceValidate &&
9132                :        pSrc->type == DRAWABLE_WINDOW &&
9133                :        ((WindowPtr)pSrc)->viewable)
9134                :    {
9135                :        (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
9136                :    }
9137                :    
9138                :    if (checkGCDamage (pDst, pGC))
9139                :    {
9140                :        BoxRec box;
9141                :
9142                :        box.x1 = dstx + pDst->x;
9143                :        box.x2 = box.x1 + width;
9144                :        box.y1 = dsty + pDst->y;
9145                :        box.y2 = box.y1 + height;
9146                :
9147                :        TRIM_BOX(box, pGC);
9148                :        if(BOX_NOT_EMPTY(box))
9149                :           damageDamageBox (pDst, &box, pGC->subWindowMode);
9150                :    }
9151                :
9152                :    ret = (*pGC->ops->CopyArea)(pSrc, pDst,
9153                :            pGC, srcx, srcy, width, height, dstx, dsty);
9154                :    damageReportPostOp (pDst);
9155                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
9156                :    return ret;
9157                :}
9158                :
9159                :static RegionPtr
9160                :damageCopyPlane(DrawablePtr     pSrc,
9161                :                DrawablePtr     pDst,
9162                :                GCPtr           pGC,
9163                :                int             srcx,
9164                :                int             srcy,
9165                :                int             width,
9166                :                int             height,
9167                :                int             dstx,
9168                :                int             dsty,
9169                :                unsigned long   bitPlane)
9170                :{
9171                :    RegionPtr ret;
9172                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
9173                :
9174                :    /* The driver will only call SourceValidate() when pSrc != pDst,
9175                :     * but the software sprite (misprite.c) always need to know when a
9176                :     * drawable is copied so it can remove the sprite. See #1030. */
9177                :    if ((pSrc == pDst) && pSrc->pScreen->SourceValidate &&
9178                :        pSrc->type == DRAWABLE_WINDOW &&
9179                :        ((WindowPtr)pSrc)->viewable)
9180                :    {
9181                :        (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
9182                :    }
9183                :
9184                :    if (checkGCDamage (pDst, pGC))
9185                :    {
9186                :        BoxRec box;
9187                :
9188                :        box.x1 = dstx + pDst->x;
9189                :        box.x2 = box.x1 + width;
9190                :        box.y1 = dsty + pDst->y;
9191                :        box.y2 = box.y1 + height;
9192                :
9193                :        TRIM_BOX(box, pGC);
9194                :        if(BOX_NOT_EMPTY(box))
9195                :           damageDamageBox (pDst, &box, pGC->subWindowMode);
9196                :    }
9197                :
9198                :    ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
9199                :               pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
9200                :    damageReportPostOp (pDst);
9201                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
9202                :    return ret;
9203                :}
9204                :
9205                :static void
9206                :damagePolyPoint(DrawablePtr pDrawable,
9207                :                GCPtr       pGC,
9208                :                int         mode,
9209                :                int         npt,
9210                :                xPoint      *ppt)
9211                :{
9212                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9213                :
9214                :    if (npt && checkGCDamage (pDrawable, pGC))
9215                :    {
9216                :        BoxRec  box;
9217                :        int     nptTmp = npt;
9218                :        xPoint  *pptTmp = ppt;
9219                :
9220                :        box.x2 = box.x1 = pptTmp->x;
9221                :        box.y2 = box.y1 = pptTmp->y;
9222                :
9223                :        /* this could be slow if the points were spread out */
9224                :
9225                :        while(--nptTmp) 
9226                :        {
9227                :           pptTmp++;
9228                :           if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
9229                :           else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
9230                :           if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
9231                :           else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
9232                :        }
9233                :
9234                :        box.x2++;
9235                :        box.y2++;
9236                :
9237                :        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9238                :        if(BOX_NOT_EMPTY(box))
9239                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9240                :    }
9241                :    (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt);
9242                :    damageReportPostOp (pDrawable);
9243                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9244                :}
9245                :
9246                :static void
9247                :damagePolylines(DrawablePtr pDrawable,
9248                :                GCPtr       pGC,
9249                :                int         mode,
9250                :                int         npt,
9251                :                DDXPointPtr ppt)
9252                :{
9253                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9254                :
9255                :    if (npt && checkGCDamage (pDrawable, pGC))
9256                :    {
9257                :        int         nptTmp = npt;
9258                :        DDXPointPtr pptTmp = ppt;
9259                :        BoxRec      box;
9260                :        int         extra = pGC->lineWidth >> 1;
9261                :
9262                :        box.x2 = box.x1 = pptTmp->x;
9263                :        box.y2 = box.y1 = pptTmp->y;
9264                :
9265                :        if(nptTmp > 1) 
9266                :        {
9267                :           if(pGC->joinStyle == JoinMiter)
9268                :                extra = 6 * pGC->lineWidth;
9269                :           else if(pGC->capStyle == CapProjecting)
9270                :                extra = pGC->lineWidth;
9271                :        }
9272                :
9273                :        if(mode == CoordModePrevious) 
9274                :        {
9275                :           int x = box.x1;
9276                :           int y = box.y1;
9277                :           while(--nptTmp) 
9278                :           {
9279                :                pptTmp++;
9280                :                x += pptTmp->x;
9281                :                y += pptTmp->y;
9282                :                if(box.x1 > x) box.x1 = x;
9283                :                else if(box.x2 < x) box.x2 = x;
9284                :                if(box.y1 > y) box.y1 = y;
9285                :                else if(box.y2 < y) box.y2 = y;
9286                :            }
9287                :        }
9288                :        else 
9289                :        {
9290                :           while(--nptTmp) 
9291                :           {
9292                :                pptTmp++;
9293                :                if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
9294                :                else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
9295                :                if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
9296                :                else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
9297                :            }
9298                :        }
9299                :
9300                :        box.x2++;
9301                :        box.y2++;
9302                :
9303                :        if(extra) 
9304                :        {
9305                :           box.x1 -= extra;
9306                :           box.x2 += extra;
9307                :           box.y1 -= extra;
9308                :           box.y2 += extra;
9309                :        }
9310                :
9311                :        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9312                :        if(BOX_NOT_EMPTY(box))
9313                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9314                :    }
9315                :    (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt);
9316                :    damageReportPostOp (pDrawable);
9317                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9318                :}
9319                :
9320                :static void
9321                :damagePolySegment(DrawablePtr   pDrawable,
9322                :                  GCPtr         pGC,
9323                :                  int           nSeg,
9324                :                  xSegment      *pSeg)
9325                :{ /* damagePolySegment total:      1  0.0011 */
9326                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9327                :
9328                :    if (nSeg && checkGCDamage (pDrawable, pGC))
9329                :    {
9330                :        BoxRec      box;
9331                :        int         extra = pGC->lineWidth;
9332                :        int         nsegTmp = nSeg;
9333                :        xSegment    *pSegTmp = pSeg;
9334                :
9335                :        if(pGC->capStyle != CapProjecting)
9336                :           extra >>= 1;
9337                :
9338                :        if(pSegTmp->x2 > pSegTmp->x1) {
9339                :            box.x1 = pSegTmp->x1;
9340                :            box.x2 = pSegTmp->x2;
9341                :        } else {
9342                :            box.x2 = pSegTmp->x1;
9343                :            box.x1 = pSegTmp->x2;
9344                :        }
9345                :
9346                :        if(pSegTmp->y2 > pSegTmp->y1) {
9347                :            box.y1 = pSegTmp->y1;
9348                :            box.y2 = pSegTmp->y2;
9349                :        } else {
9350                :            box.y2 = pSegTmp->y1;
9351                :            box.y1 = pSegTmp->y2;
9352                :        }
9353                :
9354                :        while(--nsegTmp) 
9355                :        {
9356                :            pSegTmp++;
9357                :            if(pSegTmp->x2 > pSegTmp->x1) 
9358                :            {
9359                :                if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1;
9360                :                if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2;
9361                :            }
9362                :            else 
9363                :            {
9364                :                if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2;
9365                :                if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1;
9366                :            }
9367                :            if(pSegTmp->y2 > pSegTmp->y1) 
9368                :            {
9369                :                if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1;
9370                :                if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2;
9371                :            }
9372                :            else
9373                :            {
9374                :                if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2;
9375                :                if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1;
9376                :            }
9377                :        }
9378                :
9379                :        box.x2++;
9380                :        box.y2++;
9381                :
9382                :        if(extra) 
9383                :        {
9384                :           box.x1 -= extra;
9385                :           box.x2 += extra;
9386                :           box.y1 -= extra;
9387                :           box.y2 += extra;
9388                :        }
9389                :
9390      1  0.0011 :        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9391                :        if(BOX_NOT_EMPTY(box))
9392                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9393                :    }
9394                :    (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg);
9395                :    damageReportPostOp (pDrawable);
9396                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9397                :}
9398                :
9399                :static void
9400                :damagePolyRectangle(DrawablePtr  pDrawable,
9401                :                    GCPtr        pGC,
9402                :                    int          nRects,
9403                :                    xRectangle  *pRects)
9404                :{
9405                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9406                :
9407                :    if (nRects && checkGCDamage (pDrawable, pGC))
9408                :    {
9409                :        BoxRec      box;
9410                :        int         offset1, offset2, offset3;
9411                :        int         nRectsTmp = nRects;
9412                :        xRectangle  *pRectsTmp = pRects;
9413                :
9414                :        offset2 = pGC->lineWidth;
9415                :        if(!offset2) offset2 = 1;
9416                :        offset1 = offset2 >> 1;
9417                :        offset3 = offset2 - offset1;
9418                :
9419                :        while(nRectsTmp--)
9420                :        {
9421                :            box.x1 = pRectsTmp->x - offset1;
9422                :            box.y1 = pRectsTmp->y - offset1;
9423                :            box.x2 = box.x1 + pRectsTmp->width + offset2;
9424                :            box.y2 = box.y1 + offset2;
9425                :            TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9426                :            if(BOX_NOT_EMPTY(box))
9427                :                damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9428                :
9429                :            box.x1 = pRectsTmp->x - offset1;
9430                :            box.y1 = pRectsTmp->y + offset3;
9431                :            box.x2 = box.x1 + offset2;
9432                :            box.y2 = box.y1 + pRectsTmp->height - offset2;
9433                :            TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9434                :            if(BOX_NOT_EMPTY(box))
9435                :                damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9436                :
9437                :            box.x1 = pRectsTmp->x + pRectsTmp->width - offset1;
9438                :            box.y1 = pRectsTmp->y + offset3;
9439                :            box.x2 = box.x1 + offset2;
9440                :            box.y2 = box.y1 + pRectsTmp->height - offset2;
9441                :            TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9442                :            if(BOX_NOT_EMPTY(box))
9443                :                damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9444                :
9445                :            box.x1 = pRectsTmp->x - offset1;
9446                :            box.y1 = pRectsTmp->y + pRectsTmp->height - offset1;
9447                :            box.x2 = box.x1 + pRectsTmp->width + offset2;
9448                :            box.y2 = box.y1 + offset2;
9449                :            TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9450                :            if(BOX_NOT_EMPTY(box))
9451                :                damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9452                :
9453                :            pRectsTmp++;
9454                :        }
9455                :    }
9456                :    (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects);
9457                :    damageReportPostOp (pDrawable);
9458                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9459                :}
9460                :
9461                :static void
9462                :damagePolyArc(DrawablePtr   pDrawable,
9463                :              GCPtr         pGC,
9464                :              int           nArcs,
9465                :              xArc          *pArcs)
9466                :{
9467                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9468                :
9469                :    if (nArcs && checkGCDamage (pDrawable, pGC))
9470                :    {
9471                :        int     extra = pGC->lineWidth >> 1;
9472                :        BoxRec  box;
9473                :        int     nArcsTmp = nArcs;
9474                :        xArc    *pArcsTmp = pArcs;
9475                :
9476                :        box.x1 = pArcsTmp->x;
9477                :        box.x2 = box.x1 + pArcsTmp->width;
9478                :        box.y1 = pArcsTmp->y;
9479                :        box.y2 = box.y1 + pArcsTmp->height;
9480                :
9481                :        while(--nArcsTmp) 
9482                :        {
9483                :            pArcsTmp++;
9484                :            if(box.x1 > pArcsTmp->x)
9485                :                box.x1 = pArcsTmp->x;
9486                :            if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
9487                :                box.x2 = pArcsTmp->x + pArcsTmp->width;
9488                :            if(box.y1 > pArcsTmp->y) 
9489                :                box.y1 = pArcsTmp->y;
9490                :            if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
9491                :                box.y2 = pArcsTmp->y + pArcsTmp->height;
9492                :        }
9493                :
9494                :        if(extra) 
9495                :        {
9496                :           box.x1 -= extra;
9497                :           box.x2 += extra;
9498                :           box.y1 -= extra;
9499                :           box.y2 += extra;
9500                :        }
9501                :
9502                :        box.x2++;
9503                :        box.y2++;
9504                :
9505                :        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9506                :        if(BOX_NOT_EMPTY(box))
9507                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9508                :    }
9509                :    (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs);
9510                :    damageReportPostOp (pDrawable);
9511                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9512                :}
9513                :
9514                :static void
9515                :damageFillPolygon(DrawablePtr   pDrawable,
9516                :                  GCPtr         pGC,
9517                :                  int           shape,
9518                :                  int           mode,
9519                :                  int           npt,
9520                :                  DDXPointPtr   ppt)
9521                :{
9522                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9523                :
9524                :    if (npt > 2 && checkGCDamage (pDrawable, pGC))
9525                :    {
9526                :        DDXPointPtr pptTmp = ppt;
9527                :        int         nptTmp = npt;
9528                :        BoxRec      box;
9529                :
9530                :        box.x2 = box.x1 = pptTmp->x;
9531                :        box.y2 = box.y1 = pptTmp->y;
9532                :
9533                :        if(mode != CoordModeOrigin) 
9534                :        {
9535                :           int x = box.x1;
9536                :           int y = box.y1;
9537                :           while(--nptTmp) 
9538                :           {
9539                :                pptTmp++;
9540                :                x += pptTmp->x;
9541                :                y += pptTmp->y;
9542                :                if(box.x1 > x) box.x1 = x;
9543                :                else if(box.x2 < x) box.x2 = x;
9544                :                if(box.y1 > y) box.y1 = y;
9545                :                else if(box.y2 < y) box.y2 = y;
9546                :            }
9547                :        }
9548                :        else 
9549                :        {
9550                :           while(--nptTmp) 
9551                :           {
9552                :                pptTmp++;
9553                :                if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
9554                :                else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
9555                :                if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
9556                :                else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
9557                :            }
9558                :        }
9559                :
9560                :        box.x2++;
9561                :        box.y2++;
9562                :
9563                :        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9564                :        if(BOX_NOT_EMPTY(box))
9565                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9566                :    }
9567                :    
9568                :    (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt);
9569                :    damageReportPostOp (pDrawable);
9570                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9571                :}
9572                :
9573                :
9574                :static void
9575                :damagePolyFillRect(DrawablePtr  pDrawable,
9576                :                   GCPtr        pGC,
9577                :                   int          nRects,
9578                :                   xRectangle   *pRects)
9579      2  0.0022 :{ /* damagePolyFillRect total:     17  0.0185 */
9580      2  0.0022 :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9581      2  0.0022 :    if (nRects && checkGCDamage (pDrawable, pGC))
9582                :    {
9583                :        BoxRec      box;
9584                :        xRectangle  *pRectsTmp = pRects;
9585                :        int         nRectsTmp = nRects;
9586                :
9587                :        box.x1 = pRectsTmp->x;
9588                :        box.x2 = box.x1 + pRectsTmp->width;
9589                :        box.y1 = pRectsTmp->y;
9590                :        box.y2 = box.y1 + pRectsTmp->height;
9591                :
9592      2  0.0022 :        while(--nRectsTmp) 
9593                :        {
9594                :            pRectsTmp++;
9595                :            if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x;
9596                :            if(box.x2 < (pRectsTmp->x + pRectsTmp->width))
9597                :                box.x2 = pRectsTmp->x + pRectsTmp->width;
9598      1  0.0011 :            if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y;
9599                :            if(box.y2 < (pRectsTmp->y + pRectsTmp->height))
9600                :                box.y2 = pRectsTmp->y + pRectsTmp->height;
9601                :        }
9602                :
9603      4  0.0044 :        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9604      1  0.0011 :        if(BOX_NOT_EMPTY(box))
9605      1  0.0011 :            damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9606                :    }
9607      1  0.0011 :    (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects);
9608      1  0.0011 :    damageReportPostOp (pDrawable);
9609                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9610                :}
9611                :
9612                :
9613                :static void
9614                :damagePolyFillArc(DrawablePtr   pDrawable,
9615                :                  GCPtr         pGC,
9616                :                  int           nArcs,
9617                :                  xArc          *pArcs)
9618                :{
9619                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9620                :
9621                :    if (nArcs && checkGCDamage (pDrawable, pGC))
9622                :    {
9623                :        BoxRec  box;
9624                :        int     nArcsTmp = nArcs;
9625                :        xArc    *pArcsTmp = pArcs;
9626                :
9627                :        box.x1 = pArcsTmp->x;
9628                :        box.x2 = box.x1 + pArcsTmp->width;
9629                :        box.y1 = pArcsTmp->y;
9630                :        box.y2 = box.y1 + pArcsTmp->height;
9631                :
9632                :        while(--nArcsTmp) 
9633                :        {
9634                :            pArcsTmp++;
9635                :            if(box.x1 > pArcsTmp->x)
9636                :                box.x1 = pArcsTmp->x;
9637                :            if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
9638                :                box.x2 = pArcsTmp->x + pArcsTmp->width;
9639                :            if(box.y1 > pArcsTmp->y)
9640                :                box.y1 = pArcsTmp->y;
9641                :            if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
9642                :                box.y2 = pArcsTmp->y + pArcsTmp->height;
9643                :        }
9644                :
9645                :        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
9646                :        if(BOX_NOT_EMPTY(box))
9647                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9648                :    }
9649                :    (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs);
9650                :    damageReportPostOp (pDrawable);
9651                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9652                :}
9653                :
9654                :/*
9655                : * general Poly/Image text function.  Extract glyph information,
9656                : * compute bounding box and remove cursor if it is overlapped.
9657                : */
9658                :
9659                :static void
9660                :damageDamageChars (DrawablePtr  pDrawable,
9661                :                   FontPtr      font,
9662                :                   int          x,
9663                :                   int          y,
9664                :                   unsigned int n,
9665                :                   CharInfoPtr  *charinfo,
9666                :                   Bool         imageblt,
9667                :                   int          subWindowMode)
9668                :{
9669                :    ExtentInfoRec   extents;
9670                :    BoxRec          box;
9671                :
9672                :    QueryGlyphExtents(font, charinfo, n, &extents);
9673                :    if (imageblt)
9674                :    {
9675                :        if (extents.overallWidth > extents.overallRight)
9676                :            extents.overallRight = extents.overallWidth;
9677                :        if (extents.overallWidth < extents.overallLeft)
9678                :            extents.overallLeft = extents.overallWidth;
9679                :        if (extents.overallLeft > 0)
9680                :            extents.overallLeft = 0;
9681                :        if (extents.fontAscent > extents.overallAscent)
9682                :            extents.overallAscent = extents.fontAscent;
9683                :        if (extents.fontDescent > extents.overallDescent)
9684                :            extents.overallDescent = extents.fontDescent;
9685                :    }
9686                :    box.x1 = x + extents.overallLeft;
9687                :    box.y1 = y - extents.overallAscent;
9688                :    box.x2 = x + extents.overallRight;
9689                :    box.y2 = y + extents.overallDescent;
9690                :    damageDamageBox (pDrawable, &box, subWindowMode);
9691                :}
9692                :
9693                :/*
9694                : * values for textType:
9695                : */
9696                :#define TT_POLY8   0
9697                :#define TT_IMAGE8  1
9698                :#define TT_POLY16  2
9699                :#define TT_IMAGE16 3
9700                :
9701                :static int 
9702                :damageText (DrawablePtr     pDrawable,
9703                :            GCPtr           pGC,
9704                :            int             x,
9705                :            int             y,
9706                :            unsigned long   count,
9707                :            char            *chars,
9708                :            FontEncoding    fontEncoding,
9709                :            Bool            textType)
9710                :{
9711                :    CharInfoPtr     *charinfo;
9712                :    CharInfoPtr     *info;
9713                :    unsigned long   i;
9714                :    unsigned int    n;
9715                :    int             w;
9716                :    Bool            imageblt;
9717                :
9718                :    imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
9719                :
9720                :    charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
9721                :    if (!charinfo)
9722                :        return x;
9723                :
9724                :    GetGlyphs(pGC->font, count, (unsigned char *)chars,
9725                :              fontEncoding, &i, charinfo);
9726                :    n = (unsigned int)i;
9727                :    w = 0;
9728                :    if (!imageblt)
9729                :        for (info = charinfo; i--; info++)
9730                :            w += (*info)->metrics.characterWidth;
9731                :
9732                :    if (n != 0) {
9733                :        damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n,
9734                :                           charinfo, imageblt, pGC->subWindowMode);
9735                :        if (imageblt)
9736                :            (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
9737                :                                       FONTGLYPHS(pGC->font));
9738                :        else
9739                :            (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
9740                :                                      FONTGLYPHS(pGC->font));
9741                :    }
9742                :    DEALLOCATE_LOCAL(charinfo);
9743                :    return x + w;
9744                :}
9745                :
9746                :static int
9747                :damagePolyText8(DrawablePtr pDrawable,
9748                :                GCPtr       pGC,
9749                :                int         x,
9750                :                int         y,
9751                :                int         count,
9752                :                char        *chars)
9753                :{
9754                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9755                :
9756                :    if (checkGCDamage (pDrawable, pGC))
9757                :        x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
9758                :                    Linear8Bit, TT_POLY8);
9759                :    else
9760                :        x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
9761                :    damageReportPostOp (pDrawable);
9762                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9763                :    return x;
9764                :}
9765                :
9766                :static int
9767                :damagePolyText16(DrawablePtr    pDrawable,
9768                :                 GCPtr          pGC,
9769                :                 int            x,
9770                :                 int            y,
9771                :                 int            count,
9772                :                 unsigned short *chars)
9773                :{
9774                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9775                :
9776                :    if (checkGCDamage (pDrawable, pGC))
9777                :        x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
9778                :                    FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
9779                :                    TT_POLY16);
9780                :    else
9781                :        x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
9782                :    damageReportPostOp (pDrawable);
9783                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9784                :    return x;
9785                :}
9786                :
9787                :static void
9788                :damageImageText8(DrawablePtr    pDrawable,
9789                :                 GCPtr          pGC,
9790                :                 int            x,
9791                :                 int            y,
9792                :                 int            count,
9793                :                 char           *chars)
9794                :{
9795                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9796                :
9797                :    if (checkGCDamage (pDrawable, pGC))
9798                :        damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
9799                :                    Linear8Bit, TT_IMAGE8);
9800                :    else
9801                :        (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
9802                :    damageReportPostOp (pDrawable);
9803                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9804                :}
9805                :
9806                :static void
9807                :damageImageText16(DrawablePtr   pDrawable,
9808                :                  GCPtr         pGC,
9809                :                  int           x,
9810                :                  int           y,
9811                :                  int           count,
9812                :                  unsigned short *chars)
9813                :{
9814                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9815                :
9816                :    if (checkGCDamage (pDrawable, pGC))
9817                :        damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
9818                :                    FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
9819                :                    TT_IMAGE16);
9820                :    else
9821                :        (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
9822                :    damageReportPostOp (pDrawable);
9823                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9824                :}
9825                :
9826                :
9827                :static void
9828                :damageImageGlyphBlt(DrawablePtr     pDrawable,
9829                :                    GCPtr           pGC,
9830                :                    int             x,
9831                :                    int             y,
9832                :                    unsigned int    nglyph,
9833                :                    CharInfoPtr     *ppci,
9834                :                    pointer         pglyphBase)
9835                :{
9836                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9837                :    damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
9838                :                       nglyph, ppci, TRUE, pGC->subWindowMode);
9839                :    (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph,
9840                :                                        ppci, pglyphBase);
9841                :    damageReportPostOp (pDrawable);
9842                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9843                :}
9844                :
9845                :static void
9846                :damagePolyGlyphBlt(DrawablePtr  pDrawable,
9847                :                   GCPtr        pGC,
9848                :                   int          x,
9849                :                   int          y,
9850                :                   unsigned int nglyph,
9851                :                   CharInfoPtr  *ppci,
9852                :                   pointer      pglyphBase)
9853                :{
9854                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9855                :    damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
9856                :                       nglyph, ppci, FALSE, pGC->subWindowMode);
9857                :    (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
9858                :                                ppci, pglyphBase);
9859                :    damageReportPostOp (pDrawable);
9860                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9861                :}
9862                :
9863                :static void
9864                :damagePushPixels(GCPtr          pGC,
9865                :                 PixmapPtr      pBitMap,
9866                :                 DrawablePtr    pDrawable,
9867                :                 int            dx,
9868                :                 int            dy,
9869                :                 int            xOrg,
9870                :                 int            yOrg)
9871                :{
9872                :    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
9873                :    if(checkGCDamage (pDrawable, pGC))
9874                :    {
9875                :        BoxRec box;
9876                :
9877                :        box.x1 = xOrg;
9878                :        box.y1 = yOrg;
9879                :
9880                :        if(!pGC->miTranslate) {
9881                :           box.x1 += pDrawable->x;          
9882                :           box.y1 += pDrawable->y;          
9883                :        }
9884                :
9885                :        box.x2 = box.x1 + dx;
9886                :        box.y2 = box.y1 + dy;
9887                :
9888                :        TRIM_BOX(box, pGC);
9889                :        if(BOX_NOT_EMPTY(box))
9890                :           damageDamageBox (pDrawable, &box, pGC->subWindowMode);
9891                :    }
9892                :    (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
9893                :    damageReportPostOp (pDrawable);
9894                :    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
9895                :}
9896                :
9897                :static void
9898                :damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage)
9899      1  0.0011 :{ /* damageRemoveDamage total:      2  0.0022 */
9900                :    while (*pPrev)
9901                :    {
9902                :        if (*pPrev == pDamage)
9903                :        {
9904                :            *pPrev = pDamage->pNext;
9905                :            return;
9906                :        }
9907                :        pPrev = &(*pPrev)->pNext;
9908                :    }
9909                :#if DAMAGE_VALIDATE_ENABLE
9910                :    ErrorF ("Damage not on list\n");
9911                :    abort ();
9912                :#endif
9913      1  0.0011 :}
9914                :
9915                :static void
9916                :damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage)
9917      1  0.0011 :{ /* damageInsertDamage total:      1  0.0011 */
9918                :#if DAMAGE_VALIDATE_ENABLE
9919                :    DamagePtr   pOld;
9920                :
9921                :    for (pOld = *pPrev; pOld; pOld = pOld->pNext)
9922                :        if (pOld == pDamage) {
9923                :            ErrorF ("Damage already on list\n");
9924                :            abort ();
9925                :        }
9926                :#endif
9927                :    pDamage->pNext = *pPrev;
9928                :    *pPrev = pDamage;
9929                :}
9930                :
9931                :static Bool
9932                :damageDestroyPixmap (PixmapPtr pPixmap)
9933      3  0.0033 :{ /* damageDestroyPixmap total:     15  0.0163 */
9934                :    ScreenPtr   pScreen = pPixmap->drawable.pScreen;
9935      2  0.0022 :    damageScrPriv(pScreen);
9936                :
9937                :    if (pPixmap->refcnt == 1)
9938                :    {
9939      1  0.0011 :        DamagePtr       *pPrev = getPixmapDamageRef (pPixmap);
9940                :        DamagePtr       pDamage;
9941                :
9942                :        while ((pDamage = *pPrev))
9943                :        {
9944                :            damageRemoveDamage (pPrev, pDamage);
9945                :            if (!pDamage->isWindow)
9946                :                DamageDestroy (pDamage);
9947                :        }
9948                :    }
9949      3  0.0033 :    unwrap (pScrPriv, pScreen, DestroyPixmap);
9950      2  0.0022 :    (*pScreen->DestroyPixmap) (pPixmap);
9951      3  0.0033 :    wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
9952                :    return TRUE;
9953      1  0.0011 :}
9954                :
9955                :static void
9956                :damagePaintWindow(WindowPtr pWindow,
9957                :                  RegionPtr prgn,
9958                :                  int       what)
9959                :{
9960                :    ScreenPtr pScreen = pWindow->drawable.pScreen;
9961                :    damageScrPriv(pScreen);
9962                :
9963                :    /*
9964                :     * Painting background none doesn't actually *do* anything, so
9965                :     * no damage is recorded
9966                :     */
9967                :    if ((what != PW_BACKGROUND || pWindow->backgroundState != None) &&
9968                :        getWindowDamage (pWindow))
9969                :        damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1);
9970                :    if(what == PW_BACKGROUND) {
9971                :        unwrap (pScrPriv, pScreen, PaintWindowBackground);
9972                :        (*pScreen->PaintWindowBackground) (pWindow, prgn, what);
9973                :        damageReportPostOp (&pWindow->drawable);
9974                :        wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow);
9975                :    } else {
9976                :        unwrap (pScrPriv, pScreen, PaintWindowBorder);
9977                :        (*pScreen->PaintWindowBorder) (pWindow, prgn, what);
9978                :        damageReportPostOp (&pWindow->drawable);
9979                :        wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow);
9980                :    }
9981                :}
9982                :
9983                :
9984                :static void
9985                :damageCopyWindow(WindowPtr      pWindow,
9986                :                 DDXPointRec    ptOldOrg,
9987                :                 RegionPtr      prgnSrc)
9988                :{
9989                :    ScreenPtr pScreen = pWindow->drawable.pScreen;
9990                :    damageScrPriv(pScreen);
9991                :
9992                :    if (getWindowDamage (pWindow))
9993                :    {
9994                :        int dx = pWindow->drawable.x - ptOldOrg.x;
9995                :        int dy = pWindow->drawable.y - ptOldOrg.y;
9996                :        
9997                :        /*
9998                :         * The region comes in source relative, but the damage occurs
9999                :         * at the destination location.  Translate back and forth.
10000                :         */
10001                :        REGION_TRANSLATE (pScreen, prgnSrc, dx, dy);
10002                :        damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE, -1);
10003                :        REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
10004                :    }
10005                :    unwrap (pScrPriv, pScreen, CopyWindow);
10006                :    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
10007                :    damageReportPostOp (&pWindow->drawable);
10008                :    wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
10009                :}
10010                :
10011                :static GCOps damageGCOps = {
10012                :    damageFillSpans, damageSetSpans,
10013                :    damagePutImage, damageCopyArea,
10014                :    damageCopyPlane, damagePolyPoint,
10015                :    damagePolylines, damagePolySegment,
10016                :    damagePolyRectangle, damagePolyArc,
10017                :    damageFillPolygon, damagePolyFillRect,
10018                :    damagePolyFillArc, damagePolyText8,
10019                :    damagePolyText16, damageImageText8,
10020                :    damageImageText16, damageImageGlyphBlt,
10021                :    damagePolyGlyphBlt, damagePushPixels,
10022                :    {NULL}              /* devPrivate */
10023                :};
10024                :
10025                :static void
10026                :damageRestoreAreas (PixmapPtr   pPixmap,
10027                :                    RegionPtr   prgn,
10028                :                    int         xorg,
10029                :                    int         yorg,
10030                :                    WindowPtr   pWindow)
10031                :{
10032                :    ScreenPtr pScreen = pWindow->drawable.pScreen;
10033                :    damageScrPriv(pScreen);
10034                :
10035                :    damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1);
10036                :    unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
10037                :    (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn,
10038                :                                                xorg, yorg, pWindow);
10039                :    damageReportPostOp (&pWindow->drawable);
10040                :    wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
10041                :                             damageRestoreAreas);
10042                :}
10043                :
10044                :static void
10045                :damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
10046                :{
10047                :    DamagePtr   pDamage;
10048                :    ScreenPtr   pScreen = pWindow->drawable.pScreen;
10049                :    damageScrPriv(pScreen);
10050                :
10051                :    if ((pDamage = damageGetWinPriv(pWindow)))
10052                :    {
10053                :        PixmapPtr   pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow);
10054                :        DamagePtr   *pPrev = getPixmapDamageRef(pOldPixmap);
10055                :        
10056                :        while (pDamage)
10057                :        {
10058                :            damageRemoveDamage (pPrev, pDamage);
10059                :            pDamage = pDamage->pNextWin;
10060                :        }
10061                :    }
10062                :    unwrap (pScrPriv, pScreen, SetWindowPixmap);
10063                :    (*pScreen->SetWindowPixmap) (pWindow, pPixmap);
10064                :    wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
10065                :    if ((pDamage = damageGetWinPriv(pWindow)))
10066                :    {
10067                :        DamagePtr   *pPrev = getPixmapDamageRef(pPixmap);
10068                :        
10069                :        while (pDamage)
10070                :        {
10071                :            damageInsertDamage (pPrev, pDamage);
10072                :            pDamage = pDamage->pNextWin;
10073                :        }
10074                :    }
10075                :}
10076                :
10077                :static Bool
10078                :damageDestroyWindow (WindowPtr pWindow)
10079                :{
10080                :    DamagePtr   pDamage;
10081                :    ScreenPtr   pScreen = pWindow->drawable.pScreen;
10082                :    Bool        ret;
10083                :    damageScrPriv(pScreen);
10084                :
10085                :    while ((pDamage = damageGetWinPriv(pWindow)))
10086                :    {
10087                :        DamageUnregister (&pWindow->drawable, pDamage);
10088                :        DamageDestroy (pDamage);
10089                :    }
10090                :    unwrap (pScrPriv, pScreen, DestroyWindow);
10091                :    ret = (*pScreen->DestroyWindow) (pWindow);
10092                :    wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
10093                :    return ret;
10094                :}
10095                :
10096                :static Bool
10097                :damageCloseScreen (int i, ScreenPtr pScreen)
10098                :{
10099                :    damageScrPriv(pScreen);
10100                :
10101                :    unwrap (pScrPriv, pScreen, DestroyPixmap);
10102                :    unwrap (pScrPriv, pScreen, CreateGC);
10103                :    unwrap (pScrPriv, pScreen, PaintWindowBackground);
10104                :    unwrap (pScrPriv, pScreen, PaintWindowBorder);
10105                :    unwrap (pScrPriv, pScreen, CopyWindow);
10106                :    unwrap (pScrPriv, pScreen, CloseScreen);
10107                :    unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
10108                :    xfree (pScrPriv);
10109                :    return (*pScreen->CloseScreen) (i, pScreen);
10110                :}
10111                :
10112                :Bool
10113                :DamageSetup (ScreenPtr pScreen)
10114                :{
10115                :    DamageScrPrivPtr    pScrPriv;
10116                :#ifdef RENDER
10117                :    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
10118                :#endif
10119                :
10120                :    if (damageGeneration != serverGeneration)
10121                :    {
10122                :        damageScrPrivateIndex = AllocateScreenPrivateIndex ();
10123                :        if (damageScrPrivateIndex == -1)
10124                :            return FALSE;
10125                :        damageGCPrivateIndex = AllocateGCPrivateIndex ();
10126                :        if (damageGCPrivateIndex == -1)
10127                :            return FALSE;
10128                :        damagePixPrivateIndex = AllocatePixmapPrivateIndex ();
10129                :        if (damagePixPrivateIndex == -1)
10130                :            return FALSE;
10131                :        damageWinPrivateIndex = AllocateWindowPrivateIndex ();
10132                :        if (damageWinPrivateIndex == -1)
10133                :            return FALSE;
10134                :        damageGeneration = serverGeneration;
10135                :    }
10136                :    if (pScreen->devPrivates[damageScrPrivateIndex].ptr)
10137                :        return TRUE;
10138                :
10139                :    if (!AllocateGCPrivate (pScreen, damageGCPrivateIndex, sizeof (DamageGCPrivRec)))
10140                :        return FALSE;
10141                :    if (!AllocatePixmapPrivate (pScreen, damagePixPrivateIndex, 0))
10142                :        return FALSE;
10143                :    if (!AllocateWindowPrivate (pScreen, damageWinPrivateIndex, 0))
10144                :        return FALSE;
10145                :
10146                :    pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec));
10147                :    if (!pScrPriv)
10148                :        return FALSE;
10149                :
10150                :    pScrPriv->internalLevel = 0;
10151                :    pScrPriv->pScreenDamage = 0;
10152                :
10153                :    wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
10154                :    wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
10155                :    wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow);
10156                :    wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow);
10157                :    wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
10158                :    wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
10159                :    wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
10160                :    wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen);
10161                :    wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
10162                :                             damageRestoreAreas);
10163                :#ifdef RENDER
10164                :    if (ps) {
10165                :        wrap (pScrPriv, ps, Glyphs, damageGlyphs);
10166                :        wrap (pScrPriv, ps, Composite, damageComposite);
10167                :    }
10168                :#endif
10169                :
10170                :    pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv;
10171                :    return TRUE;
10172                :}
10173                :
10174                :DamagePtr
10175                :DamageCreate (DamageReportFunc  damageReport,
10176                :              DamageDestroyFunc damageDestroy,
10177                :              DamageReportLevel damageLevel,
10178                :              Bool              isInternal,
10179                :              ScreenPtr         pScreen,
10180                :              void              *closure)
10181      2  0.0022 :{ /* DamageCreate total:     12  0.0131 */
10182                :    DamagePtr   pDamage;
10183                :
10184      4  0.0044 :    pDamage = xalloc (sizeof (DamageRec));
10185      1  0.0011 :    if (!pDamage)
10186                :        return 0;
10187                :    pDamage->pNext = 0;
10188                :    pDamage->pNextWin = 0;
10189      3  0.0033 :    REGION_NULL(pScreen, &pDamage->damage);
10190                :    REGION_NULL(pScreen, &pDamage->pendingDamage);
10191                :    
10192                :    pDamage->damageLevel = damageLevel;
10193      1  0.0011 :    pDamage->isInternal = isInternal;
10194                :    pDamage->closure = closure;
10195                :    pDamage->isWindow = FALSE;
10196                :    pDamage->pDrawable = 0;
10197                :    pDamage->reportAfter = FALSE;
10198                :
10199                :    pDamage->damageReport = damageReport;
10200                :    pDamage->damageDestroy = damageDestroy;
10201                :    return pDamage;
10202      1  0.0011 :}
10203                :
10204                :void
10205                :DamageRegister (DrawablePtr pDrawable,
10206                :                DamagePtr   pDamage)
10207      1  0.0011 :{ /* DamageRegister total:      1  0.0011 */
10208                :    if (pDrawable->type == DRAWABLE_WINDOW)
10209                :    {
10210                :        WindowPtr   pWindow = (WindowPtr) pDrawable;
10211                :        winDamageRef(pWindow);
10212                :
10213                :#if DAMAGE_VALIDATE_ENABLE
10214                :        DamagePtr   pOld;
10215                :        
10216                :        for (pOld = *pPrev; pOld; pOld = pOld->pNextWin)
10217                :            if (pOld == pDamage) {
10218                :                ErrorF ("Damage already on window list\n");
10219                :                abort ();
10220                :            }
10221                :#endif
10222                :        pDamage->pNextWin = *pPrev;
10223                :        *pPrev = pDamage;
10224                :        pDamage->isWindow = TRUE;
10225                :    }
10226                :    else
10227                :        pDamage->isWindow = FALSE;
10228                :    pDamage->pDrawable = pDrawable;
10229                :    damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage);
10230                :}
10231                :
10232                :void
10233                :DamageDrawInternal (ScreenPtr pScreen, Bool enable)
10234                :{
10235                :    damageScrPriv (pScreen);
10236                :
10237                :    pScrPriv->internalLevel += enable ? 1 : -1;
10238                :}
10239                :
10240                :void
10241                :DamageUnregister (DrawablePtr       pDrawable,
10242                :                  DamagePtr         pDamage)
10243                :{
10244                :    if (pDrawable->type == DRAWABLE_WINDOW)
10245                :    {
10246                :        WindowPtr   pWindow = (WindowPtr) pDrawable;
10247                :        winDamageRef (pWindow);
10248                :#if DAMAGE_VALIDATE_ENABLE
10249                :        int     found = 0;
10250                :#endif
10251                :
10252                :        while (*pPrev)
10253                :        {
10254                :            if (*pPrev == pDamage)
10255                :            {
10256                :                *pPrev = pDamage->pNextWin;
10257                :#if DAMAGE_VALIDATE_ENABLE
10258                :                found = 1;
10259                :#endif
10260                :                break;
10261                :            }
10262                :            pPrev = &(*pPrev)->pNextWin;
10263                :        }
10264                :#if DAMAGE_VALIDATE_ENABLE
10265                :        if (!found) {
10266                :            ErrorF ("Damage not on window list\n");
10267                :            abort ();
10268                :        }
10269                :#endif
10270                :    }
10271                :    pDamage->pDrawable = 0;
10272                :    damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage);
10273                :}
10274                :
10275                :void
10276                :DamageDestroy (DamagePtr    pDamage)
10277      1  0.0011 :{ /* DamageDestroy total:      3  0.0033 */
10278                :    if (pDamage->damageDestroy)
10279                :        (*pDamage->damageDestroy) (pDamage, pDamage->closure);
10280      2  0.0022 :    REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage);
10281                :    REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->pendingDamage);
10282                :    xfree (pDamage);
10283                :}
10284                :
10285                :Bool
10286                :DamageSubtract (DamagePtr           pDamage,
10287                :                const RegionPtr     pRegion)
10288                :{
10289                :    RegionPtr   pClip;
10290                :    RegionRec   pixmapClip;
10291                :    DrawablePtr pDrawable = pDamage->pDrawable;
10292                :    
10293                :    REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion);
10294                :    if (pDrawable)
10295                :    {
10296                :        if (pDrawable->type == DRAWABLE_WINDOW)
10297                :            pClip = &((WindowPtr) pDrawable)->borderClip;
10298                :        else
10299                :        {
10300                :            BoxRec  box;
10301                :
10302                :            box.x1 = pDrawable->x;
10303                :            box.y1 = pDrawable->y;
10304                :            box.x2 = pDrawable->x + pDrawable->width;
10305                :            box.y2 = pDrawable->y + pDrawable->height;
10306                :            REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1);
10307                :            pClip = &pixmapClip;
10308                :        }
10309                :        REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y);
10310                :        REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip);
10311                :        REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y);
10312                :        if (pDrawable->type != DRAWABLE_WINDOW)
10313                :            REGION_UNINIT(pDrawable->pScreen, &pixmapClip);
10314                :    }
10315                :    return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage);
10316                :}
10317                :
10318                :void
10319                :DamageEmpty (DamagePtr      pDamage)
10320      1  0.0011 :{ /* DamageEmpty total:      3  0.0033 */
10321      1  0.0011 :    REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage);
10322      1  0.0011 :}
10323                :
10324                :RegionPtr
10325                :DamageRegion (DamagePtr             pDamage)
10326      7  0.0076 :{ /* DamageRegion total:     10  0.0109 */
10327                :    return &pDamage->damage;
10328      3  0.0033 :}
10329                :
10330                :_X_EXPORT void
10331                :DamageDamageRegion (DrawablePtr pDrawable,
10332                :                    RegionPtr   pRegion)
10333                :{
10334                :    damageDamageRegion (pDrawable, pRegion, FALSE, -1);
10335                :
10336                :    /* Go back and report this damage for DamagePtrs with reportAfter set, since
10337                :     * this call isn't part of an in-progress drawing op in the call chain and
10338                :     * the DDX probably just wants to know about it right away.
10339                :     */
10340                :    damageReportPostOp (pDrawable);
10341                :}
10342                :
10343                :void
10344                :DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter)
10345      4  0.0044 :{ /* DamageSetReportAfterOp total:      5  0.0054 */
10346                :    pDamage->reportAfter = reportAfter;
10347      1  0.0011 :}
10348 /* 
10349  * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i830_driver.c"
10350  * 
10351  *    154  0.1678
10352  */
10353
10354
10355                :/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c,v 1.50 2004/02/20 00:06:00 alanh Exp $ */
10356                :/**************************************************************************
10357                :
10358                :Copyright 2001 VA Linux Systems Inc., Fremont, California.
10359                :Copyright Â© 2002 by David Dawes
10360                :
10361                :All Rights Reserved.
10362                :
10363                :Permission is hereby granted, free of charge, to any person obtaining a
10364                :copy of this software and associated documentation files (the "Software"),
10365                :to deal in the Software without restriction, including without limitation
10366                :on the rights to use, copy, modify, merge, publish, distribute, sub
10367                :license, and/or sell copies of the Software, and to permit persons to whom
10368                :the Software is furnished to do so, subject to the following conditions:
10369                :
10370                :The above copyright notice and this permission notice (including the next
10371                :paragraph) shall be included in all copies or substantial portions of the
10372                :Software.
10373                :
10374                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10375                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10376                :FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
10377                :THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
10378                :DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
10379                :OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
10380                :USE OR OTHER DEALINGS IN THE SOFTWARE.
10381                :
10382                :**************************************************************************/
10383                :
10384                :/*
10385                : * Reformatted with GNU indent (2.2.8), using the following options:
10386                : *
10387                : *    -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
10388                : *    -lp -npcs -psl -sob -ss -br -ce -sc -hnl
10389                : *
10390                : * This provides a good match with the original i810 code and preferred
10391                : * XFree86 formatting conventions.
10392                : *
10393                : * When editing this driver, please follow the existing formatting, and edit
10394                : * with <TAB> characters expanded at 8-column intervals.
10395                : */
10396                :
10397                :/*
10398                : * Authors: Jeff Hartmann <jhartmann@valinux.com>
10399                : *          Abraham van der Merwe <abraham@2d3d.co.za>
10400                : *          David Dawes <dawes@xfree86.org>
10401                : *          Alan Hourihane <alanh@tungstengraphics.com>
10402                : */
10403                :
10404                :/*
10405                : * Mode handling is based on the VESA driver written by:
10406                : * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
10407                : */
10408                :
10409                :/*
10410                : * Changes:
10411                : *
10412                : *    23/08/2001 Abraham van der Merwe <abraham@2d3d.co.za>
10413                : *        - Fixed display timing bug (mode information for some
10414                : *          modes were not initialized correctly)
10415                : *        - Added workarounds for GTT corruptions (I don't adjust
10416                : *          the pitches for 1280x and 1600x modes so we don't
10417                : *          need extra memory)
10418                : *        - The code will now default to 60Hz if LFP is connected
10419                : *        - Added different refresh rate setting code to work
10420                : *          around 0x4f02 BIOS bug
10421                : *        - BIOS workaround for some mode sets (I use legacy BIOS
10422                : *          calls for setting those)
10423                : *        - Removed 0x4f04, 0x01 (save state) BIOS call which causes
10424                : *          LFP to malfunction (do some house keeping and restore
10425                : *          modes ourselves instead - not perfect, but at least the
10426                : *          LFP is working now)
10427                : *        - Several other smaller bug fixes
10428                : *
10429                : *    06/09/2001 Abraham van der Merwe <abraham@2d3d.co.za>
10430                : *        - Preliminary local memory support (works without agpgart)
10431                : *        - DGA fixes (the code were still using i810 mode sets, etc.)
10432                : *        - agpgart fixes
10433                : *
10434                : *    18/09/2001
10435                : *        - Proper local memory support (should work correctly now
10436                : *          with/without agpgart module)
10437                : *        - more agpgart fixes
10438                : *        - got rid of incorrect GTT adjustments
10439                : *
10440                : *    09/10/2001
10441                : *        - Changed the DPRINTF() variadic macro to an ANSI C compatible
10442                : *          version
10443                : *
10444                : *    10/10/2001
10445                : *        - Fixed DPRINTF_stub(). I forgot the __...__ macros in there
10446                : *          instead of the function arguments :P
10447                : *        - Added a workaround for the 1600x1200 bug (Text mode corrupts
10448                : *          when you exit from any 1600x1200 mode and 1280x1024@85Hz. I
10449                : *          suspect this is a BIOS bug (hence the 1280x1024@85Hz case)).
10450                : *          For now I'm switching to 800x600@60Hz then to 80x25 text mode
10451                : *          and then restoring the registers - very ugly indeed.
10452                : *
10453                : *    15/10/2001
10454                : *        - Improved 1600x1200 mode set workaround. The previous workaround
10455                : *          was causing mode set problems later on.
10456                : *
10457                : *    18/10/2001
10458                : *        - Fixed a bug in I830BIOSLeaveVT() which caused a bug when you
10459                : *          switched VT's
10460                : */
10461                :/*
10462                : *    07/2002 David Dawes
10463                : *        - Add Intel(R) 855GM/852GM support.
10464                : */
10465                :/*
10466                : *    07/2002 David Dawes
10467                : *        - Cleanup code formatting.
10468                : *        - Improve VESA mode selection, and fix refresh rate selection.
10469                : *        - Don't duplicate functions provided in 4.2 vbe modules.
10470                : *        - Don't duplicate functions provided in the vgahw module.
10471                : *        - Rewrite memory allocation.
10472                : *        - Rewrite initialisation and save/restore state handling.
10473                : *        - Decouple the i810 support from i830 and later.
10474                : *        - Remove various unnecessary hacks and workarounds.
10475                : *        - Fix an 845G problem with the ring buffer not in pre-allocated
10476                : *          memory.
10477                : *        - Fix screen blanking.
10478                : *        - Clear the screen at startup so you don't see the previous session.
10479                : *        - Fix some HW cursor glitches, and turn HW cursor off at VT switch
10480                : *          and exit.
10481                : *
10482                : *    08/2002 Keith Whitwell
10483                : *        - Fix DRI initialisation.
10484                : *
10485                : *
10486                : *    08/2002 Alan Hourihane and David Dawes
10487                : *        - Add XVideo support.
10488                : *
10489                : *
10490                : *    10/2002 David Dawes
10491                : *        - Add Intel(R) 865G support.
10492                : *
10493                : *
10494                : *    01/2004 Alan Hourihane
10495                : *        - Add Intel(R) 915G support.
10496                : *        - Add Dual Head and Clone capabilities.
10497                : *        - Add lid status checking
10498                : *        - Fix Xvideo with high-res LFP's
10499                : *        - Add ARGB HW cursor support
10500                : *
10501                : *    05/2005 Alan Hourihane
10502                : *        - Add Intel(R) 945G support.
10503                : *
10504                : *    09/2005 Alan Hourihane
10505                : *        - Add Intel(R) 945GM support.
10506                : *
10507                : *    10/2005 Alan Hourihane, Keith Whitwell, Brian Paul
10508                : *        - Added Rotation support
10509                : *
10510                : *    12/2005 Alan Hourihane, Keith Whitwell
10511                : *        - Add Intel(R) 965G support.
10512                : */
10513                :
10514                :#ifdef HAVE_CONFIG_H
10515                :#include "config.h"
10516                :#endif
10517                :
10518                :#ifndef PRINT_MODE_INFO
10519                :#define PRINT_MODE_INFO 0
10520                :#endif
10521                :
10522                :#include <assert.h>
10523                :#include <string.h>
10524                :#include <stdio.h>
10525                :#include <unistd.h>
10526                :#include <stdlib.h>
10527                :#include <stdio.h>
10528                :
10529                :#include "xf86.h"
10530                :#include "xf86_OSproc.h"
10531                :#include "xf86Resources.h"
10532                :#include "xf86RAC.h"
10533                :#include "xf86cmap.h"
10534                :#include "compiler.h"
10535                :#include "mibstore.h"
10536                :#include "vgaHW.h"
10537                :#include "mipointer.h"
10538                :#include "micmap.h"
10539                :#include "shadowfb.h"
10540                :#include <X11/extensions/randr.h>
10541                :#include "fb.h"
10542                :#include "miscstruct.h"
10543                :#include "dixstruct.h"
10544                :#include "xf86xv.h"
10545                :#include <X11/extensions/Xv.h>
10546                :#include "vbe.h"
10547                :#include "shadow.h"
10548                :#include "i830.h"
10549                :#include "i830_display.h"
10550                :#include "i830_debug.h"
10551                :#include "i830_bios.h"
10552                :
10553                :#ifdef XF86DRI
10554                :#include "dri.h"
10555                :#include <sys/ioctl.h>
10556                :#include <errno.h>
10557                :#endif
10558                :
10559                :#ifdef I830_USE_EXA
10560                :const char *I830exaSymbols[] = {
10561                :    "exaGetVersion",
10562                :    "exaDriverInit",
10563                :    "exaDriverFini",
10564                :    "exaOffscreenAlloc",
10565                :    "exaOffscreenFree",
10566                :    "exaWaitSync",
10567                :    NULL
10568                :};
10569                :#endif
10570                :
10571                :#define BIT(x) (1 << (x))
10572                :#define MAX(a,b) ((a) > (b) ? (a) : (b))
10573                :#define NB_OF(x) (sizeof (x) / sizeof (*x))
10574                :
10575                :/* *INDENT-OFF* */
10576                :static SymTabRec I830Chipsets[] = {
10577                :   {PCI_CHIP_I830_M,            "i830"},
10578                :   {PCI_CHIP_845_G,             "845G"},
10579                :   {PCI_CHIP_I855_GM,           "852GM/855GM"},
10580                :   {PCI_CHIP_I865_G,            "865G"},
10581                :   {PCI_CHIP_I915_G,            "915G"},
10582                :   {PCI_CHIP_E7221_G,           "E7221 (i915)"},
10583                :   {PCI_CHIP_I915_GM,           "915GM"},
10584                :   {PCI_CHIP_I945_G,            "945G"},
10585                :   {PCI_CHIP_I945_GM,           "945GM"},
10586                :   {PCI_CHIP_I945_GME,          "945GME"},
10587                :   {PCI_CHIP_I965_G,            "965G"},
10588                :   {PCI_CHIP_I965_G_1,          "965G"},
10589                :   {PCI_CHIP_I965_Q,            "965Q"},
10590                :   {PCI_CHIP_I946_GZ,           "946GZ"},
10591                :   {PCI_CHIP_I965_GM,           "965GM"},
10592                :   {PCI_CHIP_I965_GME,          "965GME/GLE"},
10593                :   {PCI_CHIP_G33_G,             "G33"},
10594                :   {PCI_CHIP_Q35_G,             "Q35"},
10595                :   {PCI_CHIP_Q33_G,             "Q33"},
10596                :   {-1,                         NULL}
10597                :};
10598                :
10599                :static PciChipsets I830PciChipsets[] = {
10600                :   {PCI_CHIP_I830_M,            PCI_CHIP_I830_M,        RES_SHARED_VGA},
10601                :   {PCI_CHIP_845_G,             PCI_CHIP_845_G,         RES_SHARED_VGA},
10602                :   {PCI_CHIP_I855_GM,           PCI_CHIP_I855_GM,       RES_SHARED_VGA},
10603                :   {PCI_CHIP_I865_G,            PCI_CHIP_I865_G,        RES_SHARED_VGA},
10604                :   {PCI_CHIP_I915_G,            PCI_CHIP_I915_G,        RES_SHARED_VGA},
10605                :   {PCI_CHIP_E7221_G,           PCI_CHIP_E7221_G,       RES_SHARED_VGA},
10606                :   {PCI_CHIP_I915_GM,           PCI_CHIP_I915_GM,       RES_SHARED_VGA},
10607                :   {PCI_CHIP_I945_G,            PCI_CHIP_I945_G,        RES_SHARED_VGA},
10608                :   {PCI_CHIP_I945_GM,           PCI_CHIP_I945_GM,       RES_SHARED_VGA},
10609                :   {PCI_CHIP_I945_GME,          PCI_CHIP_I945_GME,      RES_SHARED_VGA},
10610                :   {PCI_CHIP_I965_G,            PCI_CHIP_I965_G,        RES_SHARED_VGA},
10611                :   {PCI_CHIP_I965_G_1,          PCI_CHIP_I965_G_1,      RES_SHARED_VGA},
10612                :   {PCI_CHIP_I965_Q,            PCI_CHIP_I965_Q,        RES_SHARED_VGA},
10613                :   {PCI_CHIP_I946_GZ,           PCI_CHIP_I946_GZ,       RES_SHARED_VGA},
10614                :   {PCI_CHIP_I965_GM,           PCI_CHIP_I965_GM,       RES_SHARED_VGA},
10615                :   {PCI_CHIP_I965_GME,          PCI_CHIP_I965_GME,      RES_SHARED_VGA},
10616                :   {PCI_CHIP_G33_G,             PCI_CHIP_G33_G,         RES_SHARED_VGA},
10617                :   {PCI_CHIP_Q35_G,             PCI_CHIP_Q35_G,         RES_SHARED_VGA},
10618                :   {PCI_CHIP_Q33_G,             PCI_CHIP_Q33_G,         RES_SHARED_VGA},
10619                :   {-1,                         -1,                     RES_UNDEFINED}
10620                :};
10621                :
10622                :/*
10623                : * Note: "ColorKey" is provided for compatibility with the i810 driver.
10624                : * However, the correct option name is "VideoKey".  "ColorKey" usually
10625                : * refers to the tranparency key for 8+24 overlays, not for video overlays.
10626                : */
10627                :
10628                :typedef enum {
10629                :#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
10630                :   OPTION_ACCELMETHOD,
10631                :#endif
10632                :   OPTION_NOACCEL,
10633                :   OPTION_SW_CURSOR,
10634                :   OPTION_CACHE_LINES,
10635                :   OPTION_DRI,
10636                :   OPTION_PAGEFLIP,
10637                :   OPTION_XVIDEO,
10638                :   OPTION_VIDEO_KEY,
10639                :   OPTION_COLOR_KEY,
10640                :   OPTION_CHECKDEVICES,
10641                :   OPTION_MODEDEBUG,
10642                :#ifdef XF86DRI_MM
10643                :   OPTION_INTELTEXPOOL,
10644                :   OPTION_INTELMMSIZE,
10645                :#endif
10646                :   OPTION_TRIPLEBUFFER,
10647                :} I830Opts;
10648                :
10649                :static OptionInfoRec I830Options[] = {
10650                :#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
10651                :   {OPTION_ACCELMETHOD, "AccelMethod",  OPTV_ANYSTR,    {0},    FALSE},
10652                :#endif
10653                :   {OPTION_NOACCEL,     "NoAccel",      OPTV_BOOLEAN,   {0},    FALSE},
10654                :   {OPTION_SW_CURSOR,   "SWcursor",     OPTV_BOOLEAN,   {0},    FALSE},
10655                :   {OPTION_CACHE_LINES, "CacheLines",   OPTV_INTEGER,   {0},    FALSE},
10656                :   {OPTION_DRI,         "DRI",          OPTV_BOOLEAN,   {0},    TRUE},
10657                :   {OPTION_PAGEFLIP,    "PageFlip",     OPTV_BOOLEAN,   {0},    FALSE},
10658                :   {OPTION_XVIDEO,      "XVideo",       OPTV_BOOLEAN,   {0},    TRUE},
10659                :   {OPTION_COLOR_KEY,   "ColorKey",     OPTV_INTEGER,   {0},    FALSE},
10660                :   {OPTION_VIDEO_KEY,   "VideoKey",     OPTV_INTEGER,   {0},    FALSE},
10661                :   {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,   {0},    FALSE},
10662                :   {OPTION_MODEDEBUG,   "ModeDebug",    OPTV_BOOLEAN,   {0},    FALSE},
10663                :#ifdef XF86DRI_MM
10664                :   {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,   {0},    FALSE},
10665                :   {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,   {0},    FALSE},
10666                :#endif
10667                :   {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN,  {0},    FALSE},
10668                :   {-1,                 NULL,           OPTV_NONE,      {0},    FALSE}
10669                :};
10670                :/* *INDENT-ON* */
10671                :
10672                :const char *i830_output_type_names[] = {
10673                :   "Unused",
10674                :   "Analog",
10675                :   "DVO",
10676                :   "SDVO",
10677                :   "LVDS",
10678                :   "TVOUT",
10679                :};
10680                :
10681                :static void i830AdjustFrame(int scrnIndex, int x, int y, int flags);
10682                :static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen);
10683                :static Bool I830EnterVT(int scrnIndex, int flags);
10684                :static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
10685                :static Bool SaveHWState(ScrnInfoPtr pScrn);
10686                :static Bool RestoreHWState(ScrnInfoPtr pScrn);
10687                :
10688                :/* temporary */
10689                :extern void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y);
10690                :
10691                :#ifdef I830DEBUG
10692                :void
10693                :I830DPRINTF_stub(const char *filename, int line, const char *function,
10694                :                 const char *fmt, ...)
10695                :{
10696                :   va_list ap;
10697                :
10698                :   ErrorF("\n##############################################\n"
10699                :          "*** In function %s, on line %d, in file %s ***\n",
10700                :          function, line, filename);
10701                :   va_start(ap, fmt);
10702                :   VErrorF(fmt, ap);
10703                :   va_end(ap);
10704                :   ErrorF("##############################################\n\n");
10705                :}
10706                :#else /* #ifdef I830DEBUG */
10707                :void
10708                :I830DPRINTF_stub(const char *filename, int line, const char *function,
10709                :                 const char *fmt, ...)
10710                :{
10711                :   /* do nothing */
10712                :}
10713                :#endif /* #ifdef I830DEBUG */
10714                :
10715                :/* Export I830 options to i830 driver where necessary */
10716                :const OptionInfoRec *
10717                :I830AvailableOptions(int chipid, int busid)
10718                :{
10719                :   int i;
10720                :
10721                :   for (i = 0; I830PciChipsets[i].PCIid > 0; i++) {
10722                :      if (chipid == I830PciChipsets[i].PCIid)
10723                :         return I830Options;
10724                :   }
10725                :   return NULL;
10726                :}
10727                :
10728                :static Bool
10729                :I830GetRec(ScrnInfoPtr pScrn)
10730                :{
10731                :   I830Ptr pI830;
10732                :
10733                :   if (pScrn->driverPrivate)
10734                :      return TRUE;
10735                :   pI830 = pScrn->driverPrivate = xnfcalloc(sizeof(I830Rec), 1);
10736                :   return TRUE;
10737                :}
10738                :
10739                :static void
10740                :I830FreeRec(ScrnInfoPtr pScrn)
10741                :{
10742                :   I830Ptr pI830;
10743                :
10744                :   if (!pScrn)
10745                :      return;
10746                :   if (!pScrn->driverPrivate)
10747                :      return;
10748                :
10749                :   pI830 = I830PTR(pScrn);
10750                :
10751                :   xfree(pScrn->driverPrivate);
10752                :   pScrn->driverPrivate = NULL;
10753                :}
10754                :
10755                :static void
10756                :I830ProbeDDC(ScrnInfoPtr pScrn, int index)
10757                :{
10758                :   vbeInfoPtr pVbe;
10759                :
10760                :   /* The vbe module gets loaded in PreInit(), so no need to load it here. */
10761                :
10762                :   pVbe = VBEInit(NULL, index);
10763                :   ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
10764                :}
10765                :
10766                :static int
10767                :I830DetectMemory(ScrnInfoPtr pScrn)
10768                :{
10769                :   I830Ptr pI830 = I830PTR(pScrn);
10770                :   PCITAG bridge;
10771                :   CARD16 gmch_ctrl;
10772                :   int memsize = 0, gtt_size;
10773                :   int range;
10774                :#if 0
10775                :   VbeInfoBlock *vbeInfo;
10776                :#endif
10777                :
10778                :   bridge = pciTag(0, 0, 0);            /* This is always the host bridge */
10779                :   gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
10780                :
10781                :   if (IS_I965G(pI830)) {
10782                :      /* The 965 may have a GTT that is actually larger than is necessary
10783                :       * to cover the aperture, so check the hardware's reporting of the
10784                :       * GTT size.
10785                :       */
10786                :      switch (INREG(PGETBL_CTL) & PGETBL_SIZE_MASK) {
10787                :      case PGETBL_SIZE_512KB:
10788                :         gtt_size = 512;
10789                :         break;
10790                :      case PGETBL_SIZE_256KB:
10791                :         gtt_size = 256;
10792                :         break;
10793                :      case PGETBL_SIZE_128KB:
10794                :         gtt_size = 128;
10795                :         break;
10796                :      default:
10797                :         FatalError("Unknown GTT size value: %08x\n", (int)INREG(PGETBL_CTL));
10798                :      }
10799                :   } else if (IS_G33CLASS(pI830)) {
10800                :      /* G33's GTT size is detect in GMCH_CTRL */
10801                :      switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
10802                :      case G33_PGETBL_SIZE_1M:
10803                :         gtt_size = 1024;
10804                :         break;
10805                :      case G33_PGETBL_SIZE_2M:
10806                :         gtt_size = 2048;
10807                :         break;
10808                :      default:
10809                :         FatalError("Unknown GTT size value: %08x\n",
10810                :                    (int)(gmch_ctrl & G33_PGETBL_SIZE_MASK));
10811                :      }
10812                :   } else {
10813                :      /* Older chipsets only had GTT appropriately sized for the aperture. */
10814                :      gtt_size = pI830->FbMapSize / (1024*1024);
10815                :   }
10816                :
10817                :   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "detected %d kB GTT.\n", gtt_size);
10818                :
10819                :   /* The stolen memory has the GTT at the top, and the 4KB popup below that.
10820                :    * Everything else can be freely used by the graphics driver.
10821                :    */
10822                :   range = gtt_size + 4;
10823                :
10824                :   if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
10825                :      switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
10826                :      case I855_GMCH_GMS_STOLEN_1M:
10827                :         memsize = MB(1) - KB(range);
10828                :         break;
10829                :      case I855_GMCH_GMS_STOLEN_4M:
10830                :         memsize = MB(4) - KB(range);
10831                :         break;
10832                :      case I855_GMCH_GMS_STOLEN_8M:
10833                :         memsize = MB(8) - KB(range);
10834                :         break;
10835                :      case I855_GMCH_GMS_STOLEN_16M:
10836                :         memsize = MB(16) - KB(range);
10837                :         break;
10838                :      case I855_GMCH_GMS_STOLEN_32M:
10839                :         memsize = MB(32) - KB(range);
10840                :         break;
10841                :      case I915G_GMCH_GMS_STOLEN_48M:
10842                :         if (IS_I9XX(pI830))
10843                :            memsize = MB(48) - KB(range);
10844                :         break;
10845                :      case I915G_GMCH_GMS_STOLEN_64M:
10846                :         if (IS_I9XX(pI830))
10847                :            memsize = MB(64) - KB(range);
10848                :         break;
10849                :      case G33_GMCH_GMS_STOLEN_128M:
10850                :         if (IS_G33CLASS(pI830))
10851                :             memsize = MB(128) - KB(range);
10852                :         break;
10853                :      case G33_GMCH_GMS_STOLEN_256M:
10854                :         if (IS_G33CLASS(pI830))
10855                :             memsize = MB(256) - KB(range);
10856                :         break;
10857                :      }
10858                :   } else {
10859                :      switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
10860                :      case I830_GMCH_GMS_STOLEN_512:
10861                :         memsize = KB(512) - KB(range);
10862                :         break;
10863                :      case I830_GMCH_GMS_STOLEN_1024:
10864                :         memsize = MB(1) - KB(range);
10865                :         break;
10866                :      case I830_GMCH_GMS_STOLEN_8192:
10867                :         memsize = MB(8) - KB(range);
10868                :         break;
10869                :      case I830_GMCH_GMS_LOCAL:
10870                :         memsize = 0;
10871                :         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
10872                :                    "Local memory found, but won't be used.\n");
10873                :         break;
10874                :      }
10875                :   }
10876                :
10877                :#if 0
10878                :   /* And 64KB page aligned */
10879                :   memsize &= ~0xFFFF;
10880                :#endif
10881                :
10882                :   if (memsize > 0) {
10883                :      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10884                :                 "detected %d kB stolen memory.\n", memsize / 1024);
10885                :   } else {
10886                :      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n");
10887                :   }
10888                :
10889                :   return memsize;
10890                :}
10891                :
10892                :static Bool
10893                :I830MapMMIO(ScrnInfoPtr pScrn)
10894                :{
10895                :   int mmioFlags;
10896                :   I830Ptr pI830 = I830PTR(pScrn);
10897                :
10898                :#if !defined(__alpha__)
10899                :   mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
10900                :#else
10901                :   mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
10902                :#endif
10903                :
10904                :   pI830->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
10905                :                                   pI830->PciTag,
10906                :                                   pI830->MMIOAddr, I810_REG_SIZE);
10907                :   if (!pI830->MMIOBase)
10908                :      return FALSE;
10909                :
10910                :   /* Set up the GTT mapping for the various places it has been moved over
10911                :    * time.
10912                :    */
10913                :   if (IS_I9XX(pI830)) {
10914                :      if (IS_I965G(pI830)) {
10915                :         pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
10916                :                                        pI830->PciTag,
10917                :                                        pI830->MMIOAddr + (512 * 1024),
10918                :                                        512 * 1024);
10919                :         if (pI830->GTTBase == NULL)
10920                :            return FALSE;
10921                :      } else {
10922                :         CARD32 gttaddr = pI830->PciInfo->memBase[3] & 0xFFFFFF00;
10923                :
10924                :         pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
10925                :                                        pI830->PciTag,
10926                :                                        gttaddr,
10927                :                                        pI830->FbMapSize / 1024);
10928                :         if (pI830->GTTBase == NULL)
10929                :            return FALSE;
10930                :      }
10931                :   } else {
10932                :      /* The GTT aperture on i830 is write-only.  We could probably map the
10933                :       * actual physical pages that back it, but leave it alone for now.
10934                :       */
10935                :      pI830->GTTBase = NULL;
10936                :   }
10937                :
10938                :   return TRUE;
10939                :}
10940                :
10941                :static Bool
10942                :I830MapMem(ScrnInfoPtr pScrn)
10943                :{
10944                :   I830Ptr pI830 = I830PTR(pScrn);
10945                :   long i;
10946                :
10947                :   for (i = 2; i < pI830->FbMapSize; i <<= 1) ;
10948                :   pI830->FbMapSize = i;
10949                :
10950                :   if (!I830MapMMIO(pScrn))
10951                :      return FALSE;
10952                :
10953                :   pI830->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
10954                :                                 pI830->PciTag,
10955                :                                 pI830->LinearAddr, pI830->FbMapSize);
10956                :   if (!pI830->FbBase)
10957                :      return FALSE;
10958                :
10959                :   if (I830IsPrimary(pScrn) && pI830->LpRing->mem != NULL) {
10960                :      pI830->LpRing->virtual_start =
10961                :         pI830->FbBase + pI830->LpRing->mem->offset;
10962                :   }
10963                :
10964                :   return TRUE;
10965                :}
10966                :
10967                :static void
10968                :I830UnmapMMIO(ScrnInfoPtr pScrn)
10969                :{
10970                :   I830Ptr pI830 = I830PTR(pScrn);
10971                :
10972                :   xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
10973                :                   I810_REG_SIZE);
10974                :   pI830->MMIOBase = NULL;
10975                :
10976                :   if (IS_I9XX(pI830)) {
10977                :      if (IS_I965G(pI830))
10978                :         xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase, 512 * 1024);
10979                :      else {
10980                :         xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase,
10981                :                         pI830->FbMapSize / 1024);
10982                :      }
10983                :   }
10984                :}
10985                :
10986                :static Bool
10987                :I830UnmapMem(ScrnInfoPtr pScrn)
10988                :{
10989                :   I830Ptr pI830 = I830PTR(pScrn);
10990                :
10991                :   xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->FbBase,
10992                :                   pI830->FbMapSize);
10993                :   pI830->FbBase = NULL;
10994                :   I830UnmapMMIO(pScrn);
10995                :   return TRUE;
10996                :}
10997                :
10998                :static void
10999                :I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
11000                :                LOCO * colors, VisualPtr pVisual)
11001                :{
11002                :   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
11003                :   int i,j, index;
11004                :   int p;
11005                :   CARD16 lut_r[256], lut_g[256], lut_b[256];
11006                :
11007                :   DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
11008                :
11009                :   for(p = 0; p < xf86_config->num_crtc; p++) {
11010                :      xf86CrtcPtr          crtc = xf86_config->crtc[p];
11011                :      I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
11012                :
11013                :      /* Initialize to the old lookup table values. */
11014                :      for (i = 0; i < 256; i++) {
11015                :         lut_r[i] = intel_crtc->lut_r[i] << 8;
11016                :         lut_g[i] = intel_crtc->lut_g[i] << 8;
11017                :         lut_b[i] = intel_crtc->lut_b[i] << 8;
11018                :      }
11019                :
11020                :      switch(pScrn->depth) {
11021                :      case 15:
11022                :         for (i = 0; i < numColors; i++) {
11023                :            index = indices[i];
11024                :            for (j = 0; j < 8; j++) {
11025                :               lut_r[index * 8 + j] = colors[index].red << 8;
11026                :               lut_g[index * 8 + j] = colors[index].green << 8;
11027                :               lut_b[index * 8 + j] = colors[index].blue << 8;
11028                :            }
11029                :         }
11030                :         break;
11031                :      case 16:
11032                :         for (i = 0; i < numColors; i++) {
11033                :            index = indices[i];
11034                :
11035                :            if (index <= 31) {
11036                :               for (j = 0; j < 8; j++) {
11037                :                  lut_r[index * 8 + j] = colors[index].red << 8;
11038                :                  lut_b[index * 8 + j] = colors[index].blue << 8;
11039                :               }
11040                :            }
11041                :
11042                :            for (j = 0; j < 4; j++) {
11043                :               lut_g[index * 4 + j] = colors[index].green << 8;
11044                :            }
11045                :         }
11046                :        break;
11047                :      default:
11048                :         for (i = 0; i < numColors; i++) {
11049                :            index = indices[i];
11050                :            lut_r[index] = colors[index].red << 8;
11051                :            lut_g[index] = colors[index].green << 8;
11052                :            lut_b[index] = colors[index].blue << 8;
11053                :         }
11054                :         break;
11055                :      }
11056                :
11057                :      /* Make the change through RandR */
11058                :#ifdef RANDR_12_INTERFACE
11059                :      RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
11060                :#else
11061                :      crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
11062                :#endif
11063                :   }
11064                :}
11065                :
11066                :int
11067                :i830_output_clones (ScrnInfoPtr pScrn, int type_mask)
11068                :{
11069                :    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR (pScrn);
11070                :    int                 o;
11071                :    int                 index_mask = 0;
11072                :
11073                :    for (o = 0; o < config->num_output; o++)
11074                :    {
11075                :        xf86OutputPtr           output = config->output[o];
11076                :        I830OutputPrivatePtr    intel_output = output->driver_private;
11077                :        if (type_mask & (1 << intel_output->type))
11078                :            index_mask |= (1 << o);
11079                :    }
11080                :    return index_mask;
11081                :}
11082                :
11083                :/**
11084                : * Set up the outputs according to what type of chip we are.
11085                : *
11086                : * Some outputs may not initialize, due to allocation failure or because a
11087                : * controller chip isn't found.
11088                : */
11089                :static void
11090                :I830SetupOutputs(ScrnInfoPtr pScrn)
11091                :{
11092                :   xf86CrtcConfigPtr    config = XF86_CRTC_CONFIG_PTR (pScrn);
11093                :   I830Ptr  pI830 = I830PTR(pScrn);
11094                :   int      o;
11095                :
11096                :   /* everyone has at least a single analog output */
11097                :   i830_crt_init(pScrn);
11098                :
11099                :   /* Set up integrated LVDS */
11100                :   if (IS_MOBILE(pI830) && !IS_I830(pI830))
11101                :      i830_lvds_init(pScrn);
11102                :
11103                :   if (IS_I9XX(pI830)) {
11104                :      i830_sdvo_init(pScrn, SDVOB);
11105                :      i830_sdvo_init(pScrn, SDVOC);
11106                :   } else {
11107                :      i830_dvo_init(pScrn);
11108                :   }
11109                :   if (IS_I9XX(pI830) && !IS_I915G(pI830))
11110                :      i830_tv_init(pScrn);
11111                :   
11112                :   for (o = 0; o < config->num_output; o++)
11113                :   {
11114                :      xf86OutputPtr        output = config->output[o];
11115                :      I830OutputPrivatePtr intel_output = output->driver_private;
11116                :      int                  crtc_mask;
11117                :      int                  c;
11118                :      
11119                :      crtc_mask = 0;
11120                :      for (c = 0; c < config->num_crtc; c++)
11121                :      {
11122                :         xf86CrtcPtr          crtc = config->crtc[c];
11123                :         I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
11124                :
11125                :         if (intel_output->pipe_mask & (1 << intel_crtc->pipe))
11126                :            crtc_mask |= (1 << c);
11127                :      }
11128                :      output->possible_crtcs = crtc_mask;
11129                :      output->possible_clones = i830_output_clones (pScrn, intel_output->clone_mask);
11130                :   }
11131                :}
11132                :
11133                :/**
11134                : * Setup the CRTCs
11135                : */
11136                :
11137                :
11138                :static void 
11139                :I830PreInitDDC(ScrnInfoPtr pScrn)
11140                :{
11141                :   I830Ptr pI830 = I830PTR(pScrn);
11142                :
11143                :   if (!xf86LoadSubModule(pScrn, "ddc")) {
11144                :      pI830->ddc2 = FALSE;
11145                :   } else {
11146                :      xf86LoaderReqSymLists(I810ddcSymbols, NULL);
11147                :      pI830->ddc2 = TRUE;
11148                :   }
11149                :
11150                :   /* DDC can use I2C bus */
11151                :   /* Load I2C if we have the code to use it */
11152                :   if (pI830->ddc2) {
11153                :      if (xf86LoadSubModule(pScrn, "i2c")) {
11154                :         xf86LoaderReqSymLists(I810i2cSymbols, NULL);
11155                :
11156                :         pI830->ddc2 = TRUE;
11157                :      } else {
11158                :         pI830->ddc2 = FALSE;
11159                :      }
11160                :   }
11161                :}
11162                :
11163                :static void
11164                :PreInitCleanup(ScrnInfoPtr pScrn)
11165                :{
11166                :   I830Ptr pI830 = I830PTR(pScrn);
11167                :
11168                :   if (I830IsPrimary(pScrn)) {
11169                :      if (pI830->entityPrivate)
11170                :         pI830->entityPrivate->pScrn_1 = NULL;
11171                :   } else {
11172                :      if (pI830->entityPrivate)
11173                :         pI830->entityPrivate->pScrn_2 = NULL;
11174                :   }
11175                :   if (pI830->swfSaved) {
11176                :      OUTREG(SWF0, pI830->saveSWF0);
11177                :      OUTREG(SWF4, pI830->saveSWF4);
11178                :   }
11179                :   if (pI830->MMIOBase)
11180                :      I830UnmapMMIO(pScrn);
11181                :   I830FreeRec(pScrn);
11182                :}
11183                :
11184                :Bool
11185                :I830IsPrimary(ScrnInfoPtr pScrn)
11186                :{
11187                :   I830Ptr pI830 = I830PTR(pScrn);
11188                :
11189                :   if (xf86IsEntityShared(pScrn->entityList[0])) {
11190                :        if (pI830->init == 0) return TRUE;
11191                :        else return FALSE;
11192                :   }
11193                :
11194                :   return TRUE;
11195                :}
11196                :
11197                :static Bool
11198                :i830_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
11199                :{
11200                :    scrn->virtualX = width;
11201                :    scrn->virtualY = height;
11202                :    return TRUE;
11203                :}
11204                :
11205                :static const xf86CrtcConfigFuncsRec i830_xf86crtc_config_funcs = {
11206                :    i830_xf86crtc_resize
11207                :};
11208                :
11209                :#define HOTKEY_BIOS_SWITCH      0
11210                :#define HOTKEY_DRIVER_NOTIFY    1
11211                :
11212                :/**
11213                : * Controls the BIOS's behavior on hotkey switch.
11214                : *
11215                : * If the mode is HOTKEY_BIOS_SWITCH, the BIOS will be set to do a mode switch
11216                : * on its own and update the state in the scratch register.
11217                : * If the mode is HOTKEY_DRIVER_NOTIFY, the BIOS won't do a mode switch and
11218                : * will just update the state to represent what it would have been switched to.
11219                : */
11220                :static void
11221                :i830SetHotkeyControl(ScrnInfoPtr pScrn, int mode)
11222                :{
11223                :   I830Ptr pI830 = I830PTR(pScrn);
11224                :   CARD8 gr18;
11225                :
11226                :   gr18 = pI830->readControl(pI830, GRX, 0x18);
11227                :   if (mode == HOTKEY_BIOS_SWITCH)
11228                :      gr18 &= ~HOTKEY_VBIOS_SWITCH_BLOCK;
11229                :   else
11230                :      gr18 |= HOTKEY_VBIOS_SWITCH_BLOCK;
11231                :   pI830->writeControl(pI830, GRX, 0x18, gr18);
11232                :}
11233                :
11234                :/**
11235                : * This is called per zaphod head (so usually just once) to do initialization
11236                : * before the Screen is created.
11237                : *
11238                : * This code generally covers probing, module loading, option handling
11239                : * card mapping, and RandR setup.
11240                : */
11241                :static Bool
11242                :I830PreInit(ScrnInfoPtr pScrn, int flags)
11243                :{
11244                :   xf86CrtcConfigPtr   xf86_config;
11245                :   vgaHWPtr hwp;
11246                :   I830Ptr pI830;
11247                :   MessageType from = X_PROBED;
11248                :   rgb defaultWeight = { 0, 0, 0 };
11249                :   EntityInfoPtr pEnt;
11250                :   I830EntPtr pI830Ent = NULL;                                  
11251                :   int flags24;
11252                :   int i;
11253                :   char *s;
11254                :   pointer pVBEModule = NULL;
11255                :   const char *chipname;
11256                :   int num_pipe;
11257                :   int max_width, max_height;
11258                :
11259                :   if (pScrn->numEntities != 1)
11260                :      return FALSE;
11261                :
11262                :   /* Load int10 module */
11263                :   if (!xf86LoadSubModule(pScrn, "int10"))
11264                :      return FALSE;
11265                :   xf86LoaderReqSymLists(I810int10Symbols, NULL);
11266                :
11267                :   /* Load vbe module */
11268                :   if (!(pVBEModule = xf86LoadSubModule(pScrn, "vbe")))
11269                :      return FALSE;
11270                :   xf86LoaderReqSymLists(I810vbeSymbols, NULL);
11271                :
11272                :   pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
11273                :
11274                :   if (flags & PROBE_DETECT) {
11275                :      I830ProbeDDC(pScrn, pEnt->index);
11276                :      return TRUE;
11277                :   }
11278                :
11279                :   /* The vgahw module should be loaded here when needed */
11280                :   if (!xf86LoadSubModule(pScrn, "vgahw"))
11281                :      return FALSE;
11282                :   xf86LoaderReqSymLists(I810vgahwSymbols, NULL);
11283                :
11284                :   /* Allocate a vgaHWRec */
11285                :   if (!vgaHWGetHWRec(pScrn))
11286                :      return FALSE;
11287                :
11288                :   /* Allocate driverPrivate */
11289                :   if (!I830GetRec(pScrn))
11290                :      return FALSE;
11291                :
11292                :   pI830 = I830PTR(pScrn);
11293                :   pI830->SaveGeneration = -1;
11294                :   pI830->pEnt = pEnt;
11295                :
11296                :   pScrn->displayWidth = 640; /* default it */
11297                :
11298                :   if (pI830->pEnt->location.type != BUS_PCI)
11299                :      return FALSE;
11300                :
11301                :   pI830->PciInfo = xf86GetPciInfoForEntity(pI830->pEnt->index);
11302                :   pI830->PciTag = pciTag(pI830->PciInfo->bus, pI830->PciInfo->device,
11303                :                          pI830->PciInfo->func);
11304                :
11305                :    /* Allocate an entity private if necessary */
11306                :    if (xf86IsEntityShared(pScrn->entityList[0])) {
11307                :        pI830Ent = xf86GetEntityPrivate(pScrn->entityList[0],
11308                :                                        I830EntityIndex)->ptr;
11309                :        pI830->entityPrivate = pI830Ent;
11310                :    } else 
11311                :        pI830->entityPrivate = NULL;
11312                :
11313                :   if (xf86RegisterResources(pI830->pEnt->index, NULL, ResNone)) {
11314                :      PreInitCleanup(pScrn);
11315                :      return FALSE;
11316                :   }
11317                :
11318                :   if (xf86IsEntityShared(pScrn->entityList[0])) {
11319                :      if (xf86IsPrimInitDone(pScrn->entityList[0])) {
11320                :         pI830->init = 1;
11321                :
11322                :         if (!pI830Ent->pScrn_1) {
11323                :            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
11324                :                 "Failed to setup second head due to primary head failure.\n");
11325                :            return FALSE;
11326                :         }
11327                :      } else {
11328                :         xf86SetPrimInitDone(pScrn->entityList[0]);
11329                :         pI830->init = 0;
11330                :      }
11331                :   }
11332                :
11333                :   if (xf86IsEntityShared(pScrn->entityList[0])) {
11334                :      if (!I830IsPrimary(pScrn)) {
11335                :         pI830Ent->pScrn_2 = pScrn;
11336                :      } else {
11337                :         pI830Ent->pScrn_1 = pScrn;
11338                :         pI830Ent->pScrn_2 = NULL;
11339                :      }
11340                :   }
11341                :
11342                :   pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
11343                :   pScrn->monitor = pScrn->confScreen->monitor;
11344                :   pScrn->progClock = TRUE;
11345                :   pScrn->rgbBits = 8;
11346                :
11347                :   flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
11348                :
11349                :   if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24))
11350                :      return FALSE;
11351                :
11352                :   switch (pScrn->depth) {
11353                :   case 8:
11354                :   case 15:
11355                :   case 16:
11356                :   case 24:
11357                :      break;
11358                :   default:
11359                :      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
11360                :                 "Given depth (%d) is not supported by I830 driver\n",
11361                :                 pScrn->depth);
11362                :      return FALSE;
11363                :   }
11364                :   xf86PrintDepthBpp(pScrn);
11365                :
11366                :   if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
11367                :      return FALSE;
11368                :   if (!xf86SetDefaultVisual(pScrn, -1))
11369                :      return FALSE;
11370                :
11371                :   hwp = VGAHWPTR(pScrn);
11372                :   pI830->cpp = pScrn->bitsPerPixel / 8;
11373                :
11374                :   pI830->preinit = TRUE;
11375                :
11376                :   /* Process the options */
11377                :   xf86CollectOptions(pScrn, NULL);
11378                :   if (!(pI830->Options = xalloc(sizeof(I830Options))))
11379                :      return FALSE;
11380                :   memcpy(pI830->Options, I830Options, sizeof(I830Options));
11381                :   xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI830->Options);
11382                :
11383                :   if (xf86ReturnOptValBool(pI830->Options, OPTION_MODEDEBUG, FALSE)) {
11384                :      pI830->debug_modes = TRUE;
11385                :   } else {
11386                :      pI830->debug_modes = FALSE;
11387                :   }
11388                :
11389                :   /* We have to use PIO to probe, because we haven't mapped yet. */
11390                :   I830SetPIOAccess(pI830);
11391                :
11392                :   switch (pI830->PciInfo->chipType) {
11393                :   case PCI_CHIP_I830_M:
11394                :      chipname = "830M";
11395                :      break;
11396                :   case PCI_CHIP_845_G:
11397                :      chipname = "845G";
11398                :      break;
11399                :   case PCI_CHIP_I855_GM:
11400                :      /* Check capid register to find the chipset variant */
11401                :      pI830->variant = (pciReadLong(pI830->PciTag, I85X_CAPID)
11402                :                                >> I85X_VARIANT_SHIFT) & I85X_VARIANT_MASK;
11403                :      switch (pI830->variant) {
11404                :      case I855_GM:
11405                :         chipname = "855GM";
11406                :         break;
11407                :      case I855_GME:
11408                :         chipname = "855GME";
11409                :         break;
11410                :      case I852_GM:
11411                :         chipname = "852GM";
11412                :         break;
11413                :      case I852_GME:
11414                :         chipname = "852GME";
11415                :         break;
11416                :      default:
11417                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
11418                :                    "Unknown 852GM/855GM variant: 0x%x)\n", pI830->variant);
11419                :         chipname = "852GM/855GM (unknown variant)";
11420                :         break;
11421                :      }
11422                :      break;
11423                :   case PCI_CHIP_I865_G:
11424                :      chipname = "865G";
11425                :      break;
11426                :   case PCI_CHIP_I915_G:
11427                :      chipname = "915G";
11428                :      break;
11429                :   case PCI_CHIP_E7221_G:
11430                :      chipname = "E7221 (i915)";
11431                :      break;
11432                :   case PCI_CHIP_I915_GM:
11433                :      chipname = "915GM";
11434                :      break;
11435                :   case PCI_CHIP_I945_G:
11436                :      chipname = "945G";
11437                :      break;
11438                :   case PCI_CHIP_I945_GM:
11439                :      chipname = "945GM";
11440                :      break;
11441                :   case PCI_CHIP_I945_GME:
11442                :      chipname = "945GME";
11443                :      break;
11444                :   case PCI_CHIP_I965_G:
11445                :   case PCI_CHIP_I965_G_1:
11446                :      chipname = "965G";
11447                :      break;
11448                :   case PCI_CHIP_I965_Q:
11449                :      chipname = "965Q";
11450                :      break;
11451                :   case PCI_CHIP_I946_GZ:
11452                :      chipname = "946GZ";
11453                :      break;
11454                :   case PCI_CHIP_I965_GM:
11455                :      chipname = "965GM";
11456                :      break;
11457                :   case PCI_CHIP_I965_GME:
11458                :      chipname = "965GME/GLE";
11459                :      break;
11460                :   case PCI_CHIP_G33_G:
11461                :      chipname = "G33";
11462                :      break;
11463                :   case PCI_CHIP_Q35_G:
11464                :      chipname = "Q35";
11465                :      break;
11466                :   case PCI_CHIP_Q33_G:
11467                :      chipname = "Q33";
11468                :      break;
11469                :   default:
11470                :      chipname = "unknown chipset";
11471                :      break;
11472                :   }
11473                :   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
11474                :              "Integrated Graphics Chipset: Intel(R) %s\n", chipname);
11475                :
11476                :   /* Set the Chipset and ChipRev, allowing config file entries to override. */
11477                :   if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) {
11478                :      pScrn->chipset = pI830->pEnt->device->chipset;
11479                :      from = X_CONFIG;
11480                :   } else if (pI830->pEnt->device->chipID >= 0) {
11481                :      pScrn->chipset = (char *)xf86TokenToString(I830Chipsets,
11482                :                                                 pI830->pEnt->device->chipID);
11483                :      from = X_CONFIG;
11484                :      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
11485                :                 pI830->pEnt->device->chipID);
11486                :      pI830->PciInfo->chipType = pI830->pEnt->device->chipID;
11487                :   } else {
11488                :      from = X_PROBED;
11489                :      pScrn->chipset = (char *)xf86TokenToString(I830Chipsets,
11490                :                                                 pI830->PciInfo->chipType);
11491                :   }
11492                :
11493                :   if (pI830->pEnt->device->chipRev >= 0) {
11494                :      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
11495                :                 pI830->pEnt->device->chipRev);
11496                :   }
11497                :
11498                :   xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
11499                :              (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i8xx");
11500                :
11501                :   if (pI830->pEnt->device->MemBase != 0) {
11502                :      pI830->LinearAddr = pI830->pEnt->device->MemBase;
11503                :      from = X_CONFIG;
11504                :   } else {
11505                :      if (IS_I9XX(pI830)) {
11506                :         pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xFF000000;
11507                :         from = X_PROBED;
11508                :      } else if (pI830->PciInfo->memBase[1] != 0) {
11509                :         /* XXX Check mask. */
11510                :         pI830->LinearAddr = pI830->PciInfo->memBase[0] & 0xFF000000;
11511                :         from = X_PROBED;
11512                :      } else {
11513                :         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
11514                :                    "No valid FB address in PCI config space\n");
11515                :         PreInitCleanup(pScrn);
11516                :         return FALSE;
11517                :      }
11518                :   }
11519                :
11520                :   xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
11521                :              (unsigned long)pI830->LinearAddr);
11522                :
11523                :   if (pI830->pEnt->device->IOBase != 0) {
11524                :      pI830->MMIOAddr = pI830->pEnt->device->IOBase;
11525                :      from = X_CONFIG;
11526                :   } else {
11527                :      if (IS_I9XX(pI830)) {
11528                :         pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000;
11529                :         from = X_PROBED;
11530                :      } else if (pI830->PciInfo->memBase[1]) {
11531                :         pI830->MMIOAddr = pI830->PciInfo->memBase[1] & 0xFFF80000;
11532                :         from = X_PROBED;
11533                :      } else {
11534                :         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
11535                :                    "No valid MMIO address in PCI config space\n");
11536                :         PreInitCleanup(pScrn);
11537                :         return FALSE;
11538                :      }
11539                :   }
11540                :
11541                :   xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
11542                :              (unsigned long)pI830->MMIOAddr);
11543                :
11544                :   /* Allocate an xf86CrtcConfig */
11545                :   xf86CrtcConfigInit (pScrn, &i830_xf86crtc_config_funcs);
11546                :   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
11547                :
11548                :   /* See i830_exa.c comments for why we limit the framebuffer size like this.
11549                :    */
11550                :   if (IS_I965G(pI830)) {
11551                :      max_width = 8192;
11552                :      max_height = 8192;
11553                :   } else {
11554                :      max_width = 2048;
11555                :      max_height = 2048;
11556                :   }
11557                :   xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height);
11558                :
11559                :   if (IS_I830(pI830) || IS_845G(pI830)) {
11560                :      PCITAG bridge;
11561                :      CARD16 gmch_ctrl;
11562                :
11563                :      bridge = pciTag(0, 0, 0);         /* This is always the host bridge */
11564                :      gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
11565                :      if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
11566                :         pI830->FbMapSize = 0x8000000;
11567                :      } else {
11568                :         pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */
11569                :      }
11570                :   } else {
11571                :      if (IS_I9XX(pI830)) {
11572                :         pI830->FbMapSize = 1UL << pciGetBaseSize(pI830->PciTag, 2, TRUE,
11573                :                                                  NULL);
11574                :      } else {
11575                :         /* 128MB aperture for later i8xx series. */
11576                :         pI830->FbMapSize = 0x8000000;
11577                :      }
11578                :   }
11579                :
11580                :   /* Some of the probing needs MMIO access, so map it here. */
11581                :   I830MapMMIO(pScrn);
11582                :
11583                :   if (pI830->debug_modes) {
11584                :      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state on X startup:\n");
11585                :      i830DumpRegs (pScrn);
11586                :   }
11587                :
11588                :   i830TakeRegSnapshot(pScrn);
11589                :
11590                :#if 1
11591                :   pI830->saveSWF0 = INREG(SWF0);
11592                :   pI830->saveSWF4 = INREG(SWF4);
11593                :   pI830->swfSaved = TRUE;
11594                :
11595                :   /* Set "extended desktop" */
11596                :   OUTREG(SWF0, pI830->saveSWF0 | (1 << 21));
11597                :
11598                :   /* Set "driver loaded",  "OS unknown", "APM 1.2" */
11599                :   OUTREG(SWF4, (pI830->saveSWF4 & ~((3 << 19) | (7 << 16))) |
11600                :                (1 << 23) | (2 << 16));
11601                :#endif
11602                :
11603                :   if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
11604                :      num_pipe = 1;
11605                :   else
11606                :   if (IS_MOBILE(pI830) || IS_I9XX(pI830))
11607                :      num_pipe = 2;
11608                :   else
11609                :      num_pipe = 1;
11610                :   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n",
11611                :              num_pipe, num_pipe > 1 ? "s" : "");
11612                :
11613                :   if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) {
11614                :      pI830->noAccel = TRUE;
11615                :   }
11616                :
11617                :   /*
11618                :    * The ugliness below:
11619                :    * If either XAA or EXA (exclusive) is compiled in, default to it.
11620                :    * 
11621                :    * If both are compiled in, and the user didn't specify noAccel, use the
11622                :    * config option AccelMethod to determine which to use, defaulting to XAA
11623                :    * if none is specified, or if the string was unrecognized.
11624                :    *
11625                :    * All this *could* go away if we removed XAA support from this driver,
11626                :    * for example. :)
11627                :    */
11628                :   if (!pI830->noAccel) {
11629                :#if (defined(I830_USE_EXA) && defined(I830_USE_XAA)) || !defined(I830_USE_EXA)
11630                :       pI830->useEXA = FALSE;
11631                :#else
11632                :       pI830->useEXA = TRUE;
11633                :#endif
11634                :#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
11635                :       int from = X_DEFAULT;
11636                :       if ((s = (char *)xf86GetOptValString(pI830->Options,
11637                :                                            OPTION_ACCELMETHOD))) {
11638                :           if (!xf86NameCmp(s, "EXA")) {
11639                :               from = X_CONFIG;
11640                :               pI830->useEXA = TRUE;
11641                :           }
11642                :           else if (!xf86NameCmp(s, "XAA")) {
11643                :               from = X_CONFIG;
11644                :               pI830->useEXA = FALSE;
11645                :           }
11646                :       }
11647                :#endif
11648                :       xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n",
11649                :                  pI830->useEXA ? "EXA" : "XAA");
11650                :   }
11651                :
11652                :   if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) {
11653                :      pI830->SWCursor = TRUE;
11654                :   }
11655                :
11656                :   pI830->directRenderingDisabled =
11657                :        !xf86ReturnOptValBool(pI830->Options, OPTION_DRI, TRUE);
11658                :
11659                :#ifdef XF86DRI
11660                :   if (!pI830->directRenderingDisabled) {
11661                :      if (pI830->noAccel || pI830->SWCursor) {
11662                :         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
11663                :                    "needs HW cursor and 2D acceleration.\n");
11664                :         pI830->directRenderingDisabled = TRUE;
11665                :      } else if (pScrn->depth != 16 && pScrn->depth != 24) {
11666                :         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
11667                :                    "runs only at depths 16 and 24.\n");
11668                :         pI830->directRenderingDisabled = TRUE;
11669                :      }
11670                :
11671                :      pI830->mmModeFlags = 0;
11672                :
11673                :      if (!pI830->directRenderingDisabled) {
11674                :         pI830->mmModeFlags = I830_KERNEL_TEX;
11675                :#ifdef XF86DRI_MM
11676                :         Bool tmp = FALSE;
11677                :
11678                :         if (!IS_I965G(pI830))
11679                :            pI830->mmModeFlags |= I830_KERNEL_MM;
11680                :#endif
11681                :
11682                :         from = X_PROBED;
11683                :
11684                :#ifdef XF86DRI_MM
11685                :         if (xf86GetOptValBool(pI830->Options, 
11686                :                               OPTION_INTELTEXPOOL, &tmp)) {
11687                :            from = X_CONFIG;
11688                :            if (tmp) {
11689                :               pI830->mmModeFlags |= I830_KERNEL_TEX;
11690                :               pI830->mmModeFlags &= ~I830_KERNEL_MM;
11691                :            } else {
11692                :               pI830->mmModeFlags &= ~I830_KERNEL_TEX;
11693                :               pI830->mmModeFlags |= I830_KERNEL_MM;
11694                :            }          
11695                :         }
11696                :#endif
11697                :
11698                :         xf86DrvMsg(pScrn->scrnIndex, from,
11699                :                    "Will %stry to allocate texture pool "
11700                :                    "for old Mesa 3D driver.\n",
11701                :                    (pI830->mmModeFlags & I830_KERNEL_TEX) ?
11702                :                    "" : "not ");
11703                :
11704                :#ifdef XF86DRI_MM
11705                :         pI830->mmSize = I830_MM_MAXSIZE;
11706                :         from = X_INFO;
11707                :         if (xf86GetOptValInteger(pI830->Options, OPTION_INTELMMSIZE,
11708                :                                  &(pI830->mmSize))) {
11709                :            from = X_CONFIG;
11710                :         }
11711                :         xf86DrvMsg(pScrn->scrnIndex, from, 
11712                :                    "Will try to reserve %d kiB of AGP aperture space\n"
11713                :                    "\tfor the DRM memory manager.\n",
11714                :                    pI830->mmSize);
11715                :#endif
11716                :      }
11717                :   } 
11718                :   
11719                :#endif
11720                :
11721                :   I830PreInitDDC(pScrn);
11722                :   for (i = 0; i < num_pipe; i++) {
11723                :       i830_crtc_init(pScrn, i);
11724                :   }
11725                :   I830SetupOutputs(pScrn);
11726                :
11727                :   SaveHWState(pScrn);
11728                :   if (!xf86InitialConfiguration (pScrn, FALSE))
11729                :   {
11730                :      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
11731                :      RestoreHWState(pScrn);
11732                :      PreInitCleanup(pScrn);
11733                :      return FALSE;
11734                :   }
11735                :   RestoreHWState(pScrn);
11736                :
11737                :   /* XXX This should go away, replaced by xf86Crtc.c support for it */
11738                :   pI830->rotation = RR_Rotate_0;
11739                :
11740                :   /*
11741                :    * Let's setup the mobile systems to check the lid status
11742                :    */
11743                :   if (IS_MOBILE(pI830)) {
11744                :      pI830->checkDevices = TRUE;
11745                :
11746                :      if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKDEVICES, TRUE)) {
11747                :         pI830->checkDevices = FALSE;
11748                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
11749                :      } else
11750                :      if (pI830->entityPrivate && !I830IsPrimary(pScrn) &&
11751                :          !I830PTR(pI830->entityPrivate->pScrn_1)->checkDevices) {
11752                :         /* If checklid is off, on the primary head, then 
11753                :          * turn it off on the secondary*/
11754                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
11755                :         pI830->checkDevices = FALSE;
11756                :      } else
11757                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays enabled\n");
11758                :   } else
11759                :      pI830->checkDevices = FALSE;
11760                :
11761                :   pI830->stolen_size = I830DetectMemory(pScrn);
11762                :
11763                :   pI830->XvDisabled =
11764                :        !xf86ReturnOptValBool(pI830->Options, OPTION_XVIDEO, TRUE);
11765                :
11766                :#ifdef I830_XV
11767                :   if (xf86GetOptValInteger(pI830->Options, OPTION_VIDEO_KEY,
11768                :                            &(pI830->colorKey))) {
11769                :      from = X_CONFIG;
11770                :   } else if (xf86GetOptValInteger(pI830->Options, OPTION_COLOR_KEY,
11771                :                            &(pI830->colorKey))) {
11772                :      from = X_CONFIG;
11773                :   } else {
11774                :      pI830->colorKey = (1 << pScrn->offset.red) |
11775                :                        (1 << pScrn->offset.green) |
11776                :                        (((pScrn->mask.blue >> pScrn->offset.blue) - 1) <<
11777                :                         pScrn->offset.blue);
11778                :      from = X_DEFAULT;
11779                :   }
11780                :   xf86DrvMsg(pScrn->scrnIndex, from, "video overlay key set to 0x%x\n",
11781                :              pI830->colorKey);
11782                :#endif
11783                :
11784                :#ifdef XF86DRI
11785                :   pI830->allowPageFlip = FALSE;
11786                :   from = (!pI830->directRenderingDisabled &&
11787                :           xf86GetOptValBool(pI830->Options, OPTION_PAGEFLIP,
11788                :                             &pI830->allowPageFlip)) ? X_CONFIG : X_DEFAULT;
11789                :
11790                :   xf86DrvMsg(pScrn->scrnIndex, from, "Will%s try to enable page flipping\n",
11791                :              pI830->allowPageFlip ? "" : " not");
11792                :#endif
11793                :
11794                :#ifdef XF86DRI
11795                :   pI830->TripleBuffer = FALSE;
11796                :   from =  (!pI830->directRenderingDisabled &&
11797                :            xf86GetOptValBool(pI830->Options, OPTION_TRIPLEBUFFER,
11798                :                              &pI830->TripleBuffer)) ? X_CONFIG : X_DEFAULT;
11799                :
11800                :   xf86DrvMsg(pScrn->scrnIndex, from, "Triple buffering %sabled\n",
11801                :              pI830->TripleBuffer ? "en" : "dis");
11802                :#endif
11803                :
11804                :   /*
11805                :    * If the driver can do gamma correction, it should call xf86SetGamma() here.
11806                :    */
11807                :
11808                :   {
11809                :      Gamma zeros = { 0.0, 0.0, 0.0 };
11810                :
11811                :      if (!xf86SetGamma(pScrn, zeros)) {
11812                :         PreInitCleanup(pScrn);
11813                :         return FALSE;
11814                :      }
11815                :   }
11816                :
11817                :   /* Check if the HW cursor needs physical address. */
11818                :   if (IS_MOBILE(pI830) || IS_I9XX(pI830))
11819                :      pI830->CursorNeedsPhysical = TRUE;
11820                :   else
11821                :      pI830->CursorNeedsPhysical = FALSE;
11822                :
11823                :   if (IS_I965G(pI830) || IS_G33CLASS(pI830))
11824                :      pI830->CursorNeedsPhysical = FALSE;
11825                :
11826                :   /*
11827                :    * XXX If we knew the pre-initialised GTT format for certain, we could
11828                :    * probably figure out the physical address even in the StolenOnly case.
11829                :    */
11830                :   if (!I830IsPrimary(pScrn)) {
11831                :        I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
11832                :        if (!pI8301->SWCursor) {
11833                :          xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
11834                :                 "Using HW Cursor because it's enabled on primary head.\n");
11835                :          pI830->SWCursor = FALSE;
11836                :        }
11837                :   } else 
11838                :   if (pI830->StolenOnly && pI830->CursorNeedsPhysical && !pI830->SWCursor) {
11839                :      xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
11840                :                 "HW Cursor disabled because it needs agpgart memory.\n");
11841                :      pI830->SWCursor = TRUE;
11842                :   }
11843                :
11844                :   if (pScrn->modes == NULL) {
11845                :      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
11846                :      PreInitCleanup(pScrn);
11847                :      return FALSE;
11848                :   }
11849                :   pScrn->currentMode = pScrn->modes;
11850                :
11851                :   if (!IS_I965G(pI830) && pScrn->virtualY > 2048) {
11852                :      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n");
11853                :      pI830->noAccel = TRUE;
11854                :   }
11855                :
11856                :   /* Don't need MMIO access anymore. */
11857                :   if (pI830->swfSaved) {
11858                :      OUTREG(SWF0, pI830->saveSWF0);
11859                :      OUTREG(SWF4, pI830->saveSWF4);
11860                :   }
11861                :
11862                :   /* Set display resolution */
11863                :   xf86SetDpi(pScrn, 0, 0);
11864                :
11865                :   /* Load the required sub modules */
11866                :   if (!xf86LoadSubModule(pScrn, "fb")) {
11867                :      PreInitCleanup(pScrn);
11868                :      return FALSE;
11869                :   }
11870                :
11871                :   xf86LoaderReqSymLists(I810fbSymbols, NULL);
11872                :
11873                :#ifdef I830_USE_XAA
11874                :   if (!pI830->noAccel && !pI830->useEXA) {
11875                :      if (!xf86LoadSubModule(pScrn, "xaa")) {
11876                :         PreInitCleanup(pScrn);
11877                :         return FALSE;
11878                :      }
11879                :      xf86LoaderReqSymLists(I810xaaSymbols, NULL);
11880                :   }
11881                :#endif
11882                :
11883                :#ifdef I830_USE_EXA
11884                :   if (!pI830->noAccel && pI830->useEXA) {
11885                :      XF86ModReqInfo req;
11886                :      int errmaj, errmin;
11887                :
11888                :      memset(&req, 0, sizeof(req));
11889                :      req.majorversion = 2;
11890                :      req.minorversion = 1;
11891                :      if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
11892                :                &errmaj, &errmin)) {
11893                :         LoaderErrorMsg(NULL, "exa", errmaj, errmin);
11894                :         PreInitCleanup(pScrn);
11895                :         return FALSE;
11896                :      }
11897                :      xf86LoaderReqSymLists(I830exaSymbols, NULL);
11898                :   }
11899                :#endif
11900                :   if (!pI830->SWCursor) {
11901                :      if (!xf86LoadSubModule(pScrn, "ramdac")) {
11902                :         PreInitCleanup(pScrn);
11903                :         return FALSE;
11904                :      }
11905                :      xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
11906                :   }
11907                :
11908                :   i830CompareRegsToSnapshot(pScrn, "After PreInit");
11909                :
11910                :   I830UnmapMMIO(pScrn);
11911                :
11912                :   /*  We won't be using the VGA access after the probe. */
11913                :   I830SetMMIOAccess(pI830);
11914                :   xf86SetOperatingState(resVgaIo, pI830->pEnt->index, ResUnusedOpr);
11915                :   xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr);
11916                :
11917                :#if 0
11918                :   if (I830IsPrimary(pScrn)) {
11919                :      vbeFree(pI830->pVbe);
11920                :   }
11921                :   pI830->pVbe = NULL;
11922                :#endif
11923                :
11924                :#if defined(XF86DRI)
11925                :   /* Load the dri module if requested. */
11926                :   if (xf86ReturnOptValBool(pI830->Options, OPTION_DRI, FALSE) &&
11927                :       !pI830->directRenderingDisabled) {
11928                :      if (xf86LoadSubModule(pScrn, "dri")) {
11929                :         xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL);
11930                :      }
11931                :   }
11932                :#endif
11933                :
11934                :   pI830->preinit = FALSE;
11935                :
11936                :   return TRUE;
11937                :}
11938                :
11939                :/*
11940                : * Reset registers that it doesn't make sense to save/restore to a sane state.
11941                : * This is basically the ring buffer and fence registers.  Restoring these
11942                : * doesn't make sense without restoring GTT mappings.  This is something that
11943                : * whoever gets control next should do.
11944                : */
11945                :static void
11946                :ResetState(ScrnInfoPtr pScrn, Bool flush)
11947                :{
11948                :   I830Ptr pI830 = I830PTR(pScrn);
11949                :   int i;
11950                :   unsigned long temp;
11951                :
11952                :   DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush));
11953                :
11954                :   if (!I830IsPrimary(pScrn)) return;
11955                :
11956                :   if (pI830->entityPrivate)
11957                :      pI830->entityPrivate->RingRunning = 0;
11958                :
11959                :   /* Reset the fence registers to 0 */
11960                :   if (IS_I965G(pI830)) {
11961                :      for (i = 0; i < FENCE_NEW_NR; i++) {
11962                :         OUTREG(FENCE_NEW + i * 8, 0);
11963                :         OUTREG(FENCE_NEW + 4 + i * 8, 0);
11964                :      }
11965                :   } else {
11966                :      for (i = 0; i < FENCE_NR; i++)
11967                :         OUTREG(FENCE + i * 4, 0);
11968                :   }
11969                :   /* Flush the ring buffer (if enabled), then disable it. */
11970                :   /* God this is ugly */
11971                :#define flush_ring() do { \
11972                :      temp = INREG(LP_RING + RING_LEN); \
11973                :      if (temp & RING_VALID) { \
11974                :         I830RefreshRing(pScrn); \
11975                :         I830Sync(pScrn); \
11976                :         DO_RING_IDLE(); \
11977                :      } \
11978                :   } while(0)
11979                :#ifdef I830_USE_XAA
11980                :   if (!pI830->useEXA && flush && pI830->AccelInfoRec)
11981                :       flush_ring();
11982                :#endif
11983                :#ifdef I830_USE_EXA
11984                :   if (pI830->useEXA && flush && pI830->EXADriverPtr)
11985                :       flush_ring();
11986                :#endif
11987                :
11988                :   OUTREG(LP_RING + RING_LEN, 0);
11989                :   OUTREG(LP_RING + RING_HEAD, 0);
11990                :   OUTREG(LP_RING + RING_TAIL, 0);
11991                :   OUTREG(LP_RING + RING_START, 0);
11992                :
11993                :   xf86_hide_cursors (pScrn);
11994                :}
11995                :
11996                :static void
11997                :SetFenceRegs(ScrnInfoPtr pScrn)
11998                :{
11999                :   I830Ptr pI830 = I830PTR(pScrn);
12000                :   int i;
12001                :
12002                :   DPRINTF(PFX, "SetFenceRegs\n");
12003                :
12004                :   if (!I830IsPrimary(pScrn)) return;
12005                :
12006                :   if (IS_I965G(pI830)) {
12007                :      for (i = 0; i < FENCE_NEW_NR; i++) {
12008                :         OUTREG(FENCE_NEW + i * 8, pI830->fence[i]);
12009                :         OUTREG(FENCE_NEW + 4 + i * 8, pI830->fence[i+FENCE_NEW_NR]);
12010                :         if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
12011                :            ErrorF("Fence Start Register : %x\n", pI830->fence[i]);
12012                :            ErrorF("Fence End Register : %x\n", pI830->fence[i+FENCE_NEW_NR]);
12013                :         }
12014                :      }
12015                :   } else {
12016                :      for (i = 0; i < FENCE_NR; i++) {
12017                :         OUTREG(FENCE + i * 4, pI830->fence[i]);
12018                :         if (I810_DEBUG & DEBUG_VERBOSE_VGA)
12019                :            ErrorF("Fence Register : %x\n", pI830->fence[i]);
12020                :      }
12021                :   }
12022                :}
12023                :
12024                :static void
12025                :SetRingRegs(ScrnInfoPtr pScrn)
12026                :{
12027                :   I830Ptr pI830 = I830PTR(pScrn);
12028                :   unsigned int itemp;
12029                :
12030                :   DPRINTF(PFX, "SetRingRegs\n");
12031                :
12032                :   if (pI830->noAccel)
12033                :      return;
12034                :
12035                :   if (!I830IsPrimary(pScrn)) return;
12036                :
12037                :   if (pI830->entityPrivate)
12038                :      pI830->entityPrivate->RingRunning = 1;
12039                :
12040                :   OUTREG(LP_RING + RING_LEN, 0);
12041                :   OUTREG(LP_RING + RING_TAIL, 0);
12042                :   OUTREG(LP_RING + RING_HEAD, 0);
12043                :
12044                :   assert((pI830->LpRing->mem->offset & I830_RING_START_MASK) ==
12045                :           pI830->LpRing->mem->offset);
12046                :
12047                :   /* Don't care about the old value.  Reserved bits must be zero anyway. */
12048                :   itemp = pI830->LpRing->mem->offset;
12049                :   OUTREG(LP_RING + RING_START, itemp);
12050                :
12051                :   if (((pI830->LpRing->mem->size - 4096) & I830_RING_NR_PAGES) !=
12052                :       pI830->LpRing->mem->size - 4096) {
12053                :      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
12054                :                 "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
12055                :                 "mask (%x)\n", pI830->LpRing->mem->size - 4096,
12056                :                 I830_RING_NR_PAGES);
12057                :   }
12058                :   /* Don't care about the old value.  Reserved bits must be zero anyway. */
12059                :   itemp = (pI830->LpRing->mem->size - 4096) & I830_RING_NR_PAGES;
12060                :   itemp |= (RING_NO_REPORT | RING_VALID);
12061                :   OUTREG(LP_RING + RING_LEN, itemp);
12062                :   I830RefreshRing(pScrn);
12063                :}
12064                :
12065                :/*
12066                : * This should be called everytime the X server gains control of the screen,
12067                : * before any video modes are programmed (ScreenInit, EnterVT).
12068                : */
12069                :static void
12070                :SetHWOperatingState(ScrnInfoPtr pScrn)
12071                :{
12072                :   I830Ptr pI830 = I830PTR(pScrn);
12073                :
12074                :   DPRINTF(PFX, "SetHWOperatingState\n");
12075                :
12076                :   /* Disable clock gating reported to work incorrectly according to the specs.
12077                :    */
12078                :   if (IS_I965GM(pI830)) {
12079                :      OUTREG(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
12080                :   } else if (IS_I965G(pI830)) {
12081                :      OUTREG(RENCLK_GATE_D1,
12082                :             I965_RCC_CLOCK_GATE_DISABLE | I965_ISC_CLOCK_GATE_DISABLE);
12083                :   } else if (IS_I855(pI830) || IS_I865G(pI830)) {
12084                :      OUTREG(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
12085                :   } else if (IS_I830(pI830)) {
12086                :      OUTREG(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
12087                :   }
12088                :
12089                :   if (!pI830->noAccel)
12090                :      SetRingRegs(pScrn);
12091                :   SetFenceRegs(pScrn);
12092                :   if (!pI830->SWCursor)
12093                :      I830InitHWCursor(pScrn);
12094                :}
12095                :
12096                :static Bool
12097                :SaveHWState(ScrnInfoPtr pScrn)
12098                :{
12099                :   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
12100                :   I830Ptr pI830 = I830PTR(pScrn);
12101                :   vgaHWPtr hwp = VGAHWPTR(pScrn);
12102                :   vgaRegPtr vgaReg = &hwp->SavedReg;
12103                :   int i;
12104                :
12105                :   /* Save video mode information for native mode-setting. */
12106                :   pI830->saveDSPACNTR = INREG(DSPACNTR);
12107                :   pI830->savePIPEACONF = INREG(PIPEACONF);
12108                :   pI830->savePIPEASRC = INREG(PIPEASRC);
12109                :   pI830->saveFPA0 = INREG(FPA0);
12110                :   pI830->saveFPA1 = INREG(FPA1);
12111                :   pI830->saveDPLL_A = INREG(DPLL_A);
12112                :   if (IS_I965G(pI830))
12113                :      pI830->saveDPLL_A_MD = INREG(DPLL_A_MD);
12114                :   pI830->saveHTOTAL_A = INREG(HTOTAL_A);
12115                :   pI830->saveHBLANK_A = INREG(HBLANK_A);
12116                :   pI830->saveHSYNC_A = INREG(HSYNC_A);
12117                :   pI830->saveVTOTAL_A = INREG(VTOTAL_A);
12118                :   pI830->saveVBLANK_A = INREG(VBLANK_A);
12119                :   pI830->saveVSYNC_A = INREG(VSYNC_A);
12120                :   pI830->saveBCLRPAT_A = INREG(BCLRPAT_A);
12121                :   pI830->saveDSPASTRIDE = INREG(DSPASTRIDE);
12122                :   pI830->saveDSPASIZE = INREG(DSPASIZE);
12123                :   pI830->saveDSPAPOS = INREG(DSPAPOS);
12124                :   pI830->saveDSPABASE = INREG(DSPABASE);
12125                :
12126                :   for(i= 0; i < 256; i++) {
12127                :      pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
12128                :   }
12129                :
12130                :   if(xf86_config->num_crtc == 2) {
12131                :      pI830->savePIPEBCONF = INREG(PIPEBCONF);
12132                :      pI830->savePIPEBSRC = INREG(PIPEBSRC);
12133                :      pI830->saveDSPBCNTR = INREG(DSPBCNTR);
12134                :      pI830->saveFPB0 = INREG(FPB0);
12135                :      pI830->saveFPB1 = INREG(FPB1);
12136                :      pI830->saveDPLL_B = INREG(DPLL_B);
12137                :      if (IS_I965G(pI830))
12138                :         pI830->saveDPLL_B_MD = INREG(DPLL_B_MD);
12139                :      pI830->saveHTOTAL_B = INREG(HTOTAL_B);
12140                :      pI830->saveHBLANK_B = INREG(HBLANK_B);
12141                :      pI830->saveHSYNC_B = INREG(HSYNC_B);
12142                :      pI830->saveVTOTAL_B = INREG(VTOTAL_B);
12143                :      pI830->saveVBLANK_B = INREG(VBLANK_B);
12144                :      pI830->saveVSYNC_B = INREG(VSYNC_B);
12145                :      pI830->saveBCLRPAT_B = INREG(BCLRPAT_B);
12146                :      pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
12147                :      pI830->saveDSPBSIZE = INREG(DSPBSIZE);
12148                :      pI830->saveDSPBPOS = INREG(DSPBPOS);
12149                :      pI830->saveDSPBBASE = INREG(DSPBBASE);
12150                :      for(i= 0; i < 256; i++) {
12151                :         pI830->savePaletteB[i] = INREG(PALETTE_B + (i << 2));
12152                :      }
12153                :   }
12154                :
12155                :   if (IS_I965G(pI830)) {
12156                :      pI830->saveDSPASURF = INREG(DSPASURF);
12157                :      pI830->saveDSPBSURF = INREG(DSPBSURF);
12158                :   }
12159                :
12160                :   pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0);
12161                :   pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1);
12162                :   pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV);
12163                :   pI830->saveVGACNTRL = INREG(VGACNTRL);
12164                :
12165                :   for(i = 0; i < 7; i++) {
12166                :      pI830->saveSWF[i] = INREG(SWF0 + (i << 2));
12167                :      pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2));
12168                :   }
12169                :   pI830->saveSWF[14] = INREG(SWF30);
12170                :   pI830->saveSWF[15] = INREG(SWF31);
12171                :   pI830->saveSWF[16] = INREG(SWF32);
12172                :
12173                :   if (IS_MOBILE(pI830) && !IS_I830(pI830))
12174                :      pI830->saveLVDS = INREG(LVDS);
12175                :   pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
12176                :
12177                :   for (i = 0; i < xf86_config->num_output; i++) {
12178                :      xf86OutputPtr   output = xf86_config->output[i];
12179                :      if (output->funcs->save)
12180                :         (*output->funcs->save) (output);
12181                :   }
12182                :
12183                :   vgaHWUnlock(hwp);
12184                :   vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
12185                :
12186                :   return TRUE;
12187                :}
12188                :
12189                :static Bool
12190                :RestoreHWState(ScrnInfoPtr pScrn)
12191                :{
12192                :   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
12193                :   I830Ptr pI830 = I830PTR(pScrn);
12194                :   vgaHWPtr hwp = VGAHWPTR(pScrn);
12195                :   vgaRegPtr vgaReg = &hwp->SavedReg;
12196                :   int i;
12197                :
12198                :   DPRINTF(PFX, "RestoreHWState\n");
12199                :
12200                :#ifdef XF86DRI
12201                :   I830DRISetVBlankInterrupt (pScrn, FALSE);
12202                :#endif
12203                :   /* Disable outputs */
12204                :   for (i = 0; i < xf86_config->num_output; i++) {
12205                :      xf86OutputPtr   output = xf86_config->output[i];
12206                :      output->funcs->dpms(output, DPMSModeOff);
12207                :   }
12208                :   i830WaitForVblank(pScrn);
12209                :   
12210                :   /* Disable pipes */
12211                :   for (i = 0; i < xf86_config->num_crtc; i++) {
12212                :      xf86CrtcPtr crtc = xf86_config->crtc[i];
12213                :      crtc->funcs->dpms(crtc, DPMSModeOff);
12214                :   }
12215                :   i830WaitForVblank(pScrn);
12216                :
12217                :   if (IS_MOBILE(pI830) && !IS_I830(pI830))
12218                :      OUTREG(LVDS, pI830->saveLVDS);
12219                :
12220                :   if (!IS_I830(pI830) && !IS_845G(pI830))
12221                :     OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
12222                :
12223                :   if (pI830->saveDPLL_A & DPLL_VCO_ENABLE)
12224                :   {
12225                :      OUTREG(DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE);
12226                :      usleep(150);
12227                :   }
12228                :   OUTREG(FPA0, pI830->saveFPA0);
12229                :   OUTREG(FPA1, pI830->saveFPA1);
12230                :   OUTREG(DPLL_A, pI830->saveDPLL_A);
12231                :   usleep(150);
12232                :   if (IS_I965G(pI830))
12233                :      OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
12234                :   else
12235                :      OUTREG(DPLL_A, pI830->saveDPLL_A);
12236                :   usleep(150);
12237                :
12238                :   OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
12239                :   OUTREG(HBLANK_A, pI830->saveHBLANK_A);
12240                :   OUTREG(HSYNC_A, pI830->saveHSYNC_A);
12241                :   OUTREG(VTOTAL_A, pI830->saveVTOTAL_A);
12242                :   OUTREG(VBLANK_A, pI830->saveVBLANK_A);
12243                :   OUTREG(VSYNC_A, pI830->saveVSYNC_A);
12244                :   OUTREG(BCLRPAT_A, pI830->saveBCLRPAT_A);
12245                :   
12246                :   OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
12247                :   OUTREG(DSPASIZE, pI830->saveDSPASIZE);
12248                :   OUTREG(DSPAPOS, pI830->saveDSPAPOS);
12249                :   OUTREG(PIPEASRC, pI830->savePIPEASRC);
12250                :   OUTREG(DSPABASE, pI830->saveDSPABASE);
12251                :   if (IS_I965G(pI830))
12252                :      OUTREG(DSPASURF, pI830->saveDSPASURF);
12253                :   OUTREG(PIPEACONF, pI830->savePIPEACONF);
12254                :   i830WaitForVblank(pScrn);
12255                :   OUTREG(DSPACNTR, pI830->saveDSPACNTR);
12256                :   OUTREG(DSPABASE, INREG(DSPABASE));
12257                :   i830WaitForVblank(pScrn);
12258                :   
12259                :   if(xf86_config->num_crtc == 2) 
12260                :   {
12261                :      if (pI830->saveDPLL_B & DPLL_VCO_ENABLE)
12262                :      {
12263                :         OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE);
12264                :         usleep(150);
12265                :      }
12266                :      OUTREG(FPB0, pI830->saveFPB0);
12267                :      OUTREG(FPB1, pI830->saveFPB1);
12268                :      OUTREG(DPLL_B, pI830->saveDPLL_B);
12269                :      usleep(150);
12270                :      if (IS_I965G(pI830))
12271                :         OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
12272                :      else
12273                :         OUTREG(DPLL_B, pI830->saveDPLL_B);
12274                :      usleep(150);
12275                :   
12276                :      OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
12277                :      OUTREG(HBLANK_B, pI830->saveHBLANK_B);
12278                :      OUTREG(HSYNC_B, pI830->saveHSYNC_B);
12279                :      OUTREG(VTOTAL_B, pI830->saveVTOTAL_B);
12280                :      OUTREG(VBLANK_B, pI830->saveVBLANK_B);
12281                :      OUTREG(VSYNC_B, pI830->saveVSYNC_B);
12282                :      OUTREG(BCLRPAT_B, pI830->saveBCLRPAT_B);
12283                :      OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
12284                :      OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
12285                :      OUTREG(DSPBPOS, pI830->saveDSPBPOS);
12286                :      OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
12287                :      OUTREG(DSPBBASE, pI830->saveDSPBBASE);
12288                :      if (IS_I965G(pI830))
12289                :         OUTREG(DSPBSURF, pI830->saveDSPBSURF);
12290                :      OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
12291                :      i830WaitForVblank(pScrn);
12292                :      OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
12293                :      OUTREG(DSPBBASE, INREG(DSPBBASE));
12294                :      i830WaitForVblank(pScrn);
12295                :   }
12296                :
12297                :   /* Restore outputs */
12298                :   for (i = 0; i < xf86_config->num_output; i++) {
12299                :      xf86OutputPtr   output = xf86_config->output[i];
12300                :      if (output->funcs->restore)
12301                :         output->funcs->restore(output);
12302                :   }
12303                :    
12304                :   OUTREG(VGACNTRL, pI830->saveVGACNTRL);
12305                :
12306                :   OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
12307                :   OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
12308                :   OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
12309                :
12310                :   for(i = 0; i < 256; i++) {
12311                :      OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
12312                :   }
12313                :   
12314                :   if(xf86_config->num_crtc == 2) {
12315                :      for(i= 0; i < 256; i++) {
12316                :         OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]);
12317                :      }
12318                :   }
12319                :
12320                :   for(i = 0; i < 7; i++) {
12321                :      OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
12322                :      OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
12323                :   }
12324                :
12325                :   OUTREG(SWF30, pI830->saveSWF[14]);
12326                :   OUTREG(SWF31, pI830->saveSWF[15]);
12327                :   OUTREG(SWF32, pI830->saveSWF[16]);
12328                :
12329                :   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
12330                :   vgaHWLock(hwp);
12331                :
12332                :   return TRUE;
12333                :}
12334                :
12335                :static void
12336                :I830PointerMoved(int index, int x, int y)
12337                :{
12338                :   ScrnInfoPtr pScrn = xf86Screens[index];
12339                :   I830Ptr pI830 = I830PTR(pScrn);
12340                :   int newX = x, newY = y;
12341                :
12342                :   switch (pI830->rotation) {
12343                :      case RR_Rotate_0:
12344                :         break;
12345                :      case RR_Rotate_90:
12346                :         newX = y;
12347                :         newY = pScrn->pScreen->width - x - 1;
12348                :         break;
12349                :      case RR_Rotate_180:
12350                :         newX = pScrn->pScreen->width - x - 1;
12351                :         newY = pScrn->pScreen->height - y - 1;
12352                :         break;
12353                :      case RR_Rotate_270:
12354                :         newX = pScrn->pScreen->height - y - 1;
12355                :         newY = x;
12356                :         break;
12357                :   }
12358                :
12359                :   (*pI830->PointerMoved)(index, newX, newY);
12360                :}
12361                :
12362                :static Bool
12363                :I830InitFBManager(
12364                :    ScreenPtr pScreen,  
12365                :    BoxPtr FullBox
12366                :){
12367                :   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
12368                :   RegionRec ScreenRegion;
12369                :   RegionRec FullRegion;
12370                :   BoxRec ScreenBox;
12371                :   Bool ret;
12372                :
12373                :   ScreenBox.x1 = 0;
12374                :   ScreenBox.y1 = 0;
12375                :   ScreenBox.x2 = pScrn->displayWidth;
12376                :   if (pScrn->virtualX > pScrn->virtualY)
12377                :      ScreenBox.y2 = pScrn->virtualX;
12378                :   else
12379                :      ScreenBox.y2 = pScrn->virtualY;
12380                :
12381                :   if((FullBox->x1 >  ScreenBox.x1) || (FullBox->y1 >  ScreenBox.y1) ||
12382                :      (FullBox->x2 <  ScreenBox.x2) || (FullBox->y2 <  ScreenBox.y2)) {
12383                :        return FALSE;   
12384                :   }
12385                :
12386                :   if (FullBox->y2 < FullBox->y1) return FALSE;
12387                :   if (FullBox->x2 < FullBox->x2) return FALSE;
12388                :
12389                :   REGION_INIT(pScreen, &ScreenRegion, &ScreenBox, 1); 
12390                :   REGION_INIT(pScreen, &FullRegion, FullBox, 1); 
12391                :
12392                :   REGION_SUBTRACT(pScreen, &FullRegion, &FullRegion, &ScreenRegion);
12393                :
12394                :   ret = xf86InitFBManagerRegion(pScreen, &FullRegion);
12395                :
12396                :   REGION_UNINIT(pScreen, &ScreenRegion);
12397                :   REGION_UNINIT(pScreen, &FullRegion);
12398                :    
12399                :   return ret;
12400                :}
12401                :
12402                :/**
12403                : * Intialiazes the hardware for the 3D pipeline use in the 2D driver.
12404                : *
12405                : * Some state caching is performed to avoid redundant state emits.  This
12406                : * function is also responsible for marking the state as clobbered for DRI
12407                : * clients.
12408                : */
12409                :void
12410                :IntelEmitInvarientState(ScrnInfoPtr pScrn)
12411      3  0.0033 :{ /* IntelEmitInvarientState total:     36  0.0392 */
12412      3  0.0033 :   I830Ptr pI830 = I830PTR(pScrn);
12413                :   CARD32 ctx_addr;
12414                :
12415      2  0.0022 :   if (pI830->noAccel)
12416                :      return;
12417                :
12418                :#ifdef XF86DRI
12419      4  0.0044 :   if (pI830->directRenderingEnabled) {
12420      4  0.0044 :      drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn->pScreen);
12421                :
12422                :      /* Mark that the X Server was the last holder of the context */
12423      5  0.0054 :      if (sarea)
12424      3  0.0033 :         sarea->ctxOwner = DRIGetContext(pScrn->pScreen);
12425                :   }
12426                :#endif
12427                :
12428                :   /* If we've emitted our state since the last clobber by another client,
12429                :    * skip it.
12430                :    */
12431      8  0.0087 :   if (*pI830->last_3d != LAST_3D_OTHER)
12432                :      return;
12433                :
12434                :   ctx_addr = pI830->logical_context->offset;
12435                :   assert((pI830->logical_context->offset & 2047) == 0);
12436                :   {
12437                :      BEGIN_LP_RING(2);
12438                :      OUT_RING(MI_SET_CONTEXT);
12439                :      OUT_RING(pI830->logical_context->offset |
12440                :               CTXT_NO_RESTORE |
12441                :               CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);
12442                :      ADVANCE_LP_RING();
12443                :   }
12444                :
12445                :   if (!IS_I965G(pI830))
12446                :   {
12447                :      if (IS_I9XX(pI830))
12448                :         I915EmitInvarientState(pScrn);
12449                :      else
12450                :         I830EmitInvarientState(pScrn);
12451                :   }
12452      4  0.0044 :}
12453                :
12454                :#ifdef XF86DRI_MM
12455                :#ifndef XSERVER_LIBDRM_MM
12456                :
12457                :static int
12458                :I830DrmMMInit(int drmFD, unsigned long pageOffs, unsigned long pageSize,
12459                :              unsigned memType)
12460                :{
12461                :
12462                :   drm_mm_init_arg_t arg;
12463                :   int ret;
12464                :   
12465                :   memset(&arg, 0, sizeof(arg));
12466                :   arg.req.op = mm_init;
12467                :   arg.req.p_offset = pageOffs;
12468                :   arg.req.p_size = pageSize;
12469                :   arg.req.mem_type = memType;
12470                :
12471                :   ret = ioctl(drmFD, DRM_IOCTL_MM_INIT, &arg);
12472                :   
12473                :   if (ret)
12474                :      return -errno;
12475                :   
12476                :   return 0;
12477                :   
12478                :}
12479                :
12480                :static int
12481                :I830DrmMMTakedown(int drmFD, unsigned memType)
12482                :{
12483                :   drm_mm_init_arg_t arg;
12484                :   int ret = 0;
12485                :   
12486                :   memset(&arg, 0, sizeof(arg));
12487                :   arg.req.op = mm_takedown;
12488                :   arg.req.mem_type = memType;
12489                :   if (ioctl(drmFD, DRM_IOCTL_MM_INIT, &arg)) {
12490                :      ret = -errno;
12491                :   }
12492                :   
12493                :   return ret;
12494                :}
12495                :
12496                :static int I830DrmMMLock(int fd, unsigned memType)
12497                :{
12498                :    drm_mm_init_arg_t arg;
12499                :    int ret;
12500                :
12501                :    memset(&arg, 0, sizeof(arg));
12502                :    arg.req.op = mm_lock;
12503                :    arg.req.mem_type = memType;
12504                :
12505                :    do{
12506                :        ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
12507                :    } while (ret && errno == EAGAIN);
12508                :    
12509                :    return ret; 
12510                :}
12511                :
12512                :static int I830DrmMMUnlock(int fd, unsigned memType)
12513                :{
12514                :    drm_mm_init_arg_t arg;
12515                :    int ret;
12516                :
12517                :    memset(&arg, 0, sizeof(arg));
12518                :    arg.req.op = mm_unlock;
12519                :    arg.req.mem_type = memType;
12520                :
12521                :    do{
12522                :        ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
12523                :    } while (ret && errno == EAGAIN);
12524                :    
12525                :    return ret; 
12526                :}
12527                :
12528                :#endif
12529                :#endif /* XF86DRI_MM */
12530                :
12531                :static Bool
12532                :I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
12533                :{
12534                :   ScrnInfoPtr pScrn;
12535                :   vgaHWPtr hwp;
12536                :   I830Ptr pI830;
12537                :   VisualPtr visual;
12538                :   I830Ptr pI8301 = NULL;
12539                :   unsigned long sys_mem;
12540                :   int i;
12541                :   Bool allocation_done = FALSE;
12542                :   MessageType from;
12543                :#ifdef XF86DRI
12544                :   Bool driDisabled;
12545                :#ifdef XF86DRI_MM
12546                :   unsigned long savedMMSize;
12547                :#endif
12548                :#endif
12549                :
12550                :   pScrn = xf86Screens[pScreen->myNum];
12551                :   pI830 = I830PTR(pScrn);
12552                :   hwp = VGAHWPTR(pScrn);
12553                :
12554                :   pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
12555                :
12556                :   /*
12557                :    * The "VideoRam" config file parameter specifies the maximum amount of
12558                :    * memory that will be used/allocated.  When not present, we allow the
12559                :    * driver to allocate as much memory as it wishes to satisfy its
12560                :    * allocations, but if agpgart support isn't available, it gets limited
12561                :    * to the amount of pre-allocated ("stolen") memory.
12562                :    *
12563                :    * Note that in using this value for allocator initialization, we're
12564                :    * limiting aperture allocation to the VideoRam option, rather than limiting
12565                :    * actual memory allocation, so alignment and things will cause less than
12566                :    * VideoRam to be actually used.
12567                :    */
12568                :   if (pI830->pEnt->device->videoRam == 0) {
12569                :      from = X_DEFAULT;
12570                :      pScrn->videoRam = pI830->FbMapSize / KB(1);
12571                :   } else {
12572                :#if 0
12573                :      from = X_CONFIG;
12574                :      pScrn->videoRam = pI830->pEnt->device->videoRam;
12575                :#else
12576                :      /* Disable VideoRam configuration, at least for now.  Previously,
12577                :       * VideoRam was necessary to avoid overly low limits on allocated
12578                :       * memory, so users created larger, yet still small, fixed allocation
12579                :       * limits in their config files.  Now, the driver wants to allocate more,
12580                :       * and the old intention of the VideoRam lines that had been entered is
12581                :       * obsolete.
12582                :       */
12583                :      from = X_DEFAULT;
12584                :      pScrn->videoRam = pI830->FbMapSize / KB(1);
12585                :
12586                :      if (pScrn->videoRam != pI830->pEnt->device->videoRam) {
12587                :         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12588                :                    "VideoRam configuration found, which is no longer "
12589                :                    "recommended.\n");
12590                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
12591                :                    "Continuing with default %dkB VideoRam instead of %d "
12592                :                    "kB.\n",
12593                :                    pScrn->videoRam, pI830->pEnt->device->videoRam);
12594                :      }
12595                :#endif
12596                :   }
12597                :
12598                :   /* Limit videoRam to how much we might be able to allocate from AGP */
12599                :   sys_mem = I830CheckAvailableMemory(pScrn);
12600                :   if (sys_mem == -1) {
12601                :      if (pScrn->videoRam > pI830->stolen_size / KB(1)) {
12602                :         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12603                :                    "/dev/agpgart is either not available, or no memory "
12604                :                    "is available\nfor allocation.  "
12605                :                    "Using pre-allocated memory only.\n");
12606                :         pScrn->videoRam = pI830->stolen_size / KB(1);
12607                :      }
12608                :      pI830->StolenOnly = TRUE;
12609                :   } else {
12610                :      if (sys_mem + (pI830->stolen_size / 1024) < pScrn->videoRam) {
12611                :         pScrn->videoRam = sys_mem + (pI830->stolen_size / 1024);
12612                :         from = X_PROBED;
12613                :         if (sys_mem + (pI830->stolen_size / 1024) <
12614                :             pI830->pEnt->device->videoRam)
12615                :         {
12616                :            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12617                :                       "VideoRAM reduced to %d kByte "
12618                :                       "(limited to available sysmem)\n", pScrn->videoRam);
12619                :         }
12620                :      }
12621                :   }
12622                :
12623                :   /* Limit video RAM to the actual aperture size */
12624                :   if (pScrn->videoRam > pI830->FbMapSize / 1024) {
12625                :      pScrn->videoRam = pI830->FbMapSize / 1024;
12626                :      if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) {
12627                :         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12628                :                    "VideoRam reduced to %d kByte (limited to aperture "
12629                :                    "size)\n",
12630                :                    pScrn->videoRam);
12631                :      }
12632                :   }
12633                :
12634                :   /* Make sure it's on a page boundary */
12635                :   if (pScrn->videoRam & 3) {
12636                :      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB "
12637                :                 "(page aligned - was %d KB)\n",
12638                :                 pScrn->videoRam & ~3, pScrn->videoRam);
12639                :      pScrn->videoRam &= ~3;
12640                :   }
12641                :
12642                :   /* Set up our video memory allocator for the chosen videoRam */
12643                :   if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) {
12644                :      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
12645                :                 "Couldn't initialize video memory allocator\n");
12646                :      PreInitCleanup(pScrn);
12647                :      return FALSE;
12648                :   }
12649                :
12650                :   xf86DrvMsg(pScrn->scrnIndex,
12651                :              pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
12652                :              "VideoRam: %d KB\n", pScrn->videoRam);
12653                :
12654                :   if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES,
12655                :                            &(pI830->CacheLines))) {
12656                :      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n",
12657                :                 pI830->CacheLines);
12658                :   } else {
12659                :      pI830->CacheLines = -1;
12660                :   }
12661                :
12662                :   pI830->disableTiling = FALSE;
12663                :
12664                :   if (I830IsPrimary(pScrn)) {
12665                :      /* Alloc our pointers for the primary head */
12666                :      if (!pI830->LpRing)
12667                :         pI830->LpRing = xcalloc(1, sizeof(I830RingBuffer));
12668                :      if (!pI830->overlayOn)
12669                :         pI830->overlayOn = xalloc(sizeof(Bool));
12670                :      if (!pI830->last_3d)
12671                :         pI830->last_3d = xalloc(sizeof(enum last_3d));
12672                :      if (!pI830->LpRing || !pI830->overlayOn || !pI830->last_3d) {
12673                :         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
12674                :                 "Could not allocate primary data structures.\n");
12675                :         return FALSE;
12676                :      }
12677                :      *pI830->last_3d = LAST_3D_OTHER;
12678                :      *pI830->overlayOn = FALSE;
12679                :      if (pI830->entityPrivate)
12680                :         pI830->entityPrivate->XvInUse = -1;
12681                :   } else {
12682                :      /* Make our second head point to the first heads structures */
12683                :      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
12684                :      pI830->LpRing = pI8301->LpRing;
12685                :      pI830->overlay_regs = pI8301->overlay_regs;
12686                :      pI830->overlayOn = pI8301->overlayOn;
12687                :      pI830->last_3d = pI8301->last_3d;
12688                :   }
12689                :
12690                :   /* Need MMIO mapped to do GTT lookups during memory allocation. */
12691                :   I830MapMMIO(pScrn);
12692                :
12693                :#if defined(XF86DRI)
12694                :   /*
12695                :    * If DRI is potentially usable, check if there is enough memory available
12696                :    * for it, and if there's also enough to allow tiling to be enabled.
12697                :    */
12698                :
12699                :   if (!I830CheckDRIAvailable(pScrn)) {
12700                :      pI830->directRenderingDisabled = TRUE;
12701                :#ifdef XF86DRI_MM
12702                :      pI830->mmSize = 0;
12703                :#endif
12704                :   }
12705                :
12706                :#ifdef I830_XV
12707                :    /*
12708                :     * Set this so that the overlay allocation is factored in when
12709                :     * appropriate.
12710                :     */
12711                :    pI830->XvEnabled = !pI830->XvDisabled;
12712                :#endif
12713                :
12714                :   if (!pI830->directRenderingDisabled) {
12715                :      int savedDisplayWidth = pScrn->displayWidth;
12716                :      Bool tiled = FALSE;
12717                :
12718                :      if (IS_I965G(pI830)) {
12719                :         int tile_pixels = 512 / pI830->cpp;
12720                :         pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) &
12721                :            ~(tile_pixels - 1);
12722                :         tiled = TRUE;
12723                :      } else {
12724                :         /* Good pitches to allow tiling.  Don't care about pitches < 1024
12725                :          * pixels.
12726                :          */
12727                :         static const int pitches[] = {
12728                :            1024,
12729                :            2048,
12730                :            4096,
12731                :            8192,
12732                :            0
12733                :         };
12734                :
12735                :         for (i = 0; pitches[i] != 0; i++) {
12736                :            if (pitches[i] >= pScrn->displayWidth) {
12737                :               pScrn->displayWidth = pitches[i];
12738                :               tiled = TRUE;
12739                :               break;
12740                :            }
12741                :         }
12742                :      }
12743                :
12744                :      /* Attempt several rounds of allocation to get 2d and 3d memory to fit:
12745                :       *
12746                :       * 0: tiled, large memory manager
12747                :       * 1: tiled, small memory manager
12748                :       * 2: untiled, large
12749                :       * 3: untiled, small
12750                :       */
12751                :
12752                :      pI830->disableTiling = FALSE;
12753                :#ifdef XF86DRI_MM
12754                :      savedMMSize = pI830->mmSize;
12755                :#define MM_TURNS 4
12756                :#else
12757                :#define MM_TURNS 2
12758                :#endif
12759                :      for (i = 0; i < MM_TURNS; i++) {
12760                :         if (!tiled && i < 2)
12761                :            continue;
12762                :
12763                :         if (i >= MM_TURNS/2) {
12764                :            /* For further allocations, disable tiling */
12765                :            pI830->disableTiling = TRUE;
12766                :            pScrn->displayWidth = savedDisplayWidth;
12767                :            if (pI830->allowPageFlip)
12768                :               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12769                :                          "Couldn't allocate tiled memory, page flipping "
12770                :                          "disabled\n");
12771                :            pI830->allowPageFlip = FALSE;
12772                :         }
12773                :
12774                :#ifdef XF86DRI_MM
12775                :         if (i & 1) {
12776                :            /* For this allocation, switch to a smaller DRI memory manager
12777                :             * size.
12778                :             */
12779                :            pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE / KB(1);
12780                :         } else {
12781                :            pI830->mmSize = savedMMSize;
12782                :         }
12783                :
12784                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
12785                :                    "Attempting memory allocation with %s buffers and \n"
12786                :                    "\t       %s DRI memory manager reservation:\n",
12787                :                    (i & 2) ? "untiled" : "tiled",
12788                :                    (i & 1) ? "small" : "large");
12789                :#else
12790                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
12791                :                    "Attempting memory allocation with %s buffers:\n",
12792                :                    (i & 1) ? "untiled" : "tiled");
12793                :#endif
12794                :
12795                :         if (i830_allocate_2d_memory(pScrn) &&
12796                :             i830_allocate_3d_memory(pScrn))
12797                :         {
12798                :            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Success.\n");
12799                :            if (pScrn->displayWidth != savedDisplayWidth) {
12800                :               xf86DrvMsg(pScrn->scrnIndex, X_INFO,
12801                :                          "Increasing the scanline pitch to allow tiling mode "
12802                :                          "(%d -> %d).\n",
12803                :                          savedDisplayWidth, pScrn->displayWidth);
12804                :            }
12805                :            allocation_done = TRUE;
12806                :            break;
12807                :         }
12808                :
12809                :         i830_reset_allocations(pScrn);
12810                :      }
12811                :
12812                :      if (i == MM_TURNS) {
12813                :         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12814                :                    "Not enough video memory.  Disabling DRI.\n");
12815                :#ifdef XF86DRI_MM
12816                :         pI830->mmSize = 0;
12817                :#endif
12818                :         pI830->directRenderingDisabled = TRUE;
12819                :      }
12820                :   } else
12821                :#endif
12822                :      pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
12823                :
12824                :   if (!allocation_done) {
12825                :      if (!i830_allocate_2d_memory(pScrn)) {
12826                :         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
12827                :                    "Couldn't allocate video memory\n");
12828                :         return FALSE;
12829                :      }
12830                :      allocation_done = TRUE;
12831                :   }
12832                :
12833                :   I830UnmapMMIO(pScrn);
12834                :
12835                :   i830_describe_allocations(pScrn, 1, "");
12836                :
12837                :   if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
12838                :      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
12839                :                 "Cannot support DRI with frame buffer width > 2048.\n");
12840                :      pI830->disableTiling = TRUE;
12841                :      pI830->directRenderingDisabled = TRUE;
12842                :   }
12843                :
12844                :   pScrn->displayWidth = pScrn->displayWidth;
12845                :
12846                :#ifdef HAS_MTRR_SUPPORT
12847                :   {
12848                :      int fd;
12849                :      struct mtrr_gentry gentry;
12850                :      struct mtrr_sentry sentry;
12851                :
12852                :      if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) != -1 ) {
12853                :         for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0;
12854                :              ++gentry.regnum) {
12855                :
12856                :            if (gentry.size < 1) {
12857                :               /* DISABLED */
12858                :               continue;
12859                :            }
12860                :
12861                :            /* Check the MTRR range is one we like and if not - remove it.
12862                :             * The Xserver common layer will then setup the right range
12863                :             * for us.
12864                :             */
12865                :            if (gentry.base == pI830->LinearAddr && 
12866                :                gentry.size < pI830->FbMapSize) {
12867                :
12868                :               xf86DrvMsg(pScrn->scrnIndex, X_INFO,
12869                :                  "Removing bad MTRR range (base 0x%lx, size 0x%x)\n",
12870                :                  gentry.base, gentry.size);
12871                :
12872                :               sentry.base = gentry.base;
12873                :               sentry.size = gentry.size;
12874                :               sentry.type = gentry.type;
12875                :
12876                :               if (ioctl (fd, MTRRIOC_DEL_ENTRY, &sentry) == -1) {
12877                :                  xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
12878                :                     "Failed to remove bad MTRR range\n");
12879                :               }
12880                :            }
12881                :         }
12882                :         close(fd);
12883                :      }
12884                :   }
12885                :#endif
12886                :
12887                :   pI830->starting = TRUE;
12888                :
12889                :   miClearVisualTypes();
12890                :   if (!miSetVisualTypes(pScrn->depth,
12891                :                            miGetDefaultVisualMask(pScrn->depth),
12892                :                            pScrn->rgbBits, pScrn->defaultVisual))
12893                :         return FALSE;
12894                :   if (!miSetPixmapDepths())
12895                :      return FALSE;
12896                :
12897                :#ifdef I830_XV
12898                :   pI830->XvEnabled = !pI830->XvDisabled;
12899                :   if (pI830->XvEnabled) {
12900                :      if (!I830IsPrimary(pScrn)) {
12901                :         if (!pI8301->XvEnabled || pI830->noAccel) {
12902                :            pI830->XvEnabled = FALSE;
12903                :            xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n");
12904                :         }
12905                :      } else
12906                :      if (pI830->noAccel || pI830->StolenOnly) {
12907                :         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled because it "
12908                :                    "needs 2D accel and AGPGART.\n");
12909                :         pI830->XvEnabled = FALSE;
12910                :      }
12911                :   }
12912                :#else
12913                :   pI830->XvEnabled = FALSE;
12914                :#endif
12915                :
12916                :   if (!pI830->noAccel) {
12917                :      if (pI830->LpRing->mem->size == 0) {
12918                :          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12919                :                     "Disabling acceleration because the ring buffer "
12920                :                      "allocation failed.\n");
12921                :           pI830->noAccel = TRUE;
12922                :      }
12923                :   }
12924                :
12925                :#ifdef I830_XV
12926                :   if (pI830->XvEnabled) {
12927                :      if (pI830->noAccel) {
12928                :         xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because it "
12929                :                    "needs 2D acceleration.\n");
12930                :         pI830->XvEnabled = FALSE;
12931                :      }
12932                :      if (!IS_I9XX(pI830) && pI830->overlay_regs == NULL) {
12933                :          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12934                :                     "Disabling Xv because the overlay register buffer "
12935                :                      "allocation failed.\n");
12936                :         pI830->XvEnabled = FALSE;
12937                :      }
12938                :   }
12939                :#endif
12940                :
12941                :#ifdef XF86DRI
12942                :   /*
12943                :    * pI830->directRenderingDisabled is set once in PreInit.  Reinitialise
12944                :    * pI830->directRenderingEnabled based on it each generation.
12945                :    */
12946                :   pI830->directRenderingEnabled = !pI830->directRenderingDisabled;
12947                :   /*
12948                :    * Setup DRI after visuals have been established, but before fbScreenInit
12949                :    * is called.   fbScreenInit will eventually call into the drivers
12950                :    * InitGLXVisuals call back.
12951                :    */
12952                :
12953                :   if (pI830->directRenderingEnabled) {
12954                :      if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) {
12955                :         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
12956                :                    "needs HW cursor, 2D accel and AGPGART.\n");
12957                :         pI830->directRenderingEnabled = FALSE;
12958                :         i830_free_3d_memory(pScrn);
12959                :      }
12960                :   }
12961                :
12962                :   driDisabled = !pI830->directRenderingEnabled;
12963                :
12964                :   if (pI830->directRenderingEnabled)
12965                :      pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
12966                :
12967                :   if (!pI830->directRenderingEnabled) {
12968                :      i830_free_3d_memory(pScrn);
12969                :   }
12970                :
12971                :#else
12972                :   pI830->directRenderingEnabled = FALSE;
12973                :#endif
12974                :
12975                :#ifdef XF86DRI
12976                :   if (pI830->directRenderingEnabled)
12977                :      pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
12978                :
12979                :   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n",
12980                :              pI830->allowPageFlip ? "en" : "dis");
12981                :#endif
12982                :
12983                :   DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n");
12984                :   if (!I830MapMem(pScrn))
12985                :      return FALSE;
12986                :
12987                :   pScrn->memPhysBase = (unsigned long)pI830->FbBase;
12988                :
12989                :   if (I830IsPrimary(pScrn)) {
12990                :      pScrn->fbOffset = pI830->front_buffer->offset;
12991                :   } else {
12992                :      pScrn->fbOffset = pI8301->front_buffer_2->offset;
12993                :   }
12994                :
12995                :   pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth;
12996                :   pI830->yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth;
12997                :
12998                :   vgaHWSetMmioFuncs(hwp, pI830->MMIOBase, 0);
12999                :   vgaHWGetIOBase(hwp);
13000                :   DPRINTF(PFX, "assert( if(!vgaHWMapMem(pScrn)) )\n");
13001                :   if (!vgaHWMapMem(pScrn))
13002                :      return FALSE;
13003                :
13004                :   DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
13005                :
13006                :   if (!pI830->useEXA) {
13007                :      if (I830IsPrimary(pScrn)) {
13008                :         if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
13009                :            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
13010                :                       "Failed to init memory manager\n");
13011                :         }
13012                :      } else {
13013                :         if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
13014                :            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
13015                :                       "Failed to init memory manager\n");
13016                :         }
13017                :      }
13018                :   }
13019                :
13020                :    if (pScrn->virtualX > pScrn->displayWidth)
13021                :        pScrn->displayWidth = pScrn->virtualX;
13022                :
13023                :   DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
13024                :   if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, 
13025                :                     pScrn->virtualX, pScrn->virtualY,
13026                :                     pScrn->xDpi, pScrn->yDpi,
13027                :                     pScrn->displayWidth, pScrn->bitsPerPixel))
13028                :      return FALSE;
13029                :
13030                :   if (pScrn->bitsPerPixel > 8) {
13031                :      /* Fixup RGB ordering */
13032                :      visual = pScreen->visuals + pScreen->numVisuals;
13033                :      while (--visual >= pScreen->visuals) {
13034                :         if ((visual->class | DynamicClass) == DirectColor) {
13035                :            visual->offsetRed = pScrn->offset.red;
13036                :            visual->offsetGreen = pScrn->offset.green;
13037                :            visual->offsetBlue = pScrn->offset.blue;
13038                :            visual->redMask = pScrn->mask.red;
13039                :            visual->greenMask = pScrn->mask.green;
13040                :            visual->blueMask = pScrn->mask.blue;
13041                :         }
13042                :      }
13043                :   }
13044                :
13045                :   fbPictureInit(pScreen, NULL, 0);
13046                :
13047                :   xf86SetBlackWhitePixels(pScreen);
13048                :
13049                :   xf86DiDGAInit (pScreen, pI830->LinearAddr + pScrn->fbOffset);
13050                :
13051                :   DPRINTF(PFX,
13052                :           "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
13053                :
13054                :   if (!pI830->noAccel) {
13055                :      if (!I830AccelInit(pScreen)) {
13056                :         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
13057                :                    "Hardware acceleration initialization failed\n");
13058                :      }
13059                :   }
13060                :
13061                :   miInitializeBackingStore(pScreen);
13062                :   xf86SetBackingStore(pScreen);
13063                :   xf86SetSilkenMouse(pScreen);
13064                :   miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
13065                :
13066                :   if (!pI830->SWCursor) {
13067                :      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
13068                :      if (!I830CursorInit(pScreen))
13069                :         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
13070                :                    "Hardware cursor initialization failed\n");
13071                :   } else
13072                :      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n");
13073                :
13074                :   if (!I830EnterVT(scrnIndex, 0))
13075                :      return FALSE;
13076                :
13077                :   DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n");
13078                :   if (!miCreateDefColormap(pScreen))
13079                :      return FALSE;
13080                :
13081                :   DPRINTF(PFX, "assert( if(!xf86HandleColormaps(pScreen, ...)) )\n");
13082                :   if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, NULL,
13083                :                            CMAP_RELOAD_ON_MODE_SWITCH |
13084                :                            CMAP_PALETTED_TRUECOLOR)) {
13085                :      return FALSE;
13086                :   }
13087                :
13088                :   xf86DPMSInit(pScreen, xf86DPMSSet, 0);
13089                :
13090                :#ifdef I830_XV
13091                :   /* Init video */
13092                :   if (pI830->XvEnabled)
13093                :      I830InitVideo(pScreen);
13094                :#endif
13095                :
13096                :#ifdef XF86DRI
13097                :   if (pI830->directRenderingEnabled) {
13098                :      pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
13099                :   }
13100                :#endif
13101                :
13102                :   /* Setup 3D engine, needed for rotation too */
13103                :   IntelEmitInvarientState(pScrn);
13104                :
13105                :#ifdef XF86DRI
13106                :   if (pI830->directRenderingEnabled) {
13107                :      pI830->directRenderingOpen = TRUE;
13108                :      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Enabled\n");
13109                :   } else {
13110                :      if (driDisabled)
13111                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n");
13112                :      else
13113                :         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Failed\n");
13114                :   }
13115                :#else
13116                :   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Not available\n");
13117                :#endif
13118                :
13119                :   pScreen->SaveScreen = xf86SaveScreen;
13120                :   pI830->CloseScreen = pScreen->CloseScreen;
13121                :   pScreen->CloseScreen = I830CloseScreen;
13122                :
13123                :   if (!xf86CrtcScreenInit (pScreen))
13124                :       return FALSE;
13125                :       
13126                :   /* Wrap pointer motion to flip touch screen around */
13127                :   pI830->PointerMoved = pScrn->PointerMoved;
13128                :   pScrn->PointerMoved = I830PointerMoved;
13129                :
13130                :   if (serverGeneration == 1)
13131                :      xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
13132                :
13133                :   if (IS_I965G(pI830)) {
13134                :      /* turn off clock gating */
13135                :#if 0
13136                :      OUTREG(0x6204, 0x70804000);
13137                :      OUTREG(0x6208, 0x00000001);
13138                :#else
13139                :      OUTREG(0x6204, 0x70000000);
13140                :#endif
13141                :      /* Enable DAP stateless accesses.  
13142                :       * Required for all i965 steppings.
13143                :       */
13144                :      OUTREG(SVG_WORK_CTL, 0x00000010);
13145                :   }
13146                :
13147                :   pI830->starting = FALSE;
13148                :   pI830->closing = FALSE;
13149                :   pI830->suspended = FALSE;
13150                :
13151                :#ifdef XF86DRI_MM
13152                :   if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM))
13153                :   {
13154                :      if (pI830->memory_manager == NULL) {
13155                :         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
13156                :                    "Too little AGP aperture space for DRM memory manager.\n"
13157                :                    "\tPlease increase AGP aperture size from BIOS configuration screen.\n"
13158                :                    "\tDisabling DRI.\n");
13159                :         pI830->directRenderingOpen = FALSE;
13160                :         I830DRICloseScreen(pScreen);
13161                :         pI830->directRenderingEnabled = FALSE;
13162                :      } else {
13163                :         unsigned long aperEnd = ROUND_DOWN_TO(pI830->memory_manager->offset +
13164                :                                               pI830->memory_manager->size,
13165                :                                               GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
13166                :         unsigned long aperStart = ROUND_TO(pI830->memory_manager->offset,
13167                :                                            GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
13168                :
13169                :#ifndef XSERVER_LIBDRM_MM
13170                :         if (I830DrmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
13171                :                           DRM_BO_MEM_TT)) {
13172                :#else
13173                :         if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
13174                :                       DRM_BO_MEM_TT)) {
13175                :#endif     
13176                :            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
13177                :                       "Could not initialize the DRM memory manager.\n");
13178                :            
13179                :            pI830->directRenderingOpen = FALSE;
13180                :            I830DRICloseScreen(pScreen);
13181                :            pI830->directRenderingEnabled = FALSE;
13182                :         }
13183                :      }
13184                :   }
13185                :#endif /* XF86DRI_MM */
13186                :
13187                :   return TRUE;
13188                :}
13189                :
13190                :static void
13191                :i830AdjustFrame(int scrnIndex, int x, int y, int flags)
13192                :{
13193                :   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
13194                :   xf86CrtcConfigPtr    config = XF86_CRTC_CONFIG_PTR(pScrn);
13195                :   I830Ptr pI830 = I830PTR(pScrn);
13196                :   xf86OutputPtr  output = config->output[config->compat_output];
13197                :   xf86CrtcPtr  crtc = output->crtc;
13198                :
13199                :   DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
13200                :           x, pI830->xoffset, y, pI830->yoffset);
13201                :
13202                :   if (crtc && crtc->enabled)
13203                :   {
13204                :      /* Sync the engine before adjust frame */
13205                :      i830WaitSync(pScrn);
13206                :      i830PipeSetBase(crtc, crtc->desiredX + x, crtc->desiredY + y);
13207                :      crtc->x = output->initial_x + x;
13208                :      crtc->y = output->initial_y + y;
13209                :   }
13210                :}
13211                :
13212                :static void
13213                :I830FreeScreen(int scrnIndex, int flags)
13214                :{
13215                :   I830FreeRec(xf86Screens[scrnIndex]);
13216                :   if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
13217                :      vgaHWFreeHWRec(xf86Screens[scrnIndex]);
13218                :}
13219                :
13220                :static void
13221                :I830LeaveVT(int scrnIndex, int flags)
13222                :{
13223                :   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
13224                :   I830Ptr pI830 = I830PTR(pScrn);
13225                :
13226                :   DPRINTF(PFX, "Leave VT\n");
13227                :
13228                :   pI830->leaving = TRUE;
13229                :
13230                :   if (pI830->devicesTimer)
13231                :      TimerCancel(pI830->devicesTimer);
13232                :   pI830->devicesTimer = NULL;
13233                :
13234                :   i830SetHotkeyControl(pScrn, HOTKEY_BIOS_SWITCH);
13235                :
13236                :   if (!I830IsPrimary(pScrn)) {
13237                :        I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
13238                :        if (!pI8301->gtt_acquired) {
13239                :                return;
13240                :        }
13241                :   }
13242                :
13243                :#ifdef XF86DRI
13244                :   if (pI830->directRenderingOpen) {
13245                :      DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
13246                :#ifdef XF86DRI_MM
13247                :      if (pI830->mmModeFlags & I830_KERNEL_MM) {
13248                :#ifndef XSERVER_LIBDRM_MM
13249                :         I830DrmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
13250                :#else
13251                :         drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
13252                :#endif
13253                :      }
13254                :#endif /* XF86DRI_MM */
13255                :      I830DRISetVBlankInterrupt (pScrn, FALSE);
13256                :      
13257                :      drmCtlUninstHandler(pI830->drmSubFD);
13258                :   }
13259                :#endif
13260                :
13261                :   xf86_hide_cursors (pScrn);
13262                :
13263                :   ResetState(pScrn, TRUE);
13264                :
13265                :   RestoreHWState(pScrn);
13266                :
13267                :   if (pI830->debug_modes) {
13268                :      i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
13269                :      i830DumpRegs (pScrn);
13270                :   }
13271                :
13272                :   if (I830IsPrimary(pScrn))
13273                :      i830_unbind_all_memory(pScrn);
13274                :   if (pI830->AccelInfoRec)
13275                :      pI830->AccelInfoRec->NeedToSync = FALSE;
13276                :}
13277                :
13278                :/*
13279                : * This gets called when gaining control of the VT, and from ScreenInit().
13280                : */
13281                :static Bool
13282                :I830EnterVT(int scrnIndex, int flags)
13283                :{
13284                :   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
13285                :   I830Ptr  pI830 = I830PTR(pScrn);
13286                :   xf86CrtcConfigPtr    config = XF86_CRTC_CONFIG_PTR(pScrn);
13287                :   int o;
13288                :
13289                :   DPRINTF(PFX, "Enter VT\n");
13290                :
13291                :   /*
13292                :    * Only save state once per server generation since that's what most
13293                :    * drivers do.  Could change this to save state at each VT enter.
13294                :    */
13295                :   if (pI830->SaveGeneration != serverGeneration) {
13296                :      pI830->SaveGeneration = serverGeneration;
13297                :      SaveHWState(pScrn);
13298                :   }
13299                :
13300                :   pI830->leaving = FALSE;
13301                :
13302                :   if (I830IsPrimary(pScrn))
13303                :      if (!i830_bind_all_memory(pScrn))
13304                :         return FALSE;
13305                :
13306                :   if (i830_check_error_state(pScrn)) {
13307                :      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
13308                :                 "Existing errors found in hardware state.\n");
13309                :   }
13310                :
13311                :   ResetState(pScrn, FALSE);
13312                :   SetHWOperatingState(pScrn);
13313                :
13314                :   /* Clear the framebuffer */
13315                :   memset(pI830->FbBase + pScrn->fbOffset, 0,
13316                :          pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
13317                :
13318                :   for (o = 0; o < config->num_output; o++) {
13319                :        xf86OutputPtr  output = config->output[o];
13320                :        output->funcs->dpms(output, DPMSModeOff);
13321                :   }
13322                :
13323                :   if (!xf86SetDesiredModes (pScrn))
13324                :      return FALSE;
13325                :   
13326                :   if (pI830->debug_modes) {
13327                :      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state at EnterVT:\n");
13328                :      i830DumpRegs (pScrn);
13329                :   }
13330                :   i830DescribeOutputConfiguration(pScrn);
13331                :
13332                :   ResetState(pScrn, TRUE);
13333                :   SetHWOperatingState(pScrn);
13334                :
13335                :#ifdef XF86DRI
13336                :   if (pI830->directRenderingEnabled) {
13337                :
13338                :      I830DRISetVBlankInterrupt (pScrn, TRUE);
13339                :
13340                :      if (!pI830->starting) {
13341                :         ScreenPtr pScreen = pScrn->pScreen;
13342                :         drmI830Sarea *sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
13343                :         int i;
13344                :
13345                :         I830DRIResume(screenInfo.screens[scrnIndex]);
13346                :      
13347                :         I830RefreshRing(pScrn);
13348                :         I830Sync(pScrn);
13349                :         DO_RING_IDLE();
13350                :
13351                :         sarea->texAge++;
13352                :         for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++)
13353                :            sarea->texList[i].age = sarea->texAge;
13354                :
13355                :#ifdef XF86DRI_MM
13356                :         if (pI830->mmModeFlags & I830_KERNEL_MM) {
13357                :#ifndef XSERVER_LIBDRM_MM
13358                :            I830DrmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
13359                :#else
13360                :            drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
13361                :#endif
13362                :         }
13363                :#endif /* XF86DRI_MM */
13364                :
13365                :         DPRINTF(PFX, "calling dri unlock\n");
13366                :         DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
13367                :      }
13368                :      pI830->LockHeld = 0;
13369                :   }
13370                :#endif
13371                :
13372                :   /* Set the hotkey to just notify us.  We can check its results periodically
13373                :    * in the CheckDevicesTimer.  Eventually we want the kernel to just hand us
13374                :    * an input event when someone presses the button, but for now we just have
13375                :    * to poll.
13376                :    */
13377                :   i830SetHotkeyControl(pScrn, HOTKEY_DRIVER_NOTIFY);
13378                :
13379                :   if (pI830->checkDevices)
13380                :      pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
13381                :
13382                :   /* Mark 3D state as being clobbered */
13383                :   *pI830->last_3d = LAST_3D_OTHER;
13384                :
13385                :   return TRUE;
13386                :}
13387                :
13388                :static Bool
13389                :I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
13390                :{
13391                :   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
13392                :   I830Ptr pI830 = I830PTR(pScrn);
13393                :
13394                :   return xf86SetSingleMode (pScrn, mode, pI830->rotation);
13395                :}
13396                :
13397                :static Bool
13398                :I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
13399                :{
13400                :   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
13401                :   I830Ptr pI830 = I830PTR(pScrn);
13402                :#ifdef I830_USE_XAA
13403                :   XAAInfoRecPtr infoPtr = pI830->AccelInfoRec;
13404                :#endif
13405                :
13406                :   pI830->closing = TRUE;
13407                :#ifdef XF86DRI
13408                :   if (pI830->directRenderingOpen) {
13409                :#ifdef DAMAGE
13410                :      if (pI830->pDamage) {
13411                :         PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
13412                :
13413                :         DamageUnregister(&pPix->drawable, pI830->pDamage);
13414                :         DamageDestroy(pI830->pDamage);
13415                :         pI830->pDamage = NULL;
13416                :      }
13417                :#endif
13418                :#ifdef XF86DRI_MM
13419                :      if (pI830->mmModeFlags & I830_KERNEL_MM) {
13420                :#ifndef XSERVER_LIBDRM_MM
13421                :         I830DrmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);
13422                :#else
13423                :         drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);  
13424                :#endif
13425                :      }
13426                :#endif /* XF86DRI_MM */
13427                :      pI830->directRenderingOpen = FALSE;
13428                :      I830DRICloseScreen(pScreen);
13429                :   }
13430                :#endif
13431                :
13432                :   if (pScrn->vtSema == TRUE) {
13433                :      I830LeaveVT(scrnIndex, 0);
13434                :   }
13435                :
13436                :   if (pI830->devicesTimer)
13437                :      TimerCancel(pI830->devicesTimer);
13438                :   pI830->devicesTimer = NULL;
13439                :
13440                :   DPRINTF(PFX, "\nUnmapping memory\n");
13441                :   I830UnmapMem(pScrn);
13442                :   vgaHWUnmapMem(pScrn);
13443                :
13444                :   if (pI830->ScanlineColorExpandBuffers) {
13445                :      xfree(pI830->ScanlineColorExpandBuffers);
13446                :      pI830->ScanlineColorExpandBuffers = NULL;
13447                :   }
13448                :#ifdef I830_USE_XAA
13449                :   if (infoPtr) {
13450                :      if (infoPtr->ScanlineColorExpandBuffers)
13451                :         xfree(infoPtr->ScanlineColorExpandBuffers);
13452                :      XAADestroyInfoRec(infoPtr);
13453                :      pI830->AccelInfoRec = NULL;
13454                :   }
13455                :#endif
13456                :#ifdef I830_USE_EXA
13457                :   if (pI830->useEXA && pI830->EXADriverPtr) {
13458                :       exaDriverFini(pScreen);
13459                :       xfree(pI830->EXADriverPtr);
13460                :       pI830->EXADriverPtr = NULL;
13461                :   }
13462                :#endif
13463                :   xf86_cursors_fini (pScreen);
13464                :
13465                :   i830_reset_allocations(pScrn);
13466                :
13467                :   if (I830IsPrimary(pScrn)) {
13468                :      xf86GARTCloseScreen(scrnIndex);
13469                :
13470                :      xfree(pI830->LpRing);
13471                :      pI830->LpRing = NULL;
13472                :      xfree(pI830->overlayOn);
13473                :      pI830->overlayOn = NULL;
13474                :      xfree(pI830->last_3d);
13475                :      pI830->last_3d = NULL;
13476                :   }
13477                :
13478                :   pScrn->PointerMoved = pI830->PointerMoved;
13479                :   pScrn->vtSema = FALSE;
13480                :   pI830->closing = FALSE;
13481                :   pScreen->CloseScreen = pI830->CloseScreen;
13482                :   return (*pScreen->CloseScreen) (scrnIndex, pScreen);
13483                :}
13484                :
13485                :static ModeStatus
13486                :I830ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
13487                :{
13488                :   if (mode->Flags & V_INTERLACE) {
13489                :      if (verbose) {
13490                :         xf86DrvMsg(scrnIndex, X_PROBED,
13491                :                    "Removing interlaced mode \"%s\"\n", mode->name);
13492                :      }
13493                :      return MODE_BAD;
13494                :   }
13495                :   return MODE_OK;
13496                :}
13497                :
13498                :#ifndef SUSPEND_SLEEP
13499                :#define SUSPEND_SLEEP 0
13500                :#endif
13501                :#ifndef RESUME_SLEEP
13502                :#define RESUME_SLEEP 0
13503                :#endif
13504                :
13505                :/*
13506                : * This function is only required if we need to do anything differently from
13507                : * DoApmEvent() in common/xf86PM.c, including if we want to see events other
13508                : * than suspend/resume.
13509                : */
13510                :static Bool
13511                :I830PMEvent(int scrnIndex, pmEvent event, Bool undo)
13512                :{
13513                :   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
13514                :   I830Ptr pI830 = I830PTR(pScrn);
13515                :
13516                :   DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event, BOOLTOSTRING(undo));
13517                : 
13518                :   switch(event) {
13519                :   case XF86_APM_SYS_SUSPEND:
13520                :   case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/
13521                :   case XF86_APM_USER_SUSPEND:
13522                :   case XF86_APM_SYS_STANDBY:
13523                :   case XF86_APM_USER_STANDBY:
13524                :      if (!undo && !pI830->suspended) {
13525                :         pScrn->LeaveVT(scrnIndex, 0);
13526                :         pI830->suspended = TRUE;
13527                :         sleep(SUSPEND_SLEEP);
13528                :      } else if (undo && pI830->suspended) {
13529                :         sleep(RESUME_SLEEP);
13530                :         pScrn->EnterVT(scrnIndex, 0);
13531                :         pI830->suspended = FALSE;
13532                :      }
13533                :      break;
13534                :   case XF86_APM_STANDBY_RESUME:
13535                :   case XF86_APM_NORMAL_RESUME:
13536                :   case XF86_APM_CRITICAL_RESUME:
13537                :      if (pI830->suspended) {
13538                :         sleep(RESUME_SLEEP);
13539                :         pScrn->EnterVT(scrnIndex, 0);
13540                :         pI830->suspended = FALSE;
13541                :         /*
13542                :          * Turn the screen saver off when resuming.  This seems to be
13543                :          * needed to stop xscreensaver kicking in (when used).
13544                :          *
13545                :          * XXX DoApmEvent() should probably call this just like
13546                :          * xf86VTSwitch() does.  Maybe do it here only in 4.2
13547                :          * compatibility mode.
13548                :          */
13549                :         SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
13550                :      }
13551                :      break;
13552                :   /* This is currently used for ACPI */
13553                :   case XF86_APM_CAPABILITY_CHANGED:
13554                :#if 0
13555                :      /* If we had status checking turned on, turn it off now */
13556                :      if (pI830->checkDevices) {
13557                :         if (pI830->devicesTimer)
13558                :            TimerCancel(pI830->devicesTimer);
13559                :         pI830->devicesTimer = NULL;
13560                :         pI830->checkDevices = FALSE; 
13561                :      }
13562                :#endif
13563                :      if (!I830IsPrimary(pScrn))
13564                :         return TRUE;
13565                :
13566                :      ErrorF("I830PMEvent: Capability change\n");
13567                :
13568                :      I830CheckDevicesTimer(NULL, 0, pScrn);
13569                :      SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
13570                :      break;
13571                :   default:
13572                :      ErrorF("I830PMEvent: received APM event %d\n", event);
13573                :   }
13574                :   return TRUE;
13575                :}
13576                :
13577                :#if 0
13578                :/**
13579                : * This function is used for testing of the screen detect functions from the
13580                : * periodic timer.
13581                : */
13582                :static void
13583                :i830MonitorDetectDebugger(ScrnInfoPtr pScrn)
13584                :{
13585                :   Bool found_crt;
13586                :   I830Ptr pI830 = I830PTR(pScrn);
13587                :   int start, finish, i;
13588                :
13589                :   if (!pScrn->vtSema)
13590                :      return 1000;
13591                :
13592                :   for (i = 0; i < xf86_config->num_output; i++) {
13593                :      enum output_status ret;
13594                :      char *result;
13595                :
13596                :      start = GetTimeInMillis();
13597                :      ret = pI830->output[i].detect(pScrn, &pI830->output[i]);
13598                :      finish = GetTimeInMillis();
13599                :
13600                :      if (ret == OUTPUT_STATUS_CONNECTED)
13601                :         result = "connected";
13602                :      else if (ret == OUTPUT_STATUS_DISCONNECTED)
13603                :         result = "disconnected";
13604                :      else
13605                :         result = "unknown";
13606                :
13607                :      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n",
13608                :                 result, finish - start);
13609                :   }
13610                :}
13611                :#endif
13612                :
13613                :static CARD32
13614                :I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg)
13615                :{
13616                :   ScrnInfoPtr pScrn = (ScrnInfoPtr) arg;
13617                :   I830Ptr pI830 = I830PTR(pScrn);
13618                :   CARD8 gr18;
13619                :
13620                :   if (!pScrn->vtSema)
13621                :      return 1000;
13622                :
13623                :#if 0
13624                :   i830MonitorDetectDebugger(pScrn);
13625                :#endif
13626                :
13627                :   /* Check for a hotkey press report from the BIOS. */
13628                :   gr18 = pI830->readControl(pI830, GRX, 0x18);
13629                :   if ((gr18 & (HOTKEY_TOGGLE | HOTKEY_SWITCH)) != 0) {
13630                :      /* The user has pressed the hotkey requesting a toggle or switch.
13631                :       * Re-probe our connected displays and turn on whatever we find.
13632                :       *
13633                :       * In the future, we want the hotkey to dump down to a user app which
13634                :       * implements a sensible policy using RandR-1.2.  For now, all we get
13635                :       * is this.
13636                :       */
13637                :      
13638                :      xf86ProbeOutputModes (pScrn, 0, 0);
13639                :      xf86SetScrnInfoModes (pScrn);
13640                :      xf86DiDGAReInit (pScrn->pScreen);
13641                :      xf86SwitchMode(pScrn->pScreen, pScrn->currentMode);
13642                :
13643                :      /* Clear the BIOS's hotkey press flags */
13644                :      gr18 &= ~(HOTKEY_TOGGLE | HOTKEY_SWITCH);
13645                :      pI830->writeControl(pI830, GRX, 0x18, gr18);
13646                :   }
13647                :
13648                :   return 1000;
13649                :}
13650                :
13651                :void
13652                :i830WaitSync(ScrnInfoPtr pScrn)
13653     31  0.0338 :{ /* i830WaitSync total:    103  0.1122 */
13654      1  0.0011 :   I830Ptr pI830 = I830PTR(pScrn);
13655                :
13656                :#ifdef I830_USE_XAA
13657     15  0.0163 :   if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec 
13658                :        && pI830->AccelInfoRec->NeedToSync) {
13659                :      (*pI830->AccelInfoRec->Sync)(pScrn);
13660                :      pI830->AccelInfoRec->NeedToSync = FALSE;
13661                :   }
13662                :#endif
13663                :#ifdef I830_USE_EXA
13664      6  0.0065 :   if (!pI830->noAccel && pI830->useEXA && pI830->EXADriverPtr) {
13665                :        ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
13666     21  0.0229 :        exaWaitSync(pScreen);
13667                :   }
13668                :#endif
13669     29  0.0316 :}
13670                :
13671                :void
13672                :i830MarkSync(ScrnInfoPtr pScrn)
13673      7  0.0076 :{ /* i830MarkSync total:     15  0.0163 */
13674                :   I830Ptr pI830 = I830PTR(pScrn);
13675                :
13676                :#ifdef I830_USE_XAA
13677                :   if (!pI830->useEXA && pI830->AccelInfoRec)
13678                :      pI830->AccelInfoRec->NeedToSync = TRUE;
13679                :#endif
13680                :#ifdef I830_USE_EXA
13681      2  0.0022 :   if (pI830->useEXA && pI830->EXADriverPtr) {
13682                :      ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
13683      3  0.0033 :      exaMarkSync(pScreen);
13684                :   }
13685                :#endif
13686      3  0.0033 :}
13687                :
13688                :void
13689                :I830InitpScrn(ScrnInfoPtr pScrn)
13690                :{
13691                :   pScrn->PreInit = I830PreInit;
13692                :   pScrn->ScreenInit = I830ScreenInit;
13693                :   pScrn->SwitchMode = I830SwitchMode;
13694                :   pScrn->AdjustFrame = i830AdjustFrame;
13695                :   pScrn->EnterVT = I830EnterVT;
13696                :   pScrn->LeaveVT = I830LeaveVT;
13697                :   pScrn->FreeScreen = I830FreeScreen;
13698                :   pScrn->ValidMode = I830ValidMode;
13699                :   pScrn->PMEvent = I830PMEvent;
13700                :}
13701 /* 
13702  * Total samples for file : "/home/cworth/src/xorg/xserver/mi/misprite.c"
13703  * 
13704  *    140  0.1525
13705  */
13706
13707
13708                :/*
13709                : * misprite.c
13710                : *
13711                : * machine independent software sprite routines
13712                : */
13713                :
13714                :
13715                :/*
13716                :
13717                :Copyright 1989, 1998  The Open Group
13718                :
13719                :Permission to use, copy, modify, distribute, and sell this software and its
13720                :documentation for any purpose is hereby granted without fee, provided that
13721                :the above copyright notice appear in all copies and that both that
13722                :copyright notice and this permission notice appear in supporting
13723                :documentation.
13724                :
13725                :The above copyright notice and this permission notice shall be included in
13726                :all copies or substantial portions of the Software.
13727                :
13728                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13729                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13730                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
13731                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
13732                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
13733                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13734                :
13735                :Except as contained in this notice, the name of The Open Group shall not be
13736                :used in advertising or otherwise to promote the sale, use or other dealings
13737                :in this Software without prior written authorization from The Open Group.
13738                :*/
13739                :
13740                :#ifdef HAVE_DIX_CONFIG_H
13741                :#include <dix-config.h>
13742                :#endif
13743                :
13744                :# include   <X11/X.h>
13745                :# include   <X11/Xproto.h>
13746                :# include   "misc.h"
13747                :# include   "pixmapstr.h"
13748                :# include   "input.h"
13749                :# include   "mi.h"
13750                :# include   "cursorstr.h"
13751                :# include   <X11/fonts/font.h>
13752                :# include   "scrnintstr.h"
13753                :# include   "colormapst.h"
13754                :# include   "windowstr.h"
13755                :# include   "gcstruct.h"
13756                :# include   "mipointer.h"
13757                :# include   "mispritest.h"
13758                :# include   "dixfontstr.h"
13759                :# include   <X11/fonts/fontstruct.h>
13760                :
13761                :#ifdef RENDER
13762                :# include   "mipict.h"
13763                :#endif
13764                :# include   "damage.h"
13765                :
13766                :#define SPRITE_DEBUG_ENABLE 0
13767                :#if SPRITE_DEBUG_ENABLE
13768                :#define SPRITE_DEBUG(x) ErrorF x
13769                :#else
13770                :#define SPRITE_DEBUG(x)
13771                :#endif
13772                :
13773                :/*
13774                : * screen wrappers
13775                : */
13776                :
13777                :static int  miSpriteScreenIndex;
13778                :static unsigned long miSpriteGeneration = 0;
13779                :
13780                :static Bool         miSpriteCloseScreen(int i, ScreenPtr pScreen);
13781                :static void         miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
13782                :                                     int w, int h, unsigned int format,
13783                :                                     unsigned long planemask, char *pdstLine);
13784                :static void         miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
13785                :                                     DDXPointPtr ppt, int *pwidth, int nspans,
13786                :                                     char *pdstStart);
13787                :static void         miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
13788                :                                           int width, int height);
13789                :static void         miSpriteCopyWindow (WindowPtr pWindow,
13790                :                                        DDXPointRec ptOldOrg,
13791                :                                        RegionPtr prgnSrc);
13792                :static void         miSpriteBlockHandler(int i, pointer blockData,
13793                :                                         pointer pTimeout,
13794                :                                         pointer pReadMask);
13795                :static void         miSpriteInstallColormap(ColormapPtr pMap);
13796                :static void         miSpriteStoreColors(ColormapPtr pMap, int ndef,
13797                :                                        xColorItem *pdef);
13798                :
13799                :static void         miSpriteSaveDoomedAreas(WindowPtr pWin,
13800                :                                            RegionPtr pObscured, int dx,
13801                :                                            int dy);
13802                :static void         miSpriteComputeSaved(ScreenPtr pScreen);
13803                :
13804                :#define SCREEN_PROLOGUE(pScreen, field)\
13805                :  ((pScreen)->field = \
13806                :   ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
13807                :
13808                :#define SCREEN_EPILOGUE(pScreen, field)\
13809                :    ((pScreen)->field = miSprite##field)
13810                :
13811                :/*
13812                : * pointer-sprite method table
13813                : */
13814                :
13815                :static Bool miSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
13816                :static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
13817                :static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor,
13818                :                              int x, int y);
13819                :static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y);
13820                :
13821                :_X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
13822                :    miSpriteRealizeCursor,
13823                :    miSpriteUnrealizeCursor,
13824                :    miSpriteSetCursor,
13825                :    miSpriteMoveCursor,
13826                :};
13827                :
13828                :/*
13829                : * other misc functions
13830                : */
13831                :
13832                :static void miSpriteRemoveCursor(ScreenPtr pScreen);
13833                :static void miSpriteRestoreCursor(ScreenPtr pScreen);
13834                :
13835                :static void
13836                :miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
13837                :{
13838                :    ScreenPtr               pScreen = closure;
13839                :    miSpriteScreenPtr       pScreenPriv;
13840                :    
13841                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
13842                :    
13843                :    if (pScreenPriv->isUp &&
13844                :        RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
13845                :    {
13846                :        SPRITE_DEBUG(("Damage remove\n"));
13847                :        miSpriteRemoveCursor (pScreen);
13848                :    }
13849                :}
13850                :
13851                :/*
13852                : * miSpriteInitialize -- called from device-dependent screen
13853                : * initialization proc after all of the function pointers have
13854                : * been stored in the screen structure.
13855                : */
13856                :
13857                :Bool
13858                :miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
13859                :    ScreenPtr               pScreen;
13860                :    miSpriteCursorFuncPtr   cursorFuncs;
13861                :    miPointerScreenFuncPtr  screenFuncs;
13862                :{
13863                :    miSpriteScreenPtr   pScreenPriv;
13864                :    VisualPtr           pVisual;
13865                :    
13866                :    if (!DamageSetup (pScreen))
13867                :        return FALSE;
13868                :
13869                :    if (miSpriteGeneration != serverGeneration)
13870                :    {
13871                :        miSpriteScreenIndex = AllocateScreenPrivateIndex ();
13872                :        if (miSpriteScreenIndex < 0)
13873                :            return FALSE;
13874                :        miSpriteGeneration = serverGeneration;
13875                :    }
13876                :    
13877                :    pScreenPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec));
13878                :    if (!pScreenPriv)
13879                :        return FALSE;
13880                :    
13881                :    pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
13882                :                                         (DamageDestroyFunc) 0,
13883                :                                         DamageReportRawRegion,
13884                :                                         TRUE,
13885                :                                         pScreen,
13886                :                                         (void *) pScreen);
13887                :
13888                :    if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
13889                :    {
13890                :        xfree ((pointer) pScreenPriv);
13891                :        return FALSE;
13892                :    }
13893                :    for (pVisual = pScreen->visuals;
13894                :         pVisual->vid != pScreen->rootVisual;
13895                :         pVisual++)
13896                :        ;
13897                :    pScreenPriv->pVisual = pVisual;
13898                :    pScreenPriv->CloseScreen = pScreen->CloseScreen;
13899                :    pScreenPriv->GetImage = pScreen->GetImage;
13900                :    pScreenPriv->GetSpans = pScreen->GetSpans;
13901                :    pScreenPriv->SourceValidate = pScreen->SourceValidate;
13902                :
13903                :    pScreenPriv->CopyWindow = pScreen->CopyWindow;
13904                :    
13905                :    pScreenPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
13906                :    
13907                :    pScreenPriv->InstallColormap = pScreen->InstallColormap;
13908                :    pScreenPriv->StoreColors = pScreen->StoreColors;
13909                :    
13910                :    pScreenPriv->BlockHandler = pScreen->BlockHandler;
13911                :    
13912                :    pScreenPriv->pCursor = NULL;
13913                :    pScreenPriv->x = 0;
13914                :    pScreenPriv->y = 0;
13915                :    pScreenPriv->isUp = FALSE;
13916                :    pScreenPriv->shouldBeUp = FALSE;
13917                :    pScreenPriv->pCacheWin = NullWindow;
13918                :    pScreenPriv->isInCacheWin = FALSE;
13919                :    pScreenPriv->checkPixels = TRUE;
13920                :    pScreenPriv->pInstalledMap = NULL;
13921                :    pScreenPriv->pColormap = NULL;
13922                :    pScreenPriv->funcs = cursorFuncs;
13923                :    pScreenPriv->colors[SOURCE_COLOR].red = 0;
13924                :    pScreenPriv->colors[SOURCE_COLOR].green = 0;
13925                :    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
13926                :    pScreenPriv->colors[MASK_COLOR].red = 0;
13927                :    pScreenPriv->colors[MASK_COLOR].green = 0;
13928                :    pScreenPriv->colors[MASK_COLOR].blue = 0;
13929                :    pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv;
13930                :    
13931                :    pScreen->CloseScreen = miSpriteCloseScreen;
13932                :    pScreen->GetImage = miSpriteGetImage;
13933                :    pScreen->GetSpans = miSpriteGetSpans;
13934                :    pScreen->SourceValidate = miSpriteSourceValidate;
13935                :    
13936                :    pScreen->CopyWindow = miSpriteCopyWindow;
13937                :    
13938                :    pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
13939                :    
13940                :    pScreen->InstallColormap = miSpriteInstallColormap;
13941                :    pScreen->StoreColors = miSpriteStoreColors;
13942                :
13943                :    pScreen->BlockHandler = miSpriteBlockHandler;
13944                :    
13945                :    return TRUE;
13946                :}
13947                :
13948                :/*
13949                : * Screen wrappers
13950                : */
13951                :
13952                :/*
13953                : * CloseScreen wrapper -- unwrap everything, free the private data
13954                : * and call the wrapped function
13955                : */
13956                :
13957                :static Bool
13958                :miSpriteCloseScreen (i, pScreen)
13959                :    int i;
13960                :    ScreenPtr   pScreen;
13961                :{
13962                :    miSpriteScreenPtr   pScreenPriv;
13963                :
13964                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
13965                :
13966                :    pScreen->CloseScreen = pScreenPriv->CloseScreen;
13967                :    pScreen->GetImage = pScreenPriv->GetImage;
13968                :    pScreen->GetSpans = pScreenPriv->GetSpans;
13969                :    pScreen->SourceValidate = pScreenPriv->SourceValidate;
13970                :    pScreen->BlockHandler = pScreenPriv->BlockHandler;
13971                :    pScreen->InstallColormap = pScreenPriv->InstallColormap;
13972                :    pScreen->StoreColors = pScreenPriv->StoreColors;
13973                :
13974                :    pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
13975                :    miSpriteIsUpFALSE (pScreen, pScreenPriv);
13976                :    DamageDestroy (pScreenPriv->pDamage);
13977                :    
13978                :    xfree ((pointer) pScreenPriv);
13979                :
13980                :    return (*pScreen->CloseScreen) (i, pScreen);
13981                :}
13982                :
13983                :static void
13984                :miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
13985                :    DrawablePtr     pDrawable;
13986                :    int             sx, sy, w, h;
13987                :    unsigned int    format;
13988                :    unsigned long   planemask;
13989                :    char            *pdstLine;
13990                :{
13991                :    ScreenPtr       pScreen = pDrawable->pScreen;
13992                :    miSpriteScreenPtr    pScreenPriv;
13993                :    
13994                :    SCREEN_PROLOGUE (pScreen, GetImage);
13995                :
13996                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
13997                :
13998                :    if (pDrawable->type == DRAWABLE_WINDOW &&
13999                :        pScreenPriv->isUp &&
14000                :        ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
14001                :    {
14002                :        SPRITE_DEBUG (("GetImage remove\n"));
14003                :        miSpriteRemoveCursor (pScreen);
14004                :    }
14005                :
14006                :    (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
14007                :                          format, planemask, pdstLine);
14008                :
14009                :    SCREEN_EPILOGUE (pScreen, GetImage);
14010                :}
14011                :
14012                :static void
14013                :miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
14014                :    DrawablePtr pDrawable;
14015                :    int         wMax;
14016                :    DDXPointPtr ppt;
14017                :    int         *pwidth;
14018                :    int         nspans;
14019                :    char        *pdstStart;
14020                :{
14021                :    ScreenPtr               pScreen = pDrawable->pScreen;
14022                :    miSpriteScreenPtr       pScreenPriv;
14023                :    
14024                :    SCREEN_PROLOGUE (pScreen, GetSpans);
14025                :
14026                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14027                :
14028                :    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
14029                :    {
14030                :        DDXPointPtr     pts;
14031                :        int             *widths;
14032                :        int             nPts;
14033                :        int             xorg,
14034                :                        yorg;
14035                :
14036                :        xorg = pDrawable->x;
14037                :        yorg = pDrawable->y;
14038                :
14039                :        for (pts = ppt, widths = pwidth, nPts = nspans;
14040                :             nPts--;
14041                :             pts++, widths++)
14042                :        {
14043                :            if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
14044                :                             pts->x+xorg,*widths))
14045                :            {
14046                :                SPRITE_DEBUG (("GetSpans remove\n"));
14047                :                miSpriteRemoveCursor (pScreen);
14048                :                break;
14049                :            }
14050                :        }
14051                :    }
14052                :
14053                :    (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
14054                :
14055                :    SCREEN_EPILOGUE (pScreen, GetSpans);
14056                :}
14057                :
14058                :static void
14059                :miSpriteSourceValidate (pDrawable, x, y, width, height)
14060                :    DrawablePtr pDrawable;
14061                :    int         x, y, width, height;
14062     31  0.0338 :{ /* miSpriteSourceValidate total:    140  0.1525 */
14063                :    ScreenPtr               pScreen = pDrawable->pScreen;
14064                :    miSpriteScreenPtr       pScreenPriv;
14065                :    
14066     55  0.0599 :    SCREEN_PROLOGUE (pScreen, SourceValidate);
14067                :
14068      7  0.0076 :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14069                :
14070                :    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
14071                :        ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
14072                :                    x, y, width, height))
14073                :    {
14074                :        SPRITE_DEBUG (("SourceValidate remove\n"));
14075                :        miSpriteRemoveCursor (pScreen);
14076                :    }
14077                :
14078     26  0.0283 :    if (pScreen->SourceValidate)
14079                :        (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
14080                :
14081      5  0.0054 :    SCREEN_EPILOGUE (pScreen, SourceValidate);
14082     16  0.0174 :}
14083                :
14084                :static void
14085                :miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
14086                :{
14087                :    ScreenPtr   pScreen = pWindow->drawable.pScreen;
14088                :    miSpriteScreenPtr       pScreenPriv;
14089                :    
14090                :    SCREEN_PROLOGUE (pScreen, CopyWindow);
14091                :
14092                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14093                :    /*
14094                :     * Damage will take care of destination check
14095                :     */
14096                :    if (pScreenPriv->isUp &&
14097                :        RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->saved) != rgnOUT)
14098                :    {
14099                :        SPRITE_DEBUG (("CopyWindow remove\n"));
14100                :        miSpriteRemoveCursor (pScreen);
14101                :    }
14102                :
14103                :    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
14104                :    SCREEN_EPILOGUE (pScreen, CopyWindow);
14105                :}
14106                :
14107                :static void
14108                :miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
14109                :    int i;
14110                :    pointer     blockData;
14111                :    pointer     pTimeout;
14112                :    pointer     pReadmask;
14113                :{
14114                :    ScreenPtr           pScreen = screenInfo.screens[i];
14115                :    miSpriteScreenPtr   pPriv;
14116                :
14117                :    pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14118                :
14119                :    SCREEN_PROLOGUE(pScreen, BlockHandler);
14120                :    
14121                :    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
14122                :
14123                :    SCREEN_EPILOGUE(pScreen, BlockHandler);
14124                :
14125                :    if (!pPriv->isUp && pPriv->shouldBeUp)
14126                :    {
14127                :        SPRITE_DEBUG (("BlockHandler restore\n"));
14128                :        miSpriteRestoreCursor (pScreen);
14129                :    }
14130                :}
14131                :
14132                :static void
14133                :miSpriteInstallColormap (pMap)
14134                :    ColormapPtr pMap;
14135                :{
14136                :    ScreenPtr           pScreen = pMap->pScreen;
14137                :    miSpriteScreenPtr   pPriv;
14138                :
14139                :    pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14140                :
14141                :    SCREEN_PROLOGUE(pScreen, InstallColormap);
14142                :    
14143                :    (*pScreen->InstallColormap) (pMap);
14144                :
14145                :    SCREEN_EPILOGUE(pScreen, InstallColormap);
14146                :
14147                :    pPriv->pInstalledMap = pMap;
14148                :    if (pPriv->pColormap != pMap)
14149                :    {
14150                :        pPriv->checkPixels = TRUE;
14151                :        if (pPriv->isUp)
14152                :            miSpriteRemoveCursor (pScreen);
14153                :    }
14154                :}
14155                :
14156                :static void
14157                :miSpriteStoreColors (pMap, ndef, pdef)
14158                :    ColormapPtr pMap;
14159                :    int         ndef;
14160                :    xColorItem  *pdef;
14161                :{
14162                :    ScreenPtr           pScreen = pMap->pScreen;
14163                :    miSpriteScreenPtr   pPriv;
14164                :    int                 i;
14165                :    int                 updated;
14166                :    VisualPtr           pVisual;
14167                :
14168                :    pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14169                :
14170                :    SCREEN_PROLOGUE(pScreen, StoreColors);
14171                :    
14172                :    (*pScreen->StoreColors) (pMap, ndef, pdef);
14173                :
14174                :    SCREEN_EPILOGUE(pScreen, StoreColors);
14175                :
14176                :    if (pPriv->pColormap == pMap)
14177                :    {
14178                :        updated = 0;
14179                :        pVisual = pMap->pVisual;
14180                :        if (pVisual->class == DirectColor)
14181                :        {
14182                :            /* Direct color - match on any of the subfields */
14183                :
14184                :#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
14185                :
14186                :#define UpdateDAC(plane,dac,mask) {\
14187                :    if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\
14188                :        pPriv->colors[plane].dac = pdef[i].dac; \
14189                :        updated = 1; \
14190                :    } \
14191                :}
14192                :
14193                :#define CheckDirect(plane) \
14194                :            UpdateDAC(plane,red,redMask) \
14195                :            UpdateDAC(plane,green,greenMask) \
14196                :            UpdateDAC(plane,blue,blueMask)
14197                :
14198                :            for (i = 0; i < ndef; i++)
14199                :            {
14200                :                CheckDirect (SOURCE_COLOR)
14201                :                CheckDirect (MASK_COLOR)
14202                :            }
14203                :        }
14204                :        else
14205                :        {
14206                :            /* PseudoColor/GrayScale - match on exact pixel */
14207                :            for (i = 0; i < ndef; i++)
14208                :            {
14209                :                if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel)
14210                :                {
14211                :                    pPriv->colors[SOURCE_COLOR] = pdef[i];
14212                :                    if (++updated == 2)
14213                :                        break;
14214                :                }
14215                :                if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
14216                :                {
14217                :                    pPriv->colors[MASK_COLOR] = pdef[i];
14218                :                    if (++updated == 2)
14219                :                        break;
14220                :                }
14221                :            }
14222                :        }
14223                :        if (updated)
14224                :        {
14225                :            pPriv->checkPixels = TRUE;
14226                :            if (pPriv->isUp)
14227                :                miSpriteRemoveCursor (pScreen);
14228                :        }
14229                :    }
14230                :}
14231                :
14232                :static void
14233                :miSpriteFindColors (ScreenPtr pScreen)
14234                :{
14235                :    miSpriteScreenPtr   pScreenPriv = (miSpriteScreenPtr)
14236                :                            pScreen->devPrivates[miSpriteScreenIndex].ptr;
14237                :    CursorPtr           pCursor;
14238                :    xColorItem          *sourceColor, *maskColor;
14239                :
14240                :    pCursor = pScreenPriv->pCursor;
14241                :    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
14242                :    maskColor = &pScreenPriv->colors[MASK_COLOR];
14243                :    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
14244                :        !(pCursor->foreRed == sourceColor->red &&
14245                :          pCursor->foreGreen == sourceColor->green &&
14246                :          pCursor->foreBlue == sourceColor->blue &&
14247                :          pCursor->backRed == maskColor->red &&
14248                :          pCursor->backGreen == maskColor->green &&
14249                :          pCursor->backBlue == maskColor->blue))
14250                :    {
14251                :        pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
14252                :        sourceColor->red = pCursor->foreRed;
14253                :        sourceColor->green = pCursor->foreGreen;
14254                :        sourceColor->blue = pCursor->foreBlue;
14255                :        FakeAllocColor (pScreenPriv->pColormap, sourceColor);
14256                :        maskColor->red = pCursor->backRed;
14257                :        maskColor->green = pCursor->backGreen;
14258                :        maskColor->blue = pCursor->backBlue;
14259                :        FakeAllocColor (pScreenPriv->pColormap, maskColor);
14260                :        /* "free" the pixels right away, don't let this confuse you */
14261                :        FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
14262                :        FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
14263                :    }
14264                :    pScreenPriv->checkPixels = FALSE;
14265                :}
14266                :
14267                :/*
14268                : * BackingStore wrappers
14269                : */
14270                :
14271                :static void
14272                :miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
14273                :    WindowPtr   pWin;
14274                :    RegionPtr   pObscured;
14275                :    int         dx, dy;
14276                :{
14277                :    ScreenPtr           pScreen;
14278                :    miSpriteScreenPtr   pScreenPriv;
14279                :    BoxRec              cursorBox;
14280                :
14281                :    pScreen = pWin->drawable.pScreen;
14282                :    
14283                :    SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
14284                :
14285                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14286                :    if (pScreenPriv->isUp)
14287                :    {
14288                :        cursorBox = pScreenPriv->saved;
14289                :
14290                :        if (dx || dy)
14291                :        {
14292                :            cursorBox.x1 += dx;
14293                :            cursorBox.y1 += dy;
14294                :            cursorBox.x2 += dx;
14295                :            cursorBox.y2 += dy;
14296                :        }
14297                :        if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
14298                :            miSpriteRemoveCursor (pScreen);
14299                :    }
14300                :
14301                :    (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
14302                :
14303                :    SCREEN_EPILOGUE (pScreen, SaveDoomedAreas);
14304                :}
14305                :
14306                :/*
14307                : * miPointer interface routines
14308                : */
14309                :
14310                :#define SPRITE_PAD  8
14311                :
14312                :static Bool
14313                :miSpriteRealizeCursor (pScreen, pCursor)
14314                :    ScreenPtr   pScreen;
14315                :    CursorPtr   pCursor;
14316                :{
14317                :    miSpriteScreenPtr   pScreenPriv;
14318                :
14319                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14320                :    if (pCursor == pScreenPriv->pCursor)
14321                :        pScreenPriv->checkPixels = TRUE;
14322                :    return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
14323                :}
14324                :
14325                :static Bool
14326                :miSpriteUnrealizeCursor (pScreen, pCursor)
14327                :    ScreenPtr   pScreen;
14328                :    CursorPtr   pCursor;
14329                :{
14330                :    miSpriteScreenPtr   pScreenPriv;
14331                :
14332                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14333                :    return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
14334                :}
14335                :
14336                :static void
14337                :miSpriteSetCursor (pScreen, pCursor, x, y)
14338                :    ScreenPtr   pScreen;
14339                :    CursorPtr   pCursor;
14340                :    int         x;
14341                :    int         y;
14342                :{
14343                :    miSpriteScreenPtr   pScreenPriv;
14344                :
14345                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14346                :    if (!pCursor)
14347                :    {
14348                :        pScreenPriv->shouldBeUp = FALSE;
14349                :        if (pScreenPriv->isUp)
14350                :            miSpriteRemoveCursor (pScreen);
14351                :        pScreenPriv->pCursor = 0;
14352                :        return;
14353                :    }
14354                :    pScreenPriv->shouldBeUp = TRUE;
14355                :    if (pScreenPriv->x == x &&
14356                :        pScreenPriv->y == y &&
14357                :        pScreenPriv->pCursor == pCursor &&
14358                :        !pScreenPriv->checkPixels)
14359                :    {
14360                :        return;
14361                :    }
14362                :    pScreenPriv->x = x;
14363                :    pScreenPriv->y = y;
14364                :    pScreenPriv->pCacheWin = NullWindow;
14365                :    if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
14366                :    {
14367                :        pScreenPriv->pCursor = pCursor;
14368                :        miSpriteFindColors (pScreen);
14369                :    }
14370                :    if (pScreenPriv->isUp) {
14371                :        int     sx, sy;
14372                :        /*
14373                :         * check to see if the old saved region
14374                :         * encloses the new sprite, in which case we use
14375                :         * the flicker-free MoveCursor primitive.
14376                :         */
14377                :        sx = pScreenPriv->x - (int)pCursor->bits->xhot;
14378                :        sy = pScreenPriv->y - (int)pCursor->bits->yhot;
14379                :        if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 &&
14380                :            sx < pScreenPriv->saved.x2 &&
14381                :            sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 &&
14382                :            sy < pScreenPriv->saved.y2 &&
14383                :            (int) pCursor->bits->width + (2 * SPRITE_PAD) ==
14384                :                pScreenPriv->saved.x2 - pScreenPriv->saved.x1 &&
14385                :            (int) pCursor->bits->height + (2 * SPRITE_PAD) ==
14386                :                pScreenPriv->saved.y2 - pScreenPriv->saved.y1
14387                :            )
14388                :        {
14389                :            DamageDrawInternal (pScreen, TRUE);
14390                :            miSpriteIsUpFALSE (pScreen, pScreenPriv);
14391                :            if (!(sx >= pScreenPriv->saved.x1 &&
14392                :                  sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 &&
14393                :                  sy >= pScreenPriv->saved.y1 &&
14394                :                  sy + (int)pCursor->bits->height < pScreenPriv->saved.y2))
14395                :            {
14396                :                int oldx1, oldy1, dx, dy;
14397                :
14398                :                oldx1 = pScreenPriv->saved.x1;
14399                :                oldy1 = pScreenPriv->saved.y1;
14400                :                dx = oldx1 - (sx - SPRITE_PAD);
14401                :                dy = oldy1 - (sy - SPRITE_PAD);
14402                :                pScreenPriv->saved.x1 -= dx;
14403                :                pScreenPriv->saved.y1 -= dy;
14404                :                pScreenPriv->saved.x2 -= dx;
14405                :                pScreenPriv->saved.y2 -= dy;
14406                :                (void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
14407                :                                pScreenPriv->saved.x1,
14408                :                                pScreenPriv->saved.y1,
14409                :                                pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
14410                :                                pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
14411                :                                dx, dy);
14412                :            }
14413                :            (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
14414                :                                  pScreenPriv->saved.x1,
14415                :                                  pScreenPriv->saved.y1,
14416                :                                  pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
14417                :                                  pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
14418                :                                  sx - pScreenPriv->saved.x1,
14419                :                                  sy - pScreenPriv->saved.y1,
14420                :                                  pScreenPriv->colors[SOURCE_COLOR].pixel,
14421                :                                  pScreenPriv->colors[MASK_COLOR].pixel);
14422                :            miSpriteIsUpTRUE (pScreen, pScreenPriv);
14423                :            DamageDrawInternal (pScreen, FALSE);
14424                :        }
14425                :        else
14426                :        {
14427                :            SPRITE_DEBUG (("SetCursor remove\n"));
14428                :            miSpriteRemoveCursor (pScreen);
14429                :        }
14430                :    }
14431                :    if (!pScreenPriv->isUp && pScreenPriv->pCursor)
14432                :    {
14433                :        SPRITE_DEBUG (("SetCursor restore\n"));
14434                :        miSpriteRestoreCursor (pScreen);
14435                :    }
14436                :}
14437                :
14438                :static void
14439                :miSpriteMoveCursor (pScreen, x, y)
14440                :    ScreenPtr   pScreen;
14441                :    int         x, y;
14442                :{
14443                :    miSpriteScreenPtr   pScreenPriv;
14444                :
14445                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14446                :    miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
14447                :}
14448                :
14449                :/*
14450                : * undraw/draw cursor
14451                : */
14452                :
14453                :static void
14454                :miSpriteRemoveCursor (pScreen)
14455                :    ScreenPtr   pScreen;
14456                :{
14457                :    miSpriteScreenPtr   pScreenPriv;
14458                :
14459                :    DamageDrawInternal (pScreen, TRUE);
14460                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14461                :    miSpriteIsUpFALSE (pScreen, pScreenPriv);
14462                :    pScreenPriv->pCacheWin = NullWindow;
14463                :    if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
14464                :                                         pScreenPriv->saved.x1,
14465                :                                         pScreenPriv->saved.y1,
14466                :                                         pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
14467                :                                         pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
14468                :    {
14469                :        miSpriteIsUpTRUE (pScreen, pScreenPriv);
14470                :    }
14471                :    DamageDrawInternal (pScreen, FALSE);
14472                :}
14473                :
14474                :/*
14475                : * Called from the block handler, restores the cursor
14476                : * before waiting for something to do.
14477                : */
14478                :
14479                :static void
14480                :miSpriteRestoreCursor (pScreen)
14481                :    ScreenPtr   pScreen;
14482                :{
14483                :    miSpriteScreenPtr   pScreenPriv;
14484                :    int                 x, y;
14485                :    CursorPtr           pCursor;
14486                :
14487                :    DamageDrawInternal (pScreen, TRUE);
14488                :    miSpriteComputeSaved (pScreen);
14489                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14490                :    pCursor = pScreenPriv->pCursor;
14491                :    x = pScreenPriv->x - (int)pCursor->bits->xhot;
14492                :    y = pScreenPriv->y - (int)pCursor->bits->yhot;
14493                :    if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
14494                :                                      pScreenPriv->saved.x1,
14495                :                                      pScreenPriv->saved.y1,
14496                :                                      pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
14497                :                                      pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
14498                :    {
14499                :        if (pScreenPriv->checkPixels)
14500                :            miSpriteFindColors (pScreen);
14501                :        if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
14502                :                                  pScreenPriv->colors[SOURCE_COLOR].pixel,
14503                :                                  pScreenPriv->colors[MASK_COLOR].pixel))
14504                :        {
14505                :            miSpriteIsUpTRUE (pScreen, pScreenPriv);
14506                :        }
14507                :    }
14508                :    DamageDrawInternal (pScreen, FALSE);
14509                :}
14510                :
14511                :/*
14512                : * compute the desired area of the screen to save
14513                : */
14514                :
14515                :static void
14516                :miSpriteComputeSaved (pScreen)
14517                :    ScreenPtr   pScreen;
14518                :{
14519                :    miSpriteScreenPtr   pScreenPriv;
14520                :    int             x, y, w, h;
14521                :    int             wpad, hpad;
14522                :    CursorPtr       pCursor;
14523                :
14524                :    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
14525                :    pCursor = pScreenPriv->pCursor;
14526                :    x = pScreenPriv->x - (int)pCursor->bits->xhot;
14527                :    y = pScreenPriv->y - (int)pCursor->bits->yhot;
14528                :    w = pCursor->bits->width;
14529                :    h = pCursor->bits->height;
14530                :    wpad = SPRITE_PAD;
14531                :    hpad = SPRITE_PAD;
14532                :    pScreenPriv->saved.x1 = x - wpad;
14533                :    pScreenPriv->saved.y1 = y - hpad;
14534                :    pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2;
14535                :    pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2;
14536                :}
14537 /* 
14538  * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbcopy.c"
14539  * 
14540  *    127  0.1384
14541  */
14542
14543
14544                :/*
14545                : * Copyright Â© 1998 Keith Packard
14546                : *
14547                : * Permission to use, copy, modify, distribute, and sell this software and its
14548                : * documentation for any purpose is hereby granted without fee, provided that
14549                : * the above copyright notice appear in all copies and that both that
14550                : * copyright notice and this permission notice appear in supporting
14551                : * documentation, and that the name of Keith Packard not be used in
14552                : * advertising or publicity pertaining to distribution of the software without
14553                : * specific, written prior permission.  Keith Packard makes no
14554                : * representations about the suitability of this software for any purpose.  It
14555                : * is provided "as is" without express or implied warranty.
14556                : *
14557                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
14558                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
14559                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
14560                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
14561                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
14562                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14563                : * PERFORMANCE OF THIS SOFTWARE.
14564                : */
14565                :
14566                :#ifdef HAVE_DIX_CONFIG_H
14567                :#include <dix-config.h>
14568                :#endif
14569                :
14570                :#include <stdlib.h>
14571                :
14572                :#include "fb.h"
14573                :
14574                :void
14575                :fbCopyNtoN (DrawablePtr pSrcDrawable,
14576                :            DrawablePtr pDstDrawable,
14577                :            GCPtr       pGC,
14578                :            BoxPtr      pbox,
14579                :            int         nbox,
14580                :            int         dx,
14581                :            int         dy,
14582                :            Bool        reverse,
14583                :            Bool        upsidedown,
14584                :            Pixel       bitplane,
14585                :            void        *closure)
14586                :{
14587                :    CARD8       alu = pGC ? pGC->alu : GXcopy;
14588                :    FbBits      pm = pGC ? fbGetGCPrivate(pGC)->pm : FB_ALLONES;
14589                :    FbBits      *src;
14590                :    FbStride    srcStride;
14591                :    int         srcBpp;
14592                :    int         srcXoff, srcYoff;
14593                :    FbBits      *dst;
14594                :    FbStride    dstStride;
14595                :    int         dstBpp;
14596                :    int         dstXoff, dstYoff;
14597                :    
14598                :    fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
14599                :    fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
14600                :
14601                :    while (nbox--)
14602                :    {
14603                :#ifndef FB_ACCESS_WRAPPER /* pixman_blt() doesn't support accessors yet */
14604                :        if (pm == FB_ALLONES && alu == GXcopy && !reverse &&
14605                :            !upsidedown)
14606                :        {
14607                :            if (!pixman_blt ((uint32_t *)src, (uint32_t *)dst, srcStride, dstStride, srcBpp, dstBpp,
14608                :                             (pbox->x1 + dx + srcXoff),
14609                :                             (pbox->y1 + dy + srcYoff),
14610                :                             (pbox->x1 + srcXoff),
14611                :                             (pbox->y1 + srcYoff),
14612                :                             (pbox->x2 - pbox->x1),
14613                :                             (pbox->y2 - pbox->y1)))
14614                :                goto fallback;
14615                :            else
14616                :                goto next;
14617                :        }
14618                :    fallback:
14619                :#endif
14620                :        fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride,
14621                :               srcStride,
14622                :               (pbox->x1 + dx + srcXoff) * srcBpp,
14623                :               
14624                :               dst + (pbox->y1 + dstYoff) * dstStride,
14625                :               dstStride,
14626                :               (pbox->x1 + dstXoff) * dstBpp,
14627                :               
14628                :               (pbox->x2 - pbox->x1) * dstBpp,
14629                :               (pbox->y2 - pbox->y1),
14630                :               
14631                :               alu,
14632                :               pm,
14633                :               dstBpp,
14634                :               
14635                :               reverse,
14636                :               upsidedown);
14637                :#ifndef FB_ACCESS_WRAPPER
14638                :    next:
14639                :#endif
14640                :        pbox++;
14641                :    }    
14642                :    fbFinishAccess (pDstDrawable);
14643                :    fbFinishAccess (pSrcDrawable);
14644                :}
14645                :
14646                :void
14647                :fbCopy1toN (DrawablePtr pSrcDrawable,
14648                :            DrawablePtr pDstDrawable,
14649                :            GCPtr       pGC,
14650                :            BoxPtr      pbox,
14651                :            int         nbox,
14652                :            int         dx,
14653                :            int         dy,
14654                :            Bool        reverse,
14655                :            Bool        upsidedown,
14656                :            Pixel       bitplane,
14657                :            void        *closure)
14658                :{
14659                :    FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
14660                :    FbBits      *src;
14661                :    FbStride    srcStride;
14662                :    int         srcBpp;
14663                :    int         srcXoff, srcYoff;
14664                :    FbBits      *dst;
14665                :    FbStride    dstStride;
14666                :    int         dstBpp;
14667                :    int         dstXoff, dstYoff;
14668                :
14669                :    fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
14670                :    fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
14671                :
14672                :    while (nbox--)
14673                :    {
14674                :        if (dstBpp == 1)
14675                :        {
14676                :            fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride,
14677                :                   srcStride,
14678                :                   (pbox->x1 + dx + srcXoff) * srcBpp,
14679                :    
14680                :                   dst + (pbox->y1 + dstYoff) * dstStride,
14681                :                   dstStride,
14682                :                   (pbox->x1 + dstXoff) * dstBpp,
14683                :    
14684                :                   (pbox->x2 - pbox->x1) * dstBpp,
14685                :                   (pbox->y2 - pbox->y1),
14686                :    
14687                :                   FbOpaqueStipple1Rop(pGC->alu,
14688                :                                       pGC->fgPixel,pGC->bgPixel),
14689                :                   pPriv->pm,
14690                :                   dstBpp,
14691                :    
14692                :                   reverse,
14693                :                   upsidedown);
14694                :        }
14695                :        else
14696                :        {
14697                :            fbBltOne ((FbStip *) (src + (pbox->y1 + dy + srcYoff) * srcStride),
14698                :                      srcStride*(FB_UNIT/FB_STIP_UNIT),
14699                :                      (pbox->x1 + dx + srcXoff),
14700                :    
14701                :                      dst + (pbox->y1 + dstYoff) * dstStride,
14702                :                      dstStride,
14703                :                      (pbox->x1 + dstXoff) * dstBpp,
14704                :                      dstBpp,
14705                :    
14706                :                      (pbox->x2 - pbox->x1) * dstBpp,
14707                :                      (pbox->y2 - pbox->y1),
14708                :    
14709                :                      pPriv->and, pPriv->xor,
14710                :                      pPriv->bgand, pPriv->bgxor);
14711                :        }
14712                :        pbox++;
14713                :    }
14714                :
14715                :    fbFinishAccess (pDstDrawable);
14716                :    fbFinishAccess (pSrcDrawable);
14717                :}
14718                :
14719                :void
14720                :fbCopyNto1 (DrawablePtr pSrcDrawable,
14721                :            DrawablePtr pDstDrawable,
14722                :            GCPtr       pGC,
14723                :            BoxPtr      pbox,
14724                :            int         nbox,
14725                :            int         dx,
14726                :            int         dy,
14727                :            Bool        reverse,
14728                :            Bool        upsidedown,
14729                :            Pixel       bitplane,
14730                :            void        *closure)
14731                :{
14732                :    FbGCPrivPtr pPriv = fbGetGCPrivate (pGC);
14733                :    
14734                :    while (nbox--)
14735                :    {
14736                :        if (pDstDrawable->bitsPerPixel == 1)
14737                :        {
14738                :            FbBits      *src;
14739                :            FbStride    srcStride;
14740                :            int         srcBpp;
14741                :            int         srcXoff, srcYoff;
14742                :    
14743                :            FbStip      *dst;
14744                :            FbStride    dstStride;
14745                :            int         dstBpp;
14746                :            int         dstXoff, dstYoff;
14747                :            
14748                :            fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
14749                :            fbGetStipDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
14750                :            fbBltPlane (src + (pbox->y1+ dy + srcYoff) * srcStride,
14751                :                        srcStride,
14752                :                        (pbox->x1 + dx + srcXoff) * srcBpp,
14753                :                        srcBpp,
14754                :    
14755                :                        dst + (pbox->y1 + dstYoff) * dstStride,
14756                :                        dstStride,
14757                :                        (pbox->x1 + dstXoff) * dstBpp,
14758                :    
14759                :                        (pbox->x2 - pbox->x1) * srcBpp,
14760                :                        (pbox->y2 - pbox->y1),
14761                :    
14762                :                        (FbStip) pPriv->and, (FbStip) pPriv->xor,
14763                :                        (FbStip) pPriv->bgand, (FbStip) pPriv->bgxor,
14764                :                        bitplane);
14765                :            fbFinishAccess (pDstDrawable);
14766                :            fbFinishAccess (pSrcDrawable);
14767                :        }
14768                :        else
14769                :        {
14770                :            FbBits      *src;
14771                :            FbStride    srcStride;
14772                :            int         srcBpp;
14773                :            int         srcXoff, srcYoff;
14774                :
14775                :            FbBits      *dst;
14776                :            FbStride    dstStride;
14777                :            int         dstBpp;
14778                :            int         dstXoff, dstYoff;
14779                :    
14780                :            FbStip      *tmp;
14781                :            FbStride    tmpStride;
14782                :            int         width, height;
14783                :            
14784                :            width = pbox->x2 - pbox->x1;
14785                :            height = pbox->y2 - pbox->y1;
14786                :            
14787                :            tmpStride = ((width + FB_STIP_MASK) >> FB_STIP_SHIFT);
14788                :            tmp = xalloc (tmpStride * height * sizeof (FbStip));
14789                :            if (!tmp)
14790                :                return;
14791                :            
14792                :            fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
14793                :            fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
14794                :            
14795                :            fbBltPlane (src + (pbox->y1+ dy + srcYoff) * srcStride,
14796                :                        srcStride,
14797                :                        (pbox->x1 + dx + srcXoff) * srcBpp,
14798                :                        srcBpp,
14799                :    
14800                :                        tmp,
14801                :                        tmpStride,
14802                :                        0,
14803                :    
14804                :                        width * srcBpp,
14805                :                        height,
14806                :    
14807                :                        fbAndStip(GXcopy,FB_ALLONES,FB_ALLONES),
14808                :                        fbXorStip(GXcopy,FB_ALLONES,FB_ALLONES),
14809                :                        fbAndStip(GXcopy,0,FB_ALLONES),
14810                :                        fbXorStip(GXcopy,0,FB_ALLONES),
14811                :                        bitplane);
14812                :            fbBltOne (tmp,
14813                :                      tmpStride,
14814                :                      0,
14815                :    
14816                :                      dst + (pbox->y1 + dstYoff) * dstStride,
14817                :                      dstStride,
14818                :                      (pbox->x1 + dstXoff) * dstBpp,
14819                :                      dstBpp,
14820                :    
14821                :                      width * dstBpp,
14822                :                      height,
14823                :    
14824                :                      pPriv->and, pPriv->xor,
14825                :                      pPriv->bgand, pPriv->bgxor);
14826                :            xfree (tmp);
14827                :
14828                :            fbFinishAccess (pDstDrawable);
14829                :            fbFinishAccess (pSrcDrawable);
14830                :        }
14831                :        pbox++;
14832                :    }
14833                :}
14834                :
14835                :void
14836                :fbCopyRegion (DrawablePtr   pSrcDrawable,
14837                :              DrawablePtr   pDstDrawable,
14838                :              GCPtr         pGC,
14839                :              RegionPtr     pDstRegion,
14840                :              int           dx,
14841                :              int           dy,
14842                :              fbCopyProc    copyProc,
14843                :              Pixel         bitPlane,
14844                :              void          *closure)
14845      4  0.0044 :{ /* fbCopyRegion total:     27  0.0294 */
14846                :    int         careful;
14847                :    Bool        reverse;
14848                :    Bool        upsidedown;
14849                :    BoxPtr      pbox;
14850                :    int         nbox;
14851                :    BoxPtr      pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp;
14852                :    
14853      8  0.0087 :    pbox = REGION_RECTS(pDstRegion);
14854                :    nbox = REGION_NUM_RECTS(pDstRegion);
14855                :    
14856                :    /* XXX we have to err on the side of safety when both are windows,
14857                :     * because we don't know if IncludeInferiors is being used.
14858                :     */
14859      2  0.0022 :    careful = ((pSrcDrawable == pDstDrawable) ||
14860                :               ((pSrcDrawable->type == DRAWABLE_WINDOW) &&
14861                :                (pDstDrawable->type == DRAWABLE_WINDOW)));
14862                :
14863                :    pboxNew1 = NULL;
14864                :    pboxNew2 = NULL;
14865                :    if (careful && dy < 0)
14866                :    {
14867                :        upsidedown = TRUE;
14868                :
14869                :        if (nbox > 1)
14870                :        {
14871                :            /* keep ordering in each band, reverse order of bands */
14872                :            pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
14873                :            if(!pboxNew1)
14874                :                return;
14875                :            pboxBase = pboxNext = pbox+nbox-1;
14876                :            while (pboxBase >= pbox)
14877                :            {
14878                :                while ((pboxNext >= pbox) &&
14879                :                       (pboxBase->y1 == pboxNext->y1))
14880                :                    pboxNext--;
14881                :                pboxTmp = pboxNext+1;
14882                :                while (pboxTmp <= pboxBase)
14883                :                {
14884                :                    *pboxNew1++ = *pboxTmp++;
14885                :                }
14886                :                pboxBase = pboxNext;
14887                :            }
14888                :            pboxNew1 -= nbox;
14889                :            pbox = pboxNew1;
14890                :        }
14891                :    }
14892                :    else
14893                :    {
14894                :        /* walk source top to bottom */
14895                :        upsidedown = FALSE;
14896                :    }
14897                :
14898                :    if (careful && dx < 0)
14899                :    {
14900                :        /* walk source right to left */
14901                :        if (dy <= 0)
14902                :            reverse = TRUE;
14903                :        else
14904                :            reverse = FALSE;
14905                :
14906                :        if (nbox > 1)
14907                :        {
14908                :            /* reverse order of rects in each band */
14909                :            pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
14910                :            if(!pboxNew2)
14911                :            {
14912                :                if (pboxNew1)
14913                :                    DEALLOCATE_LOCAL(pboxNew1);
14914                :                return;
14915                :            }
14916                :            pboxBase = pboxNext = pbox;
14917                :            while (pboxBase < pbox+nbox)
14918                :            {
14919                :                while ((pboxNext < pbox+nbox) &&
14920                :                       (pboxNext->y1 == pboxBase->y1))
14921                :                    pboxNext++;
14922                :                pboxTmp = pboxNext;
14923                :                while (pboxTmp != pboxBase)
14924                :                {
14925                :                    *pboxNew2++ = *--pboxTmp;
14926                :                }
14927                :                pboxBase = pboxNext;
14928                :            }
14929      1  0.0011 :            pboxNew2 -= nbox;
14930                :            pbox = pboxNew2;
14931                :        }
14932                :    }
14933                :    else
14934                :    {
14935                :        /* walk source left to right */
14936                :        reverse = FALSE;
14937                :    }
14938                :
14939      8  0.0087 :    (*copyProc) (pSrcDrawable,
14940                :                 pDstDrawable,
14941                :                 pGC,
14942                :                 pbox,
14943                :                 nbox,
14944                :                 dx, dy,
14945                :                 reverse, upsidedown, bitPlane, closure);
14946                :    
14947                :    if (pboxNew1)
14948                :        DEALLOCATE_LOCAL (pboxNew1);
14949                :    if (pboxNew2)
14950                :        DEALLOCATE_LOCAL (pboxNew2);
14951      4  0.0044 :}
14952                :
14953                :RegionPtr
14954                :fbDoCopy (DrawablePtr   pSrcDrawable,
14955                :          DrawablePtr   pDstDrawable,
14956                :          GCPtr         pGC,
14957                :          int           xIn, 
14958                :          int           yIn,
14959                :          int           widthSrc, 
14960                :          int           heightSrc,
14961                :          int           xOut, 
14962                :          int           yOut,
14963                :          fbCopyProc    copyProc,
14964                :          Pixel         bitPlane,
14965                :          void          *closure)
14966      5  0.0054 :{ /* fbDoCopy total:    100  0.1089 */
14967                :    RegionPtr   prgnSrcClip = NULL; /* may be a new region, or just a copy */
14968                :    Bool        freeSrcClip = FALSE;
14969                :    RegionPtr   prgnExposed = NULL;
14970                :    RegionRec   rgnDst;
14971                :    int         dx;
14972                :    int         dy;
14973                :    int         numRects;
14974                :    int         box_x1;
14975                :    int         box_y1;
14976                :    int         box_x2;
14977                :    int         box_y2;
14978                :    Bool        fastSrc = FALSE;    /* for fast clipping with pixmap source */
14979                :    Bool        fastDst = FALSE;    /* for fast clipping with one rect dest */
14980                :    Bool        fastExpose = FALSE; /* for fast exposures with pixmap source */
14981                :
14982                :    /* Short cut for unmapped windows */
14983                :
14984      1  0.0011 :    if (pDstDrawable->type == DRAWABLE_WINDOW && 
14985                :        !((WindowPtr)pDstDrawable)->realized)
14986                :    {
14987                :        return NULL;
14988                :    }
14989                :
14990      8  0.0087 :    if ((pSrcDrawable != pDstDrawable) &&
14991                :        pSrcDrawable->pScreen->SourceValidate)
14992                :    {
14993      1  0.0011 :        (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc);
14994                :    }
14995                :
14996                :    /* Compute source clip region */
14997      2  0.0022 :    if (pSrcDrawable->type == DRAWABLE_PIXMAP)
14998                :    {
14999      6  0.0065 :        if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
15000                :            prgnSrcClip = fbGetCompositeClip(pGC);
15001                :        else
15002                :            fastSrc = TRUE;
15003                :    }
15004                :    else
15005                :    {
15006                :        if (pGC->subWindowMode == IncludeInferiors)
15007                :        {
15008                :            /*
15009                :             * XFree86 DDX empties the border clip when the
15010                :             * VT is inactive, make sure the region isn't empty
15011                :             */
15012                :            if (!((WindowPtr) pSrcDrawable)->parent &&
15013                :                REGION_NOTEMPTY (pSrcDrawable->pScreen,
15014                :                                 &((WindowPtr) pSrcDrawable)->borderClip))
15015                :            {
15016                :                /*
15017                :                 * special case bitblt from root window in
15018                :                 * IncludeInferiors mode; just like from a pixmap
15019                :                 */
15020                :                fastSrc = TRUE;
15021                :            }
15022                :            else if ((pSrcDrawable == pDstDrawable) &&
15023                :                     (pGC->clientClipType == CT_NONE))
15024                :            {
15025                :                prgnSrcClip = fbGetCompositeClip(pGC);
15026                :            }
15027                :            else
15028                :            {
15029                :                prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
15030                :                freeSrcClip = TRUE;
15031                :            }
15032                :        }
15033                :        else
15034                :        {
15035                :            prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
15036                :        }
15037                :    }
15038                :
15039                :    xIn += pSrcDrawable->x;
15040      2  0.0022 :    yIn += pSrcDrawable->y;
15041                :    
15042      1  0.0011 :    xOut += pDstDrawable->x;
15043      2  0.0022 :    yOut += pDstDrawable->y;
15044                :
15045                :    box_x1 = xIn;
15046                :    box_y1 = yIn;
15047                :    box_x2 = xIn + widthSrc;
15048      2  0.0022 :    box_y2 = yIn + heightSrc;
15049                :
15050      2  0.0022 :    dx = xIn - xOut;
15051      4  0.0044 :    dy = yIn - yOut;
15052                :
15053                :    /* Don't create a source region if we are doing a fast clip */
15054      3  0.0033 :    if (fastSrc)
15055                :    {
15056                :        RegionPtr cclip;
15057                :    
15058                :        fastExpose = TRUE;
15059                :        /*
15060                :         * clip the source; if regions extend beyond the source size,
15061                :         * make sure exposure events get sent
15062                :         */
15063      4  0.0044 :        if (box_x1 < pSrcDrawable->x)
15064                :        {
15065                :            box_x1 = pSrcDrawable->x;
15066                :            fastExpose = FALSE;
15067                :        }
15068                :        if (box_y1 < pSrcDrawable->y)
15069                :        {
15070                :            box_y1 = pSrcDrawable->y;
15071                :            fastExpose = FALSE;
15072                :        }
15073      7  0.0076 :        if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
15074                :        {
15075                :            box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
15076                :            fastExpose = FALSE;
15077                :        }
15078      4  0.0044 :        if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
15079                :        {
15080                :            box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
15081                :            fastExpose = FALSE;
15082                :        }
15083                :        
15084                :        /* Translate and clip the dst to the destination composite clip */
15085                :        box_x1 -= dx;
15086                :        box_x2 -= dx;
15087      1  0.0011 :        box_y1 -= dy;
15088      1  0.0011 :        box_y2 -= dy;
15089                :
15090                :        /* If the destination composite clip is one rectangle we can
15091                :           do the clip directly.  Otherwise we have to create a full
15092                :           blown region and call intersect */
15093                :
15094      1  0.0011 :        cclip = fbGetCompositeClip(pGC);
15095      2  0.0022 :        if (REGION_NUM_RECTS(cclip) == 1)
15096                :        {
15097      9  0.0098 :            BoxPtr pBox = REGION_RECTS(cclip);
15098                :
15099                :            if (box_x1 < pBox->x1) box_x1 = pBox->x1;
15100                :            if (box_x2 > pBox->x2) box_x2 = pBox->x2;
15101                :            if (box_y1 < pBox->y1) box_y1 = pBox->y1;
15102      1  0.0011 :            if (box_y2 > pBox->y2) box_y2 = pBox->y2;
15103                :            fastDst = TRUE;
15104                :        }
15105                :    }
15106                :    
15107                :    /* Check to see if the region is empty */
15108      2  0.0022 :    if (box_x1 >= box_x2 || box_y1 >= box_y2)
15109                :    {
15110      3  0.0033 :        REGION_NULL(pGC->pScreen, &rgnDst);
15111                :    }
15112                :    else
15113                :    {
15114                :        BoxRec  box;
15115                :        box.x1 = box_x1;
15116                :        box.y1 = box_y1;
15117                :        box.x2 = box_x2;
15118                :        box.y2 = box_y2;
15119                :        REGION_INIT(pGC->pScreen, &rgnDst, &box, 1);
15120                :    }
15121                :    
15122                :    /* Clip against complex source if needed */
15123      2  0.0022 :    if (!fastSrc)
15124                :    {
15125                :        REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
15126                :        REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
15127                :    }
15128                :
15129                :    /* Clip against complex dest if needed */
15130      1  0.0011 :    if (!fastDst)
15131                :    {
15132                :        REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst,
15133                :                         fbGetCompositeClip(pGC));
15134                :    }
15135                :
15136                :    /* Do bit blitting */
15137                :    numRects = REGION_NUM_RECTS(&rgnDst);
15138      1  0.0011 :    if (numRects && widthSrc && heightSrc)
15139     16  0.0174 :        fbCopyRegion (pSrcDrawable, pDstDrawable, pGC,
15140                :                      &rgnDst, dx, dy, copyProc, bitPlane, closure);
15141                :
15142                :    /* Pixmap sources generate a NoExposed (we return NULL to do this) */
15143                :    if (!fastExpose && pGC->fExpose)
15144                :        prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
15145                :                                        xIn - pSrcDrawable->x,
15146                :                                        yIn - pSrcDrawable->y,
15147                :                                        widthSrc, heightSrc,
15148                :                                        xOut - pDstDrawable->x,
15149                :                                        yOut - pDstDrawable->y,
15150                :                                        (unsigned long) bitPlane);
15151                :    REGION_UNINIT(pGC->pScreen, &rgnDst);
15152      1  0.0011 :    if (freeSrcClip)
15153                :        REGION_DESTROY(pGC->pScreen, prgnSrcClip);
15154                :    fbValidateDrawable (pDstDrawable);
15155                :    return prgnExposed;
15156      5  0.0054 :}
15157                :
15158                :RegionPtr
15159                :fbCopyArea (DrawablePtr pSrcDrawable,
15160                :            DrawablePtr pDstDrawable,
15161                :            GCPtr       pGC,
15162                :            int         xIn, 
15163                :            int         yIn,
15164                :            int         widthSrc, 
15165                :            int         heightSrc,
15166                :            int         xOut, 
15167                :            int         yOut)
15168                :{
15169                :    fbCopyProc  copy;
15170                :
15171                :#ifdef FB_24_32BIT
15172                :    if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
15173                :        copy = fb24_32CopyMtoN;
15174                :    else
15175                :#endif
15176                :        copy = fbCopyNtoN;
15177                :    return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
15178                :                     widthSrc, heightSrc, xOut, yOut, copy, 0, 0);
15179                :}
15180                :
15181                :RegionPtr
15182                :fbCopyPlane (DrawablePtr    pSrcDrawable,
15183                :             DrawablePtr    pDstDrawable,
15184                :             GCPtr          pGC,
15185                :             int            xIn, 
15186                :             int            yIn,
15187                :             int            widthSrc, 
15188                :             int            heightSrc,
15189                :             int            xOut, 
15190                :             int            yOut,
15191                :             unsigned long  bitplane)
15192                :{
15193                :    if (pSrcDrawable->bitsPerPixel > 1)
15194                :        return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
15195                :                         xIn, yIn, widthSrc, heightSrc,
15196                :                         xOut, yOut, fbCopyNto1, (Pixel) bitplane, 0);
15197                :    else if (bitplane & 1)
15198                :        return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
15199                :                         widthSrc, heightSrc, xOut, yOut, fbCopy1toN,
15200                :                         (Pixel) bitplane, 0);
15201                :    else
15202                :        return miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
15203                :                                 xIn, yIn,
15204                :                                 widthSrc,
15205                :                                 heightSrc,
15206                :                                 xOut, yOut, bitplane);
15207                :}
15208 /* 
15209  * Total samples for file : "msort.c"
15210  * 
15211  *    125  0.1362
15212  */
15213
15214 <credited to line zero>    125  0.1362 :
15215  /* msort_with_tmp total:    125  0.1362 */
15216 /* 
15217  * Total samples for file : "i810_hwmc.c"
15218  * 
15219  *    119  0.1296
15220  */
15221
15222 <credited to line zero>    119  0.1296 :
15223  /* __i686.get_pc_thunk.bx total:    119  0.1296 */
15224 /* 
15225  * Total samples for file : "/home/cworth/src/xorg/xserver/dix/resource.c"
15226  * 
15227  *    117  0.1275
15228  */
15229
15230
15231                :/************************************************************
15232                :
15233                :Copyright 1987, 1998  The Open Group
15234                :
15235                :Permission to use, copy, modify, distribute, and sell this software and its
15236                :documentation for any purpose is hereby granted without fee, provided that
15237                :the above copyright notice appear in all copies and that both that
15238                :copyright notice and this permission notice appear in supporting
15239                :documentation.
15240                :
15241                :The above copyright notice and this permission notice shall be included in
15242                :all copies or substantial portions of the Software.
15243                :
15244                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15245                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15246                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
15247                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15248                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
15249                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15250                :
15251                :Except as contained in this notice, the name of The Open Group shall not be
15252                :used in advertising or otherwise to promote the sale, use or other dealings
15253                :in this Software without prior written authorization from The Open Group.
15254                :
15255                :
15256                :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
15257                :
15258                :                        All Rights Reserved
15259                :
15260                :Permission to use, copy, modify, and distribute this software and its 
15261                :documentation for any purpose and without fee is hereby granted, 
15262                :provided that the above copyright notice appear in all copies and that
15263                :both that copyright notice and this permission notice appear in 
15264                :supporting documentation, and that the name of Digital not be
15265                :used in advertising or publicity pertaining to distribution of the
15266                :software without specific, written prior permission.  
15267                :
15268                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15269                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
15270                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
15271                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
15272                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
15273                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15274                :SOFTWARE.
15275                :
15276                :********************************************************/
15277                :/* The panoramix components contained the following notice */
15278                :/*****************************************************************
15279                :
15280                :Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
15281                :
15282                :Permission is hereby granted, free of charge, to any person obtaining a copy
15283                :of this software and associated documentation files (the "Software"), to deal
15284                :in the Software without restriction, including without limitation the rights
15285                :to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15286                :copies of the Software.
15287                :
15288                :The above copyright notice and this permission notice shall be included in
15289                :all copies or substantial portions of the Software.
15290                :
15291                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15292                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15293                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
15294                :DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
15295                :BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
15296                :WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
15297                :IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15298                :
15299                :Except as contained in this notice, the name of Digital Equipment Corporation
15300                :shall not be used in advertising or otherwise to promote the sale, use or other
15301                :dealings in this Software without prior written authorization from Digital
15302                :Equipment Corporation.
15303                :
15304                :******************************************************************/
15305                :/* XSERVER_DTRACE additions:
15306                : * Copyright 2005-2006 Sun Microsystems, Inc.  All rights reserved.
15307                : *
15308                : * Permission is hereby granted, free of charge, to any person obtaining a
15309                : * copy of this software and associated documentation files (the
15310                : * "Software"), to deal in the Software without restriction, including
15311                : * without limitation the rights to use, copy, modify, merge, publish,
15312                : * distribute, and/or sell copies of the Software, and to permit persons
15313                : * to whom the Software is furnished to do so, provided that the above
15314                : * copyright notice(s) and this permission notice appear in all copies of
15315                : * the Software and that both the above copyright notice(s) and this
15316                : * permission notice appear in supporting documentation.
15317                : * 
15318                : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15319                : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15320                : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
15321                : * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
15322                : * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
15323                : * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
15324                : * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15325                : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15326                : * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15327                : * 
15328                : * Except as contained in this notice, the name of a copyright holder
15329                : * shall not be used in advertising or otherwise to promote the sale, use
15330                : * or other dealings in this Software without prior written authorization
15331                : * of the copyright holder.
15332                : */
15333                :
15334                :/*      Routines to manage various kinds of resources:
15335                : *
15336                : *      CreateNewResourceType, CreateNewResourceClass, InitClientResources,
15337                : *      FakeClientID, AddResource, FreeResource, FreeClientResources,
15338                : *      FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange
15339                : */
15340                :
15341                :/* 
15342                : *      A resource ID is a 32 bit quantity, the upper 2 bits of which are
15343                : *      off-limits for client-visible resources.  The next 8 bits are
15344                : *      used as client ID, and the low 22 bits come from the client.
15345                : *      A resource ID is "hashed" by extracting and xoring subfields
15346                : *      (varying with the size of the hash table).
15347                : *
15348                : *      It is sometimes necessary for the server to create an ID that looks
15349                : *      like it belongs to a client.  This ID, however,  must not be one
15350                : *      the client actually can create, or we have the potential for conflict.
15351                : *      The 31st bit of the ID is reserved for the server's use for this
15352                : *      purpose.  By setting CLIENT_ID(id) to the client, the SERVER_BIT to
15353                : *      1, and an otherwise arbitrary ID in the low 22 bits, we can create a
15354                : *      resource "owned" by the client.
15355                : */
15356                :
15357                :#define NEED_EVENTS
15358                :#ifdef HAVE_DIX_CONFIG_H
15359                :#include <dix-config.h>
15360                :#endif
15361                :
15362                :#include <X11/X.h>
15363                :#include "misc.h"
15364                :#include "os.h"
15365                :#include "resource.h"
15366                :#include "dixstruct.h" 
15367                :#include "opaque.h"
15368                :#include "windowstr.h"
15369                :#include "dixfont.h"
15370                :#include "colormap.h"
15371                :#include "inputstr.h"
15372                :#include "dixevents.h"
15373                :#include "dixgrabs.h"
15374                :#include "cursor.h"
15375                :#ifdef PANORAMIX
15376                :#include "panoramiX.h"
15377                :#include "panoramiXsrv.h"
15378                :#endif
15379                :#include "xace.h"
15380                :#include <assert.h>
15381                :
15382                :#ifdef XSERVER_DTRACE
15383                :#include <sys/types.h>
15384                :typedef const char *string;
15385                :#include "Xserver-dtrace.h"
15386                :
15387                :#define TypeNameString(t) NameForAtom(ResourceNames[t & TypeMask])
15388                :#endif
15389                :
15390                :static void RebuildTable(
15391                :    int /*client*/
15392                :);
15393                :
15394                :#define SERVER_MINID 32
15395                :
15396                :#define INITBUCKETS 64
15397                :#define INITHASHSIZE 6
15398                :#define MAXHASHSIZE 11
15399                :
15400                :typedef struct _Resource {
15401                :    struct _Resource    *next;
15402                :    XID                 id;
15403                :    RESTYPE             type;
15404                :    pointer             value;
15405                :} ResourceRec, *ResourcePtr;
15406                :#define NullResource ((ResourcePtr)NULL)
15407                :
15408                :typedef struct _ClientResource {
15409                :    ResourcePtr *resources;
15410                :    int         elements;
15411                :    int         buckets;
15412                :    int         hashsize;       /* log(2)(buckets) */
15413                :    XID         fakeID;
15414                :    XID         endFakeID;
15415                :    XID         expectID;
15416                :} ClientResourceRec;
15417                :
15418                :_X_EXPORT RESTYPE lastResourceType;
15419                :static RESTYPE lastResourceClass;
15420                :_X_EXPORT RESTYPE TypeMask;
15421                :
15422                :static DeleteType *DeleteFuncs = (DeleteType *)NULL;
15423                :
15424                :#ifdef XResExtension
15425                :
15426                :_X_EXPORT Atom * ResourceNames = NULL;
15427                :
15428                :_X_EXPORT void RegisterResourceName (RESTYPE type, char *name)
15429                :{
15430                :    ResourceNames[type & TypeMask] =  MakeAtom(name, strlen(name), TRUE);
15431                :}
15432                :
15433                :#endif
15434                :
15435                :_X_EXPORT RESTYPE
15436                :CreateNewResourceType(DeleteType deleteFunc)
15437                :{
15438                :    RESTYPE next = lastResourceType + 1;
15439                :    DeleteType *funcs;
15440                :
15441                :    if (next & lastResourceClass)
15442                :        return 0;
15443                :    funcs = (DeleteType *)xrealloc(DeleteFuncs,
15444                :                                   (next + 1) * sizeof(DeleteType));
15445                :    if (!funcs)
15446                :        return 0;
15447                :
15448                :#ifdef XResExtension
15449                :    {
15450                :       Atom *newnames;
15451                :       newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom));
15452                :       if(!newnames)
15453                :           return 0;
15454                :       ResourceNames = newnames;
15455                :       ResourceNames[next] = 0;
15456                :    }
15457                :#endif
15458                :
15459                :    lastResourceType = next;
15460                :    DeleteFuncs = funcs;
15461                :    DeleteFuncs[next] = deleteFunc;
15462                :    return next;
15463                :}
15464                :
15465                :_X_EXPORT RESTYPE
15466                :CreateNewResourceClass(void)
15467                :{
15468                :    RESTYPE next = lastResourceClass >> 1;
15469                :
15470                :    if (next & lastResourceType)
15471                :        return 0;
15472                :    lastResourceClass = next;
15473                :    TypeMask = next - 1;
15474                :    return next;
15475                :}
15476                :
15477                :static ClientResourceRec clientTable[MAXCLIENTS];
15478                :
15479                :/*****************
15480                : * InitClientResources
15481                : *    When a new client is created, call this to allocate space
15482                : *    in resource table
15483                : *****************/
15484                :
15485                :Bool
15486                :InitClientResources(ClientPtr client)
15487                :{
15488                :    int i, j;
15489                : 
15490                :    if (client == serverClient)
15491                :    {
15492                :        lastResourceType = RT_LASTPREDEF;
15493                :        lastResourceClass = RC_LASTPREDEF;
15494                :        TypeMask = RC_LASTPREDEF - 1;
15495                :        if (DeleteFuncs)
15496                :            xfree(DeleteFuncs);
15497                :        DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) *
15498                :                                           sizeof(DeleteType));
15499                :        if (!DeleteFuncs)
15500                :            return FALSE;
15501                :        DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA;
15502                :        DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow;
15503                :        DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap;
15504                :        DeleteFuncs[RT_GC & TypeMask] = FreeGC;
15505                :        DeleteFuncs[RT_FONT & TypeMask] = CloseFont;
15506                :        DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor;
15507                :        DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap;
15508                :        DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels;
15509                :        DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone;
15510                :        DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab;
15511                :
15512                :#ifdef XResExtension
15513                :        if(ResourceNames)
15514                :            xfree(ResourceNames);
15515                :        ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom));
15516                :        if(!ResourceNames)
15517                :           return FALSE;
15518                :#endif
15519                :    }
15520                :    clientTable[i = client->index].resources =
15521                :        (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr));
15522                :    if (!clientTable[i].resources)
15523                :        return FALSE;
15524                :    clientTable[i].buckets = INITBUCKETS;
15525                :    clientTable[i].elements = 0;
15526                :    clientTable[i].hashsize = INITHASHSIZE;
15527                :    /* Many IDs allocated from the server client are visible to clients,
15528                :     * so we don't use the SERVER_BIT for them, but we have to start
15529                :     * past the magic value constants used in the protocol.  For normal
15530                :     * clients, we can start from zero, with SERVER_BIT set.
15531                :     */
15532                :    clientTable[i].fakeID = client->clientAsMask |
15533                :                            (client->index ? SERVER_BIT : SERVER_MINID);
15534                :    clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1;
15535                :    clientTable[i].expectID = client->clientAsMask;
15536                :    for (j=0; j<INITBUCKETS; j++) 
15537                :    {
15538                :        clientTable[i].resources[j] = NullResource;
15539                :    }
15540                :    return TRUE;
15541                :}
15542                :
15543                :
15544                :static int
15545                :Hash(int client, XID id)
15546      7  0.0076 :{ /* Hash total:     27  0.0294 */
15547      3  0.0033 :    id &= RESOURCE_ID_MASK;
15548      9  0.0098 :    switch (clientTable[client].hashsize)
15549                :    {
15550                :        case 6:
15551      2  0.0022 :            return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));
15552                :        case 7:
15553      6  0.0065 :            return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));
15554                :        case 8:
15555                :            return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));
15556                :        case 9:
15557                :            return ((int)(0x1FF & (id ^ (id>>9))));
15558                :        case 10:
15559                :            return ((int)(0x3FF & (id ^ (id>>10))));
15560                :        case 11:
15561                :            return ((int)(0x7FF & (id ^ (id>>11))));
15562                :    }
15563                :    return -1;
15564                :}
15565                :
15566                :static XID
15567                :AvailableID(
15568                :    int client,
15569                :    XID id,
15570                :    XID maxid,
15571                :    XID goodid)
15572                :{
15573                :    ResourcePtr res;
15574                :
15575                :    if ((goodid >= id) && (goodid <= maxid))
15576                :        return goodid;
15577                :    for (; id <= maxid; id++)
15578                :    {
15579                :        res = clientTable[client].resources[Hash(client, id)];
15580                :        while (res && (res->id != id))
15581                :            res = res->next;
15582                :        if (!res)
15583                :            return id;
15584                :    }
15585                :    return 0;
15586                :}
15587                :
15588                :_X_EXPORT void
15589                :GetXIDRange(int client, Bool server, XID *minp, XID *maxp)
15590                :{
15591                :    XID id, maxid;
15592                :    ResourcePtr *resp;
15593                :    ResourcePtr res;
15594                :    int i;
15595                :    XID goodid;
15596                :
15597                :    id = (Mask)client << CLIENTOFFSET;
15598                :    if (server)
15599                :        id |= client ? SERVER_BIT : SERVER_MINID;
15600                :    maxid = id | RESOURCE_ID_MASK;
15601                :    goodid = 0;
15602                :    for (resp = clientTable[client].resources, i = clientTable[client].buckets;
15603                :         --i >= 0;)
15604                :    {
15605                :        for (res = *resp++; res; res = res->next)
15606                :        {
15607                :            if ((res->id < id) || (res->id > maxid))
15608                :                continue;
15609                :            if (((res->id - id) >= (maxid - res->id)) ?
15610                :                (goodid = AvailableID(client, id, res->id - 1, goodid)) :
15611                :                !(goodid = AvailableID(client, res->id + 1, maxid, goodid)))
15612                :                maxid = res->id - 1;
15613                :            else
15614                :                id = res->id + 1;
15615                :        }
15616                :    }
15617                :    if (id > maxid)
15618                :        id = maxid = 0;
15619                :    *minp = id;
15620                :    *maxp = maxid;
15621                :}
15622                :
15623                :/**
15624                : *  GetXIDList is called by the XC-MISC extension's MiscGetXIDList function.
15625                : *  This function tries to find count unused XIDs for the given client.  It 
15626                : *  puts the IDs in the array pids and returns the number found, which should
15627                : *  almost always be the number requested.
15628                : *
15629                : *  The circumstances that lead to a call to this function are very rare.
15630                : *  Xlib must run out of IDs while trying to generate a request that wants
15631                : *  multiple ID's, like the Multi-buffering CreateImageBuffers request.
15632                : *
15633                : *  No rocket science in the implementation; just iterate over all
15634                : *  possible IDs for the given client and pick the first count IDs
15635                : *  that aren't in use.  A more efficient algorithm could probably be
15636                : *  invented, but this will be used so rarely that this should suffice.
15637                : */
15638                :
15639                :_X_EXPORT unsigned int
15640                :GetXIDList(ClientPtr pClient, unsigned count, XID *pids)
15641                :{
15642                :    unsigned int found = 0;
15643                :    XID id = pClient->clientAsMask;
15644                :    XID maxid;
15645                :
15646                :    maxid = id | RESOURCE_ID_MASK;
15647                :    while ( (found < count) && (id <= maxid) )
15648                :    {
15649                :        if (!LookupIDByClass(id, RC_ANY))
15650                :        {
15651                :            pids[found++] = id;
15652                :        }
15653                :        id++;
15654                :    }
15655                :    return found;
15656                :}
15657                :
15658                :/*
15659                : * Return the next usable fake client ID.
15660                : *
15661                : * Normally this is just the next one in line, but if we've used the last
15662                : * in the range, we need to find a new range of safe IDs to avoid
15663                : * over-running another client.
15664                : */
15665                :
15666                :_X_EXPORT XID
15667                :FakeClientID(int client)
15668                :{
15669                :    XID id, maxid;
15670                :
15671                :    id = clientTable[client].fakeID++;
15672                :    if (id != clientTable[client].endFakeID)
15673                :        return id;
15674                :    GetXIDRange(client, TRUE, &id, &maxid);
15675                :    if (!id) {
15676                :        if (!client)
15677                :            FatalError("FakeClientID: server internal ids exhausted\n");
15678                :        MarkClientException(clients[client]);
15679                :        id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3);
15680                :        maxid = id | RESOURCE_ID_MASK;
15681                :    }
15682                :    clientTable[client].fakeID = id + 1;
15683                :    clientTable[client].endFakeID = maxid + 1;
15684                :    return id;
15685                :}
15686                :
15687                :_X_EXPORT Bool
15688                :AddResource(XID id, RESTYPE type, pointer value)
15689      2  0.0022 :{ /* AddResource total:      8  0.0087 */
15690                :    int client;
15691                :    ClientResourceRec *rrec;
15692                :    ResourcePtr res, *head;
15693                :        
15694                :#ifdef XSERVER_DTRACE
15695                :    XSERVER_RESOURCE_ALLOC(id, type, value, TypeNameString(type));
15696                :#endif
15697                :    client = CLIENT_ID(id);
15698      1  0.0011 :    rrec = &clientTable[client];
15699      1  0.0011 :    if (!rrec->buckets)
15700                :    {
15701                :        ErrorF("AddResource(%lx, %lx, %lx), client=%d \n",
15702                :                (unsigned long)id, type, (unsigned long)value, client);
15703                :        FatalError("client not in use\n");
15704                :    }
15705                :    if ((rrec->elements >= 4*rrec->buckets) &&
15706                :        (rrec->hashsize < MAXHASHSIZE))
15707                :        RebuildTable(client);
15708                :    head = &rrec->resources[Hash(client, id)];
15709                :    res = (ResourcePtr)xalloc(sizeof(ResourceRec));
15710                :    if (!res)
15711                :    {
15712                :        (*DeleteFuncs[type & TypeMask])(value, id);
15713                :        return FALSE;
15714                :    }
15715      1  0.0011 :    res->next = *head;
15716                :    res->id = id;
15717                :    res->type = type;
15718      1  0.0011 :    res->value = value;
15719                :    *head = res;
15720                :    rrec->elements++;
15721      2  0.0022 :    if (!(id & SERVER_BIT) && (id >= rrec->expectID))
15722                :        rrec->expectID = id + 1;
15723                :    return TRUE;
15724                :}
15725                :
15726                :static void
15727                :RebuildTable(int client)
15728                :{
15729                :    int j;
15730                :    ResourcePtr res, next;
15731                :    ResourcePtr **tails, *resources;
15732                :    ResourcePtr **tptr, *rptr;
15733                :
15734                :    /*
15735                :     * For now, preserve insertion order, since some ddx layers depend
15736                :     * on resources being free in the opposite order they are added.
15737                :     */
15738                :
15739                :    j = 2 * clientTable[client].buckets;
15740                :    tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *));
15741                :    if (!tails)
15742                :        return;
15743                :    resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr));
15744                :    if (!resources)
15745                :    {
15746                :        DEALLOCATE_LOCAL(tails);
15747                :        return;
15748                :    }
15749                :    for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++)
15750                :    {
15751                :        *rptr = NullResource;
15752                :        *tptr = rptr;
15753                :    }
15754                :    clientTable[client].hashsize++;
15755                :    for (j = clientTable[client].buckets,
15756                :         rptr = clientTable[client].resources;
15757                :         --j >= 0;
15758                :         rptr++)
15759                :    {
15760                :        for (res = *rptr; res; res = next)
15761                :        {
15762                :            next = res->next;
15763                :            res->next = NullResource;
15764                :            tptr = &tails[Hash(client, res->id)];
15765                :            **tptr = res;
15766                :            *tptr = &res->next;
15767                :        }
15768                :    }
15769                :    DEALLOCATE_LOCAL(tails);
15770                :    clientTable[client].buckets *= 2;
15771                :    xfree(clientTable[client].resources);
15772                :    clientTable[client].resources = resources;
15773                :}
15774                :
15775                :_X_EXPORT void
15776                :FreeResource(XID id, RESTYPE skipDeleteFuncType)
15777      1  0.0011 :{ /* FreeResource total:     27  0.0294 */
15778                :    int         cid;
15779                :    ResourcePtr res;
15780                :    ResourcePtr *prev, *head;
15781                :    int *eltptr;
15782                :    int         elements;
15783                :    Bool        gotOne = FALSE;
15784                :
15785      1  0.0011 :    if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
15786                :    {
15787                :        head = &clientTable[cid].resources[Hash(cid, id)];
15788                :        eltptr = &clientTable[cid].elements;
15789                :
15790                :        prev = head;
15791      2  0.0022 :        while ( (res = *prev) )
15792                :        {
15793      2  0.0022 :            if (res->id == id)
15794                :            {
15795                :                RESTYPE rtype = res->type;
15796                :
15797                :#ifdef XSERVER_DTRACE
15798                :                XSERVER_RESOURCE_FREE(res->id, res->type,
15799                :                              res->value, TypeNameString(res->type));
15800                :#endif              
15801                :                *prev = res->next;
15802                :                elements = --*eltptr;
15803                :                if (rtype & RC_CACHED)
15804      1  0.0011 :                    FlushClientCaches(res->id);
15805      1  0.0011 :                if (rtype != skipDeleteFuncType)
15806      6  0.0065 :                    (*DeleteFuncs[rtype & TypeMask])(res->value, res->id);
15807      1  0.0011 :                xfree(res);
15808                :                if (*eltptr != elements)
15809                :                    prev = head; /* prev may no longer be valid */
15810                :                gotOne = TRUE;
15811                :            }
15812                :            else
15813     11  0.0120 :                prev = &res->next;
15814                :        }
15815      1  0.0011 :        if(clients[cid] && (id == clients[cid]->lastDrawableID))
15816                :        {
15817                :            clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0];
15818                :            clients[cid]->lastDrawableID = WindowTable[0]->drawable.id;
15819                :        }
15820                :    }
15821                :    if (!gotOne)
15822                :        ErrorF("Freeing resource id=%lX which isn't there.\n",
15823                :                   (unsigned long)id);
15824                :}
15825                :
15826                :
15827                :_X_EXPORT void
15828                :FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
15829                :{
15830                :    int         cid;
15831                :    ResourcePtr res;
15832                :    ResourcePtr *prev, *head;
15833                :    if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
15834                :    {
15835                :        head = &clientTable[cid].resources[Hash(cid, id)];
15836                :
15837                :        prev = head;
15838                :        while ( (res = *prev) )
15839                :        {
15840                :            if (res->id == id && res->type == type)
15841                :            {
15842                :#ifdef XSERVER_DTRACE
15843                :                XSERVER_RESOURCE_FREE(res->id, res->type,
15844                :                              res->value, TypeNameString(res->type));
15845                :#endif                              
15846                :                *prev = res->next;
15847                :                if (type & RC_CACHED)
15848                :                    FlushClientCaches(res->id);
15849                :                if (!skipFree)
15850                :                    (*DeleteFuncs[type & TypeMask])(res->value, res->id);
15851                :                xfree(res);
15852                :                break;
15853                :            }
15854                :            else
15855                :                prev = &res->next;
15856                :        }
15857                :        if(clients[cid] && (id == clients[cid]->lastDrawableID))
15858                :        {
15859                :            clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0];
15860                :            clients[cid]->lastDrawableID = WindowTable[0]->drawable.id;
15861                :        }
15862                :    }
15863                :}
15864                :
15865                :/*
15866                : * Change the value associated with a resource id.  Caller
15867                : * is responsible for "doing the right thing" with the old
15868                : * data
15869                : */
15870                :
15871                :_X_EXPORT Bool
15872                :ChangeResourceValue (XID id, RESTYPE rtype, pointer value)
15873                :{
15874                :    int    cid;
15875                :    ResourcePtr res;
15876                :
15877                :    if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
15878                :    {
15879                :        res = clientTable[cid].resources[Hash(cid, id)];
15880                :
15881                :        for (; res; res = res->next)
15882                :            if ((res->id == id) && (res->type == rtype))
15883                :            {
15884                :                if (rtype & RC_CACHED)
15885                :                    FlushClientCaches(res->id);
15886                :                res->value = value;
15887                :                return TRUE;
15888                :            }
15889                :    }
15890                :    return FALSE;
15891                :}
15892                :
15893                :/* Note: if func adds or deletes resources, then func can get called
15894                : * more than once for some resources.  If func adds new resources,
15895                : * func might or might not get called for them.  func cannot both
15896                : * add and delete an equal number of resources!
15897                : */
15898                :
15899                :_X_EXPORT void
15900                :FindClientResourcesByType(
15901                :    ClientPtr client,
15902                :    RESTYPE type,
15903                :    FindResType func,
15904                :    pointer cdata
15905                :){
15906                :    ResourcePtr *resources;
15907                :    ResourcePtr this, next;
15908                :    int i, elements;
15909                :    int *eltptr;
15910                :
15911                :    if (!client)
15912                :        client = serverClient;
15913                :
15914                :    resources = clientTable[client->index].resources;
15915                :    eltptr = &clientTable[client->index].elements;
15916                :    for (i = 0; i < clientTable[client->index].buckets; i++) 
15917                :    {
15918                :        for (this = resources[i]; this; this = next)
15919                :        {
15920                :            next = this->next;
15921                :            if (!type || this->type == type) {
15922                :                elements = *eltptr;
15923                :                (*func)(this->value, this->id, cdata);
15924                :                if (*eltptr != elements)
15925                :                    next = resources[i]; /* start over */
15926                :            }
15927                :        }
15928                :    }
15929                :}
15930                :
15931                :_X_EXPORT void
15932                :FindAllClientResources(
15933                :    ClientPtr client,
15934                :    FindAllRes func,
15935                :    pointer cdata
15936                :){
15937                :    ResourcePtr *resources;
15938                :    ResourcePtr this, next;
15939                :    int i, elements;
15940                :    int *eltptr;
15941                :
15942                :    if (!client)
15943                :        client = serverClient;
15944                :
15945                :    resources = clientTable[client->index].resources;
15946                :    eltptr = &clientTable[client->index].elements;
15947                :    for (i = 0; i < clientTable[client->index].buckets; i++)
15948                :    {
15949                :        for (this = resources[i]; this; this = next)
15950                :        {
15951                :            next = this->next;
15952                :            elements = *eltptr;
15953                :            (*func)(this->value, this->id, this->type, cdata);
15954                :            if (*eltptr != elements)
15955                :                next = resources[i]; /* start over */
15956                :        }
15957                :    }
15958                :}
15959                :
15960                :
15961                :pointer
15962                :LookupClientResourceComplex(
15963                :    ClientPtr client,
15964                :    RESTYPE type,
15965                :    FindComplexResType func,
15966                :    pointer cdata
15967                :){
15968                :    ResourcePtr *resources;
15969                :    ResourcePtr this;
15970                :    int i;
15971                :
15972                :    if (!client)
15973                :        client = serverClient;
15974                :
15975                :    resources = clientTable[client->index].resources;
15976                :    for (i = 0; i < clientTable[client->index].buckets; i++) {
15977                :        for (this = resources[i]; this; this = this->next) {
15978                :            if (!type || this->type == type) {
15979                :                if((*func)(this->value, this->id, cdata))
15980                :                    return this->value;
15981                :            }
15982                :        }
15983                :    }
15984                :    return NULL;
15985                :}
15986                :
15987                :
15988                :void
15989                :FreeClientNeverRetainResources(ClientPtr client)
15990                :{
15991                :    ResourcePtr *resources;
15992                :    ResourcePtr this;
15993                :    ResourcePtr *prev;
15994                :    int j;
15995                :
15996                :    if (!client)
15997                :        return;
15998                :
15999                :    resources = clientTable[client->index].resources;
16000                :    for (j=0; j < clientTable[client->index].buckets; j++) 
16001                :    {
16002                :        prev = &resources[j];
16003                :        while ( (this = *prev) )
16004                :        {
16005                :            RESTYPE rtype = this->type;
16006                :            if (rtype & RC_NEVERRETAIN)
16007                :            {
16008                :#ifdef XSERVER_DTRACE
16009                :                XSERVER_RESOURCE_FREE(this->id, this->type,
16010                :                              this->value, TypeNameString(this->type));
16011                :#endif              
16012                :                *prev = this->next;
16013                :                if (rtype & RC_CACHED)
16014                :                    FlushClientCaches(this->id);
16015                :                (*DeleteFuncs[rtype & TypeMask])(this->value, this->id);
16016                :                xfree(this);        
16017                :            }
16018                :            else
16019                :                prev = &this->next;
16020                :        }
16021                :    }
16022                :}
16023                :
16024                :void
16025                :FreeClientResources(ClientPtr client)
16026                :{
16027                :    ResourcePtr *resources;
16028                :    ResourcePtr this;
16029                :    int j;
16030                :
16031                :    /* This routine shouldn't be called with a null client, but just in
16032                :        case ... */
16033                :
16034                :    if (!client)
16035                :        return;
16036                :
16037                :    HandleSaveSet(client);
16038                :
16039                :    resources = clientTable[client->index].resources;
16040                :    for (j=0; j < clientTable[client->index].buckets; j++) 
16041                :    {
16042                :        /* It may seem silly to update the head of this resource list as
16043                :        we delete the members, since the entire list will be deleted any way, 
16044                :        but there are some resource deletion functions "FreeClientPixels" for 
16045                :        one which do a LookupID on another resource id (a Colormap id in this
16046                :        case), so the resource list must be kept valid up to the point that
16047                :        it is deleted, so every time we delete a resource, we must update the
16048                :        head, just like in FreeResource. I hope that this doesn't slow down
16049                :        mass deletion appreciably. PRH */
16050                :
16051                :        ResourcePtr *head;
16052                :
16053                :        head = &resources[j];
16054                :
16055                :        for (this = *head; this; this = *head)
16056                :        {
16057                :            RESTYPE rtype = this->type;
16058                :#ifdef XSERVER_DTRACE
16059                :            XSERVER_RESOURCE_FREE(this->id, this->type,
16060                :                          this->value, TypeNameString(this->type));
16061                :#endif              
16062                :            *head = this->next;
16063                :            if (rtype & RC_CACHED)
16064                :                FlushClientCaches(this->id);
16065                :            (*DeleteFuncs[rtype & TypeMask])(this->value, this->id);
16066                :            xfree(this);            
16067                :        }
16068                :    }
16069                :    xfree(clientTable[client->index].resources);
16070                :    clientTable[client->index].resources = NULL;
16071                :    clientTable[client->index].buckets = 0;
16072                :}
16073                :
16074                :void
16075                :FreeAllResources(void)
16076                :{
16077                :    int i;
16078                :
16079                :    for (i = currentMaxClients; --i >= 0; ) 
16080                :    {
16081                :        if (clientTable[i].buckets) 
16082                :            FreeClientResources(clients[i]);
16083                :    }
16084                :}
16085                :
16086                :_X_EXPORT Bool
16087                :LegalNewID(XID id, ClientPtr client)
16088      3  0.0033 :{ /* LegalNewID total:      7  0.0076 */
16089                :
16090                :#ifdef PANORAMIX
16091                :    XID         minid, maxid;
16092                :
16093      2  0.0022 :        if (!noPanoramiXExtension) { 
16094                :            minid = client->clientAsMask | (client->index ? 
16095                :                                            SERVER_BIT : SERVER_MINID);
16096                :            maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1;
16097                :            if ((id >= minid) && (id <= maxid))
16098                :                return TRUE;
16099                :        }
16100                :#endif /* PANORAMIX */
16101      1  0.0011 :        return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) &&
16102                :            ((clientTable[client->index].expectID <= id) ||
16103                :             !LookupIDByClass(id, RC_ANY)));
16104      1  0.0011 :}
16105                :
16106                :/* SecurityLookupIDByType and SecurityLookupIDByClass:
16107                : * These are the heart of the resource ID security system.  They take
16108                : * two additional arguments compared to the old LookupID functions:
16109                : * the client doing the lookup, and the access mode (see resource.h).
16110                : * The resource is returned if it exists and the client is allowed access,
16111                : * else NULL is returned.
16112                : */
16113                :
16114                :_X_EXPORT pointer
16115                :SecurityLookupIDByType(ClientPtr client, XID id, RESTYPE rtype, Mask mode)
16116      8  0.0087 :{ /* SecurityLookupIDByType total:     40  0.0436 */
16117                :    int    cid;
16118                :    ResourcePtr res;
16119                :    pointer retval = NULL;
16120                :
16121     11  0.0120 :    if (((cid = CLIENT_ID(id)) < MAXCLIENTS) &&
16122                :        clientTable[cid].buckets)
16123                :    {
16124      2  0.0022 :        res = clientTable[cid].resources[Hash(cid, id)];
16125                :
16126      6  0.0065 :        for (; res; res = res->next)
16127      7  0.0076 :            if ((res->id == id) && (res->type == rtype))
16128                :            {
16129      1  0.0011 :                retval = res->value;
16130                :                break;
16131                :            }
16132                :    }
16133      4  0.0044 :    if (retval && client && 
16134                :        !XaceHook(XACE_RESOURCE_ACCESS, client, id, rtype, mode, retval))
16135                :        retval = NULL;
16136                :
16137                :    return retval;
16138      1  0.0011 :}
16139                :
16140                :
16141                :_X_EXPORT pointer
16142                :SecurityLookupIDByClass(ClientPtr client, XID id, RESTYPE classes, Mask mode)
16143      3  0.0033 :{ /* SecurityLookupIDByClass total:      8  0.0087 */
16144                :    int    cid;
16145                :    ResourcePtr res = NULL;
16146                :    pointer retval = NULL;
16147                :
16148      1  0.0011 :    if (((cid = CLIENT_ID(id)) < MAXCLIENTS) &&
16149                :        clientTable[cid].buckets)
16150                :    {
16151                :        res = clientTable[cid].resources[Hash(cid, id)];
16152                :
16153      1  0.0011 :        for (; res; res = res->next)
16154      2  0.0022 :            if ((res->id == id) && (res->type & classes))
16155                :            {
16156                :                retval = res->value;
16157                :                break;
16158                :            }
16159                :    }
16160                :    if (retval && client &&
16161                :        !XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type, mode, retval))
16162                :        retval = NULL;
16163                :
16164                :    return retval;
16165      1  0.0011 :}
16166                :
16167                :/* We can't replace the LookupIDByType and LookupIDByClass functions with
16168                : * macros because of compatibility with loadable servers.
16169                : */
16170                :
16171                :_X_EXPORT pointer
16172                :LookupIDByType(XID id, RESTYPE rtype)
16173                :{
16174                :    return SecurityLookupIDByType(NullClient, id, rtype,
16175                :                                  DixUnknownAccess);
16176                :}
16177                :
16178                :_X_EXPORT pointer
16179                :LookupIDByClass(XID id, RESTYPE classes)
16180                :{
16181                :    return SecurityLookupIDByClass(NullClient, id, classes,
16182                :                                   DixUnknownAccess);
16183                :}
16184 /* 
16185  * Total samples for file : "xkbKillSrv.c"
16186  * 
16187  *    111  0.1209
16188  */
16189
16190 <credited to line zero>    111  0.1209 :
16191  /* __i686.get_pc_thunk.cx total:      2  0.0022 */
16192  /* __i686.get_pc_thunk.bx total:     97  0.1057 */
16193  /* __divdi3 total:     12  0.0131 */
16194 /* 
16195  * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa_accel.c"
16196  * 
16197  *    109  0.1187
16198  */
16199
16200
16201                :/*
16202                : * Copyright Â© 2001 Keith Packard
16203                : *
16204                : * Partly based on code that is Copyright Â© The XFree86 Project Inc.
16205                : *
16206                : * Permission to use, copy, modify, distribute, and sell this software and its
16207                : * documentation for any purpose is hereby granted without fee, provided that
16208                : * the above copyright notice appear in all copies and that both that
16209                : * copyright notice and this permission notice appear in supporting
16210                : * documentation, and that the name of Keith Packard not be used in
16211                : * advertising or publicity pertaining to distribution of the software without
16212                : * specific, written prior permission.  Keith Packard makes no
16213                : * representations about the suitability of this software for any purpose.  It
16214                : * is provided "as is" without express or implied warranty.
16215                : *
16216                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16217                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16218                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
16219                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
16220                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16221                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16222                : * PERFORMANCE OF THIS SOFTWARE.
16223                : *
16224                : * Authors:
16225                : *    Eric Anholt <eric@anholt.net>
16226                : *    Michel Dänzer <michel@tungstengraphics.com>
16227                : *
16228                : */
16229                :
16230                :#ifdef HAVE_DIX_CONFIG_H
16231                :#include <dix-config.h>
16232                :#endif
16233                :#include "exa_priv.h"
16234                :#include <X11/fonts/fontstruct.h>
16235                :#include "dixfontstr.h"
16236                :#include "exa.h"
16237                :#include "cw.h"
16238                :
16239                :static void
16240                :exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
16241                :             DDXPointPtr ppt, int *pwidth, int fSorted)
16242                :{
16243                :    ScreenPtr       pScreen = pDrawable->pScreen;
16244                :    ExaScreenPriv (pScreen);
16245                :    RegionPtr       pClip = fbGetCompositeClip(pGC);
16246                :    PixmapPtr       pPixmap;
16247                :    BoxPtr          pextent, pbox;
16248                :    int             nbox;
16249                :    int             extentX1, extentX2, extentY1, extentY2;
16250                :    int             fullX1, fullX2, fullY1;
16251                :    int             partX1, partX2;
16252                :    int             off_x, off_y;
16253                :    ExaMigrationRec pixmaps[1];
16254                :
16255                :    pixmaps[0].as_dst = TRUE;
16256                :    pixmaps[0].as_src = FALSE;
16257                :    pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
16258                :
16259                :    if (pExaScr->swappedOut ||
16260                :        pGC->fillStyle != FillSolid ||
16261                :        pPixmap->drawable.width > pExaScr->info->maxX ||
16262                :        pPixmap->drawable.height > pExaScr->info->maxY)
16263                :    {
16264                :        exaDoMigration (pixmaps, 1, FALSE);
16265                :        ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
16266                :        return;
16267                :    } else {
16268                :        exaDoMigration (pixmaps, 1, TRUE);
16269                :    }
16270                :
16271                :    if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) ||
16272                :        !(*pExaScr->info->PrepareSolid) (pPixmap,
16273                :                                         pGC->alu,
16274                :                                         pGC->planemask,
16275                :                                         pGC->fgPixel))
16276                :    {
16277                :        exaDoMigration (pixmaps, 1, FALSE);
16278                :        ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
16279                :        return;
16280                :    }
16281                :
16282                :    pextent = REGION_EXTENTS(pGC->pScreen, pClip);
16283                :    extentX1 = pextent->x1;
16284                :    extentY1 = pextent->y1;
16285                :    extentX2 = pextent->x2;
16286                :    extentY2 = pextent->y2;
16287                :    while (n--)
16288                :    {
16289                :        fullX1 = ppt->x;
16290                :        fullY1 = ppt->y;
16291                :        fullX2 = fullX1 + (int) *pwidth;
16292                :        ppt++;
16293                :        pwidth++;
16294                :
16295                :        if (fullY1 < extentY1 || extentY2 <= fullY1)
16296                :            continue;
16297                :
16298                :        if (fullX1 < extentX1)
16299                :            fullX1 = extentX1;
16300                :
16301                :        if (fullX2 > extentX2)
16302                :            fullX2 = extentX2;
16303                :
16304                :        if (fullX1 >= fullX2)
16305                :            continue;
16306                :
16307                :        nbox = REGION_NUM_RECTS (pClip);
16308                :        if (nbox == 1)
16309                :        {
16310                :            (*pExaScr->info->Solid) (pPixmap,
16311                :                                     fullX1 + off_x, fullY1 + off_y,
16312                :                                     fullX2 + off_x, fullY1 + 1 + off_y);
16313                :        }
16314                :        else
16315                :        {
16316                :            pbox = REGION_RECTS(pClip);
16317                :            while(nbox--)
16318                :            {
16319                :                if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
16320                :                {
16321                :                    partX1 = pbox->x1;
16322                :                    if (partX1 < fullX1)
16323                :                        partX1 = fullX1;
16324                :                    partX2 = pbox->x2;
16325                :                    if (partX2 > fullX2)
16326                :                        partX2 = fullX2;
16327                :                    if (partX2 > partX1) {
16328                :                        (*pExaScr->info->Solid) (pPixmap,
16329                :                                                 partX1 + off_x, fullY1 + off_y,
16330                :                                                 partX2 + off_x, fullY1 + 1 + off_y);
16331                :                    }
16332                :                }
16333                :                pbox++;
16334                :            }
16335                :        }
16336                :    }
16337                :    (*pExaScr->info->DoneSolid) (pPixmap);
16338                :    exaMarkSync(pScreen);
16339                :}
16340                :
16341                :static void
16342                :exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
16343                :             int w, int h, int leftPad, int format, char *bits)
16344                :{
16345                :    ExaScreenPriv (pDrawable->pScreen);
16346                :    PixmapPtr pPix;
16347                :    ExaMigrationRec pixmaps[1];
16348                :    RegionPtr pClip;
16349                :    BoxPtr pbox;
16350                :    int nbox;
16351                :    int xoff, yoff;
16352                :    int src_stride, bpp = pDrawable->bitsPerPixel;
16353                :
16354                :    pixmaps[0].as_dst = TRUE;
16355                :    pixmaps[0].as_src = FALSE;
16356                :    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
16357                :
16358                :    /* Don't bother with under 8bpp, XYPixmaps. */
16359                :    if (format != ZPixmap || bpp < 8)
16360                :        goto migrate_and_fallback;
16361                :
16362                :    /* Only accelerate copies: no rop or planemask. */
16363                :    if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
16364                :        goto migrate_and_fallback;
16365                :
16366                :    if (pExaScr->swappedOut)
16367                :        goto fallback;
16368                :
16369                :    exaDoMigration (pixmaps, 1, TRUE);
16370                :
16371                :    if (pExaScr->info->UploadToScreen == NULL)
16372                :        goto fallback;
16373                :
16374                :    pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
16375                :
16376                :    if (pPix == NULL)
16377                :        goto fallback;
16378                :
16379                :    x += pDrawable->x;
16380                :    y += pDrawable->y;
16381                :
16382                :    pClip = fbGetCompositeClip(pGC);
16383                :    src_stride = PixmapBytePad(w, pDrawable->depth);
16384                :    for (nbox = REGION_NUM_RECTS(pClip),
16385                :         pbox = REGION_RECTS(pClip);
16386                :         nbox--;
16387                :         pbox++)
16388                :    {
16389                :        int x1 = x;
16390                :        int y1 = y;
16391                :        int x2 = x + w;
16392                :        int y2 = y + h;
16393                :        char *src;
16394                :        Bool ok;
16395                :
16396                :        if (x1 < pbox->x1)
16397                :            x1 = pbox->x1;
16398                :        if (y1 < pbox->y1)
16399                :            y1 = pbox->y1;
16400                :        if (x2 > pbox->x2)
16401                :            x2 = pbox->x2;
16402                :        if (y2 > pbox->y2)
16403                :            y2 = pbox->y2;
16404                :        if (x1 >= x2 || y1 >= y2)
16405                :            continue;
16406                :
16407                :        src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
16408                :        ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
16409                :                                           x2 - x1, y2 - y1, src, src_stride);
16410                :        /* If we fail to accelerate the upload, fall back to using unaccelerated
16411                :         * fb calls.
16412                :         */
16413                :        if (!ok) {
16414                :            FbStip *dst;
16415                :            FbStride dst_stride;
16416                :            int dstBpp;
16417                :            int dstXoff, dstYoff;
16418                :
16419                :            exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
16420                :
16421                :            fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
16422                :                              dstXoff, dstYoff);
16423                :
16424                :            fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
16425                :                      src_stride / sizeof(FbStip),
16426                :                      (x1 - x) * dstBpp,
16427                :                      dst + (y1 + dstYoff) * dst_stride,
16428                :                      dst_stride,
16429                :                      (x1 + dstXoff) * dstBpp,
16430                :                      (x2 - x1) * dstBpp,
16431                :                      y2 - y1,
16432                :                      GXcopy, FB_ALLONES, dstBpp);
16433                :
16434                :            exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
16435                :        }
16436                :
16437                :        exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff);
16438                :    }
16439                :
16440                :    return;
16441                :
16442                :migrate_and_fallback:
16443                :    exaDoMigration (pixmaps, 1, FALSE);
16444                :
16445                :fallback:
16446                :    ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
16447                :}
16448                :
16449                :static Bool inline
16450                :exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
16451                :                   GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
16452                :{
16453                :    ExaScreenPriv (pDstDrawable->pScreen);
16454                :    PixmapPtr pSrcPixmap, pDstPixmap;
16455                :    int src_off_x, src_off_y, dst_off_x, dst_off_y;
16456                :    int dirsetup;
16457                :
16458                :    /* Need to get both pixmaps to call the driver routines */
16459                :    pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y);
16460                :    pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y);
16461                :    if (!pSrcPixmap || !pDstPixmap)
16462                :        return FALSE;
16463                :
16464                :    /*
16465                :     * Now the case of a chip that only supports xdir = ydir = 1 or
16466                :     * xdir = ydir = -1, but we have xdir != ydir.
16467                :     */
16468                :    dirsetup = 0;       /* No direction set up yet. */
16469                :    for (; nbox; pbox++, nbox--) {
16470                :        if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
16471                :            /* Do a xdir = ydir = -1 blit instead. */
16472                :            if (dirsetup != -1) {
16473                :                if (dirsetup != 0)
16474                :                    pExaScr->info->DoneCopy(pDstPixmap);
16475                :                dirsetup = -1;
16476                :                if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
16477                :                                                   pDstPixmap,
16478                :                                                   -1, -1,
16479                :                                                   pGC ? pGC->alu : GXcopy,
16480                :                                                   pGC ? pGC->planemask :
16481                :                                                         FB_ALLONES))
16482                :                    return FALSE;
16483                :            }
16484                :            (*pExaScr->info->Copy)(pDstPixmap,
16485                :                                   src_off_x + pbox->x1 + dx,
16486                :                                   src_off_y + pbox->y1 + dy,
16487                :                                   dst_off_x + pbox->x1,
16488                :                                   dst_off_y + pbox->y1,
16489                :                                   pbox->x2 - pbox->x1,
16490                :                                   pbox->y2 - pbox->y1);
16491                :        } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
16492                :            /* Do a xdir = ydir = 1 blit instead. */
16493                :            if (dirsetup != 1) {
16494                :                if (dirsetup != 0)
16495                :                    pExaScr->info->DoneCopy(pDstPixmap);
16496                :                dirsetup = 1;
16497                :                if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
16498                :                                                   pDstPixmap,
16499                :                                                   1, 1,
16500                :                                                   pGC ? pGC->alu : GXcopy,
16501                :                                                   pGC ? pGC->planemask :
16502                :                                                         FB_ALLONES))
16503                :                    return FALSE;
16504                :            }
16505                :            (*pExaScr->info->Copy)(pDstPixmap,
16506                :                                   src_off_x + pbox->x1 + dx,
16507                :                                   src_off_y + pbox->y1 + dy,
16508                :                                   dst_off_x + pbox->x1,
16509                :                                   dst_off_y + pbox->y1,
16510                :                                   pbox->x2 - pbox->x1,
16511                :                                   pbox->y2 - pbox->y1);
16512                :        } else if (dx >= 0) {
16513                :            /*
16514                :             * xdir = 1, ydir = -1.
16515                :             * Perform line-by-line xdir = ydir = 1 blits, going up.
16516                :             */
16517                :            int i;
16518                :            if (dirsetup != 1) {
16519                :                if (dirsetup != 0)
16520                :                    pExaScr->info->DoneCopy(pDstPixmap);
16521                :                dirsetup = 1;
16522                :                if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
16523                :                                                   pDstPixmap,
16524                :                                                   1, 1,
16525                :                                                   pGC ? pGC->alu : GXcopy,
16526                :                                                   pGC ? pGC->planemask :
16527                :                                                         FB_ALLONES))
16528                :                    return FALSE;
16529                :            }
16530                :            for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
16531                :                (*pExaScr->info->Copy)(pDstPixmap,
16532                :                                       src_off_x + pbox->x1 + dx,
16533                :                                       src_off_y + pbox->y1 + dy + i,
16534                :                                       dst_off_x + pbox->x1,
16535                :                                       dst_off_y + pbox->y1 + i,
16536                :                                       pbox->x2 - pbox->x1, 1);
16537                :        } else {
16538                :            /*
16539                :             * xdir = -1, ydir = 1.
16540                :             * Perform line-by-line xdir = ydir = -1 blits, going down.
16541                :             */
16542                :            int i;
16543                :            if (dirsetup != -1) {
16544                :                if (dirsetup != 0)
16545                :                    pExaScr->info->DoneCopy(pDstPixmap);
16546                :                dirsetup = -1;
16547                :                if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
16548                :                                                   pDstPixmap,
16549                :                                                   -1, -1,
16550                :                                                   pGC ? pGC->alu : GXcopy,
16551                :                                                   pGC ? pGC->planemask :
16552                :                                                         FB_ALLONES))
16553                :                    return FALSE;
16554                :            }
16555                :            for (i = 0; i < pbox->y2 - pbox->y1; i++)
16556                :                (*pExaScr->info->Copy)(pDstPixmap,
16557                :                                       src_off_x + pbox->x1 + dx,
16558                :                                       src_off_y + pbox->y1 + dy + i,
16559                :                                       dst_off_x + pbox->x1,
16560                :                                       dst_off_y + pbox->y1 + i,
16561                :                                       pbox->x2 - pbox->x1, 1);
16562                :        }
16563                :        exaPixmapDirty(pDstPixmap, dst_off_x + pbox->x1, dst_off_y + pbox->y1,
16564                :                       dst_off_x + pbox->x2, dst_off_y + pbox->y2);
16565                :    }
16566                :    if (dirsetup != 0)
16567                :        pExaScr->info->DoneCopy(pDstPixmap);
16568                :    exaMarkSync(pDstDrawable->pScreen);
16569                :    return TRUE;
16570                :}
16571                :
16572                :void
16573                :exaCopyNtoN (DrawablePtr    pSrcDrawable,
16574                :             DrawablePtr    pDstDrawable,
16575                :             GCPtr          pGC,
16576                :             BoxPtr         pbox,
16577                :             int            nbox,
16578                :             int            dx,
16579                :             int            dy,
16580                :             Bool           reverse,
16581                :             Bool           upsidedown,
16582                :             Pixel          bitplane,
16583                :             void           *closure)
16584      3  0.0033 :{ /* exaCopyNtoN total:     47  0.0512 */
16585      6  0.0065 :    ExaScreenPriv (pDstDrawable->pScreen);
16586                :    PixmapPtr pSrcPixmap, pDstPixmap;
16587                :    int     src_off_x, src_off_y;
16588                :    int     dst_off_x, dst_off_y;
16589                :    ExaMigrationRec pixmaps[2];
16590                :    Bool fallback = FALSE;
16591                :
16592                :    pixmaps[0].as_dst = TRUE;
16593                :    pixmaps[0].as_src = FALSE;
16594      5  0.0054 :    pixmaps[0].pPix = pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
16595      3  0.0033 :    pixmaps[1].as_dst = FALSE;
16596      1  0.0011 :    pixmaps[1].as_src = TRUE;
16597      7  0.0076 :    pixmaps[1].pPix = pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
16598                :
16599                :    /* Respect maxX/maxY in a trivial way: don't set up drawing when we might
16600                :     * violate the limits.  The proper solution would be a temporary pixmap
16601                :     * adjusted so that the drawing happened within limits.
16602                :     */
16603     11  0.0120 :    if (pSrcPixmap->drawable.width > pExaScr->info->maxX ||
16604                :        pSrcPixmap->drawable.height > pExaScr->info->maxY ||
16605                :        pDstPixmap->drawable.width > pExaScr->info->maxX ||
16606                :        pDstPixmap->drawable.height > pExaScr->info->maxY)
16607                :    {
16608                :        fallback = TRUE;
16609                :    } else {
16610      1  0.0011 :        exaDoMigration (pixmaps, 2, TRUE);
16611                :    }
16612                :
16613                :    /* Mixed directions must be handled specially if the card is lame */
16614      2  0.0022 :    if (!fallback && (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
16615                :        reverse != upsidedown) {
16616                :        if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
16617                :                               dx, dy))
16618                :            return;
16619                :        fallback = TRUE;
16620                :    }
16621                :
16622      2  0.0022 :    pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
16623                :    pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
16624                :
16625                :    exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y);
16626      4  0.0044 :    exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y);
16627                :
16628                :    if (fallback || !exaPixmapIsOffscreen(pSrcPixmap) ||
16629                :        !exaPixmapIsOffscreen(pDstPixmap) ||
16630                :        !(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
16631                :                                        upsidedown ? -1 : 1,
16632                :                                        pGC ? pGC->alu : GXcopy,
16633                :                                        pGC ? pGC->planemask : FB_ALLONES)) {
16634                :        fallback = TRUE;
16635                :        return;
16636                :        EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
16637                :                      exaDrawableLocation(pSrcDrawable),
16638                :                      exaDrawableLocation(pDstDrawable)));
16639                :        exaDoMigration (pixmaps, 2, FALSE);
16640                :        exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST);
16641                :        exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC);
16642                :        fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC,
16643                :                    pbox, nbox, dx, dy, reverse, upsidedown,
16644                :                    bitplane, closure);
16645                :        exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
16646                :        exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
16647                :    }
16648                :
16649                :    while (nbox--)
16650                :    {
16651                :        if (!fallback)
16652                :            (*pExaScr->info->Copy) (pDstPixmap,
16653                :                                    pbox->x1 + dx + src_off_x,
16654                :                                    pbox->y1 + dy + src_off_y,
16655                :                                    pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
16656                :                                    pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
16657                :        exaPixmapDirty (pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
16658                :                        pbox->x2  + dst_off_x, pbox->y2 + dst_off_y);
16659                :        pbox++;
16660                :    }
16661                :
16662                :    if (fallback)
16663                :        return;
16664                :
16665                :    (*pExaScr->info->DoneCopy) (pDstPixmap);
16666                :    exaMarkSync (pDstDrawable->pScreen);
16667      2  0.0022 :}
16668                :
16669                :RegionPtr
16670                :exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
16671                :            int srcx, int srcy, int width, int height, int dstx, int dsty)
16672      5  0.0054 :{ /* exaCopyArea total:     33  0.0359 */
16673                :    ExaScreenPriv (pDstDrawable->pScreen);
16674                :
16675      9  0.0098 :    if (pExaScr->swappedOut) {
16676                :        return  ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC,
16677                :                                 srcx, srcy, width, height, dstx, dsty);
16678                :    }
16679                :
16680     14  0.0153 :    return  fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
16681                :                      srcx, srcy, width, height,
16682                :                      dstx, dsty, exaCopyNtoN, 0, NULL);
16683      5  0.0054 :}
16684                :
16685                :static void
16686                :exaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
16687                :             DDXPointPtr ppt)
16688                :{
16689                :    int i;
16690                :    xRectangle *prect;
16691                :
16692                :    /* If we can't reuse the current GC as is, don't bother accelerating the
16693                :     * points.
16694                :     */
16695                :    if (pGC->fillStyle != FillSolid) {
16696                :        ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt);
16697                :        return;
16698                :    }
16699                :
16700                :    prect = ALLOCATE_LOCAL(sizeof(xRectangle) * npt);
16701                :    for (i = 0; i < npt; i++) {
16702                :        prect[i].x = ppt[i].x;
16703                :        prect[i].y = ppt[i].y;
16704                :        if (i > 0 && mode == CoordModePrevious) {
16705                :            prect[i].x += prect[i - 1].x;
16706                :            prect[i].y += prect[i - 1].y;
16707                :        }
16708                :        prect[i].width = 1;
16709                :        prect[i].height = 1;
16710                :    }
16711                :    pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
16712                :    DEALLOCATE_LOCAL(prect);
16713                :}
16714                :
16715                :/**
16716                : * exaPolylines() checks if it can accelerate the lines as a group of
16717                : * horizontal or vertical lines (rectangles), and uses existing rectangle fill
16718                : * acceleration if so.
16719                : */
16720                :static void
16721                :exaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
16722                :             DDXPointPtr ppt)
16723                :{
16724                :    xRectangle *prect;
16725                :    int x1, x2, y1, y2;
16726                :    int i;
16727                :
16728                :    /* Don't try to do wide lines or non-solid fill style. */
16729                :    if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
16730                :        pGC->fillStyle != FillSolid) {
16731                :        ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
16732                :        return;
16733                :    }
16734                :
16735                :    prect = ALLOCATE_LOCAL(sizeof(xRectangle) * (npt - 1));
16736                :    x1 = ppt[0].x;
16737                :    y1 = ppt[0].y;
16738                :    /* If we have any non-horizontal/vertical, fall back. */
16739                :    for (i = 0; i < npt; i++) {
16740                :        if (mode == CoordModePrevious) {
16741                :            x2 = x1 + ppt[i + 1].x;
16742                :            y2 = y1 + ppt[i + 1].y;
16743                :        } else {
16744                :            x2 = ppt[i + 1].x;
16745                :            y2 = ppt[i + 1].y;
16746                :        }
16747                :
16748                :        if (x1 != x2 && y1 != y2) {
16749                :            DEALLOCATE_LOCAL(prect);
16750                :            ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
16751                :            return;
16752                :        }
16753                :
16754                :        if (x1 < x2) {
16755                :            prect[i].x = x1;
16756                :            prect[i].width = x2 - x1 + 1;
16757                :        } else {
16758                :            prect[i].x = x2;
16759                :            prect[i].width = x1 - x2 + 1;
16760                :        }
16761                :        if (y1 < y2) {
16762                :            prect[i].y = y1;
16763                :            prect[i].height = y2 - y1 + 1;
16764                :        } else {
16765                :            prect[i].y = y2;
16766                :            prect[i].height = y1 - y2 + 1;
16767                :        }
16768                :
16769                :        x1 = x2;
16770                :        y1 = y2;
16771                :    }
16772                :    pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
16773                :    DEALLOCATE_LOCAL(prect);
16774                :}
16775                :
16776                :/**
16777                : * exaPolySegment() checks if it can accelerate the lines as a group of
16778                : * horizontal or vertical lines (rectangles), and uses existing rectangle fill
16779                : * acceleration if so.
16780                : */
16781                :static void
16782                :exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
16783                :                xSegment *pSeg)
16784      1  0.0011 :{ /* exaPolySegment total:      3  0.0033 */
16785                :    xRectangle *prect;
16786                :    int i;
16787                :
16788                :    /* Don't try to do wide lines or non-solid fill style. */
16789                :    if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
16790                :        pGC->fillStyle != FillSolid)
16791                :    {
16792                :        ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg);
16793                :        return;
16794                :    }
16795                :
16796                :    /* If we have any non-horizontal/vertical, fall back. */
16797                :    for (i = 0; i < nseg; i++) {
16798                :        if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) {
16799                :            ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg);
16800                :            return;
16801                :        }
16802                :    }
16803                :
16804      1  0.0011 :    prect = ALLOCATE_LOCAL(sizeof(xRectangle) * nseg);
16805                :    for (i = 0; i < nseg; i++) {
16806                :        if (pSeg[i].x1 < pSeg[i].x2) {
16807                :            prect[i].x = pSeg[i].x1;
16808                :            prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
16809                :        } else {
16810                :            prect[i].x = pSeg[i].x2;
16811                :            prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
16812                :        }
16813                :        if (pSeg[i].y1 < pSeg[i].y2) {
16814                :            prect[i].y = pSeg[i].y1;
16815                :            prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
16816                :        } else {
16817                :            prect[i].y = pSeg[i].y2;
16818      1  0.0011 :            prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
16819                :        }
16820                :    }
16821                :    pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
16822                :    DEALLOCATE_LOCAL(prect);
16823                :}
16824                :
16825                :static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion,
16826                :                                Pixel pixel, CARD32 planemask, CARD32 alu);
16827                :
16828                :static void
16829                :exaPolyFillRect(DrawablePtr pDrawable,
16830                :                GCPtr       pGC,
16831                :                int         nrect,
16832                :                xRectangle  *prect)
16833      1  0.0011 :{ /* exaPolyFillRect total:     19  0.0207 */
16834      1  0.0011 :    ExaScreenPriv (pDrawable->pScreen);
16835                :    RegionPtr       pClip = fbGetCompositeClip(pGC);
16836                :    PixmapPtr       pPixmap = exaGetDrawablePixmap(pDrawable);
16837                :    register BoxPtr pbox;
16838                :    BoxPtr          pextent;
16839                :    int             extentX1, extentX2, extentY1, extentY2;
16840                :    int             fullX1, fullX2, fullY1, fullY2;
16841                :    int             partX1, partX2, partY1, partY2;
16842                :    int             xoff, yoff;
16843                :    int             xorg, yorg;
16844                :    int             n;
16845                :    ExaMigrationRec pixmaps[2];
16846                :    RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
16847                :
16848                :    /* Compute intersection of rects and clip region */
16849      1  0.0011 :    REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y);
16850                :    REGION_INTERSECT(pScreen, pReg, pClip, pReg);
16851                :
16852                :    if (!REGION_NUM_RECTS(pReg)) {
16853                :        goto out;
16854                :    }
16855                :
16856                :    pixmaps[0].as_dst = TRUE;
16857                :    pixmaps[0].as_src = FALSE;
16858                :    pixmaps[0].pPix = pPixmap;
16859                : 
16860      4  0.0044 :    exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
16861                :
16862      4  0.0044 :    if (pExaScr->swappedOut ||
16863                :        pPixmap->drawable.width > pExaScr->info->maxX ||
16864                :        pPixmap->drawable.height > pExaScr->info->maxY)
16865                :    {
16866                :        goto fallback;
16867                :    }
16868                :
16869                :    /* For ROPs where overlaps don't matter, convert rectangles to region and
16870                :     * call exaFillRegion{Solid,Tiled}.
16871                :     */
16872      2  0.0022 :    if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
16873                :        (pGC->alu == GXcopy || pGC->alu == GXclear || pGC->alu == GXnoop ||
16874                :         pGC->alu == GXcopyInverted || pGC->alu == GXset)) {
16875      6  0.0065 :        if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
16876                :             exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ?
16877                :                                pGC->fgPixel : pGC->tile.pixel, pGC->planemask,
16878                :                                pGC->alu)) ||
16879                :            (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
16880                :             exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
16881                :                                pGC->planemask, pGC->alu))) {
16882                :            goto out;
16883                :        }
16884                :    }
16885                :
16886                :    if (pGC->fillStyle != FillSolid &&
16887                :        !(pGC->tileIsPixel && pGC->fillStyle == FillTiled))
16888                :    {
16889                :        goto fallback;
16890                :    }
16891                :
16892                :    exaDoMigration (pixmaps, 1, TRUE);
16893                :
16894                :    if (!exaPixmapIsOffscreen (pPixmap) ||
16895                :        !(*pExaScr->info->PrepareSolid) (pPixmap,
16896                :                                         pGC->alu,
16897                :                                         pGC->planemask,
16898                :                                         pGC->fgPixel))
16899                :    {
16900                :fallback:
16901                :        if (pGC->fillStyle == FillTiled && !pGC->tileIsPixel) {
16902                :            pixmaps[1].as_dst = FALSE;
16903                :            pixmaps[1].as_src = TRUE;
16904                :            pixmaps[1].pPix = pGC->tile.pixmap;
16905                :            exaDoMigration (pixmaps, 2, FALSE);
16906                :        } else {
16907                :            exaDoMigration (pixmaps, 1, FALSE);
16908                :        }
16909                :
16910                :        ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
16911                :        goto out;
16912                :    }
16913                :
16914                :    xorg = pDrawable->x;
16915                :    yorg = pDrawable->y;
16916                :
16917                :    pextent = REGION_EXTENTS(pGC->pScreen, pClip);
16918                :    extentX1 = pextent->x1;
16919                :    extentY1 = pextent->y1;
16920                :    extentX2 = pextent->x2;
16921                :    extentY2 = pextent->y2;
16922                :    while (nrect--)
16923                :    {
16924                :        fullX1 = prect->x + xorg;
16925                :        fullY1 = prect->y + yorg;
16926                :        fullX2 = fullX1 + (int) prect->width;
16927                :        fullY2 = fullY1 + (int) prect->height;
16928                :        prect++;
16929                :
16930                :        if (fullX1 < extentX1)
16931                :            fullX1 = extentX1;
16932                :
16933                :        if (fullY1 < extentY1)
16934                :            fullY1 = extentY1;
16935                :
16936                :        if (fullX2 > extentX2)
16937                :            fullX2 = extentX2;
16938                :
16939                :        if (fullY2 > extentY2)
16940                :            fullY2 = extentY2;
16941                :
16942                :        if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
16943                :            continue;
16944                :        n = REGION_NUM_RECTS (pClip);
16945                :        if (n == 1)
16946                :        {
16947                :            (*pExaScr->info->Solid) (pPixmap,
16948                :                                     fullX1 + xoff, fullY1 + yoff,
16949                :                                     fullX2 + xoff, fullY2 + yoff);
16950                :        }
16951                :        else
16952                :        {
16953                :            pbox = REGION_RECTS(pClip);
16954                :            /*
16955                :             * clip the rectangle to each box in the clip region
16956                :             * this is logically equivalent to calling Intersect(),
16957                :             * but rectangles may overlap each other here.
16958                :             */
16959                :            while(n--)
16960                :            {
16961                :                partX1 = pbox->x1;
16962                :                if (partX1 < fullX1)
16963                :                    partX1 = fullX1;
16964                :                partY1 = pbox->y1;
16965                :                if (partY1 < fullY1)
16966                :                    partY1 = fullY1;
16967                :                partX2 = pbox->x2;
16968                :                if (partX2 > fullX2)
16969                :                    partX2 = fullX2;
16970                :                partY2 = pbox->y2;
16971                :                if (partY2 > fullY2)
16972                :                    partY2 = fullY2;
16973                :
16974                :                pbox++;
16975                :
16976                :                if (partX1 < partX2 && partY1 < partY2) {
16977                :                    (*pExaScr->info->Solid) (pPixmap,
16978                :                                             partX1 + xoff, partY1 + yoff,
16979                :                                             partX2 + xoff, partY2 + yoff);
16980                :                }
16981                :            }
16982                :        }
16983                :    }
16984                :    (*pExaScr->info->DoneSolid) (pPixmap);
16985                :    exaMarkSync(pDrawable->pScreen);
16986                :
16987                :out:
16988                :    REGION_DESTROY(pScreen, pReg);
16989                :}
16990                :
16991                :static void
16992                :exaSolidBoxClipped (DrawablePtr pDrawable,
16993                :                    RegionPtr   pClip,
16994                :                    FbBits      pm,
16995                :                    FbBits      fg,
16996                :                    int         x1,
16997                :                    int         y1,
16998                :                    int         x2,
16999                :                    int         y2)
17000                :{
17001                :    ExaScreenPriv (pDrawable->pScreen);
17002                :    PixmapPtr   pPixmap;
17003                :    BoxPtr      pbox;
17004                :    int         nbox;
17005                :    int         xoff, yoff;
17006                :    int         partX1, partX2, partY1, partY2;
17007                :    ExaMigrationRec pixmaps[1];
17008                :    Bool        fallback = FALSE;
17009                :
17010                :    pixmaps[0].as_dst = TRUE;
17011                :    pixmaps[0].as_src = FALSE;
17012                :    pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
17013                :
17014                :    if (pExaScr->swappedOut ||
17015                :        pPixmap->drawable.width > pExaScr->info->maxX ||
17016                :        pPixmap->drawable.height > pExaScr->info->maxY)
17017                :    {
17018                :        fallback = TRUE;
17019                :    } else {
17020                :        exaDoMigration (pixmaps, 1, TRUE);
17021                :    }
17022                :
17023                :    exaGetDrawableDeltas (pDrawable, pPixmap, &xoff, &yoff);
17024                :
17025                :    if (fallback || !exaPixmapIsOffscreen(pPixmap) ||
17026                :        !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg))
17027                :    {
17028                :        EXA_FALLBACK(("to %p (%c)\n", pDrawable,
17029                :                      exaDrawableLocation(pDrawable)));
17030                :        exaDoMigration (pixmaps, 1, FALSE);
17031                :        fallback = TRUE;
17032                :        exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
17033                :        fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
17034                :        fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
17035                :                           fbAnd (GXcopy, fg, pm),
17036                :                           fbXor (GXcopy, fg, pm));
17037                :        exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
17038                :    }
17039                :    for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
17040                :         nbox--;
17041                :         pbox++)
17042                :    {
17043                :        partX1 = pbox->x1;
17044                :        if (partX1 < x1)
17045                :            partX1 = x1;
17046                :
17047                :        partX2 = pbox->x2;
17048                :        if (partX2 > x2)
17049                :            partX2 = x2;
17050                :
17051                :        if (partX2 <= partX1)
17052                :            continue;
17053                :
17054                :        partY1 = pbox->y1;
17055                :        if (partY1 < y1)
17056                :            partY1 = y1;
17057                :
17058                :        partY2 = pbox->y2;
17059                :        if (partY2 > y2)
17060                :            partY2 = y2;
17061                :
17062                :        if (partY2 <= partY1)
17063                :            continue;
17064                :
17065                :        if (!fallback) {
17066                :            (*pExaScr->info->Solid) (pPixmap,
17067                :                                     partX1 + xoff, partY1 + yoff,
17068                :                                     partX2 + xoff, partY2 + yoff);
17069                :        }
17070                :
17071                :        exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff,
17072                :                        partY2 + yoff);
17073                :    }
17074                :
17075                :    if (fallback)
17076                :        return;
17077                :
17078                :    (*pExaScr->info->DoneSolid) (pPixmap);
17079                :    exaMarkSync(pDrawable->pScreen);
17080                :}
17081                :
17082                :static void
17083                :exaImageGlyphBlt (DrawablePtr   pDrawable,
17084                :                  GCPtr         pGC,
17085                :                  int           x,
17086                :                  int           y,
17087                :                  unsigned int  nglyph,
17088                :                  CharInfoPtr   *ppciInit,
17089                :                  pointer       pglyphBase)
17090                :{
17091                :    FbGCPrivPtr     pPriv = fbGetGCPrivate(pGC);
17092                :    CharInfoPtr     *ppci;
17093                :    CharInfoPtr     pci;
17094                :    unsigned char   *pglyph;            /* pointer bits in glyph */
17095                :    int             gWidth, gHeight;    /* width and height of glyph */
17096                :    FbStride        gStride;            /* stride of glyph */
17097                :    Bool            opaque;
17098                :    int             n;
17099                :    int             gx, gy;
17100                :    void            (*glyph) (FbBits *,
17101                :                              FbStride,
17102                :                              int,
17103                :                              FbStip *,
17104                :                              FbBits,
17105                :                              int,
17106                :                              int);
17107                :    FbBits          *dst;
17108                :    FbStride        dstStride;
17109                :    int             dstBpp;
17110                :    int             dstXoff, dstYoff;
17111                :    FbBits          depthMask;
17112                :    PixmapPtr       pPixmap = exaGetDrawablePixmap(pDrawable);
17113                :    ExaMigrationRec pixmaps[1];
17114                :    int             xBack, widthBack, yBack, heightBack;
17115                :
17116                :    for (ppci = ppciInit, n = nglyph, widthBack = 0; n; n--)
17117                :        widthBack += (*ppci++)->metrics.characterWidth;
17118                :
17119                :    xBack = x;
17120                :    if (widthBack < 0)
17121                :    {
17122                :        xBack += widthBack;
17123                :        widthBack = -widthBack;
17124                :    }
17125                :    yBack = y - FONTASCENT(pGC->font);
17126                :    heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
17127                :
17128                :    if (xBack >= pDrawable->width || yBack >= pDrawable->height ||
17129                :        (xBack + widthBack) <= 0 || (yBack + heightBack) <= 0)
17130                :        return;
17131                :
17132                :    pixmaps[0].as_dst = TRUE;
17133                :    pixmaps[0].as_src = TRUE;
17134                :    pixmaps[0].pPix = pPixmap;
17135                :
17136                :    depthMask = FbFullMask(pDrawable->depth);
17137                :    if ((pGC->planemask & depthMask) != depthMask)
17138                :    {
17139                :        exaDoMigration(pixmaps, 1, FALSE);
17140                :        ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
17141                :        goto damage;
17142                :    }
17143                :    glyph = NULL;
17144                :    switch (pDrawable->bitsPerPixel) {
17145                :    case 8:     glyph = fbGlyph8; break;
17146                :    case 16:    glyph = fbGlyph16; break;
17147                :    case 24:    glyph = fbGlyph24; break;
17148                :    case 32:    glyph = fbGlyph32; break;
17149                :    }
17150                :
17151                :    x += pDrawable->x;
17152                :    y += pDrawable->y;
17153                :    xBack += pDrawable->x;
17154                :    yBack += pDrawable->y;
17155                :
17156                :    if (TERMINALFONT (pGC->font) && !glyph)
17157                :    {
17158                :        opaque = TRUE;
17159                :    }
17160                :    else
17161                :    {
17162                :        exaSolidBoxClipped (pDrawable,
17163                :                            fbGetCompositeClip(pGC),
17164                :                            pGC->planemask,
17165                :                            pGC->bgPixel,
17166                :                            xBack,
17167                :                            yBack,
17168                :                            xBack + widthBack,
17169                :                            yBack + heightBack);
17170                :        opaque = FALSE;
17171                :    }
17172                :
17173                :    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
17174                :    exaDoMigration(pixmaps, 1, FALSE);
17175                :    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
17176                :    exaPrepareAccessGC (pGC);
17177                :
17178                :    fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
17179                :
17180                :    for (ppci = ppciInit; nglyph; nglyph--, x += pci->metrics.characterWidth)
17181                :    {
17182                :        pci = *ppci++;
17183                :        gWidth = GLYPHWIDTHPIXELS(pci);
17184                :        gHeight = GLYPHHEIGHTPIXELS(pci);
17185                :        gx = x + pci->metrics.leftSideBearing;
17186                :        gy = y - pci->metrics.ascent;
17187                :
17188                :        if (!gWidth || !gHeight || (gx + gWidth) <= xBack ||
17189                :            (gy + gHeight) <= yBack || gx >= (xBack + widthBack) ||
17190                :            gy >= (yBack + heightBack))
17191                :            continue;
17192                :
17193                :        pglyph = FONTGLYPHBITS(pglyphBase, pci);
17194                :
17195                :        if (glyph && gWidth <= sizeof (FbStip) * 8 &&
17196                :            fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
17197                :        {
17198                :            (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
17199                :                      (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight);
17200                :        }
17201                :        else
17202                :        {
17203                :            RegionPtr pClip = fbGetCompositeClip(pGC);
17204                :
17205                :            gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
17206                :            fbPutXYImage (pDrawable, pClip, pPriv->fg, pPriv->bg, pPriv->pm,
17207                :                          GXcopy, opaque, gx, gy, gWidth, gHeight,
17208                :                          (FbStip *) pglyph, gStride, 0);
17209                :        }
17210                :    }
17211                :    exaFinishAccessGC (pGC);
17212                :    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
17213                :
17214                :damage:
17215                :    exaGetDrawableDeltas(pDrawable, pPixmap, &dstXoff, &dstYoff);
17216                :    exaPixmapDirty(pPixmap, xBack + dstXoff, yBack + dstYoff,
17217                :                   xBack + dstXoff + widthBack, yBack + dstYoff + heightBack);
17218                :}
17219                :
17220                :const GCOps exaOps = {
17221                :    exaFillSpans,
17222                :    ExaCheckSetSpans,
17223                :    exaPutImage,
17224                :    exaCopyArea,
17225                :    ExaCheckCopyPlane,
17226                :    exaPolyPoint,
17227                :    exaPolylines,
17228                :    exaPolySegment,
17229                :    miPolyRectangle,
17230                :    ExaCheckPolyArc,
17231                :    miFillPolygon,
17232                :    exaPolyFillRect,
17233                :    miPolyFillArc,
17234                :    miPolyText8,
17235                :    miPolyText16,
17236                :    miImageText8,
17237                :    miImageText16,
17238                :    exaImageGlyphBlt,
17239                :    ExaCheckPolyGlyphBlt,
17240                :    ExaCheckPushPixels,
17241                :};
17242                :
17243                :void
17244                :exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
17245                :{
17246                :    RegionRec   rgnDst;
17247                :    int         dx, dy;
17248                :    PixmapPtr   pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
17249                :
17250                :    dx = ptOldOrg.x - pWin->drawable.x;
17251                :    dy = ptOldOrg.y - pWin->drawable.y;
17252                :    REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
17253                :
17254                :    REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
17255                :
17256                :    REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
17257                :#ifdef COMPOSITE
17258                :    if (pPixmap->screen_x || pPixmap->screen_y)
17259                :        REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
17260                :                          -pPixmap->screen_x, -pPixmap->screen_y);
17261                :#endif
17262                :
17263                :    fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
17264                :                  NULL,
17265                :                  &rgnDst, dx, dy, exaCopyNtoN, 0, NULL);
17266                :
17267                :    REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
17268                :}
17269                :
17270                :static Bool
17271                :exaFillRegionSolid (DrawablePtr pDrawable,
17272                :                    RegionPtr   pRegion,
17273                :                    Pixel       pixel,
17274                :                    CARD32      planemask,
17275                :                    CARD32      alu)
17276      2  0.0022 :{ /* exaFillRegionSolid total:      7  0.0076 */
17277                :    ExaScreenPriv(pDrawable->pScreen);
17278                :    PixmapPtr pPixmap;
17279                :    int xoff, yoff;
17280                :    ExaMigrationRec pixmaps[1];
17281                :    int nbox = REGION_NUM_RECTS (pRegion);
17282                :    BoxPtr pBox = REGION_RECTS (pRegion);
17283                :
17284                :    pixmaps[0].as_dst = TRUE;
17285                :    pixmaps[0].as_src = FALSE;
17286      1  0.0011 :    pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
17287                : 
17288      1  0.0011 :    if (pPixmap->drawable.width > pExaScr->info->maxX ||
17289                :        pPixmap->drawable.height > pExaScr->info->maxY)
17290                :    {
17291                :        goto fallback;
17292                :    } else {
17293                :        exaDoMigration (pixmaps, 1, TRUE);
17294                :    }
17295                :
17296      2  0.0022 :    if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
17297                :        (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
17298                :    {
17299                :        while (nbox--)
17300                :        {
17301                :            (*pExaScr->info->Solid) (pPixmap,
17302                :                                     pBox->x1 + xoff, pBox->y1 + yoff,
17303                :                                     pBox->x2 + xoff, pBox->y2 + yoff);
17304                :            pBox++;
17305                :        }
17306                :        (*pExaScr->info->DoneSolid) (pPixmap);
17307      1  0.0011 :        exaMarkSync(pDrawable->pScreen);
17308                :    }
17309                :    else
17310                :    {
17311                :fallback:
17312                :        if (alu != GXcopy || planemask != FB_ALLONES)
17313                :            return FALSE;
17314                :        return TRUE;
17315                :        EXA_FALLBACK(("to %p (%c)\n", pDrawable,
17316                :                      exaDrawableLocation(pDrawable)));
17317                :        exaDoMigration (pixmaps, 1, FALSE);
17318                :        exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
17319                :        fbFillRegionSolid (pDrawable, pRegion, 0,
17320                :                           fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
17321                :        exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
17322                :    }
17323                :
17324                :    return TRUE;
17325                :}
17326                :
17327                :/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
17328                : * Based on fbFillRegionTiled(), fbTile().
17329                : */
17330                :Bool
17331                :exaFillRegionTiled (DrawablePtr pDrawable,
17332                :                    RegionPtr   pRegion,
17333                :                    PixmapPtr   pTile,
17334                :                    DDXPointPtr pPatOrg,
17335                :                    CARD32      planemask,
17336                :                    CARD32      alu)
17337                :{
17338                :    ExaScreenPriv(pDrawable->pScreen);
17339                :    PixmapPtr pPixmap;
17340                :    int xoff, yoff, tileXoff, tileYoff;
17341                :    int tileWidth, tileHeight;
17342                :    ExaMigrationRec pixmaps[2];
17343                :    int nbox = REGION_NUM_RECTS (pRegion);
17344                :    BoxPtr pBox = REGION_RECTS (pRegion);
17345                :
17346                :    tileWidth = pTile->drawable.width;
17347                :    tileHeight = pTile->drawable.height;
17348                :
17349                :    /* If we're filling with a solid color, grab it out and go to
17350                :     * FillRegionSolid, saving numerous copies.
17351                :     */
17352                :    if (tileWidth == 1 && tileHeight == 1)
17353                :        return exaFillRegionSolid(pDrawable, pRegion,
17354                :                                  exaGetPixmapFirstPixel (pTile), planemask,
17355                :                                  alu);
17356                :
17357                :    pixmaps[0].as_dst = TRUE;
17358                :    pixmaps[0].as_src = FALSE;
17359                :    pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
17360                :    pixmaps[1].as_dst = FALSE;
17361                :    pixmaps[1].as_src = TRUE;
17362                :    pixmaps[1].pPix = pTile;
17363                :
17364                :    if (pPixmap->drawable.width > pExaScr->info->maxX ||
17365                :        pPixmap->drawable.height > pExaScr->info->maxY ||
17366                :        tileWidth > pExaScr->info->maxX ||
17367                :        tileHeight > pExaScr->info->maxY)
17368                :    {
17369                :        goto fallback;
17370                :    } else {
17371                :        exaDoMigration (pixmaps, 2, TRUE);
17372                :    }
17373                :
17374                :    pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
17375                :
17376                :    if (!pPixmap)
17377                :        goto fallback;
17378                :
17379                :    if (!exaPixmapIsOffscreen(pTile))
17380                :        goto fallback;
17381                :
17382                :    if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile,
17383                :                                                             &tileXoff, &tileYoff),
17384                :                                       pPixmap, 0, 0, alu, planemask))
17385                :    {
17386                :        while (nbox--)
17387                :        {
17388                :            int height = pBox->y2 - pBox->y1;
17389                :            int dstY = pBox->y1;
17390                :            int tileY;
17391                :
17392                :            tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight;
17393                :            while (height > 0) {
17394                :                int width = pBox->x2 - pBox->x1;
17395                :                int dstX = pBox->x1;
17396                :                int tileX;
17397                :                int h = tileHeight - tileY;
17398                :
17399                :                if (h > height)
17400                :                    h = height;
17401                :                height -= h;
17402                :
17403                :                tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth;
17404                :                while (width > 0) {
17405                :                    int w = tileWidth - tileX;
17406                :                    if (w > width)
17407                :                        w = width;
17408                :                    width -= w;
17409                :
17410                :                    (*pExaScr->info->Copy) (pPixmap,
17411                :                                            tileX + tileXoff, tileY + tileYoff,
17412                :                                            dstX + xoff, dstY + yoff,
17413                :                                            w, h);
17414                :                    dstX += w;
17415                :                    tileX = 0;
17416                :                }
17417                :                dstY += h;
17418                :                tileY = 0;
17419                :            }
17420                :            pBox++;
17421                :        }
17422                :        (*pExaScr->info->DoneCopy) (pPixmap);
17423                :        exaMarkSync(pDrawable->pScreen);
17424                :        return TRUE;
17425                :    }
17426                :
17427                :fallback:
17428                :    if (alu != GXcopy || planemask != FB_ALLONES)
17429                :        return FALSE;
17430                :    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable,
17431                :                  exaDrawableLocation(&pTile->drawable),
17432                :                  exaDrawableLocation(pDrawable)));
17433                :    exaDoMigration (pixmaps, 2, FALSE);
17434                :    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
17435                :    exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
17436                :    fbFillRegionTiled (pDrawable, pRegion, pTile);
17437                :    exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
17438                :    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
17439                :
17440                :    return TRUE;
17441                :}
17442                :
17443                :void
17444                :exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
17445                :{
17446                :    ExaScreenPriv (pWin->drawable.pScreen);
17447                :    PixmapPtr pPixmap = exaGetDrawablePixmap((DrawablePtr)pWin);
17448                :    int xoff, yoff;
17449                :    BoxPtr pBox;
17450                :    int nbox = REGION_NUM_RECTS(pRegion);
17451                :
17452                :    if (!nbox)
17453                :        return;
17454                :
17455                :    if (!pExaScr->swappedOut) {
17456                :        DDXPointRec zeros = { 0, 0 };
17457                :
17458                :        switch (what) {
17459                :        case PW_BACKGROUND:
17460                :            switch (pWin->backgroundState) {
17461                :            case None:
17462                :                return;
17463                :            case ParentRelative:
17464                :                do {
17465                :                    pWin = pWin->parent;
17466                :                } while (pWin->backgroundState == ParentRelative);
17467                :                (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
17468                :                                                                 what);
17469                :                return;
17470                :            case BackgroundPixel:
17471                :                exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel,
17472                :                                   FB_ALLONES, GXcopy);
17473                :                goto damage;
17474                :            case BackgroundPixmap:
17475                :                exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap,
17476                :                                   &zeros, FB_ALLONES, GXcopy);
17477                :                goto damage;
17478                :            }
17479                :            break;
17480                :        case PW_BORDER:
17481                :            if (pWin->borderIsPixel) {
17482                :                exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel,
17483                :                                   FB_ALLONES, GXcopy);
17484                :                goto damage;
17485                :            } else {
17486                :                exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap,
17487                :                                   &zeros, FB_ALLONES, GXcopy);
17488                :                goto damage;
17489                :            }
17490                :            break;
17491                :        }
17492                :    }
17493                :    ExaCheckPaintWindow (pWin, pRegion, what);
17494                :
17495                :damage:
17496                :    exaGetDrawableDeltas((DrawablePtr)pWin, pPixmap, &xoff, &yoff);
17497                :
17498                :    pBox = REGION_RECTS(pRegion);
17499                :
17500                :    while (nbox--)
17501                :    {
17502                :        exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff,
17503                :                        pBox->x2 + xoff, pBox->y2 + yoff);
17504                :        pBox++;
17505                :    }
17506                :}
17507                :
17508                :/**
17509                : * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
17510                : *
17511                : * This is probably the only case we actually care about.  The rest fall through
17512                : * to migration and ExaCheckGetImage, which hopefully will result in migration
17513                : * pushing the pixmap out of framebuffer.
17514                : */
17515                :void
17516                :exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
17517                :             unsigned int format, unsigned long planeMask, char *d)
17518                :{
17519                :    ExaScreenPriv (pDrawable->pScreen);
17520                :    ExaMigrationRec pixmaps[1];
17521                :    PixmapPtr pPix;
17522                :    int xoff, yoff;
17523                :    Bool ok;
17524                :
17525                :    if (pExaScr->swappedOut || (w == 1 && h == 1))
17526                :        goto fallback;
17527                :
17528                :    if (pExaScr->info->DownloadFromScreen == NULL)
17529                :        goto migrate_and_fallback;
17530                :
17531                :    /* Only cover the ZPixmap, solid copy case. */
17532                :    if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
17533                :        goto migrate_and_fallback;
17534                :
17535                :    /* Only try to handle the 8bpp and up cases, since we don't want to think
17536                :     * about <8bpp.
17537                :     */
17538                :    if (pDrawable->bitsPerPixel < 8)
17539                :        goto migrate_and_fallback;
17540                :
17541                :    pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
17542                :    if (pPix == NULL)
17543                :        goto fallback;
17544                :
17545                :    xoff += pDrawable->x;
17546                :    yoff += pDrawable->y;
17547                :
17548                :    ok = pExaScr->info->DownloadFromScreen(pPix, x + xoff, y + yoff, w, h, d,
17549                :                                           PixmapBytePad(w, pDrawable->depth));
17550                :    if (ok) {
17551                :        exaWaitSync(pDrawable->pScreen);
17552                :        return;
17553                :    }
17554                :
17555                :migrate_and_fallback:
17556                :    pixmaps[0].as_dst = FALSE;
17557                :    pixmaps[0].as_src = TRUE;
17558                :    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
17559                :    exaDoMigration (pixmaps, 1, FALSE);
17560                :fallback:
17561                :    ExaCheckGetImage (pDrawable, x, y, w, h, format, planeMask, d);
17562                :}
17563                :
17564                :/**
17565                : * GetSpans isn't accelerated yet, but performs migration so that we'll
17566                : * hopefully avoid the read-from-framebuffer cost.
17567                : */
17568                :void
17569                :exaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth,
17570                :             int nspans, char *pdstStart)
17571                :{
17572                :    ExaMigrationRec pixmaps[1];
17573                :
17574                :    pixmaps[0].as_dst = FALSE;
17575                :    pixmaps[0].as_src = TRUE;
17576                :    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
17577                :    exaDoMigration (pixmaps, 1, FALSE);
17578                :
17579                :    ExaCheckGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
17580                :}
17581 /* 
17582  * Total samples for file : "/home/cworth/src/xorg/xserver/render/glyph.c"
17583  * 
17584  *    103  0.1122
17585  */
17586
17587
17588                :/*
17589                : *
17590                : * Copyright Â© 2000 SuSE, Inc.
17591                : *
17592                : * Permission to use, copy, modify, distribute, and sell this software and its
17593                : * documentation for any purpose is hereby granted without fee, provided that
17594                : * the above copyright notice appear in all copies and that both that
17595                : * copyright notice and this permission notice appear in supporting
17596                : * documentation, and that the name of SuSE not be used in advertising or
17597                : * publicity pertaining to distribution of the software without specific,
17598                : * written prior permission.  SuSE makes no representations about the
17599                : * suitability of this software for any purpose.  It is provided "as is"
17600                : * without express or implied warranty.
17601                : *
17602                : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17603                : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17604                : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17605                : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
17606                : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
17607                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17608                : *
17609                : * Author:  Keith Packard, SuSE, Inc.
17610                : */
17611                :
17612                :#ifdef HAVE_DIX_CONFIG_H
17613                :#include <dix-config.h>
17614                :#endif
17615                :
17616                :#include "misc.h"
17617                :#include "scrnintstr.h"
17618                :#include "os.h"
17619                :#include "regionstr.h"
17620                :#include "validate.h"
17621                :#include "windowstr.h"
17622                :#include "input.h"
17623                :#include "resource.h"
17624                :#include "colormapst.h"
17625                :#include "cursorstr.h"
17626                :#include "dixstruct.h"
17627                :#include "gcstruct.h"
17628                :#include "servermd.h"
17629                :#include "picturestr.h"
17630                :#include "glyphstr.h"
17631                :
17632                :/*
17633                : * From Knuth -- a good choice for hash/rehash values is p, p-2 where
17634                : * p and p-2 are both prime.  These tables are sized to have an extra 10%
17635                : * free to avoid exponential performance degradation as the hash table fills
17636                : */
17637                :static GlyphHashSetRec glyphHashSets[] = {
17638                :    { 32,               43,             41        },
17639                :    { 64,               73,             71        },
17640                :    { 128,              151,            149       },
17641                :    { 256,              283,            281       },
17642                :    { 512,              571,            569       },
17643                :    { 1024,             1153,           1151      },
17644                :    { 2048,             2269,           2267      },
17645                :    { 4096,             4519,           4517      },
17646                :    { 8192,             9013,           9011      },
17647                :    { 16384,            18043,          18041     },
17648                :    { 32768,            36109,          36107     },
17649                :    { 65536,            72091,          72089     },
17650                :    { 131072,           144409,         144407    },
17651                :    { 262144,           288361,         288359    },
17652                :    { 524288,           576883,         576881    },
17653                :    { 1048576,          1153459,        1153457   },
17654                :    { 2097152,          2307163,        2307161   },
17655                :    { 4194304,          4613893,        4613891   },
17656                :    { 8388608,          9227641,        9227639   },
17657                :    { 16777216,         18455029,       18455027  },
17658                :    { 33554432,         36911011,       36911009  },
17659                :    { 67108864,         73819861,       73819859  },
17660                :    { 134217728,        147639589,      147639587 },
17661                :    { 268435456,        295279081,      295279079 },
17662                :    { 536870912,        590559793,      590559791 }
17663                :};
17664                :
17665                :#define NGLYPHHASHSETS  (sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
17666                :
17667                :static const CARD8      glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 };
17668                :
17669                :static GlyphHashRec     globalGlyphs[GlyphFormatNum];
17670                :
17671                :static int      globalTotalGlyphPrivateSize = 0;
17672                :
17673                :static int      glyphPrivateCount = 0;
17674                :
17675                :void
17676                :ResetGlyphPrivates (void)
17677                :{
17678                :    glyphPrivateCount = 0;
17679                :}
17680                :
17681                :int
17682                :AllocateGlyphPrivateIndex (void)
17683                :{
17684                :    return glyphPrivateCount++;
17685                :}
17686                :
17687                :Bool
17688                :AllocateGlyphPrivate (ScreenPtr pScreen,
17689                :                      int       index2,
17690                :                      unsigned  amount)
17691                :{
17692                :    PictureScreenPtr ps;
17693                :    unsigned         oldamount;
17694                :
17695                :    ps = GetPictureScreenIfSet (pScreen);
17696                :    if (!ps)
17697                :        return FALSE;
17698                :
17699                :    /* Round up sizes for proper alignment */
17700                :    amount = ((amount + (sizeof (DevUnion) - 1)) / sizeof (DevUnion)) *
17701                :        sizeof (DevUnion);
17702                :
17703                :    if (index2 >= ps->glyphPrivateLen)
17704                :    {
17705                :        unsigned *nsizes;
17706                :        nsizes = (unsigned *) xrealloc (ps->glyphPrivateSizes,
17707                :                                        (index2 + 1) * sizeof (unsigned));
17708                :        if (!nsizes)
17709                :            return FALSE;
17710                :        
17711                :        while (ps->glyphPrivateLen <= index2)
17712                :        {
17713                :            nsizes[ps->glyphPrivateLen++] = 0;
17714                :            ps->totalGlyphPrivateSize += sizeof (DevUnion);
17715                :        }
17716                :        ps->glyphPrivateSizes = nsizes;
17717                :    }
17718                :    oldamount = ps->glyphPrivateSizes[index2];
17719                :    if (amount > oldamount)
17720                :    {
17721                :        ps->glyphPrivateSizes[index2] = amount;
17722                :        ps->totalGlyphPrivateSize += (amount - oldamount);
17723                :    }
17724                :    ps->totalGlyphPrivateSize = BitmapBytePad (ps->totalGlyphPrivateSize * 8);
17725                :    
17726                :    return TRUE;
17727                :}
17728                :
17729                :static void
17730                :SetGlyphScreenPrivateOffsets (void)
17731                :{
17732                :    PictureScreenPtr ps;
17733                :    int              offset = 0;
17734                :    int              i;
17735                :
17736                :    for (i = 0; i < screenInfo.numScreens; i++)
17737                :    {
17738                :        ps = GetPictureScreenIfSet (screenInfo.screens[i]);
17739                :        if (ps && ps->totalGlyphPrivateSize)
17740                :        {
17741                :            ps->glyphPrivateOffset = offset;
17742                :            offset += ps->totalGlyphPrivateSize / sizeof (DevUnion);
17743                :        }
17744                :    }
17745                :}
17746                :
17747                :static void
17748                :SetGlyphPrivatePointers (GlyphPtr glyph)
17749                :{
17750                :    PictureScreenPtr ps;
17751                :    int              i;
17752                :    char             *ptr;
17753                :    DevUnion         *ppriv;
17754                :    unsigned         *sizes;
17755                :    unsigned         size;
17756                :    int              len;
17757                :
17758                :    for (i = 0; i < screenInfo.numScreens; i++)
17759                :    {
17760                :        ps = GetPictureScreenIfSet (screenInfo.screens[i]);
17761                :        if (ps && ps->totalGlyphPrivateSize)
17762                :        {
17763                :            ppriv = glyph->devPrivates + ps->glyphPrivateOffset;
17764                :            sizes = ps->glyphPrivateSizes;
17765                :            ptr = (char *) (ppriv + ps->glyphPrivateLen);
17766                :            for (len = ps->glyphPrivateLen; --len >= 0; ppriv++, sizes++)
17767                :            {
17768                :                if ((size = *sizes) != 0)
17769                :                {
17770                :                    ppriv->ptr = (pointer) ptr;
17771                :                    ptr += size;
17772                :                }
17773                :                else
17774                :                    ppriv->ptr = (pointer) 0;
17775                :            }
17776                :        }
17777                :    }
17778                :}
17779                :
17780                :static Bool
17781                :ReallocGlobalGlyphPrivate (GlyphPtr glyph)
17782                :{
17783                :    PictureScreenPtr ps;
17784                :    DevUnion         *devPrivates;
17785                :    char             *ptr;
17786                :    int              i;
17787                :
17788                :    devPrivates = xalloc (globalTotalGlyphPrivateSize);
17789                :    if (!devPrivates)
17790                :        return FALSE;
17791                :
17792                :    ptr = (char *) devPrivates;
17793                :    for (i = 0; i < screenInfo.numScreens; i++)
17794                :    {
17795                :        ps = GetPictureScreenIfSet (screenInfo.screens[i]);
17796                :        if (ps && ps->totalGlyphPrivateSize)
17797                :        {
17798                :            if (ps->glyphPrivateOffset != -1)
17799                :            {
17800                :                memcpy (ptr, glyph->devPrivates + ps->glyphPrivateOffset,
17801                :                        ps->totalGlyphPrivateSize);
17802                :            }
17803                :            else if (ps->totalGlyphPrivateSize)
17804                :            {
17805                :                memset (ptr, 0, ps->totalGlyphPrivateSize);
17806                :            }
17807                :            
17808                :            ptr += ps->totalGlyphPrivateSize;
17809                :        }
17810                :    }
17811                :
17812                :    if (glyph->devPrivates)
17813                :        xfree (glyph->devPrivates);
17814                :    
17815                :    glyph->devPrivates = devPrivates;
17816                :
17817                :    return TRUE;
17818                :}
17819                :
17820                :Bool
17821                :GlyphInit (ScreenPtr pScreen)
17822                :{
17823                :    PictureScreenPtr ps = GetPictureScreen (pScreen);
17824                :    
17825                :    ps->totalGlyphPrivateSize = 0;
17826                :    ps->glyphPrivateSizes = 0;
17827                :    ps->glyphPrivateLen = 0;
17828                :    ps->glyphPrivateOffset = -1;
17829                :    
17830                :    return TRUE;
17831                :}
17832                :
17833                :Bool
17834                :GlyphFinishInit (ScreenPtr pScreen)
17835                :{
17836                :    PictureScreenPtr ps = GetPictureScreen (pScreen);
17837                :
17838                :    if (ps->totalGlyphPrivateSize)
17839                :    {
17840                :        GlyphPtr glyph;
17841                :        int      fdepth, i;
17842                :        
17843                :        globalTotalGlyphPrivateSize += ps->totalGlyphPrivateSize;
17844                :        
17845                :        for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
17846                :        {
17847                :            if (!globalGlyphs[fdepth].hashSet)
17848                :                continue;
17849                :                
17850                :            for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
17851                :            {
17852                :                glyph = globalGlyphs[fdepth].table[i].glyph;
17853                :                if (glyph && glyph != DeletedGlyph)
17854                :                {
17855                :                    if (!ReallocGlobalGlyphPrivate (glyph))
17856                :                        return FALSE;
17857                :                }
17858                :            }
17859                :        }
17860                :
17861                :        SetGlyphScreenPrivateOffsets ();
17862                :
17863                :        for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
17864                :        {
17865                :            if (!globalGlyphs[fdepth].hashSet)
17866                :                continue;
17867                :                
17868                :            for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
17869                :            {
17870                :                glyph = globalGlyphs[fdepth].table[i].glyph;
17871                :                if (glyph && glyph != DeletedGlyph)
17872                :                {
17873                :                    SetGlyphPrivatePointers (glyph);
17874                :                        
17875                :                    if (!(*ps->RealizeGlyph) (pScreen, glyph))
17876                :                        return FALSE;
17877                :                }
17878                :            }
17879                :        }
17880                :    }
17881                :    else
17882                :        ps->glyphPrivateOffset = 0;
17883                :    
17884                :    return TRUE;
17885                :}
17886                :
17887                :void
17888                :GlyphUninit (ScreenPtr pScreen)
17889                :{
17890                :    PictureScreenPtr ps = GetPictureScreen (pScreen);
17891                :    GlyphPtr         glyph;
17892                :    int              fdepth, i;
17893                :
17894                :    globalTotalGlyphPrivateSize -= ps->totalGlyphPrivateSize;
17895                :
17896                :    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
17897                :    {
17898                :        if (!globalGlyphs[fdepth].hashSet)
17899                :            continue;
17900                :        
17901                :        for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
17902                :        {
17903                :            glyph = globalGlyphs[fdepth].table[i].glyph;
17904                :            if (glyph && glyph != DeletedGlyph)
17905                :            {
17906                :                (*ps->UnrealizeGlyph) (pScreen, glyph);
17907                :                
17908                :                if (globalTotalGlyphPrivateSize)
17909                :                {
17910                :                    if (!ReallocGlobalGlyphPrivate (glyph))
17911                :                        return;
17912                :                }
17913                :                else
17914                :                {
17915                :                    if (glyph->devPrivates)
17916                :                        xfree (glyph->devPrivates);
17917                :                    glyph->devPrivates = NULL;
17918                :                }
17919                :            }
17920                :        }
17921                :    }
17922                :
17923                :    if (globalTotalGlyphPrivateSize)
17924                :        SetGlyphScreenPrivateOffsets ();
17925                :
17926                :    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
17927                :    {
17928                :        if (!globalGlyphs[fdepth].hashSet)
17929                :            continue;
17930                :        
17931                :        for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
17932                :        {
17933                :            glyph = globalGlyphs[fdepth].table[i].glyph;    
17934                :            if (glyph && glyph != DeletedGlyph)
17935                :            {
17936                :                if (globalTotalGlyphPrivateSize)
17937                :                    SetGlyphPrivatePointers (glyph);
17938                :            }
17939                :        }
17940                :    }
17941                :
17942                :    if (ps->glyphPrivateSizes)
17943                :        xfree (ps->glyphPrivateSizes);
17944                :}
17945                :
17946                :GlyphHashSetPtr
17947                :FindGlyphHashSet (CARD32 filled)
17948                :{
17949                :    int i;
17950                :
17951                :    for (i = 0; i < NGLYPHHASHSETS; i++)
17952                :        if (glyphHashSets[i].entries >= filled)
17953                :            return &glyphHashSets[i];
17954                :    return 0;
17955                :}
17956                :
17957                :static int _GlyphSetPrivateAllocateIndex = 0;
17958                :
17959                :int
17960                :AllocateGlyphSetPrivateIndex (void)
17961                :{
17962                :    return _GlyphSetPrivateAllocateIndex++;
17963                :}
17964                :
17965                :void
17966                :ResetGlyphSetPrivateIndex (void)
17967                :{
17968                :    _GlyphSetPrivateAllocateIndex = 0;
17969                :}
17970                :
17971                :Bool
17972                :_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr)
17973                :{
17974                :    pointer *new;
17975                :
17976                :    if (n > glyphSet->maxPrivate) {
17977                :        if (glyphSet->devPrivates &&
17978                :            glyphSet->devPrivates != (pointer)(&glyphSet[1])) {
17979                :            new = (pointer *) xrealloc (glyphSet->devPrivates,
17980                :                                        (n + 1) * sizeof (pointer));
17981                :            if (!new)
17982                :                return FALSE;
17983                :        } else {
17984                :            new = (pointer *) xalloc ((n + 1) * sizeof (pointer));
17985                :            if (!new)
17986                :                return FALSE;
17987                :            if (glyphSet->devPrivates)
17988                :                memcpy (new,
17989                :                        glyphSet->devPrivates,
17990                :                        (glyphSet->maxPrivate + 1) * sizeof (pointer));
17991                :        }
17992                :        glyphSet->devPrivates = new;
17993                :        /* Zero out new, uninitialize privates */
17994                :        while (++glyphSet->maxPrivate < n)
17995                :            glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer)0;
17996                :    }
17997                :    glyphSet->devPrivates[n] = ptr;
17998                :    return TRUE;
17999                :}
18000                :
18001                :GlyphRefPtr
18002                :FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare)
18003      9  0.0098 :{ /* FindGlyphRef total:     88  0.0959 */
18004                :    CARD32      elt, step, s;
18005                :    GlyphPtr    glyph;
18006                :    GlyphRefPtr table, gr, del;
18007      2  0.0022 :    CARD32      tableSize = hash->hashSet->size;
18008                :
18009      1  0.0011 :    table = hash->table;
18010     37  0.0403 :    elt = signature % tableSize;
18011                :    step = 0;
18012                :    del = 0;
18013                :    for (;;)
18014                :    {
18015      6  0.0065 :        gr = &table[elt];
18016     13  0.0142 :        s = gr->signature;
18017      2  0.0022 :        glyph = gr->glyph;
18018      5  0.0054 :        if (!glyph)
18019                :        {
18020                :            if (del)
18021                :                gr = del;
18022                :            break;
18023                :        }
18024                :        if (glyph == DeletedGlyph)
18025                :        {
18026                :            if (!del)
18027                :                del = gr;
18028                :            else if (gr == del)
18029                :                break;
18030                :        }
18031      2  0.0022 :        else if (s == signature &&
18032                :                 (!match || 
18033                :                  memcmp (&compare->info, &glyph->info, compare->size) == 0))
18034                :        {
18035                :            break;
18036                :        }
18037      3  0.0033 :        if (!step)
18038                :        {
18039      1  0.0011 :            step = signature % hash->hashSet->rehash;
18040      4  0.0044 :            if (!step)
18041                :                step = 1;
18042                :        }
18043                :        elt += step;
18044                :        if (elt >= tableSize)
18045                :            elt -= tableSize;
18046                :    }
18047                :    return gr;
18048      3  0.0033 :}
18049                :
18050                :CARD32
18051                :HashGlyph (GlyphPtr glyph)
18052                :{
18053                :    CARD32  *bits = (CARD32 *) &(glyph->info);
18054                :    CARD32  hash;
18055                :    int     n = glyph->size / sizeof (CARD32);
18056                :
18057                :    hash = 0;
18058                :    while (n--)
18059                :        hash ^= *bits++;
18060                :    return hash;
18061                :}
18062                :
18063                :#ifdef CHECK_DUPLICATES
18064                :void
18065                :DuplicateRef (GlyphPtr glyph, char *where)
18066                :{
18067                :    ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where);
18068                :}
18069                :
18070                :void
18071                :CheckDuplicates (GlyphHashPtr hash, char *where)
18072                :{
18073                :    GlyphPtr    g;
18074                :    int         i, j;
18075                :
18076                :    for (i = 0; i < hash->hashSet->size; i++)
18077                :    {
18078                :        g = hash->table[i].glyph;
18079                :        if (!g || g == DeletedGlyph)
18080                :            continue;
18081                :        for (j = i + 1; j < hash->hashSet->size; j++)
18082                :            if (hash->table[j].glyph == g)
18083                :                DuplicateRef (g, where);
18084                :    }
18085                :}
18086                :#else
18087                :#define CheckDuplicates(a,b)
18088                :#define DuplicateRef(a,b)
18089                :#endif
18090                :
18091                :void
18092                :FreeGlyph (GlyphPtr glyph, int format)
18093                :{
18094                :    CheckDuplicates (&globalGlyphs[format], "FreeGlyph");
18095                :    if (--glyph->refcnt == 0)
18096                :    {
18097                :        PictureScreenPtr ps;
18098                :        GlyphRefPtr      gr;
18099                :        int              i;
18100                :        int              first;
18101                :
18102                :        first = -1;
18103                :        for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
18104                :            if (globalGlyphs[format].table[i].glyph == glyph)
18105                :            {
18106                :                if (first != -1)
18107                :                    DuplicateRef (glyph, "FreeGlyph check");
18108                :                first = i;
18109                :            }
18110                :
18111                :        gr = FindGlyphRef (&globalGlyphs[format],
18112                :                           HashGlyph (glyph), TRUE, glyph);
18113                :        if (gr - globalGlyphs[format].table != first)
18114                :            DuplicateRef (glyph, "Found wrong one");
18115                :        if (gr->glyph && gr->glyph != DeletedGlyph)
18116                :        {
18117                :            gr->glyph = DeletedGlyph;
18118                :            gr->signature = 0;
18119                :            globalGlyphs[format].tableEntries--;
18120                :        }
18121                :
18122                :        for (i = 0; i < screenInfo.numScreens; i++)
18123                :        {
18124                :            ps = GetPictureScreenIfSet (screenInfo.screens[i]);
18125                :            if (ps)
18126                :                (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
18127                :        }
18128                :        
18129                :        if (glyph->devPrivates)
18130                :            xfree (glyph->devPrivates);
18131                :        xfree (glyph);
18132                :    }
18133                :}
18134                :
18135                :void
18136                :AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
18137                :{
18138                :    GlyphRefPtr     gr;
18139                :    CARD32          hash;
18140                :
18141                :    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
18142                :    /* Locate existing matching glyph */
18143                :    hash = HashGlyph (glyph);
18144                :    gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph);
18145                :    if (gr->glyph && gr->glyph != DeletedGlyph)
18146                :    {
18147                :        PictureScreenPtr ps;
18148                :        int              i;
18149                :        
18150                :        for (i = 0; i < screenInfo.numScreens; i++)
18151                :        {
18152                :            ps = GetPictureScreenIfSet (screenInfo.screens[i]);
18153                :            if (ps)
18154                :                (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
18155                :        }
18156                :        if (glyph->devPrivates)
18157                :            xfree (glyph->devPrivates);
18158                :        xfree (glyph);
18159                :        glyph = gr->glyph;
18160                :    }
18161                :    else
18162                :    {
18163                :        gr->glyph = glyph;
18164                :        gr->signature = hash;
18165                :        globalGlyphs[glyphSet->fdepth].tableEntries++;
18166                :    }
18167                :    
18168                :    /* Insert/replace glyphset value */
18169                :    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
18170                :    ++glyph->refcnt;
18171                :    if (gr->glyph && gr->glyph != DeletedGlyph)
18172                :        FreeGlyph (gr->glyph, glyphSet->fdepth);
18173                :    else
18174                :        glyphSet->hash.tableEntries++;
18175                :    gr->glyph = glyph;
18176                :    gr->signature = id;
18177                :    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
18178                :}
18179                :
18180                :Bool
18181                :DeleteGlyph (GlyphSetPtr glyphSet, Glyph id)
18182                :{
18183                :    GlyphRefPtr     gr;
18184                :    GlyphPtr        glyph;
18185                :
18186                :    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
18187                :    glyph = gr->glyph;
18188                :    if (glyph && glyph != DeletedGlyph)
18189                :    {
18190                :        gr->glyph = DeletedGlyph;
18191                :        glyphSet->hash.tableEntries--;
18192                :        FreeGlyph (glyph, glyphSet->fdepth);
18193                :        return TRUE;
18194                :    }
18195                :    return FALSE;
18196                :}
18197                :
18198                :GlyphPtr
18199                :FindGlyph (GlyphSetPtr glyphSet, Glyph id)
18200      6  0.0065 :{ /* FindGlyph total:     15  0.0163 */
18201                :    GlyphPtr        glyph;
18202                :
18203      3  0.0033 :    glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph;
18204      2  0.0022 :    if (glyph == DeletedGlyph)
18205                :        glyph = 0;
18206                :    return glyph;
18207      4  0.0044 :}
18208                :
18209                :GlyphPtr
18210                :AllocateGlyph (xGlyphInfo *gi, int fdepth)
18211                :{
18212                :    PictureScreenPtr ps;
18213                :    int              size;
18214                :    GlyphPtr         glyph;
18215                :    int              i;
18216                :
18217                :    size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]);
18218                :    glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec));
18219                :    if (!glyph)
18220                :        return 0;
18221                :    glyph->refcnt = 0;
18222                :    glyph->size = size + sizeof (xGlyphInfo);
18223                :    glyph->info = *gi;
18224                :
18225                :    if (globalTotalGlyphPrivateSize)
18226                :    {
18227                :        glyph->devPrivates = xalloc (globalTotalGlyphPrivateSize);
18228                :        if (!glyph->devPrivates)
18229                :            return 0;
18230                :
18231                :        SetGlyphPrivatePointers (glyph);
18232                :    } else
18233                :        glyph->devPrivates = NULL;
18234                :
18235                :    for (i = 0; i < screenInfo.numScreens; i++)
18236                :    {
18237                :        ps = GetPictureScreenIfSet (screenInfo.screens[i]);
18238                :        if (ps)
18239                :        {
18240                :            if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph))
18241                :            {
18242                :                while (i--)
18243                :                {
18244                :                    ps = GetPictureScreenIfSet (screenInfo.screens[i]);
18245                :                    if (ps)
18246                :                        (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
18247                :                }
18248                :                
18249                :                if (glyph->devPrivates)
18250                :                    xfree (glyph->devPrivates);
18251                :                xfree (glyph);
18252                :                return 0;
18253                :            }
18254                :        }
18255                :    }
18256                :    
18257                :    return glyph;
18258                :}
18259                :    
18260                :Bool
18261                :AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet)
18262                :{
18263                :    hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec));
18264                :    if (!hash->table)
18265                :        return FALSE;
18266                :    memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec));
18267                :    hash->hashSet = hashSet;
18268                :    hash->tableEntries = 0;
18269                :    return TRUE;
18270                :}
18271                :
18272                :Bool
18273                :ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global)
18274                :{
18275                :    CARD32          tableEntries;
18276                :    GlyphHashSetPtr hashSet;
18277                :    GlyphHashRec    newHash;
18278                :    GlyphRefPtr     gr;
18279                :    GlyphPtr        glyph;
18280                :    int             i;
18281                :    int             oldSize;
18282                :    CARD32          s;
18283                :
18284                :    tableEntries = hash->tableEntries + change;
18285                :    hashSet = FindGlyphHashSet (tableEntries);
18286                :    if (hashSet == hash->hashSet)
18287                :        return TRUE;
18288                :    if (global)
18289                :        CheckDuplicates (hash, "ResizeGlyphHash top");
18290                :    if (!AllocateGlyphHash (&newHash, hashSet))
18291                :        return FALSE;
18292                :    if (hash->table)
18293                :    {
18294                :        oldSize = hash->hashSet->size;
18295                :        for (i = 0; i < oldSize; i++)
18296                :        {
18297                :            glyph = hash->table[i].glyph;
18298                :            if (glyph && glyph != DeletedGlyph)
18299                :            {
18300                :                s = hash->table[i].signature;
18301                :                gr = FindGlyphRef (&newHash, s, global, glyph);
18302                :                gr->signature = s;
18303                :                gr->glyph = glyph;
18304                :                ++newHash.tableEntries;
18305                :            }
18306                :        }
18307                :        xfree (hash->table);
18308                :    }
18309                :    *hash = newHash;
18310                :    if (global)
18311                :        CheckDuplicates (hash, "ResizeGlyphHash bottom");
18312                :    return TRUE;
18313                :}
18314                :
18315                :Bool
18316                :ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change)
18317                :{
18318                :    return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) &&
18319                :            ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE));
18320                :}
18321                :                            
18322                :GlyphSetPtr
18323                :AllocateGlyphSet (int fdepth, PictFormatPtr format)
18324                :{
18325                :    GlyphSetPtr glyphSet;
18326                :    int size;
18327                :    
18328                :    if (!globalGlyphs[fdepth].hashSet)
18329                :    {
18330                :        if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0]))
18331                :            return FALSE;
18332                :    }
18333                :
18334                :    size = (sizeof (GlyphSetRec) +
18335                :            (sizeof (pointer) * _GlyphSetPrivateAllocateIndex));
18336                :    glyphSet = xalloc (size);
18337                :    if (!glyphSet)
18338                :        return FALSE;
18339                :    bzero((char *)glyphSet, size);
18340                :    glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1;
18341                :    if (_GlyphSetPrivateAllocateIndex)
18342                :        glyphSet->devPrivates = (pointer)(&glyphSet[1]);
18343                :
18344                :    if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0]))
18345                :    {
18346                :        xfree (glyphSet);
18347                :        return FALSE;
18348                :    }
18349                :    glyphSet->refcnt = 1;
18350                :    glyphSet->fdepth = fdepth;
18351                :    glyphSet->format = format;
18352                :    return glyphSet;    
18353                :}
18354                :
18355                :int
18356                :FreeGlyphSet (pointer   value,
18357                :              XID       gid)
18358                :{
18359                :    GlyphSetPtr glyphSet = (GlyphSetPtr) value;
18360                :    
18361                :    if (--glyphSet->refcnt == 0)
18362                :    {
18363                :        CARD32      i, tableSize = glyphSet->hash.hashSet->size;
18364                :        GlyphRefPtr table = glyphSet->hash.table;
18365                :        GlyphPtr    glyph;
18366                :    
18367                :        for (i = 0; i < tableSize; i++)
18368                :        {
18369                :            glyph = table[i].glyph;
18370                :            if (glyph && glyph != DeletedGlyph)
18371                :                FreeGlyph (glyph, glyphSet->fdepth);
18372                :        }
18373                :        if (!globalGlyphs[glyphSet->fdepth].tableEntries)
18374                :        {
18375                :            xfree (globalGlyphs[glyphSet->fdepth].table);
18376                :            globalGlyphs[glyphSet->fdepth].table = 0;
18377                :            globalGlyphs[glyphSet->fdepth].hashSet = 0;
18378                :        }
18379                :        else
18380                :            ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE);
18381                :        xfree (table);
18382                :
18383                :        if (glyphSet->devPrivates &&
18384                :            glyphSet->devPrivates != (pointer)(&glyphSet[1]))
18385                :            xfree(glyphSet->devPrivates);
18386                :
18387                :        xfree (glyphSet);
18388                :    }
18389                :    return Success;
18390                :}
18391 /* 
18392  * Total samples for file : "/home/cworth/src/xorg/xserver/Xext/xace.c"
18393  * 
18394  *    101  0.1100
18395  */
18396
18397
18398                :/************************************************************
18399                :
18400                :Author: Eamon Walsh <ewalsh@epoch.ncsc.mil>
18401                :
18402                :Permission to use, copy, modify, distribute, and sell this software and its
18403                :documentation for any purpose is hereby granted without fee, provided that
18404                :this permission notice appear in supporting documentation.  This permission
18405                :notice shall be included in all copies or substantial portions of the
18406                :Software.
18407                :
18408                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18409                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18410                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18411                :AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18412                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18413                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18414                :
18415                :********************************************************/
18416                :
18417                :#ifdef HAVE_DIX_CONFIG_H
18418                :#include <dix-config.h>
18419                :#endif
18420                :
18421                :#include <stdarg.h>
18422                :#include "windowstr.h"
18423                :#include "scrnintstr.h"
18424                :#include "gcstruct.h"
18425                :#include "xacestr.h"
18426                :#include "modinit.h"
18427                :
18428                :CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0};
18429                :
18430                :/* Proc vectors for untrusted clients, swapped and unswapped versions.
18431                : * These are the same as the normal proc vectors except that extensions
18432                : * that haven't declared themselves secure will have ProcBadRequest plugged
18433                : * in for their major opcode dispatcher.  This prevents untrusted clients
18434                : * from guessing extension major opcodes and using the extension even though
18435                : * the extension can't be listed or queried.
18436                : */
18437                :static int (*UntrustedProcVector[256])(
18438                :    ClientPtr /*client*/
18439                :);
18440                :static int (*SwappedUntrustedProcVector[256])(
18441                :    ClientPtr /*client*/
18442                :);
18443                :
18444                :/* Entry point for hook functions.  Called by Xserver.
18445                : */
18446                :int XaceHook(int hook, ...)
18447     22  0.0240 :{ /* XaceHook total:     74  0.0806 */
18448                :    pointer calldata;   /* data passed to callback */
18449                :    int *prv = NULL;    /* points to return value from callback */
18450                :    va_list ap;         /* argument list */
18451      8  0.0087 :    va_start(ap, hook);
18452                :
18453                :    /* Marshal arguments for passing to callback.
18454                :     * Each callback has its own case, which sets up a structure to hold
18455                :     * the arguments and integer return parameter, or in some cases just
18456                :     * sets calldata directly to a single argument (with no return result)
18457                :     */
18458      7  0.0076 :    switch (hook)
18459                :    {
18460                :        case XACE_CORE_DISPATCH: {
18461                :            XaceCoreDispatchRec rec = {
18462                :                va_arg(ap, ClientPtr),
18463                :                TRUE    /* default allow */
18464                :            };
18465                :            calldata = &rec;
18466                :            prv = &rec.rval;
18467                :            break;
18468                :        }
18469                :        case XACE_RESOURCE_ACCESS: {
18470                :            XaceResourceAccessRec rec = {
18471                :                va_arg(ap, ClientPtr),
18472                :                va_arg(ap, XID),
18473                :                va_arg(ap, RESTYPE),
18474                :                va_arg(ap, Mask),
18475                :                va_arg(ap, pointer),
18476                :                TRUE    /* default allow */
18477     13  0.0142 :            };
18478                :            calldata = &rec;
18479                :            prv = &rec.rval;
18480                :            break;
18481                :        }
18482                :        case XACE_DEVICE_ACCESS: {
18483                :            XaceDeviceAccessRec rec = {
18484                :                va_arg(ap, ClientPtr),
18485                :                va_arg(ap, DeviceIntPtr),
18486                :                va_arg(ap, Bool),
18487                :                TRUE    /* default allow */
18488                :            };
18489                :            calldata = &rec;
18490                :            prv = &rec.rval;
18491                :            break;
18492                :        }
18493                :        case XACE_PROPERTY_ACCESS: {
18494                :            XacePropertyAccessRec rec = {
18495                :                va_arg(ap, ClientPtr),
18496                :                va_arg(ap, WindowPtr),
18497                :                va_arg(ap, Atom),
18498                :                va_arg(ap, Mask),
18499                :                XaceAllowOperation   /* default allow */
18500                :            };
18501                :            calldata = &rec;
18502                :            prv = &rec.rval;
18503                :            break;
18504                :        }
18505                :        case XACE_DRAWABLE_ACCESS: {
18506                :            XaceDrawableAccessRec rec = {
18507                :                va_arg(ap, ClientPtr),
18508                :                va_arg(ap, DrawablePtr),
18509                :                TRUE    /* default allow */
18510                :            };
18511                :            calldata = &rec;
18512                :            prv = &rec.rval;
18513                :            break;
18514                :        }
18515                :        case XACE_MAP_ACCESS:
18516                :        case XACE_BACKGRND_ACCESS: {
18517                :            XaceMapAccessRec rec = {
18518                :                va_arg(ap, ClientPtr),
18519                :                va_arg(ap, WindowPtr),
18520                :                TRUE    /* default allow */
18521                :            };
18522                :            calldata = &rec;
18523                :            prv = &rec.rval;
18524                :            break;
18525                :        }
18526                :        case XACE_EXT_DISPATCH:
18527                :        case XACE_EXT_ACCESS: {
18528                :            XaceExtAccessRec rec = {
18529                :                va_arg(ap, ClientPtr),
18530                :                va_arg(ap, ExtensionEntry*),
18531                :                TRUE    /* default allow */
18532                :            };
18533                :            calldata = &rec;
18534                :            prv = &rec.rval;
18535                :            break;
18536                :        }
18537                :        case XACE_HOSTLIST_ACCESS: {
18538                :            XaceHostlistAccessRec rec = {
18539                :                va_arg(ap, ClientPtr),
18540                :                va_arg(ap, Mask),
18541                :                TRUE    /* default allow */
18542                :            };
18543                :            calldata = &rec;
18544                :            prv = &rec.rval;
18545                :            break;
18546                :        }
18547                :        case XACE_SITE_POLICY: {
18548                :            XaceSitePolicyRec rec = {
18549                :                va_arg(ap, char*),
18550                :                va_arg(ap, int),
18551                :                FALSE   /* default unrecognized */
18552                :            };
18553                :            calldata = &rec;
18554                :            prv = &rec.rval;
18555                :            break;
18556                :        }
18557                :        case XACE_DECLARE_EXT_SECURE: {
18558                :            XaceDeclareExtSecureRec rec = {
18559                :                va_arg(ap, ExtensionEntry*),
18560                :                va_arg(ap, Bool)
18561                :            };
18562                :            calldata = &rec;
18563                :            break;
18564                :        }
18565                :        case XACE_AUTH_AVAIL: {
18566                :            XaceAuthAvailRec rec = {
18567                :                va_arg(ap, ClientPtr),
18568                :                va_arg(ap, XID)
18569                :            };
18570                :            calldata = &rec;
18571                :            break;
18572                :        }
18573                :        case XACE_KEY_AVAIL: {
18574                :            XaceKeyAvailRec rec = {
18575                :                va_arg(ap, xEventPtr),
18576                :                va_arg(ap, DeviceIntPtr),
18577                :                va_arg(ap, int)
18578                :            };
18579                :            calldata = &rec;
18580                :            break;
18581                :        }
18582                :        case XACE_WINDOW_INIT: {
18583                :            XaceWindowRec rec = {
18584                :                va_arg(ap, ClientPtr),
18585                :                va_arg(ap, WindowPtr)
18586                :            };
18587                :            calldata = &rec;
18588                :            break;
18589                :        }
18590                :        case XACE_AUDIT_BEGIN: {
18591                :            XaceAuditRec rec = {
18592                :                va_arg(ap, ClientPtr),
18593                :                0
18594      2  0.0022 :            };
18595                :            calldata = &rec;
18596                :            break;
18597                :        }
18598                :        case XACE_AUDIT_END: {
18599                :            XaceAuditRec rec = {
18600                :                va_arg(ap, ClientPtr),
18601                :                va_arg(ap, int)
18602      2  0.0022 :            };
18603                :            calldata = &rec;
18604                :            break;
18605                :        }
18606                :        default: {
18607                :            va_end(ap);
18608                :            return 0;   /* unimplemented hook number */
18609                :        }
18610                :    }
18611                :    va_end(ap);
18612                : 
18613                :    /* call callbacks and return result, if any. */
18614     10  0.0109 :    CallCallbacks(&XaceHooks[hook], calldata);
18615      4  0.0044 :    return prv ? *prv : 0;
18616      6  0.0065 :}
18617                :
18618                :static int
18619                :ProcXaceDispatch(ClientPtr client)
18620                :{
18621                :    REQUEST(xReq);
18622                :
18623                :    switch (stuff->data)
18624                :    {
18625                :        default:
18626                :            return BadRequest;
18627                :    }
18628                :} /* ProcXaceDispatch */
18629                :
18630                :static int
18631                :SProcXaceDispatch(ClientPtr client)
18632                :{
18633                :    REQUEST(xReq);
18634                :
18635                :    switch (stuff->data)
18636                :    {
18637                :        default:
18638                :            return BadRequest;
18639                :    }
18640                :} /* SProcXaceDispatch */
18641                :
18642                :
18643                :/* XaceResetProc
18644                : *
18645                : * Arguments:
18646                : *      extEntry is the extension information for the XACE extension.
18647                : *
18648                : * Returns: nothing.
18649                : *
18650                : * Side Effects:
18651                : *      Performs any cleanup needed by XACE at server shutdown time.
18652                : */
18653                :static void
18654                :XaceResetProc(ExtensionEntry *extEntry)
18655                :{
18656                :    int i;
18657                :
18658                :    for (i=0; i<XACE_NUM_HOOKS; i++)
18659                :    {
18660                :        DeleteCallbackList(&XaceHooks[i]);
18661                :        XaceHooks[i] = NULL;
18662                :    }
18663                :} /* XaceResetProc */
18664                :
18665                :
18666                :static int
18667                :XaceCatchDispatchProc(ClientPtr client)
18668                :{ /* XaceCatchDispatchProc total:      5  0.0054 */
18669                :    REQUEST(xReq);
18670                :    int major = stuff->reqType;
18671                :
18672      5  0.0054 :    if (!ProcVector[major])
18673                :        return (BadRequest);
18674                :
18675                :    if (!XaceHook(XACE_CORE_DISPATCH, client))
18676                :        return (BadAccess);
18677                :
18678                :    return client->swapped ? 
18679                :        (* SwappedProcVector[major])(client) :
18680                :        (* ProcVector[major])(client);
18681                :}
18682                :
18683                :static int
18684                :XaceCatchExtProc(ClientPtr client)
18685      4  0.0044 :{ /* XaceCatchExtProc total:     22  0.0240 */
18686                :    REQUEST(xReq);
18687                :    int major = stuff->reqType;
18688      2  0.0022 :    ExtensionEntry *ext = GetExtensionEntry(major);
18689                :
18690      2  0.0022 :    if (!ext || !ProcVector[major])
18691                :        return (BadRequest);
18692                :
18693      1  0.0011 :    if (!XaceHook(XACE_EXT_DISPATCH, client, ext))
18694                :        return (BadRequest); /* pretend extension doesn't exist */
18695                :
18696      1  0.0011 :    return client->swapped ?
18697                :        (* SwappedProcVector[major])(client) :
18698                :        (* ProcVector[major])(client);
18699     12  0.0131 :}
18700                :
18701                :        
18702                :/* SecurityClientStateCallback
18703                : *
18704                : * Arguments:
18705                : *      pcbl is &ClientStateCallback.
18706                : *      nullata is NULL.
18707                : *      calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
18708                : *      which contains information about client state changes.
18709                : *
18710                : * Returns: nothing.
18711                : *
18712                : * Side Effects:
18713                : * 
18714                : * If a new client is connecting, its authorization ID is copied to
18715                : * client->authID.  If this is a generated authorization, its reference
18716                : * count is bumped, its timer is cancelled if it was running, and its
18717                : * trustlevel is copied to TRUSTLEVEL(client).
18718                : * 
18719                : * If a client is disconnecting and the client was using a generated
18720                : * authorization, the authorization's reference count is decremented, and
18721                : * if it is now zero, the timer for this authorization is started.
18722                : */
18723                :
18724                :static void
18725                :XaceClientStateCallback(
18726                :    CallbackListPtr *pcbl,
18727                :    pointer nulldata,
18728                :    pointer calldata)
18729                :{
18730                :    NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
18731                :    ClientPtr client = pci->client;
18732                :
18733                :    switch (client->clientState)
18734                :    {
18735                :        case ClientStateRunning:
18736                :        { 
18737                :            client->requestVector = client->swapped ?
18738                :                SwappedUntrustedProcVector : UntrustedProcVector;
18739                :            break;
18740                :        }
18741                :        default: break; 
18742                :    }
18743                :} /* XaceClientStateCallback */
18744                :
18745                :/* XaceExtensionInit
18746                : *
18747                : * Initialize the XACE Extension
18748                : */
18749                :void XaceExtensionInit(INITARGS)
18750                :{
18751                :    ExtensionEntry      *extEntry;
18752                :    int i;
18753                :
18754                :    if (!AddCallback(&ClientStateCallback, XaceClientStateCallback, NULL))
18755                :        return;
18756                :
18757                :    extEntry = AddExtension(XACE_EXTENSION_NAME,
18758                :                            XaceNumberEvents, XaceNumberErrors,
18759                :                            ProcXaceDispatch, SProcXaceDispatch,
18760                :                            XaceResetProc, StandardMinorOpcode);
18761                :
18762                :    /* initialize dispatching intercept functions */
18763                :    for (i = 0; i < 128; i++)
18764                :    {
18765                :        UntrustedProcVector[i] = XaceCatchDispatchProc;
18766                :        SwappedUntrustedProcVector[i] = XaceCatchDispatchProc;
18767                :    }
18768                :    for (i = 128; i < 256; i++)
18769                :    {
18770                :        UntrustedProcVector[i] = XaceCatchExtProc;
18771                :        SwappedUntrustedProcVector[i] = XaceCatchExtProc;
18772                :    }
18773                :}
18774                :
18775                :/* XaceCensorImage
18776                : *
18777                : * Called after pScreen->GetImage to prevent pieces or trusted windows from
18778                : * being returned in image data from an untrusted window.
18779                : *
18780                : * Arguments:
18781                : *      client is the client doing the GetImage.
18782                : *      pVisibleRegion is the visible region of the window.
18783                : *      widthBytesLine is the width in bytes of one horizontal line in pBuf.
18784                : *      pDraw is the source window.
18785                : *      x, y, w, h is the rectangle of image data from pDraw in pBuf.
18786                : *      format is the format of the image data in pBuf: ZPixmap or XYPixmap.
18787                : *      pBuf is the image data.
18788                : *
18789                : * Returns: nothing.
18790                : *
18791                : * Side Effects:
18792                : *      Any part of the rectangle (x, y, w, h) that is outside the visible
18793                : *      region of the window will be destroyed (overwritten) in pBuf.
18794                : */
18795                :void
18796                :XaceCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h,
18797                :                format, pBuf)
18798                :    ClientPtr client;
18799                :    RegionPtr pVisibleRegion;
18800                :    long widthBytesLine;
18801                :    DrawablePtr pDraw;
18802                :    int x, y, w, h;
18803                :    unsigned int format;
18804                :    char * pBuf;
18805                :{
18806                :    ScreenPtr pScreen;
18807                :    RegionRec imageRegion;  /* region representing x,y,w,h */
18808                :    RegionRec censorRegion; /* region to obliterate */
18809                :    BoxRec imageBox;
18810                :    int nRects;
18811                :
18812                :    pScreen = pDraw->pScreen;
18813                :
18814                :    imageBox.x1 = x;
18815                :    imageBox.y1 = y;
18816                :    imageBox.x2 = x + w;
18817                :    imageBox.y2 = y + h;
18818                :    REGION_INIT(pScreen, &imageRegion, &imageBox, 1);
18819                :    REGION_NULL(pScreen, &censorRegion);
18820                :
18821                :    /* censorRegion = imageRegion - visibleRegion */
18822                :    REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion);
18823                :    nRects = REGION_NUM_RECTS(&censorRegion);
18824                :    if (nRects > 0)
18825                :    { /* we have something to censor */
18826                :        GCPtr pScratchGC = NULL;
18827                :        PixmapPtr pPix = NULL;
18828                :        xRectangle *pRects = NULL;
18829                :        Bool failed = FALSE;
18830                :        int depth = 1;
18831                :        int bitsPerPixel = 1;
18832                :        int i;
18833                :        BoxPtr pBox;
18834                :
18835                :        /* convert region to list-of-rectangles for PolyFillRect */
18836                :
18837                :        pRects = (xRectangle *)ALLOCATE_LOCAL(nRects * sizeof(xRectangle *));
18838                :        if (!pRects)
18839                :        {
18840                :            failed = TRUE;
18841                :            goto failSafe;
18842                :        }
18843                :        for (pBox = REGION_RECTS(&censorRegion), i = 0;
18844                :             i < nRects;
18845                :             i++, pBox++)
18846                :        {
18847                :            pRects[i].x = pBox->x1;
18848                :            pRects[i].y = pBox->y1 - imageBox.y1;
18849                :            pRects[i].width  = pBox->x2 - pBox->x1;
18850                :            pRects[i].height = pBox->y2 - pBox->y1;
18851                :        }
18852                :
18853                :        /* use pBuf as a fake pixmap */
18854                :
18855                :        if (format == ZPixmap)
18856                :        {
18857                :            depth = pDraw->depth;
18858                :            bitsPerPixel = pDraw->bitsPerPixel;
18859                :        }
18860                :
18861                :        pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
18862                :                    depth, bitsPerPixel,
18863                :                    widthBytesLine, (pointer)pBuf);
18864                :        if (!pPix)
18865                :        {
18866                :            failed = TRUE;
18867                :            goto failSafe;
18868                :        }
18869                :
18870                :        pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
18871                :        if (!pScratchGC)
18872                :        {
18873                :            failed = TRUE;
18874                :            goto failSafe;
18875                :        }
18876                :
18877                :        ValidateGC(&pPix->drawable, pScratchGC);
18878                :        (* pScratchGC->ops->PolyFillRect)(&pPix->drawable,
18879                :                            pScratchGC, nRects, pRects);
18880                :
18881                :    failSafe:
18882                :        if (failed)
18883                :        {
18884                :            /* Censoring was not completed above.  To be safe, wipe out
18885                :             * all the image data so that nothing trusted gets out.
18886                :             */
18887                :            bzero(pBuf, (int)(widthBytesLine * h));
18888                :        }
18889                :        if (pRects)     DEALLOCATE_LOCAL(pRects);
18890                :        if (pScratchGC) FreeScratchGC(pScratchGC);
18891                :        if (pPix)       FreeScratchPixmapHeader(pPix);
18892                :    }
18893                :    REGION_UNINIT(pScreen, &imageRegion);
18894                :    REGION_UNINIT(pScreen, &censorRegion);
18895                :} /* XaceCensorImage */
18896 /* 
18897  * Total samples for file : "/home/cworth/src/xorg/xserver/dix/dixutils.c"
18898  * 
18899  *     87  0.0948
18900  */
18901
18902
18903                :/***********************************************************
18904                :
18905                :Copyright 1987, 1998  The Open Group
18906                :
18907                :Permission to use, copy, modify, distribute, and sell this software and its
18908                :documentation for any purpose is hereby granted without fee, provided that
18909                :the above copyright notice appear in all copies and that both that
18910                :copyright notice and this permission notice appear in supporting
18911                :documentation.
18912                :
18913                :The above copyright notice and this permission notice shall be included in
18914                :all copies or substantial portions of the Software.
18915                :
18916                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18917                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18918                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18919                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18920                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18921                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18922                :
18923                :Except as contained in this notice, the name of The Open Group shall not be
18924                :used in advertising or otherwise to promote the sale, use or other dealings
18925                :in this Software without prior written authorization from The Open Group.
18926                :
18927                :
18928                :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
18929                :
18930                :                        All Rights Reserved
18931                :
18932                :Permission to use, copy, modify, and distribute this software and its 
18933                :documentation for any purpose and without fee is hereby granted, 
18934                :provided that the above copyright notice appear in all copies and that
18935                :both that copyright notice and this permission notice appear in 
18936                :supporting documentation, and that the name of Digital not be
18937                :used in advertising or publicity pertaining to distribution of the
18938                :software without specific, written prior permission.  
18939                :
18940                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
18941                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18942                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18943                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18944                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
18945                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
18946                :SOFTWARE.
18947                :
18948                :******************************************************************/
18949                :
18950                :/*
18951                :
18952                :(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved.
18953                :
18954                :Permission to use, copy, modify, distribute, and sublicense this software and its
18955                :documentation for any purpose and without fee is hereby granted, provided that
18956                :the above copyright notices appear in all copies and that both those copyright
18957                :notices and this permission notice appear in supporting documentation and that
18958                :the name of Adobe Systems Incorporated not be used in advertising or publicity
18959                :pertaining to distribution of the software without specific, written prior
18960                :permission.  No trademark license to use the Adobe trademarks is hereby
18961                :granted.  If the Adobe trademark "Display PostScript"(tm) is used to describe
18962                :this software, its functionality or for any other purpose, such use shall be
18963                :limited to a statement that this software works in conjunction with the Display
18964                :PostScript system.  Proper trademark attribution to reflect Adobe's ownership
18965                :of the trademark shall be given whenever any such reference to the Display
18966                :PostScript system is made.
18967                :
18968                :ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
18969                :PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.  ADOBE
18970                :DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
18971                :WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
18972                :INFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
18973                :OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
18974                :DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
18975                :LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18976                :PERFORMANCE OF THIS SOFTWARE.  ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
18977                :SUPPORT FOR THE SOFTWARE.
18978                :
18979                :Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
18980                :Incorporated which may be registered in certain jurisdictions.
18981                :
18982                :Author:  Adobe Systems Incorporated
18983                :
18984                :*/
18985                :
18986                :
18987                :#ifdef HAVE_DIX_CONFIG_H
18988                :#include <dix-config.h>
18989                :#endif
18990                :
18991                :#include <X11/X.h>
18992                :#include <X11/Xmd.h>
18993                :#include "misc.h"
18994                :#include "windowstr.h"
18995                :#include "dixstruct.h"
18996                :#include "pixmapstr.h"
18997                :#include "scrnintstr.h"
18998                :#define  XK_LATIN1
18999                :#include <X11/keysymdef.h>
19000                :#include "xace.h"
19001                :
19002                :/*
19003                : * CompareTimeStamps returns -1, 0, or +1 depending on if the first
19004                : * argument is less than, equal to or greater than the second argument.
19005                : */
19006                :
19007                :_X_EXPORT int
19008                :CompareTimeStamps(TimeStamp a, TimeStamp b)
19009                :{
19010                :    if (a.months < b.months)
19011                :        return EARLIER;
19012                :    if (a.months > b.months)
19013                :        return LATER;
19014                :    if (a.milliseconds < b.milliseconds)
19015                :        return EARLIER;
19016                :    if (a.milliseconds > b.milliseconds)
19017                :        return LATER;
19018                :    return SAMETIME;
19019                :}
19020                :
19021                :/*
19022                : * convert client times to server TimeStamps
19023                : */
19024                :
19025                :#define HALFMONTH ((unsigned long) 1<<31)
19026                :_X_EXPORT TimeStamp
19027                :ClientTimeToServerTime(CARD32 c)
19028                :{
19029                :    TimeStamp ts;
19030                :    if (c == CurrentTime)
19031                :        return currentTime;
19032                :    ts.months = currentTime.months;
19033                :    ts.milliseconds = c;
19034                :    if (c > currentTime.milliseconds)
19035                :    {
19036                :        if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH)
19037                :            ts.months -= 1;
19038                :    }
19039                :    else if (c < currentTime.milliseconds)
19040                :    {
19041                :        if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH)
19042                :            ts.months += 1;
19043                :    }
19044                :    return ts;
19045                :}
19046                :
19047                :/*
19048                : * ISO Latin-1 case conversion routine
19049                : *
19050                : * this routine always null-terminates the result, so
19051                : * beware of too-small buffers
19052                : */
19053                :
19054                :static unsigned char
19055                :ISOLatin1ToLower (unsigned char source)
19056                :{
19057                :    unsigned char   dest;
19058                :    if ((source >= XK_A) && (source <= XK_Z))
19059                :       dest = source + (XK_a - XK_A);
19060                :    else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis))
19061                :       dest = source + (XK_agrave - XK_Agrave);
19062                :    else if ((source >= XK_Ooblique) && (source <= XK_Thorn))
19063                :       dest = source + (XK_oslash - XK_Ooblique);
19064                :    else
19065                :       dest = source;
19066                :    return dest;
19067                :}
19068                :
19069                :
19070                :_X_EXPORT void
19071                :CopyISOLatin1Lowered(unsigned char *dest, unsigned char *source, int length)
19072                :{
19073                :    int i;
19074                :
19075                :    for (i = 0; i < length; i++, source++, dest++)
19076                :        *dest = ISOLatin1ToLower (*source);
19077                :    *dest = '\0';
19078                :}
19079                :
19080                :int
19081                :CompareISOLatin1Lowered(unsigned char *s1, int s1len, 
19082                :                        unsigned char *s2, int s2len)
19083      1  0.0011 :{ /* CompareISOLatin1Lowered total:     22  0.0240 */
19084                :    unsigned char   c1, c2;
19085                :    
19086                :    for (;;) 
19087                :    {
19088                :        /* note -- compare against zero so that -1 ignores len */
19089      8  0.0087 :        c1 = s1len-- ? *s1++ : '\0';
19090     10  0.0109 :        c2 = s2len-- ? *s2++ : '\0';
19091      3  0.0033 :        if (!c1 || 
19092                :            (c1 != c2 && 
19093                :             (c1 = ISOLatin1ToLower (c1)) != (c2 = ISOLatin1ToLower (c2))))
19094                :            break;
19095                :    }
19096                :    return (int) c1 - (int) c2;
19097                :}
19098                :
19099                :/*
19100                : * dixLookupWindow and dixLookupDrawable:
19101                : * Look up the window/drawable taking into account the client doing the
19102                : * lookup, the type of drawable desired, and the type of access desired.
19103                : * Return Success with *pDraw set if the window/drawable exists and the client
19104                : * is allowed access, else return an error code with *pDraw set to NULL.  The
19105                : * access mask values are defined in resource.h.  The type mask values are
19106                : * defined in pixmap.h, with zero equivalent to M_DRAWABLE.
19107                : */
19108                :_X_EXPORT int
19109                :dixLookupDrawable(DrawablePtr *pDraw, XID id, ClientPtr client,
19110                :                  Mask type, Mask access)
19111      1  0.0011 :{ /* dixLookupDrawable total:      6  0.0065 */
19112                :    DrawablePtr pTmp;
19113                :    RESTYPE rtype;
19114                :    *pDraw = NULL;
19115                :    client->errorValue = id;
19116                :
19117                :    if (id == INVALID)
19118                :        return BadDrawable;
19119                :
19120                :    if (id == client->lastDrawableID) {
19121                :        pTmp = client->lastDrawable;
19122                :
19123                :        /* an access check is required for cached drawables */
19124                :        rtype = (type & M_WINDOW) ? RT_WINDOW : RT_PIXMAP;
19125                :        if (!XaceHook(XACE_RESOURCE_ACCESS, client, id, rtype, access, pTmp))
19126                :            return BadDrawable;
19127                :    } else
19128                :        pTmp = (DrawablePtr)SecurityLookupIDByClass(client, id, RC_DRAWABLE,
19129                :                                                   access);
19130                :    if (!pTmp)
19131                :        return BadDrawable;
19132      3  0.0033 :    if (!((1 << pTmp->type) & (type ? type : M_DRAWABLE)))
19133                :        return BadMatch;
19134                :
19135                :    if (type & M_DRAWABLE) {
19136                :        client->lastDrawable = pTmp;
19137                :        client->lastDrawableID = id;
19138                :        client->lastGCID = INVALID;
19139                :        client->lastGC = (GCPtr)NULL;
19140                :    }
19141                :    *pDraw = pTmp;
19142                :    return Success;
19143      2  0.0022 :}
19144                :
19145                :_X_EXPORT int
19146                :dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
19147                :{
19148                :    int rc;
19149                :    rc = dixLookupDrawable((DrawablePtr*)pWin, id, client, M_WINDOW, access);
19150                :    return (rc == BadDrawable) ? BadWindow : rc;
19151                :}
19152                :
19153                :_X_EXPORT int
19154                :dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access)
19155      1  0.0011 :{ /* dixLookupGC total:      2  0.0022 */
19156      1  0.0011 :    GCPtr pTmp = (GCPtr)SecurityLookupIDByType(client, id, RT_GC, access);
19157                :    if (pTmp) {
19158                :        *pGC = pTmp;
19159                :        return Success;
19160                :    }
19161                :    client->errorValue = id;
19162                :    *pGC = NULL;
19163                :    return BadGC;
19164                :}
19165                :
19166                :_X_EXPORT int
19167                :dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access)
19168                :{
19169                :    pointer pRes = (pointer)SecurityLookupIDByClass(client, rid, RC_ANY,
19170                :                                                    access);
19171                :    int clientIndex = CLIENT_ID(rid);
19172                :    client->errorValue = rid;
19173                :
19174                :    if (clientIndex && pRes && clients[clientIndex] && !(rid & SERVER_BIT)) {
19175                :        *pClient = clients[clientIndex];
19176                :        return Success;
19177                :    }
19178                :    *pClient = NULL;
19179                :    return BadValue;
19180                :}
19181                :
19182                :/*
19183                : * These are deprecated compatibility functions and will be removed soon!
19184                : * Please use the new dixLookup*() functions above.
19185                : */
19186                :_X_EXPORT _X_DEPRECATED WindowPtr
19187                :SecurityLookupWindow(XID id, ClientPtr client, Mask access_mode)
19188                :{
19189                :    WindowPtr pWin;
19190                :    int i = dixLookupWindow(&pWin, id, client, access_mode);
19191                :    static int warn = 1;
19192                :    if (warn-- > 0)
19193                :        ErrorF("Warning: LookupWindow()/SecurityLookupWindow() "
19194                :               "are deprecated.  Please convert your driver/module "
19195                :               "to use dixLookupWindow().\n");
19196                :    return (i == Success) ? pWin : NULL;
19197                :}
19198                :
19199                :_X_EXPORT _X_DEPRECATED WindowPtr
19200                :LookupWindow(XID id, ClientPtr client)
19201                :{
19202                :    return SecurityLookupWindow(id, client, DixUnknownAccess);
19203                :}
19204                :
19205                :_X_EXPORT _X_DEPRECATED pointer
19206                :SecurityLookupDrawable(XID id, ClientPtr client, Mask access_mode)
19207                :{
19208                :    DrawablePtr pDraw;
19209                :    int i = dixLookupDrawable(&pDraw, id, client, M_DRAWABLE, access_mode);
19210                :    static int warn = 1;
19211                :    if (warn-- > 0)
19212                :        ErrorF("Warning: LookupDrawable()/SecurityLookupDrawable() "
19213                :               "are deprecated.  Please convert your driver/module "
19214                :               "to use dixLookupDrawable().\n");
19215                :    return (i == Success) ? pDraw : NULL;
19216                :}
19217                :
19218                :_X_EXPORT _X_DEPRECATED pointer
19219                :LookupDrawable(XID id, ClientPtr client)
19220                :{
19221                :    return SecurityLookupDrawable(id, client, DixUnknownAccess);
19222                :}
19223                :
19224                :_X_EXPORT _X_DEPRECATED ClientPtr
19225                :LookupClient(XID id, ClientPtr client)
19226                :{
19227                :    ClientPtr pClient;
19228                :    int i = dixLookupClient(&pClient, id, client, DixUnknownAccess);
19229                :    static int warn = 1;
19230                :    if (warn-- > 0)
19231                :        ErrorF("Warning: LookupClient() is deprecated.  Please convert your "
19232                :               "driver/module to use dixLookupClient().\n");
19233                :    return (i == Success) ? pClient : NULL;
19234                :}
19235                :
19236                :/* end deprecated functions */
19237                :
19238                :int
19239                :AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
19240                :                      Bool toRoot, Bool remap)
19241                :{
19242                :    int numnow;
19243                :    SaveSetElt *pTmp = NULL;
19244                :    int j;
19245                :
19246                :    numnow = client->numSaved;
19247                :    j = 0;
19248                :    if (numnow)
19249                :    {
19250                :        pTmp = client->saveSet;
19251                :        while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (pointer)pWin))
19252                :            j++;
19253                :    }
19254                :    if (mode == SetModeInsert)
19255                :    {
19256                :        if (j < numnow)         /* duplicate */
19257                :           return(Success);
19258                :        numnow++;
19259                :        pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow);
19260                :        if (!pTmp)
19261                :            return(BadAlloc);
19262                :        client->saveSet = pTmp;
19263                :        client->numSaved = numnow;
19264                :        SaveSetAssignWindow(client->saveSet[numnow - 1], pWin);
19265                :        SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot);
19266                :        SaveSetAssignRemap(client->saveSet[numnow - 1], remap);
19267                :        return(Success);
19268                :    }
19269                :    else if ((mode == SetModeDelete) && (j < numnow))
19270                :    {
19271                :        while (j < numnow-1)
19272                :        {
19273                :           pTmp[j] = pTmp[j+1];
19274                :           j++;
19275                :        }
19276                :        numnow--;
19277                :        if (numnow)
19278                :        {
19279                :            pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow);
19280                :            if (pTmp)
19281                :                client->saveSet = pTmp;
19282                :        }
19283                :        else
19284                :        {
19285                :            xfree(client->saveSet);
19286                :            client->saveSet = (SaveSetElt *)NULL;
19287                :        }
19288                :        client->numSaved = numnow;
19289                :        return(Success);
19290                :    }
19291                :    return(Success);
19292                :}
19293                :
19294                :void
19295                :DeleteWindowFromAnySaveSet(WindowPtr pWin)
19296                :{
19297                :    int i;
19298                :    ClientPtr client;
19299                :    
19300                :    for (i = 0; i< currentMaxClients; i++)
19301                :    {    
19302                :        client = clients[i];
19303                :        if (client && client->numSaved)
19304                :            (void)AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE, TRUE);
19305                :    }
19306                :}
19307                :
19308                :/* No-op Don't Do Anything : sometimes we need to be able to call a procedure
19309                : * that doesn't do anything.  For example, on screen with only static
19310                : * colormaps, if someone calls install colormap, it's easier to have a dummy
19311                : * procedure to call than to check if there's a procedure 
19312                : */
19313                :_X_EXPORT void
19314                :NoopDDA(void)
19315                :{
19316                :}
19317                :
19318                :typedef struct _BlockHandler {
19319                :    BlockHandlerProcPtr BlockHandler;
19320                :    WakeupHandlerProcPtr WakeupHandler;
19321                :    pointer blockData;
19322                :    Bool    deleted;
19323                :} BlockHandlerRec, *BlockHandlerPtr;
19324                :
19325                :static BlockHandlerPtr  handlers;
19326                :static int              numHandlers;
19327                :static int              sizeHandlers;
19328                :static Bool             inHandler;
19329                :static Bool             handlerDeleted;
19330                :
19331                :/**
19332                : * 
19333                : *  \param pTimeout   DIX doesn't want to know how OS represents time
19334                : *  \param pReadMask  nor how it represents the det of descriptors
19335                : */
19336                :void
19337                :BlockHandler(pointer pTimeout, pointer pReadmask)
19338                :{
19339                :    int i, j;
19340                :    
19341                :    ++inHandler;
19342                :    for (i = 0; i < screenInfo.numScreens; i++)
19343                :        (* screenInfo.screens[i]->BlockHandler)(i, 
19344                :                                screenInfo.screens[i]->blockData,
19345                :                                pTimeout, pReadmask);
19346                :    for (i = 0; i < numHandlers; i++)
19347                :        (*handlers[i].BlockHandler) (handlers[i].blockData,
19348                :                                     pTimeout, pReadmask);
19349                :    if (handlerDeleted)
19350                :    {
19351                :        for (i = 0; i < numHandlers;)
19352                :            if (handlers[i].deleted)
19353                :            {
19354                :                for (j = i; j < numHandlers - 1; j++)
19355                :                    handlers[j] = handlers[j+1];
19356                :                numHandlers--;
19357                :            }
19358                :            else
19359                :                i++;
19360                :        handlerDeleted = FALSE;
19361                :    }
19362                :    --inHandler;
19363                :}
19364                :
19365                :/**
19366                : *
19367                : *  \param result    32 bits of undefined result from the wait
19368                : *  \param pReadmask the resulting descriptor mask
19369                : */
19370                :void
19371                :WakeupHandler(int result, pointer pReadmask)
19372                :{
19373                :    int i, j;
19374                :
19375                :    ++inHandler;
19376                :    for (i = numHandlers - 1; i >= 0; i--)
19377                :        (*handlers[i].WakeupHandler) (handlers[i].blockData,
19378                :                                      result, pReadmask);
19379                :    for (i = 0; i < screenInfo.numScreens; i++)
19380                :        (* screenInfo.screens[i]->WakeupHandler)(i, 
19381                :                                screenInfo.screens[i]->wakeupData,
19382                :                                result, pReadmask);
19383                :    if (handlerDeleted)
19384                :    {
19385                :        for (i = 0; i < numHandlers;)
19386                :            if (handlers[i].deleted)
19387                :            {
19388                :                for (j = i; j < numHandlers - 1; j++)
19389                :                    handlers[j] = handlers[j+1];
19390                :                numHandlers--;
19391                :            }
19392                :            else
19393                :                i++;
19394                :        handlerDeleted = FALSE;
19395                :    }
19396                :    --inHandler;
19397                :}
19398                :
19399                :/**
19400                : * Reentrant with BlockHandler and WakeupHandler, except wakeup won't
19401                : * get called until next time
19402                : */
19403                :_X_EXPORT Bool
19404                :RegisterBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler, 
19405                :                                WakeupHandlerProcPtr wakeupHandler, 
19406                :                                pointer blockData)
19407                :{
19408                :    BlockHandlerPtr new;
19409                :
19410                :    if (numHandlers >= sizeHandlers)
19411                :    {
19412                :        new = (BlockHandlerPtr) xrealloc (handlers, (numHandlers + 1) *
19413                :                                          sizeof (BlockHandlerRec));
19414                :        if (!new)
19415                :            return FALSE;
19416                :        handlers = new;
19417                :        sizeHandlers = numHandlers + 1;
19418                :    }
19419                :    handlers[numHandlers].BlockHandler = blockHandler;
19420                :    handlers[numHandlers].WakeupHandler = wakeupHandler;
19421                :    handlers[numHandlers].blockData = blockData;
19422                :    handlers[numHandlers].deleted = FALSE;
19423                :    numHandlers = numHandlers + 1;
19424                :    return TRUE;
19425                :}
19426                :
19427                :_X_EXPORT void
19428                :RemoveBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler, 
19429                :                              WakeupHandlerProcPtr wakeupHandler, 
19430                :                              pointer blockData)
19431                :{
19432                :    int     i;
19433                :
19434                :    for (i = 0; i < numHandlers; i++)
19435                :        if (handlers[i].BlockHandler == blockHandler &&
19436                :            handlers[i].WakeupHandler == wakeupHandler &&
19437                :            handlers[i].blockData == blockData)
19438                :        {
19439                :            if (inHandler)
19440                :            {
19441                :                handlerDeleted = TRUE;
19442                :                handlers[i].deleted = TRUE;
19443                :            }
19444                :            else
19445                :            {
19446                :                for (; i < numHandlers - 1; i++)
19447                :                    handlers[i] = handlers[i+1];
19448                :                numHandlers--;
19449                :            }
19450                :            break;
19451                :        }
19452                :}
19453                :
19454                :void
19455                :InitBlockAndWakeupHandlers (void)
19456                :{
19457                :    xfree (handlers);
19458                :    handlers = (BlockHandlerPtr) 0;
19459                :    numHandlers = 0;
19460                :    sizeHandlers = 0;
19461                :}
19462                :
19463                :/*
19464                : * A general work queue.  Perform some task before the server
19465                : * sleeps for input.
19466                : */
19467                :
19468                :WorkQueuePtr            workQueue;
19469                :static WorkQueuePtr     *workQueueLast = &workQueue;
19470                :
19471                :void
19472                :ProcessWorkQueue(void)
19473                :{
19474                :    WorkQueuePtr    q, *p;
19475                :
19476                :    p = &workQueue;
19477                :    /*
19478                :     * Scan the work queue once, calling each function.  Those
19479                :     * which return TRUE are removed from the queue, otherwise
19480                :     * they will be called again.  This must be reentrant with
19481                :     * QueueWorkProc.
19482                :     */
19483                :    while ((q = *p))
19484                :    {
19485                :        if ((*q->function) (q->client, q->closure))
19486                :        {
19487                :            /* remove q from the list */
19488                :            *p = q->next;    /* don't fetch until after func called */
19489                :            xfree (q);
19490                :        }
19491                :        else
19492                :        {
19493                :            p = &q->next;    /* don't fetch until after func called */
19494                :        }
19495                :    }
19496                :    workQueueLast = p;
19497                :}
19498                :
19499                :void
19500                :ProcessWorkQueueZombies(void)
19501                :{
19502                :    WorkQueuePtr    q, *p;
19503                :
19504                :    p = &workQueue;
19505                :    while ((q = *p))
19506                :    {
19507                :        if (q->client && q->client->clientGone)
19508                :        {
19509                :            (void) (*q->function) (q->client, q->closure);
19510                :            /* remove q from the list */
19511                :            *p = q->next;    /* don't fetch until after func called */
19512                :            xfree (q);
19513                :        }
19514                :        else
19515                :        {
19516                :            p = &q->next;    /* don't fetch until after func called */
19517                :        }
19518                :    }
19519                :    workQueueLast = p;
19520                :}
19521                :
19522                :_X_EXPORT Bool
19523                :QueueWorkProc (
19524                :    Bool (*function)(ClientPtr /* pClient */, pointer /* closure */),
19525                :    ClientPtr client, pointer closure)
19526                :{
19527                :    WorkQueuePtr    q;
19528                :
19529                :    q = (WorkQueuePtr) xalloc (sizeof *q);
19530                :    if (!q)
19531                :        return FALSE;
19532                :    q->function = function;
19533                :    q->client = client;
19534                :    q->closure = closure;
19535                :    q->next = NULL;
19536                :    *workQueueLast = q;
19537                :    workQueueLast = &q->next;
19538                :    return TRUE;
19539                :}
19540                :
19541                :/*
19542                : * Manage a queue of sleeping clients, awakening them
19543                : * when requested, by using the OS functions IgnoreClient
19544                : * and AttendClient.  Note that this *ignores* the troubles
19545                : * with request data interleaving itself with events, but
19546                : * we'll leave that until a later time.
19547                : */
19548                :
19549                :typedef struct _SleepQueue {
19550                :    struct _SleepQueue  *next;
19551                :    ClientPtr           client;
19552                :    ClientSleepProcPtr  function;
19553                :    pointer             closure;
19554                :} SleepQueueRec, *SleepQueuePtr;
19555                :
19556                :static SleepQueuePtr    sleepQueue = NULL;
19557                :
19558                :_X_EXPORT Bool
19559                :ClientSleep (ClientPtr client, ClientSleepProcPtr function, pointer closure)
19560                :{
19561                :    SleepQueuePtr   q;
19562                :
19563                :    q = (SleepQueuePtr) xalloc (sizeof *q);
19564                :    if (!q)
19565                :        return FALSE;
19566                :
19567                :    IgnoreClient (client);
19568                :    q->next = sleepQueue;
19569                :    q->client = client;
19570                :    q->function = function;
19571                :    q->closure = closure;
19572                :    sleepQueue = q;
19573                :    return TRUE;
19574                :}
19575                :
19576                :Bool
19577                :ClientSignal (ClientPtr client)
19578                :{
19579                :    SleepQueuePtr   q;
19580                :
19581                :    for (q = sleepQueue; q; q = q->next)
19582                :        if (q->client == client)
19583                :        {
19584                :            return QueueWorkProc (q->function, q->client, q->closure);
19585                :        }
19586                :    return FALSE;
19587                :}
19588                :
19589                :_X_EXPORT void
19590                :ClientWakeup (ClientPtr client)
19591                :{
19592                :    SleepQueuePtr   q, *prev;
19593                :
19594                :    prev = &sleepQueue;
19595                :    while ( (q = *prev) )
19596                :    {
19597                :        if (q->client == client)
19598                :        {
19599                :            *prev = q->next;
19600                :            xfree (q);
19601                :            if (client->clientGone)
19602                :                /* Oops -- new zombie cleanup code ensures this only
19603                :                 * happens from inside CloseDownClient; don't want to
19604                :                 * recurse here...
19605                :                 */
19606                :                /* CloseDownClient(client) */;
19607                :            else
19608                :                AttendClient (client);
19609                :            break;
19610                :        }
19611                :        prev = &q->next;
19612                :    }
19613                :}
19614                :
19615                :Bool
19616                :ClientIsAsleep (ClientPtr client)
19617                :{
19618                :    SleepQueuePtr   q;
19619                :
19620                :    for (q = sleepQueue; q; q = q->next)
19621                :        if (q->client == client)
19622                :            return TRUE;
19623                :    return FALSE;
19624                :}
19625                :
19626                :/*
19627                : *  Generic Callback Manager
19628                : */
19629                :
19630                :/* ===== Private Procedures ===== */
19631                :
19632                :static int numCallbackListsToCleanup = 0;
19633                :static CallbackListPtr **listsToCleanup = NULL;
19634                :
19635                :static Bool 
19636                :_AddCallback(
19637                :    CallbackListPtr *pcbl,
19638                :    CallbackProcPtr callback,
19639                :    pointer         data)
19640                :{
19641                :    CallbackPtr     cbr;
19642                :
19643                :    cbr = (CallbackPtr) xalloc(sizeof(CallbackRec));
19644                :    if (!cbr)
19645                :        return FALSE;
19646                :    cbr->proc = callback;
19647                :    cbr->data = data;
19648                :    cbr->next = (*pcbl)->list;
19649                :    cbr->deleted = FALSE;
19650                :    (*pcbl)->list = cbr;
19651                :    return TRUE;
19652                :}
19653                :
19654                :static Bool 
19655                :_DeleteCallback(
19656                :    CallbackListPtr *pcbl,
19657                :    CallbackProcPtr callback,
19658                :    pointer         data)
19659                :{
19660                :    CallbackListPtr cbl = *pcbl;
19661                :    CallbackPtr     cbr, pcbr;
19662                :
19663                :    for (pcbr = NULL, cbr = cbl->list;
19664                :         cbr != NULL;
19665                :         pcbr = cbr, cbr = cbr->next)
19666                :    {
19667                :        if ((cbr->proc == callback) && (cbr->data == data))
19668                :            break;
19669                :    }
19670                :    if (cbr != NULL)
19671                :    {
19672                :        if (cbl->inCallback)
19673                :        {
19674                :            ++(cbl->numDeleted);
19675                :            cbr->deleted = TRUE;
19676                :        }
19677                :        else
19678                :        {
19679                :            if (pcbr == NULL)
19680                :                cbl->list = cbr->next;
19681                :            else
19682                :                pcbr->next = cbr->next;
19683                :            xfree(cbr);
19684                :        }
19685                :        return TRUE;
19686                :    }
19687                :    return FALSE;
19688                :}
19689                :
19690                :static void 
19691                :_CallCallbacks(
19692                :    CallbackListPtr    *pcbl,
19693                :    pointer         call_data)
19694     17  0.0185 :{ /* _CallCallbacks total:     30  0.0327 */
19695                :    CallbackListPtr cbl = *pcbl;
19696                :    CallbackPtr     cbr, pcbr;
19697                :
19698      3  0.0033 :    ++(cbl->inCallback);
19699      3  0.0033 :    for (cbr = cbl->list; cbr != NULL; cbr = cbr->next)
19700                :    {
19701      6  0.0065 :        (*(cbr->proc)) (pcbl, cbr->data, call_data);
19702                :    }
19703                :    --(cbl->inCallback);
19704                :
19705                :    if (cbl->inCallback) return;
19706                :
19707                :    /* Was the entire list marked for deletion? */
19708                :
19709      1  0.0011 :    if (cbl->deleted)
19710                :    {
19711                :        DeleteCallbackList(pcbl);
19712                :        return;
19713                :    }
19714                :
19715                :    /* Were some individual callbacks on the list marked for deletion?
19716                :     * If so, do the deletions.
19717                :     */
19718                :
19719                :    if (cbl->numDeleted)
19720                :    {
19721                :        for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; )
19722                :        {
19723                :            if (cbr->deleted)
19724                :            {
19725                :                if (pcbr)
19726                :                {
19727                :                    cbr = cbr->next;
19728                :                    xfree(pcbr->next);
19729                :                    pcbr->next = cbr;
19730                :                } else
19731                :                {
19732                :                    cbr = cbr->next;
19733                :                    xfree(cbl->list);
19734                :                    cbl->list = cbr;
19735                :                }
19736                :                cbl->numDeleted--;
19737                :            }
19738                :            else /* this one wasn't deleted */
19739                :            {
19740                :                pcbr = cbr;
19741                :                cbr = cbr->next;
19742                :            }
19743                :        }
19744                :    }
19745                :}
19746                :
19747                :static void
19748                :_DeleteCallbackList(
19749                :    CallbackListPtr    *pcbl)
19750                :{
19751                :    CallbackListPtr cbl = *pcbl;
19752                :    CallbackPtr     cbr, nextcbr;
19753                :    int i;
19754                :
19755                :    if (cbl->inCallback)
19756                :    {
19757                :        cbl->deleted = TRUE;
19758                :        return;
19759                :    }
19760                :
19761                :    for (i = 0; i < numCallbackListsToCleanup; i++)
19762                :    {
19763                :        if ((listsToCleanup[i] = pcbl) != 0)
19764                :        {
19765                :            listsToCleanup[i] = NULL;
19766                :            break;
19767                :        }
19768                :    }
19769                :
19770                :    for (cbr = cbl->list; cbr != NULL; cbr = nextcbr)
19771                :    {
19772                :        nextcbr = cbr->next;
19773                :        xfree(cbr);
19774                :    }
19775                :    xfree(cbl);
19776                :    *pcbl = NULL;
19777                :}
19778                :
19779                :static CallbackFuncsRec default_cbfuncs =
19780                :{
19781                :    _AddCallback,
19782                :    _DeleteCallback,
19783                :    _CallCallbacks,
19784                :    _DeleteCallbackList
19785                :};
19786                :
19787                :static Bool
19788                :CreateCallbackList(CallbackListPtr *pcbl, CallbackFuncsPtr cbfuncs)
19789                :{
19790                :    CallbackListPtr  cbl;
19791                :    int i;
19792                :
19793                :    if (!pcbl) return FALSE;
19794                :    cbl = (CallbackListPtr) xalloc(sizeof(CallbackListRec));
19795                :    if (!cbl) return FALSE;
19796                :    cbl->funcs = cbfuncs ? *cbfuncs : default_cbfuncs;
19797                :    cbl->inCallback = 0;
19798                :    cbl->deleted = FALSE;
19799                :    cbl->numDeleted = 0;
19800                :    cbl->list = NULL;
19801                :    *pcbl = cbl;
19802                :
19803                :    for (i = 0; i < numCallbackListsToCleanup; i++)
19804                :    {
19805                :        if (!listsToCleanup[i])
19806                :        {
19807                :            listsToCleanup[i] = pcbl;
19808                :            return TRUE;
19809                :        }    
19810                :    }
19811                :
19812                :    listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup,
19813                :                sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1));
19814                :    listsToCleanup[numCallbackListsToCleanup] = pcbl;
19815                :    numCallbackListsToCleanup++;
19816                :    return TRUE;
19817                :}
19818                :
19819                :/* ===== Public Procedures ===== */
19820                :
19821                :_X_EXPORT Bool 
19822                :AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
19823                :{
19824                :    if (!pcbl) return FALSE;
19825                :    if (!*pcbl)
19826                :    {   /* list hasn't been created yet; go create it */
19827                :        if (!CreateCallbackList(pcbl, (CallbackFuncsPtr)NULL))
19828                :            return FALSE;
19829                :    }
19830                :    return ((*(*pcbl)->funcs.AddCallback) (pcbl, callback, data));
19831                :}
19832                :
19833                :_X_EXPORT Bool 
19834                :DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
19835                :{
19836                :    if (!pcbl || !*pcbl) return FALSE;
19837                :    return ((*(*pcbl)->funcs.DeleteCallback) (pcbl, callback, data));
19838                :}
19839                :
19840                :void 
19841                :CallCallbacks(CallbackListPtr *pcbl, pointer call_data)
19842      6  0.0065 :{ /* CallCallbacks total:     27  0.0294 */
19843     10  0.0109 :    if (!pcbl || !*pcbl) return;
19844      5  0.0054 :    (*(*pcbl)->funcs.CallCallbacks) (pcbl, call_data);
19845      6  0.0065 :}
19846                :
19847                :void
19848                :DeleteCallbackList(CallbackListPtr *pcbl)
19849                :{
19850                :    if (!pcbl || !*pcbl) return;
19851                :    (*(*pcbl)->funcs.DeleteCallbackList) (pcbl);
19852                :}
19853                :
19854                :void 
19855                :InitCallbackManager(void)
19856                :{
19857                :    int i;
19858                :
19859                :    for (i = 0; i < numCallbackListsToCleanup; i++)
19860                :    {
19861                :        DeleteCallbackList(listsToCleanup[i]);
19862                :    }
19863                :    if (listsToCleanup) xfree(listsToCleanup);
19864                :
19865                :    numCallbackListsToCleanup = 0;
19866                :    listsToCleanup = NULL;
19867                :}
19868 /* 
19869  * Total samples for file : "/home/cworth/src/xorg/xserver/render/render.c"
19870  * 
19871  *     81  0.0882
19872  */
19873
19874
19875                :/*
19876                : *
19877                : * Copyright Â© 2000 SuSE, Inc.
19878                : *
19879                : * Permission to use, copy, modify, distribute, and sell this software and its
19880                : * documentation for any purpose is hereby granted without fee, provided that
19881                : * the above copyright notice appear in all copies and that both that
19882                : * copyright notice and this permission notice appear in supporting
19883                : * documentation, and that the name of SuSE not be used in advertising or
19884                : * publicity pertaining to distribution of the software without specific,
19885                : * written prior permission.  SuSE makes no representations about the
19886                : * suitability of this software for any purpose.  It is provided "as is"
19887                : * without express or implied warranty.
19888                : *
19889                : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
19890                : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
19891                : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19892                : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19893                : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
19894                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19895                : *
19896                : * Author:  Keith Packard, SuSE, Inc.
19897                : */
19898                :
19899                :#define NEED_REPLIES
19900                :#define NEED_EVENTS
19901                :#ifdef HAVE_DIX_CONFIG_H
19902                :#include <dix-config.h>
19903                :#endif
19904                :
19905                :#include <X11/X.h>
19906                :#include <X11/Xproto.h>
19907                :#include "misc.h"
19908                :#include "os.h"
19909                :#include "dixstruct.h"
19910                :#include "resource.h"
19911                :#include "scrnintstr.h"
19912                :#include "windowstr.h"
19913                :#include "pixmapstr.h"
19914                :#include "colormapst.h"
19915                :#include "extnsionst.h"
19916                :#include "servermd.h"
19917                :#include <X11/extensions/render.h>
19918                :#include <X11/extensions/renderproto.h>
19919                :#include "picturestr.h"
19920                :#include "glyphstr.h"
19921                :#include <X11/Xfuncproto.h>
19922                :#include "cursorstr.h"
19923                :
19924                :#if HAVE_STDINT_H
19925                :#include <stdint.h>
19926                :#elif !defined(UINT32_MAX)
19927                :#define UINT32_MAX 0xffffffffU
19928                :#endif
19929                :
19930                :static int ProcRenderQueryVersion (ClientPtr pClient);
19931                :static int ProcRenderQueryPictFormats (ClientPtr pClient);
19932                :static int ProcRenderQueryPictIndexValues (ClientPtr pClient);
19933                :static int ProcRenderQueryDithers (ClientPtr pClient);
19934                :static int ProcRenderCreatePicture (ClientPtr pClient);
19935                :static int ProcRenderChangePicture (ClientPtr pClient);
19936                :static int ProcRenderSetPictureClipRectangles (ClientPtr pClient);
19937                :static int ProcRenderFreePicture (ClientPtr pClient);
19938                :static int ProcRenderComposite (ClientPtr pClient);
19939                :static int ProcRenderScale (ClientPtr pClient);
19940                :static int ProcRenderTrapezoids (ClientPtr pClient);
19941                :static int ProcRenderTriangles (ClientPtr pClient);
19942                :static int ProcRenderTriStrip (ClientPtr pClient);
19943                :static int ProcRenderTriFan (ClientPtr pClient);
19944                :static int ProcRenderColorTrapezoids (ClientPtr pClient);
19945                :static int ProcRenderColorTriangles (ClientPtr pClient);
19946                :static int ProcRenderTransform (ClientPtr pClient);
19947                :static int ProcRenderCreateGlyphSet (ClientPtr pClient);
19948                :static int ProcRenderReferenceGlyphSet (ClientPtr pClient);
19949                :static int ProcRenderFreeGlyphSet (ClientPtr pClient);
19950                :static int ProcRenderAddGlyphs (ClientPtr pClient);
19951                :static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient);
19952                :static int ProcRenderFreeGlyphs (ClientPtr pClient);
19953                :static int ProcRenderCompositeGlyphs (ClientPtr pClient);
19954                :static int ProcRenderFillRectangles (ClientPtr pClient);
19955                :static int ProcRenderCreateCursor (ClientPtr pClient);
19956                :static int ProcRenderSetPictureTransform (ClientPtr pClient);
19957                :static int ProcRenderQueryFilters (ClientPtr pClient);
19958                :static int ProcRenderSetPictureFilter (ClientPtr pClient);
19959                :static int ProcRenderCreateAnimCursor (ClientPtr pClient);
19960                :static int ProcRenderAddTraps (ClientPtr pClient);
19961                :static int ProcRenderCreateSolidFill (ClientPtr pClient);
19962                :static int ProcRenderCreateLinearGradient (ClientPtr pClient);
19963                :static int ProcRenderCreateRadialGradient (ClientPtr pClient);
19964                :static int ProcRenderCreateConicalGradient (ClientPtr pClient);
19965                :
19966                :static int ProcRenderDispatch (ClientPtr pClient);
19967                :
19968                :static int SProcRenderQueryVersion (ClientPtr pClient);
19969                :static int SProcRenderQueryPictFormats (ClientPtr pClient);
19970                :static int SProcRenderQueryPictIndexValues (ClientPtr pClient);
19971                :static int SProcRenderQueryDithers (ClientPtr pClient);
19972                :static int SProcRenderCreatePicture (ClientPtr pClient);
19973                :static int SProcRenderChangePicture (ClientPtr pClient);
19974                :static int SProcRenderSetPictureClipRectangles (ClientPtr pClient);
19975                :static int SProcRenderFreePicture (ClientPtr pClient);
19976                :static int SProcRenderComposite (ClientPtr pClient);
19977                :static int SProcRenderScale (ClientPtr pClient);
19978                :static int SProcRenderTrapezoids (ClientPtr pClient);
19979                :static int SProcRenderTriangles (ClientPtr pClient);
19980                :static int SProcRenderTriStrip (ClientPtr pClient);
19981                :static int SProcRenderTriFan (ClientPtr pClient);
19982                :static int SProcRenderColorTrapezoids (ClientPtr pClient);
19983                :static int SProcRenderColorTriangles (ClientPtr pClient);
19984                :static int SProcRenderTransform (ClientPtr pClient);
19985                :static int SProcRenderCreateGlyphSet (ClientPtr pClient);
19986                :static int SProcRenderReferenceGlyphSet (ClientPtr pClient);
19987                :static int SProcRenderFreeGlyphSet (ClientPtr pClient);
19988                :static int SProcRenderAddGlyphs (ClientPtr pClient);
19989                :static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient);
19990                :static int SProcRenderFreeGlyphs (ClientPtr pClient);
19991                :static int SProcRenderCompositeGlyphs (ClientPtr pClient);
19992                :static int SProcRenderFillRectangles (ClientPtr pClient);
19993                :static int SProcRenderCreateCursor (ClientPtr pClient);
19994                :static int SProcRenderSetPictureTransform (ClientPtr pClient);
19995                :static int SProcRenderQueryFilters (ClientPtr pClient);
19996                :static int SProcRenderSetPictureFilter (ClientPtr pClient);
19997                :static int SProcRenderCreateAnimCursor (ClientPtr pClient);
19998                :static int SProcRenderAddTraps (ClientPtr pClient);
19999                :static int SProcRenderCreateSolidFill (ClientPtr pClient);
20000                :static int SProcRenderCreateLinearGradient (ClientPtr pClient);
20001                :static int SProcRenderCreateRadialGradient (ClientPtr pClient);
20002                :static int SProcRenderCreateConicalGradient (ClientPtr pClient);
20003                :
20004                :static int SProcRenderDispatch (ClientPtr pClient);
20005                :
20006                :int     (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = {
20007                :    ProcRenderQueryVersion,
20008                :    ProcRenderQueryPictFormats,
20009                :    ProcRenderQueryPictIndexValues,
20010                :    ProcRenderQueryDithers,
20011                :    ProcRenderCreatePicture,
20012                :    ProcRenderChangePicture,
20013                :    ProcRenderSetPictureClipRectangles,
20014                :    ProcRenderFreePicture,
20015                :    ProcRenderComposite,
20016                :    ProcRenderScale,
20017                :    ProcRenderTrapezoids,
20018                :    ProcRenderTriangles,
20019                :    ProcRenderTriStrip,
20020                :    ProcRenderTriFan,
20021                :    ProcRenderColorTrapezoids,
20022                :    ProcRenderColorTriangles,
20023                :    ProcRenderTransform,
20024                :    ProcRenderCreateGlyphSet,
20025                :    ProcRenderReferenceGlyphSet,
20026                :    ProcRenderFreeGlyphSet,
20027                :    ProcRenderAddGlyphs,
20028                :    ProcRenderAddGlyphsFromPicture,
20029                :    ProcRenderFreeGlyphs,
20030                :    ProcRenderCompositeGlyphs,
20031                :    ProcRenderCompositeGlyphs,
20032                :    ProcRenderCompositeGlyphs,
20033                :    ProcRenderFillRectangles,
20034                :    ProcRenderCreateCursor,
20035                :    ProcRenderSetPictureTransform,
20036                :    ProcRenderQueryFilters,
20037                :    ProcRenderSetPictureFilter,
20038                :    ProcRenderCreateAnimCursor,
20039                :    ProcRenderAddTraps,
20040                :    ProcRenderCreateSolidFill,
20041                :    ProcRenderCreateLinearGradient,
20042                :    ProcRenderCreateRadialGradient,
20043                :    ProcRenderCreateConicalGradient
20044                :};
20045                :
20046                :int     (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = {
20047                :    SProcRenderQueryVersion,
20048                :    SProcRenderQueryPictFormats,
20049                :    SProcRenderQueryPictIndexValues,
20050                :    SProcRenderQueryDithers,
20051                :    SProcRenderCreatePicture,
20052                :    SProcRenderChangePicture,
20053                :    SProcRenderSetPictureClipRectangles,
20054                :    SProcRenderFreePicture,
20055                :    SProcRenderComposite,
20056                :    SProcRenderScale,
20057                :    SProcRenderTrapezoids,
20058                :    SProcRenderTriangles,
20059                :    SProcRenderTriStrip,
20060                :    SProcRenderTriFan,
20061                :    SProcRenderColorTrapezoids,
20062                :    SProcRenderColorTriangles,
20063                :    SProcRenderTransform,
20064                :    SProcRenderCreateGlyphSet,
20065                :    SProcRenderReferenceGlyphSet,
20066                :    SProcRenderFreeGlyphSet,
20067                :    SProcRenderAddGlyphs,
20068                :    SProcRenderAddGlyphsFromPicture,
20069                :    SProcRenderFreeGlyphs,
20070                :    SProcRenderCompositeGlyphs,
20071                :    SProcRenderCompositeGlyphs,
20072                :    SProcRenderCompositeGlyphs,
20073                :    SProcRenderFillRectangles,
20074                :    SProcRenderCreateCursor,
20075                :    SProcRenderSetPictureTransform,
20076                :    SProcRenderQueryFilters,
20077                :    SProcRenderSetPictureFilter,
20078                :    SProcRenderCreateAnimCursor,
20079                :    SProcRenderAddTraps,
20080                :    SProcRenderCreateSolidFill,
20081                :    SProcRenderCreateLinearGradient,
20082                :    SProcRenderCreateRadialGradient,
20083                :    SProcRenderCreateConicalGradient
20084                :};
20085                :
20086                :static void
20087                :RenderResetProc (ExtensionEntry *extEntry);
20088                :    
20089                :#if 0
20090                :static CARD8    RenderReqCode;
20091                :#endif
20092                :int     RenderErrBase;
20093                :int     RenderClientPrivateIndex;
20094                :
20095                :typedef struct _RenderClient {
20096                :    int     major_version;
20097                :    int     minor_version;
20098                :} RenderClientRec, *RenderClientPtr;
20099                :
20100                :#define GetRenderClient(pClient)    ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr)
20101                :
20102                :static void
20103                :RenderClientCallback (CallbackListPtr   *list,
20104                :                      pointer           closure,
20105                :                      pointer           data)
20106                :{
20107                :    NewClientInfoRec    *clientinfo = (NewClientInfoRec *) data;
20108                :    ClientPtr           pClient = clientinfo->client;
20109                :    RenderClientPtr     pRenderClient = GetRenderClient (pClient);
20110                :
20111                :    pRenderClient->major_version = 0;
20112                :    pRenderClient->minor_version = 0;
20113                :}
20114                :
20115                :void
20116                :RenderExtensionInit (void)
20117                :{
20118                :    ExtensionEntry *extEntry;
20119                :
20120                :    if (!PictureType)
20121                :        return;
20122                :    if (!PictureFinishInit ())
20123                :        return;
20124                :    RenderClientPrivateIndex = AllocateClientPrivateIndex ();
20125                :    if (!AllocateClientPrivate (RenderClientPrivateIndex, 
20126                :                                sizeof (RenderClientRec)))
20127                :        return;
20128                :    if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0))
20129                :        return;
20130                :
20131                :    extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors,
20132                :                             ProcRenderDispatch, SProcRenderDispatch,
20133                :                             RenderResetProc, StandardMinorOpcode);
20134                :    if (!extEntry)
20135                :        return;
20136                :#if 0
20137                :    RenderReqCode = (CARD8) extEntry->base;
20138                :#endif
20139                :    RenderErrBase = extEntry->errorBase;
20140                :}
20141                :
20142                :static void
20143                :RenderResetProc (ExtensionEntry *extEntry)
20144                :{
20145                :    ResetPicturePrivateIndex();
20146                :    ResetGlyphSetPrivateIndex();
20147                :}
20148                :
20149                :static int
20150                :ProcRenderQueryVersion (ClientPtr client)
20151                :{
20152                :    RenderClientPtr pRenderClient = GetRenderClient (client);
20153                :    xRenderQueryVersionReply rep;
20154                :    register int n;
20155                :    REQUEST(xRenderQueryVersionReq);
20156                :
20157                :    pRenderClient->major_version = stuff->majorVersion;
20158                :    pRenderClient->minor_version = stuff->minorVersion;
20159                :
20160                :    REQUEST_SIZE_MATCH(xRenderQueryVersionReq);
20161                :    rep.type = X_Reply;
20162                :    rep.length = 0;
20163                :    rep.sequenceNumber = client->sequence;
20164                :    rep.majorVersion = RENDER_MAJOR;
20165                :    rep.minorVersion = RENDER_MINOR;
20166                :    if (client->swapped) {
20167                :        swaps(&rep.sequenceNumber, n);
20168                :        swapl(&rep.length, n);
20169                :        swapl(&rep.majorVersion, n);
20170                :        swapl(&rep.minorVersion, n);
20171                :    }
20172                :    WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep);
20173                :    return (client->noClientException);
20174                :}
20175                :
20176                :#if 0
20177                :static int
20178                :VisualDepth (ScreenPtr pScreen, VisualPtr pVisual)
20179                :{
20180                :    DepthPtr    pDepth;
20181                :    int         d, v;
20182                :
20183                :    for (d = 0; d < pScreen->numDepths; d++)
20184                :    {
20185                :        pDepth = pScreen->allowedDepths + d;
20186                :        for (v = 0; v < pDepth->numVids; v++)
20187                :        {
20188                :            if (pDepth->vids[v] == pVisual->vid)
20189                :                return pDepth->depth;
20190                :        }
20191                :    }
20192                :    return 0;
20193                :}
20194                :#endif
20195                :
20196                :static VisualPtr
20197                :findVisual (ScreenPtr pScreen, VisualID vid)
20198                :{
20199                :    VisualPtr   pVisual;
20200                :    int         v;
20201                :
20202                :    for (v = 0; v < pScreen->numVisuals; v++)
20203                :    {
20204                :        pVisual = pScreen->visuals + v;
20205                :        if (pVisual->vid == vid)
20206                :            return pVisual;
20207                :    }
20208                :    return 0;
20209                :}
20210                :
20211                :extern char *ConnectionInfo;
20212                :
20213                :static int
20214                :ProcRenderQueryPictFormats (ClientPtr client)
20215                :{
20216                :    RenderClientPtr                 pRenderClient = GetRenderClient (client);
20217                :    xRenderQueryPictFormatsReply    *reply;
20218                :    xPictScreen                     *pictScreen;
20219                :    xPictDepth                      *pictDepth;
20220                :    xPictVisual                     *pictVisual;
20221                :    xPictFormInfo                   *pictForm;
20222                :    CARD32                          *pictSubpixel;
20223                :    ScreenPtr                       pScreen;
20224                :    VisualPtr                       pVisual;
20225                :    DepthPtr                        pDepth;
20226                :    int                             v, d;
20227                :    PictureScreenPtr                ps;
20228                :    PictFormatPtr                   pFormat;
20229                :    int                             nformat;
20230                :    int                             ndepth;
20231                :    int                             nvisual;
20232                :    int                             rlength;
20233                :    int                             s;
20234                :    int                             n;
20235                :    int                             numScreens;
20236                :    int                             numSubpixel;
20237                :/*    REQUEST(xRenderQueryPictFormatsReq); */
20238                :
20239                :    REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq);
20240                :
20241                :#ifdef PANORAMIX
20242                :    if (noPanoramiXExtension)
20243                :        numScreens = screenInfo.numScreens;
20244                :    else 
20245                :        numScreens = ((xConnSetup *)ConnectionInfo)->numRoots;
20246                :#else
20247                :    numScreens = screenInfo.numScreens;
20248                :#endif
20249                :    ndepth = nformat = nvisual = 0;
20250                :    for (s = 0; s < numScreens; s++)
20251                :    {
20252                :        pScreen = screenInfo.screens[s];
20253                :        for (d = 0; d < pScreen->numDepths; d++)
20254                :        {
20255                :            pDepth = pScreen->allowedDepths + d;
20256                :            ++ndepth;
20257                :
20258                :            for (v = 0; v < pDepth->numVids; v++)
20259                :            {
20260                :                pVisual = findVisual (pScreen, pDepth->vids[v]);
20261                :                if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual))
20262                :                    ++nvisual;
20263                :            }
20264                :        }
20265                :        ps = GetPictureScreenIfSet(pScreen);
20266                :        if (ps)
20267                :            nformat += ps->nformats;
20268                :    }
20269                :    if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6)
20270                :        numSubpixel = 0;
20271                :    else
20272                :        numSubpixel = numScreens;
20273                :    
20274                :    rlength = (sizeof (xRenderQueryPictFormatsReply) +
20275                :               nformat * sizeof (xPictFormInfo) +
20276                :               numScreens * sizeof (xPictScreen) +
20277                :               ndepth * sizeof (xPictDepth) +
20278                :               nvisual * sizeof (xPictVisual) +
20279                :               numSubpixel * sizeof (CARD32));
20280                :    reply = (xRenderQueryPictFormatsReply *) xalloc (rlength);
20281                :    if (!reply)
20282                :        return BadAlloc;
20283                :    reply->type = X_Reply;
20284                :    reply->sequenceNumber = client->sequence;
20285                :    reply->length = (rlength - sizeof(xGenericReply)) >> 2;
20286                :    reply->numFormats = nformat;
20287                :    reply->numScreens = numScreens;
20288                :    reply->numDepths = ndepth;
20289                :    reply->numVisuals = nvisual;
20290                :    reply->numSubpixel = numSubpixel;
20291                :    
20292                :    pictForm = (xPictFormInfo *) (reply + 1);
20293                :    
20294                :    for (s = 0; s < numScreens; s++)
20295                :    {
20296                :        pScreen = screenInfo.screens[s];
20297                :        ps = GetPictureScreenIfSet(pScreen);
20298                :        if (ps)
20299                :        {
20300                :            for (nformat = 0, pFormat = ps->formats; 
20301                :                 nformat < ps->nformats;
20302                :                 nformat++, pFormat++)
20303                :            {
20304                :                pictForm->id = pFormat->id;
20305                :                pictForm->type = pFormat->type;
20306                :                pictForm->depth = pFormat->depth;
20307                :                pictForm->direct.red = pFormat->direct.red;
20308                :                pictForm->direct.redMask = pFormat->direct.redMask;
20309                :                pictForm->direct.green = pFormat->direct.green;
20310                :                pictForm->direct.greenMask = pFormat->direct.greenMask;
20311                :                pictForm->direct.blue = pFormat->direct.blue;
20312                :                pictForm->direct.blueMask = pFormat->direct.blueMask;
20313                :                pictForm->direct.alpha = pFormat->direct.alpha;
20314                :                pictForm->direct.alphaMask = pFormat->direct.alphaMask;
20315                :                if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap)
20316                :                    pictForm->colormap = pFormat->index.pColormap->mid;
20317                :                else
20318                :                    pictForm->colormap = None;
20319                :                if (client->swapped)
20320                :                {
20321                :                    swapl (&pictForm->id, n);
20322                :                    swaps (&pictForm->direct.red, n);
20323                :                    swaps (&pictForm->direct.redMask, n);
20324                :                    swaps (&pictForm->direct.green, n);
20325                :                    swaps (&pictForm->direct.greenMask, n);
20326                :                    swaps (&pictForm->direct.blue, n);
20327                :                    swaps (&pictForm->direct.blueMask, n);
20328                :                    swaps (&pictForm->direct.alpha, n);
20329                :                    swaps (&pictForm->direct.alphaMask, n);
20330                :                    swapl (&pictForm->colormap, n);
20331                :                }
20332                :                pictForm++;
20333                :            }
20334                :        }
20335                :    }
20336                :    
20337                :    pictScreen = (xPictScreen *) pictForm;
20338                :    for (s = 0; s < numScreens; s++)
20339                :    {
20340                :        pScreen = screenInfo.screens[s];
20341                :        pictDepth = (xPictDepth *) (pictScreen + 1);
20342                :        ndepth = 0;
20343                :        for (d = 0; d < pScreen->numDepths; d++)
20344                :        {
20345                :            pictVisual = (xPictVisual *) (pictDepth + 1);
20346                :            pDepth = pScreen->allowedDepths + d;
20347                :
20348                :            nvisual = 0;
20349                :            for (v = 0; v < pDepth->numVids; v++)
20350                :            {
20351                :                pVisual = findVisual (pScreen, pDepth->vids[v]);
20352                :                if (pVisual && (pFormat = PictureMatchVisual (pScreen, 
20353                :                                                              pDepth->depth, 
20354                :                                                              pVisual)))
20355                :                {
20356                :                    pictVisual->visual = pVisual->vid;
20357                :                    pictVisual->format = pFormat->id;
20358                :                    if (client->swapped)
20359                :                    {
20360                :                        swapl (&pictVisual->visual, n);
20361                :                        swapl (&pictVisual->format, n);
20362                :                    }
20363                :                    pictVisual++;
20364                :                    nvisual++;
20365                :                }
20366                :            }
20367                :            pictDepth->depth = pDepth->depth;
20368                :            pictDepth->nPictVisuals = nvisual;
20369                :            if (client->swapped)
20370                :            {
20371                :                swaps (&pictDepth->nPictVisuals, n);
20372                :            }
20373                :            ndepth++;
20374                :            pictDepth = (xPictDepth *) pictVisual;
20375                :        }
20376                :        pictScreen->nDepth = ndepth;
20377                :        ps = GetPictureScreenIfSet(pScreen);
20378                :        if (ps)
20379                :            pictScreen->fallback = ps->fallback->id;
20380                :        else
20381                :            pictScreen->fallback = 0;
20382                :        if (client->swapped)
20383                :        {
20384                :            swapl (&pictScreen->nDepth, n);
20385                :            swapl (&pictScreen->fallback, n);
20386                :        }
20387                :        pictScreen = (xPictScreen *) pictDepth;
20388                :    }
20389                :    pictSubpixel = (CARD32 *) pictScreen;
20390                :    
20391                :    for (s = 0; s < numSubpixel; s++)
20392                :    {
20393                :        pScreen = screenInfo.screens[s];
20394                :        ps = GetPictureScreenIfSet(pScreen);
20395                :        if (ps)
20396                :            *pictSubpixel = ps->subpixel;
20397                :        else
20398                :            *pictSubpixel = SubPixelUnknown;
20399                :        if (client->swapped)
20400                :        {
20401                :            swapl (pictSubpixel, n);
20402                :        }
20403                :        ++pictSubpixel;
20404                :    }
20405                :    
20406                :    if (client->swapped)
20407                :    {
20408                :        swaps (&reply->sequenceNumber, n);
20409                :        swapl (&reply->length, n);
20410                :        swapl (&reply->numFormats, n);
20411                :        swapl (&reply->numScreens, n);
20412                :        swapl (&reply->numDepths, n);
20413                :        swapl (&reply->numVisuals, n);
20414                :        swapl (&reply->numSubpixel, n);
20415                :    }
20416                :    WriteToClient(client, rlength, (char *) reply);
20417                :    xfree (reply);
20418                :    return client->noClientException;
20419                :}
20420                :
20421                :static int
20422                :ProcRenderQueryPictIndexValues (ClientPtr client)
20423                :{
20424                :    PictFormatPtr   pFormat;
20425                :    int             num;
20426                :    int             rlength;
20427                :    int             i, n;
20428                :    REQUEST(xRenderQueryPictIndexValuesReq);
20429                :    xRenderQueryPictIndexValuesReply *reply;
20430                :    xIndexValue     *values;
20431                :
20432                :    REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq);
20433                :
20434                :    pFormat = (PictFormatPtr) SecurityLookupIDByType (client, 
20435                :                                                      stuff->format,
20436                :                                                      PictFormatType,
20437                :                                                      DixReadAccess);
20438                :
20439                :    if (!pFormat)
20440                :    {
20441                :        client->errorValue = stuff->format;
20442                :        return RenderErrBase + BadPictFormat;
20443                :    }
20444                :    if (pFormat->type != PictTypeIndexed)
20445                :    {
20446                :        client->errorValue = stuff->format;
20447                :        return BadMatch;
20448                :    }
20449                :    num = pFormat->index.nvalues;
20450                :    rlength = (sizeof (xRenderQueryPictIndexValuesReply) + 
20451                :               num * sizeof(xIndexValue));
20452                :    reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength);
20453                :    if (!reply)
20454                :        return BadAlloc;
20455                :
20456                :    reply->type = X_Reply;
20457                :    reply->sequenceNumber = client->sequence;
20458                :    reply->length = (rlength - sizeof(xGenericReply)) >> 2;
20459                :    reply->numIndexValues = num;
20460                :
20461                :    values = (xIndexValue *) (reply + 1);
20462                :    
20463                :    memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue));
20464                :    
20465                :    if (client->swapped)
20466                :    {
20467                :        for (i = 0; i < num; i++)
20468                :        {
20469                :            swapl (&values[i].pixel, n);
20470                :            swaps (&values[i].red, n);
20471                :            swaps (&values[i].green, n);
20472                :            swaps (&values[i].blue, n);
20473                :            swaps (&values[i].alpha, n);
20474                :        }
20475                :        swaps (&reply->sequenceNumber, n);
20476                :        swapl (&reply->length, n);
20477                :        swapl (&reply->numIndexValues, n);
20478                :    }
20479                :
20480                :    WriteToClient(client, rlength, (char *) reply);
20481                :    xfree(reply);
20482                :    return (client->noClientException);
20483                :}
20484                :
20485                :static int
20486                :ProcRenderQueryDithers (ClientPtr client)
20487                :{
20488                :    return BadImplementation;
20489                :}
20490                :
20491                :static int
20492                :ProcRenderCreatePicture (ClientPtr client)
20493      6  0.0065 :{ /* ProcRenderCreatePicture total:     14  0.0153 */
20494                :    PicturePtr      pPicture;
20495                :    DrawablePtr     pDrawable;
20496                :    PictFormatPtr   pFormat;
20497                :    int             len, error, rc;
20498                :    REQUEST(xRenderCreatePictureReq);
20499                :
20500                :    REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
20501                :
20502      1  0.0011 :    LEGAL_NEW_RESOURCE(stuff->pid, client);
20503      2  0.0022 :    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
20504                :                           DixWriteAccess);
20505                :    if (rc != Success)
20506                :        return rc;
20507                :
20508      1  0.0011 :    pFormat = (PictFormatPtr) SecurityLookupIDByType (client, 
20509                :                                                      stuff->format,
20510                :                                                      PictFormatType,
20511                :                                                      DixReadAccess);
20512                :    if (!pFormat)
20513                :    {
20514                :        client->errorValue = stuff->format;
20515                :        return RenderErrBase + BadPictFormat;
20516                :    }
20517                :    if (pFormat->depth != pDrawable->depth)
20518                :        return BadMatch;
20519                :    len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2);
20520                :    if (Ones(stuff->mask) != len)
20521                :        return BadLength;
20522                :    
20523                :    pPicture = CreatePicture (stuff->pid,
20524                :                              pDrawable,
20525                :                              pFormat,
20526                :                              stuff->mask,
20527                :                              (XID *) (stuff + 1),
20528                :                              client,
20529                :                              &error);
20530                :    if (!pPicture)
20531                :        return error;
20532      4  0.0044 :    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
20533                :        return BadAlloc;
20534                :    return Success;
20535                :}
20536                :
20537                :static int
20538                :ProcRenderChangePicture (ClientPtr client)
20539      6  0.0065 :{ /* ProcRenderChangePicture total:      7  0.0076 */
20540                :    PicturePtr      pPicture;
20541                :    REQUEST(xRenderChangePictureReq);
20542                :    int len;
20543                :
20544                :    REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
20545      1  0.0011 :    VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
20546                :                    RenderErrBase + BadPicture);
20547                :
20548                :    len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2);
20549                :    if (Ones(stuff->mask) != len)
20550                :        return BadLength;
20551                :    
20552                :    return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1),
20553                :                          (DevUnion *) 0, client);
20554                :}
20555                :
20556                :static int
20557                :ProcRenderSetPictureClipRectangles (ClientPtr client)
20558      1  0.0011 :{ /* ProcRenderSetPictureClipRectangles total:      1  0.0011 */
20559                :    REQUEST(xRenderSetPictureClipRectanglesReq);
20560                :    PicturePtr      pPicture;
20561                :    int             nr;
20562                :    int             result;
20563                :
20564                :    REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
20565                :    VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
20566                :                    RenderErrBase + BadPicture);
20567                :    if (!pPicture->pDrawable)
20568                :        return BadDrawable;
20569                :
20570                :    nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq);
20571                :    if (nr & 4)
20572                :        return BadLength;
20573                :    nr >>= 3;
20574                :    result = SetPictureClipRects (pPicture, 
20575                :                                  stuff->xOrigin, stuff->yOrigin,
20576                :                                  nr, (xRectangle *) &stuff[1]);
20577                :    if (client->noClientException != Success)
20578                :        return(client->noClientException);
20579                :    else
20580                :        return(result);
20581                :}
20582                :
20583                :static int
20584                :ProcRenderFreePicture (ClientPtr client)
20585      1  0.0011 :{ /* ProcRenderFreePicture total:      2  0.0022 */
20586                :    PicturePtr  pPicture;
20587                :    REQUEST(xRenderFreePictureReq);
20588                :
20589      1  0.0011 :    REQUEST_SIZE_MATCH(xRenderFreePictureReq);
20590                :
20591                :    VERIFY_PICTURE (pPicture, stuff->picture, client, DixDestroyAccess,
20592                :                    RenderErrBase + BadPicture);
20593                :    FreeResource (stuff->picture, RT_NONE);
20594                :    return(client->noClientException);
20595                :}
20596                :
20597                :static Bool
20598                :PictOpValid (CARD8 op)
20599                :{
20600                :    if (/*PictOpMinimum <= op && */ op <= PictOpMaximum)
20601                :        return TRUE;
20602                :    if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum)
20603                :        return TRUE;
20604                :    if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum)
20605                :        return TRUE;
20606                :    return FALSE;
20607                :}
20608                :
20609                :static int
20610                :ProcRenderComposite (ClientPtr client)
20611      1  0.0011 :{ /* ProcRenderComposite total:      1  0.0011 */
20612                :    PicturePtr  pSrc, pMask, pDst;
20613                :    REQUEST(xRenderCompositeReq);
20614                :
20615                :    REQUEST_SIZE_MATCH(xRenderCompositeReq);
20616                :    if (!PictOpValid (stuff->op))
20617                :    {
20618                :        client->errorValue = stuff->op;
20619                :        return BadValue;
20620                :    }
20621                :    VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
20622                :                    RenderErrBase + BadPicture);
20623                :    if (!pDst->pDrawable)
20624                :        return BadDrawable;
20625                :    VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, 
20626                :                    RenderErrBase + BadPicture);
20627                :    VERIFY_ALPHA (pMask, stuff->mask, client, DixReadAccess, 
20628                :                  RenderErrBase + BadPicture);
20629                :    if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
20630                :        (pMask && pMask->pDrawable && pDst->pDrawable->pScreen != pMask->pDrawable->pScreen))
20631                :        return BadMatch;
20632                :    CompositePicture (stuff->op,
20633                :                      pSrc,
20634                :                      pMask,
20635                :                      pDst,
20636                :                      stuff->xSrc,
20637                :                      stuff->ySrc,
20638                :                      stuff->xMask,
20639                :                      stuff->yMask,
20640                :                      stuff->xDst,
20641                :                      stuff->yDst,
20642                :                      stuff->width,
20643                :                      stuff->height);
20644                :    return Success;
20645                :}
20646                :
20647                :static int
20648                :ProcRenderScale (ClientPtr client)
20649                :{
20650                :    return BadImplementation;
20651                :}
20652                :
20653                :static int
20654                :ProcRenderTrapezoids (ClientPtr client)
20655                :{
20656                :    int         ntraps;
20657                :    PicturePtr  pSrc, pDst;
20658                :    PictFormatPtr   pFormat;
20659                :    REQUEST(xRenderTrapezoidsReq);
20660                :
20661                :    REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
20662                :    if (!PictOpValid (stuff->op))
20663                :    {
20664                :        client->errorValue = stuff->op;
20665                :        return BadValue;
20666                :    }
20667                :    VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, 
20668                :                    RenderErrBase + BadPicture);
20669                :    VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, 
20670                :                    RenderErrBase + BadPicture);
20671                :    if (!pDst->pDrawable)
20672                :        return BadDrawable;
20673                :    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
20674                :        return BadMatch;
20675                :    if (stuff->maskFormat)
20676                :    {
20677                :        pFormat = (PictFormatPtr) SecurityLookupIDByType (client,
20678                :                                                          stuff->maskFormat,
20679                :                                                          PictFormatType,
20680                :                                                          DixReadAccess);
20681                :        if (!pFormat)
20682                :        {
20683                :            client->errorValue = stuff->maskFormat;
20684                :            return RenderErrBase + BadPictFormat;
20685                :        }
20686                :    }
20687                :    else
20688                :        pFormat = 0;
20689                :    ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq);
20690                :    if (ntraps % sizeof (xTrapezoid))
20691                :        return BadLength;
20692                :    ntraps /= sizeof (xTrapezoid);
20693                :    if (ntraps)
20694                :        CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat,
20695                :                             stuff->xSrc, stuff->ySrc,
20696                :                             ntraps, (xTrapezoid *) &stuff[1]);
20697                :    return client->noClientException;
20698                :}
20699                :
20700                :static int
20701                :ProcRenderTriangles (ClientPtr client)
20702                :{
20703                :    int         ntris;
20704                :    PicturePtr  pSrc, pDst;
20705                :    PictFormatPtr   pFormat;
20706                :    REQUEST(xRenderTrianglesReq);
20707                :
20708                :    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
20709                :    if (!PictOpValid (stuff->op))
20710                :    {
20711                :        client->errorValue = stuff->op;
20712                :        return BadValue;
20713                :    }
20714                :    VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, 
20715                :                    RenderErrBase + BadPicture);
20716                :    VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, 
20717                :                    RenderErrBase + BadPicture);
20718                :    if (!pDst->pDrawable)
20719                :        return BadDrawable;
20720                :    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
20721                :        return BadMatch;
20722                :    if (stuff->maskFormat)
20723                :    {
20724                :        pFormat = (PictFormatPtr) SecurityLookupIDByType (client,
20725                :                                                          stuff->maskFormat,
20726                :                                                          PictFormatType,
20727                :                                                          DixReadAccess);
20728                :        if (!pFormat)
20729                :        {
20730                :            client->errorValue = stuff->maskFormat;
20731                :            return RenderErrBase + BadPictFormat;
20732                :        }
20733                :    }
20734                :    else
20735                :        pFormat = 0;
20736                :    ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq);
20737                :    if (ntris % sizeof (xTriangle))
20738                :        return BadLength;
20739                :    ntris /= sizeof (xTriangle);
20740                :    if (ntris)
20741                :        CompositeTriangles (stuff->op, pSrc, pDst, pFormat,
20742                :                            stuff->xSrc, stuff->ySrc,
20743                :                            ntris, (xTriangle *) &stuff[1]);
20744                :    return client->noClientException;
20745                :}
20746                :
20747                :static int
20748                :ProcRenderTriStrip (ClientPtr client)
20749                :{
20750                :    int         npoints;
20751                :    PicturePtr  pSrc, pDst;
20752                :    PictFormatPtr   pFormat;
20753                :    REQUEST(xRenderTrianglesReq);
20754                :
20755                :    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
20756                :    if (!PictOpValid (stuff->op))
20757                :    {
20758                :        client->errorValue = stuff->op;
20759                :        return BadValue;
20760                :    }
20761                :    VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, 
20762                :                    RenderErrBase + BadPicture);
20763                :    VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, 
20764                :                    RenderErrBase + BadPicture);
20765                :    if (!pDst->pDrawable)
20766                :        return BadDrawable;
20767                :    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
20768                :        return BadMatch;
20769                :    if (stuff->maskFormat)
20770                :    {
20771                :        pFormat = (PictFormatPtr) SecurityLookupIDByType (client,
20772                :                                                          stuff->maskFormat,
20773                :                                                          PictFormatType,
20774                :                                                          DixReadAccess);
20775                :        if (!pFormat)
20776                :        {
20777                :            client->errorValue = stuff->maskFormat;
20778                :            return RenderErrBase + BadPictFormat;
20779                :        }
20780                :    }
20781                :    else
20782                :        pFormat = 0;
20783                :    npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq));
20784                :    if (npoints & 4)
20785                :        return(BadLength);
20786                :    npoints >>= 3;
20787                :    if (npoints >= 3)
20788                :        CompositeTriStrip (stuff->op, pSrc, pDst, pFormat,
20789                :                           stuff->xSrc, stuff->ySrc,
20790                :                           npoints, (xPointFixed *) &stuff[1]);
20791                :    return client->noClientException;
20792                :}
20793                :
20794                :static int
20795                :ProcRenderTriFan (ClientPtr client)
20796                :{
20797                :    int         npoints;
20798                :    PicturePtr  pSrc, pDst;
20799                :    PictFormatPtr   pFormat;
20800                :    REQUEST(xRenderTrianglesReq);
20801                :
20802                :    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
20803                :    if (!PictOpValid (stuff->op))
20804                :    {
20805                :        client->errorValue = stuff->op;
20806                :        return BadValue;
20807                :    }
20808                :    VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, 
20809                :                    RenderErrBase + BadPicture);
20810                :    VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, 
20811                :                    RenderErrBase + BadPicture);
20812                :    if (!pDst->pDrawable)
20813                :        return BadDrawable;
20814                :    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
20815                :        return BadMatch;
20816                :    if (stuff->maskFormat)
20817                :    {
20818                :        pFormat = (PictFormatPtr) SecurityLookupIDByType (client,
20819                :                                                          stuff->maskFormat,
20820                :                                                          PictFormatType,
20821                :                                                          DixReadAccess);
20822                :        if (!pFormat)
20823                :        {
20824                :            client->errorValue = stuff->maskFormat;
20825                :            return RenderErrBase + BadPictFormat;
20826                :        }
20827                :    }
20828                :    else
20829                :        pFormat = 0;
20830                :    npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq));
20831                :    if (npoints & 4)
20832                :        return(BadLength);
20833                :    npoints >>= 3;
20834                :    if (npoints >= 3)
20835                :        CompositeTriFan (stuff->op, pSrc, pDst, pFormat,
20836                :                         stuff->xSrc, stuff->ySrc,
20837                :                         npoints, (xPointFixed *) &stuff[1]);
20838                :    return client->noClientException;
20839                :}
20840                :
20841                :static int
20842                :ProcRenderColorTrapezoids (ClientPtr client)
20843                :{
20844                :    return BadImplementation;
20845                :}
20846                :
20847                :static int
20848                :ProcRenderColorTriangles (ClientPtr client)
20849                :{
20850                :    return BadImplementation;
20851                :}
20852                :
20853                :static int
20854                :ProcRenderTransform (ClientPtr client)
20855                :{
20856                :    return BadImplementation;
20857                :}
20858                :
20859                :static int
20860                :ProcRenderCreateGlyphSet (ClientPtr client)
20861                :{
20862                :    GlyphSetPtr     glyphSet;
20863                :    PictFormatPtr   format;
20864                :    int             f;
20865                :    REQUEST(xRenderCreateGlyphSetReq);
20866                :
20867                :    REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq);
20868                :
20869                :    LEGAL_NEW_RESOURCE(stuff->gsid, client);
20870                :    format = (PictFormatPtr) SecurityLookupIDByType (client,
20871                :                                                     stuff->format,
20872                :                                                     PictFormatType,
20873                :                                                     DixReadAccess);
20874                :    if (!format)
20875                :    {
20876                :        client->errorValue = stuff->format;
20877                :        return RenderErrBase + BadPictFormat;
20878                :    }
20879                :    switch (format->depth) {
20880                :    case 1:
20881                :        f = GlyphFormat1;
20882                :        break;
20883                :    case 4:
20884                :        f = GlyphFormat4;
20885                :        break;
20886                :    case 8:
20887                :        f = GlyphFormat8;
20888                :        break;
20889                :    case 16:
20890                :        f = GlyphFormat16;
20891                :        break;
20892                :    case 32:
20893                :        f = GlyphFormat32;
20894                :        break;
20895                :    default:
20896                :        return BadMatch;
20897                :    }
20898                :    if (format->type != PictTypeDirect)
20899                :        return BadMatch;
20900                :    glyphSet = AllocateGlyphSet (f, format);
20901                :    if (!glyphSet)
20902                :        return BadAlloc;
20903                :    if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet))
20904                :        return BadAlloc;
20905                :    return Success;
20906                :}
20907                :
20908                :static int
20909                :ProcRenderReferenceGlyphSet (ClientPtr client)
20910                :{
20911                :    GlyphSetPtr     glyphSet;
20912                :    REQUEST(xRenderReferenceGlyphSetReq);
20913                :
20914                :    REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq);
20915                :
20916                :    LEGAL_NEW_RESOURCE(stuff->gsid, client);
20917                :
20918                :    glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
20919                :                                                     stuff->existing,
20920                :                                                     GlyphSetType,
20921                :                                                     DixWriteAccess);
20922                :    if (!glyphSet)
20923                :    {
20924                :        client->errorValue = stuff->existing;
20925                :        return RenderErrBase + BadGlyphSet;
20926                :    }
20927                :    glyphSet->refcnt++;
20928                :    if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet))
20929                :        return BadAlloc;
20930                :    return client->noClientException;
20931                :}
20932                :
20933                :#define NLOCALDELTA     64
20934                :#define NLOCALGLYPH     256
20935                :
20936                :static int
20937                :ProcRenderFreeGlyphSet (ClientPtr client)
20938                :{
20939                :    GlyphSetPtr     glyphSet;
20940                :    REQUEST(xRenderFreeGlyphSetReq);
20941                :
20942                :    REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
20943                :    glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
20944                :                                                     stuff->glyphset,
20945                :                                                     GlyphSetType,
20946                :                                                     DixDestroyAccess);
20947                :    if (!glyphSet)
20948                :    {
20949                :        client->errorValue = stuff->glyphset;
20950                :        return RenderErrBase + BadGlyphSet;
20951                :    }
20952                :    FreeResource (stuff->glyphset, RT_NONE);
20953                :    return client->noClientException;
20954                :}
20955                :
20956                :typedef struct _GlyphNew {
20957                :    Glyph       id;
20958                :    GlyphPtr    glyph;
20959                :} GlyphNewRec, *GlyphNewPtr;
20960                :
20961                :static int
20962                :ProcRenderAddGlyphs (ClientPtr client)
20963                :{
20964                :    GlyphSetPtr     glyphSet;
20965                :    REQUEST(xRenderAddGlyphsReq);
20966                :    GlyphNewRec     glyphsLocal[NLOCALGLYPH];
20967                :    GlyphNewPtr     glyphsBase, glyphs;
20968                :    GlyphPtr        glyph;
20969                :    int             remain, nglyphs;
20970                :    CARD32          *gids;
20971                :    xGlyphInfo      *gi;
20972                :    CARD8           *bits;
20973                :    int             size;
20974                :    int             err = BadAlloc;
20975                :
20976                :    REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
20977                :    glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
20978                :                                                     stuff->glyphset,
20979                :                                                     GlyphSetType,
20980                :                                                     DixWriteAccess);
20981                :    if (!glyphSet)
20982                :    {
20983                :        client->errorValue = stuff->glyphset;
20984                :        return RenderErrBase + BadGlyphSet;
20985                :    }
20986                :
20987                :    nglyphs = stuff->nglyphs;
20988                :    if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec))
20989                :            return BadAlloc;
20990                :
20991                :    if (nglyphs <= NLOCALGLYPH)
20992                :        glyphsBase = glyphsLocal;
20993                :    else
20994                :    {
20995                :        glyphsBase = (GlyphNewPtr) Xalloc (nglyphs * sizeof (GlyphNewRec));
20996                :        if (!glyphsBase)
20997                :            return BadAlloc;
20998                :    }
20999                :
21000                :    remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq);
21001                :
21002                :    glyphs = glyphsBase;
21003                :
21004                :    gids = (CARD32 *) (stuff + 1);
21005                :    gi = (xGlyphInfo *) (gids + nglyphs);
21006                :    bits = (CARD8 *) (gi + nglyphs);
21007                :    remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs;
21008                :    while (remain >= 0 && nglyphs)
21009                :    {
21010                :        glyph = AllocateGlyph (gi, glyphSet->fdepth);
21011                :        if (!glyph)
21012                :        {
21013                :            err = BadAlloc;
21014                :            goto bail;
21015                :        }
21016                :        
21017                :        glyphs->glyph = glyph;
21018                :        glyphs->id = *gids;     
21019                :        
21020                :        size = glyph->size - sizeof (xGlyphInfo);
21021                :        if (remain < size)
21022                :            break;
21023                :        memcpy ((CARD8 *) (glyph + 1), bits, size);
21024                :        
21025                :        if (size & 3)
21026                :            size += 4 - (size & 3);
21027                :        bits += size;
21028                :        remain -= size;
21029                :        gi++;
21030                :        gids++;
21031                :        glyphs++;
21032                :        nglyphs--;
21033                :    }
21034                :    if (nglyphs || remain)
21035                :    {
21036                :        err = BadLength;
21037                :        goto bail;
21038                :    }
21039                :    nglyphs = stuff->nglyphs;
21040                :    if (!ResizeGlyphSet (glyphSet, nglyphs))
21041                :    {
21042                :        err = BadAlloc;
21043                :        goto bail;
21044                :    }
21045                :    glyphs = glyphsBase;
21046                :    while (nglyphs--) {
21047                :        AddGlyph (glyphSet, glyphs->glyph, glyphs->id);
21048                :        glyphs++;
21049                :    }
21050                :
21051                :    if (glyphsBase != glyphsLocal)
21052                :        Xfree (glyphsBase);
21053                :    return client->noClientException;
21054                :bail:
21055                :    while (glyphs != glyphsBase)
21056                :    {
21057                :        --glyphs;
21058                :        xfree (glyphs->glyph);
21059                :    }
21060                :    if (glyphsBase != glyphsLocal)
21061                :        Xfree (glyphsBase);
21062                :    return err;
21063                :}
21064                :
21065                :static int
21066                :ProcRenderAddGlyphsFromPicture (ClientPtr client)
21067                :{
21068                :    return BadImplementation;
21069                :}
21070                :
21071                :static int
21072                :ProcRenderFreeGlyphs (ClientPtr client)
21073                :{
21074                :    REQUEST(xRenderFreeGlyphsReq);
21075                :    GlyphSetPtr     glyphSet;
21076                :    int             nglyph;
21077                :    CARD32          *gids;
21078                :    CARD32          glyph;
21079                :
21080                :    REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
21081                :    glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
21082                :                                                     stuff->glyphset,
21083                :                                                     GlyphSetType,
21084                :                                                     DixWriteAccess);
21085                :    if (!glyphSet)
21086                :    {
21087                :        client->errorValue = stuff->glyphset;
21088                :        return RenderErrBase + BadGlyphSet;
21089                :    }
21090                :    nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2;
21091                :    gids = (CARD32 *) (stuff + 1);
21092                :    while (nglyph-- > 0)
21093                :    {
21094                :        glyph = *gids++;
21095                :        if (!DeleteGlyph (glyphSet, glyph))
21096                :        {
21097                :            client->errorValue = glyph;
21098                :            return RenderErrBase + BadGlyph;
21099                :        }
21100                :    }
21101                :    return client->noClientException;
21102                :}
21103                :
21104                :static int
21105                :ProcRenderCompositeGlyphs (ClientPtr client)
21106      4  0.0044 :{ /* ProcRenderCompositeGlyphs total:     30  0.0327 */
21107                :    GlyphSetPtr     glyphSet;
21108                :    GlyphSet        gs;
21109                :    PicturePtr      pSrc, pDst;
21110                :    PictFormatPtr   pFormat;
21111                :    GlyphListRec    listsLocal[NLOCALDELTA];
21112                :    GlyphListPtr    lists, listsBase;
21113                :    GlyphPtr        glyphsLocal[NLOCALGLYPH];
21114                :    Glyph           glyph;
21115                :    GlyphPtr        *glyphs, *glyphsBase;
21116                :    xGlyphElt       *elt;
21117                :    CARD8           *buffer, *end;
21118                :    int             nglyph;
21119                :    int             nlist;
21120                :    int             space;
21121                :    int             size;
21122                :    int             n;
21123                :    
21124                :    REQUEST(xRenderCompositeGlyphsReq);
21125                :
21126                :    REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
21127                :
21128                :    switch (stuff->renderReqType) {
21129                :    default:                        size = 1; break;
21130                :    case X_RenderCompositeGlyphs16: size = 2; break;
21131                :    case X_RenderCompositeGlyphs32: size = 4; break;
21132                :    }
21133                :            
21134                :    if (!PictOpValid (stuff->op))
21135                :    {
21136                :        client->errorValue = stuff->op;
21137                :        return BadValue;
21138                :    }
21139                :    VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
21140                :                    RenderErrBase + BadPicture);
21141                :    VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
21142                :                    RenderErrBase + BadPicture);
21143                :    if (!pDst->pDrawable)
21144                :        return BadDrawable;
21145                :    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
21146                :        return BadMatch;
21147                :    if (stuff->maskFormat)
21148                :    {
21149      1  0.0011 :        pFormat = (PictFormatPtr) SecurityLookupIDByType (client,
21150                :                                                          stuff->maskFormat,
21151                :                                                          PictFormatType,
21152                :                                                          DixReadAccess);
21153                :        if (!pFormat)
21154                :        {
21155                :            client->errorValue = stuff->maskFormat;
21156                :            return RenderErrBase + BadPictFormat;
21157                :        }
21158                :    }
21159                :    else
21160                :        pFormat = 0;
21161                :
21162      1  0.0011 :    glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
21163                :                                                     stuff->glyphset,
21164                :                                                     GlyphSetType,
21165                :                                                     DixReadAccess);
21166                :    if (!glyphSet)
21167                :    {
21168                :        client->errorValue = stuff->glyphset;
21169                :        return RenderErrBase + BadGlyphSet;
21170                :    }
21171                :
21172                :    buffer = (CARD8 *) (stuff + 1);
21173      2  0.0022 :    end = (CARD8 *) stuff + (client->req_len << 2);
21174                :    nglyph = 0;
21175                :    nlist = 0;
21176                :    while (buffer + sizeof (xGlyphElt) < end)
21177                :    {
21178                :        elt = (xGlyphElt *) buffer;
21179                :        buffer += sizeof (xGlyphElt);
21180                :        
21181                :        if (elt->len == 0xff)
21182                :        {
21183                :            buffer += 4;
21184                :        }
21185                :        else
21186                :        {
21187      1  0.0011 :            nlist++;
21188                :            nglyph += elt->len;
21189                :            space = size * elt->len;
21190                :            if (space & 3)
21191                :                space += 4 - (space & 3);
21192                :            buffer += space;
21193                :        }
21194                :    }
21195                :    if (nglyph <= NLOCALGLYPH)
21196                :        glyphsBase = glyphsLocal;
21197                :    else
21198                :    {
21199                :        glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr));
21200                :        if (!glyphsBase)
21201                :            return BadAlloc;
21202                :    }
21203                :    if (nlist <= NLOCALDELTA)
21204                :        listsBase = listsLocal;
21205                :    else
21206                :    {
21207                :        listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec));
21208                :        if (!listsBase)
21209                :            return BadAlloc;
21210                :    }
21211                :    buffer = (CARD8 *) (stuff + 1);
21212                :    glyphs = glyphsBase;
21213                :    lists = listsBase;
21214      1  0.0011 :    while (buffer + sizeof (xGlyphElt) < end)
21215                :    {
21216                :        elt = (xGlyphElt *) buffer;
21217                :        buffer += sizeof (xGlyphElt);
21218                :        
21219                :        if (elt->len == 0xff)
21220                :        {
21221                :            if (buffer + sizeof (GlyphSet) < end)
21222                :            {
21223                :                memcpy(&gs, buffer, sizeof(GlyphSet));
21224                :                glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
21225                :                                                                 gs,
21226                :                                                                 GlyphSetType,
21227                :                                                                 DixReadAccess);
21228                :                if (!glyphSet)
21229                :                {
21230                :                    client->errorValue = gs;
21231                :                    if (glyphsBase != glyphsLocal)
21232                :                        DEALLOCATE_LOCAL (glyphsBase);
21233                :                    if (listsBase != listsLocal)
21234                :                        DEALLOCATE_LOCAL (listsBase);
21235                :                    return RenderErrBase + BadGlyphSet;
21236                :                }
21237                :            }
21238                :            buffer += 4;
21239                :        }
21240                :        else
21241                :        {
21242                :            lists->xOff = elt->deltax;
21243                :            lists->yOff = elt->deltay;
21244      1  0.0011 :            lists->format = glyphSet->format;
21245                :            lists->len = 0;
21246                :            n = elt->len;
21247      3  0.0033 :            while (n--)
21248                :            {
21249                :                if (buffer + size <= end)
21250                :                {
21251                :                    switch (size) {
21252                :                    case 1:
21253      7  0.0076 :                        glyph = *((CARD8 *)buffer); break;
21254                :                    case 2:
21255                :                        glyph = *((CARD16 *)buffer); break;
21256                :                    case 4:
21257                :                    default:
21258                :                        glyph = *((CARD32 *)buffer); break;
21259                :                    }
21260      5  0.0054 :                    if ((*glyphs = FindGlyph (glyphSet, glyph)))
21261                :                    {
21262      2  0.0022 :                        lists->len++;
21263                :                        glyphs++;
21264                :                    }
21265                :                }
21266                :                buffer += size;
21267                :            }
21268                :            space = size * elt->len;
21269                :            if (space & 3)
21270      1  0.0011 :                buffer += 4 - (space & 3);
21271                :            lists++;
21272                :        }
21273                :    }
21274                :    if (buffer > end)
21275                :        return BadLength;
21276                :
21277      1  0.0011 :    CompositeGlyphs (stuff->op,
21278                :                     pSrc,
21279                :                     pDst,
21280                :                     pFormat,
21281                :                     stuff->xSrc,
21282                :                     stuff->ySrc,
21283                :                     nlist,
21284                :                     listsBase,
21285                :                     glyphsBase);
21286                :
21287                :    if (glyphsBase != glyphsLocal)
21288                :        DEALLOCATE_LOCAL (glyphsBase);
21289                :    if (listsBase != listsLocal)
21290                :        DEALLOCATE_LOCAL (listsBase);
21291                :    
21292                :    return client->noClientException;
21293                :}
21294                :
21295                :static int
21296                :ProcRenderFillRectangles (ClientPtr client)
21297      4  0.0044 :{ /* ProcRenderFillRectangles total:     10  0.0109 */
21298                :    PicturePtr      pDst;
21299                :    int             things;
21300                :    REQUEST(xRenderFillRectanglesReq);
21301                :    
21302                :    REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq);
21303      1  0.0011 :    if (!PictOpValid (stuff->op))
21304                :    {
21305                :        client->errorValue = stuff->op;
21306                :        return BadValue;
21307                :    }
21308                :    VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, 
21309                :                    RenderErrBase + BadPicture);
21310                :    if (!pDst->pDrawable)
21311                :        return BadDrawable;
21312                :    
21313                :    things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
21314                :    if (things & 4)
21315                :        return(BadLength);
21316                :    things >>= 3;
21317                :    
21318      2  0.0022 :    CompositeRects (stuff->op,
21319                :                    pDst,
21320                :                    &stuff->color,
21321                :                    things,
21322                :                    (xRectangle *) &stuff[1]);
21323                :    
21324      1  0.0011 :    return client->noClientException;
21325      2  0.0022 :}
21326                :
21327                :static void
21328                :SetBit (unsigned char *line, int x, int bit)
21329                :{
21330                :    unsigned char   mask;
21331                :    
21332                :    if (screenInfo.bitmapBitOrder == LSBFirst)
21333                :        mask = (1 << (x & 7));
21334                :    else
21335                :        mask = (0x80 >> (x & 7));
21336                :    /* XXX assumes byte order is host byte order */
21337                :    line += (x >> 3);
21338                :    if (bit)
21339                :        *line |= mask;
21340                :    else
21341                :        *line &= ~mask;
21342                :}
21343                :
21344                :#define DITHER_DIM 2
21345                :
21346                :static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = {
21347                :    {  1,  3,  },
21348                :    {  4,  2,  },
21349                :};
21350                :
21351                :#define DITHER_SIZE  ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1)
21352                :
21353                :static int
21354                :ProcRenderCreateCursor (ClientPtr client)
21355                :{
21356                :    REQUEST(xRenderCreateCursorReq);
21357                :    PicturePtr      pSrc;
21358                :    ScreenPtr       pScreen;
21359                :    unsigned short  width, height;
21360                :    CARD32          *argbbits, *argb;
21361                :    unsigned char   *srcbits, *srcline;
21362                :    unsigned char   *mskbits, *mskline;
21363                :    int             stride;
21364                :    int             x, y;
21365                :    int             nbytes_mono;
21366                :    CursorMetricRec cm;
21367                :    CursorPtr       pCursor;
21368                :    CARD32          twocolor[3];
21369                :    int             ncolor;
21370                :
21371                :    REQUEST_SIZE_MATCH (xRenderCreateCursorReq);
21372                :    LEGAL_NEW_RESOURCE(stuff->cid, client);
21373                :    
21374                :    VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, 
21375                :                    RenderErrBase + BadPicture);
21376                :    if (!pSrc->pDrawable)
21377                :        return BadDrawable;
21378                :    pScreen = pSrc->pDrawable->pScreen;
21379                :    width = pSrc->pDrawable->width;
21380                :    height = pSrc->pDrawable->height;
21381                :    if ( stuff->x > width 
21382                :      || stuff->y > height )
21383                :        return (BadMatch);
21384                :    argbbits = xalloc (width * height * sizeof (CARD32));
21385                :    if (!argbbits)
21386                :        return (BadAlloc);
21387                :    
21388                :    stride = BitmapBytePad(width);
21389                :    nbytes_mono = stride*height;
21390                :    srcbits = (unsigned char *)xalloc(nbytes_mono);
21391                :    if (!srcbits)
21392                :    {
21393                :        xfree (argbbits);
21394                :        return (BadAlloc);
21395                :    }
21396                :    mskbits = (unsigned char *)xalloc(nbytes_mono);
21397                :    if (!mskbits)
21398                :    {
21399                :        xfree(argbbits);
21400                :        xfree(srcbits);
21401                :        return (BadAlloc);
21402                :    }
21403                :    bzero ((char *) mskbits, nbytes_mono);
21404                :    bzero ((char *) srcbits, nbytes_mono);
21405                :
21406                :    if (pSrc->format == PICT_a8r8g8b8)
21407                :    {
21408                :        (*pScreen->GetImage) (pSrc->pDrawable,
21409                :                              0, 0, width, height, ZPixmap,
21410                :                              0xffffffff, (pointer) argbbits);
21411                :    }
21412                :    else
21413                :    {
21414                :        PixmapPtr       pPixmap;
21415                :        PicturePtr      pPicture;
21416                :        PictFormatPtr   pFormat;
21417                :        int             error;
21418                :
21419                :        pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
21420                :        if (!pFormat)
21421                :        {
21422                :            xfree (argbbits);
21423                :            xfree (srcbits);
21424                :            xfree (mskbits);
21425                :            return (BadImplementation);
21426                :        }
21427                :        pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32);
21428                :        if (!pPixmap)
21429                :        {
21430                :            xfree (argbbits);
21431                :            xfree (srcbits);
21432                :            xfree (mskbits);
21433                :            return (BadAlloc);
21434                :        }
21435                :        pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, 
21436                :                                  client, &error);
21437                :        if (!pPicture)
21438                :        {
21439                :            xfree (argbbits);
21440                :            xfree (srcbits);
21441                :            xfree (mskbits);
21442                :            return error;
21443                :        }
21444                :        (*pScreen->DestroyPixmap) (pPixmap);
21445                :        CompositePicture (PictOpSrc,
21446                :                          pSrc, 0, pPicture,
21447                :                          0, 0, 0, 0, 0, 0, width, height);
21448                :        (*pScreen->GetImage) (pPicture->pDrawable,
21449                :                              0, 0, width, height, ZPixmap,
21450                :                              0xffffffff, (pointer) argbbits);
21451                :        FreePicture (pPicture, 0);
21452                :    }
21453                :    /*
21454                :     * Check whether the cursor can be directly supported by 
21455                :     * the core cursor code
21456                :     */
21457                :    ncolor = 0;
21458                :    argb = argbbits;
21459                :    for (y = 0; ncolor <= 2 && y < height; y++)
21460                :    {
21461                :        for (x = 0; ncolor <= 2 && x < width; x++)
21462                :        {
21463                :            CARD32  p = *argb++;
21464                :            CARD32  a = (p >> 24);
21465                :
21466                :            if (a == 0)     /* transparent */
21467                :                continue;
21468                :            if (a == 0xff)  /* opaque */
21469                :            {
21470                :                int n;
21471                :                for (n = 0; n < ncolor; n++)
21472                :                    if (p == twocolor[n])
21473                :                        break;
21474                :                if (n == ncolor)
21475                :                    twocolor[ncolor++] = p;
21476                :            }
21477                :            else
21478                :                ncolor = 3;
21479                :        }
21480                :    }
21481                :    
21482                :    /*
21483                :     * Convert argb image to two plane cursor
21484                :     */
21485                :    srcline = srcbits;
21486                :    mskline = mskbits;
21487                :    argb = argbbits;
21488                :    for (y = 0; y < height; y++)
21489                :    {
21490                :        for (x = 0; x < width; x++)
21491                :        {
21492                :            CARD32  p = *argb++;
21493                :
21494                :            if (ncolor <= 2)
21495                :            {
21496                :                CARD32  a = ((p >> 24));
21497                :
21498                :                SetBit (mskline, x, a != 0);
21499                :                SetBit (srcline, x, a != 0 && p == twocolor[0]);
21500                :            }
21501                :            else
21502                :            {
21503                :                CARD32  a = ((p >> 24) * DITHER_SIZE + 127) / 255;
21504                :                CARD32  i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255;
21505                :                CARD32  d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)];
21506                :                /* Set mask from dithered alpha value */
21507                :                SetBit(mskline, x, a > d);
21508                :                /* Set src from dithered intensity value */
21509                :                SetBit(srcline, x, a > d && i <= d);
21510                :            }
21511                :        }
21512                :        srcline += stride;
21513                :        mskline += stride;
21514                :    }
21515                :    /*
21516                :     * Dither to white and black if the cursor has more than two colors
21517                :     */
21518                :    if (ncolor > 2)
21519                :    {
21520                :        twocolor[0] = 0xff000000;
21521                :        twocolor[1] = 0xffffffff;
21522                :    }
21523                :    else
21524                :    {
21525                :        xfree (argbbits);
21526                :        argbbits = 0;
21527                :    }
21528                :    
21529                :#define GetByte(p,s)    (((p) >> (s)) & 0xff)
21530                :#define GetColor(p,s)   (GetByte(p,s) | (GetByte(p,s) << 8))
21531                :    
21532                :    cm.width = width;
21533                :    cm.height = height;
21534                :    cm.xhot = stuff->x;
21535                :    cm.yhot = stuff->y;
21536                :    pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm,
21537                :                               GetColor(twocolor[0], 16),
21538                :                               GetColor(twocolor[0], 8),
21539                :                               GetColor(twocolor[0], 0),
21540                :                               GetColor(twocolor[1], 16),
21541                :                               GetColor(twocolor[1], 8),
21542                :                               GetColor(twocolor[1], 0));
21543                :    if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
21544                :        return (client->noClientException);
21545                :    return BadAlloc;
21546                :}
21547                :
21548                :static int
21549                :ProcRenderSetPictureTransform (ClientPtr client)
21550                :{ /* ProcRenderSetPictureTransform total:      2  0.0022 */
21551                :    REQUEST(xRenderSetPictureTransformReq);
21552                :    PicturePtr  pPicture;
21553                :    int         result;
21554                :
21555      1  0.0011 :    REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
21556                :    VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
21557                :                    RenderErrBase + BadPicture);
21558                :    result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform);
21559                :    if (client->noClientException != Success)
21560                :        return(client->noClientException);
21561                :    else
21562                :        return(result);
21563      1  0.0011 :}
21564                :
21565                :static int
21566                :ProcRenderQueryFilters (ClientPtr client)
21567                :{
21568                :    REQUEST (xRenderQueryFiltersReq);
21569                :    DrawablePtr                 pDrawable;
21570                :    xRenderQueryFiltersReply    *reply;
21571                :    int                         nbytesName;
21572                :    int                         nnames;
21573                :    ScreenPtr                   pScreen;
21574                :    PictureScreenPtr            ps;
21575                :    int                         i, j, len, total_bytes, rc;
21576                :    INT16                       *aliases;
21577                :    char                        *names;
21578                :
21579                :    REQUEST_SIZE_MATCH(xRenderQueryFiltersReq);
21580                :    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
21581                :                           DixReadAccess);
21582                :    if (rc != Success)
21583                :        return rc;
21584                :    
21585                :    pScreen = pDrawable->pScreen;
21586                :    nbytesName = 0;
21587                :    nnames = 0;
21588                :    ps = GetPictureScreenIfSet(pScreen);
21589                :    if (ps)
21590                :    {
21591                :        for (i = 0; i < ps->nfilters; i++)
21592                :            nbytesName += 1 + strlen (ps->filters[i].name);
21593                :        for (i = 0; i < ps->nfilterAliases; i++)
21594                :            nbytesName += 1 + strlen (ps->filterAliases[i].alias);
21595                :        nnames = ps->nfilters + ps->nfilterAliases;
21596                :    }
21597                :    len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2);
21598                :    total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2);
21599                :    reply = (xRenderQueryFiltersReply *) xalloc (total_bytes);
21600                :    if (!reply)
21601                :        return BadAlloc;
21602                :    aliases = (INT16 *) (reply + 1);
21603                :    names = (char *) (aliases + ((nnames + 1) & ~1));
21604                :    
21605                :    reply->type = X_Reply;
21606                :    reply->sequenceNumber = client->sequence;
21607                :    reply->length = len;
21608                :    reply->numAliases = nnames;
21609                :    reply->numFilters = nnames;
21610                :    if (ps)
21611                :    {
21612                :
21613                :        /* fill in alias values */
21614                :        for (i = 0; i < ps->nfilters; i++)
21615                :            aliases[i] = FilterAliasNone;
21616                :        for (i = 0; i < ps->nfilterAliases; i++)
21617                :        {
21618                :            for (j = 0; j < ps->nfilters; j++)
21619                :                if (ps->filterAliases[i].filter_id == ps->filters[j].id)
21620                :                    break;
21621                :            if (j == ps->nfilters)
21622                :            {
21623                :                for (j = 0; j < ps->nfilterAliases; j++)
21624                :                    if (ps->filterAliases[i].filter_id == 
21625                :                        ps->filterAliases[j].alias_id)
21626                :                    {
21627                :                        break;
21628                :                    }
21629                :                if (j == ps->nfilterAliases)
21630                :                    j = FilterAliasNone;
21631                :                else
21632                :                    j = j + ps->nfilters;
21633                :            }
21634                :            aliases[i + ps->nfilters] = j;
21635                :        }
21636                :
21637                :        /* fill in filter names */
21638                :        for (i = 0; i < ps->nfilters; i++)
21639                :        {
21640                :            j = strlen (ps->filters[i].name);
21641                :            *names++ = j;
21642                :            strncpy (names, ps->filters[i].name, j);
21643                :            names += j;
21644                :        }
21645                :        
21646                :        /* fill in filter alias names */
21647                :        for (i = 0; i < ps->nfilterAliases; i++)
21648                :        {
21649                :            j = strlen (ps->filterAliases[i].alias);
21650                :            *names++ = j;
21651                :            strncpy (names, ps->filterAliases[i].alias, j);
21652                :            names += j;
21653                :        }
21654                :    }
21655                :
21656                :    if (client->swapped)
21657                :    {
21658                :        register int n;
21659                :
21660                :        for (i = 0; i < reply->numAliases; i++)
21661                :        {
21662                :            swaps (&aliases[i], n);
21663                :        }
21664                :        swaps(&reply->sequenceNumber, n);
21665                :        swapl(&reply->length, n);
21666                :        swapl(&reply->numAliases, n);
21667                :        swapl(&reply->numFilters, n);
21668                :    }
21669                :    WriteToClient(client, total_bytes, (char *) reply);
21670                :    xfree (reply);
21671                :    
21672                :    return(client->noClientException);
21673                :}
21674                :
21675                :static int
21676                :ProcRenderSetPictureFilter (ClientPtr client)
21677                :{ /* ProcRenderSetPictureFilter total:      4  0.0044 */
21678                :    REQUEST (xRenderSetPictureFilterReq);
21679                :    PicturePtr  pPicture;
21680                :    int         result;
21681                :    xFixed      *params;
21682                :    int         nparams;
21683                :    char        *name;
21684                :    
21685      1  0.0011 :    REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq);
21686      2  0.0022 :    VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
21687                :                    RenderErrBase + BadPicture);
21688                :    name = (char *) (stuff + 1);
21689                :    params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3));
21690                :    nparams = ((xFixed *) stuff + client->req_len) - params;
21691      1  0.0011 :    result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams);
21692                :    return result;
21693                :}
21694                :
21695                :static int
21696                :ProcRenderCreateAnimCursor (ClientPtr client)
21697                :{
21698                :    REQUEST(xRenderCreateAnimCursorReq);
21699                :    CursorPtr       *cursors;
21700                :    CARD32          *deltas;
21701                :    CursorPtr       pCursor;
21702                :    int             ncursor;
21703                :    xAnimCursorElt  *elt;
21704                :    int             i;
21705                :    int             ret;
21706                :
21707                :    REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq);
21708                :    LEGAL_NEW_RESOURCE(stuff->cid, client);
21709                :    if (client->req_len & 1)
21710                :        return BadLength;
21711                :    ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1;
21712                :    cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32)));
21713                :    if (!cursors)
21714                :        return BadAlloc;
21715                :    deltas = (CARD32 *) (cursors + ncursor);
21716                :    elt = (xAnimCursorElt *) (stuff + 1);
21717                :    for (i = 0; i < ncursor; i++)
21718                :    {
21719                :        cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor,
21720                :                                                       RT_CURSOR, DixReadAccess);
21721                :        if (!cursors[i])
21722                :        {
21723                :            xfree (cursors);
21724                :            client->errorValue = elt->cursor;
21725                :            return BadCursor;
21726                :        }
21727                :        deltas[i] = elt->delay;
21728                :        elt++;
21729                :    }
21730                :    ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor);
21731                :    xfree (cursors);
21732                :    if (ret != Success)
21733                :        return ret;
21734                :    
21735                :    if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor))
21736                :        return client->noClientException;
21737                :    return BadAlloc;
21738                :}
21739                :
21740                :static int
21741                :ProcRenderAddTraps (ClientPtr client)
21742                :{
21743                :    int         ntraps;
21744                :    PicturePtr  pPicture;
21745                :    REQUEST(xRenderAddTrapsReq);
21746                :
21747                :    REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
21748                :    VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess, 
21749                :                    RenderErrBase + BadPicture);
21750                :    if (!pPicture->pDrawable)
21751                :        return BadDrawable;
21752                :    ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq);
21753                :    if (ntraps % sizeof (xTrap))
21754                :        return BadLength;
21755                :    ntraps /= sizeof (xTrap);
21756                :    if (ntraps)
21757                :        AddTraps (pPicture,
21758                :                  stuff->xOff, stuff->yOff,
21759                :                  ntraps, (xTrap *) &stuff[1]);
21760                :    return client->noClientException;
21761                :}
21762                :
21763                :static int ProcRenderCreateSolidFill(ClientPtr client)
21764                :{
21765                :    PicturePtr      pPicture;
21766                :    int             error = 0;
21767                :    REQUEST(xRenderCreateSolidFillReq);
21768                :
21769                :    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
21770                :
21771                :    LEGAL_NEW_RESOURCE(stuff->pid, client);
21772                :
21773                :    pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error);
21774                :    if (!pPicture)
21775                :        return error;
21776                :    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
21777                :        return BadAlloc;
21778                :    return Success;
21779                :}
21780                :
21781                :static int ProcRenderCreateLinearGradient (ClientPtr client)
21782                :{
21783                :    PicturePtr      pPicture;
21784                :    int             len;
21785                :    int             error = 0;
21786                :    xFixed          *stops;
21787                :    xRenderColor   *colors;
21788                :    REQUEST(xRenderCreateLinearGradientReq);
21789                :
21790                :    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
21791                :
21792                :    LEGAL_NEW_RESOURCE(stuff->pid, client);
21793                :
21794                :    len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
21795                :    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
21796                :        return BadLength;
21797                :
21798                :    stops = (xFixed *)(stuff + 1);
21799                :    colors = (xRenderColor *)(stops + stuff->nStops);
21800                :
21801                :    pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2,
21802                :                                            stuff->nStops, stops, colors, &error);
21803                :    if (!pPicture)
21804                :        return error;
21805                :    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
21806                :        return BadAlloc;
21807                :    return Success;
21808                :}
21809                :
21810                :static int ProcRenderCreateRadialGradient (ClientPtr client)
21811                :{
21812                :    PicturePtr      pPicture;
21813                :    int             len;
21814                :    int             error = 0;
21815                :    xFixed          *stops;
21816                :    xRenderColor   *colors;
21817                :    REQUEST(xRenderCreateRadialGradientReq);
21818                :
21819                :    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
21820                :
21821                :    LEGAL_NEW_RESOURCE(stuff->pid, client);
21822                :
21823                :    len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
21824                :    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
21825                :        return BadLength;
21826                :
21827                :    stops = (xFixed *)(stuff + 1);
21828                :    colors = (xRenderColor *)(stops + stuff->nStops);
21829                :
21830                :    pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer,
21831                :                                            stuff->inner_radius, stuff->outer_radius,
21832                :                                            stuff->nStops, stops, colors, &error);
21833                :    if (!pPicture)
21834                :        return error;
21835                :    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
21836                :        return BadAlloc;
21837                :    return Success;
21838                :}
21839                :
21840                :static int ProcRenderCreateConicalGradient (ClientPtr client)
21841                :{
21842                :    PicturePtr      pPicture;
21843                :    int             len;
21844                :    int             error = 0;
21845                :    xFixed          *stops;
21846                :    xRenderColor   *colors;
21847                :    REQUEST(xRenderCreateConicalGradientReq);
21848                :
21849                :    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
21850                :
21851                :    LEGAL_NEW_RESOURCE(stuff->pid, client);
21852                :
21853                :    len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
21854                :    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
21855                :        return BadLength;
21856                :
21857                :    stops = (xFixed *)(stuff + 1);
21858                :    colors = (xRenderColor *)(stops + stuff->nStops);
21859                :
21860                :    pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle,
21861                :                                             stuff->nStops, stops, colors, &error);
21862                :    if (!pPicture)
21863                :        return error;
21864                :    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
21865                :        return BadAlloc;
21866                :    return Success;
21867                :}
21868                :
21869                :
21870                :static int
21871                :ProcRenderDispatch (ClientPtr client)
21872      8  0.0087 :{ /* ProcRenderDispatch total:     10  0.0109 */
21873                :    REQUEST(xReq);
21874                :    
21875      1  0.0011 :    if (stuff->data < RenderNumberRequests)
21876                :        return (*ProcRenderVector[stuff->data]) (client);
21877                :    else
21878                :        return BadRequest;
21879      1  0.0011 :}
21880                :
21881                :static int
21882                :SProcRenderQueryVersion (ClientPtr client)
21883                :{
21884                :    register int n;
21885                :    REQUEST(xRenderQueryVersionReq);
21886                :
21887                :    swaps(&stuff->length, n);
21888                :    swapl(&stuff->majorVersion, n);
21889                :    swapl(&stuff->minorVersion, n);
21890                :    return (*ProcRenderVector[stuff->renderReqType])(client);
21891                :}
21892                :
21893                :static int
21894                :SProcRenderQueryPictFormats (ClientPtr client)
21895                :{
21896                :    register int n;
21897                :    REQUEST(xRenderQueryPictFormatsReq);
21898                :    swaps(&stuff->length, n);
21899                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
21900                :}
21901                :
21902                :static int
21903                :SProcRenderQueryPictIndexValues (ClientPtr client)
21904                :{
21905                :    register int n;
21906                :    REQUEST(xRenderQueryPictIndexValuesReq);
21907                :    swaps(&stuff->length, n);
21908                :    swapl(&stuff->format, n);
21909                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
21910                :}
21911                :
21912                :static int
21913                :SProcRenderQueryDithers (ClientPtr client)
21914                :{
21915                :    return BadImplementation;
21916                :}
21917                :
21918                :static int
21919                :SProcRenderCreatePicture (ClientPtr client)
21920                :{
21921                :    register int n;
21922                :    REQUEST(xRenderCreatePictureReq);
21923                :    swaps(&stuff->length, n);
21924                :    swapl(&stuff->pid, n);
21925                :    swapl(&stuff->drawable, n);
21926                :    swapl(&stuff->format, n);
21927                :    swapl(&stuff->mask, n);
21928                :    SwapRestL(stuff);
21929                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
21930                :}
21931                :
21932                :static int
21933                :SProcRenderChangePicture (ClientPtr client)
21934                :{
21935                :    register int n;
21936                :    REQUEST(xRenderChangePictureReq);
21937                :    swaps(&stuff->length, n);
21938                :    swapl(&stuff->picture, n);
21939                :    swapl(&stuff->mask, n);
21940                :    SwapRestL(stuff);
21941                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
21942                :}
21943                :
21944                :static int
21945                :SProcRenderSetPictureClipRectangles (ClientPtr client)
21946                :{
21947                :    register int n;
21948                :    REQUEST(xRenderSetPictureClipRectanglesReq);
21949                :    swaps(&stuff->length, n);
21950                :    swapl(&stuff->picture, n);
21951                :    swaps(&stuff->xOrigin, n);
21952                :    swaps(&stuff->yOrigin, n);
21953                :    SwapRestS(stuff);
21954                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
21955                :}
21956                :
21957                :static int
21958                :SProcRenderFreePicture (ClientPtr client)
21959                :{
21960                :    register int n;
21961                :    REQUEST(xRenderFreePictureReq);
21962                :    swaps(&stuff->length, n);
21963                :    swapl(&stuff->picture, n);
21964                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
21965                :}
21966                :
21967                :static int
21968                :SProcRenderComposite (ClientPtr client)
21969                :{
21970                :    register int n;
21971                :    REQUEST(xRenderCompositeReq);
21972                :    swaps(&stuff->length, n);
21973                :    swapl(&stuff->src, n);
21974                :    swapl(&stuff->mask, n);
21975                :    swapl(&stuff->dst, n);
21976                :    swaps(&stuff->xSrc, n);
21977                :    swaps(&stuff->ySrc, n);
21978                :    swaps(&stuff->xMask, n);
21979                :    swaps(&stuff->yMask, n);
21980                :    swaps(&stuff->xDst, n);
21981                :    swaps(&stuff->yDst, n);
21982                :    swaps(&stuff->width, n);
21983                :    swaps(&stuff->height, n);
21984                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
21985                :}
21986                :
21987                :static int
21988                :SProcRenderScale (ClientPtr client)
21989                :{
21990                :    register int n;
21991                :    REQUEST(xRenderScaleReq);
21992                :    swaps(&stuff->length, n);
21993                :    swapl(&stuff->src, n);
21994                :    swapl(&stuff->dst, n);
21995                :    swapl(&stuff->colorScale, n);
21996                :    swapl(&stuff->alphaScale, n);
21997                :    swaps(&stuff->xSrc, n);
21998                :    swaps(&stuff->ySrc, n);
21999                :    swaps(&stuff->xDst, n);
22000                :    swaps(&stuff->yDst, n);
22001                :    swaps(&stuff->width, n);
22002                :    swaps(&stuff->height, n);
22003                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22004                :}
22005                :
22006                :static int
22007                :SProcRenderTrapezoids (ClientPtr client)
22008                :{
22009                :    register int n;
22010                :    REQUEST(xRenderTrapezoidsReq);
22011                :
22012                :    REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
22013                :    swaps (&stuff->length, n);
22014                :    swapl (&stuff->src, n);
22015                :    swapl (&stuff->dst, n);
22016                :    swapl (&stuff->maskFormat, n);
22017                :    swaps (&stuff->xSrc, n);
22018                :    swaps (&stuff->ySrc, n);
22019                :    SwapRestL(stuff);
22020                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22021                :}
22022                :
22023                :static int
22024                :SProcRenderTriangles (ClientPtr client)
22025                :{
22026                :    register int n;
22027                :    REQUEST(xRenderTrianglesReq);
22028                :
22029                :    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
22030                :    swaps (&stuff->length, n);
22031                :    swapl (&stuff->src, n);
22032                :    swapl (&stuff->dst, n);
22033                :    swapl (&stuff->maskFormat, n);
22034                :    swaps (&stuff->xSrc, n);
22035                :    swaps (&stuff->ySrc, n);
22036                :    SwapRestL(stuff);
22037                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22038                :}
22039                :
22040                :static int
22041                :SProcRenderTriStrip (ClientPtr client)
22042                :{
22043                :    register int n;
22044                :    REQUEST(xRenderTriStripReq);
22045                :
22046                :    REQUEST_AT_LEAST_SIZE(xRenderTriStripReq);
22047                :    swaps (&stuff->length, n);
22048                :    swapl (&stuff->src, n);
22049                :    swapl (&stuff->dst, n);
22050                :    swapl (&stuff->maskFormat, n);
22051                :    swaps (&stuff->xSrc, n);
22052                :    swaps (&stuff->ySrc, n);
22053                :    SwapRestL(stuff);
22054                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22055                :}
22056                :
22057                :static int
22058                :SProcRenderTriFan (ClientPtr client)
22059                :{
22060                :    register int n;
22061                :    REQUEST(xRenderTriFanReq);
22062                :
22063                :    REQUEST_AT_LEAST_SIZE(xRenderTriFanReq);
22064                :    swaps (&stuff->length, n);
22065                :    swapl (&stuff->src, n);
22066                :    swapl (&stuff->dst, n);
22067                :    swapl (&stuff->maskFormat, n);
22068                :    swaps (&stuff->xSrc, n);
22069                :    swaps (&stuff->ySrc, n);
22070                :    SwapRestL(stuff);
22071                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22072                :}
22073                :
22074                :static int
22075                :SProcRenderColorTrapezoids (ClientPtr client)
22076                :{
22077                :    return BadImplementation;
22078                :}
22079                :
22080                :static int
22081                :SProcRenderColorTriangles (ClientPtr client)
22082                :{
22083                :    return BadImplementation;
22084                :}
22085                :
22086                :static int
22087                :SProcRenderTransform (ClientPtr client)
22088                :{
22089                :    return BadImplementation;
22090                :}
22091                :
22092                :static int
22093                :SProcRenderCreateGlyphSet (ClientPtr client)
22094                :{
22095                :    register int n;
22096                :    REQUEST(xRenderCreateGlyphSetReq);
22097                :    swaps(&stuff->length, n);
22098                :    swapl(&stuff->gsid, n);
22099                :    swapl(&stuff->format, n);
22100                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22101                :}
22102                :
22103                :static int
22104                :SProcRenderReferenceGlyphSet (ClientPtr client)
22105                :{
22106                :    register int n;
22107                :    REQUEST(xRenderReferenceGlyphSetReq);
22108                :    swaps(&stuff->length, n);
22109                :    swapl(&stuff->gsid, n);
22110                :    swapl(&stuff->existing, n);
22111                :    return (*ProcRenderVector[stuff->renderReqType])  (client);
22112                :}
22113                :
22114                :static int
22115                :SProcRenderFreeGlyphSet (ClientPtr client)
22116                :{
22117                :    register int n;
22118                :    REQUEST(xRenderFreeGlyphSetReq);
22119                :    swaps(&stuff->length, n);
22120                :    swapl(&stuff->glyphset, n);
22121                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22122                :}
22123                :
22124                :static int
22125                :SProcRenderAddGlyphs (ClientPtr client)
22126                :{
22127                :    register int n;
22128                :    register int i;
22129                :    CARD32  *gids;
22130                :    void    *end;
22131                :    xGlyphInfo *gi;
22132                :    REQUEST(xRenderAddGlyphsReq);
22133                :    swaps(&stuff->length, n);
22134                :    swapl(&stuff->glyphset, n);
22135                :    swapl(&stuff->nglyphs, n);
22136                :    if (stuff->nglyphs & 0xe0000000)
22137                :        return BadLength;
22138                :    end = (CARD8 *) stuff + (client->req_len << 2);
22139                :    gids = (CARD32 *) (stuff + 1);
22140                :    gi = (xGlyphInfo *) (gids + stuff->nglyphs);
22141                :    if ((char *) end - (char *) (gids + stuff->nglyphs) < 0)
22142                :        return BadLength;
22143                :    if ((char *) end - (char *) (gi + stuff->nglyphs) < 0)
22144                :        return BadLength;
22145                :    for (i = 0; i < stuff->nglyphs; i++)
22146                :    {
22147                :        swapl (&gids[i], n);
22148                :        swaps (&gi[i].width, n);
22149                :        swaps (&gi[i].height, n);
22150                :        swaps (&gi[i].x, n);
22151                :        swaps (&gi[i].y, n);
22152                :        swaps (&gi[i].xOff, n);
22153                :        swaps (&gi[i].yOff, n);
22154                :    }
22155                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22156                :}
22157                :
22158                :static int
22159                :SProcRenderAddGlyphsFromPicture (ClientPtr client)
22160                :{
22161                :    return BadImplementation;
22162                :}
22163                :
22164                :static int
22165                :SProcRenderFreeGlyphs (ClientPtr client)
22166                :{
22167                :    register int n;
22168                :    REQUEST(xRenderFreeGlyphsReq);
22169                :    swaps(&stuff->length, n);
22170                :    swapl(&stuff->glyphset, n);
22171                :    SwapRestL(stuff);
22172                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22173                :}
22174                :
22175                :static int
22176                :SProcRenderCompositeGlyphs (ClientPtr client)
22177                :{
22178                :    register int n;
22179                :    xGlyphElt   *elt;
22180                :    CARD8       *buffer;
22181                :    CARD8       *end;
22182                :    int         space;
22183                :    int         i;
22184                :    int         size;
22185                :    
22186                :    REQUEST(xRenderCompositeGlyphsReq);
22187                :    
22188                :    switch (stuff->renderReqType) {
22189                :    default:                        size = 1; break;
22190                :    case X_RenderCompositeGlyphs16: size = 2; break;
22191                :    case X_RenderCompositeGlyphs32: size = 4; break;
22192                :    }
22193                :            
22194                :    swaps(&stuff->length, n);
22195                :    swapl(&stuff->src, n);
22196                :    swapl(&stuff->dst, n);
22197                :    swapl(&stuff->maskFormat, n);
22198                :    swapl(&stuff->glyphset, n);
22199                :    swaps(&stuff->xSrc, n);
22200                :    swaps(&stuff->ySrc, n);
22201                :    buffer = (CARD8 *) (stuff + 1);
22202                :    end = (CARD8 *) stuff + (client->req_len << 2);
22203                :    while (buffer + sizeof (xGlyphElt) < end)
22204                :    {
22205                :        elt = (xGlyphElt *) buffer;
22206                :        buffer += sizeof (xGlyphElt);
22207                :        
22208                :        swaps (&elt->deltax, n);
22209                :        swaps (&elt->deltay, n);
22210                :        
22211                :        i = elt->len;
22212                :        if (i == 0xff)
22213                :        {
22214                :            swapl (buffer, n);
22215                :            buffer += 4;
22216                :        }
22217                :        else
22218                :        {
22219                :            space = size * i;
22220                :            switch (size) {
22221                :            case 1:
22222                :                buffer += i;
22223                :                break;
22224                :            case 2:
22225                :                while (i--)
22226                :                {
22227                :                    swaps (buffer, n);
22228                :                    buffer += 2;
22229                :                }
22230                :                break;
22231                :            case 4:
22232                :                while (i--)
22233                :                {
22234                :                    swapl (buffer, n);
22235                :                    buffer += 4;
22236                :                }
22237                :                break;
22238                :            }
22239                :            if (space & 3)
22240                :                buffer += 4 - (space & 3);
22241                :        }
22242                :    }
22243                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22244                :}
22245                :
22246                :static int
22247                :SProcRenderFillRectangles (ClientPtr client)
22248                :{
22249                :    register int n;
22250                :    REQUEST(xRenderFillRectanglesReq);
22251                :
22252                :    REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq);
22253                :    swaps(&stuff->length, n);
22254                :    swapl(&stuff->dst, n);
22255                :    swaps(&stuff->color.red, n);
22256                :    swaps(&stuff->color.green, n);
22257                :    swaps(&stuff->color.blue, n);
22258                :    swaps(&stuff->color.alpha, n);
22259                :    SwapRestS(stuff);
22260                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22261                :}
22262                :    
22263                :static int
22264                :SProcRenderCreateCursor (ClientPtr client)
22265                :{
22266                :    register int n;
22267                :    REQUEST(xRenderCreateCursorReq);
22268                :    REQUEST_SIZE_MATCH (xRenderCreateCursorReq);
22269                :    
22270                :    swaps(&stuff->length, n);
22271                :    swapl(&stuff->cid, n);
22272                :    swapl(&stuff->src, n);
22273                :    swaps(&stuff->x, n);
22274                :    swaps(&stuff->y, n);
22275                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22276                :}
22277                :    
22278                :static int
22279                :SProcRenderSetPictureTransform (ClientPtr client)
22280                :{
22281                :    register int n;
22282                :    REQUEST(xRenderSetPictureTransformReq);
22283                :    REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
22284                :
22285                :    swaps(&stuff->length, n);
22286                :    swapl(&stuff->picture, n);
22287                :    swapl(&stuff->transform.matrix11, n);
22288                :    swapl(&stuff->transform.matrix12, n);
22289                :    swapl(&stuff->transform.matrix13, n);
22290                :    swapl(&stuff->transform.matrix21, n);
22291                :    swapl(&stuff->transform.matrix22, n);
22292                :    swapl(&stuff->transform.matrix23, n);
22293                :    swapl(&stuff->transform.matrix31, n);
22294                :    swapl(&stuff->transform.matrix32, n);
22295                :    swapl(&stuff->transform.matrix33, n);
22296                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22297                :}
22298                :
22299                :static int
22300                :SProcRenderQueryFilters (ClientPtr client)
22301                :{
22302                :    register int n;
22303                :    REQUEST (xRenderQueryFiltersReq);
22304                :    REQUEST_SIZE_MATCH (xRenderQueryFiltersReq);
22305                :
22306                :    swaps(&stuff->length, n);
22307                :    swapl(&stuff->drawable, n);
22308                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22309                :}
22310                :    
22311                :static int
22312                :SProcRenderSetPictureFilter (ClientPtr client)
22313                :{
22314                :    register int n;
22315                :    REQUEST (xRenderSetPictureFilterReq);
22316                :    REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq);
22317                :
22318                :    swaps(&stuff->length, n);
22319                :    swapl(&stuff->picture, n);
22320                :    swaps(&stuff->nbytes, n);
22321                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22322                :}
22323                :    
22324                :static int
22325                :SProcRenderCreateAnimCursor (ClientPtr client)
22326                :{
22327                :    register int n;
22328                :    REQUEST (xRenderCreateAnimCursorReq);
22329                :    REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq);
22330                :
22331                :    swaps(&stuff->length, n);
22332                :    swapl(&stuff->cid, n);
22333                :    SwapRestL(stuff);
22334                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22335                :}
22336                :
22337                :static int
22338                :SProcRenderAddTraps (ClientPtr client)
22339                :{
22340                :    register int n;
22341                :    REQUEST (xRenderAddTrapsReq);
22342                :    REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq);
22343                :
22344                :    swaps(&stuff->length, n);
22345                :    swapl(&stuff->picture, n);
22346                :    swaps(&stuff->xOff, n);
22347                :    swaps(&stuff->yOff, n);
22348                :    SwapRestL(stuff);
22349                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22350                :}
22351                :
22352                :static int
22353                :SProcRenderCreateSolidFill(ClientPtr client)
22354                :{
22355                :    register int n;
22356                :    REQUEST (xRenderCreateSolidFillReq);
22357                :    REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq);
22358                :
22359                :    swaps(&stuff->length, n);
22360                :    swapl(&stuff->pid, n);
22361                :    swaps(&stuff->color.alpha, n);
22362                :    swaps(&stuff->color.red, n);
22363                :    swaps(&stuff->color.green, n);
22364                :    swaps(&stuff->color.blue, n);
22365                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22366                :}
22367                :
22368                :static void swapStops(void *stuff, int n)
22369                :{
22370                :    int i;
22371                :    CARD32 *stops;
22372                :    CARD16 *colors;
22373                :    stops = (CARD32 *)(stuff);
22374                :    for (i = 0; i < n; ++i) {
22375                :        swapl(stops, n);
22376                :        ++stops;
22377                :    }
22378                :    colors = (CARD16 *)(stops);
22379                :    for (i = 0; i < 4*n; ++i) {
22380                :        swaps(stops, n);
22381                :        ++stops;
22382                :    }
22383                :}
22384                :
22385                :static int
22386                :SProcRenderCreateLinearGradient (ClientPtr client)
22387                :{
22388                :    register int n;
22389                :    int len;
22390                :    REQUEST (xRenderCreateLinearGradientReq);
22391                :    REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq);
22392                :
22393                :    swaps(&stuff->length, n);
22394                :    swapl(&stuff->pid, n);
22395                :    swapl(&stuff->p1.x, n);
22396                :    swapl(&stuff->p1.y, n);
22397                :    swapl(&stuff->p2.x, n);
22398                :    swapl(&stuff->p2.y, n);
22399                :    swapl(&stuff->nStops, n);
22400                :
22401                :    len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
22402                :    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
22403                :        return BadLength;
22404                :
22405                :    swapStops(stuff+1, stuff->nStops);
22406                :
22407                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22408                :}
22409                :
22410                :static int
22411                :SProcRenderCreateRadialGradient (ClientPtr client)
22412                :{
22413                :    register int n;
22414                :    int len;
22415                :    REQUEST (xRenderCreateRadialGradientReq);
22416                :    REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq);
22417                :
22418                :    swaps(&stuff->length, n);
22419                :    swapl(&stuff->pid, n);
22420                :    swapl(&stuff->inner.x, n);
22421                :    swapl(&stuff->inner.y, n);
22422                :    swapl(&stuff->outer.x, n);
22423                :    swapl(&stuff->outer.y, n);
22424                :    swapl(&stuff->inner_radius, n);
22425                :    swapl(&stuff->outer_radius, n);
22426                :    swapl(&stuff->nStops, n);
22427                :
22428                :    len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
22429                :    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
22430                :        return BadLength;
22431                :
22432                :    swapStops(stuff+1, stuff->nStops);
22433                :
22434                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22435                :}
22436                :
22437                :static int
22438                :SProcRenderCreateConicalGradient (ClientPtr client)
22439                :{
22440                :    register int n;
22441                :    int len;
22442                :    REQUEST (xRenderCreateConicalGradientReq);
22443                :    REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq);
22444                :
22445                :    swaps(&stuff->length, n);
22446                :    swapl(&stuff->pid, n);
22447                :    swapl(&stuff->center.x, n);
22448                :    swapl(&stuff->center.y, n);
22449                :    swapl(&stuff->angle, n);
22450                :    swapl(&stuff->nStops, n);
22451                :
22452                :    len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
22453                :    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
22454                :        return BadLength;
22455                :
22456                :    swapStops(stuff+1, stuff->nStops);
22457                :
22458                :    return (*ProcRenderVector[stuff->renderReqType]) (client);
22459                :}
22460                :
22461                :static int
22462                :SProcRenderDispatch (ClientPtr client)
22463                :{
22464                :    REQUEST(xReq);
22465                :    
22466                :    if (stuff->data < RenderNumberRequests)
22467                :        return (*SProcRenderVector[stuff->data]) (client);
22468                :    else
22469                :        return BadRequest;
22470                :}
22471                :
22472                :#ifdef PANORAMIX
22473                :#include "panoramiX.h"
22474                :#include "panoramiXsrv.h"
22475                :
22476                :#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\
22477                :    pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\
22478                :    if (!pPicture) { \
22479                :        client->errorValue = pid; \
22480                :        return err; \
22481                :    } \
22482                :}
22483                :
22484                :#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\
22485                :    if (pid == None) \
22486                :        pPicture = 0; \
22487                :    else { \
22488                :        VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \
22489                :    } \
22490                :} \
22491                :
22492                :int         (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr);
22493                :
22494                :unsigned long   XRT_PICTURE;
22495                :
22496                :static int
22497                :PanoramiXRenderCreatePicture (ClientPtr client)
22498                :{
22499                :    REQUEST(xRenderCreatePictureReq);
22500                :    PanoramiXRes    *refDraw, *newPict;
22501                :    int             result = Success, j;
22502                :
22503                :    REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
22504                :    if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass(
22505                :                client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess)))
22506                :        return BadDrawable;
22507                :    if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes))))
22508                :        return BadAlloc;
22509                :    newPict->type = XRT_PICTURE;
22510                :    newPict->info[0].id = stuff->pid;
22511                :    
22512                :    if (refDraw->type == XRT_WINDOW &&
22513                :        stuff->drawable == WindowTable[0]->drawable.id)
22514                :    {
22515                :        newPict->u.pict.root = TRUE;
22516                :    }
22517                :    else
22518                :        newPict->u.pict.root = FALSE;
22519                :
22520                :    for(j = 1; j < PanoramiXNumScreens; j++)
22521                :        newPict->info[j].id = FakeClientID(client->index);
22522                :    
22523                :    FOR_NSCREENS_BACKWARD(j) {
22524                :        stuff->pid = newPict->info[j].id;
22525                :        stuff->drawable = refDraw->info[j].id;
22526                :        result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client);
22527                :        if(result != Success) break;
22528                :    }
22529                :
22530                :    if (result == Success)
22531                :        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
22532                :    else 
22533                :        xfree(newPict);
22534                :
22535                :    return (result);
22536                :}
22537                :
22538                :static int
22539                :PanoramiXRenderChangePicture (ClientPtr client)
22540                :{
22541                :    PanoramiXRes    *pict;
22542                :    int             result = Success, j;
22543                :    REQUEST(xRenderChangePictureReq);
22544                :
22545                :    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
22546                :    
22547                :    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
22548                :                       RenderErrBase + BadPicture);
22549                :    
22550                :    FOR_NSCREENS_BACKWARD(j) {
22551                :        stuff->picture = pict->info[j].id;
22552                :        result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client);
22553                :        if(result != Success) break;
22554                :    }
22555                :
22556                :    return (result);
22557                :}
22558                :
22559                :static int
22560                :PanoramiXRenderSetPictureClipRectangles (ClientPtr client)
22561                :{
22562                :    REQUEST(xRenderSetPictureClipRectanglesReq);
22563                :    int             result = Success, j;
22564                :    PanoramiXRes    *pict;
22565                :
22566                :    REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
22567                :    
22568                :    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
22569                :                       RenderErrBase + BadPicture);
22570                :    
22571                :    FOR_NSCREENS_BACKWARD(j) {
22572                :        stuff->picture = pict->info[j].id;
22573                :        result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client);
22574                :        if(result != Success) break;
22575                :    }
22576                :
22577                :    return (result);
22578                :}
22579                :
22580                :static int
22581                :PanoramiXRenderSetPictureTransform (ClientPtr client)
22582                :{
22583                :    REQUEST(xRenderSetPictureTransformReq);
22584                :    int             result = Success, j;
22585                :    PanoramiXRes    *pict;
22586                :
22587                :    REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq);
22588                :    
22589                :    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
22590                :                       RenderErrBase + BadPicture);
22591                :    
22592                :    FOR_NSCREENS_BACKWARD(j) {
22593                :        stuff->picture = pict->info[j].id;
22594                :        result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client);
22595                :        if(result != Success) break;
22596                :    }
22597                :
22598                :    return (result);
22599                :}
22600                :
22601                :static int
22602                :PanoramiXRenderSetPictureFilter (ClientPtr client)
22603                :{
22604                :    REQUEST(xRenderSetPictureFilterReq);
22605                :    int             result = Success, j;
22606                :    PanoramiXRes    *pict;
22607                :
22608                :    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
22609                :    
22610                :    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
22611                :                       RenderErrBase + BadPicture);
22612                :    
22613                :    FOR_NSCREENS_BACKWARD(j) {
22614                :        stuff->picture = pict->info[j].id;
22615                :        result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client);
22616                :        if(result != Success) break;
22617                :    }
22618                :
22619                :    return (result);
22620                :}
22621                :
22622                :static int
22623                :PanoramiXRenderFreePicture (ClientPtr client)
22624                :{
22625                :    PanoramiXRes *pict;
22626                :    int         result = Success, j;
22627                :    REQUEST(xRenderFreePictureReq);
22628                :
22629                :    REQUEST_SIZE_MATCH(xRenderFreePictureReq);
22630                :
22631                :    client->errorValue = stuff->picture;
22632                :
22633                :    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess,
22634                :                       RenderErrBase + BadPicture);
22635                :    
22636                :
22637                :    FOR_NSCREENS_BACKWARD(j) {
22638                :        stuff->picture = pict->info[j].id;
22639                :        result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client);
22640                :        if(result != Success) break;
22641                :    }
22642                :
22643                :    /* Since ProcRenderFreePicture is using FreeResource, it will free
22644                :        our resource for us on the last pass through the loop above */
22645                : 
22646                :    return (result);
22647                :}
22648                :
22649                :static int
22650                :PanoramiXRenderComposite (ClientPtr client)
22651                :{
22652                :    PanoramiXRes        *src, *msk, *dst;
22653                :    int                 result = Success, j;
22654                :    xRenderCompositeReq orig;
22655                :    REQUEST(xRenderCompositeReq);
22656                :
22657                :    REQUEST_SIZE_MATCH(xRenderCompositeReq);
22658                :    
22659                :    VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess, 
22660                :                        RenderErrBase + BadPicture);
22661                :    VERIFY_XIN_ALPHA (msk, stuff->mask, client, DixReadAccess, 
22662                :                      RenderErrBase + BadPicture);
22663                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, 
22664                :                        RenderErrBase + BadPicture);
22665                :    
22666                :    orig = *stuff;
22667                :    
22668                :    FOR_NSCREENS_FORWARD(j) {
22669                :        stuff->src = src->info[j].id;
22670                :        if (src->u.pict.root)
22671                :        {
22672                :            stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x;
22673                :            stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y;
22674                :        }
22675                :        stuff->dst = dst->info[j].id;
22676                :        if (dst->u.pict.root)
22677                :        {
22678                :            stuff->xDst = orig.xDst - panoramiXdataPtr[j].x;
22679                :            stuff->yDst = orig.yDst - panoramiXdataPtr[j].y;
22680                :        }
22681                :        if (msk)
22682                :        {
22683                :            stuff->mask = msk->info[j].id;
22684                :            if (msk->u.pict.root)
22685                :            {
22686                :                stuff->xMask = orig.xMask - panoramiXdataPtr[j].x;
22687                :                stuff->yMask = orig.yMask - panoramiXdataPtr[j].y;
22688                :            }
22689                :        }
22690                :        result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client);
22691                :        if(result != Success) break;
22692                :    }
22693                :
22694                :    return result;
22695                :}
22696                :
22697                :static int
22698                :PanoramiXRenderCompositeGlyphs (ClientPtr client)
22699                :{
22700                :    PanoramiXRes    *src, *dst;
22701                :    int             result = Success, j;
22702                :    REQUEST(xRenderCompositeGlyphsReq);
22703                :    xGlyphElt       origElt, *elt;
22704                :    INT16           xSrc, ySrc;
22705                :
22706                :    REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
22707                :    VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
22708                :                        RenderErrBase + BadPicture);
22709                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
22710                :                        RenderErrBase + BadPicture);
22711                :
22712                :    if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) +
22713                :                                 sizeof (xGlyphElt)))
22714                :    {
22715                :        elt = (xGlyphElt *) (stuff + 1);
22716                :        origElt = *elt;
22717                :        xSrc = stuff->xSrc;
22718                :        ySrc = stuff->ySrc;
22719                :        FOR_NSCREENS_FORWARD(j) {
22720                :            stuff->src = src->info[j].id;
22721                :            if (src->u.pict.root)
22722                :            {
22723                :                stuff->xSrc = xSrc - panoramiXdataPtr[j].x;
22724                :                stuff->ySrc = ySrc - panoramiXdataPtr[j].y;
22725                :            }
22726                :            stuff->dst = dst->info[j].id;
22727                :            if (dst->u.pict.root)
22728                :            {
22729                :                elt->deltax = origElt.deltax - panoramiXdataPtr[j].x;
22730                :                elt->deltay = origElt.deltay - panoramiXdataPtr[j].y;
22731                :            }
22732                :            result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client);
22733                :            if(result != Success) break;
22734                :        }
22735                :    }
22736                :
22737                :    return result;
22738                :}
22739                :
22740                :static int
22741                :PanoramiXRenderFillRectangles (ClientPtr client)
22742                :{
22743                :    PanoramiXRes    *dst;
22744                :    int             result = Success, j;
22745                :    REQUEST(xRenderFillRectanglesReq);
22746                :    char            *extra;
22747                :    int             extra_len;
22748                :
22749                :    REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq);
22750                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, 
22751                :                        RenderErrBase + BadPicture);
22752                :    extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq);
22753                :    if (extra_len &&
22754                :        (extra = (char *) ALLOCATE_LOCAL (extra_len)))
22755                :    {
22756                :        memcpy (extra, stuff + 1, extra_len);
22757                :        FOR_NSCREENS_FORWARD(j) {
22758                :            if (j) memcpy (stuff + 1, extra, extra_len);
22759                :            if (dst->u.pict.root)
22760                :            {
22761                :                int x_off = panoramiXdataPtr[j].x;
22762                :                int y_off = panoramiXdataPtr[j].y;
22763                :
22764                :                if(x_off || y_off) {
22765                :                    xRectangle  *rects = (xRectangle *) (stuff + 1);
22766                :                    int         i = extra_len / sizeof (xRectangle);
22767                :
22768                :                    while (i--)
22769                :                    {
22770                :                        rects->x -= x_off;
22771                :                        rects->y -= y_off;
22772                :                        rects++;
22773                :                    }
22774                :                }
22775                :            }
22776                :            stuff->dst = dst->info[j].id;
22777                :            result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client);
22778                :            if(result != Success) break;
22779                :        }
22780                :        DEALLOCATE_LOCAL(extra);
22781                :    }
22782                :
22783                :    return result;
22784                :}
22785                :
22786                :static int
22787                :PanoramiXRenderTrapezoids(ClientPtr client)
22788                :{
22789                :    PanoramiXRes        *src, *dst;
22790                :    int                 result = Success, j;
22791                :    REQUEST(xRenderTrapezoidsReq);
22792                :    char                *extra;
22793                :    int                 extra_len;
22794                :    
22795                :    REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq);
22796                :    
22797                :    VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
22798                :                        RenderErrBase + BadPicture);
22799                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
22800                :                        RenderErrBase + BadPicture);
22801                :
22802                :    extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq);
22803                :
22804                :    if (extra_len &&
22805                :        (extra = (char *) ALLOCATE_LOCAL (extra_len))) {
22806                :        memcpy (extra, stuff + 1, extra_len);
22807                :
22808                :        FOR_NSCREENS_FORWARD(j) {
22809                :            if (j) memcpy (stuff + 1, extra, extra_len);
22810                :            if (dst->u.pict.root) {
22811                :                int x_off = panoramiXdataPtr[j].x;
22812                :                int y_off = panoramiXdataPtr[j].y;
22813                :
22814                :                if(x_off || y_off) {
22815                :                    xTrapezoid  *trap = (xTrapezoid *) (stuff + 1);
22816                :                    int         i = extra_len / sizeof (xTrapezoid);
22817                :
22818                :                    while (i--) {
22819                :                        trap->top -= y_off;
22820                :                        trap->bottom -= y_off;
22821                :                        trap->left.p1.x -= x_off;
22822                :                        trap->left.p1.y -= y_off;
22823                :                        trap->left.p2.x -= x_off;
22824                :                        trap->left.p2.y -= y_off;
22825                :                        trap->right.p1.x -= x_off;
22826                :                        trap->right.p1.y -= y_off;
22827                :                        trap->right.p2.x -= x_off;
22828                :                        trap->right.p2.y -= y_off;
22829                :                        trap++;
22830                :                    }
22831                :                }
22832                :            }
22833                :            
22834                :            stuff->src = src->info[j].id;
22835                :            stuff->dst = dst->info[j].id;
22836                :            result =
22837                :                (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client);
22838                :
22839                :            if(result != Success) break;
22840                :        }
22841                :        
22842                :        DEALLOCATE_LOCAL(extra);
22843                :    }
22844                :
22845                :    return result;
22846                :}
22847                :
22848                :static int
22849                :PanoramiXRenderTriangles(ClientPtr client)
22850                :{
22851                :    PanoramiXRes        *src, *dst;
22852                :    int                 result = Success, j;
22853                :    REQUEST(xRenderTrianglesReq);
22854                :    char                *extra;
22855                :    int                 extra_len;
22856                :    
22857                :    REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq);
22858                :    
22859                :    VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
22860                :                        RenderErrBase + BadPicture);
22861                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
22862                :                        RenderErrBase + BadPicture);
22863                :
22864                :    extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq);
22865                :
22866                :    if (extra_len &&
22867                :        (extra = (char *) ALLOCATE_LOCAL (extra_len))) {
22868                :        memcpy (extra, stuff + 1, extra_len);
22869                :
22870                :        FOR_NSCREENS_FORWARD(j) {
22871                :            if (j) memcpy (stuff + 1, extra, extra_len);
22872                :            if (dst->u.pict.root) {
22873                :                int x_off = panoramiXdataPtr[j].x;
22874                :                int y_off = panoramiXdataPtr[j].y;
22875                :
22876                :                if(x_off || y_off) {
22877                :                    xTriangle  *tri = (xTriangle *) (stuff + 1);
22878                :                    int         i = extra_len / sizeof (xTriangle);
22879                :
22880                :                    while (i--) {
22881                :                        tri->p1.x -= x_off;
22882                :                        tri->p1.y -= y_off;
22883                :                        tri->p2.x -= x_off;
22884                :                        tri->p2.y -= y_off;
22885                :                        tri->p3.x -= x_off;
22886                :                        tri->p3.y -= y_off;
22887                :                        tri++;
22888                :                    }
22889                :                }
22890                :            }
22891                :            
22892                :            stuff->src = src->info[j].id;
22893                :            stuff->dst = dst->info[j].id;
22894                :            result =
22895                :                (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client);
22896                :
22897                :            if(result != Success) break;
22898                :        }
22899                :        
22900                :        DEALLOCATE_LOCAL(extra);
22901                :    }
22902                :
22903                :    return result;
22904                :}
22905                :
22906                :static int
22907                :PanoramiXRenderTriStrip(ClientPtr client)
22908                :{
22909                :    PanoramiXRes        *src, *dst;
22910                :    int                 result = Success, j;
22911                :    REQUEST(xRenderTriStripReq);
22912                :    char                *extra;
22913                :    int                 extra_len;
22914                :    
22915                :    REQUEST_AT_LEAST_SIZE (xRenderTriStripReq);
22916                :    
22917                :    VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
22918                :                        RenderErrBase + BadPicture);
22919                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
22920                :                        RenderErrBase + BadPicture);
22921                :
22922                :    extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq);
22923                :
22924                :    if (extra_len &&
22925                :        (extra = (char *) ALLOCATE_LOCAL (extra_len))) {
22926                :        memcpy (extra, stuff + 1, extra_len);
22927                :
22928                :        FOR_NSCREENS_FORWARD(j) {
22929                :            if (j) memcpy (stuff + 1, extra, extra_len);
22930                :            if (dst->u.pict.root) {
22931                :                int x_off = panoramiXdataPtr[j].x;
22932                :                int y_off = panoramiXdataPtr[j].y;
22933                :
22934                :                if(x_off || y_off) {
22935                :                    xPointFixed  *fixed = (xPointFixed *) (stuff + 1);
22936                :                    int         i = extra_len / sizeof (xPointFixed);
22937                :
22938                :                    while (i--) {
22939                :                        fixed->x -= x_off;
22940                :                        fixed->y -= y_off;
22941                :                        fixed++;
22942                :                    }
22943                :                }
22944                :            }
22945                :            
22946                :            stuff->src = src->info[j].id;
22947                :            stuff->dst = dst->info[j].id;
22948                :            result =
22949                :                (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client);
22950                :
22951                :            if(result != Success) break;
22952                :        }
22953                :        
22954                :        DEALLOCATE_LOCAL(extra);
22955                :    }
22956                :
22957                :    return result;
22958                :}
22959                :
22960                :static int
22961                :PanoramiXRenderTriFan(ClientPtr client)
22962                :{
22963                :    PanoramiXRes        *src, *dst;
22964                :    int                 result = Success, j;
22965                :    REQUEST(xRenderTriFanReq);
22966                :    char                *extra;
22967                :    int                 extra_len;
22968                :    
22969                :    REQUEST_AT_LEAST_SIZE (xRenderTriFanReq);
22970                :    
22971                :    VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
22972                :                        RenderErrBase + BadPicture);
22973                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
22974                :                        RenderErrBase + BadPicture);
22975                :
22976                :    extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq);
22977                :
22978                :    if (extra_len &&
22979                :        (extra = (char *) ALLOCATE_LOCAL (extra_len))) {
22980                :        memcpy (extra, stuff + 1, extra_len);
22981                :
22982                :        FOR_NSCREENS_FORWARD(j) {
22983                :            if (j) memcpy (stuff + 1, extra, extra_len);
22984                :            if (dst->u.pict.root) {
22985                :                int x_off = panoramiXdataPtr[j].x;
22986                :                int y_off = panoramiXdataPtr[j].y;
22987                :
22988                :                if(x_off || y_off) {
22989                :                    xPointFixed  *fixed = (xPointFixed *) (stuff + 1);
22990                :                    int         i = extra_len / sizeof (xPointFixed);
22991                :
22992                :                    while (i--) {
22993                :                        fixed->x -= x_off;
22994                :                        fixed->y -= y_off;
22995                :                        fixed++;
22996                :                    }
22997                :                }
22998                :            }
22999                :            
23000                :            stuff->src = src->info[j].id;
23001                :            stuff->dst = dst->info[j].id;
23002                :            result =
23003                :                (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client);
23004                :
23005                :            if(result != Success) break;
23006                :        }
23007                :        
23008                :        DEALLOCATE_LOCAL(extra);
23009                :    }
23010                :
23011                :    return result;
23012                :}
23013                :
23014                :#if 0 /* Not implemented yet */
23015                :
23016                :static int
23017                :PanoramiXRenderColorTrapezoids(ClientPtr client)
23018                :{
23019                :    PanoramiXRes        *src, *dst;
23020                :    int                 result = Success, j;
23021                :    REQUEST(xRenderColorTrapezoidsReq);
23022                :    char                *extra;
23023                :    int                 extra_len;
23024                :    
23025                :    REQUEST_AT_LEAST_SIZE (xRenderColorTrapezoidsReq);
23026                :    
23027                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
23028                :                        RenderErrBase + BadPicture);
23029                :
23030                :    extra_len = (client->req_len << 2) - sizeof (xRenderColorTrapezoidsReq);
23031                :
23032                :    if (extra_len &&
23033                :        (extra = (char *) ALLOCATE_LOCAL (extra_len))) {
23034                :        memcpy (extra, stuff + 1, extra_len);
23035                :
23036                :        FOR_NSCREENS_FORWARD(j) {
23037                :            if (j) memcpy (stuff + 1, extra, extra_len);
23038                :            if (dst->u.pict.root) {
23039                :                int x_off = panoramiXdataPtr[j].x;
23040                :                int y_off = panoramiXdataPtr[j].y;
23041                :
23042                :                if(x_off || y_off) {
23043                :                        ....; 
23044                :                }
23045                :            }
23046                :            
23047                :            stuff->dst = dst->info[j].id;
23048                :            result =
23049                :                (*PanoramiXSaveRenderVector[X_RenderColorTrapezoids]) (client);
23050                :
23051                :            if(result != Success) break;
23052                :        }
23053                :        
23054                :        DEALLOCATE_LOCAL(extra);
23055                :    }
23056                :
23057                :    return result;
23058                :}
23059                :
23060                :static int
23061                :PanoramiXRenderColorTriangles(ClientPtr client)
23062                :{
23063                :    PanoramiXRes        *src, *dst;
23064                :    int                 result = Success, j;
23065                :    REQUEST(xRenderColorTrianglesReq);
23066                :    char                *extra;
23067                :    int                 extra_len;
23068                :    
23069                :    REQUEST_AT_LEAST_SIZE (xRenderColorTrianglesReq);
23070                :    
23071                :    VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
23072                :                        RenderErrBase + BadPicture);
23073                :
23074                :    extra_len = (client->req_len << 2) - sizeof (xRenderColorTrianglesReq);
23075                :
23076                :    if (extra_len &&
23077                :        (extra = (char *) ALLOCATE_LOCAL (extra_len))) {
23078                :        memcpy (extra, stuff + 1, extra_len);
23079                :
23080                :        FOR_NSCREENS_FORWARD(j) {
23081                :            if (j) memcpy (stuff + 1, extra, extra_len);
23082                :            if (dst->u.pict.root) {
23083                :                int x_off = panoramiXdataPtr[j].x;
23084                :                int y_off = panoramiXdataPtr[j].y;
23085                :
23086                :                if(x_off || y_off) {
23087                :                        ....; 
23088                :                }
23089                :            }
23090                :            
23091                :            stuff->dst = dst->info[j].id;
23092                :            result =
23093                :                (*PanoramiXSaveRenderVector[X_RenderColorTriangles]) (client);
23094                :
23095                :            if(result != Success) break;
23096                :        }
23097                :        
23098                :        DEALLOCATE_LOCAL(extra);
23099                :    }
23100                :
23101                :    return result;
23102                :}
23103                :
23104                :#endif
23105                :
23106                :static int
23107                :PanoramiXRenderAddTraps (ClientPtr client)
23108                :{
23109                :    PanoramiXRes    *picture;
23110                :    int             result = Success, j;
23111                :    REQUEST(xRenderAddTrapsReq);
23112                :    char            *extra;
23113                :    int             extra_len;
23114                :    INT16           x_off, y_off;
23115                :
23116                :    REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq);
23117                :    VERIFY_XIN_PICTURE (picture, stuff->picture, client, DixWriteAccess, 
23118                :                        RenderErrBase + BadPicture);
23119                :    extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq);
23120                :    if (extra_len &&
23121                :        (extra = (char *) ALLOCATE_LOCAL (extra_len)))
23122                :    {
23123                :        memcpy (extra, stuff + 1, extra_len);
23124                :        x_off = stuff->xOff;
23125                :        y_off = stuff->yOff;
23126                :        FOR_NSCREENS_FORWARD(j) {
23127                :            if (j) memcpy (stuff + 1, extra, extra_len);
23128                :            stuff->picture = picture->info[j].id;
23129                :            
23130                :            if (picture->u.pict.root)
23131                :            {
23132                :                stuff->xOff = x_off + panoramiXdataPtr[j].x;
23133                :                stuff->yOff = y_off + panoramiXdataPtr[j].y;
23134                :            }
23135                :            result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client);
23136                :            if(result != Success) break;
23137                :        }
23138                :        DEALLOCATE_LOCAL(extra);
23139                :    }
23140                :
23141                :    return result;
23142                :}
23143                :
23144                :void
23145                :PanoramiXRenderInit (void)
23146                :{
23147                :    int     i;
23148                :    
23149                :    XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource);
23150                :    for (i = 0; i < RenderNumberRequests; i++)
23151                :        PanoramiXSaveRenderVector[i] = ProcRenderVector[i];
23152                :    /*
23153                :     * Stuff in Xinerama aware request processing hooks
23154                :     */
23155                :    ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture;
23156                :    ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture;
23157                :    ProcRenderVector[X_RenderSetPictureTransform] = PanoramiXRenderSetPictureTransform;
23158                :    ProcRenderVector[X_RenderSetPictureFilter] = PanoramiXRenderSetPictureFilter;
23159                :    ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles;
23160                :    ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture;
23161                :    ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite;
23162                :    ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs;
23163                :    ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs;
23164                :    ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs;
23165                :    ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles;
23166                :
23167                :    ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids;
23168                :    ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles;
23169                :    ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip;
23170                :    ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan;
23171                :    ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps;
23172                :}
23173                :
23174                :void
23175                :PanoramiXRenderReset (void)
23176                :{
23177                :    int     i;
23178                :    for (i = 0; i < RenderNumberRequests; i++)
23179                :        ProcRenderVector[i] = PanoramiXSaveRenderVector[i];
23180                :}
23181                :
23182                :#endif  /* PANORAMIX */
23183 /* 
23184  * Total samples for file : "/home/cworth/src/xorg/xserver/render/picture.c"
23185  * 
23186  *     74  0.0806
23187  */
23188
23189
23190                :/*
23191                : *
23192                : * Copyright Â© 2000 SuSE, Inc.
23193                : *
23194                : * Permission to use, copy, modify, distribute, and sell this software and its
23195                : * documentation for any purpose is hereby granted without fee, provided that
23196                : * the above copyright notice appear in all copies and that both that
23197                : * copyright notice and this permission notice appear in supporting
23198                : * documentation, and that the name of SuSE not be used in advertising or
23199                : * publicity pertaining to distribution of the software without specific,
23200                : * written prior permission.  SuSE makes no representations about the
23201                : * suitability of this software for any purpose.  It is provided "as is"
23202                : * without express or implied warranty.
23203                : *
23204                : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
23205                : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
23206                : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23207                : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
23208                : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
23209                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23210                : *
23211                : * Author:  Keith Packard, SuSE, Inc.
23212                : */
23213                :
23214                :#ifdef HAVE_DIX_CONFIG_H
23215                :#include <dix-config.h>
23216                :#endif
23217                :
23218                :#include "misc.h"
23219                :#include "scrnintstr.h"
23220                :#include "os.h"
23221                :#include "regionstr.h"
23222                :#include "validate.h"
23223                :#include "windowstr.h"
23224                :#include "input.h"
23225                :#include "resource.h"
23226                :#include "colormapst.h"
23227                :#include "cursorstr.h"
23228                :#include "dixstruct.h"
23229                :#include "gcstruct.h"
23230                :#include "servermd.h"
23231                :#include "picturestr.h"
23232                :
23233                :_X_EXPORT int   PictureScreenPrivateIndex = -1;
23234                :int             PictureWindowPrivateIndex;
23235                :static int      PictureGeneration;
23236                :RESTYPE         PictureType;
23237                :RESTYPE         PictFormatType;
23238                :RESTYPE         GlyphSetType;
23239                :int             PictureCmapPolicy = PictureCmapPolicyDefault;
23240                :
23241                :/* Picture Private machinery */
23242                :
23243                :static int picturePrivateCount;
23244                :
23245                :void
23246                :ResetPicturePrivateIndex (void)
23247                :{
23248                :    picturePrivateCount = 0;
23249                :}
23250                :
23251                :int
23252                :AllocatePicturePrivateIndex (void)
23253                :{
23254                :    return picturePrivateCount++;
23255                :}
23256                :
23257                :Bool
23258                :AllocatePicturePrivate (ScreenPtr pScreen, int index2, unsigned int amount)
23259                :{
23260                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
23261                :    unsigned int        oldamount;
23262                :
23263                :    /* Round up sizes for proper alignment */
23264                :    amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long);
23265                :
23266                :    if (index2 >= ps->PicturePrivateLen)
23267                :    {
23268                :        unsigned int *nsizes;
23269                :
23270                :        nsizes = (unsigned int *)xrealloc(ps->PicturePrivateSizes,
23271                :                                          (index2 + 1) * sizeof(unsigned int));
23272                :        if (!nsizes)
23273                :            return FALSE;
23274                :        while (ps->PicturePrivateLen <= index2)
23275                :        {
23276                :            nsizes[ps->PicturePrivateLen++] = 0;
23277                :            ps->totalPictureSize += sizeof(DevUnion);
23278                :        }
23279                :        ps->PicturePrivateSizes = nsizes;
23280                :    }
23281                :    oldamount = ps->PicturePrivateSizes[index2];
23282                :    if (amount > oldamount)
23283                :    {
23284                :        ps->PicturePrivateSizes[index2] = amount;
23285                :        ps->totalPictureSize += (amount - oldamount);
23286                :    }
23287                :
23288                :    return TRUE;
23289                :}
23290                :
23291                :
23292                :Bool
23293                :PictureDestroyWindow (WindowPtr pWindow)
23294                :{
23295                :    ScreenPtr           pScreen = pWindow->drawable.pScreen;
23296                :    PicturePtr          pPicture;
23297                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
23298                :    Bool                ret;
23299                :
23300                :    while ((pPicture = GetPictureWindow(pWindow)))
23301                :    {
23302                :        SetPictureWindow(pWindow, pPicture->pNext);
23303                :        if (pPicture->id)
23304                :            FreeResource (pPicture->id, PictureType);
23305                :        FreePicture ((pointer) pPicture, pPicture->id);
23306                :    }
23307                :    pScreen->DestroyWindow = ps->DestroyWindow;
23308                :    ret = (*pScreen->DestroyWindow) (pWindow);
23309                :    ps->DestroyWindow = pScreen->DestroyWindow;
23310                :    pScreen->DestroyWindow = PictureDestroyWindow;
23311                :    return ret;
23312                :}
23313                :
23314                :Bool
23315                :PictureCloseScreen (int index, ScreenPtr pScreen)
23316                :{
23317                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
23318                :    Bool                ret;
23319                :    int                 n;
23320                :
23321                :    pScreen->CloseScreen = ps->CloseScreen;
23322                :    ret = (*pScreen->CloseScreen) (index, pScreen);
23323                :    PictureResetFilters (pScreen);
23324                :    for (n = 0; n < ps->nformats; n++)
23325                :        if (ps->formats[n].type == PictTypeIndexed)
23326                :            (*ps->CloseIndexed) (pScreen, &ps->formats[n]);
23327                :    GlyphUninit (pScreen);
23328                :    SetPictureScreen(pScreen, 0);
23329                :    if (ps->PicturePrivateSizes)
23330                :        xfree (ps->PicturePrivateSizes);
23331                :    xfree (ps->formats);
23332                :    xfree (ps);
23333                :    return ret;
23334                :}
23335                :
23336                :void
23337                :PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef)
23338                :{
23339                :    ScreenPtr           pScreen = pColormap->pScreen;
23340                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
23341                :
23342                :    pScreen->StoreColors = ps->StoreColors;
23343                :    (*pScreen->StoreColors) (pColormap, ndef, pdef);
23344                :    ps->StoreColors = pScreen->StoreColors;
23345                :    pScreen->StoreColors = PictureStoreColors;
23346                :
23347                :    if (pColormap->class == PseudoColor || pColormap->class == GrayScale)
23348                :    {
23349                :        PictFormatPtr   format = ps->formats;
23350                :        int             nformats = ps->nformats;
23351                :
23352                :        while (nformats--)
23353                :        {
23354                :            if (format->type == PictTypeIndexed &&
23355                :                format->index.pColormap == pColormap)
23356                :            {
23357                :                (*ps->UpdateIndexed) (pScreen, format, ndef, pdef);
23358                :                break;
23359                :            }
23360                :            format++;
23361                :        }
23362                :    }
23363                :}
23364                :
23365                :static int
23366                :visualDepth (ScreenPtr pScreen, VisualPtr pVisual)
23367                :{
23368                :    int         d, v;
23369                :    DepthPtr    pDepth;
23370                :
23371                :    for (d = 0; d < pScreen->numDepths; d++)
23372                :    {
23373                :        pDepth = &pScreen->allowedDepths[d];
23374                :        for (v = 0; v < pDepth->numVids; v++)
23375                :            if (pDepth->vids[v] == pVisual->vid)
23376                :                return pDepth->depth;
23377                :    }
23378                :    return 0;
23379                :}
23380                :
23381                :typedef struct _formatInit {
23382                :    CARD32  format;
23383                :    CARD8   depth;
23384                :} FormatInitRec, *FormatInitPtr;
23385                :
23386                :static int
23387                :addFormat (FormatInitRec    formats[256],
23388                :           int              nformat,
23389                :           CARD32           format,
23390                :           CARD8            depth)
23391                :{
23392                :    int n;
23393                :
23394                :    for (n = 0; n < nformat; n++)
23395                :        if (formats[n].format == format && formats[n].depth == depth)
23396                :            return nformat;
23397                :    formats[nformat].format = format;
23398                :    formats[nformat].depth = depth;
23399                :    return ++nformat;
23400                :}
23401                :
23402                :#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1))
23403                :
23404                :PictFormatPtr
23405                :PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp)
23406                :{
23407                :    int             nformats, f;
23408                :    PictFormatPtr   pFormats;
23409                :    FormatInitRec   formats[1024];
23410                :    CARD32          format;
23411                :    CARD8           depth;
23412                :    VisualPtr       pVisual;
23413                :    int             v;
23414                :    int             bpp;
23415                :    int             type;
23416                :    int             r, g, b;
23417                :    int             d;
23418                :    DepthPtr        pDepth;
23419                :
23420                :    nformats = 0;
23421                :    /* formats required by protocol */
23422                :    formats[nformats].format = PICT_a1;
23423                :    formats[nformats].depth = 1;
23424                :    nformats++;
23425                :    formats[nformats].format = PICT_FORMAT(BitsPerPixel(8),
23426                :                                           PICT_TYPE_A,
23427                :                                           8, 0, 0, 0);
23428                :    formats[nformats].depth = 8;
23429                :    nformats++;
23430                :    formats[nformats].format = PICT_FORMAT(BitsPerPixel(4),
23431                :                                           PICT_TYPE_A,
23432                :                                           4, 0, 0, 0);
23433                :    formats[nformats].depth = 4;
23434                :    nformats++;
23435                :    formats[nformats].format = PICT_a8r8g8b8;
23436                :    formats[nformats].depth = 32;
23437                :    nformats++;
23438                :    formats[nformats].format = PICT_x8r8g8b8;
23439                :    formats[nformats].depth = 32;
23440                :    nformats++;
23441                :
23442                :    /* now look through the depths and visuals adding other formats */
23443                :    for (v = 0; v < pScreen->numVisuals; v++)
23444                :    {
23445                :        pVisual = &pScreen->visuals[v];
23446                :        depth = visualDepth (pScreen, pVisual);
23447                :        if (!depth)
23448                :            continue;
23449                :        bpp = BitsPerPixel (depth);
23450                :        switch (pVisual->class) {
23451                :        case DirectColor:
23452                :        case TrueColor:
23453                :            r = Ones (pVisual->redMask);
23454                :            g = Ones (pVisual->greenMask);
23455                :            b = Ones (pVisual->blueMask);
23456                :            type = PICT_TYPE_OTHER;
23457                :            /*
23458                :             * Current rendering code supports only two direct formats,
23459                :             * fields must be packed together at the bottom of the pixel
23460                :             * and must be either RGB or BGR
23461                :             */
23462                :            if (pVisual->offsetBlue == 0 &&
23463                :                pVisual->offsetGreen == b &&
23464                :                pVisual->offsetRed == b + g)
23465                :            {
23466                :                type = PICT_TYPE_ARGB;
23467                :            }
23468                :            else if (pVisual->offsetRed == 0 &&
23469                :                     pVisual->offsetGreen == r && 
23470                :                     pVisual->offsetBlue == r + g)
23471                :            {
23472                :                type = PICT_TYPE_ABGR;
23473                :            }
23474                :            if (type != PICT_TYPE_OTHER)
23475                :            {
23476                :                format = PICT_FORMAT(bpp, type, 0, r, g, b);
23477                :                nformats = addFormat (formats, nformats, format, depth);
23478                :            }
23479                :            break;
23480                :        case StaticColor:
23481                :        case PseudoColor:
23482                :            format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v);
23483                :            nformats = addFormat (formats, nformats, format, depth);
23484                :            break;
23485                :        case StaticGray:
23486                :        case GrayScale:
23487                :            format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v);
23488                :            nformats = addFormat (formats, nformats, format, depth);
23489                :            break;
23490                :        }
23491                :    }
23492                :    /*
23493                :     * Walk supported depths and add useful Direct formats
23494                :     */
23495                :    for (d = 0; d < pScreen->numDepths; d++)
23496                :    {
23497                :        pDepth = &pScreen->allowedDepths[d];
23498                :        bpp = BitsPerPixel (pDepth->depth);
23499                :        format = 0;
23500                :        switch (bpp) {
23501                :        case 16:
23502                :            /* depth 12 formats */
23503                :            if (pDepth->depth >= 12)
23504                :            {
23505                :                nformats = addFormat (formats, nformats,
23506                :                                      PICT_x4r4g4b4, pDepth->depth);
23507                :                nformats = addFormat (formats, nformats,
23508                :                                      PICT_x4b4g4r4, pDepth->depth);
23509                :            }
23510                :            /* depth 15 formats */
23511                :            if (pDepth->depth >= 15)
23512                :            {
23513                :                nformats = addFormat (formats, nformats,
23514                :                                      PICT_x1r5g5b5, pDepth->depth);
23515                :                nformats = addFormat (formats, nformats,
23516                :                                      PICT_x1b5g5r5, pDepth->depth);
23517                :            }
23518                :            /* depth 16 formats */
23519                :            if (pDepth->depth >= 16) 
23520                :            {
23521                :                nformats = addFormat (formats, nformats,
23522                :                                      PICT_a1r5g5b5, pDepth->depth);
23523                :                nformats = addFormat (formats, nformats,
23524                :                                      PICT_a1b5g5r5, pDepth->depth);
23525                :                nformats = addFormat (formats, nformats,
23526                :                                      PICT_r5g6b5, pDepth->depth);
23527                :                nformats = addFormat (formats, nformats,
23528                :                                      PICT_b5g6r5, pDepth->depth);
23529                :                nformats = addFormat (formats, nformats,
23530                :                                      PICT_a4r4g4b4, pDepth->depth);
23531                :                nformats = addFormat (formats, nformats,
23532                :                                      PICT_a4b4g4r4, pDepth->depth);
23533                :            }
23534                :            break;
23535                :        case 24:
23536                :            if (pDepth->depth >= 24)
23537                :            {
23538                :                nformats = addFormat (formats, nformats,
23539                :                                      PICT_r8g8b8, pDepth->depth);
23540                :                nformats = addFormat (formats, nformats,
23541                :                                      PICT_b8g8r8, pDepth->depth);
23542                :            }
23543                :            break;
23544                :        case 32:
23545                :            if (pDepth->depth >= 24)
23546                :            {
23547                :                nformats = addFormat (formats, nformats,
23548                :                                      PICT_x8r8g8b8, pDepth->depth);
23549                :                nformats = addFormat (formats, nformats,
23550                :                                      PICT_x8b8g8r8, pDepth->depth);
23551                :            }
23552                :            break;
23553                :        }
23554                :    }
23555                :    
23556                :
23557                :    pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec));
23558                :    if (!pFormats)
23559                :        return 0;
23560                :    memset (pFormats, '\0', nformats * sizeof (PictFormatRec));
23561                :    for (f = 0; f < nformats; f++)
23562                :    {
23563                :        pFormats[f].id = FakeClientID (0);
23564                :        pFormats[f].depth = formats[f].depth;
23565                :        format = formats[f].format;
23566                :        pFormats[f].format = format;
23567                :        switch (PICT_FORMAT_TYPE(format)) {
23568                :        case PICT_TYPE_ARGB:
23569                :            pFormats[f].type = PictTypeDirect;
23570                :            
23571                :            pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
23572                :            if (pFormats[f].direct.alphaMask)
23573                :                pFormats[f].direct.alpha = (PICT_FORMAT_R(format) +
23574                :                                            PICT_FORMAT_G(format) +
23575                :                                            PICT_FORMAT_B(format));
23576                :            
23577                :            pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
23578                :            pFormats[f].direct.red = (PICT_FORMAT_G(format) + 
23579                :                                      PICT_FORMAT_B(format));
23580                :            
23581                :            pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
23582                :            pFormats[f].direct.green = PICT_FORMAT_B(format);
23583                :            
23584                :            pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
23585                :            pFormats[f].direct.blue = 0;
23586                :            break;
23587                :
23588                :        case PICT_TYPE_ABGR:
23589                :            pFormats[f].type = PictTypeDirect;
23590                :            
23591                :            pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
23592                :            if (pFormats[f].direct.alphaMask)
23593                :                pFormats[f].direct.alpha = (PICT_FORMAT_B(format) +
23594                :                                            PICT_FORMAT_G(format) +
23595                :                                            PICT_FORMAT_R(format));
23596                :            
23597                :            pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
23598                :            pFormats[f].direct.blue = (PICT_FORMAT_G(format) + 
23599                :                                       PICT_FORMAT_R(format));
23600                :            
23601                :            pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
23602                :            pFormats[f].direct.green = PICT_FORMAT_R(format);
23603                :            
23604                :            pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
23605                :            pFormats[f].direct.red = 0;
23606                :            break;
23607                :
23608                :        case PICT_TYPE_A:
23609                :            pFormats[f].type = PictTypeDirect;
23610                :
23611                :            pFormats[f].direct.alpha = 0;
23612                :            pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
23613                :
23614                :            /* remaining fields already set to zero */
23615                :            break;
23616                :            
23617                :        case PICT_TYPE_COLOR:
23618                :        case PICT_TYPE_GRAY:
23619                :            pFormats[f].type = PictTypeIndexed;
23620                :            pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
23621                :            break;
23622                :        }
23623                :    }
23624                :    *nformatp = nformats;
23625                :    return pFormats;
23626                :}
23627                :
23628                :static VisualPtr
23629                :PictureFindVisual (ScreenPtr pScreen, VisualID visual)
23630                :{
23631                :    int         i;
23632                :    VisualPtr   pVisual;
23633                :    for (i = 0, pVisual = pScreen->visuals;
23634                :         i < pScreen->numVisuals;
23635                :         i++, pVisual++)
23636                :    {
23637                :        if (pVisual->vid == visual)
23638                :            return pVisual;
23639                :    }
23640                :    return 0;
23641                :}
23642                :
23643                :Bool
23644                :PictureInitIndexedFormats (ScreenPtr pScreen)
23645                :{
23646                :    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
23647                :    PictFormatPtr       format;
23648                :    int                 nformat;
23649                :
23650                :    if (!ps)
23651                :        return FALSE;
23652                :    format = ps->formats;
23653                :    nformat = ps->nformats;
23654                :    while (nformat--)
23655                :    {
23656                :        if (format->type == PictTypeIndexed && !format->index.pColormap)
23657                :        {
23658                :            if (format->index.vid == pScreen->rootVisual)
23659                :                format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap,
23660                :                                                                       RT_COLORMAP);
23661                :            else
23662                :            {
23663                :                VisualPtr   pVisual;
23664                :
23665                :                pVisual = PictureFindVisual (pScreen, format->index.vid);
23666                :                if (CreateColormap (FakeClientID (0), pScreen,
23667                :                                    pVisual,
23668                :                                    &format->index.pColormap, AllocNone,
23669                :                                    0) != Success)
23670                :                {
23671                :                    return FALSE;
23672                :                }
23673                :            }
23674                :            if (!(*ps->InitIndexed) (pScreen, format))
23675                :                return FALSE;
23676                :        }
23677                :        format++;
23678                :    }
23679                :    return TRUE;
23680                :}
23681                :
23682                :Bool
23683                :PictureFinishInit (void)
23684                :{
23685                :    int     s;
23686                :
23687                :    for (s = 0; s < screenInfo.numScreens; s++)
23688                :    {
23689                :        if (!GlyphFinishInit (screenInfo.screens[s]))
23690                :            return FALSE;
23691                :        if (!PictureInitIndexedFormats (screenInfo.screens[s]))
23692                :            return FALSE;
23693                :        (void) AnimCurInit (screenInfo.screens[s]);
23694                :    }
23695                :
23696                :    return TRUE;
23697                :}
23698                :
23699                :_X_EXPORT Bool
23700                :PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel)
23701                :{
23702                :    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
23703                :
23704                :    if (!ps)
23705                :        return FALSE;
23706                :    ps->subpixel = subpixel;
23707                :    return TRUE;
23708                :    
23709                :}
23710                :
23711                :_X_EXPORT int
23712                :PictureGetSubpixelOrder (ScreenPtr pScreen)
23713                :{
23714                :    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
23715                :
23716                :    if (!ps)
23717                :        return SubPixelUnknown;
23718                :    return ps->subpixel;
23719                :}
23720                :    
23721                :PictFormatPtr
23722                :PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual)
23723                :{
23724                :    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
23725                :    PictFormatPtr       format;
23726                :    int                 nformat;
23727                :    int                 type;
23728                :
23729                :    if (!ps)
23730                :        return 0;
23731                :    format = ps->formats;
23732                :    nformat = ps->nformats;
23733                :    switch (pVisual->class) {
23734                :    case StaticGray:
23735                :    case GrayScale:
23736                :    case StaticColor:
23737                :    case PseudoColor:
23738                :        type = PictTypeIndexed;
23739                :        break;
23740                :    case TrueColor:
23741                :    case DirectColor:
23742                :        type = PictTypeDirect;
23743                :        break;
23744                :    default:
23745                :        return 0;
23746                :    }
23747                :    while (nformat--)
23748                :    {
23749                :        if (format->depth == depth && format->type == type)
23750                :        {
23751                :            if (type == PictTypeIndexed)
23752                :            {
23753                :                if (format->index.vid == pVisual->vid)
23754                :                    return format;
23755                :            }
23756                :            else
23757                :            {
23758                :                if (format->direct.redMask << format->direct.red == 
23759                :                    pVisual->redMask &&
23760                :                    format->direct.greenMask << format->direct.green == 
23761                :                    pVisual->greenMask &&
23762                :                    format->direct.blueMask << format->direct.blue == 
23763                :                    pVisual->blueMask)
23764                :                {
23765                :                    return format;
23766                :                }
23767                :            }
23768                :        }
23769                :        format++;
23770                :    }
23771                :    return 0;
23772                :}
23773                :
23774                :PictFormatPtr
23775                :PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f)
23776                :{
23777                :    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
23778                :    PictFormatPtr       format;
23779                :    int                 nformat;
23780                :
23781                :    if (!ps)
23782                :        return 0;
23783                :    format = ps->formats;
23784                :    nformat = ps->nformats;
23785                :    while (nformat--)
23786                :    {
23787                :        if (format->depth == depth && format->format == (f & 0xffffff))
23788                :            return format;
23789                :        format++;
23790                :    }
23791                :    return 0;
23792                :}
23793                :
23794                :int
23795                :PictureParseCmapPolicy (const char *name)
23796                :{
23797                :    if ( strcmp (name, "default" ) == 0)
23798                :        return PictureCmapPolicyDefault;
23799                :    else if ( strcmp (name, "mono" ) == 0)
23800                :        return PictureCmapPolicyMono;
23801                :    else if ( strcmp (name, "gray" ) == 0)
23802                :        return PictureCmapPolicyGray;
23803                :    else if ( strcmp (name, "color" ) == 0)
23804                :        return PictureCmapPolicyColor;
23805                :    else if ( strcmp (name, "all" ) == 0)
23806                :        return PictureCmapPolicyAll;
23807                :    else
23808                :        return PictureCmapPolicyInvalid;
23809                :}
23810                :
23811                :_X_EXPORT Bool
23812                :PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
23813                :{
23814                :    PictureScreenPtr    ps;
23815                :    int                 n;
23816                :    CARD32              type, a, r, g, b;
23817                :    
23818                :    if (PictureGeneration != serverGeneration)
23819                :    {
23820                :        PictureType = CreateNewResourceType (FreePicture);
23821                :        if (!PictureType)
23822                :            return FALSE;
23823                :        PictFormatType = CreateNewResourceType (FreePictFormat);
23824                :        if (!PictFormatType)
23825                :            return FALSE;
23826                :        GlyphSetType = CreateNewResourceType (FreeGlyphSet);
23827                :        if (!GlyphSetType)
23828                :            return FALSE;
23829                :        PictureScreenPrivateIndex = AllocateScreenPrivateIndex();
23830                :        if (PictureScreenPrivateIndex < 0)
23831                :            return FALSE;
23832                :        PictureWindowPrivateIndex = AllocateWindowPrivateIndex();
23833                :        PictureGeneration = serverGeneration;
23834                :#ifdef XResExtension
23835                :        RegisterResourceName (PictureType, "PICTURE");
23836                :        RegisterResourceName (PictFormatType, "PICTFORMAT");
23837                :        RegisterResourceName (GlyphSetType, "GLYPHSET");
23838                :#endif
23839                :    }
23840                :    if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0))
23841                :        return FALSE;
23842                :    
23843                :    if (!formats)
23844                :    {
23845                :        formats = PictureCreateDefaultFormats (pScreen, &nformats);
23846                :        if (!formats)
23847                :            return FALSE;
23848                :    }
23849                :    for (n = 0; n < nformats; n++)
23850                :    {
23851                :        if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n)))
23852                :        {
23853                :            xfree (formats);
23854                :            return FALSE;
23855                :        }
23856                :        if (formats[n].type == PictTypeIndexed)
23857                :        {
23858                :            VisualPtr   pVisual = PictureFindVisual (pScreen, formats[n].index.vid);
23859                :            if ((pVisual->class | DynamicClass) == PseudoColor)
23860                :                type = PICT_TYPE_COLOR;
23861                :            else
23862                :                type = PICT_TYPE_GRAY;
23863                :            a = r = g = b = 0;
23864                :        }
23865                :        else
23866                :        {
23867                :            if ((formats[n].direct.redMask|
23868                :                 formats[n].direct.blueMask|
23869                :                 formats[n].direct.greenMask) == 0)
23870                :                type = PICT_TYPE_A;
23871                :            else if (formats[n].direct.red > formats[n].direct.blue)
23872                :                type = PICT_TYPE_ARGB;
23873                :            else
23874                :                type = PICT_TYPE_ABGR;
23875                :            a = Ones (formats[n].direct.alphaMask);
23876                :            r = Ones (formats[n].direct.redMask);
23877                :            g = Ones (formats[n].direct.greenMask);
23878                :            b = Ones (formats[n].direct.blueMask);
23879                :        }
23880                :        formats[n].format = PICT_FORMAT(0,type,a,r,g,b);
23881                :    }
23882                :    ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec));
23883                :    if (!ps)
23884                :    {
23885                :        xfree (formats);
23886                :        return FALSE;
23887                :    }
23888                :    SetPictureScreen(pScreen, ps);
23889                :    if (!GlyphInit (pScreen))
23890                :    {
23891                :        SetPictureScreen(pScreen, 0);
23892                :        xfree (formats);
23893                :        xfree (ps);
23894                :        return FALSE;
23895                :    }
23896                :
23897                :    ps->totalPictureSize = sizeof (PictureRec);
23898                :    ps->PicturePrivateSizes = 0;
23899                :    ps->PicturePrivateLen = 0;
23900                :    
23901                :    ps->formats = formats;
23902                :    ps->fallback = formats;
23903                :    ps->nformats = nformats;
23904                :    
23905                :    ps->filters = 0;
23906                :    ps->nfilters = 0;
23907                :    ps->filterAliases = 0;
23908                :    ps->nfilterAliases = 0;
23909                :
23910                :    ps->subpixel = SubPixelUnknown;
23911                :
23912                :    ps->CloseScreen = pScreen->CloseScreen;
23913                :    ps->DestroyWindow = pScreen->DestroyWindow;
23914                :    ps->StoreColors = pScreen->StoreColors;
23915                :    pScreen->DestroyWindow = PictureDestroyWindow;
23916                :    pScreen->CloseScreen = PictureCloseScreen;
23917                :    pScreen->StoreColors = PictureStoreColors;
23918                :
23919                :    if (!PictureSetDefaultFilters (pScreen))
23920                :    {
23921                :        PictureResetFilters (pScreen);
23922                :        SetPictureScreen(pScreen, 0);
23923                :        xfree (formats);
23924                :        xfree (ps);
23925                :        return FALSE;
23926                :    }
23927                :
23928                :    return TRUE;
23929                :}
23930                :
23931                :void
23932                :SetPictureToDefaults (PicturePtr    pPicture)
23933                :{ /* SetPictureToDefaults total:      8  0.0087 */
23934                :    pPicture->refcnt = 1;
23935                :    pPicture->repeat = 0;
23936                :    pPicture->graphicsExposures = FALSE;
23937                :    pPicture->subWindowMode = ClipByChildren;
23938                :    pPicture->polyEdge = PolyEdgeSharp;
23939                :    pPicture->polyMode = PolyModePrecise;
23940                :    pPicture->freeCompClip = FALSE;
23941                :    pPicture->clientClipType = CT_NONE;
23942                :    pPicture->componentAlpha = FALSE;
23943                :    pPicture->repeatType = RepeatNone;
23944                :
23945                :    pPicture->alphaMap = 0;
23946                :    pPicture->alphaOrigin.x = 0;
23947                :    pPicture->alphaOrigin.y = 0;
23948                :
23949                :    pPicture->clipOrigin.x = 0;
23950      1  0.0011 :    pPicture->clipOrigin.y = 0;
23951                :    pPicture->clientClip = 0;
23952                :
23953                :    pPicture->transform = 0;
23954                :
23955                :    pPicture->dither = None;
23956      4  0.0044 :    pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE);
23957                :    pPicture->filter_params = 0;
23958                :    pPicture->filter_nparams = 0;
23959                :
23960                :    pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
23961      1  0.0011 :    pPicture->stateChanges = (1 << (CPLastBit+1)) - 1;
23962      1  0.0011 :    pPicture->pSourcePict = 0;
23963      1  0.0011 :}
23964                :
23965                :PicturePtr
23966                :AllocatePicture (ScreenPtr  pScreen)
23967                :{ /* AllocatePicture total:      4  0.0044 */
23968                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
23969                :    PicturePtr          pPicture;
23970                :    char                *ptr;
23971                :    DevUnion            *ppriv;
23972                :    unsigned int        *sizes;
23973                :    unsigned int        size;
23974                :    int                 i;
23975                :
23976      3  0.0033 :    pPicture = (PicturePtr) xalloc (ps->totalPictureSize);
23977                :    if (!pPicture)
23978                :        return 0;
23979                :    ppriv = (DevUnion *)(pPicture + 1);
23980                :    pPicture->devPrivates = ppriv;
23981                :    sizes = ps->PicturePrivateSizes;
23982                :    ptr = (char *)(ppriv + ps->PicturePrivateLen);
23983                :    for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++)
23984                :    {
23985                :        if ( (size = *sizes) )
23986                :        {
23987                :            ppriv->ptr = (pointer)ptr;
23988                :            ptr += size;
23989                :        }
23990                :        else
23991                :            ppriv->ptr = (pointer)NULL;
23992                :    }
23993                :    return pPicture;
23994      1  0.0011 :}
23995                :
23996                :PicturePtr
23997                :CreatePicture (Picture          pid,
23998                :               DrawablePtr      pDrawable,
23999                :               PictFormatPtr    pFormat,
24000                :               Mask             vmask,
24001                :               XID              *vlist,
24002                :               ClientPtr        client,
24003                :               int              *error)
24004      2  0.0022 :{ /* CreatePicture total:     12  0.0131 */
24005                :    PicturePtr          pPicture;
24006      2  0.0022 :    PictureScreenPtr    ps = GetPictureScreen(pDrawable->pScreen);
24007                :
24008                :    pPicture = AllocatePicture (pDrawable->pScreen);
24009                :    if (!pPicture)
24010                :    {
24011                :        *error = BadAlloc;
24012                :        return 0;
24013                :    }
24014                :
24015                :    pPicture->id = pid;
24016                :    pPicture->pDrawable = pDrawable;
24017                :    pPicture->pFormat = pFormat;
24018      1  0.0011 :    pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
24019      1  0.0011 :    if (pDrawable->type == DRAWABLE_PIXMAP)
24020                :    {
24021                :        ++((PixmapPtr)pDrawable)->refcnt;
24022                :        pPicture->pNext = 0;
24023                :    }
24024                :    else
24025                :    {
24026                :        pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable));
24027                :        SetPictureWindow(((WindowPtr) pDrawable), pPicture);
24028                :    }
24029                :
24030                :    SetPictureToDefaults (pPicture);
24031                :    
24032                :    if (vmask)
24033                :        *error = ChangePicture (pPicture, vmask, vlist, 0, client);
24034                :    else
24035                :        *error = Success;
24036                :    if (*error == Success)
24037      4  0.0044 :        *error = (*ps->CreatePicture) (pPicture);
24038      1  0.0011 :    if (*error != Success)
24039                :    {
24040                :        FreePicture (pPicture, (XID) 0);
24041                :        pPicture = 0;
24042                :    }
24043                :    return pPicture;
24044      1  0.0011 :}
24045                :
24046                :static CARD32 xRenderColorToCard32(xRenderColor c)
24047                :{
24048                :    return
24049                :        (c.alpha >> 8 << 24) |
24050                :        (c.red >> 8 << 16) |
24051                :        (c.green & 0xff00) |
24052                :        (c.blue >> 8);
24053                :}
24054                :
24055                :static unsigned int premultiply(unsigned int x)
24056                :{
24057                :    unsigned int a = x >> 24;
24058                :    unsigned int t = (x & 0xff00ff) * a + 0x800080;
24059                :    t = (t + ((t >> 8) & 0xff00ff)) >> 8;
24060                :    t &= 0xff00ff;
24061                :
24062                :    x = ((x >> 8) & 0xff) * a + 0x80;
24063                :    x = (x + ((x >> 8) & 0xff));
24064                :    x &= 0xff00;
24065                :    x |= t | (a << 24);
24066                :    return x;
24067                :}
24068                :
24069                :static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a,
24070                :                                          unsigned int y, unsigned int b)
24071                :{
24072                :    CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
24073                :    t >>= 8;
24074                :    t &= 0xff00ff;
24075                :
24076                :    x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
24077                :    x &= 0xff00ff00;
24078                :    x |= t;
24079                :    return x;
24080                :}
24081                :
24082                :CARD32
24083                :PictureGradientColor (PictGradientStopPtr stop1,
24084                :                      PictGradientStopPtr stop2,
24085                :                      CARD32              x)
24086                :{
24087                :     CARD32 current_color, next_color;
24088                :     int           dist, idist;
24089                :
24090                :     current_color = xRenderColorToCard32 (stop1->color);
24091                :     next_color    = xRenderColorToCard32 (stop2->color);
24092                :
24093                :     dist  = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
24094                :     idist = 256 - dist;
24095                :
24096                :     return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
24097                :                                               next_color, dist));
24098                :}
24099                :
24100                :static void initGradient(SourcePictPtr pGradient, int stopCount,
24101                :                         xFixed *stopPoints, xRenderColor *stopColors, int *error)
24102                :{
24103                :    int i;
24104                :    xFixed dpos;
24105                :
24106                :    if (stopCount <= 0) {
24107                :        *error = BadValue;
24108                :        return;
24109                :    }
24110                :
24111                :    dpos = -1;
24112                :    for (i = 0; i < stopCount; ++i) {
24113                :        if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) {
24114                :            *error = BadValue;
24115                :            return;
24116                :        }
24117                :        dpos = stopPoints[i];
24118                :    }
24119                :
24120                :    pGradient->gradient.stops = xalloc(stopCount*sizeof(PictGradientStop));
24121                :    if (!pGradient->gradient.stops) {
24122                :        *error = BadAlloc;
24123                :        return;
24124                :    }
24125                :
24126                :    pGradient->gradient.nstops = stopCount;
24127                :
24128                :    for (i = 0; i < stopCount; ++i) {
24129                :        pGradient->gradient.stops[i].x = stopPoints[i];
24130                :        pGradient->gradient.stops[i].color = stopColors[i];
24131                :    }
24132                :
24133                :    pGradient->gradient.class          = SourcePictClassUnknown;
24134                :    pGradient->gradient.stopRange      = 0xffff;
24135                :    pGradient->gradient.colorTable     = NULL;
24136                :    pGradient->gradient.colorTableSize = 0;
24137                :}
24138                :
24139                :static PicturePtr createSourcePicture(void)
24140                :{
24141                :    PicturePtr pPicture;
24142                :    pPicture = (PicturePtr) xalloc(sizeof(PictureRec));
24143                :    pPicture->pDrawable = 0;
24144                :    pPicture->pFormat = 0;
24145                :    pPicture->pNext = 0;
24146                :    pPicture->format = PICT_a8r8g8b8;
24147                :    pPicture->devPrivates = 0;
24148                :
24149                :    SetPictureToDefaults(pPicture);
24150                :    return pPicture;
24151                :}
24152                :
24153                :PicturePtr
24154                :CreateSolidPicture (Picture pid, xRenderColor *color, int *error)
24155                :{
24156                :    PicturePtr pPicture;
24157                :    pPicture = createSourcePicture();
24158                :    if (!pPicture) {
24159                :        *error = BadAlloc;
24160                :        return 0;
24161                :    }
24162                :
24163                :    pPicture->id = pid;
24164                :    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill));
24165                :    if (!pPicture->pSourcePict) {
24166                :        *error = BadAlloc;
24167                :        xfree(pPicture);
24168                :        return 0;
24169                :    }
24170                :    pPicture->pSourcePict->type = SourcePictTypeSolidFill;
24171                :    pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color);
24172                :    return pPicture;
24173                :}
24174                :
24175                :PicturePtr
24176                :CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2,
24177                :                             int nStops, xFixed *stops, xRenderColor *colors, int *error)
24178                :{
24179                :    PicturePtr pPicture;
24180                :
24181                :    if (nStops < 2) {
24182                :        *error = BadValue;
24183                :        return 0;
24184                :    }
24185                :
24186                :    pPicture = createSourcePicture();
24187                :    if (!pPicture) {
24188                :        *error = BadAlloc;
24189                :        return 0;
24190                :    }
24191                :
24192                :    pPicture->id = pid;
24193                :    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient));
24194                :    if (!pPicture->pSourcePict) {
24195                :        *error = BadAlloc;
24196                :        xfree(pPicture);
24197                :        return 0;
24198                :    }
24199                :
24200                :    pPicture->pSourcePict->linear.type = SourcePictTypeLinear;
24201                :    pPicture->pSourcePict->linear.p1 = *p1;
24202                :    pPicture->pSourcePict->linear.p2 = *p2;
24203                :
24204                :    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
24205                :    if (*error) {
24206                :        xfree(pPicture);
24207                :        return 0;
24208                :    }
24209                :    return pPicture;
24210                :}
24211                :
24212                :#define FixedToDouble(x) ((x)/65536.)
24213                :
24214                :PicturePtr
24215                :CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer,
24216                :                             xFixed innerRadius, xFixed outerRadius,
24217                :                             int nStops, xFixed *stops, xRenderColor *colors, int *error)
24218                :{
24219                :    PicturePtr pPicture;
24220                :    PictRadialGradient *radial;
24221                :
24222                :    if (nStops < 2) {
24223                :        *error = BadValue;
24224                :        return 0;
24225                :    }
24226                :
24227                :    pPicture = createSourcePicture();
24228                :    if (!pPicture) {
24229                :        *error = BadAlloc;
24230                :        return 0;
24231                :    }
24232                :
24233                :    pPicture->id = pid;
24234                :    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient));
24235                :    if (!pPicture->pSourcePict) {
24236                :        *error = BadAlloc;
24237                :        xfree(pPicture);
24238                :        return 0;
24239                :    }
24240                :    radial = &pPicture->pSourcePict->radial;
24241                :
24242                :    radial->type = SourcePictTypeRadial;
24243                :    radial->c1.x = inner->x;
24244                :    radial->c1.y = inner->y;
24245                :    radial->c1.radius = innerRadius;
24246                :    radial->c2.x = outer->x;
24247                :    radial->c2.y = outer->y;
24248                :    radial->c2.radius = outerRadius;
24249                :    radial->cdx = (radial->c2.x - radial->c1.x) / 65536.;
24250                :    radial->cdy = (radial->c2.y - radial->c1.y) / 65536.;
24251                :    radial->dr = (radial->c2.radius - radial->c1.radius) / 65536.;
24252                :    radial->A = (  radial->cdx * radial->cdx
24253                :                   + radial->cdy * radial->cdy
24254                :                   - radial->dr  * radial->dr);
24255                :    
24256                :    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
24257                :    if (*error) {
24258                :        xfree(pPicture);
24259                :        return 0;
24260                :    }
24261                :    return pPicture;
24262                :}
24263                :
24264                :PicturePtr
24265                :CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle,
24266                :                              int nStops, xFixed *stops, xRenderColor *colors, int *error)
24267                :{
24268                :    PicturePtr pPicture;
24269                :
24270                :    if (nStops < 2) {
24271                :        *error = BadValue;
24272                :        return 0;
24273                :    }
24274                :
24275                :    pPicture = createSourcePicture();
24276                :    if (!pPicture) {
24277                :        *error = BadAlloc;
24278                :        return 0;
24279                :    }
24280                :
24281                :    pPicture->id = pid;
24282                :    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient));
24283                :    if (!pPicture->pSourcePict) {
24284                :        *error = BadAlloc;
24285                :        xfree(pPicture);
24286                :        return 0;
24287                :    }
24288                :
24289                :    pPicture->pSourcePict->conical.type = SourcePictTypeConical;
24290                :    pPicture->pSourcePict->conical.center = *center;
24291                :    pPicture->pSourcePict->conical.angle = angle;
24292                :
24293                :    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
24294                :    if (*error) {
24295                :        xfree(pPicture);
24296                :        return 0;
24297                :    }
24298                :    return pPicture;
24299                :}
24300                :
24301                :#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
24302                :
24303                :#define NEXT_PTR(_type) ((_type) ulist++->ptr)
24304                :
24305                :int
24306                :ChangePicture (PicturePtr       pPicture,
24307                :               Mask             vmask,
24308                :               XID              *vlist,
24309                :               DevUnion         *ulist,
24310                :               ClientPtr        client)
24311      4  0.0044 :{ /* ChangePicture total:     16  0.0174 */
24312                :    ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
24313      4  0.0044 :    PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
24314                :    BITS32              index2;
24315                :    int                 error = 0;
24316                :    BITS32              maskQ;
24317                :    
24318                :    pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
24319                :    maskQ = vmask;
24320      1  0.0011 :    while (vmask && !error)
24321                :    {
24322                :        index2 = (BITS32) lowbit (vmask);
24323      1  0.0011 :        vmask &= ~index2;
24324                :        pPicture->stateChanges |= index2;
24325      1  0.0011 :        switch (index2)
24326                :        {
24327                :        case CPRepeat:
24328                :            {
24329                :                unsigned int    newr;
24330      1  0.0011 :                newr = NEXT_VAL(unsigned int);
24331                :                if (newr <= RepeatReflect)
24332                :                {
24333      1  0.0011 :                    pPicture->repeat = (newr != RepeatNone);
24334      1  0.0011 :                    pPicture->repeatType = newr;
24335                :                }
24336                :                else
24337                :                {
24338                :                    client->errorValue = newr;
24339                :                    error = BadValue;
24340                :                }
24341                :            }
24342                :            break;
24343                :        case CPAlphaMap:
24344                :            {
24345                :                PicturePtr  pAlpha;
24346                :                
24347                :                if (vlist)
24348                :                {
24349                :                    Picture     pid = NEXT_VAL(Picture);
24350                :
24351                :                    if (pid == None)
24352                :                        pAlpha = 0;
24353                :                    else
24354                :                    {
24355                :                        pAlpha = (PicturePtr) SecurityLookupIDByType(client,
24356                :                                                                     pid, 
24357                :                                                                     PictureType, 
24358                :                                                                     DixWriteAccess|DixReadAccess);
24359                :                        if (!pAlpha)
24360                :                        {
24361                :                            client->errorValue = pid;
24362                :                            error = BadPixmap;
24363                :                            break;
24364                :                        }
24365                :                        if (pAlpha->pDrawable == NULL ||
24366                :                            pAlpha->pDrawable->type != DRAWABLE_PIXMAP)
24367                :                        {
24368                :                            client->errorValue = pid;
24369                :                            error = BadMatch;
24370                :                            break;
24371                :                        }
24372                :                    }
24373                :                }
24374                :                else
24375                :                    pAlpha = NEXT_PTR(PicturePtr);
24376                :                if (!error)
24377                :                {
24378                :                    if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP)
24379                :                        pAlpha->refcnt++;
24380                :                    if (pPicture->alphaMap)
24381                :                        FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
24382                :                    pPicture->alphaMap = pAlpha;
24383                :                }
24384                :            }
24385                :            break;
24386                :        case CPAlphaXOrigin:
24387                :            pPicture->alphaOrigin.x = NEXT_VAL(INT16);
24388                :            break;
24389                :        case CPAlphaYOrigin:
24390                :            pPicture->alphaOrigin.y = NEXT_VAL(INT16);
24391                :            break;
24392                :        case CPClipXOrigin:
24393                :            pPicture->clipOrigin.x = NEXT_VAL(INT16);
24394                :            break;
24395                :        case CPClipYOrigin:
24396                :            pPicture->clipOrigin.y = NEXT_VAL(INT16);
24397                :            break;
24398                :        case CPClipMask:
24399                :            {
24400                :                Pixmap      pid;
24401                :                PixmapPtr   pPixmap;
24402                :                int         clipType;
24403                :                if (!pScreen)
24404                :                    return BadDrawable;
24405                :
24406                :                if (vlist)
24407                :                {
24408                :                    pid = NEXT_VAL(Pixmap);
24409                :                    if (pid == None)
24410                :                    {
24411                :                        clipType = CT_NONE;
24412                :                        pPixmap = NullPixmap;
24413                :                    }
24414                :                    else
24415                :                    {
24416                :                        clipType = CT_PIXMAP;
24417                :                        pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
24418                :                                                                    pid, 
24419                :                                                                    RT_PIXMAP,
24420                :                                                                    DixReadAccess);
24421                :                        if (!pPixmap)
24422                :                        {
24423                :                            client->errorValue = pid;
24424                :                            error = BadPixmap;
24425                :                            break;
24426                :                        }
24427                :                    }
24428                :                }
24429                :                else
24430                :                {
24431                :                    pPixmap = NEXT_PTR(PixmapPtr);
24432                :                    if (pPixmap)
24433                :                        clipType = CT_PIXMAP;
24434                :                    else
24435                :                        clipType = CT_NONE;
24436                :                }
24437                :
24438                :                if (pPixmap)
24439                :                {
24440                :                    if ((pPixmap->drawable.depth != 1) ||
24441                :                        (pPixmap->drawable.pScreen != pScreen))
24442                :                    {
24443                :                        error = BadMatch;
24444                :                        break;
24445                :                    }
24446                :                    else
24447                :                    {
24448                :                        clipType = CT_PIXMAP;
24449                :                        pPixmap->refcnt++;
24450                :                    }
24451                :                }
24452                :                error = (*ps->ChangePictureClip)(pPicture, clipType,
24453                :                                                 (pointer)pPixmap, 0);
24454                :                break;
24455                :            }
24456                :        case CPGraphicsExposure:
24457                :            {
24458                :                unsigned int    newe;
24459                :                newe = NEXT_VAL(unsigned int);
24460                :                if (newe <= xTrue)
24461                :                    pPicture->graphicsExposures = newe;
24462                :                else
24463                :                {
24464                :                    client->errorValue = newe;
24465                :                    error = BadValue;
24466                :                }
24467                :            }
24468                :            break;
24469                :        case CPSubwindowMode:
24470                :            {
24471                :                unsigned int    news;
24472                :                news = NEXT_VAL(unsigned int);
24473                :                if (news == ClipByChildren || news == IncludeInferiors)
24474                :                    pPicture->subWindowMode = news;
24475                :                else
24476                :                {
24477                :                    client->errorValue = news;
24478                :                    error = BadValue;
24479                :                }
24480                :            }
24481                :            break;
24482                :        case CPPolyEdge:
24483                :            {
24484                :                unsigned int    newe;
24485                :                newe = NEXT_VAL(unsigned int);
24486                :                if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
24487                :                    pPicture->polyEdge = newe;
24488                :                else
24489                :                {
24490                :                    client->errorValue = newe;
24491                :                    error = BadValue;
24492                :                }
24493                :            }
24494                :            break;
24495                :        case CPPolyMode:
24496                :            {
24497                :                unsigned int    newm;
24498                :                newm = NEXT_VAL(unsigned int);
24499                :                if (newm == PolyModePrecise || newm == PolyModeImprecise)
24500                :                    pPicture->polyMode = newm;
24501                :                else
24502                :                {
24503                :                    client->errorValue = newm;
24504                :                    error = BadValue;
24505                :                }
24506                :            }
24507                :            break;
24508                :        case CPDither:
24509                :            pPicture->dither = NEXT_VAL(Atom);
24510                :            break;
24511                :        case CPComponentAlpha:
24512                :            {
24513                :                unsigned int    newca;
24514                :
24515      1  0.0011 :                newca = NEXT_VAL (unsigned int);
24516                :                if (newca <= xTrue)
24517                :                    pPicture->componentAlpha = newca;
24518                :                else
24519                :                {
24520                :                    client->errorValue = newca;
24521                :                    error = BadValue;
24522                :                }
24523                :            }
24524                :            break;
24525                :        default:
24526                :            client->errorValue = maskQ;
24527                :            error = BadValue;
24528                :            break;
24529                :        }
24530                :    }
24531                :    if (ps)
24532                :        (*ps->ChangePicture) (pPicture, maskQ);
24533                :    return error;
24534      1  0.0011 :}
24535                :
24536                :int
24537                :SetPictureClipRects (PicturePtr pPicture,
24538                :                     int        xOrigin,
24539                :                     int        yOrigin,
24540                :                     int        nRect,
24541                :                     xRectangle *rects)
24542                :{
24543                :    ScreenPtr           pScreen = pPicture->pDrawable->pScreen;
24544                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
24545                :    RegionPtr           clientClip;
24546                :    int                 result;
24547                :
24548                :    clientClip = RECTS_TO_REGION(pScreen,
24549                :                                 nRect, rects, CT_UNSORTED);
24550                :    if (!clientClip)
24551                :        return BadAlloc;
24552                :    result =(*ps->ChangePictureClip) (pPicture, CT_REGION, 
24553                :                                      (pointer) clientClip, 0);
24554                :    if (result == Success)
24555                :    {
24556                :        pPicture->clipOrigin.x = xOrigin;
24557                :        pPicture->clipOrigin.y = yOrigin;
24558                :        pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
24559                :        pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
24560                :    }
24561                :    return result;
24562                :}
24563                :
24564                :int
24565                :SetPictureClipRegion (PicturePtr    pPicture,
24566                :                      int           xOrigin,
24567                :                      int           yOrigin,
24568                :                      RegionPtr     pRegion)
24569                :{
24570                :    ScreenPtr           pScreen = pPicture->pDrawable->pScreen;
24571                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
24572                :    RegionPtr           clientClip;
24573                :    int                 result;
24574                :    int                 type;
24575                :
24576                :    if (pRegion)
24577                :    {
24578                :        type = CT_REGION;
24579                :        clientClip = REGION_CREATE (pScreen,
24580                :                                    REGION_EXTENTS(pScreen, pRegion),
24581                :                                    REGION_NUM_RECTS(pRegion));
24582                :        if (!clientClip)
24583                :            return BadAlloc;
24584                :        if (!REGION_COPY (pSCreen, clientClip, pRegion))
24585                :        {
24586                :            REGION_DESTROY (pScreen, clientClip);
24587                :            return BadAlloc;
24588                :        }
24589                :    }
24590                :    else
24591                :    {
24592                :        type = CT_NONE;
24593                :        clientClip = 0;
24594                :    }
24595                :
24596                :    result =(*ps->ChangePictureClip) (pPicture, type,
24597                :                                      (pointer) clientClip, 0);
24598                :    if (result == Success)
24599                :    {
24600                :        pPicture->clipOrigin.x = xOrigin;
24601                :        pPicture->clipOrigin.y = yOrigin;
24602                :        pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
24603                :        pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
24604                :    }
24605                :    return result;
24606                :}
24607                :
24608                :static Bool
24609                :transformIsIdentity(PictTransform *t)
24610                :{
24611                :    return ((t->matrix[0][0] == t->matrix[1][1]) &&
24612                :            (t->matrix[0][0] == t->matrix[2][2]) &&
24613                :            (t->matrix[0][0] != 0) &&
24614                :            (t->matrix[0][1] == 0) &&
24615                :            (t->matrix[0][2] == 0) &&
24616                :            (t->matrix[1][0] == 0) &&
24617                :            (t->matrix[1][2] == 0) &&
24618                :            (t->matrix[2][0] == 0) &&
24619                :            (t->matrix[2][1] == 0));
24620                :}
24621                :
24622                :int
24623                :SetPictureTransform (PicturePtr     pPicture,
24624                :                     PictTransform  *transform)
24625      2  0.0022 :{ /* SetPictureTransform total:     10  0.0109 */
24626                :    if (transform && transformIsIdentity (transform))
24627                :        transform = 0;
24628                :    
24629                :    if (transform)
24630                :    {
24631                :        if (!pPicture->transform)
24632                :        {
24633                :            pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform));
24634                :            if (!pPicture->transform)
24635                :                return BadAlloc;
24636                :        }
24637                :        *pPicture->transform = *transform;
24638                :    }
24639                :    else
24640                :    {
24641                :        if (pPicture->transform)
24642                :        {
24643                :            xfree (pPicture->transform);
24644                :            pPicture->transform = 0;
24645                :        }
24646                :    }
24647                :    pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
24648                :
24649      5  0.0054 :    if (pPicture->pDrawable != NULL) {
24650                :        int result;
24651                :        PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
24652                :
24653      1  0.0011 :        result = (*ps->ChangePictureTransform) (pPicture, transform);
24654                :
24655                :        return result;
24656                :    }
24657                :
24658                :    return Success;
24659                :}
24660                :
24661                :void
24662                :CopyPicture (PicturePtr pSrc,
24663                :             Mask       mask,
24664                :             PicturePtr pDst)
24665                :{
24666                :    PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen);
24667                :    Mask origMask = mask;
24668                :
24669                :    pDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
24670                :    pDst->stateChanges |= mask;
24671                :
24672                :    while (mask) {
24673                :        Mask bit = lowbit(mask);
24674                :
24675                :        switch (bit)
24676                :        {
24677                :        case CPRepeat:
24678                :            pDst->repeat = pSrc->repeat;
24679                :            pDst->repeatType = pSrc->repeatType;
24680                :            break;
24681                :        case CPAlphaMap:
24682                :            if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP)
24683                :                pSrc->alphaMap->refcnt++;
24684                :            if (pDst->alphaMap)
24685                :                FreePicture ((pointer) pDst->alphaMap, (XID) 0);
24686                :            pDst->alphaMap = pSrc->alphaMap;
24687                :            break;
24688                :        case CPAlphaXOrigin:
24689                :            pDst->alphaOrigin.x = pSrc->alphaOrigin.x;
24690                :            break;
24691                :        case CPAlphaYOrigin:
24692                :            pDst->alphaOrigin.y = pSrc->alphaOrigin.y;
24693                :            break;
24694                :        case CPClipXOrigin:
24695                :            pDst->clipOrigin.x = pSrc->clipOrigin.x;
24696                :            break;
24697                :        case CPClipYOrigin:
24698                :            pDst->clipOrigin.y = pSrc->clipOrigin.y;
24699                :            break;
24700                :        case CPClipMask:
24701                :            switch (pSrc->clientClipType) {
24702                :            case CT_NONE:
24703                :                (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
24704                :                break;
24705                :            case CT_REGION:
24706                :                if (!pSrc->clientClip) {
24707                :                    (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
24708                :                } else {
24709                :                    RegionPtr clientClip;
24710                :                    RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip;
24711                :
24712                :                    clientClip = REGION_CREATE(pSrc->pDrawable->pScreen,
24713                :                        REGION_EXTENTS(pSrc->pDrawable->pScreen, srcClientClip),
24714                :                        REGION_NUM_RECTS(srcClientClip));
24715                :                    (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0);
24716                :                }
24717                :                break;
24718                :            default:
24719                :                /* XXX: CT_PIXMAP unimplemented */
24720                :                break;
24721                :            }
24722                :            break;
24723                :        case CPGraphicsExposure:
24724                :            pDst->graphicsExposures = pSrc->graphicsExposures;
24725                :            break;
24726                :        case CPPolyEdge:
24727                :            pDst->polyEdge = pSrc->polyEdge;
24728                :            break;
24729                :        case CPPolyMode:
24730                :            pDst->polyMode = pSrc->polyMode;
24731                :            break;
24732                :        case CPDither:
24733                :            pDst->dither = pSrc->dither;
24734                :            break;
24735                :        case CPComponentAlpha:
24736                :            pDst->componentAlpha = pSrc->componentAlpha;
24737                :            break;
24738                :        }
24739                :        mask &= ~bit;
24740                :    }
24741                :
24742                :    (*ps->ChangePicture)(pDst, origMask);
24743                :}
24744                :
24745                :static void
24746                :ValidateOnePicture (PicturePtr pPicture)
24747      5  0.0054 :{ /* ValidateOnePicture total:     10  0.0109 */
24748      1  0.0011 :    if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber)
24749                :    {
24750                :        PictureScreenPtr    ps = GetPictureScreen(pPicture->pDrawable->pScreen);
24751                :
24752      4  0.0044 :        (*ps->ValidatePicture) (pPicture, pPicture->stateChanges);
24753                :        pPicture->stateChanges = 0;
24754                :        pPicture->serialNumber = pPicture->pDrawable->serialNumber;
24755                :    }
24756                :}
24757                :
24758                :void
24759                :ValidatePicture(PicturePtr pPicture)
24760      1  0.0011 :{ /* ValidatePicture total:      3  0.0033 */
24761                :    ValidateOnePicture (pPicture);
24762      1  0.0011 :    if (pPicture->alphaMap)
24763                :        ValidateOnePicture (pPicture->alphaMap);
24764      1  0.0011 :}
24765                :
24766                :int
24767                :FreePicture (pointer    value,
24768                :             XID        pid)
24769      3  0.0033 :{ /* FreePicture total:      8  0.0087 */
24770                :    PicturePtr  pPicture = (PicturePtr) value;
24771                :
24772      2  0.0022 :    if (--pPicture->refcnt == 0)
24773                :    {
24774                :        if (pPicture->transform)
24775                :            xfree (pPicture->transform);
24776                :
24777                :        if (pPicture->pSourcePict)
24778                :        {
24779                :            if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
24780                :                xfree(pPicture->pSourcePict->linear.stops);
24781                :
24782                :            xfree(pPicture->pSourcePict);
24783                :        }
24784                :
24785                :        if (pPicture->pDrawable)
24786                :        {
24787                :            ScreenPtr       pScreen = pPicture->pDrawable->pScreen;
24788      2  0.0022 :            PictureScreenPtr    ps = GetPictureScreen(pScreen);
24789                :        
24790                :            if (pPicture->alphaMap)
24791                :                FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
24792                :            (*ps->DestroyPicture) (pPicture);
24793                :            (*ps->DestroyPictureClip) (pPicture);
24794                :            if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
24795                :            {
24796                :                WindowPtr       pWindow = (WindowPtr) pPicture->pDrawable;
24797                :                PicturePtr      *pPrev;
24798                :
24799                :                for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr);
24800                :                     *pPrev;
24801                :                     pPrev = &(*pPrev)->pNext)
24802                :                {
24803                :                    if (*pPrev == pPicture)
24804                :                    {
24805                :                        *pPrev = pPicture->pNext;
24806                :                        break;
24807                :                    }
24808                :                }
24809                :            }
24810      1  0.0011 :            else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
24811                :            {
24812                :                (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
24813                :            }
24814                :        }
24815                :        xfree (pPicture);
24816                :    }
24817                :    return Success;
24818                :}
24819                :
24820                :int
24821                :FreePictFormat (pointer pPictFormat,
24822                :                XID     pid)
24823                :{
24824                :    return Success;
24825                :}
24826                :
24827                :/**
24828                : * ReduceCompositeOp is used to choose simpler ops for cases where alpha
24829                : * channels are always one and so math on the alpha channel per pixel becomes
24830                : * unnecessary.  It may also avoid destination reads sometimes if apps aren't
24831                : * being careful to avoid these cases.
24832                : */
24833                :static Bool
24834                :ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst)
24835                :{
24836                :    Bool no_src_alpha, no_dst_alpha;
24837                :
24838                :    no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) &&
24839                :                   PICT_FORMAT_A(pSrc->format) == 0 &&
24840                :                   pSrc->alphaMap == NULL &&
24841                :                   pMask == NULL;
24842                :    no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) &&
24843                :                   PICT_FORMAT_A(pDst->format) == 0 &&
24844                :                   pDst->alphaMap == NULL;
24845                :
24846                :    /* TODO, maybe: Conjoint and Disjoint op reductions? */
24847                : 
24848                :    /* Deal with simplifications where the source alpha is always 1. */
24849                :    if (no_src_alpha)
24850                :    {
24851                :        switch (op) {
24852                :        case PictOpOver:
24853                :            op = PictOpSrc;
24854                :            break;
24855                :        case PictOpInReverse:
24856                :            op = PictOpDst;
24857                :            break;
24858                :        case PictOpOutReverse:
24859                :            op = PictOpClear;
24860                :            break;
24861                :        case PictOpAtop:
24862                :            op = PictOpIn;
24863                :            break;
24864                :        case PictOpAtopReverse:
24865                :            op = PictOpOverReverse;
24866                :            break;
24867                :        case PictOpXor:
24868                :            op = PictOpOut;
24869                :            break;
24870                :        default:
24871                :            break;
24872                :        }
24873                :    }
24874                :
24875                :    /* Deal with simplifications when the destination alpha is always 1 */
24876                :    if (no_dst_alpha)
24877                :    {
24878                :        switch (op) {
24879                :        case PictOpOverReverse:
24880                :            op = PictOpDst;
24881                :            break;
24882                :        case PictOpIn:
24883                :            op = PictOpSrc;
24884                :            break;
24885                :        case PictOpOut:
24886                :            op = PictOpClear;
24887                :            break;
24888                :        case PictOpAtop:
24889                :            op = PictOpOver;
24890                :            break;
24891                :        case PictOpXor:
24892                :            op = PictOpOutReverse;
24893                :            break;
24894                :        default:
24895                :            break;
24896                :        }
24897                :    }
24898                :
24899                :    /* Reduce some con/disjoint ops to the basic names. */
24900                :    switch (op) {
24901                :    case PictOpDisjointClear:
24902                :    case PictOpConjointClear:
24903                :        op = PictOpClear;
24904                :        break;
24905                :    case PictOpDisjointSrc:
24906                :    case PictOpConjointSrc:
24907                :        op = PictOpSrc;
24908                :        break;
24909                :    case PictOpDisjointDst:
24910                :    case PictOpConjointDst:
24911                :        op = PictOpDst;
24912                :        break;
24913                :    default:
24914                :        break;
24915                :    }
24916                :
24917                :    return op;
24918                :}
24919                :
24920                :void
24921                :CompositePicture (CARD8         op,
24922                :                  PicturePtr    pSrc,
24923                :                  PicturePtr    pMask,
24924                :                  PicturePtr    pDst,
24925                :                  INT16         xSrc,
24926                :                  INT16         ySrc,
24927                :                  INT16         xMask,
24928                :                  INT16         yMask,
24929                :                  INT16         xDst,
24930                :                  INT16         yDst,
24931                :                  CARD16        width,
24932                :                  CARD16        height)
24933      1  0.0011 :{ /* CompositePicture total:      4  0.0044 */
24934                :    PictureScreenPtr    ps = GetPictureScreen(pDst->pDrawable->pScreen);
24935                :    
24936                :    ValidatePicture (pSrc);
24937                :    if (pMask)
24938                :        ValidatePicture (pMask);
24939      2  0.0022 :    ValidatePicture (pDst);
24940                :
24941                :    op = ReduceCompositeOp (op, pSrc, pMask, pDst);
24942                :    if (op == PictOpDst)
24943                :        return;
24944                :
24945                :    (*ps->Composite) (op,
24946                :                       pSrc,
24947                :                       pMask,
24948                :                       pDst,
24949                :                       xSrc,
24950                :                       ySrc,
24951                :                       xMask,
24952                :                       yMask,
24953                :                       xDst,
24954                :                       yDst,
24955                :                       width,
24956                :                       height);
24957                :}
24958                :
24959                :void
24960                :CompositeGlyphs (CARD8          op,
24961                :                 PicturePtr     pSrc,
24962                :                 PicturePtr     pDst,
24963                :                 PictFormatPtr  maskFormat,
24964                :                 INT16          xSrc,
24965                :                 INT16          ySrc,
24966                :                 int            nlist,
24967                :                 GlyphListPtr   lists,
24968                :                 GlyphPtr       *glyphs)
24969      1  0.0011 :{ /* CompositeGlyphs total:      1  0.0011 */
24970                :    PictureScreenPtr    ps = GetPictureScreen(pDst->pDrawable->pScreen);
24971                :    
24972                :    ValidatePicture (pSrc);
24973                :    ValidatePicture (pDst);
24974                :    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs);
24975                :}
24976                :
24977                :void
24978                :CompositeRects (CARD8           op,
24979                :                PicturePtr      pDst,
24980                :                xRenderColor    *color,
24981                :                int             nRect,
24982                :                xRectangle      *rects)
24983                :{ /* CompositeRects total:      1  0.0011 */
24984      1  0.0011 :    PictureScreenPtr    ps = GetPictureScreen(pDst->pDrawable->pScreen);
24985                :    
24986                :    ValidatePicture (pDst);
24987                :    (*ps->CompositeRects) (op, pDst, color, nRect, rects);
24988                :}
24989                :
24990                :void
24991                :CompositeTrapezoids (CARD8          op,
24992                :                     PicturePtr     pSrc,
24993                :                     PicturePtr     pDst,
24994                :                     PictFormatPtr  maskFormat,
24995                :                     INT16          xSrc,
24996                :                     INT16          ySrc,
24997                :                     int            ntrap,
24998                :                     xTrapezoid     *traps)
24999                :{
25000                :    PictureScreenPtr    ps = GetPictureScreen(pDst->pDrawable->pScreen);
25001                :    
25002                :    ValidatePicture (pSrc);
25003                :    ValidatePicture (pDst);
25004                :    (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
25005                :}
25006                :
25007                :void
25008                :CompositeTriangles (CARD8           op,
25009                :                    PicturePtr      pSrc,
25010                :                    PicturePtr      pDst,
25011                :                    PictFormatPtr   maskFormat,
25012                :                    INT16           xSrc,
25013                :                    INT16           ySrc,
25014                :                    int             ntriangles,
25015                :                    xTriangle       *triangles)
25016                :{
25017                :    PictureScreenPtr    ps = GetPictureScreen(pDst->pDrawable->pScreen);
25018                :    
25019                :    ValidatePicture (pSrc);
25020                :    ValidatePicture (pDst);
25021                :    (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles);
25022                :}
25023                :
25024                :void
25025                :CompositeTriStrip (CARD8            op,
25026                :                   PicturePtr       pSrc,
25027                :                   PicturePtr       pDst,
25028                :                   PictFormatPtr    maskFormat,
25029                :                   INT16            xSrc,
25030                :                   INT16            ySrc,
25031                :                   int              npoints,
25032                :                   xPointFixed      *points)
25033                :{
25034                :    PictureScreenPtr    ps = GetPictureScreen(pDst->pDrawable->pScreen);
25035                :    
25036                :    ValidatePicture (pSrc);
25037                :    ValidatePicture (pDst);
25038                :    (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
25039                :}
25040                :
25041                :void
25042                :CompositeTriFan (CARD8          op,
25043                :                 PicturePtr     pSrc,
25044                :                 PicturePtr     pDst,
25045                :                 PictFormatPtr  maskFormat,
25046                :                 INT16          xSrc,
25047                :                 INT16          ySrc,
25048                :                 int            npoints,
25049                :                 xPointFixed    *points)
25050                :{
25051                :    PictureScreenPtr    ps = GetPictureScreen(pDst->pDrawable->pScreen);
25052                :    
25053                :    ValidatePicture (pSrc);
25054                :    ValidatePicture (pDst);
25055                :    (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
25056                :}
25057                :
25058                :void
25059                :AddTraps (PicturePtr    pPicture,
25060                :          INT16         xOff,
25061                :          INT16         yOff,
25062                :          int           ntrap,
25063                :          xTrap         *traps)
25064                :{
25065                :    PictureScreenPtr    ps = GetPictureScreen(pPicture->pDrawable->pScreen);
25066                :    
25067                :    ValidatePicture (pPicture);
25068                :    (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps);
25069                :}
25070                :
25071                :_X_EXPORT Bool
25072                :PictureTransformPoint3d (PictTransformPtr transform,
25073                :                         PictVectorPtr  vector)
25074                :{
25075                :    PictVector      result;
25076                :    int             i, j;
25077                :    xFixed_32_32    partial;
25078                :    xFixed_48_16    v;
25079                :
25080                :    for (j = 0; j < 3; j++)
25081                :    {
25082                :        v = 0;
25083                :        for (i = 0; i < 3; i++)
25084                :        {
25085                :            partial = ((xFixed_48_16) transform->matrix[j][i] *
25086                :                       (xFixed_48_16) vector->vector[i]);
25087                :            v += partial >> 16;
25088                :        }
25089                :        if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
25090                :            return FALSE;
25091                :        result.vector[j] = (xFixed) v;
25092                :    }
25093                :    if (!result.vector[2])
25094                :        return FALSE;
25095                :    *vector = result;
25096                :    return TRUE;
25097                :}
25098                :
25099                :
25100                :_X_EXPORT Bool
25101                :PictureTransformPoint (PictTransformPtr transform,
25102                :                       PictVectorPtr    vector)
25103                :{
25104                :    PictVector      result;
25105                :    int             i, j;
25106                :    xFixed_32_32    partial;
25107                :    xFixed_48_16    v;
25108                :
25109                :    for (j = 0; j < 3; j++)
25110                :    {
25111                :        v = 0;
25112                :        for (i = 0; i < 3; i++)
25113                :        {
25114                :            partial = ((xFixed_48_16) transform->matrix[j][i] * 
25115                :                       (xFixed_48_16) vector->vector[i]);
25116                :            v += partial >> 16;
25117                :        }
25118                :        if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
25119                :            return FALSE;
25120                :        result.vector[j] = (xFixed) v;
25121                :    }
25122                :    if (!result.vector[2])
25123                :        return FALSE;
25124                :    for (j = 0; j < 2; j++)
25125                :    {
25126                :        partial = (xFixed_48_16) result.vector[j] << 16;
25127                :        v = partial / result.vector[2];
25128                :        if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
25129                :            return FALSE;
25130                :        vector->vector[j] = (xFixed) v;
25131                :    }
25132                :    vector->vector[2] = xFixed1;
25133                :    return TRUE;
25134                :}
25135 /* 
25136  * Total samples for file : "/home/cworth/src/xorg/xserver/mi/miscrinit.c"
25137  * 
25138  *     66  0.0719
25139  */
25140
25141
25142                :/*
25143                :
25144                :Copyright 1990, 1998  The Open Group
25145                :
25146                :Permission to use, copy, modify, distribute, and sell this software and its
25147                :documentation for any purpose is hereby granted without fee, provided that
25148                :the above copyright notice appear in all copies and that both that
25149                :copyright notice and this permission notice appear in supporting
25150                :documentation.
25151                :
25152                :The above copyright notice and this permission notice shall be included
25153                :in all copies or substantial portions of the Software.
25154                :
25155                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25156                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25157                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25158                :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
25159                :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25160                :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25161                :OTHER DEALINGS IN THE SOFTWARE.
25162                :
25163                :Except as contained in this notice, the name of The Open Group shall
25164                :not be used in advertising or otherwise to promote the sale, use or
25165                :other dealings in this Software without prior written authorization
25166                :from The Open Group.
25167                :
25168                :*/
25169                :
25170                :#ifdef HAVE_DIX_CONFIG_H
25171                :#include <dix-config.h>
25172                :#endif
25173                :
25174                :#include <X11/X.h>
25175                :#include "servermd.h"
25176                :#include "misc.h"
25177                :#include "mi.h"
25178                :#include "scrnintstr.h"
25179                :#include "pixmapstr.h"
25180                :#include "dix.h"
25181                :#include "miline.h"
25182                :#ifdef MITSHM
25183                :#define _XSHM_SERVER_
25184                :#include <X11/extensions/XShm.h>
25185                :#endif
25186                :
25187                :/* We use this structure to propogate some information from miScreenInit to
25188                : * miCreateScreenResources.  miScreenInit allocates the structure, fills it
25189                : * in, and puts it into pScreen->devPrivate.  miCreateScreenResources 
25190                : * extracts the info and frees the structure.  We could've accomplished the
25191                : * same thing by adding fields to the screen structure, but they would have
25192                : * ended up being redundant, and would have exposed this mi implementation
25193                : * detail to the whole server.
25194                : */
25195                :
25196                :typedef struct
25197                :{
25198                :    pointer pbits; /* pointer to framebuffer */
25199                :    int width;    /* delta to add to a framebuffer addr to move one row down */
25200                :} miScreenInitParmsRec, *miScreenInitParmsPtr;
25201                :
25202                :
25203                :/* this plugs into pScreen->ModifyPixmapHeader */
25204                :_X_EXPORT Bool
25205                :miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind,
25206                :                     pPixData)
25207                :    PixmapPtr   pPixmap;
25208                :    int         width;
25209                :    int         height;
25210                :    int         depth;
25211                :    int         bitsPerPixel;
25212                :    int         devKind;
25213                :    pointer     pPixData;
25214     12  0.0131 :{ /* miModifyPixmapHeader total:     66  0.0719 */
25215      2  0.0022 :    if (!pPixmap)
25216                :        return FALSE;
25217                :
25218                :    /*
25219                :     * If all arguments are specified, reinitialize everything (including
25220                :     * validated state).
25221                :     */
25222      7  0.0076 :    if ((width > 0) && (height > 0) && (depth > 0) && (bitsPerPixel > 0) &&
25223                :        (devKind > 0) && pPixData) {
25224                :        pPixmap->drawable.depth = depth;
25225                :        pPixmap->drawable.bitsPerPixel = bitsPerPixel;
25226                :        pPixmap->drawable.id = 0;
25227                :        pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
25228                :        pPixmap->drawable.x = 0;
25229                :        pPixmap->drawable.y = 0;
25230                :        pPixmap->drawable.width = width;
25231                :        pPixmap->drawable.height = height;
25232                :        pPixmap->devKind = devKind;
25233                :        pPixmap->refcnt = 1;
25234                :        pPixmap->devPrivate.ptr = pPixData;
25235                :    } else {
25236                :        /*
25237                :         * Only modify specified fields, keeping all others intact.
25238                :         */
25239                :
25240      3  0.0033 :        if (width > 0)
25241                :            pPixmap->drawable.width = width;
25242                :
25243      5  0.0054 :        if (height > 0)
25244      1  0.0011 :            pPixmap->drawable.height = height;
25245                :
25246      1  0.0011 :        if (depth > 0)
25247                :            pPixmap->drawable.depth = depth;
25248                :
25249      8  0.0087 :        if (bitsPerPixel > 0)
25250                :            pPixmap->drawable.bitsPerPixel = bitsPerPixel;
25251      1  0.0011 :        else if ((bitsPerPixel < 0) && (depth > 0))
25252                :            pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth);
25253                :
25254                :        /*
25255                :         * CAVEAT:  Non-SI DDXen may use devKind and devPrivate fields for
25256                :         *          other purposes.
25257                :         */
25258      1  0.0011 :        if (devKind > 0)
25259                :            pPixmap->devKind = devKind;
25260                :        else if ((devKind < 0) && ((width > 0) || (depth > 0)))
25261     14  0.0153 :            pPixmap->devKind = PixmapBytePad(pPixmap->drawable.width,
25262                :                pPixmap->drawable.depth);
25263                :
25264      4  0.0044 :        if (pPixData)
25265      2  0.0022 :            pPixmap->devPrivate.ptr = pPixData;
25266                :    }
25267                :    return TRUE;
25268      5  0.0054 :}
25269                :
25270                :static Bool
25271                :miCloseScreen (int iScreen, ScreenPtr pScreen)
25272                :{
25273                :    return ((*pScreen->DestroyPixmap)((PixmapPtr)pScreen->devPrivate));
25274                :}
25275                :
25276                :/* With the introduction of pixmap privates, the "screen pixmap" can no
25277                : * longer be created in miScreenInit, since all the modules that could
25278                : * possibly ask for pixmap private space have not been initialized at
25279                : * that time.  pScreen->CreateScreenResources is called after all
25280                : * possible private-requesting modules have been inited; we create the
25281                : * screen pixmap here.
25282                : */
25283                :_X_EXPORT Bool
25284                :miCreateScreenResources(pScreen)
25285                :    ScreenPtr pScreen;
25286                :{
25287                :    miScreenInitParmsPtr pScrInitParms;
25288                :    pointer value;
25289                :
25290                :    pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate;
25291                :
25292                :    /* if width is non-zero, pScreen->devPrivate will be a pixmap
25293                :     * else it will just take the value pbits
25294                :     */
25295                :    if (pScrInitParms->width)
25296                :    {
25297                :        PixmapPtr pPixmap;
25298                :
25299                :        /* create a pixmap with no data, then redirect it to point to
25300                :         * the screen
25301                :         */
25302                :        pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth);
25303                :        if (!pPixmap)
25304                :            return FALSE;
25305                :
25306                :        if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width,
25307                :                    pScreen->height, pScreen->rootDepth,
25308                :                    BitsPerPixel(pScreen->rootDepth),
25309                :                    PixmapBytePad(pScrInitParms->width, pScreen->rootDepth),
25310                :                    pScrInitParms->pbits))
25311                :            return FALSE;
25312                :        value = (pointer)pPixmap;
25313                :    }
25314                :    else
25315                :    {
25316                :        value = pScrInitParms->pbits;
25317                :    }
25318                :    xfree(pScreen->devPrivate); /* freeing miScreenInitParmsRec */
25319                :    pScreen->devPrivate = value; /* pPixmap or pbits */
25320                :    return TRUE;
25321                :}
25322                :
25323                :Bool
25324                :miScreenDevPrivateInit(pScreen, width, pbits)
25325                :    ScreenPtr pScreen;
25326                :    int width;
25327                :    pointer pbits;
25328                :{
25329                :    miScreenInitParmsPtr pScrInitParms;
25330                :
25331                :    /* Stash pbits and width in a short-lived miScreenInitParmsRec attached
25332                :     * to the screen, until CreateScreenResources can put them in the
25333                :     * screen pixmap.
25334                :     */
25335                :    pScrInitParms = (miScreenInitParmsPtr)xalloc(sizeof(miScreenInitParmsRec));
25336                :    if (!pScrInitParms)
25337                :        return FALSE;
25338                :    pScrInitParms->pbits = pbits;
25339                :    pScrInitParms->width = width;
25340                :    pScreen->devPrivate = (pointer)pScrInitParms;
25341                :    return TRUE;
25342                :}
25343                :
25344                :_X_EXPORT Bool
25345                :miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width,
25346                :             rootDepth, numDepths, depths, rootVisual, numVisuals, visuals)
25347                :    ScreenPtr pScreen;
25348                :    pointer pbits;              /* pointer to screen bits */
25349                :    int xsize, ysize;           /* in pixels */
25350                :    int dpix, dpiy;             /* dots per inch */
25351                :    int width;                  /* pixel width of frame buffer */
25352                :    int rootDepth;              /* depth of root window */
25353                :    int numDepths;              /* number of depths supported */
25354                :    DepthRec *depths;           /* supported depths */
25355                :    VisualID rootVisual;        /* root visual */
25356                :    int numVisuals;             /* number of visuals supported */
25357                :    VisualRec *visuals;         /* supported visuals */
25358                :{
25359                :    pScreen->width = xsize;
25360                :    pScreen->height = ysize;
25361                :    pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10);
25362                :    pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10);
25363                :    pScreen->numDepths = numDepths;
25364                :    pScreen->rootDepth = rootDepth;
25365                :    pScreen->allowedDepths = depths;
25366                :    pScreen->rootVisual = rootVisual;
25367                :    /* defColormap */
25368                :    pScreen->minInstalledCmaps = 1;
25369                :    pScreen->maxInstalledCmaps = 1;
25370                :    pScreen->backingStoreSupport = NotUseful;
25371                :    pScreen->saveUnderSupport = NotUseful;
25372                :    /* whitePixel, blackPixel */
25373                :    pScreen->ModifyPixmapHeader = miModifyPixmapHeader;
25374                :    pScreen->CreateScreenResources = miCreateScreenResources;
25375                :    pScreen->GetScreenPixmap = miGetScreenPixmap;
25376                :    pScreen->SetScreenPixmap = miSetScreenPixmap;
25377                :    pScreen->numVisuals = numVisuals;
25378                :    pScreen->visuals = visuals;
25379                :    if (width)
25380                :    {
25381                :#ifdef MITSHM
25382                :        ShmRegisterFbFuncs(pScreen);
25383                :#endif
25384                :        pScreen->CloseScreen = miCloseScreen;
25385                :    }
25386                :    /* else CloseScreen */
25387                :    /* QueryBestSize, SaveScreen, GetImage, GetSpans */
25388                :    pScreen->PointerNonInterestBox = (PointerNonInterestBoxProcPtr) 0;
25389                :    pScreen->SourceValidate = (SourceValidateProcPtr) 0;
25390                :    /* CreateWindow, DestroyWindow, PositionWindow, ChangeWindowAttributes */
25391                :    /* RealizeWindow, UnrealizeWindow */
25392                :    pScreen->ValidateTree = miValidateTree;
25393                :    pScreen->PostValidateTree = (PostValidateTreeProcPtr) 0;
25394                :    pScreen->WindowExposures = miWindowExposures;
25395                :    /* PaintWindowBackground, PaintWindowBorder, CopyWindow */
25396                :    pScreen->ClearToBackground = miClearToBackground;
25397                :    pScreen->ClipNotify = (ClipNotifyProcPtr) 0;
25398                :    pScreen->RestackWindow = (RestackWindowProcPtr) 0;
25399                :    /* CreatePixmap, DestroyPixmap */
25400                :    /* RealizeFont, UnrealizeFont */
25401                :    /* CreateGC */
25402                :    /* CreateColormap, DestroyColormap, InstallColormap, UninstallColormap */
25403                :    /* ListInstalledColormaps, StoreColors, ResolveColor */
25404                :    /* BitmapToRegion */
25405                :    pScreen->SendGraphicsExpose = miSendGraphicsExpose;
25406                :    pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA;
25407                :    pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA;
25408                :    pScreen->blockData = (pointer)0;
25409                :    pScreen->wakeupData = (pointer)0;
25410                :    pScreen->MarkWindow = miMarkWindow;
25411                :    pScreen->MarkOverlappedWindows = miMarkOverlappedWindows;
25412                :    pScreen->ChangeSaveUnder = miChangeSaveUnder;
25413                :    pScreen->PostChangeSaveUnder = miPostChangeSaveUnder;
25414                :    pScreen->MoveWindow = miMoveWindow;
25415                :    pScreen->ResizeWindow = miSlideAndSizeWindow;
25416                :    pScreen->GetLayerWindow = miGetLayerWindow;
25417                :    pScreen->HandleExposures = miHandleValidateExposures;
25418                :    pScreen->ReparentWindow = (ReparentWindowProcPtr) 0;
25419                :    pScreen->ChangeBorderWidth = miChangeBorderWidth;
25420                :#ifdef SHAPE
25421                :    pScreen->SetShape = miSetShape;
25422                :#endif
25423                :    pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow;
25424                :
25425                :    pScreen->SaveDoomedAreas = 0;
25426                :    pScreen->RestoreAreas = 0;
25427                :    pScreen->ExposeCopy = 0;
25428                :    pScreen->TranslateBackingStore = 0;
25429                :    pScreen->ClearBackingStore = 0;
25430                :    pScreen->DrawGuarantee = 0;
25431                :
25432                :    miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS);
25433                :
25434                :    return miScreenDevPrivateInit(pScreen, width, pbits);
25435                :}
25436                :
25437                :_X_EXPORT int
25438                :miAllocateGCPrivateIndex()
25439                :{
25440                :    static int privateIndex = -1;
25441                :    static unsigned long miGeneration = 0;
25442                :
25443                :    if (miGeneration != serverGeneration)
25444                :    {
25445                :        privateIndex = AllocateGCPrivateIndex();
25446                :        miGeneration = serverGeneration;
25447                :    }
25448                :    return privateIndex;
25449                :}
25450                :
25451                :_X_EXPORT int miZeroLineScreenIndex;
25452                :static unsigned int miZeroLineGeneration = 0;
25453                :
25454                :_X_EXPORT void
25455                :miSetZeroLineBias(pScreen, bias)
25456                :    ScreenPtr pScreen;
25457                :    unsigned int bias;
25458                :{
25459                :    if (miZeroLineGeneration != serverGeneration)
25460                :    {
25461                :        miZeroLineScreenIndex = AllocateScreenPrivateIndex();
25462                :        miZeroLineGeneration = serverGeneration;
25463                :    }
25464                :    if (miZeroLineScreenIndex >= 0)
25465                :        pScreen->devPrivates[miZeroLineScreenIndex].uval = bias;
25466                :}
25467                :
25468                :_X_EXPORT PixmapPtr
25469                :miGetScreenPixmap(pScreen)
25470                :    ScreenPtr pScreen;
25471                :{
25472                :    return (PixmapPtr)(pScreen->devPrivate);
25473                :}
25474                :
25475                :_X_EXPORT void
25476                :miSetScreenPixmap(pPix)
25477                :    PixmapPtr pPix;
25478                :{
25479                :    if (pPix)
25480                :        pPix->drawable.pScreen->devPrivate = (pointer)pPix;
25481                :}
25482 /* 
25483  * Total samples for file : "/home/cworth/src/xorg/xserver/mi/miregion.c"
25484  * 
25485  *     66  0.0719
25486  */
25487
25488
25489                :/***********************************************************
25490                :
25491                :Copyright 1987, 1988, 1989, 1998  The Open Group
25492                :
25493                :Permission to use, copy, modify, distribute, and sell this software and its
25494                :documentation for any purpose is hereby granted without fee, provided that
25495                :the above copyright notice appear in all copies and that both that
25496                :copyright notice and this permission notice appear in supporting
25497                :documentation.
25498                :
25499                :The above copyright notice and this permission notice shall be included in
25500                :all copies or substantial portions of the Software.
25501                :
25502                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25503                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25504                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25505                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25506                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25507                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25508                :
25509                :Except as contained in this notice, the name of The Open Group shall not be
25510                :used in advertising or otherwise to promote the sale, use or other dealings
25511                :in this Software without prior written authorization from The Open Group.
25512                : 
25513                :
25514                :Copyright 1987, 1988, 1989 by 
25515                :Digital Equipment Corporation, Maynard, Massachusetts. 
25516                :
25517                :                        All Rights Reserved
25518                :
25519                :Permission to use, copy, modify, and distribute this software and its 
25520                :documentation for any purpose and without fee is hereby granted, 
25521                :provided that the above copyright notice appear in all copies and that
25522                :both that copyright notice and this permission notice appear in 
25523                :supporting documentation, and that the name of Digital not be
25524                :used in advertising or publicity pertaining to distribution of the
25525                :software without specific, written prior permission.  
25526                :
25527                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
25528                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25529                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
25530                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25531                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25532                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
25533                :SOFTWARE.
25534                :
25535                :******************************************************************/
25536                :
25537                :/* The panoramix components contained the following notice */
25538                :/*****************************************************************
25539                :
25540                :Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
25541                :
25542                :Permission is hereby granted, free of charge, to any person obtaining a copy
25543                :of this software and associated documentation files (the "Software"), to deal
25544                :in the Software without restriction, including without limitation the rights
25545                :to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25546                :copies of the Software.
25547                :
25548                :The above copyright notice and this permission notice shall be included in
25549                :all copies or substantial portions of the Software.
25550                :
25551                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25552                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25553                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
25554                :DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
25555                :BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
25556                :WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
25557                :IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25558                :
25559                :Except as contained in this notice, the name of Digital Equipment Corporation
25560                :shall not be used in advertising or otherwise to promote the sale, use or other
25561                :dealings in this Software without prior written authorization from Digital
25562                :Equipment Corporation.
25563                :
25564                :******************************************************************/
25565                :
25566                :#ifdef HAVE_DIX_CONFIG_H
25567                :#include <dix-config.h>
25568                :#endif
25569                :
25570                :#include "regionstr.h"
25571                :#include <X11/Xprotostr.h>
25572                :#include <X11/Xfuncproto.h>
25573                :#include "gc.h"
25574                :#include "mi.h"
25575                :#include "mispans.h"
25576                :#include <pixman/pixman.h>
25577                :
25578                :#undef assert
25579                :#ifdef DEBUG
25580                :#define assert(expr) {if (!(expr)) \
25581                :                FatalError("Assertion failed file %s, line %d: expr\n", \
25582                :                        __FILE__, __LINE__); }
25583                :#else
25584                :#define assert(expr)
25585                :#endif
25586                :
25587                :#define good(reg) assert(miValidRegion(reg))
25588                :
25589                :/*
25590                : * The functions in this file implement the Region abstraction used extensively
25591                : * throughout the X11 sample server. A Region is simply a set of disjoint
25592                : * (non-overlapping) rectangles, plus an "extent" rectangle which is the
25593                : * smallest single rectangle that contains all the non-overlapping rectangles.
25594                : *
25595                : * A Region is implemented as a "y-x-banded" array of rectangles.  This array
25596                : * imposes two degrees of order.  First, all rectangles are sorted by top side
25597                : * y coordinate first (y1), and then by left side x coordinate (x1).
25598                : *
25599                : * Furthermore, the rectangles are grouped into "bands".  Each rectangle in a
25600                : * band has the same top y coordinate (y1), and each has the same bottom y
25601                : * coordinate (y2).  Thus all rectangles in a band differ only in their left
25602                : * and right side (x1 and x2).  Bands are implicit in the array of rectangles:
25603                : * there is no separate list of band start pointers.
25604                : *
25605                : * The y-x band representation does not minimize rectangles.  In particular,
25606                : * if a rectangle vertically crosses a band (the rectangle has scanlines in 
25607                : * the y1 to y2 area spanned by the band), then the rectangle may be broken
25608                : * down into two or more smaller rectangles stacked one atop the other. 
25609                : *
25610                : *  -----------                             -----------
25611                : *  |         |                             |         |             band 0
25612                : *  |         |  --------                   -----------  --------
25613                : *  |         |  |      |  in y-x banded    |         |  |      |   band 1
25614                : *  |         |  |      |  form is          |         |  |      |
25615                : *  -----------  |      |                   -----------  --------
25616                : *               |      |                                |      |   band 2
25617                : *               --------                                --------
25618                : *
25619                : * An added constraint on the rectangles is that they must cover as much
25620                : * horizontal area as possible: no two rectangles within a band are allowed
25621                : * to touch.
25622                : *
25623                : * Whenever possible, bands will be merged together to cover a greater vertical
25624                : * distance (and thus reduce the number of rectangles). Two bands can be merged
25625                : * only if the bottom of one touches the top of the other and they have
25626                : * rectangles in the same places (of the same width, of course).
25627                : *
25628                : * Adam de Boor wrote most of the original region code.  Joel McCormack
25629                : * substantially modified or rewrote most of the core arithmetic routines,
25630                : * and added miRegionValidate in order to support several speed improvements
25631                : * to miValidateTree.  Bob Scheifler changed the representation to be more
25632                : * compact when empty or a single rectangle, and did a bunch of gratuitous
25633                : * reformatting.
25634                : */
25635                :
25636                :/*  true iff two Boxes overlap */
25637                :#define EXTENTCHECK(r1,r2) \
25638                :      (!( ((r1)->x2 <= (r2)->x1)  || \
25639                :          ((r1)->x1 >= (r2)->x2)  || \
25640                :          ((r1)->y2 <= (r2)->y1)  || \
25641                :          ((r1)->y1 >= (r2)->y2) ) )
25642                :
25643                :/* true iff (x,y) is in Box */
25644                :#define INBOX(r,x,y) \
25645                :      ( ((r)->x2 >  x) && \
25646                :        ((r)->x1 <= x) && \
25647                :        ((r)->y2 >  y) && \
25648                :        ((r)->y1 <= y) )
25649                :
25650                :/* true iff Box r1 contains Box r2 */
25651                :#define SUBSUMES(r1,r2) \
25652                :      ( ((r1)->x1 <= (r2)->x1) && \
25653                :        ((r1)->x2 >= (r2)->x2) && \
25654                :        ((r1)->y1 <= (r2)->y1) && \
25655                :        ((r1)->y2 >= (r2)->y2) )
25656                :
25657                :#define xallocData(n) (RegDataPtr)xalloc(REGION_SZOF(n))
25658                :#define xfreeData(reg) if ((reg)->data && (reg)->data->size) xfree((reg)->data)
25659                :
25660                :#define RECTALLOC_BAIL(pReg,n,bail) \
25661                :if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
25662                :    if (!miRectAlloc(pReg, n)) { goto bail; }
25663                :
25664                :#define RECTALLOC(pReg,n) \
25665                :if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
25666                :    if (!miRectAlloc(pReg, n)) { return FALSE; }
25667                :
25668                :#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2)      \
25669                :{                                               \
25670                :    pNextRect->x1 = nx1;                        \
25671                :    pNextRect->y1 = ny1;                        \
25672                :    pNextRect->x2 = nx2;                        \
25673                :    pNextRect->y2 = ny2;                        \
25674                :    pNextRect++;                                \
25675                :}
25676                :
25677                :#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2)                 \
25678                :{                                                                       \
25679                :    if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
25680                :    {                                                                   \
25681                :        if (!miRectAlloc(pReg, 1))                                      \
25682                :            return FALSE;                                               \
25683                :        pNextRect = REGION_TOP(pReg);                                   \
25684                :    }                                                                   \
25685                :    ADDRECT(pNextRect,nx1,ny1,nx2,ny2);                                 \
25686                :    pReg->data->numRects++;                                             \
25687                :    assert(pReg->data->numRects<=pReg->data->size);                     \
25688                :}
25689                :
25690                :
25691                :#define DOWNSIZE(reg,numRects)                                           \
25692                :if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
25693                :{                                                                        \
25694                :    RegDataPtr NewData;                                                  \
25695                :    NewData = (RegDataPtr)xrealloc((reg)->data, REGION_SZOF(numRects));  \
25696                :    if (NewData)                                                         \
25697                :    {                                                                    \
25698                :        NewData->size = (numRects);                                      \
25699                :        (reg)->data = NewData;                                           \
25700                :    }                                                                    \
25701                :}
25702                :
25703                :
25704                :_X_EXPORT BoxRec miEmptyBox = {0, 0, 0, 0};
25705                :_X_EXPORT RegDataRec miEmptyData = {0, 0};
25706                :
25707                :RegDataRec  miBrokenData = {0, 0};
25708                :static RegionRec   miBrokenRegion = { { 0, 0, 0, 0 }, &miBrokenData };
25709                :
25710                :extern void
25711                :InitRegions (void)
25712                :{
25713                :    pixman_region_set_static_pointers (&miEmptyBox, &miEmptyData, &miBrokenData);
25714                :}
25715                :
25716                :/*****************************************************************
25717                : *   RegionCreate(rect, size)
25718                : *     This routine does a simple malloc to make a structure of
25719                : *     REGION of "size" number of rectangles.
25720                : *****************************************************************/
25721                :
25722                :_X_EXPORT RegionPtr
25723                :miRegionCreate(rect, size)
25724                :    BoxPtr rect;
25725                :    int size;
25726      3  0.0033 :{ /* miRegionCreate total:      5  0.0054 */
25727                :    RegionPtr pReg;
25728                :   
25729                :    pReg = (RegionPtr)xalloc(sizeof(RegionRec));
25730      1  0.0011 :    if (!pReg)
25731                :        return &miBrokenRegion;
25732                :
25733      1  0.0011 :    miRegionInit (pReg, rect, size);
25734                :    
25735                :    return(pReg);
25736                :}
25737                :
25738                :_X_EXPORT void
25739                :miRegionDestroy(pReg)
25740                :    RegionPtr pReg;
25741      3  0.0033 :{ /* miRegionDestroy total:      5  0.0054 */
25742                :    pixman_region_fini (pReg);
25743                :    if (pReg != &miBrokenRegion)
25744      1  0.0011 :        xfree(pReg);
25745      1  0.0011 :}
25746                :
25747                :_X_EXPORT void
25748                :miPrintRegion(rgn)
25749                :    RegionPtr rgn;
25750                :{
25751                :    int num, size;
25752                :    int i;
25753                :    BoxPtr rects;
25754                :
25755                :    num = REGION_NUM_RECTS(rgn);
25756                :    size = REGION_SIZE(rgn);
25757                :    rects = REGION_RECTS(rgn);
25758                :    ErrorF("num: %d size: %d\n", num, size);
25759                :    ErrorF("extents: %d %d %d %d\n",
25760                :           rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
25761                :    for (i = 0; i < num; i++)
25762                :      ErrorF("%d %d %d %d \n",
25763                :             rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
25764                :    ErrorF("\n");
25765                :}
25766                :
25767                :_X_EXPORT Bool
25768                :miRegionEqual(reg1, reg2)
25769                :    RegionPtr reg1;
25770                :    RegionPtr reg2;
25771                :{
25772                :    return pixman_region_equal (reg1, reg2);
25773                :}
25774                :
25775                :#ifdef DEBUG
25776                :Bool
25777                :miValidRegion(reg)
25778                :    RegionPtr reg;
25779                :{
25780                :    int i, numRects;
25781                :    
25782                :    if ((reg->extents.x1 > reg->extents.x2) ||
25783                :        (reg->extents.y1 > reg->extents.y2))
25784                :        return FALSE;
25785                :    numRects = REGION_NUM_RECTS(reg);
25786                :    if (!numRects)
25787                :        return ((reg->extents.x1 == reg->extents.x2) &&
25788                :                (reg->extents.y1 == reg->extents.y2) &&
25789                :                (reg->data->size || (reg->data == &miEmptyData)));
25790                :    else if (numRects == 1)
25791                :        return (!reg->data);
25792                :    else
25793                :    {
25794                :        BoxPtr pboxP, pboxN;
25795                :        BoxRec box;
25796                :        
25797                :        pboxP = REGION_RECTS(reg);
25798                :        box = *pboxP;
25799                :        box.y2 = pboxP[numRects-1].y2;
25800                :        pboxN = pboxP + 1;
25801                :        for (i = numRects; --i > 0; pboxP++, pboxN++)
25802                :        {
25803                :            if ((pboxN->x1 >= pboxN->x2) ||
25804                :                (pboxN->y1 >= pboxN->y2))
25805                :                return FALSE;
25806                :            if (pboxN->x1 < box.x1)
25807                :                box.x1 = pboxN->x1;
25808                :            if (pboxN->x2 > box.x2)
25809                :                box.x2 = pboxN->x2;
25810                :            if ((pboxN->y1 < pboxP->y1) ||
25811                :                ((pboxN->y1 == pboxP->y1) &&
25812                :                 ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2))))
25813                :                return FALSE;
25814                :        }
25815                :        return ((box.x1 == reg->extents.x1) &&
25816                :                (box.x2 == reg->extents.x2) &&
25817                :                (box.y1 == reg->extents.y1) &&
25818                :                (box.y2 == reg->extents.y2));
25819                :    }
25820                :}
25821                :#endif /* DEBUG */
25822                :
25823                :/*****************************************************************
25824                : *   RegionInit(pReg, rect, size)
25825                : *     Outer region rect is statically allocated.
25826                : *****************************************************************/
25827                :
25828                :_X_EXPORT void
25829                :miRegionInit(pReg, rect, size)
25830                :    RegionPtr pReg;
25831                :    BoxPtr rect;
25832                :    int size;
25833      3  0.0033 :{ /* miRegionInit total:      5  0.0054 */
25834                :    if (rect)
25835                :        pixman_region_init_with_extents (pReg, rect);
25836                :    else
25837                :        pixman_region_init (pReg);
25838      2  0.0022 :}
25839                :
25840                :_X_EXPORT void
25841                :miRegionUninit(pReg)
25842                :    RegionPtr pReg;
25843                :{
25844                :    pixman_region_fini (pReg);
25845                :}
25846                :
25847                :Bool
25848                :miRegionBreak (pReg)
25849                :    RegionPtr pReg;
25850                :{
25851                :    xfreeData (pReg);
25852                :    pReg->extents = miEmptyBox;
25853                :    pReg->data = &miBrokenData;
25854                :    return FALSE;
25855                :}
25856                :
25857                :_X_EXPORT Bool
25858                :miRectAlloc(
25859                :    RegionPtr pRgn,
25860                :    int n)
25861                :{
25862                :    RegDataPtr  data;
25863                :    
25864                :    if (!pRgn->data)
25865                :    {
25866                :        n++;
25867                :        pRgn->data = xallocData(n);
25868                :        if (!pRgn->data)
25869                :            return miRegionBreak (pRgn);
25870                :        pRgn->data->numRects = 1;
25871                :        *REGION_BOXPTR(pRgn) = pRgn->extents;
25872                :    }
25873                :    else if (!pRgn->data->size)
25874                :    {
25875                :        pRgn->data = xallocData(n);
25876                :        if (!pRgn->data)
25877                :            return miRegionBreak (pRgn);
25878                :        pRgn->data->numRects = 0;
25879                :    }
25880                :    else
25881                :    {
25882                :        if (n == 1)
25883                :        {
25884                :            n = pRgn->data->numRects;
25885                :            if (n > 500) /* XXX pick numbers out of a hat */
25886                :                n = 250;
25887                :        }
25888                :        n += pRgn->data->numRects;
25889                :        data = (RegDataPtr)xrealloc(pRgn->data, REGION_SZOF(n));
25890                :        if (!data)
25891                :            return miRegionBreak (pRgn);
25892                :        pRgn->data = data;
25893                :    }
25894                :    pRgn->data->size = n;
25895                :    return TRUE;
25896                :}
25897                :
25898                :_X_EXPORT Bool
25899                :miRegionCopy(dst, src)
25900                :    RegionPtr dst;
25901                :    RegionPtr src;
25902      1  0.0011 :{ /* miRegionCopy total:      1  0.0011 */
25903                :    return pixman_region_copy (dst, src);
25904                :}
25905                :
25906                :/*======================================================================
25907                : *          Generic Region Operator
25908                : *====================================================================*/
25909                :
25910                :/*-
25911                : *-----------------------------------------------------------------------
25912                : * miCoalesce --
25913                : *      Attempt to merge the boxes in the current band with those in the
25914                : *      previous one.  We are guaranteed that the current band extends to
25915                : *      the end of the rects array.  Used only by miRegionOp.
25916                : *
25917                : * Results:
25918                : *      The new index for the previous band.
25919                : *
25920                : * Side Effects:
25921                : *      If coalescing takes place:
25922                : *          - rectangles in the previous band will have their y2 fields
25923                : *            altered.
25924                : *          - pReg->data->numRects will be decreased.
25925                : *
25926                : *-----------------------------------------------------------------------
25927                : */
25928                :_X_INLINE static int
25929                :miCoalesce (
25930                :    RegionPtr   pReg,           /* Region to coalesce                */
25931                :    int                 prevStart,      /* Index of start of previous band   */
25932                :    int                 curStart)       /* Index of start of current band    */
25933                :{
25934                :    BoxPtr      pPrevBox;       /* Current box in previous band      */
25935                :    BoxPtr      pCurBox;        /* Current box in current band       */
25936                :    int         numRects;       /* Number rectangles in both bands   */
25937                :    int         y2;             /* Bottom of current band            */
25938                :    /*
25939                :     * Figure out how many rectangles are in the band.
25940                :     */
25941                :    numRects = curStart - prevStart;
25942                :    assert(numRects == pReg->data->numRects - curStart);
25943                :
25944                :    if (!numRects) return curStart;
25945                :
25946                :    /*
25947                :     * The bands may only be coalesced if the bottom of the previous
25948                :     * matches the top scanline of the current.
25949                :     */
25950                :    pPrevBox = REGION_BOX(pReg, prevStart);
25951                :    pCurBox = REGION_BOX(pReg, curStart);
25952                :    if (pPrevBox->y2 != pCurBox->y1) return curStart;
25953                :
25954                :    /*
25955                :     * Make sure the bands have boxes in the same places. This
25956                :     * assumes that boxes have been added in such a way that they
25957                :     * cover the most area possible. I.e. two boxes in a band must
25958                :     * have some horizontal space between them.
25959                :     */
25960                :    y2 = pCurBox->y2;
25961                :
25962                :    do {
25963                :        if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {
25964                :            return (curStart);
25965                :        }
25966                :        pPrevBox++;
25967                :        pCurBox++;
25968                :        numRects--;
25969                :    } while (numRects);
25970                :
25971                :    /*
25972                :     * The bands may be merged, so set the bottom y of each box
25973                :     * in the previous band to the bottom y of the current band.
25974                :     */
25975                :    numRects = curStart - prevStart;
25976                :    pReg->data->numRects -= numRects;
25977                :    do {
25978                :        pPrevBox--;
25979                :        pPrevBox->y2 = y2;
25980                :        numRects--;
25981                :    } while (numRects);
25982                :    return prevStart;
25983                :}
25984                :
25985                :
25986                :/* Quicky macro to avoid trivial reject procedure calls to miCoalesce */
25987                :
25988                :#define Coalesce(newReg, prevBand, curBand)                             \
25989                :    if (curBand - prevBand == newReg->data->numRects - curBand) {       \
25990                :        prevBand = miCoalesce(newReg, prevBand, curBand);               \
25991                :    } else {                                                            \
25992                :        prevBand = curBand;                                             \
25993                :    }
25994                :
25995                :/*-
25996                : *-----------------------------------------------------------------------
25997                : * miAppendNonO --
25998                : *      Handle a non-overlapping band for the union and subtract operations.
25999                : *      Just adds the (top/bottom-clipped) rectangles into the region.
26000                : *      Doesn't have to check for subsumption or anything.
26001                : *
26002                : * Results:
26003                : *      None.
26004                : *
26005                : * Side Effects:
26006                : *      pReg->data->numRects is incremented and the rectangles overwritten
26007                : *      with the rectangles we're passed.
26008                : *
26009                : *-----------------------------------------------------------------------
26010                : */
26011                :
26012                :_X_INLINE static Bool
26013                :miAppendNonO (
26014                :    RegionPtr   pReg,
26015                :    BoxPtr      r,
26016                :    BoxPtr      rEnd,
26017                :    int         y1,
26018                :    int         y2)
26019                :{
26020                :    BoxPtr      pNextRect;
26021                :    int         newRects;
26022                :
26023                :    newRects = rEnd - r;
26024                :
26025                :    assert(y1 < y2);
26026                :    assert(newRects != 0);
26027                :
26028                :    /* Make sure we have enough space for all rectangles to be added */
26029                :    RECTALLOC(pReg, newRects);
26030                :    pNextRect = REGION_TOP(pReg);
26031                :    pReg->data->numRects += newRects;
26032                :    do {
26033                :        assert(r->x1 < r->x2);
26034                :        ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
26035                :        r++;
26036                :    } while (r != rEnd);
26037                :
26038                :    return TRUE;
26039                :}
26040                :
26041                :#define FindBand(r, rBandEnd, rEnd, ry1)                    \
26042                :{                                                           \
26043                :    ry1 = r->y1;                                            \
26044                :    rBandEnd = r+1;                                         \
26045                :    while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) {   \
26046                :        rBandEnd++;                                         \
26047                :    }                                                       \
26048                :}
26049                :
26050                :#define AppendRegions(newReg, r, rEnd)                                  \
26051                :{                                                                       \
26052                :    int newRects;                                                       \
26053                :    if ((newRects = rEnd - r)) {                                        \
26054                :        RECTALLOC(newReg, newRects);                                    \
26055                :        memmove((char *)REGION_TOP(newReg),(char *)r,                   \
26056                :              newRects * sizeof(BoxRec));                               \
26057                :        newReg->data->numRects += newRects;                             \
26058                :    }                                                                   \
26059                :}
26060                :
26061                :/*-
26062                : *-----------------------------------------------------------------------
26063                : * miRegionOp --
26064                : *      Apply an operation to two regions. Called by miUnion, miInverse,
26065                : *      miSubtract, miIntersect....  Both regions MUST have at least one
26066                : *      rectangle, and cannot be the same object.
26067                : *
26068                : * Results:
26069                : *      TRUE if successful.
26070                : *
26071                : * Side Effects:
26072                : *      The new region is overwritten.
26073                : *      pOverlap set to TRUE if overlapFunc ever returns TRUE.
26074                : *
26075                : * Notes:
26076                : *      The idea behind this function is to view the two regions as sets.
26077                : *      Together they cover a rectangle of area that this function divides
26078                : *      into horizontal bands where points are covered only by one region
26079                : *      or by both. For the first case, the nonOverlapFunc is called with
26080                : *      each the band and the band's upper and lower extents. For the
26081                : *      second, the overlapFunc is called to process the entire band. It
26082                : *      is responsible for clipping the rectangles in the band, though
26083                : *      this function provides the boundaries.
26084                : *      At the end of each band, the new region is coalesced, if possible,
26085                : *      to reduce the number of rectangles in the region.
26086                : *
26087                : *-----------------------------------------------------------------------
26088                : */
26089                :
26090                :typedef Bool (*OverlapProcPtr)(
26091                :    RegionPtr   pReg,
26092                :    BoxPtr      r1,
26093                :    BoxPtr      r1End,
26094                :    BoxPtr      r2,
26095                :    BoxPtr      r2End,
26096                :    short       y1,
26097                :    short       y2,
26098                :    Bool        *pOverlap);
26099                :
26100                :static Bool
26101                :miRegionOp(
26102                :    RegionPtr       newReg,                 /* Place to store result         */
26103                :    RegionPtr       reg1,                   /* First region in operation     */
26104                :    RegionPtr       reg2,                   /* 2d region in operation        */
26105                :    OverlapProcPtr  overlapFunc,            /* Function to call for over-
26106                :                                             * lapping bands                 */
26107                :    Bool            appendNon1,             /* Append non-overlapping bands  */
26108                :                                            /* in region 1 ? */
26109                :    Bool            appendNon2,             /* Append non-overlapping bands  */
26110                :                                            /* in region 2 ? */
26111                :    Bool            *pOverlap)
26112                :{
26113                :    BoxPtr      r1;                 /* Pointer into first region     */
26114                :    BoxPtr      r2;                 /* Pointer into 2d region        */
26115                :    BoxPtr      r1End;              /* End of 1st region             */
26116                :    BoxPtr      r2End;              /* End of 2d region              */
26117                :    short       ybot;               /* Bottom of intersection        */
26118                :    short       ytop;               /* Top of intersection           */
26119                :    RegDataPtr  oldData;            /* Old data for newReg           */
26120                :    int         prevBand;           /* Index of start of
26121                :                                     * previous band in newReg       */
26122                :    int         curBand;            /* Index of start of current
26123                :                                     * band in newReg                */
26124                :    BoxPtr      r1BandEnd;          /* End of current band in r1     */
26125                :    BoxPtr      r2BandEnd;          /* End of current band in r2     */
26126                :    short       top;                /* Top of non-overlapping band   */
26127                :    short       bot;                /* Bottom of non-overlapping band*/
26128                :    int         r1y1;               /* Temps for r1->y1 and r2->y1   */
26129                :    int         r2y1;
26130                :    int         newSize;
26131                :    int         numRects;
26132                :
26133                :    /*
26134                :     * Break any region computed from a broken region
26135                :     */
26136                :    if (REGION_NAR (reg1) || REGION_NAR(reg2))
26137                :        return miRegionBreak (newReg);
26138                :    
26139                :    /*
26140                :     * Initialization:
26141                :     *  set r1, r2, r1End and r2End appropriately, save the rectangles
26142                :     * of the destination region until the end in case it's one of
26143                :     * the two source regions, then mark the "new" region empty, allocating
26144                :     * another array of rectangles for it to use.
26145                :     */
26146                :
26147                :    r1 = REGION_RECTS(reg1);
26148                :    newSize = REGION_NUM_RECTS(reg1);
26149                :    r1End = r1 + newSize;
26150                :    numRects = REGION_NUM_RECTS(reg2);
26151                :    r2 = REGION_RECTS(reg2);
26152                :    r2End = r2 + numRects;
26153                :    assert(r1 != r1End);
26154                :    assert(r2 != r2End);
26155                :
26156                :    oldData = (RegDataPtr)NULL;
26157                :    if (((newReg == reg1) && (newSize > 1)) ||
26158                :        ((newReg == reg2) && (numRects > 1)))
26159                :    {
26160                :        oldData = newReg->data;
26161                :        newReg->data = &miEmptyData;
26162                :    }
26163                :    /* guess at new size */
26164                :    if (numRects > newSize)
26165                :        newSize = numRects;
26166                :    newSize <<= 1;
26167                :    if (!newReg->data)
26168                :        newReg->data = &miEmptyData;
26169                :    else if (newReg->data->size)
26170                :        newReg->data->numRects = 0;
26171                :    if (newSize > newReg->data->size)
26172                :        if (!miRectAlloc(newReg, newSize))
26173                :            return FALSE;
26174                :
26175                :    /*
26176                :     * Initialize ybot.
26177                :     * In the upcoming loop, ybot and ytop serve different functions depending
26178                :     * on whether the band being handled is an overlapping or non-overlapping
26179                :     * band.
26180                :     *  In the case of a non-overlapping band (only one of the regions
26181                :     * has points in the band), ybot is the bottom of the most recent
26182                :     * intersection and thus clips the top of the rectangles in that band.
26183                :     * ytop is the top of the next intersection between the two regions and
26184                :     * serves to clip the bottom of the rectangles in the current band.
26185                :     *  For an overlapping band (where the two regions intersect), ytop clips
26186                :     * the top of the rectangles of both regions and ybot clips the bottoms.
26187                :     */
26188                :
26189                :    ybot = min(r1->y1, r2->y1);
26190                :    
26191                :    /*
26192                :     * prevBand serves to mark the start of the previous band so rectangles
26193                :     * can be coalesced into larger rectangles. qv. miCoalesce, above.
26194                :     * In the beginning, there is no previous band, so prevBand == curBand
26195                :     * (curBand is set later on, of course, but the first band will always
26196                :     * start at index 0). prevBand and curBand must be indices because of
26197                :     * the possible expansion, and resultant moving, of the new region's
26198                :     * array of rectangles.
26199                :     */
26200                :    prevBand = 0;
26201                :    
26202                :    do {
26203                :        /*
26204                :         * This algorithm proceeds one source-band (as opposed to a
26205                :         * destination band, which is determined by where the two regions
26206                :         * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
26207                :         * rectangle after the last one in the current band for their
26208                :         * respective regions.
26209                :         */
26210                :        assert(r1 != r1End);
26211                :        assert(r2 != r2End);
26212                :    
26213                :        FindBand(r1, r1BandEnd, r1End, r1y1);
26214                :        FindBand(r2, r2BandEnd, r2End, r2y1);
26215                :
26216                :        /*
26217                :         * First handle the band that doesn't intersect, if any.
26218                :         *
26219                :         * Note that attention is restricted to one band in the
26220                :         * non-intersecting region at once, so if a region has n
26221                :         * bands between the current position and the next place it overlaps
26222                :         * the other, this entire loop will be passed through n times.
26223                :         */
26224                :        if (r1y1 < r2y1) {
26225                :            if (appendNon1) {
26226                :                top = max(r1y1, ybot);
26227                :                bot = min(r1->y2, r2y1);
26228                :                if (top != bot) {
26229                :                    curBand = newReg->data->numRects;
26230                :                    miAppendNonO(newReg, r1, r1BandEnd, top, bot);
26231                :                    Coalesce(newReg, prevBand, curBand);
26232                :                }
26233                :            }
26234                :            ytop = r2y1;
26235                :        } else if (r2y1 < r1y1) {
26236                :            if (appendNon2) {
26237                :                top = max(r2y1, ybot);
26238                :                bot = min(r2->y2, r1y1);
26239                :                if (top != bot) {
26240                :                    curBand = newReg->data->numRects;
26241                :                    miAppendNonO(newReg, r2, r2BandEnd, top, bot);
26242                :                    Coalesce(newReg, prevBand, curBand);
26243                :                }
26244                :            }
26245                :            ytop = r1y1;
26246                :        } else {
26247                :            ytop = r1y1;
26248                :        }
26249                :
26250                :        /*
26251                :         * Now see if we've hit an intersecting band. The two bands only
26252                :         * intersect if ybot > ytop
26253                :         */
26254                :        ybot = min(r1->y2, r2->y2);
26255                :        if (ybot > ytop) {
26256                :            curBand = newReg->data->numRects;
26257                :            (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,
26258                :                            pOverlap);
26259                :            Coalesce(newReg, prevBand, curBand);
26260                :        }
26261                :
26262                :        /*
26263                :         * If we've finished with a band (y2 == ybot) we skip forward
26264                :         * in the region to the next band.
26265                :         */
26266                :        if (r1->y2 == ybot) r1 = r1BandEnd;
26267                :        if (r2->y2 == ybot) r2 = r2BandEnd;
26268                :
26269                :    } while (r1 != r1End && r2 != r2End);
26270                :
26271                :    /*
26272                :     * Deal with whichever region (if any) still has rectangles left.
26273                :     *
26274                :     * We only need to worry about banding and coalescing for the very first
26275                :     * band left.  After that, we can just group all remaining boxes,
26276                :     * regardless of how many bands, into one final append to the list.
26277                :     */
26278                :
26279                :    if ((r1 != r1End) && appendNon1) {
26280                :        /* Do first nonOverlap1Func call, which may be able to coalesce */
26281                :        FindBand(r1, r1BandEnd, r1End, r1y1);
26282                :        curBand = newReg->data->numRects;
26283                :        miAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2);
26284                :        Coalesce(newReg, prevBand, curBand);
26285                :        /* Just append the rest of the boxes  */
26286                :        AppendRegions(newReg, r1BandEnd, r1End);
26287                :
26288                :    } else if ((r2 != r2End) && appendNon2) {
26289                :        /* Do first nonOverlap2Func call, which may be able to coalesce */
26290                :        FindBand(r2, r2BandEnd, r2End, r2y1);
26291                :        curBand = newReg->data->numRects;
26292                :        miAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2);
26293                :        Coalesce(newReg, prevBand, curBand);
26294                :        /* Append rest of boxes */
26295                :        AppendRegions(newReg, r2BandEnd, r2End);
26296                :    }
26297                :
26298                :    if (oldData)
26299                :        xfree(oldData);
26300                :
26301                :    if (!(numRects = newReg->data->numRects))
26302                :    {
26303                :        xfreeData(newReg);
26304                :        newReg->data = &miEmptyData;
26305                :    }
26306                :    else if (numRects == 1)
26307                :    {
26308                :        newReg->extents = *REGION_BOXPTR(newReg);
26309                :        xfreeData(newReg);
26310                :        newReg->data = (RegDataPtr)NULL;
26311                :    }
26312                :    else
26313                :    {
26314                :        DOWNSIZE(newReg, numRects);
26315                :    }
26316                :
26317                :    return TRUE;
26318                :}
26319                :
26320                :/*-
26321                : *-----------------------------------------------------------------------
26322                : * miSetExtents --
26323                : *      Reset the extents of a region to what they should be. Called by
26324                : *      miSubtract and miIntersect as they can't figure it out along the
26325                : *      way or do so easily, as miUnion can.
26326                : *
26327                : * Results:
26328                : *      None.
26329                : *
26330                : * Side Effects:
26331                : *      The region's 'extents' structure is overwritten.
26332                : *
26333                : *-----------------------------------------------------------------------
26334                : */
26335                :static void
26336                :miSetExtents (RegionPtr pReg)
26337                :{
26338                :    BoxPtr pBox, pBoxEnd;
26339                :
26340                :    if (!pReg->data)
26341                :        return;
26342                :    if (!pReg->data->size)
26343                :    {
26344                :        pReg->extents.x2 = pReg->extents.x1;
26345                :        pReg->extents.y2 = pReg->extents.y1;
26346                :        return;
26347                :    }
26348                :
26349                :    pBox = REGION_BOXPTR(pReg);
26350                :    pBoxEnd = REGION_END(pReg);
26351                :
26352                :    /*
26353                :     * Since pBox is the first rectangle in the region, it must have the
26354                :     * smallest y1 and since pBoxEnd is the last rectangle in the region,
26355                :     * it must have the largest y2, because of banding. Initialize x1 and
26356                :     * x2 from  pBox and pBoxEnd, resp., as good things to initialize them
26357                :     * to...
26358                :     */
26359                :    pReg->extents.x1 = pBox->x1;
26360                :    pReg->extents.y1 = pBox->y1;
26361                :    pReg->extents.x2 = pBoxEnd->x2;
26362                :    pReg->extents.y2 = pBoxEnd->y2;
26363                :
26364                :    assert(pReg->extents.y1 < pReg->extents.y2);
26365                :    while (pBox <= pBoxEnd) {
26366                :        if (pBox->x1 < pReg->extents.x1)
26367                :            pReg->extents.x1 = pBox->x1;
26368                :        if (pBox->x2 > pReg->extents.x2)
26369                :            pReg->extents.x2 = pBox->x2;
26370                :        pBox++;
26371                :    };
26372                :
26373                :    assert(pReg->extents.x1 < pReg->extents.x2);
26374                :}
26375                :
26376                :/*======================================================================
26377                : *          Region Intersection
26378                : *====================================================================*/
26379                :/*-
26380                : *-----------------------------------------------------------------------
26381                : * miIntersectO --
26382                : *      Handle an overlapping band for miIntersect.
26383                : *
26384                : * Results:
26385                : *      TRUE if successful.
26386                : *
26387                : * Side Effects:
26388                : *      Rectangles may be added to the region.
26389                : *
26390                : *-----------------------------------------------------------------------
26391                : */
26392                :/*ARGSUSED*/
26393                :_X_EXPORT Bool
26394                :miIntersect(newReg, reg1, reg2)
26395                :    RegionPtr   newReg;     /* destination Region */
26396                :    RegionPtr   reg1;
26397                :    RegionPtr   reg2;       /* source regions     */
26398      1  0.0011 :{ /* miIntersect total:      6  0.0065 */
26399      2  0.0022 :    return pixman_region_intersect (newReg, reg1, reg2);
26400      3  0.0033 :}
26401                :
26402                :#define MERGERECT(r)                                            \
26403                :{                                                               \
26404                :    if (r->x1 <= x2) {                                          \
26405                :        /* Merge with current rectangle */                      \
26406                :        if (r->x1 < x2) *pOverlap = TRUE;                               \
26407                :        if (x2 < r->x2) x2 = r->x2;                             \
26408                :    } else {                                                    \
26409                :        /* Add current rectangle, start new one */              \
26410                :        NEWRECT(pReg, pNextRect, x1, y1, x2, y2);               \
26411                :        x1 = r->x1;                                             \
26412                :        x2 = r->x2;                                             \
26413                :    }                                                           \
26414                :    r++;                                                        \
26415                :}
26416                :
26417                :/*======================================================================
26418                : *          Region Union
26419                : *====================================================================*/
26420                :
26421                :/*-
26422                : *-----------------------------------------------------------------------
26423                : * miUnionO --
26424                : *      Handle an overlapping band for the union operation. Picks the
26425                : *      left-most rectangle each time and merges it into the region.
26426                : *
26427                : * Results:
26428                : *      TRUE if successful.
26429                : *
26430                : * Side Effects:
26431                : *      pReg is overwritten.
26432                : *      pOverlap is set to TRUE if any boxes overlap.
26433                : *
26434                : *-----------------------------------------------------------------------
26435                : */
26436                :static Bool
26437                :miUnionO (
26438                :    RegionPtr   pReg,
26439                :    BoxPtr      r1,
26440                :    BoxPtr      r1End,
26441                :    BoxPtr      r2,
26442                :    BoxPtr      r2End,
26443                :    short       y1,
26444                :    short       y2,
26445                :    Bool        *pOverlap)
26446                :{
26447                :    BoxPtr     pNextRect;
26448                :    int        x1;     /* left and right side of current union */
26449                :    int        x2;
26450                :
26451                :    assert (y1 < y2);
26452                :    assert(r1 != r1End && r2 != r2End);
26453                :
26454                :    pNextRect = REGION_TOP(pReg);
26455                :
26456                :    /* Start off current rectangle */
26457                :    if (r1->x1 < r2->x1)
26458                :    {
26459                :        x1 = r1->x1;
26460                :        x2 = r1->x2;
26461                :        r1++;
26462                :    }
26463                :    else
26464                :    {
26465                :        x1 = r2->x1;
26466                :        x2 = r2->x2;
26467                :        r2++;
26468                :    }
26469                :    while (r1 != r1End && r2 != r2End)
26470                :    {
26471                :        if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
26472                :    }
26473                :
26474                :    /* Finish off whoever (if any) is left */
26475                :    if (r1 != r1End)
26476                :    {
26477                :        do
26478                :        {
26479                :            MERGERECT(r1);
26480                :        } while (r1 != r1End);
26481                :    }
26482                :    else if (r2 != r2End)
26483                :    {
26484                :        do
26485                :        {
26486                :            MERGERECT(r2);
26487                :        } while (r2 != r2End);
26488                :    }
26489                :    
26490                :    /* Add current rectangle */
26491                :    NEWRECT(pReg, pNextRect, x1, y1, x2, y2);
26492                :
26493                :    return TRUE;
26494                :}
26495                :
26496                :_X_EXPORT Bool 
26497                :miUnion(newReg, reg1, reg2)
26498                :    RegionPtr           newReg;                  /* destination Region */
26499                :    RegionPtr   reg1;
26500                :    RegionPtr   reg2;             /* source regions     */
26501     14  0.0153 :{ /* miUnion total:     27  0.0294 */
26502      2  0.0022 :    return pixman_region_union (newReg, reg1, reg2);
26503     11  0.0120 :}
26504                :
26505                :/*======================================================================
26506                : *          Batch Rectangle Union
26507                : *====================================================================*/
26508                :
26509                :/*-
26510                : *-----------------------------------------------------------------------
26511                : * miRegionAppend --
26512                : * 
26513                : *      "Append" the rgn rectangles onto the end of dstrgn, maintaining
26514                : *      knowledge of YX-banding when it's easy.  Otherwise, dstrgn just
26515                : *      becomes a non-y-x-banded random collection of rectangles, and not
26516                : *      yet a true region.  After a sequence of appends, the caller must
26517                : *      call miRegionValidate to ensure that a valid region is constructed.
26518                : *
26519                : * Results:
26520                : *      TRUE if successful.
26521                : *
26522                : * Side Effects:
26523                : *      dstrgn is modified if rgn has rectangles.
26524                : *
26525                : */
26526                :_X_EXPORT Bool
26527                :miRegionAppend(dstrgn, rgn)
26528                :    RegionPtr dstrgn;
26529                :    RegionPtr rgn;
26530                :{
26531                :    int numRects, dnumRects, size;
26532                :    BoxPtr new, old;
26533                :    Bool prepend;
26534                :
26535                :    if (REGION_NAR(rgn))
26536                :        return miRegionBreak (dstrgn);
26537                :    
26538                :    if (!rgn->data && (dstrgn->data == &miEmptyData))
26539                :    {
26540                :        dstrgn->extents = rgn->extents;
26541                :        dstrgn->data = (RegDataPtr)NULL;
26542                :        return TRUE;
26543                :    }
26544                :
26545                :    numRects = REGION_NUM_RECTS(rgn);
26546                :    if (!numRects)
26547                :        return TRUE;
26548                :    prepend = FALSE;
26549                :    size = numRects;
26550                :    dnumRects = REGION_NUM_RECTS(dstrgn);
26551                :    if (!dnumRects && (size < 200))
26552                :        size = 200; /* XXX pick numbers out of a hat */
26553                :    RECTALLOC(dstrgn, size);
26554                :    old = REGION_RECTS(rgn);
26555                :    if (!dnumRects)
26556                :        dstrgn->extents = rgn->extents;
26557                :    else if (dstrgn->extents.x2 > dstrgn->extents.x1)
26558                :    {
26559                :        BoxPtr first, last;
26560                :
26561                :        first = old;
26562                :        last = REGION_BOXPTR(dstrgn) + (dnumRects - 1);
26563                :        if ((first->y1 > last->y2) ||
26564                :            ((first->y1 == last->y1) && (first->y2 == last->y2) &&
26565                :             (first->x1 > last->x2)))
26566                :        {
26567                :            if (rgn->extents.x1 < dstrgn->extents.x1)
26568                :                dstrgn->extents.x1 = rgn->extents.x1;
26569                :            if (rgn->extents.x2 > dstrgn->extents.x2)
26570                :                dstrgn->extents.x2 = rgn->extents.x2;
26571                :            dstrgn->extents.y2 = rgn->extents.y2;
26572                :        }
26573                :        else
26574                :        {
26575                :            first = REGION_BOXPTR(dstrgn);
26576                :            last = old + (numRects - 1);
26577                :            if ((first->y1 > last->y2) ||
26578                :                ((first->y1 == last->y1) && (first->y2 == last->y2) &&
26579                :                 (first->x1 > last->x2)))
26580                :            {
26581                :                prepend = TRUE;
26582                :                if (rgn->extents.x1 < dstrgn->extents.x1)
26583                :                    dstrgn->extents.x1 = rgn->extents.x1;
26584                :                if (rgn->extents.x2 > dstrgn->extents.x2)
26585                :                    dstrgn->extents.x2 = rgn->extents.x2;
26586                :                dstrgn->extents.y1 = rgn->extents.y1;
26587                :            }
26588                :            else
26589                :                dstrgn->extents.x2 = dstrgn->extents.x1;
26590                :        }
26591                :    }
26592                :    if (prepend)
26593                :    {
26594                :        new = REGION_BOX(dstrgn, numRects);
26595                :        if (dnumRects == 1)
26596                :            *new = *REGION_BOXPTR(dstrgn);
26597                :        else
26598                :            memmove((char *)new,(char *)REGION_BOXPTR(dstrgn), 
26599                :                  dnumRects * sizeof(BoxRec));
26600                :        new = REGION_BOXPTR(dstrgn);
26601                :    }
26602                :    else
26603                :        new = REGION_BOXPTR(dstrgn) + dnumRects;
26604                :    if (numRects == 1)
26605                :        *new = *old;
26606                :    else
26607                :        memmove((char *)new, (char *)old, numRects * sizeof(BoxRec));
26608                :    dstrgn->data->numRects += numRects;
26609                :    return TRUE;
26610                :}
26611                :
26612                :   
26613                :#define ExchangeRects(a, b) \
26614                :{                           \
26615                :    BoxRec     t;           \
26616                :    t = rects[a];           \
26617                :    rects[a] = rects[b];    \
26618                :    rects[b] = t;           \
26619                :}
26620                :
26621                :static void
26622                :QuickSortRects(
26623                :    BoxRec     rects[],
26624                :    int        numRects)
26625                :{ /* QuickSortRects total:      1  0.0011 */
26626                :    int y1;
26627                :    int x1;
26628                :    int        i, j;
26629                :    BoxPtr     r;
26630                :
26631                :    /* Always called with numRects > 1 */
26632                :
26633                :    do
26634                :    {
26635                :        if (numRects == 2)
26636                :        {
26637      1  0.0011 :            if (rects[0].y1 > rects[1].y1 ||
26638                :                    (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
26639                :                ExchangeRects(0, 1);
26640                :            return;
26641                :        }
26642                :
26643                :        /* Choose partition element, stick in location 0 */
26644                :        ExchangeRects(0, numRects >> 1);
26645                :        y1 = rects[0].y1;
26646                :        x1 = rects[0].x1;
26647                :
26648                :        /* Partition array */
26649                :        i = 0;
26650                :        j = numRects;
26651                :        do
26652                :        {
26653                :            r = &(rects[i]);
26654                :            do
26655                :            {
26656                :                r++;
26657                :                i++;
26658                :            } while (i != numRects &&
26659                :                     (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
26660                :            r = &(rects[j]);
26661                :            do
26662                :            {
26663                :                r--;
26664                :                j--;
26665                :            } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
26666                :            if (i < j)
26667                :                ExchangeRects(i, j);
26668                :        } while (i < j);
26669                :
26670                :        /* Move partition element back to middle */
26671                :        ExchangeRects(0, j);
26672                :
26673                :        /* Recurse */
26674                :        if (numRects-j-1 > 1)
26675                :            QuickSortRects(&rects[j+1], numRects-j-1);
26676                :        numRects = j;
26677                :    } while (numRects > 1);
26678                :}
26679                :
26680                :/*-
26681                : *-----------------------------------------------------------------------
26682                : * miRegionValidate --
26683                : * 
26684                : *      Take a ``region'' which is a non-y-x-banded random collection of
26685                : *      rectangles, and compute a nice region which is the union of all the
26686                : *      rectangles.
26687                : *
26688                : * Results:
26689                : *      TRUE if successful.
26690                : *
26691                : * Side Effects:
26692                : *      The passed-in ``region'' may be modified.
26693                : *      pOverlap set to TRUE if any retangles overlapped, else FALSE;
26694                : *
26695                : * Strategy:
26696                : *      Step 1. Sort the rectangles into ascending order with primary key y1
26697                : *              and secondary key x1.
26698                : *
26699                : *      Step 2. Split the rectangles into the minimum number of proper y-x
26700                : *              banded regions.  This may require horizontally merging
26701                : *              rectangles, and vertically coalescing bands.  With any luck,
26702                : *              this step in an identity tranformation (ala the Box widget),
26703                : *              or a coalescing into 1 box (ala Menus).
26704                : *
26705                : *      Step 3. Merge the separate regions down to a single region by calling
26706                : *              miUnion.  Maximize the work each miUnion call does by using
26707                : *              a binary merge.
26708                : *
26709                : *-----------------------------------------------------------------------
26710                : */
26711                :
26712                :_X_EXPORT Bool
26713                :miRegionValidate(badreg, pOverlap)
26714                :    RegionPtr badreg;
26715                :    Bool *pOverlap;
26716      1  0.0011 :{ /* miRegionValidate total:      7  0.0076 */
26717                :    /* Descriptor for regions under construction  in Step 2. */
26718                :    typedef struct {
26719                :        RegionRec   reg;
26720                :        int         prevBand;
26721                :        int         curBand;
26722                :    } RegionInfo;
26723                :
26724                :    int numRects;   /* Original numRects for badreg         */
26725                :    RegionInfo *ri;         /* Array of current regions             */
26726                :    int numRI;      /* Number of entries used in ri         */
26727                :    int sizeRI;     /* Number of entries available in ri    */
26728                :    int i;          /* Index into rects                     */
26729                :    int j;          /* Index into ri                        */
26730                :    RegionInfo *rit;       /* &ri[j]                                */
26731                :    RegionPtr  reg;        /* ri[j].reg                     */
26732                :    BoxPtr      box;        /* Current box in rects                 */
26733                :    BoxPtr      riBox;      /* Last box in ri[j].reg                */
26734                :    RegionPtr  hreg;       /* ri[j_half].reg                        */
26735                :    Bool                ret = TRUE;
26736                :
26737                :    *pOverlap = FALSE;
26738                :    if (!badreg->data)
26739                :    {
26740                :        good(badreg);
26741                :        return TRUE;
26742                :    }
26743                :    numRects = badreg->data->numRects;
26744                :    if (!numRects)
26745                :    {
26746                :        if (REGION_NAR(badreg))
26747                :            return FALSE;
26748                :        good(badreg);
26749                :        return TRUE;
26750                :    }
26751      1  0.0011 :    if (badreg->extents.x1 < badreg->extents.x2)
26752                :    {
26753                :        if ((numRects) == 1)
26754                :        {
26755                :            xfreeData(badreg);
26756                :            badreg->data = (RegDataPtr) NULL;
26757                :        }
26758                :        else
26759                :        {
26760                :            DOWNSIZE(badreg, numRects);
26761                :        }
26762                :        good(badreg);
26763                :        return TRUE;
26764                :    }
26765                :
26766                :    /* Step 1: Sort the rects array into ascending (y1, x1) order */
26767                :    QuickSortRects(REGION_BOXPTR(badreg), numRects);
26768                :
26769                :    /* Step 2: Scatter the sorted array into the minimum number of regions */
26770                :
26771                :    /* Set up the first region to be the first rectangle in badreg */
26772                :    /* Note that step 2 code will never overflow the ri[0].reg rects array */
26773                :    ri = (RegionInfo *) xalloc(4 * sizeof(RegionInfo));
26774                :    if (!ri)
26775                :        return miRegionBreak (badreg);
26776                :    sizeRI = 4;
26777                :    numRI = 1;
26778                :    ri[0].prevBand = 0;
26779                :    ri[0].curBand = 0;
26780                :    ri[0].reg = *badreg;
26781                :    box = REGION_BOXPTR(&ri[0].reg);
26782                :    ri[0].reg.extents = *box;
26783                :    ri[0].reg.data->numRects = 1;
26784                :
26785                :    /* Now scatter rectangles into the minimum set of valid regions.  If the
26786                :       next rectangle to be added to a region would force an existing rectangle
26787                :       in the region to be split up in order to maintain y-x banding, just
26788                :       forget it.  Try the next region.  If it doesn't fit cleanly into any
26789                :       region, make a new one. */
26790                :
26791                :    for (i = numRects; --i > 0;)
26792                :    {
26793                :        box++;
26794                :        /* Look for a region to append box to */
26795                :        for (j = numRI, rit = ri; --j >= 0; rit++)
26796                :        {
26797                :            reg = &rit->reg;
26798                :            riBox = REGION_END(reg);
26799                :
26800                :            if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
26801                :            {
26802                :                /* box is in same band as riBox.  Merge or append it */
26803                :                if (box->x1 <= riBox->x2)
26804                :                {
26805                :                    /* Merge it with riBox */
26806                :                    if (box->x1 < riBox->x2) *pOverlap = TRUE;
26807                :                    if (box->x2 > riBox->x2) riBox->x2 = box->x2;
26808                :                }
26809                :                else
26810                :                {
26811                :                    RECTALLOC_BAIL(reg, 1, bail);
26812                :                    *REGION_TOP(reg) = *box;
26813                :                    reg->data->numRects++;
26814                :                }
26815                :                goto NextRect;   /* So sue me */
26816                :            }
26817      1  0.0011 :            else if (box->y1 >= riBox->y2)
26818                :            {
26819                :                /* Put box into new band */
26820                :                if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
26821                :                if (reg->extents.x1 > box->x1)   reg->extents.x1 = box->x1;
26822                :                Coalesce(reg, rit->prevBand, rit->curBand);
26823                :                rit->curBand = reg->data->numRects;
26824                :                RECTALLOC_BAIL(reg, 1, bail);
26825                :                *REGION_TOP(reg) = *box;
26826                :                reg->data->numRects++;
26827                :                goto NextRect;
26828                :            }
26829                :            /* Well, this region was inappropriate.  Try the next one. */
26830                :        } /* for j */
26831                :
26832                :        /* Uh-oh.  No regions were appropriate.  Create a new one. */
26833      1  0.0011 :        if (sizeRI == numRI)
26834                :        {
26835                :            /* Oops, allocate space for new region information */
26836                :            sizeRI <<= 1;
26837                :            rit = (RegionInfo *) xrealloc(ri, sizeRI * sizeof(RegionInfo));
26838                :            if (!rit)
26839                :                goto bail;
26840                :            ri = rit;
26841                :            rit = &ri[numRI];
26842                :        }
26843                :        numRI++;
26844                :        rit->prevBand = 0;
26845                :        rit->curBand = 0;
26846                :        rit->reg.extents = *box;
26847                :        rit->reg.data = (RegDataPtr)NULL;
26848                :        if (!miRectAlloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
26849                :            goto bail;
26850                :NextRect: ;
26851                :    } /* for i */
26852                :
26853                :    /* Make a final pass over each region in order to Coalesce and set
26854                :       extents.x2 and extents.y2 */
26855                :
26856                :    for (j = numRI, rit = ri; --j >= 0; rit++)
26857                :    {
26858                :        reg = &rit->reg;
26859                :        riBox = REGION_END(reg);
26860                :        reg->extents.y2 = riBox->y2;
26861                :        if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
26862                :        Coalesce(reg, rit->prevBand, rit->curBand);
26863                :        if (reg->data->numRects == 1) /* keep unions happy below */
26864                :        {
26865                :            xfreeData(reg);
26866                :            reg->data = (RegDataPtr)NULL;
26867                :        }
26868                :    }
26869                :
26870                :    /* Step 3: Union all regions into a single region */
26871      1  0.0011 :    while (numRI > 1)
26872                :    {
26873                :        int half = numRI/2;
26874                :        for (j = numRI & 1; j < (half + (numRI & 1)); j++)
26875                :        {
26876                :            reg = &ri[j].reg;
26877                :            hreg = &ri[j+half].reg;
26878                :            if (!miRegionOp(reg, reg, hreg, miUnionO, TRUE, TRUE, pOverlap))
26879                :                ret = FALSE;
26880                :            if (hreg->extents.x1 < reg->extents.x1)
26881                :                reg->extents.x1 = hreg->extents.x1;
26882                :            if (hreg->extents.y1 < reg->extents.y1)
26883                :                reg->extents.y1 = hreg->extents.y1;
26884                :            if (hreg->extents.x2 > reg->extents.x2)
26885                :                reg->extents.x2 = hreg->extents.x2;
26886      1  0.0011 :            if (hreg->extents.y2 > reg->extents.y2)
26887                :                reg->extents.y2 = hreg->extents.y2;
26888                :            xfreeData(hreg);
26889                :        }
26890                :        numRI -= half;
26891                :    }
26892                :    *badreg = ri[0].reg;
26893                :    xfree(ri);
26894                :    good(badreg);
26895                :    return ret;
26896                :bail:
26897                :    for (i = 0; i < numRI; i++)
26898                :        xfreeData(&ri[i].reg);
26899                :    xfree (ri);
26900                :    return miRegionBreak (badreg);
26901                :}
26902                :
26903                :_X_EXPORT RegionPtr
26904                :miRectsToRegion(nrects, prect, ctype)
26905                :    int                 nrects;
26906                :    xRectangle          *prect;
26907                :    int                 ctype;
26908      1  0.0011 :{ /* miRectsToRegion total:      8  0.0087 */
26909                :    
26910                :    RegionPtr           pRgn;
26911                :    RegDataPtr          pData;
26912                :    BoxPtr              pBox;
26913                :    int                 i;
26914                :    int                 x1, y1, x2, y2;
26915                :
26916                :    pRgn = miRegionCreate(NullBox, 0);
26917                :    if (REGION_NAR (pRgn))
26918                :        return pRgn;
26919      4  0.0044 :    if (!nrects)
26920                :        return pRgn;
26921                :    if (nrects == 1)
26922                :    {
26923                :        x1 = prect->x;
26924                :        y1 = prect->y;
26925      1  0.0011 :        if ((x2 = x1 + (int) prect->width) > MAXSHORT)
26926                :            x2 = MAXSHORT;
26927                :        if ((y2 = y1 + (int) prect->height) > MAXSHORT)
26928                :            y2 = MAXSHORT;
26929                :        if (x1 != x2 && y1 != y2)
26930                :        {
26931                :            pRgn->extents.x1 = x1;
26932                :            pRgn->extents.y1 = y1;
26933                :            pRgn->extents.x2 = x2;
26934                :            pRgn->extents.y2 = y2;
26935                :            pRgn->data = (RegDataPtr)NULL;
26936                :        }
26937                :        return pRgn;
26938                :    }
26939                :    pData = xallocData(nrects);
26940                :    if (!pData)
26941                :    {
26942                :        miRegionBreak (pRgn);
26943                :        return pRgn;
26944                :    }
26945                :    pBox = (BoxPtr) (pData + 1);
26946                :    for (i = nrects; --i >= 0; prect++)
26947                :    {
26948                :        x1 = prect->x;
26949                :        y1 = prect->y;
26950                :        if ((x2 = x1 + (int) prect->width) > MAXSHORT)
26951                :            x2 = MAXSHORT;
26952                :        if ((y2 = y1 + (int) prect->height) > MAXSHORT)
26953                :            y2 = MAXSHORT;
26954                :        if (x1 != x2 && y1 != y2)
26955                :        {
26956                :            pBox->x1 = x1;
26957                :            pBox->y1 = y1;
26958                :            pBox->x2 = x2;
26959                :            pBox->y2 = y2;
26960                :            pBox++;
26961                :        }
26962                :    }
26963      1  0.0011 :    if (pBox != (BoxPtr) (pData + 1))
26964                :    {
26965                :        pData->size = nrects;
26966                :        pData->numRects = pBox - (BoxPtr) (pData + 1);
26967                :        pRgn->data = pData;
26968                :        if (ctype != CT_YXBANDED)
26969                :        {
26970                :            Bool overlap; /* result ignored */
26971                :            pRgn->extents.x1 = pRgn->extents.x2 = 0;
26972                :            miRegionValidate(pRgn, &overlap);
26973                :        }
26974                :        else
26975                :            miSetExtents(pRgn);
26976                :        good(pRgn);
26977                :    }
26978                :    else
26979                :    {
26980                :        xfree (pData);
26981                :    }
26982                :    return pRgn;
26983      1  0.0011 :}
26984                :
26985                :/*======================================================================
26986                : *                Region Subtraction
26987                : *====================================================================*/
26988                :
26989                :
26990                :/*-
26991                : *-----------------------------------------------------------------------
26992                : * miSubtractO --
26993                : *      Overlapping band subtraction. x1 is the left-most point not yet
26994                : *      checked.
26995                : *
26996                : * Results:
26997                : *      TRUE if successful.
26998                : *
26999                : * Side Effects:
27000                : *      pReg may have rectangles added to it.
27001                : *
27002                : *-----------------------------------------------------------------------
27003                : */
27004                :/*ARGSUSED*/
27005                :
27006                :/*-
27007                : *-----------------------------------------------------------------------
27008                : * miSubtract --
27009                : *      Subtract regS from regM and leave the result in regD.
27010                : *      S stands for subtrahend, M for minuend and D for difference.
27011                : *
27012                : * Results:
27013                : *      TRUE if successful.
27014                : *
27015                : * Side Effects:
27016                : *      regD is overwritten.
27017                : *
27018                : *-----------------------------------------------------------------------
27019                : */
27020                :_X_EXPORT Bool
27021                :miSubtract(regD, regM, regS)
27022                :    RegionPtr   regD;               
27023                :    RegionPtr   regM;
27024                :    RegionPtr   regS;          
27025                :{
27026                :    return pixman_region_subtract (regD, regM, regS);
27027                :}
27028                :
27029                :/*======================================================================
27030                : *          Region Inversion
27031                : *====================================================================*/
27032                :
27033                :/*-
27034                : *-----------------------------------------------------------------------
27035                : * miInverse --
27036                : *      Take a region and a box and return a region that is everything
27037                : *      in the box but not in the region. The careful reader will note
27038                : *      that this is the same as subtracting the region from the box...
27039                : *
27040                : * Results:
27041                : *      TRUE.
27042                : *
27043                : * Side Effects:
27044                : *      newReg is overwritten.
27045                : *
27046                : *-----------------------------------------------------------------------
27047                : */
27048                :_X_EXPORT Bool
27049                :miInverse(newReg, reg1, invRect)
27050                :    RegionPtr     newReg;       /* Destination region */
27051                :    RegionPtr     reg1;         /* Region to invert */
27052                :    BoxPtr        invRect;      /* Bounding box for inversion */
27053                :{
27054                :    return pixman_region_inverse (newReg, reg1, invRect);
27055                :}
27056                :_X_EXPORT int
27057                :miRectIn(region, prect)
27058                :    RegionPtr  region;
27059                :    BoxPtr     prect;
27060                :{
27061                :    return pixman_region_contains_rectangle (region, prect);
27062                :}
27063                :
27064                :/* TranslateRegion(pReg, x, y)
27065                :   translates in place
27066                :*/
27067                :
27068                :_X_EXPORT void
27069                :miTranslateRegion(pReg, x, y)
27070                :    RegionPtr pReg;
27071                :    int x;
27072                :    int y;
27073      2  0.0022 :{ /* miTranslateRegion total:      2  0.0022 */
27074                :    pixman_region_translate (pReg, x, y);
27075                :}
27076                :
27077                :_X_EXPORT void
27078                :miRegionReset(pReg, pBox)
27079                :    RegionPtr pReg;
27080                :    BoxPtr pBox;
27081                :{
27082                :    pixman_region_reset (pReg, pBox);
27083                :}
27084                :
27085                :_X_EXPORT Bool
27086                :miPointInRegion(pReg, x, y, box)
27087                :    RegionPtr pReg;
27088                :    int x, y;
27089                :    BoxPtr box;     /* "return" value */
27090                :{
27091                :    return pixman_region_contains_point (pReg, x, y, box);
27092                :}
27093                :
27094                :_X_EXPORT Bool
27095                :miRegionNotEmpty(pReg)
27096                :    RegionPtr pReg;
27097                :{
27098                :    return pixman_region_not_empty (pReg);
27099                :}
27100                :
27101                :Bool
27102                :miRegionBroken(RegionPtr pReg)
27103                :{
27104                :    good(pReg);
27105                :    return (REGION_NAR(pReg));
27106                :}
27107                :
27108                :_X_EXPORT void
27109                :miRegionEmpty(pReg)
27110                :    RegionPtr pReg;
27111                :{
27112                :    good(pReg);
27113                :    xfreeData(pReg);
27114                :    pReg->extents.x2 = pReg->extents.x1;
27115                :    pReg->extents.y2 = pReg->extents.y1;
27116                :    pReg->data = &miEmptyData;
27117                :}
27118                :
27119                :_X_EXPORT BoxPtr
27120                :miRegionExtents(pReg)
27121                :    RegionPtr pReg;
27122                :{
27123                :    good(pReg);
27124                :    return(&pReg->extents);
27125                :}
27126                :
27127                :#define ExchangeSpans(a, b)                                 \
27128                :{                                                           \
27129                :    DDXPointRec tpt;                                        \
27130                :    int         tw;                                         \
27131                :                                                            \
27132                :    tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt;    \
27133                :    tw = widths[a]; widths[a] = widths[b]; widths[b] = tw;  \
27134                :}
27135                :
27136                :/* ||| I should apply the merge sort code to rectangle sorting above, and see
27137                :   if mapping time can be improved.  But right now I've been at work 12 hours,
27138                :   so forget it.
27139                :*/
27140                :
27141                :static void QuickSortSpans(
27142                :    DDXPointRec spans[],
27143                :    int         widths[],
27144                :    int         numSpans)
27145                :{
27146                :    int     y;
27147                :    int     i, j, m;
27148                :    DDXPointPtr    r;
27149                :
27150                :    /* Always called with numSpans > 1 */
27151                :    /* Sorts only by y, doesn't bother to sort by x */
27152                :
27153                :    do
27154                :    {
27155                :        if (numSpans < 9)
27156                :        {
27157                :            /* Do insertion sort */
27158                :            int yprev;
27159                :
27160                :            yprev = spans[0].y;
27161                :            i = 1;
27162                :            do
27163                :            { /* while i != numSpans */
27164                :                y = spans[i].y;
27165                :                if (yprev > y)
27166                :                {
27167                :                    /* spans[i] is out of order.  Move into proper location. */
27168                :                    DDXPointRec tpt;
27169                :                    int     tw, k;
27170                :
27171                :                    for (j = 0; y >= spans[j].y; j++) {}
27172                :                    tpt = spans[i];
27173                :                    tw  = widths[i];
27174                :                    for (k = i; k != j; k--)
27175                :                    {
27176                :                        spans[k] = spans[k-1];
27177                :                        widths[k] = widths[k-1];
27178                :                    }
27179                :                    spans[j] = tpt;
27180                :                    widths[j] = tw;
27181                :                    y = spans[i].y;
27182                :                } /* if out of order */
27183                :                yprev = y;
27184                :                i++;
27185                :            } while (i != numSpans);
27186                :            return;
27187                :        }
27188                :
27189                :        /* Choose partition element, stick in location 0 */
27190                :        m = numSpans / 2;
27191                :        if (spans[m].y > spans[0].y)            ExchangeSpans(m, 0);
27192                :        if (spans[m].y > spans[numSpans-1].y)   ExchangeSpans(m, numSpans-1);
27193                :        if (spans[m].y > spans[0].y)            ExchangeSpans(m, 0);
27194                :        y = spans[0].y;
27195                :
27196                :        /* Partition array */
27197                :        i = 0;
27198                :        j = numSpans;
27199                :        do
27200                :        {
27201                :            r = &(spans[i]);
27202                :            do
27203                :            {
27204                :                r++;
27205                :                i++;
27206                :            } while (i != numSpans && r->y < y);
27207                :            r = &(spans[j]);
27208                :            do
27209                :            {
27210                :                r--;
27211                :                j--;
27212                :            } while (y < r->y);
27213                :            if (i < j)
27214                :                ExchangeSpans(i, j);
27215                :        } while (i < j);
27216                :
27217                :        /* Move partition element back to middle */
27218                :        ExchangeSpans(0, j);
27219                :
27220                :        /* Recurse */
27221                :        if (numSpans-j-1 > 1)
27222                :            QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
27223                :        numSpans = j;
27224                :    } while (numSpans > 1);
27225                :}
27226                :
27227                :#define NextBand()                                                  \
27228                :{                                                                   \
27229                :    clipy1 = pboxBandStart->y1;                                     \
27230                :    clipy2 = pboxBandStart->y2;                                     \
27231                :    pboxBandEnd = pboxBandStart + 1;                                \
27232                :    while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) {  \
27233                :        pboxBandEnd++;                                              \
27234                :    }                                                               \
27235                :    for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \
27236                :}
27237                :
27238                :/*
27239                :    Clip a list of scanlines to a region.  The caller has allocated the
27240                :    space.  FSorted is non-zero if the scanline origins are in ascending
27241                :    order.
27242                :    returns the number of new, clipped scanlines.
27243                :*/
27244                :
27245                :_X_EXPORT int
27246                :miClipSpans(
27247                :    RegionPtr   prgnDst,
27248                :    DDXPointPtr ppt,
27249                :    int         *pwidth,
27250                :    int         nspans,
27251                :    DDXPointPtr pptNew,
27252                :    int         *pwidthNew,
27253                :    int         fSorted)
27254                :{
27255                :    DDXPointPtr pptLast;
27256                :    int *pwidthNewStart;        /* the vengeance of Xerox! */
27257                :    int y, x1, x2;
27258                :    int numRects;
27259                :
27260                :    good(prgnDst);
27261                :    pptLast = ppt + nspans;
27262                :    pwidthNewStart = pwidthNew;
27263                :
27264                :    if (!prgnDst->data)
27265                :    {
27266                :        /* Do special fast code with clip boundaries in registers(?) */
27267                :        /* It doesn't pay much to make use of fSorted in this case, 
27268                :           so we lump everything together. */
27269                :
27270                :        int clipx1, clipx2, clipy1, clipy2;
27271                :
27272                :        clipx1 = prgnDst->extents.x1;
27273                :        clipy1 = prgnDst->extents.y1;
27274                :        clipx2 = prgnDst->extents.x2;
27275                :        clipy2 = prgnDst->extents.y2;
27276                :            
27277                :        for (; ppt != pptLast; ppt++, pwidth++)
27278                :        {
27279                :            y = ppt->y;
27280                :            x1 = ppt->x;
27281                :            if (clipy1 <= y && y < clipy2)
27282                :            {
27283                :                x2 = x1 + *pwidth;
27284                :                if (x1 < clipx1)    x1 = clipx1;
27285                :                if (x2 > clipx2)    x2 = clipx2;
27286                :                if (x1 < x2)
27287                :                {
27288                :                    /* part of span in clip rectangle */
27289                :                    pptNew->x = x1;
27290                :                    pptNew->y = y;
27291                :                    *pwidthNew = x2 - x1;
27292                :                    pptNew++;
27293                :                    pwidthNew++;
27294                :                }
27295                :            }
27296                :        } /* end for */
27297                :
27298                :    }
27299                :    else if ((numRects = prgnDst->data->numRects))
27300                :    {
27301                :        /* Have to clip against many boxes */
27302                :        BoxPtr pboxBandStart, pboxBandEnd;
27303                :        BoxPtr pbox;
27304                :        BoxPtr pboxLast;
27305                :        int clipy1, clipy2;
27306                :
27307                :        /* In this case, taking advantage of sorted spans gains more than
27308                :           the sorting costs. */
27309                :        if ((! fSorted) && (nspans > 1))
27310                :            QuickSortSpans(ppt, pwidth, nspans);
27311                :
27312                :        pboxBandStart = REGION_BOXPTR(prgnDst);
27313                :        pboxLast = pboxBandStart + numRects;
27314                :    
27315                :        NextBand();
27316                :
27317                :        for (; ppt != pptLast; )
27318                :        {
27319                :            y = ppt->y;
27320                :            if (y < clipy2)
27321                :            {
27322                :                /* span is in the current band */
27323                :                pbox = pboxBandStart;
27324                :                x1 = ppt->x;
27325                :                x2 = x1 + *pwidth;
27326                :                do
27327                :                { /* For each box in band */
27328                :                    int newx1, newx2;
27329                :
27330                :                    newx1 = x1;
27331                :                    newx2 = x2;
27332                :                    if (newx1 < pbox->x1)   newx1 = pbox->x1;
27333                :                    if (newx2 > pbox->x2)   newx2 = pbox->x2;
27334                :                    if (newx1 < newx2)
27335                :                    {
27336                :                        /* Part of span in clip rectangle */
27337                :                        pptNew->x = newx1;
27338                :                        pptNew->y = y;
27339                :                        *pwidthNew = newx2 - newx1;
27340                :                        pptNew++;
27341                :                        pwidthNew++;
27342                :                    }
27343                :                    pbox++;
27344                :                } while (pbox != pboxBandEnd);
27345                :                ppt++;
27346                :                pwidth++;
27347                :            }
27348                :            else
27349                :            {
27350                :                /* Move to next band, adjust ppt as needed */
27351                :                pboxBandStart = pboxBandEnd;
27352                :                if (pboxBandStart == pboxLast)
27353                :                    break; /* We're completely done */
27354                :                NextBand();
27355                :            }
27356                :        }
27357                :    }
27358                :    return (pwidthNew - pwidthNewStart);
27359                :}
27360                :
27361                :/* find the band in a region with the most rectangles */
27362                :_X_EXPORT int
27363                :miFindMaxBand(prgn)
27364                :    RegionPtr prgn;
27365                :{
27366                :    int nbox;
27367                :    BoxPtr pbox;
27368                :    int nThisBand;
27369                :    int nMaxBand = 0;
27370                :    short yThisBand;
27371                :
27372                :    good(prgn);
27373                :    nbox = REGION_NUM_RECTS(prgn);
27374                :    pbox = REGION_RECTS(prgn);
27375                :
27376                :    while(nbox > 0)
27377                :    {
27378                :        yThisBand = pbox->y1;
27379                :        nThisBand = 0;
27380                :        while((nbox > 0) && (pbox->y1 == yThisBand))
27381                :        {
27382                :            nbox--;
27383                :            pbox++;
27384                :            nThisBand++;
27385                :        }
27386                :        if (nThisBand > nMaxBand)
27387                :            nMaxBand = nThisBand;
27388                :    }
27389                :    return (nMaxBand);
27390                :}
27391 /* 
27392  * Total samples for file : "malloc.c"
27393  * 
27394  *     65  0.0708
27395  */
27396
27397 <credited to line zero>     65  0.0708 :
27398  /* malloc_consolidate total:     65  0.0708 */
27399 /* 
27400  * Total samples for file : "/home/cworth/src/xorg/xserver/os/io.c"
27401  * 
27402  *     60  0.0654
27403  */
27404
27405
27406                :/***********************************************************
27407                :
27408                :Copyright 1987, 1989, 1998  The Open Group
27409                :
27410                :Permission to use, copy, modify, distribute, and sell this software and its
27411                :documentation for any purpose is hereby granted without fee, provided that
27412                :the above copyright notice appear in all copies and that both that
27413                :copyright notice and this permission notice appear in supporting
27414                :documentation.
27415                :
27416                :The above copyright notice and this permission notice shall be included in
27417                :all copies or substantial portions of the Software.
27418                :
27419                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27420                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27421                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
27422                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
27423                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27424                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27425                :
27426                :Except as contained in this notice, the name of The Open Group shall not be
27427                :used in advertising or otherwise to promote the sale, use or other dealings
27428                :in this Software without prior written authorization from The Open Group.
27429                :
27430                :
27431                :Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
27432                :
27433                :                        All Rights Reserved
27434                :
27435                :Permission to use, copy, modify, and distribute this software and its 
27436                :documentation for any purpose and without fee is hereby granted, 
27437                :provided that the above copyright notice appear in all copies and that
27438                :both that copyright notice and this permission notice appear in 
27439                :supporting documentation, and that the name of Digital not be
27440                :used in advertising or publicity pertaining to distribution of the
27441                :software without specific, written prior permission.  
27442                :
27443                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27444                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
27445                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
27446                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27447                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
27448                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27449                :SOFTWARE.
27450                :
27451                :
27452                :******************************************************************/
27453                :/*****************************************************************
27454                : * i/o functions
27455                : *
27456                : *   WriteToClient, ReadRequestFromClient
27457                : *   InsertFakeRequest, ResetCurrentRequest
27458                : *
27459                : *****************************************************************/
27460                :
27461                :#ifdef HAVE_DIX_CONFIG_H
27462                :#include <dix-config.h>
27463                :#endif
27464                :
27465                :#if 0
27466                :#define DEBUG_COMMUNICATION
27467                :#endif
27468                :#ifdef WIN32
27469                :#include <X11/Xwinsock.h>
27470                :#endif
27471                :#include <stdio.h>
27472                :#define XSERV_t
27473                :#define TRANS_SERVER
27474                :#define TRANS_REOPEN
27475                :#include <X11/Xtrans/Xtrans.h>
27476                :#include <X11/Xmd.h>
27477                :#include <errno.h>
27478                :#if !defined(WIN32)
27479                :#ifndef Lynx
27480                :#include <sys/uio.h>
27481                :#else
27482                :#include <uio.h>
27483                :#endif
27484                :#endif
27485                :#include <X11/X.h>
27486                :#define NEED_REPLIES
27487                :#include <X11/Xproto.h>
27488                :#include "os.h"
27489                :#include "osdep.h"
27490                :#include <X11/Xpoll.h>
27491                :#include "opaque.h"
27492                :#include "dixstruct.h"
27493                :#include "misc.h"
27494                :
27495                :_X_EXPORT CallbackListPtr       ReplyCallback;
27496                :_X_EXPORT CallbackListPtr       FlushCallback;
27497                :
27498                :static ConnectionInputPtr AllocateInputBuffer(void);
27499                :static ConnectionOutputPtr AllocateOutputBuffer(void);
27500                :static xReqPtr PeekNextRequest(xReqPtr req, ClientPtr client, Bool readmore);
27501                :static void SkipRequests(xReqPtr req, ClientPtr client, int numskipped);
27502                :
27503                :/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
27504                : * systems are broken and return EWOULDBLOCK when they should return EAGAIN
27505                : */
27506                :#ifndef WIN32
27507                :#if defined(EAGAIN) && defined(EWOULDBLOCK)
27508                :#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK)
27509                :#else
27510                :#ifdef EAGAIN
27511                :#define ETEST(err) (err == EAGAIN)
27512                :#else
27513                :#define ETEST(err) (err == EWOULDBLOCK)
27514                :#endif
27515                :#endif
27516                :#else /* WIN32 The socket errorcodes differ from the normal errors*/
27517                :#define ETEST(err) (err == EAGAIN || err == WSAEWOULDBLOCK)
27518                :#endif
27519                :
27520                :static Bool CriticalOutputPending;
27521                :static int timesThisConnection = 0;
27522                :static ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL;
27523                :static ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL;
27524                :static OsCommPtr AvailableInput = (OsCommPtr)NULL;
27525                :
27526                :#define get_req_len(req,cli) ((cli)->swapped ? \
27527                :                              lswaps((req)->length) : (req)->length)
27528                :
27529                :#ifdef BIGREQS
27530                :#include <X11/extensions/bigreqstr.h>
27531                :
27532                :#define get_big_req_len(req,cli) ((cli)->swapped ? \
27533                :                                  lswapl(((xBigReq *)(req))->length) : \
27534                :                                  ((xBigReq *)(req))->length)
27535                :#endif
27536                :
27537                :#define MAX_TIMES_PER         10
27538                :
27539                :/*
27540                : *   A lot of the code in this file manipulates a ConnectionInputPtr:
27541                : *
27542                : *    -----------------------------------------------
27543                : *   |------- bufcnt ------->|           |           |
27544                : *   |           |- gotnow ->|           |           |
27545                : *   |           |-------- needed ------>|           |
27546                : *   |-----------+--------- size --------+---------->|
27547                : *    -----------------------------------------------
27548                : *   ^           ^
27549                : *   |           |
27550                : *   buffer   bufptr
27551                : *
27552                : *  buffer is a pointer to the start of the buffer.
27553                : *  bufptr points to the start of the current request.
27554                : *  bufcnt counts how many bytes are in the buffer.
27555                : *  size is the size of the buffer in bytes.
27556                : *
27557                : *  In several of the functions, gotnow and needed are local variables
27558                : *  that do the following:
27559                : *
27560                : *  gotnow is the number of bytes of the request that we're
27561                : *  trying to read that are currently in the buffer.
27562                : *  Typically, gotnow = (buffer + bufcnt) - bufptr
27563                : *
27564                : *  needed = the length of the request that we're trying to
27565                : *  read.  Watch out: needed sometimes counts bytes and sometimes
27566                : *  counts CARD32's.
27567                : */
27568                :
27569                :
27570                :/*****************************************************************
27571                : * ReadRequestFromClient
27572                : *    Returns one request in client->requestBuffer.  The request
27573                : *    length will be in client->req_len.  Return status is:
27574                : *
27575                : *    > 0  if  successful, specifies length in bytes of the request
27576                : *    = 0  if  entire request is not yet available
27577                : *    < 0  if  client should be terminated
27578                : *
27579                : *    The request returned must be contiguous so that it can be
27580                : *    cast in the dispatcher to the correct request type.  Because requests
27581                : *    are variable length, ReadRequestFromClient() must look at the first 4
27582                : *    or 8 bytes of a request to determine the length (the request length is
27583                : *    in the 3rd and 4th bytes of the request unless it is a Big Request
27584                : *    (see the Big Request Extension), in which case the 3rd and 4th bytes
27585                : *    are zero and the following 4 bytes are the request length.
27586                : *
27587                : *    Note: in order to make the server scheduler (WaitForSomething())
27588                : *    "fair", the ClientsWithInput mask is used.  This mask tells which
27589                : *    clients have FULL requests left in their buffers.  Clients with
27590                : *    partial requests require a read.  Basically, client buffers
27591                : *    are drained before select() is called again.  But, we can't keep
27592                : *    reading from a client that is sending buckets of data (or has
27593                : *    a partial request) because others clients need to be scheduled.
27594                : *****************************************************************/
27595                :
27596                :#define YieldControl()                          \
27597                :        { isItTimeToYield = TRUE;               \
27598                :          timesThisConnection = 0; }
27599                :#define YieldControlNoInput()                   \
27600                :        { YieldControl();                       \
27601                :          FD_CLR(fd, &ClientsWithInput); }
27602                :#define YieldControlDeath()                     \
27603                :        { timesThisConnection = 0; }
27604                :
27605                :int
27606                :ReadRequestFromClient(ClientPtr client)
27607      2  0.0022 :{ /* ReadRequestFromClient total:     60  0.0654 */
27608      3  0.0033 :    OsCommPtr oc = (OsCommPtr)client->osPrivate;
27609                :    ConnectionInputPtr oci = oc->input;
27610                :    int fd = oc->fd;
27611                :    unsigned int gotnow, needed;
27612                :    int result;
27613                :    register xReq *request;
27614                :    Bool need_header;
27615                :#ifdef BIGREQS
27616                :    Bool move_header;
27617                :#endif
27618                :
27619                :    /* If an input buffer was empty, either free it if it is too big
27620                :     * or link it into our list of free input buffers.  This means that
27621                :     * different clients can share the same input buffer (at different
27622                :     * times).  This was done to save memory.
27623                :     */
27624                :
27625                :    if (AvailableInput)
27626                :    {
27627                :        if (AvailableInput != oc)
27628                :        {
27629                :            register ConnectionInputPtr aci = AvailableInput->input;
27630                :            if (aci->size > BUFWATERMARK)
27631                :            {
27632                :                xfree(aci->buffer);
27633                :                xfree(aci);
27634                :            }
27635                :            else
27636                :            {
27637                :                aci->next = FreeInputs;
27638                :                FreeInputs = aci;
27639                :            }
27640                :            AvailableInput->input = (ConnectionInputPtr)NULL;
27641                :        }
27642                :        AvailableInput = (OsCommPtr)NULL;
27643                :    }
27644                :
27645                :    /* make sure we have an input buffer */
27646                :
27647                :    if (!oci)
27648                :    {
27649                :        if ((oci = FreeInputs))
27650                :        {
27651                :            FreeInputs = oci->next;
27652                :        }
27653                :        else if (!(oci = AllocateInputBuffer()))
27654                :        {
27655                :            YieldControlDeath();
27656                :            return -1;
27657                :        }
27658                :        oc->input = oci;
27659                :    }
27660                :
27661                :    /* advance to start of next request */
27662                :
27663      3  0.0033 :    oci->bufptr += oci->lenLastReq;
27664                :
27665                :    need_header = FALSE;
27666                :#ifdef BIGREQS
27667                :    move_header = FALSE;
27668                :#endif
27669      6  0.0065 :    gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
27670      2  0.0022 :    if (gotnow < sizeof(xReq))
27671                :    {
27672                :        /* We don't have an entire xReq yet.  Can't tell how big
27673                :         * the request will be until we get the whole xReq.
27674                :         */
27675                :        needed = sizeof(xReq);
27676                :        need_header = TRUE;
27677                :    }
27678                :    else
27679                :    {
27680                :        /* We have a whole xReq.  We can tell how big the whole
27681                :         * request will be unless it is a Big Request.
27682                :         */
27683                :        request = (xReq *)oci->bufptr;
27684      2  0.0022 :        needed = get_req_len(request, client);
27685                :#ifdef BIGREQS
27686      1  0.0011 :        if (!needed && client->big_requests)
27687                :        {
27688                :            /* It's a Big Request. */
27689                :            move_header = TRUE;
27690                :            if (gotnow < sizeof(xBigReq))
27691                :            {
27692                :                /* Still need more data to tell just how big. */
27693                :                needed = sizeof(xBigReq) >> 2; /* needed is in CARD32s now */
27694                :                need_header = TRUE;
27695                :            }
27696                :            else
27697                :                needed = get_big_req_len(request, client);
27698                :        }
27699                :#endif
27700      1  0.0011 :        client->req_len = needed;
27701                :        needed <<= 2; /* needed is in bytes now */
27702                :    }
27703                :    if (gotnow < needed)
27704                :    {
27705                :        /* Need to read more data, either so that we can get a
27706                :         * complete xReq (if need_header is TRUE), a complete
27707                :         * xBigReq (if move_header is TRUE), or the rest of the
27708                :         * request (if need_header and move_header are both FALSE).
27709                :         */
27710                :
27711                :        oci->lenLastReq = 0;
27712      2  0.0022 :        if (needed > MAXBUFSIZE)
27713                :        {
27714                :            /* request is too big for us to handle */
27715                :            YieldControlDeath();
27716                :            return -1;
27717                :        }
27718                :        if ((gotnow == 0) ||
27719                :            ((oci->bufptr - oci->buffer + needed) > oci->size))
27720                :        {
27721                :            /* no data, or the request is too big to fit in the buffer */
27722                :
27723                :            if ((gotnow > 0) && (oci->bufptr != oci->buffer))
27724                :                /* save the data we've already read */
27725                :                memmove(oci->buffer, oci->bufptr, gotnow);
27726                :            if (needed > oci->size)
27727                :            {
27728                :                /* make buffer bigger to accomodate request */
27729                :                char *ibuf;
27730                :
27731                :                ibuf = (char *)xrealloc(oci->buffer, needed);
27732                :                if (!ibuf)
27733                :                {
27734                :                    YieldControlDeath();
27735                :                    return -1;
27736                :                }
27737                :                oci->size = needed;
27738                :                oci->buffer = ibuf;
27739                :            }
27740                :            oci->bufptr = oci->buffer;
27741                :            oci->bufcnt = gotnow;
27742                :        }
27743                :        /*  XXX this is a workaround.  This function is sometimes called
27744                :         *  after the trans_conn has been freed.  In this case trans_conn
27745                :         *  will be null.  Really ought to restructure things so that we
27746                :         *  never get here in those circumstances.
27747                :         */
27748                :        if (!oc->trans_conn)
27749                :        {
27750                :            /*  treat as if an error occured on the read, which is what
27751                :             *  used to happen
27752                :             */
27753                :            YieldControlDeath();
27754                :            return -1;
27755                :        }
27756                :            result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt,
27757                :                                     oci->size - oci->bufcnt); 
27758                :        if (result <= 0)
27759                :        {
27760                :            if ((result < 0) && ETEST(errno))
27761                :            {
27762                :#if defined(SVR4) && defined(i386) && !defined(sun)
27763                :                if (0)
27764                :#endif
27765                :                {
27766                :                    YieldControlNoInput();
27767                :                    return 0;
27768                :                }
27769                :            }
27770                :            YieldControlDeath();
27771                :            return -1;
27772                :        }
27773                :        oci->bufcnt += result;
27774                :        gotnow += result;
27775                :        /* free up some space after huge requests */
27776                :        if ((oci->size > BUFWATERMARK) &&
27777                :            (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE))
27778                :        {
27779                :            char *ibuf;
27780                :
27781                :            ibuf = (char *)xrealloc(oci->buffer, BUFSIZE);
27782                :            if (ibuf)
27783                :            {
27784                :                oci->size = BUFSIZE;
27785                :                oci->buffer = ibuf;
27786                :                oci->bufptr = ibuf + oci->bufcnt - gotnow;
27787                :            }
27788                :        }
27789                :        if (need_header && gotnow >= needed)
27790                :        {
27791                :            /* We wanted an xReq, now we've gotten it. */
27792                :            request = (xReq *)oci->bufptr;
27793                :            needed = get_req_len(request, client);
27794                :#ifdef BIGREQS
27795                :            if (!needed && client->big_requests)
27796                :            {
27797                :                move_header = TRUE;
27798                :                if (gotnow < sizeof(xBigReq))
27799                :                    needed = sizeof(xBigReq) >> 2;
27800                :                else
27801                :                    needed = get_big_req_len(request, client);
27802                :            }
27803                :#endif
27804                :            client->req_len = needed;
27805                :            needed <<= 2;
27806                :        }
27807                :        if (gotnow < needed)
27808                :        {
27809                :            /* Still don't have enough; punt. */
27810                :            YieldControlNoInput();
27811                :            return 0;
27812                :        }
27813                :    }
27814      1  0.0011 :    if (needed == 0)
27815                :    {
27816                :#ifdef BIGREQS
27817                :        if (client->big_requests)
27818                :            needed = sizeof(xBigReq);
27819                :        else
27820                :#endif
27821                :            needed = sizeof(xReq);
27822                :    }
27823      3  0.0033 :    oci->lenLastReq = needed;
27824                :
27825                :    /*
27826                :     *  Check to see if client has at least one whole request in the
27827                :     *  buffer beyond the request we're returning to the caller.
27828                :     *  If there is only a partial request, treat like buffer
27829                :     *  is empty so that select() will be called again and other clients
27830                :     *  can get into the queue.   
27831                :     */
27832                :
27833      1  0.0011 :    gotnow -= needed;
27834                :    if (gotnow >= sizeof(xReq)) 
27835                :    {
27836      1  0.0011 :        request = (xReq *)(oci->bufptr + needed);
27837      9  0.0098 :        if (gotnow >= (result = (get_req_len(request, client) << 2))
27838                :#ifdef BIGREQS
27839                :            && (result ||
27840                :                (client->big_requests &&
27841                :                 (gotnow >= sizeof(xBigReq) &&
27842                :                  gotnow >= (get_big_req_len(request, client) << 2))))
27843                :#endif
27844                :            )
27845     11  0.0120 :            FD_SET(fd, &ClientsWithInput);
27846                :        else
27847                :        {
27848                :#ifdef SMART_SCHEDULE
27849      1  0.0011 :            if (!SmartScheduleDisable)
27850                :                FD_CLR(fd, &ClientsWithInput);
27851                :            else
27852                :#endif
27853                :                YieldControlNoInput();
27854                :        }
27855                :    }
27856                :    else
27857                :    {
27858                :        if (!gotnow)
27859                :            AvailableInput = oc;
27860                :#ifdef SMART_SCHEDULE
27861                :        if (!SmartScheduleDisable)
27862                :            FD_CLR(fd, &ClientsWithInput);
27863                :        else
27864                :#endif
27865                :            YieldControlNoInput();
27866                :    }
27867                :#ifdef SMART_SCHEDULE
27868      3  0.0033 :    if (SmartScheduleDisable)
27869                :#endif
27870                :    if (++timesThisConnection >= MAX_TIMES_PER)
27871                :        YieldControl();
27872                :#ifdef BIGREQS
27873                :    if (move_header)
27874                :    {
27875                :        request = (xReq *)oci->bufptr;
27876                :        oci->bufptr += (sizeof(xBigReq) - sizeof(xReq));
27877                :        *(xReq *)oci->bufptr = *request;
27878                :        oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq));
27879                :        client->req_len -= (sizeof(xBigReq) - sizeof(xReq)) >> 2;
27880                :    }
27881                :#endif
27882      3  0.0033 :    client->requestBuffer = (pointer)oci->bufptr;
27883                :#ifdef DEBUG_COMMUNICATION
27884                :    {
27885                :        xReq *req = client->requestBuffer;
27886                :        ErrorF("REQUEST: ClientIDX: %i, type: 0x%x data: 0x%x len: %i\n",
27887                :               client->index,req->reqType,req->data,req->length);
27888                :    }
27889                :#endif
27890                :    return needed;
27891      5  0.0054 :}
27892                :
27893                :/*****************************************************************
27894                : * InsertFakeRequest
27895                : *    Splice a consed up (possibly partial) request in as the next request.
27896                : *
27897                : **********************/
27898                :
27899                :Bool
27900                :InsertFakeRequest(ClientPtr client, char *data, int count)
27901                :{
27902                :    OsCommPtr oc = (OsCommPtr)client->osPrivate;
27903                :    ConnectionInputPtr oci = oc->input;
27904                :    int fd = oc->fd;
27905                :    int gotnow, moveup;
27906                :
27907                :    if (AvailableInput)
27908                :    {
27909                :        if (AvailableInput != oc)
27910                :        {
27911                :            ConnectionInputPtr aci = AvailableInput->input;
27912                :            if (aci->size > BUFWATERMARK)
27913                :            {
27914                :                xfree(aci->buffer);
27915                :                xfree(aci);
27916                :            }
27917                :            else
27918                :            {
27919                :                aci->next = FreeInputs;
27920                :                FreeInputs = aci;
27921                :            }
27922                :            AvailableInput->input = (ConnectionInputPtr)NULL;
27923                :        }
27924                :        AvailableInput = (OsCommPtr)NULL;
27925                :    }
27926                :    if (!oci)
27927                :    {
27928                :        if ((oci = FreeInputs))
27929                :            FreeInputs = oci->next;
27930                :        else if (!(oci = AllocateInputBuffer()))
27931                :            return FALSE;
27932                :        oc->input = oci;
27933                :    }
27934                :    oci->bufptr += oci->lenLastReq;
27935                :    oci->lenLastReq = 0;
27936                :    gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
27937                :    if ((gotnow + count) > oci->size)
27938                :    {
27939                :        char *ibuf;
27940                :
27941                :        ibuf = (char *)xrealloc(oci->buffer, gotnow + count);
27942                :        if (!ibuf)
27943                :            return(FALSE);
27944                :        oci->size = gotnow + count;
27945                :        oci->buffer = ibuf;
27946                :        oci->bufptr = ibuf + oci->bufcnt - gotnow;
27947                :    }
27948                :    moveup = count - (oci->bufptr - oci->buffer);
27949                :    if (moveup > 0)
27950                :    {
27951                :        if (gotnow > 0)
27952                :            memmove(oci->bufptr + moveup, oci->bufptr, gotnow);
27953                :        oci->bufptr += moveup;
27954                :        oci->bufcnt += moveup;
27955                :    }
27956                :    memmove(oci->bufptr - count, data, count);
27957                :    oci->bufptr -= count;
27958                :    gotnow += count;
27959                :    if ((gotnow >= sizeof(xReq)) &&
27960                :        (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2)))
27961                :        FD_SET(fd, &ClientsWithInput);
27962                :    else
27963                :        YieldControlNoInput();
27964                :    return(TRUE);
27965                :}
27966                :
27967                :/*****************************************************************
27968                : * ResetRequestFromClient
27969                : *    Reset to reexecute the current request, and yield.
27970                : *
27971                : **********************/
27972                :
27973                :_X_EXPORT void
27974                :ResetCurrentRequest(ClientPtr client)
27975                :{
27976                :    OsCommPtr oc = (OsCommPtr)client->osPrivate;
27977                :    register ConnectionInputPtr oci = oc->input;
27978                :    int fd = oc->fd;
27979                :    register xReq *request;
27980                :    int gotnow, needed;
27981                :    if (AvailableInput == oc)
27982                :        AvailableInput = (OsCommPtr)NULL;
27983                :    oci->lenLastReq = 0;
27984                :    gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
27985                :    if (gotnow < sizeof(xReq))
27986                :    {
27987                :        YieldControlNoInput();
27988                :    }
27989                :    else
27990                :    {
27991                :        request = (xReq *)oci->bufptr;
27992                :        needed = get_req_len(request, client);
27993                :#ifdef BIGREQS
27994                :        if (!needed && client->big_requests)
27995                :        {
27996                :            oci->bufptr -= sizeof(xBigReq) - sizeof(xReq);
27997                :            *(xReq *)oci->bufptr = *request;
27998                :            ((xBigReq *)oci->bufptr)->length = client->req_len;
27999                :            if (client->swapped)
28000                :            {
28001                :                char n;
28002                :                swapl(&((xBigReq *)oci->bufptr)->length, n);
28003                :            }
28004                :        }
28005                :#endif
28006                :        if (gotnow >= (needed << 2))
28007                :        {
28008                :            if (FD_ISSET(fd, &AllClients))
28009                :            {
28010                :                FD_SET(fd, &ClientsWithInput);
28011                :            }
28012                :            else
28013                :            {
28014                :                FD_SET(fd, &IgnoredClientsWithInput);
28015                :            }
28016                :            YieldControl();
28017                :        }
28018                :        else
28019                :            YieldControlNoInput();
28020                :    }
28021                :}
28022                :
28023                :
28024                :
28025                :/*****************************************************************
28026                : *  PeekNextRequest and SkipRequests were implemented to support DBE 
28027                : *  idioms, but can certainly be used outside of DBE.  There are two 
28028                : *  related macros in os.h, ReqLen and CastxReq.  See the porting 
28029                : *  layer document for more details.
28030                : *
28031                : **********************/
28032                :
28033                :
28034                :/*****************************************************************
28035                : *  PeekNextRequest
28036                : *      lets you look ahead at the unexecuted requests in a 
28037                : *      client's request buffer.
28038                : *
28039                : *      Note: this implementation of PeekNextRequest ignores the
28040                : *      readmore parameter.
28041                : *
28042                : **********************/
28043                :
28044                :static xReqPtr
28045                :PeekNextRequest(
28046                :    xReqPtr req,        /* request we're starting from */
28047                :    ClientPtr client,   /* client whose requests we're skipping */
28048                :    Bool readmore)      /* attempt to read more if next request isn't there? */
28049                :{
28050                :    register ConnectionInputPtr oci = ((OsCommPtr)client->osPrivate)->input;
28051                :    xReqPtr pnextreq;
28052                :    int needed, gotnow, reqlen;
28053                :
28054                :    if (!oci) return NULL;
28055                :
28056                :    if (!req)
28057                :    {
28058                :        /* caller wants the request after the one currently being executed */
28059                :        pnextreq = (xReqPtr)
28060                :            (((CARD32 *)client->requestBuffer) + client->req_len);
28061                :    }
28062                :    else
28063                :    {
28064                :        /* caller wants the request after the one specified by req */
28065                :        reqlen = get_req_len(req, client);
28066                :#ifdef BIGREQS
28067                :        if (!reqlen) reqlen = get_big_req_len(req, client);
28068                :#endif
28069                :        pnextreq = (xReqPtr)(((char *)req) + (reqlen << 2));
28070                :    }
28071                :
28072                :    /* see how much of the next request we have available */
28073                :
28074                :    gotnow = oci->bufcnt - (((char *)pnextreq) - oci->buffer);
28075                :
28076                :    if (gotnow < sizeof(xReq))
28077                :        return NULL;
28078                :
28079                :    needed = get_req_len(pnextreq, client) << 2;
28080                :#ifdef BIGREQS
28081                :    if (!needed)
28082                :    {
28083                :        /* it's a big request */
28084                :        if (gotnow < sizeof(xBigReq))
28085                :            return NULL;
28086                :        needed = get_big_req_len(pnextreq, client) << 2;
28087                :    }
28088                :#endif
28089                :
28090                :    /* if we have less than we need, return NULL */
28091                :
28092                :    return (gotnow < needed) ? NULL : pnextreq;
28093                :}
28094                :
28095                :/*****************************************************************
28096                : *  SkipRequests 
28097                : *      lets you skip over some of the requests in a client's
28098                : *      request buffer.  Presumably the caller has used PeekNextRequest
28099                : *      to examine the requests being skipped and has performed whatever 
28100                : *      actions they dictate.
28101                : *
28102                : **********************/
28103                :
28104                :_X_EXPORT CallbackListPtr SkippedRequestsCallback = NULL;
28105                :
28106                :static void
28107                :SkipRequests(
28108                :    xReqPtr req,        /* last request being skipped */
28109                :    ClientPtr client,   /* client whose requests we're skipping */
28110                :    int numskipped)     /* how many requests we're skipping */
28111                :{
28112                :    OsCommPtr oc = (OsCommPtr)client->osPrivate;
28113                :    register ConnectionInputPtr oci = oc->input;
28114                :    int reqlen;
28115                :
28116                :    /* see if anyone wants to snoop the skipped requests */
28117                :
28118                :    if (SkippedRequestsCallback)
28119                :    {
28120                :        SkippedRequestInfoRec skipinfo;
28121                :        skipinfo.req = req;
28122                :        skipinfo.client = client;
28123                :        skipinfo.numskipped = numskipped;
28124                :        CallCallbacks(&SkippedRequestsCallback, &skipinfo);
28125                :    }
28126                :
28127                :    /* adjust the sequence number */
28128                :    client->sequence += numskipped;
28129                :
28130                :    /* twiddle the oci to skip over the requests */
28131                :
28132                :    reqlen = get_req_len(req, client);
28133                :#ifdef BIGREQS
28134                :    if (!reqlen) reqlen = get_big_req_len(req, client);
28135                :#endif
28136                :    reqlen <<= 2;
28137                :    oci->bufptr = (char *)req;
28138                :    oci->lenLastReq = reqlen;
28139                :
28140                :    /* see if any requests left in the buffer */
28141                :
28142                :    if ( ((char *)req + reqlen) == (oci->buffer + oci->bufcnt) )
28143                :    {
28144                :        /* no requests; mark input buffer as available and client
28145                :         * as having no input
28146                :         */
28147                :        int fd = oc->fd;
28148                :        AvailableInput = oc;
28149                :        YieldControlNoInput();
28150                :    }
28151                :}
28152                :
28153                :
28154                :    /* lookup table for adding padding bytes to data that is read from
28155                :        or written to the X socket.  */
28156                :static int padlength[4] = {0, 3, 2, 1};
28157                :
28158                : /********************
28159                : * FlushAllOutput()
28160                : *    Flush all clients with output.  However, if some client still
28161                : *    has input in the queue (more requests), then don't flush.  This
28162                : *    will prevent the output queue from being flushed every time around
28163                : *    the round robin queue.  Now, some say that it SHOULD be flushed
28164                : *    every time around, but...
28165                : *
28166                : **********************/
28167                :
28168                :void
28169                :FlushAllOutput(void)
28170                :{
28171                :    register int index, base;
28172                :    register fd_mask mask; /* raphael */
28173                :    OsCommPtr oc;
28174                :    register ClientPtr client;
28175                :    Bool newoutput = NewOutputPending;
28176                :#if defined(WIN32)
28177                :    fd_set newOutputPending;
28178                :#endif
28179                :
28180                :    if (FlushCallback)
28181                :        CallCallbacks(&FlushCallback, NULL);
28182                :
28183                :    if (!newoutput)
28184                :        return;
28185                :
28186                :    /*
28187                :     * It may be that some client still has critical output pending,
28188                :     * but he is not yet ready to receive it anyway, so we will
28189                :     * simply wait for the select to tell us when he's ready to receive.
28190                :     */
28191                :    CriticalOutputPending = FALSE;
28192                :    NewOutputPending = FALSE;
28193                :
28194                :#ifndef WIN32
28195                :    for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++)
28196                :    {
28197                :        mask = OutputPending.fds_bits[ base ];
28198                :        OutputPending.fds_bits[ base ] = 0;
28199                :        while (mask)
28200                :        {
28201                :            index = ffs(mask) - 1;
28202                :            mask &= ~lowbit(mask);
28203                :            if ((index = ConnectionTranslation[(base * (sizeof(fd_mask)*8)) + index]) == 0)
28204                :                continue;
28205                :            client = clients[index];
28206                :            if (client->clientGone)
28207                :                continue;
28208                :            oc = (OsCommPtr)client->osPrivate;
28209                :            if (FD_ISSET(oc->fd, &ClientsWithInput))
28210                :            {
28211                :                FD_SET(oc->fd, &OutputPending); /* set the bit again */
28212                :                NewOutputPending = TRUE;
28213                :            }
28214                :            else
28215                :                (void)FlushClient(client, oc, (char *)NULL, 0);
28216                :        }
28217                :    }
28218                :#else  /* WIN32 */
28219                :    FD_ZERO(&newOutputPending);
28220                :    for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++)
28221                :    {
28222                :            index = XFD_FD(&OutputPending, base);
28223                :            if ((index = GetConnectionTranslation(index)) == 0)
28224                :                continue;
28225                :            client = clients[index];
28226                :            if (client->clientGone)
28227                :                continue;
28228                :            oc = (OsCommPtr)client->osPrivate;
28229                :            if (FD_ISSET(oc->fd, &ClientsWithInput))
28230                :            {
28231                :                FD_SET(oc->fd, &newOutputPending); /* set the bit again */
28232                :                NewOutputPending = TRUE;
28233                :            }
28234                :            else
28235                :                (void)FlushClient(client, oc, (char *)NULL, 0);
28236                :    }
28237                :    XFD_COPYSET(&newOutputPending, &OutputPending);
28238                :#endif /* WIN32 */
28239                :}
28240                :
28241                :void
28242                :FlushIfCriticalOutputPending(void)
28243                :{
28244                :    if (CriticalOutputPending)
28245                :        FlushAllOutput();
28246                :}
28247                :
28248                :_X_EXPORT void
28249                :SetCriticalOutputPending(void)
28250                :{
28251                :    CriticalOutputPending = TRUE;
28252                :}
28253                :
28254                :/*****************
28255                : * WriteToClient
28256                : *    Copies buf into ClientPtr.buf if it fits (with padding), else
28257                : *    flushes ClientPtr.buf and buf to client.  As of this writing,
28258                : *    every use of WriteToClient is cast to void, and the result
28259                : *    is ignored.  Potentially, this could be used by requests
28260                : *    that are sending several chunks of data and want to break
28261                : *    out of a loop on error.  Thus, we will leave the type of
28262                : *    this routine as int.
28263                : *****************/
28264                :
28265                :_X_EXPORT int
28266                :WriteToClient (ClientPtr who, int count, char *buf)
28267                :{
28268                :    OsCommPtr oc = (OsCommPtr)who->osPrivate;
28269                :    ConnectionOutputPtr oco = oc->output;
28270                :    int padBytes;
28271                :#ifdef DEBUG_COMMUNICATION
28272                :    Bool multicount = FALSE;
28273                :#endif
28274                :    if (!count)
28275                :        return(0);
28276                :#ifdef DEBUG_COMMUNICATION
28277                :    {
28278                :        char info[128];
28279                :        xError *err;
28280                :        xGenericReply *rep;
28281                :        xEvent *ev;
28282                :        
28283                :        if (!who->replyBytesRemaining) {
28284                :            switch(buf[0]) {
28285                :            case X_Reply:
28286                :                rep = (xGenericReply*)buf;
28287                :                if (rep->sequenceNumber == who->sequence) {
28288                :                    snprintf(info,127,"Xreply: type: 0x%x data: 0x%x "
28289                :                             "len: %i seq#: 0x%x", rep->type, rep->data1,
28290                :                             rep->length, rep->sequenceNumber);
28291                :                    multicount = TRUE;
28292                :                }
28293                :                break;
28294                :            case X_Error:
28295                :                err = (xError*)buf;
28296                :                snprintf(info,127,"Xerror: Code: 0x%x resID: 0x%x maj: 0x%x "
28297                :                         "min: %x", err->errorCode,err->resourceID,
28298                :                         err->minorCode,err->majorCode);
28299                :                break;
28300                :            default:
28301                :                if ((buf[0] & 0x7f) == KeymapNotify) 
28302                :                    snprintf(info,127,"KeymapNotifyEvent: %i",buf[0]);
28303                :                else {
28304                :                    ev = (xEvent*)buf;
28305                :                    snprintf(info,127,"XEvent: type: 0x%x detail: 0x%x "
28306                :                             "seq#: 0x%x",  ev->u.u.type, ev->u.u.detail,
28307                :                             ev->u.u.sequenceNumber);
28308                :                }
28309                :            }
28310                :            ErrorF("REPLY: ClientIDX: %i %s\n",who->index, info);
28311                :        } else
28312                :            multicount = TRUE;
28313                :    }
28314                :#endif
28315                :
28316                :    if (!oco)
28317                :    {
28318                :        if ((oco = FreeOutputs))
28319                :        {
28320                :            FreeOutputs = oco->next;
28321                :        }
28322                :        else if (!(oco = AllocateOutputBuffer()))
28323                :        {
28324                :            if (oc->trans_conn) {
28325                :                _XSERVTransDisconnect(oc->trans_conn);
28326                :                _XSERVTransClose(oc->trans_conn);
28327                :                oc->trans_conn = NULL;
28328                :            }
28329                :            MarkClientException(who);
28330                :            return -1;
28331                :        }
28332                :        oc->output = oco;
28333                :    }
28334                :
28335                :    padBytes = padlength[count & 3];
28336                :
28337                :    if(ReplyCallback)
28338                :    {
28339                :        ReplyInfoRec replyinfo;
28340                :
28341                :        replyinfo.client = who;
28342                :        replyinfo.replyData = buf;
28343                :        replyinfo.dataLenBytes = count + padBytes;
28344                :        if (who->replyBytesRemaining)
28345                :        { /* still sending data of an earlier reply */
28346                :            who->replyBytesRemaining -= count + padBytes;
28347                :            replyinfo.startOfReply = FALSE;
28348                :            replyinfo.bytesRemaining = who->replyBytesRemaining;
28349                :            CallCallbacks((&ReplyCallback), (pointer)&replyinfo);
28350                :        }
28351                :        else if (who->clientState == ClientStateRunning
28352                :                 && buf[0] == X_Reply)
28353                :        { /* start of new reply */
28354                :            CARD32 replylen;
28355                :            unsigned long bytesleft;
28356                :            char n;
28357                :
28358                :            replylen = ((xGenericReply *)buf)->length;
28359                :            if (who->swapped)
28360                :                swapl(&replylen, n);
28361                :            bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes;
28362                :            replyinfo.startOfReply = TRUE;
28363                :            replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft;
28364                :            CallCallbacks((&ReplyCallback), (pointer)&replyinfo);
28365                :        }                             
28366                :    }
28367                :#ifdef DEBUG_COMMUNICATION
28368                :    else if (multicount) {
28369                :        if (who->replyBytesRemaining) {
28370                :            who->replyBytesRemaining -= (count + padBytes);
28371                :        } else {
28372                :            CARD32 replylen;
28373                :            replylen = ((xGenericReply *)buf)->length;
28374                :            who->replyBytesRemaining =
28375                :                (replylen * 4) + SIZEOF(xReply) - count - padBytes;
28376                :        }
28377                :    }
28378                :#endif
28379                :    if (oco->count + count + padBytes > oco->size)
28380                :    {
28381                :        FD_CLR(oc->fd, &OutputPending);
28382                :        if(!XFD_ANYSET(&OutputPending)) {
28383                :          CriticalOutputPending = FALSE;
28384                :          NewOutputPending = FALSE;
28385                :        }
28386                :        return FlushClient(who, oc, buf, count);
28387                :    }
28388                :
28389                :    NewOutputPending = TRUE;
28390                :    FD_SET(oc->fd, &OutputPending);
28391                :    memmove((char *)oco->buf + oco->count, buf, count);
28392                :    oco->count += count + padBytes;
28393                :    return(count);
28394                :}
28395                :
28396                : /********************
28397                : * FlushClient()
28398                : *    If the client isn't keeping up with us, then we try to continue
28399                : *    buffering the data and set the apropriate bit in ClientsWritable
28400                : *    (which is used by WaitFor in the select).  If the connection yields
28401                : *    a permanent error, or we can't allocate any more space, we then
28402                : *    close the connection.
28403                : *
28404                : **********************/
28405                :
28406                :int
28407                :FlushClient(ClientPtr who, OsCommPtr oc, char *extraBuf, int extraCount)
28408                :{
28409                :    ConnectionOutputPtr oco = oc->output;
28410                :    int connection = oc->fd;
28411                :    XtransConnInfo trans_conn = oc->trans_conn;
28412                :    struct iovec iov[3];
28413                :    static char padBuffer[3];
28414                :    long written;
28415                :    long padsize;
28416                :    long notWritten;
28417                :    long todo;
28418                :
28419                :    if (!oco)
28420                :        return 0;
28421                :    written = 0;
28422                :    padsize = padlength[extraCount & 3];
28423                :    notWritten = oco->count + extraCount + padsize;
28424                :    todo = notWritten;
28425                :    while (notWritten) {
28426                :        long before = written;  /* amount of whole thing written */
28427                :        long remain = todo;     /* amount to try this time, <= notWritten */
28428                :        int i = 0;
28429                :        long len;
28430                :        
28431                :        /* You could be very general here and have "in" and "out" iovecs
28432                :         * and write a loop without using a macro, but what the heck.  This
28433                :         * translates to:
28434                :         *
28435                :         *     how much of this piece is new?
28436                :         *     if more new then we are trying this time, clamp
28437                :         *     if nothing new
28438                :         *         then bump down amount already written, for next piece
28439                :         *         else put new stuff in iovec, will need all of next piece
28440                :         *
28441                :         * Note that todo had better be at least 1 or else we'll end up
28442                :         * writing 0 iovecs.
28443                :         */
28444                :#define InsertIOV(pointer, length) \
28445                :        len = (length) - before; \
28446                :        if (len > remain) \
28447                :            len = remain; \
28448                :        if (len <= 0) { \
28449                :            before = (-len); \
28450                :        } else { \
28451                :            iov[i].iov_len = len; \
28452                :            iov[i].iov_base = (pointer) + before; \
28453                :            i++; \
28454                :            remain -= len; \
28455                :            before = 0; \
28456                :        }
28457                :
28458                :        InsertIOV ((char *)oco->buf, oco->count)
28459                :        InsertIOV (extraBuf, extraCount)
28460                :        InsertIOV (padBuffer, padsize)
28461                :
28462                :        errno = 0;
28463                :        if (trans_conn && (len = _XSERVTransWritev(trans_conn, iov, i)) >= 0)
28464                :        {
28465                :            written += len;
28466                :            notWritten -= len;
28467                :            todo = notWritten;
28468                :        }
28469                :        else if (ETEST(errno)
28470                :#ifdef SUNSYSV /* check for another brain-damaged OS bug */
28471                :                 || (errno == 0)
28472                :#endif
28473                :#ifdef EMSGSIZE /* check for another brain-damaged OS bug */
28474                :                 || ((errno == EMSGSIZE) && (todo == 1))
28475                :#endif
28476                :                )
28477                :        {
28478                :            /* If we've arrived here, then the client is stuffed to the gills
28479                :               and not ready to accept more.  Make a note of it and buffer
28480                :               the rest. */
28481                :            FD_SET(connection, &ClientsWriteBlocked);
28482                :            AnyClientsWriteBlocked = TRUE;
28483                :
28484                :            if (written < oco->count)
28485                :            {
28486                :                if (written > 0)
28487                :                {
28488                :                    oco->count -= written;
28489                :                    memmove((char *)oco->buf,
28490                :                            (char *)oco->buf + written,
28491                :                          oco->count);
28492                :                    written = 0;
28493                :                }
28494                :            }
28495                :            else
28496                :            {
28497                :                written -= oco->count;
28498                :                oco->count = 0;
28499                :            }
28500                :
28501                :            if (notWritten > oco->size)
28502                :            {
28503                :                unsigned char *obuf;
28504                :
28505                :                obuf = (unsigned char *)xrealloc(oco->buf,
28506                :                                                 notWritten + BUFSIZE);
28507                :                if (!obuf)
28508                :                {
28509                :                    _XSERVTransDisconnect(oc->trans_conn);
28510                :                    _XSERVTransClose(oc->trans_conn);
28511                :                    oc->trans_conn = NULL;
28512                :                    MarkClientException(who);
28513                :                    oco->count = 0;
28514                :                    return(-1);
28515                :                }
28516                :                oco->size = notWritten + BUFSIZE;
28517                :                oco->buf = obuf;
28518                :            }
28519                :
28520                :            /* If the amount written extended into the padBuffer, then the
28521                :               difference "extraCount - written" may be less than 0 */
28522                :            if ((len = extraCount - written) > 0)
28523                :                memmove ((char *)oco->buf + oco->count,
28524                :                         extraBuf + written,
28525                :                       len);
28526                :
28527                :            oco->count = notWritten; /* this will include the pad */
28528                :            /* return only the amount explicitly requested */
28529                :            return extraCount;
28530                :        }
28531                :#ifdef EMSGSIZE /* check for another brain-damaged OS bug */
28532                :        else if (errno == EMSGSIZE)
28533                :        {
28534                :            todo >>= 1;
28535                :        }
28536                :#endif
28537                :        else
28538                :        {
28539                :            if (oc->trans_conn)
28540                :            {
28541                :                _XSERVTransDisconnect(oc->trans_conn);
28542                :                _XSERVTransClose(oc->trans_conn);
28543                :                oc->trans_conn = NULL;
28544                :            }
28545                :            MarkClientException(who);
28546                :            oco->count = 0;
28547                :            return(-1);
28548                :        }
28549                :    }
28550                :
28551                :    /* everything was flushed out */
28552                :    oco->count = 0;
28553                :    /* check to see if this client was write blocked */
28554                :    if (AnyClientsWriteBlocked)
28555                :    {
28556                :        FD_CLR(oc->fd, &ClientsWriteBlocked);
28557                :        if (! XFD_ANYSET(&ClientsWriteBlocked))
28558                :            AnyClientsWriteBlocked = FALSE;
28559                :    }
28560                :    if (oco->size > BUFWATERMARK)
28561                :    {
28562                :        xfree(oco->buf);
28563                :        xfree(oco);
28564                :    }
28565                :    else
28566                :    {
28567                :        oco->next = FreeOutputs;
28568                :        FreeOutputs = oco;
28569                :    }
28570                :    oc->output = (ConnectionOutputPtr)NULL;
28571                :    return extraCount; /* return only the amount explicitly requested */
28572                :}
28573                :
28574                :static ConnectionInputPtr
28575                :AllocateInputBuffer(void)
28576                :{
28577                :    ConnectionInputPtr oci;
28578                :
28579                :    oci = (ConnectionInputPtr)xalloc(sizeof(ConnectionInput));
28580                :    if (!oci)
28581                :        return (ConnectionInputPtr)NULL;
28582                :    oci->buffer = (char *)xalloc(BUFSIZE);
28583                :    if (!oci->buffer)
28584                :    {
28585                :        xfree(oci);
28586                :        return (ConnectionInputPtr)NULL;
28587                :    }
28588                :    oci->size = BUFSIZE;
28589                :    oci->bufptr = oci->buffer;
28590                :    oci->bufcnt = 0;
28591                :    oci->lenLastReq = 0;
28592                :    return oci;
28593                :}
28594                :
28595                :static ConnectionOutputPtr
28596                :AllocateOutputBuffer(void)
28597                :{
28598                :    ConnectionOutputPtr oco;
28599                :
28600                :    oco = (ConnectionOutputPtr)xalloc(sizeof(ConnectionOutput));
28601                :    if (!oco)
28602                :        return (ConnectionOutputPtr)NULL;
28603                :    oco->buf = (unsigned char *) xalloc(BUFSIZE);
28604                :    if (!oco->buf)
28605                :    {
28606                :        xfree(oco);
28607                :        return (ConnectionOutputPtr)NULL;
28608                :    }
28609                :    oco->size = BUFSIZE;
28610                :    oco->count = 0;
28611                :    return oco;
28612                :}
28613                :
28614                :void
28615                :FreeOsBuffers(OsCommPtr oc)
28616                :{
28617                :    ConnectionInputPtr oci;
28618                :    ConnectionOutputPtr oco;
28619                :
28620                :    if (AvailableInput == oc)
28621                :        AvailableInput = (OsCommPtr)NULL;
28622                :    if ((oci = oc->input))
28623                :    {
28624                :        if (FreeInputs)
28625                :        {
28626                :            xfree(oci->buffer);
28627                :            xfree(oci);
28628                :        }
28629                :        else
28630                :        {
28631                :            FreeInputs = oci;
28632                :            oci->next = (ConnectionInputPtr)NULL;
28633                :            oci->bufptr = oci->buffer;
28634                :            oci->bufcnt = 0;
28635                :            oci->lenLastReq = 0;
28636                :        }
28637                :    }
28638                :    if ((oco = oc->output))
28639                :    {
28640                :        if (FreeOutputs)
28641                :        {
28642                :            xfree(oco->buf);
28643                :            xfree(oco);
28644                :        }
28645                :        else
28646                :        {
28647                :            FreeOutputs = oco;
28648                :            oco->next = (ConnectionOutputPtr)NULL;
28649                :            oco->count = 0;
28650                :        }
28651                :    }
28652                :}
28653                :
28654                :void
28655                :ResetOsBuffers(void)
28656                :{
28657                :    ConnectionInputPtr oci;
28658                :    ConnectionOutputPtr oco;
28659                :
28660                :    while ((oci = FreeInputs))
28661                :    {
28662                :        FreeInputs = oci->next;
28663                :        xfree(oci->buffer);
28664                :        xfree(oci);
28665                :    }
28666                :    while ((oco = FreeOutputs))
28667                :    {
28668                :        FreeOutputs = oco->next;
28669                :        xfree(oco->buf);
28670                :        xfree(oco);
28671                :    }
28672                :}
28673 /* 
28674  * Total samples for file : "/home/cworth/src/xorg/xserver/dix/dispatch.c"
28675  * 
28676  *     60  0.0654
28677  */
28678
28679
28680                :/************************************************************
28681                :
28682                :Copyright 1987, 1989, 1998  The Open Group
28683                :
28684                :Permission to use, copy, modify, distribute, and sell this software and its
28685                :documentation for any purpose is hereby granted without fee, provided that
28686                :the above copyright notice appear in all copies and that both that
28687                :copyright notice and this permission notice appear in supporting
28688                :documentation.
28689                :
28690                :The above copyright notice and this permission notice shall be included in
28691                :all copies or substantial portions of the Software.
28692                :
28693                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28694                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28695                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
28696                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
28697                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28698                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28699                :
28700                :Except as contained in this notice, the name of The Open Group shall not be
28701                :used in advertising or otherwise to promote the sale, use or other dealings
28702                :in this Software without prior written authorization from The Open Group.
28703                :
28704                :
28705                :Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
28706                :
28707                :                        All Rights Reserved
28708                :
28709                :Permission to use, copy, modify, and distribute this software and its 
28710                :documentation for any purpose and without fee is hereby granted, 
28711                :provided that the above copyright notice appear in all copies and that
28712                :both that copyright notice and this permission notice appear in 
28713                :supporting documentation, and that the name of Digital not be
28714                :used in advertising or publicity pertaining to distribution of the
28715                :software without specific, written prior permission.  
28716                :
28717                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
28718                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
28719                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
28720                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
28721                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28722                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28723                :SOFTWARE.
28724                :
28725                :********************************************************/
28726                :
28727                :/* The panoramix components contained the following notice */
28728                :/*****************************************************************
28729                :
28730                :Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
28731                :
28732                :Permission is hereby granted, free of charge, to any person obtaining a copy
28733                :of this software and associated documentation files (the "Software"), to deal
28734                :in the Software without restriction, including without limitation the rights
28735                :to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28736                :copies of the Software.
28737                :
28738                :The above copyright notice and this permission notice shall be included in
28739                :all copies or substantial portions of the Software.
28740                :
28741                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28742                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28743                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
28744                :DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
28745                :BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
28746                :WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
28747                :IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28748                :
28749                :Except as contained in this notice, the name of Digital Equipment Corporation
28750                :shall not be used in advertising or otherwise to promote the sale, use or other
28751                :dealings in this Software without prior written authorization from Digital
28752                :Equipment Corporation.
28753                :
28754                :******************************************************************/
28755                :
28756                :/* XSERVER_DTRACE additions:
28757                : * Copyright 2005-2006 Sun Microsystems, Inc.  All rights reserved.
28758                : *
28759                : * Permission is hereby granted, free of charge, to any person obtaining a
28760                : * copy of this software and associated documentation files (the
28761                : * "Software"), to deal in the Software without restriction, including
28762                : * without limitation the rights to use, copy, modify, merge, publish,
28763                : * distribute, and/or sell copies of the Software, and to permit persons
28764                : * to whom the Software is furnished to do so, provided that the above
28765                : * copyright notice(s) and this permission notice appear in all copies of
28766                : * the Software and that both the above copyright notice(s) and this
28767                : * permission notice appear in supporting documentation.
28768                : * 
28769                : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28770                : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28771                : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
28772                : * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
28773                : * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
28774                : * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
28775                : * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
28776                : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
28777                : * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28778                : * 
28779                : * Except as contained in this notice, the name of a copyright holder
28780                : * shall not be used in advertising or otherwise to promote the sale, use
28781                : * or other dealings in this Software without prior written authorization
28782                : * of the copyright holder.
28783                : */
28784                :
28785                :
28786                :
28787                :#ifdef HAVE_DIX_CONFIG_H
28788                :#include <dix-config.h>
28789                :#endif
28790                :
28791                :#ifdef PANORAMIX_DEBUG
28792                :#include <stdio.h>
28793                :int ProcInitialConnection();
28794                :#endif
28795                :
28796                :#include "windowstr.h"
28797                :#include <X11/fonts/fontstruct.h>
28798                :#include "dixfontstr.h"
28799                :#include "gcstruct.h"
28800                :#include "selection.h"
28801                :#include "colormapst.h"
28802                :#include "cursorstr.h"
28803                :#include "scrnintstr.h"
28804                :#include "opaque.h"
28805                :#include "input.h"
28806                :#include "servermd.h"
28807                :#include "extnsionst.h"
28808                :#include "dixfont.h"
28809                :#include "dispatch.h"
28810                :#include "swaprep.h"
28811                :#include "swapreq.h"
28812                :#ifdef PANORAMIX
28813                :#include "panoramiX.h"
28814                :#include "panoramiXsrv.h"
28815                :#endif
28816                :#include "xace.h"
28817                :#ifdef XAPPGROUP
28818                :#include "appgroup.h"
28819                :#endif
28820                :#ifdef XKB
28821                :#ifndef XKB_IN_SERVER
28822                :#define XKB_IN_SERVER
28823                :#endif
28824                :#include "inputstr.h"
28825                :#include <xkbsrv.h>
28826                :#endif
28827                :
28828                :#ifdef XSERVER_DTRACE
28829                :#include <sys/types.h>
28830                :typedef const char *string;
28831                :#include "Xserver-dtrace.h"
28832                :
28833                :char *RequestNames[256];
28834                :static void LoadRequestNames(void);
28835                :static void FreeRequestNames(void);
28836                :#define GetRequestName(i) (RequestNames[i])
28837                :#endif
28838                :
28839                :#define mskcnt ((MAXCLIENTS + 31) / 32)
28840                :#define BITMASK(i) (1U << ((i) & 31))
28841                :#define MASKIDX(i) ((i) >> 5)
28842                :#define MASKWORD(buf, i) buf[MASKIDX(i)]
28843                :#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
28844                :#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
28845                :#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
28846                :
28847                :extern xConnSetupPrefix connSetupPrefix;
28848                :extern char *ConnectionInfo;
28849                :
28850                :_X_EXPORT Selection *CurrentSelections;
28851                :_X_EXPORT int NumCurrentSelections;
28852                :CallbackListPtr SelectionCallback = NULL;
28853                :
28854                :static ClientPtr grabClient;
28855                :#define GrabNone 0
28856                :#define GrabActive 1
28857                :#define GrabKickout 2
28858                :static int grabState = GrabNone;
28859                :static long grabWaiters[mskcnt];
28860                :_X_EXPORT CallbackListPtr ServerGrabCallback = NULL;
28861                :HWEventQueuePtr checkForInput[2];
28862                :extern int connBlockScreenStart;
28863                :
28864                :static void KillAllClients(void);
28865                :
28866                :static void DeleteClientFromAnySelections(ClientPtr client);
28867                :
28868                :static int nextFreeClientID; /* always MIN free client ID */
28869                :
28870                :static int      nClients;       /* number of authorized clients */
28871                :
28872                :_X_EXPORT CallbackListPtr ClientStateCallback;
28873                :
28874                :/* dispatchException & isItTimeToYield must be declared volatile since they
28875                : * are modified by signal handlers - otherwise optimizer may assume it doesn't
28876                : * need to actually check value in memory when used and may miss changes from
28877                : * signal handlers.
28878                : */
28879                :_X_EXPORT volatile char dispatchException = 0;
28880                :_X_EXPORT volatile char isItTimeToYield;
28881                :
28882                :/* Various of the DIX function interfaces were not designed to allow
28883                : * the client->errorValue to be set on BadValue and other errors.
28884                : * Rather than changing interfaces and breaking untold code we introduce
28885                : * a new global that dispatch can use.
28886                : */
28887                :XID clientErrorValue;   /* XXX this is a kludge */
28888                :
28889                :#define SAME_SCREENS(a, b) (\
28890                :    (a.pScreen == b.pScreen))
28891                :
28892                :_X_EXPORT void
28893                :SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
28894                :{
28895                :    checkForInput[0] = c0;
28896                :    checkForInput[1] = c1;
28897                :}
28898                :
28899                :_X_EXPORT void
28900                :UpdateCurrentTime(void)
28901                :{
28902                :    TimeStamp systime;
28903                :
28904                :    /* To avoid time running backwards, we must call GetTimeInMillis before
28905                :     * calling ProcessInputEvents.
28906                :     */
28907                :    systime.months = currentTime.months;
28908                :    systime.milliseconds = GetTimeInMillis();
28909                :    if (systime.milliseconds < currentTime.milliseconds)
28910                :        systime.months++;
28911                :    if (*checkForInput[0] != *checkForInput[1])
28912                :        ProcessInputEvents();
28913                :    if (CompareTimeStamps(systime, currentTime) == LATER)
28914                :        currentTime = systime;
28915                :}
28916                :
28917                :/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
28918                :_X_EXPORT void
28919                :UpdateCurrentTimeIf(void)
28920                :{
28921                :    TimeStamp systime;
28922                :
28923                :    systime.months = currentTime.months;
28924                :    systime.milliseconds = GetTimeInMillis();
28925                :    if (systime.milliseconds < currentTime.milliseconds)
28926                :        systime.months++;
28927                :    if (*checkForInput[0] == *checkForInput[1])
28928                :        currentTime = systime;
28929                :}
28930                :
28931                :void
28932                :InitSelections(void)
28933                :{
28934                :    if (CurrentSelections)
28935                :        xfree(CurrentSelections);
28936                :    CurrentSelections = (Selection *)NULL;
28937                :    NumCurrentSelections = 0;
28938                :}
28939                :
28940                :void 
28941                :FlushClientCaches(XID id)
28942                :{ /* FlushClientCaches total:      4  0.0044 */
28943                :    int i;
28944                :    ClientPtr client;
28945                :
28946                :    client = clients[CLIENT_ID(id)];
28947      1  0.0011 :    if (client == NullClient)
28948                :        return ;
28949      1  0.0011 :    for (i=0; i<currentMaxClients; i++)
28950                :    {
28951                :        client = clients[i];
28952                :        if (client != NullClient)
28953                :        {
28954                :            if (client->lastDrawableID == id)
28955                :            {
28956                :                client->lastDrawableID = WindowTable[0]->drawable.id;
28957                :                client->lastDrawable = (DrawablePtr)WindowTable[0];
28958                :            }
28959                :            else if (client->lastGCID == id)
28960                :            {
28961                :                client->lastGCID = INVALID;
28962                :                client->lastGC = (GCPtr)NULL;
28963                :            }
28964                :        }
28965                :    }
28966      2  0.0022 :}
28967                :#ifdef SMART_SCHEDULE
28968                :
28969                :#undef SMART_DEBUG
28970                :
28971                :#define SMART_SCHEDULE_DEFAULT_INTERVAL 20          /* ms */
28972                :#define SMART_SCHEDULE_MAX_SLICE        200         /* ms */
28973                :
28974                :Bool        SmartScheduleDisable = FALSE;
28975                :long        SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
28976                :long        SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
28977                :long        SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
28978                :long        SmartScheduleTime;
28979                :static ClientPtr   SmartLastClient;
28980                :static int         SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1];
28981                :
28982                :#ifdef SMART_DEBUG
28983                :long        SmartLastPrint;
28984                :#endif
28985                :
28986                :void        Dispatch(void);
28987                :void        InitProcVectors(void);
28988                :
28989                :static int
28990                :SmartScheduleClient (int *clientReady, int nready)
28991                :{
28992                :    ClientPtr   pClient;
28993                :    int         i;
28994                :    int         client;
28995                :    int         bestPrio, best = 0;
28996                :    int         bestRobin, robin;
28997                :    long        now = SmartScheduleTime;
28998                :    long        idle;
28999                :
29000                :    bestPrio = -0x7fffffff;
29001                :    bestRobin = 0;
29002                :    idle = 2 * SmartScheduleSlice;
29003                :    for (i = 0; i < nready; i++)
29004                :    {
29005                :        client = clientReady[i];
29006                :        pClient = clients[client];
29007                :        /* Praise clients which are idle */
29008                :        if ((now - pClient->smart_check_tick) >= idle)
29009                :        {
29010                :            if (pClient->smart_priority < 0)
29011                :                pClient->smart_priority++;
29012                :        }
29013                :        pClient->smart_check_tick = now;
29014                :        
29015                :        /* check priority to select best client */
29016                :        robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff;
29017                :        if (pClient->smart_priority > bestPrio ||
29018                :            (pClient->smart_priority == bestPrio && robin > bestRobin))
29019                :        {
29020                :            bestPrio = pClient->smart_priority;
29021                :            bestRobin = robin;
29022                :            best = client;
29023                :        }
29024                :#ifdef SMART_DEBUG
29025                :        if ((now - SmartLastPrint) >= 5000)
29026                :            fprintf (stderr, " %2d: %3d", client, pClient->smart_priority);
29027                :#endif
29028                :    }
29029                :#ifdef SMART_DEBUG
29030                :    if ((now - SmartLastPrint) >= 5000)
29031                :    {
29032                :        fprintf (stderr, " use %2d\n", best);
29033                :        SmartLastPrint = now;
29034                :    }
29035                :#endif
29036                :    pClient = clients[best];
29037                :    SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index;
29038                :    /*
29039                :     * Set current client pointer
29040                :     */
29041                :    if (SmartLastClient != pClient)
29042                :    {
29043                :        pClient->smart_start_tick = now;
29044                :        SmartLastClient = pClient;
29045                :    }
29046                :    /*
29047                :     * Adjust slice
29048                :     */
29049                :    if (nready == 1)
29050                :    {
29051                :        /*
29052                :         * If it's been a long time since another client
29053                :         * has run, bump the slice up to get maximal
29054                :         * performance from a single client
29055                :         */
29056                :        if ((now - pClient->smart_start_tick) > 1000 &&
29057                :            SmartScheduleSlice < SmartScheduleMaxSlice)
29058                :        {
29059                :            SmartScheduleSlice += SmartScheduleInterval;
29060                :        }
29061                :    }
29062                :    else
29063                :    {
29064                :        SmartScheduleSlice = SmartScheduleInterval;
29065                :    }
29066                :    return best;
29067                :}
29068                :#endif
29069                :
29070                :#define MAJOROP ((xReq *)client->requestBuffer)->reqType
29071                :
29072                :void
29073                :Dispatch(void)
29074                :{ /* Dispatch total:     37  0.0403 */
29075                :    int        *clientReady;     /* array of request ready clients */
29076                :    int result;
29077                :    ClientPtr   client;
29078                :    int nready;
29079                :    HWEventQueuePtr* icheck = checkForInput;
29080                :#ifdef SMART_SCHEDULE
29081                :    long                        start_tick;
29082                :#endif
29083                :
29084                :    nextFreeClientID = 1;
29085                :    InitSelections();
29086                :    nClients = 0;
29087                :
29088                :    clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients);
29089                :    if (!clientReady)
29090                :        return;
29091                :
29092                :#ifdef XSERVER_DTRACE
29093                :    LoadRequestNames();
29094                :#endif
29095                :
29096                :    while (!dispatchException)
29097                :    {
29098                :        if (*icheck[0] != *icheck[1])
29099                :        {
29100                :            ProcessInputEvents();
29101                :            FlushIfCriticalOutputPending();
29102                :        }
29103                :
29104                :        nready = WaitForSomething(clientReady);
29105                :
29106                :#ifdef SMART_SCHEDULE
29107                :        if (nready && !SmartScheduleDisable)
29108                :        {
29109                :            clientReady[0] = SmartScheduleClient (clientReady, nready);
29110                :            nready = 1;
29111                :        }
29112                :#endif
29113                :       /***************** 
29114                :        *  Handle events in round robin fashion, doing input between 
29115                :        *  each round 
29116                :        *****************/
29117                :
29118                :        while (!dispatchException && (--nready >= 0))
29119                :        {
29120                :            client = clients[clientReady[nready]];
29121                :            if (! client)
29122                :            {
29123                :                /* KillClient can cause this to happen */
29124                :                continue;
29125                :            }
29126                :            /* GrabServer activation can cause this to be true */
29127                :            if (grabState == GrabKickout)
29128                :            {
29129                :                grabState = GrabActive;
29130                :                break;
29131                :            }
29132                :            isItTimeToYield = FALSE;
29133                : 
29134                :            requestingClient = client;
29135                :#ifdef SMART_SCHEDULE
29136                :            start_tick = SmartScheduleTime;
29137                :#endif
29138      1  0.0011 :            while (!isItTimeToYield)
29139                :            {
29140      8  0.0087 :                if (*icheck[0] != *icheck[1])
29141                :                {
29142                :                    ProcessInputEvents();
29143                :                    FlushIfCriticalOutputPending();
29144                :                }
29145                :#ifdef SMART_SCHEDULE
29146      6  0.0065 :                if (!SmartScheduleDisable && 
29147                :                    (SmartScheduleTime - start_tick) >= SmartScheduleSlice)
29148                :                {
29149                :                    /* Penalize clients which consume ticks */
29150                :                    if (client->smart_priority > SMART_MIN_PRIORITY)
29151                :                        client->smart_priority--;
29152                :                    break;
29153                :                }
29154                :#endif
29155                :                /* now, finally, deal with client requests */
29156                :
29157      2  0.0022 :                result = ReadRequestFromClient(client);
29158      2  0.0022 :                if (result <= 0) 
29159                :                {
29160                :                    if (result < 0)
29161                :                        CloseDownClient(client);
29162                :                    break;
29163                :                }
29164                :
29165      2  0.0022 :                client->sequence++;
29166                :#ifdef DEBUG
29167                :                if (client->requestLogIndex == MAX_REQUEST_LOG)
29168                :                    client->requestLogIndex = 0;
29169                :                client->requestLog[client->requestLogIndex] = MAJOROP;
29170                :                client->requestLogIndex++;
29171                :#endif
29172                :#ifdef XSERVER_DTRACE
29173                :                XSERVER_REQUEST_START(GetRequestName(MAJOROP), MAJOROP,
29174                :                              ((xReq *)client->requestBuffer)->length,
29175                :                              client->index, client->requestBuffer);
29176                :#endif
29177      4  0.0044 :                if (result > (maxBigRequestSize << 2))
29178                :                    result = BadLength;
29179                :                else {
29180                :                    XaceHook(XACE_AUDIT_BEGIN, client);
29181      3  0.0033 :                    result = (* client->requestVector[MAJOROP])(client);
29182      8  0.0087 :                    XaceHook(XACE_AUDIT_END, client, result);
29183                :                }
29184                :#ifdef XSERVER_DTRACE
29185                :                XSERVER_REQUEST_DONE(GetRequestName(MAJOROP), MAJOROP,
29186                :                              client->sequence, client->index, result);
29187                :#endif
29188                :
29189      1  0.0011 :                if (result != Success) 
29190                :                {
29191                :                    if (client->noClientException != Success)
29192                :                        CloseDownClient(client);
29193                :                    else
29194                :                        SendErrorToClient(client, MAJOROP,
29195                :                                          MinorOpcodeOfRequest(client),
29196                :                                          client->errorValue, result);
29197                :                    break;
29198                :                }
29199                :#ifdef DAMAGEEXT
29200                :                FlushIfCriticalOutputPending ();
29201                :#endif
29202                :            }
29203                :            FlushAllOutput();
29204                :#ifdef SMART_SCHEDULE
29205                :            client = clients[clientReady[nready]];
29206                :            if (client)
29207                :                client->smart_stop_tick = SmartScheduleTime;
29208                :#endif
29209                :            requestingClient = NULL;
29210                :        }
29211                :        dispatchException &= ~DE_PRIORITYCHANGE;
29212                :    }
29213                :#if defined(DDXBEFORERESET)
29214                :    ddxBeforeReset ();
29215                :#endif
29216                :    KillAllClients();
29217                :    DEALLOCATE_LOCAL(clientReady);
29218                :    dispatchException &= ~DE_RESET;
29219                :#ifdef XSERVER_DTRACE
29220                :    FreeRequestNames();
29221                :#endif
29222                :}
29223                :
29224                :#undef MAJOROP
29225                :
29226                :_X_EXPORT int
29227                :ProcBadRequest(ClientPtr client)
29228                :{
29229                :    return (BadRequest);
29230                :}
29231                :
29232                :int
29233                :ProcCreateWindow(ClientPtr client)
29234                :{
29235                :    WindowPtr pParent, pWin;
29236                :    REQUEST(xCreateWindowReq);
29237                :    int result, len, rc;
29238                :
29239                :    REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
29240                :    
29241                :    LEGAL_NEW_RESOURCE(stuff->wid, client);
29242                :    rc = dixLookupWindow(&pParent, stuff->parent, client, DixWriteAccess);
29243                :    if (rc != Success)
29244                :        return rc;
29245                :    len = client->req_len - (sizeof(xCreateWindowReq) >> 2);
29246                :    if (Ones(stuff->mask) != len)
29247                :        return BadLength;
29248                :    if (!stuff->width || !stuff->height)
29249                :    {
29250                :        client->errorValue = 0;
29251                :        return BadValue;
29252                :    }
29253                :    pWin = CreateWindow(stuff->wid, pParent, stuff->x,
29254                :                              stuff->y, stuff->width, stuff->height, 
29255                :                              stuff->borderWidth, stuff->class,
29256                :                              stuff->mask, (XID *) &stuff[1], 
29257                :                              (int)stuff->depth, 
29258                :                              client, stuff->visual, &result);
29259                :    if (pWin)
29260                :    {
29261                :        Mask mask = pWin->eventMask;
29262                :
29263                :        pWin->eventMask = 0; /* subterfuge in case AddResource fails */
29264                :        if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin))
29265                :            return BadAlloc;
29266                :        pWin->eventMask = mask;
29267                :    }
29268                :    if (client->noClientException != Success)
29269                :        return(client->noClientException);
29270                :    else
29271                :        return(result);
29272                :}
29273                :
29274                :int
29275                :ProcChangeWindowAttributes(ClientPtr client)
29276                :{
29277                :    WindowPtr pWin;
29278                :    REQUEST(xChangeWindowAttributesReq);
29279                :    int result;
29280                :    int len, rc;
29281                :
29282                :    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
29283                :    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
29284                :    if (rc != Success)
29285                :        return rc;
29286                :    len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2);
29287                :    if (len != Ones(stuff->valueMask))
29288                :        return BadLength;
29289                :    result =  ChangeWindowAttributes(pWin, 
29290                :                                  stuff->valueMask, 
29291                :                                  (XID *) &stuff[1], 
29292                :                                  client);
29293                :    if (client->noClientException != Success)
29294                :        return(client->noClientException);
29295                :    else
29296                :        return(result);
29297                :}
29298                :
29299                :int
29300                :ProcGetWindowAttributes(ClientPtr client)
29301                :{
29302                :    WindowPtr pWin;
29303                :    REQUEST(xResourceReq);
29304                :    xGetWindowAttributesReply wa;
29305                :    int rc;
29306                :
29307                :    REQUEST_SIZE_MATCH(xResourceReq);
29308                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
29309                :    if (rc != Success)
29310                :        return rc;
29311                :    GetWindowAttributes(pWin, client, &wa);
29312                :    WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
29313                :    return(client->noClientException);
29314                :}
29315                :
29316                :int
29317                :ProcDestroyWindow(ClientPtr client)
29318                :{
29319                :    WindowPtr pWin;
29320                :    REQUEST(xResourceReq);
29321                :    int rc;
29322                :
29323                :    REQUEST_SIZE_MATCH(xResourceReq);
29324                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
29325                :    if (rc != Success)
29326                :        return rc;
29327                :    if (pWin->parent)
29328                :        FreeResource(stuff->id, RT_NONE);
29329                :    return(client->noClientException);
29330                :}
29331                :
29332                :int
29333                :ProcDestroySubwindows(ClientPtr client)
29334                :{
29335                :    WindowPtr pWin;
29336                :    REQUEST(xResourceReq);
29337                :    int rc;
29338                :
29339                :    REQUEST_SIZE_MATCH(xResourceReq);
29340                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
29341                :    if (rc != Success)
29342                :        return rc;
29343                :    DestroySubwindows(pWin, client);
29344                :    return(client->noClientException);
29345                :}
29346                :
29347                :int
29348                :ProcChangeSaveSet(ClientPtr client)
29349                :{
29350                :    WindowPtr pWin;
29351                :    REQUEST(xChangeSaveSetReq);
29352                :    int result, rc;
29353                :                  
29354                :    REQUEST_SIZE_MATCH(xChangeSaveSetReq);
29355                :    rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
29356                :    if (rc != Success)
29357                :        return rc;
29358                :    if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
29359                :        return BadMatch;
29360                :    if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
29361                :    {
29362                :        result = AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
29363                :        if (client->noClientException != Success)
29364                :            return(client->noClientException);
29365                :        else
29366                :            return(result);
29367                :    }
29368                :    else
29369                :    {
29370                :        client->errorValue = stuff->mode;
29371                :        return( BadValue );
29372                :    }
29373                :}
29374                :
29375                :int
29376                :ProcReparentWindow(ClientPtr client)
29377                :{
29378                :    WindowPtr pWin, pParent;
29379                :    REQUEST(xReparentWindowReq);
29380                :    int result, rc;
29381                :
29382                :    REQUEST_SIZE_MATCH(xReparentWindowReq);
29383                :    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
29384                :    if (rc != Success)
29385                :        return rc;
29386                :    rc = dixLookupWindow(&pParent, stuff->parent, client, DixWriteAccess);
29387                :    if (rc != Success)
29388                :        return rc;
29389                :    if (SAME_SCREENS(pWin->drawable, pParent->drawable))
29390                :    {
29391                :        if ((pWin->backgroundState == ParentRelative) &&
29392                :            (pParent->drawable.depth != pWin->drawable.depth))
29393                :            return BadMatch;
29394                :        if ((pWin->drawable.class != InputOnly) &&
29395                :            (pParent->drawable.class == InputOnly))
29396                :            return BadMatch;
29397                :        result =  ReparentWindow(pWin, pParent, 
29398                :                         (short)stuff->x, (short)stuff->y, client);
29399                :        if (client->noClientException != Success)
29400                :            return(client->noClientException);
29401                :        else
29402                :            return(result);
29403                :    }
29404                :    else 
29405                :        return (BadMatch);
29406                :}
29407                :
29408                :int
29409                :ProcMapWindow(ClientPtr client)
29410                :{
29411                :    WindowPtr pWin;
29412                :    REQUEST(xResourceReq);
29413                :    int rc;
29414                :
29415                :    REQUEST_SIZE_MATCH(xResourceReq);
29416                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
29417                :    if (rc != Success)
29418                :        return rc;
29419                :    MapWindow(pWin, client);
29420                :           /* update cache to say it is mapped */
29421                :    return(client->noClientException);
29422                :}
29423                :
29424                :int
29425                :ProcMapSubwindows(ClientPtr client)
29426                :{
29427                :    WindowPtr pWin;
29428                :    REQUEST(xResourceReq);
29429                :    int rc;
29430                :
29431                :    REQUEST_SIZE_MATCH(xResourceReq);
29432                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
29433                :    if (rc != Success)
29434                :        return rc;
29435                :    MapSubwindows(pWin, client);
29436                :           /* update cache to say it is mapped */
29437                :    return(client->noClientException);
29438                :}
29439                :
29440                :int
29441                :ProcUnmapWindow(ClientPtr client)
29442                :{
29443                :    WindowPtr pWin;
29444                :    REQUEST(xResourceReq);
29445                :    int rc;
29446                :
29447                :    REQUEST_SIZE_MATCH(xResourceReq);
29448                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
29449                :    if (rc != Success)
29450                :        return rc;
29451                :    UnmapWindow(pWin, FALSE);
29452                :           /* update cache to say it is mapped */
29453                :    return(client->noClientException);
29454                :}
29455                :
29456                :int
29457                :ProcUnmapSubwindows(ClientPtr client)
29458                :{
29459                :    WindowPtr pWin;
29460                :    REQUEST(xResourceReq);
29461                :    int rc;
29462                :
29463                :    REQUEST_SIZE_MATCH(xResourceReq);
29464                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
29465                :    if (rc != Success)
29466                :        return rc;
29467                :    UnmapSubwindows(pWin);
29468                :    return(client->noClientException);
29469                :}
29470                :
29471                :int
29472                :ProcConfigureWindow(ClientPtr client)
29473                :{
29474                :    WindowPtr pWin;
29475                :    REQUEST(xConfigureWindowReq);
29476                :    int result;
29477                :    int len, rc;
29478                :
29479                :    REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
29480                :    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
29481                :    if (rc != Success)
29482                :        return rc;
29483                :    len = client->req_len - (sizeof(xConfigureWindowReq) >> 2);
29484                :    if (Ones((Mask)stuff->mask) != len)
29485                :        return BadLength;
29486                :    result =  ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], 
29487                :                              client);
29488                :    if (client->noClientException != Success)
29489                :        return(client->noClientException);
29490                :    else
29491                :        return(result);
29492                :}
29493                :
29494                :int
29495                :ProcCirculateWindow(ClientPtr client)
29496                :{
29497                :    WindowPtr pWin;
29498                :    REQUEST(xCirculateWindowReq);
29499                :    int rc;
29500                :
29501                :    REQUEST_SIZE_MATCH(xCirculateWindowReq);
29502                :    if ((stuff->direction != RaiseLowest) &&
29503                :        (stuff->direction != LowerHighest))
29504                :    {
29505                :        client->errorValue = stuff->direction;
29506                :        return BadValue;
29507                :    }
29508                :    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
29509                :    if (rc != Success)
29510                :        return rc;
29511                :    CirculateWindow(pWin, (int)stuff->direction, client);
29512                :    return(client->noClientException);
29513                :}
29514                :
29515                :static int
29516                :GetGeometry(ClientPtr client, xGetGeometryReply *rep)
29517                :{
29518                :    DrawablePtr pDraw;
29519                :    int rc;
29520                :    REQUEST(xResourceReq);
29521                :    REQUEST_SIZE_MATCH(xResourceReq);
29522                :
29523                :    rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixReadAccess);
29524                :    if (rc != Success)
29525                :        return rc;
29526                :
29527                :    rep->type = X_Reply;
29528                :    rep->length = 0;
29529                :    rep->sequenceNumber = client->sequence;
29530                :    rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
29531                :    rep->depth = pDraw->depth;
29532                :    rep->width = pDraw->width;
29533                :    rep->height = pDraw->height;
29534                :
29535                :    /* XXX - Because the pixmap-implementation of the multibuffer extension 
29536                :     *       may have the buffer-id's drawable resource value be a pointer
29537                :     *       to the buffer's window instead of the buffer itself
29538                :     *       (this happens if the buffer is the displayed buffer),
29539                :     *       we also have to check that the id matches before we can
29540                :     *       truly say that it is a DRAWABLE_WINDOW.
29541                :     */
29542                :
29543                :    if ((pDraw->type == UNDRAWABLE_WINDOW) ||
29544                :        ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id)))
29545                :    {
29546                :        WindowPtr pWin = (WindowPtr)pDraw;
29547                :        rep->x = pWin->origin.x - wBorderWidth (pWin);
29548                :        rep->y = pWin->origin.y - wBorderWidth (pWin);
29549                :        rep->borderWidth = pWin->borderWidth;
29550                :    }
29551                :    else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */
29552                :    {
29553                :        rep->x = rep->y = rep->borderWidth = 0;
29554                :    }
29555                :
29556                :    return Success;
29557                :}
29558                :
29559                :
29560                :int
29561                :ProcGetGeometry(ClientPtr client)
29562                :{
29563                :    xGetGeometryReply rep;
29564                :    int status;
29565                :
29566                :    if ((status = GetGeometry(client, &rep)) != Success)
29567                :        return status;
29568                :
29569                :    WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
29570                :    return(client->noClientException);
29571                :}
29572                :
29573                :
29574                :int
29575                :ProcQueryTree(ClientPtr client)
29576                :{
29577                :    xQueryTreeReply reply;
29578                :    int rc, numChildren = 0;
29579                :    WindowPtr pChild, pWin, pHead;
29580                :    Window  *childIDs = (Window *)NULL;
29581                :    REQUEST(xResourceReq);
29582                :
29583                :    REQUEST_SIZE_MATCH(xResourceReq);
29584                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
29585                :    if (rc != Success)
29586                :        return rc;
29587                :    reply.type = X_Reply;
29588                :    reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
29589                :    reply.sequenceNumber = client->sequence;
29590                :    if (pWin->parent)
29591                :        reply.parent = pWin->parent->drawable.id;
29592                :    else
29593                :        reply.parent = (Window)None;
29594                :    pHead = RealChildHead(pWin);
29595                :    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
29596                :        numChildren++;
29597                :    if (numChildren)
29598                :    {
29599                :        int curChild = 0;
29600                :
29601                :        childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window));
29602                :        if (!childIDs)
29603                :            return BadAlloc;
29604                :        for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
29605                :            childIDs[curChild++] = pChild->drawable.id;
29606                :    }
29607                :    
29608                :    reply.nChildren = numChildren;
29609                :    reply.length = (numChildren * sizeof(Window)) >> 2;
29610                :    
29611                :    WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
29612                :    if (numChildren)
29613                :    {
29614                :        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
29615                :        WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs);
29616                :        DEALLOCATE_LOCAL(childIDs);
29617                :    }
29618                :
29619                :    return(client->noClientException);
29620                :}
29621                :
29622                :int
29623                :ProcInternAtom(ClientPtr client)
29624                :{
29625                :    Atom atom;
29626                :    char *tchar;
29627                :    REQUEST(xInternAtomReq);
29628                :
29629                :    REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
29630                :    if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse))
29631                :    {
29632                :        client->errorValue = stuff->onlyIfExists;
29633                :        return(BadValue);
29634                :    }
29635                :    tchar = (char *) &stuff[1];
29636                :    atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
29637                :    if (atom != BAD_RESOURCE)
29638                :    {
29639                :        xInternAtomReply reply;
29640                :        reply.type = X_Reply;
29641                :        reply.length = 0;
29642                :        reply.sequenceNumber = client->sequence;
29643                :        reply.atom = atom;
29644                :        WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
29645                :        return(client->noClientException);
29646                :    }
29647                :    else
29648                :        return (BadAlloc);
29649                :}
29650                :
29651                :int
29652                :ProcGetAtomName(ClientPtr client)
29653                :{
29654                :    char *str;
29655                :    xGetAtomNameReply reply;
29656                :    int len;
29657                :    REQUEST(xResourceReq);
29658                :
29659                :    REQUEST_SIZE_MATCH(xResourceReq);
29660                :    if ( (str = NameForAtom(stuff->id)) )
29661                :    {
29662                :        len = strlen(str);
29663                :        reply.type = X_Reply;
29664                :        reply.length = (len + 3) >> 2;
29665                :        reply.sequenceNumber = client->sequence;
29666                :        reply.nameLength = len;
29667                :        WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
29668                :        (void)WriteToClient(client, len, str);
29669                :        return(client->noClientException);
29670                :    }
29671                :    else 
29672                :    { 
29673                :        client->errorValue = stuff->id;
29674                :        return (BadAtom);
29675                :    }
29676                :}
29677                :
29678                :int
29679                :ProcSetSelectionOwner(ClientPtr client)
29680                :{
29681                :    WindowPtr pWin;
29682                :    TimeStamp time;
29683                :    REQUEST(xSetSelectionOwnerReq);
29684                :
29685                :    REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
29686                :    UpdateCurrentTime();
29687                :    time = ClientTimeToServerTime(stuff->time);
29688                :
29689                :    /* If the client's time stamp is in the future relative to the server's
29690                :        time stamp, do not set the selection, just return success. */
29691                :    if (CompareTimeStamps(time, currentTime) == LATER)
29692                :        return Success;
29693                :    if (stuff->window != None)
29694                :    {
29695                :        int rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
29696                :        if (rc != Success)
29697                :            return rc;
29698                :    }
29699                :    else
29700                :        pWin = (WindowPtr)None;
29701                :    if (ValidAtom(stuff->selection))
29702                :    {
29703                :        int i = 0;
29704                :
29705                :        /*
29706                :         * First, see if the selection is already set... 
29707                :         */
29708                :        while ((i < NumCurrentSelections) && 
29709                :               CurrentSelections[i].selection != stuff->selection) 
29710                :            i++;
29711                :        if (i < NumCurrentSelections)
29712                :        {        
29713                :            xEvent event;
29714                :
29715                :            /* If the timestamp in client's request is in the past relative
29716                :                to the time stamp indicating the last time the owner of the
29717                :                selection was set, do not set the selection, just return 
29718                :                success. */
29719                :            if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged)
29720                :                == EARLIER)
29721                :                return Success;
29722                :            if (CurrentSelections[i].client &&
29723                :                (!pWin || (CurrentSelections[i].client != client)))
29724                :            {
29725                :                event.u.u.type = SelectionClear;
29726                :                event.u.selectionClear.time = time.milliseconds;
29727                :                event.u.selectionClear.window = CurrentSelections[i].window;
29728                :                event.u.selectionClear.atom = CurrentSelections[i].selection;
29729                :                (void) TryClientEvents (CurrentSelections[i].client, &event, 1,
29730                :                                NoEventMask, NoEventMask /* CantBeFiltered */,
29731                :                                NullGrab);
29732                :            }
29733                :        }
29734                :        else
29735                :        {
29736                :            /*
29737                :             * It doesn't exist, so add it...
29738                :             */
29739                :            Selection *newsels;
29740                :
29741                :            if (i == 0)
29742                :                newsels = (Selection *)xalloc(sizeof(Selection));
29743                :            else
29744                :                newsels = (Selection *)xrealloc(CurrentSelections,
29745                :                            (NumCurrentSelections + 1) * sizeof(Selection));
29746                :            if (!newsels)
29747                :                return BadAlloc;
29748                :            NumCurrentSelections++;
29749                :            CurrentSelections = newsels;
29750                :            CurrentSelections[i].selection = stuff->selection;
29751                :        }
29752                :        CurrentSelections[i].lastTimeChanged = time;
29753                :        CurrentSelections[i].window = stuff->window;
29754                :        CurrentSelections[i].pWin = pWin;
29755                :        CurrentSelections[i].client = (pWin ? client : NullClient);
29756                :        if (SelectionCallback)
29757                :        {
29758                :            SelectionInfoRec    info;
29759                :
29760                :            info.selection = &CurrentSelections[i];
29761                :            info.kind= SelectionSetOwner;
29762                :            CallCallbacks(&SelectionCallback, &info);
29763                :        }
29764                :        return (client->noClientException);
29765                :    }
29766                :    else 
29767                :    {
29768                :        client->errorValue = stuff->selection;
29769                :        return (BadAtom);
29770                :    }
29771                :}
29772                :
29773                :int
29774                :ProcGetSelectionOwner(ClientPtr client)
29775                :{
29776                :    REQUEST(xResourceReq);
29777                :
29778                :    REQUEST_SIZE_MATCH(xResourceReq);
29779                :    if (ValidAtom(stuff->id))
29780                :    {
29781                :        int i;
29782                :        xGetSelectionOwnerReply reply;
29783                :
29784                :        i = 0;
29785                :        while ((i < NumCurrentSelections) && 
29786                :               CurrentSelections[i].selection != stuff->id) i++;
29787                :        reply.type = X_Reply;
29788                :        reply.length = 0;
29789                :        reply.sequenceNumber = client->sequence;
29790                :        if (i < NumCurrentSelections)
29791                :            reply.owner = CurrentSelections[i].window;
29792                :        else
29793                :            reply.owner = None;
29794                :        WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);
29795                :        return(client->noClientException);
29796                :    }
29797                :    else            
29798                :    {
29799                :        client->errorValue = stuff->id;
29800                :        return (BadAtom); 
29801                :    }
29802                :}
29803                :
29804                :int
29805                :ProcConvertSelection(ClientPtr client)
29806                :{
29807                :    Bool paramsOkay;
29808                :    xEvent event;
29809                :    WindowPtr pWin;
29810                :    REQUEST(xConvertSelectionReq);
29811                :    int rc;
29812                :
29813                :    REQUEST_SIZE_MATCH(xConvertSelectionReq);
29814                :    rc = dixLookupWindow(&pWin, stuff->requestor, client, DixReadAccess);
29815                :    if (rc != Success)
29816                :        return rc;
29817                :
29818                :    paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target));
29819                :    if (stuff->property != None)
29820                :        paramsOkay &= ValidAtom(stuff->property);
29821                :    if (paramsOkay)
29822                :    {
29823                :        int i;
29824                :
29825                :        i = 0;
29826                :        while ((i < NumCurrentSelections) && 
29827                :               CurrentSelections[i].selection != stuff->selection) i++;
29828                :        if ((i < NumCurrentSelections) &&
29829                :            (CurrentSelections[i].window != None) &&
29830                :            XaceHook(XACE_RESOURCE_ACCESS, client,
29831                :                     CurrentSelections[i].window, RT_WINDOW,
29832                :                     DixReadAccess, CurrentSelections[i].pWin))
29833                :        {        
29834                :            event.u.u.type = SelectionRequest;
29835                :            event.u.selectionRequest.time = stuff->time;
29836                :            event.u.selectionRequest.owner = 
29837                :                        CurrentSelections[i].window;
29838                :            event.u.selectionRequest.requestor = stuff->requestor;
29839                :            event.u.selectionRequest.selection = stuff->selection;
29840                :            event.u.selectionRequest.target = stuff->target;
29841                :            event.u.selectionRequest.property = stuff->property;
29842                :            if (TryClientEvents(
29843                :                CurrentSelections[i].client, &event, 1, NoEventMask,
29844                :                NoEventMask /* CantBeFiltered */, NullGrab))
29845                :                return (client->noClientException);
29846                :        }
29847                :        event.u.u.type = SelectionNotify;
29848                :        event.u.selectionNotify.time = stuff->time;
29849                :        event.u.selectionNotify.requestor = stuff->requestor;
29850                :        event.u.selectionNotify.selection = stuff->selection;
29851                :        event.u.selectionNotify.target = stuff->target;
29852                :        event.u.selectionNotify.property = None;
29853                :        (void) TryClientEvents(client, &event, 1, NoEventMask,
29854                :                               NoEventMask /* CantBeFiltered */, NullGrab);
29855                :        return (client->noClientException);
29856                :    }
29857                :    else 
29858                :    {
29859                :        client->errorValue = stuff->property;
29860                :        return (BadAtom);
29861                :    }
29862                :}
29863                :
29864                :int
29865                :ProcGrabServer(ClientPtr client)
29866                :{
29867                :    REQUEST_SIZE_MATCH(xReq);
29868                :    if (grabState != GrabNone && client != grabClient)
29869                :    {
29870                :        ResetCurrentRequest(client);
29871                :        client->sequence--;
29872                :        BITSET(grabWaiters, client->index);
29873                :        IgnoreClient(client);
29874                :        return(client->noClientException);
29875                :    }
29876                :    OnlyListenToOneClient(client);
29877                :    grabState = GrabKickout;
29878                :    grabClient = client;
29879                :
29880                :    if (ServerGrabCallback)
29881                :    {
29882                :        ServerGrabInfoRec grabinfo;
29883                :        grabinfo.client = client;
29884                :        grabinfo.grabstate  = SERVER_GRABBED;
29885                :        CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo);
29886                :    }
29887                :
29888                :    return(client->noClientException);
29889                :}
29890                :
29891                :static void
29892                :UngrabServer(ClientPtr client)
29893                :{
29894                :    int i;
29895                :
29896                :    grabState = GrabNone;
29897                :    ListenToAllClients();
29898                :    for (i = mskcnt; --i >= 0 && !grabWaiters[i]; )
29899                :        ;
29900                :    if (i >= 0)
29901                :    {
29902                :        i <<= 5;
29903                :        while (!GETBIT(grabWaiters, i))
29904                :            i++;
29905                :        BITCLEAR(grabWaiters, i);
29906                :        AttendClient(clients[i]);
29907                :    }
29908                :
29909                :    if (ServerGrabCallback)
29910                :    {
29911                :        ServerGrabInfoRec grabinfo;
29912                :        grabinfo.client = client;
29913                :        grabinfo.grabstate  = SERVER_UNGRABBED;
29914                :        CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo);
29915                :    }
29916                :}
29917                :
29918                :int
29919                :ProcUngrabServer(ClientPtr client)
29920                :{
29921                :    REQUEST_SIZE_MATCH(xReq);
29922                :    UngrabServer(client);
29923                :    return(client->noClientException);
29924                :}
29925                :
29926                :int
29927                :ProcTranslateCoords(ClientPtr client)
29928                :{
29929                :    REQUEST(xTranslateCoordsReq);
29930                :
29931                :    WindowPtr pWin, pDst;
29932                :    xTranslateCoordsReply rep;
29933                :    int rc;
29934                :
29935                :    REQUEST_SIZE_MATCH(xTranslateCoordsReq);
29936                :    rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixReadAccess);
29937                :    if (rc != Success)
29938                :        return rc;
29939                :    rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixReadAccess);
29940                :    if (rc != Success)
29941                :        return rc;
29942                :    rep.type = X_Reply;
29943                :    rep.length = 0;
29944                :    rep.sequenceNumber = client->sequence;
29945                :    if (!SAME_SCREENS(pWin->drawable, pDst->drawable))
29946                :    {
29947                :        rep.sameScreen = xFalse;
29948                :        rep.child = None;
29949                :        rep.dstX = rep.dstY = 0;
29950                :    }
29951                :    else
29952                :    {
29953                :        INT16 x, y;
29954                :        rep.sameScreen = xTrue;
29955                :        rep.child = None;
29956                :        /* computing absolute coordinates -- adjust to destination later */
29957                :        x = pWin->drawable.x + stuff->srcX;
29958                :        y = pWin->drawable.y + stuff->srcY;
29959                :        pWin = pDst->firstChild;
29960                :        while (pWin)
29961                :        {
29962                :#ifdef SHAPE
29963                :            BoxRec  box;
29964                :#endif
29965                :            if ((pWin->mapped) &&
29966                :                (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
29967                :                (x < pWin->drawable.x + (int)pWin->drawable.width +
29968                :                 wBorderWidth (pWin)) &&
29969                :                (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
29970                :                (y < pWin->drawable.y + (int)pWin->drawable.height +
29971                :                 wBorderWidth (pWin))
29972                :#ifdef SHAPE
29973                :                /* When a window is shaped, a further check
29974                :                 * is made to see if the point is inside
29975                :                 * borderSize
29976                :                 */
29977                :                && (!wBoundingShape(pWin) ||
29978                :                    POINT_IN_REGION(pWin->drawable.pScreen, 
29979                :                                        &pWin->borderSize, x, y, &box))
29980                :                
29981                :                && (!wInputShape(pWin) ||
29982                :                    POINT_IN_REGION(pWin->drawable.pScreen,
29983                :                                    wInputShape(pWin),
29984                :                                    x - pWin->drawable.x,
29985                :                                    y - pWin->drawable.y, &box))
29986                :#endif
29987                :                )
29988                :            {
29989                :                rep.child = pWin->drawable.id;
29990                :                pWin = (WindowPtr) NULL;
29991                :            }
29992                :            else
29993                :                pWin = pWin->nextSib;
29994                :        }
29995                :        /* adjust to destination coordinates */
29996                :        rep.dstX = x - pDst->drawable.x;
29997                :        rep.dstY = y - pDst->drawable.y;
29998                :    }
29999                :    WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
30000                :    return(client->noClientException);
30001                :}
30002                :
30003                :int
30004                :ProcOpenFont(ClientPtr client)
30005                :{
30006                :    int err;
30007                :    REQUEST(xOpenFontReq);
30008                :
30009                :    REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
30010                :    client->errorValue = stuff->fid;
30011                :    LEGAL_NEW_RESOURCE(stuff->fid, client);
30012                :    err = OpenFont(client, stuff->fid, (Mask) 0,
30013                :                stuff->nbytes, (char *)&stuff[1]);
30014                :    if (err == Success)
30015                :    {
30016                :        return(client->noClientException);
30017                :    }
30018                :    else
30019                :        return err;
30020                :}
30021                :
30022                :int
30023                :ProcCloseFont(ClientPtr client)
30024                :{
30025                :    FontPtr pFont;
30026                :    REQUEST(xResourceReq);
30027                :
30028                :    REQUEST_SIZE_MATCH(xResourceReq);
30029                :    pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
30030                :                                            DixDestroyAccess);
30031                :    if ( pFont != (FontPtr)NULL)        /* id was valid */
30032                :    {
30033                :        FreeResource(stuff->id, RT_NONE);
30034                :        return(client->noClientException);
30035                :    }
30036                :    else
30037                :    {
30038                :        client->errorValue = stuff->id;
30039                :        return (BadFont);
30040                :    }
30041                :}
30042                :
30043                :int
30044                :ProcQueryFont(ClientPtr client)
30045                :{
30046                :    xQueryFontReply     *reply;
30047                :    FontPtr pFont;
30048                :    GC *pGC;
30049                :    REQUEST(xResourceReq);
30050                :
30051                :    REQUEST_SIZE_MATCH(xResourceReq);
30052                :    client->errorValue = stuff->id;             /* EITHER font or gc */
30053                :    pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
30054                :                                            DixReadAccess);
30055                :    if (!pFont)
30056                :    {
30057                :        pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC,
30058                :                                            DixReadAccess);
30059                :        if (!pGC)
30060                :        {
30061                :            client->errorValue = stuff->id;
30062                :            return(BadFont);     /* procotol spec says only error is BadFont */
30063                :        }
30064                :        pFont = pGC->font;
30065                :    }
30066                :
30067                :    {
30068                :        xCharInfo       *pmax = FONTINKMAX(pFont);
30069                :        xCharInfo       *pmin = FONTINKMIN(pFont);
30070                :        int             nprotoxcistructs;
30071                :        int             rlength;
30072                :
30073                :        nprotoxcistructs = (
30074                :           pmax->rightSideBearing == pmin->rightSideBearing &&
30075                :           pmax->leftSideBearing == pmin->leftSideBearing &&
30076                :           pmax->descent == pmin->descent &&
30077                :           pmax->ascent == pmin->ascent &&
30078                :           pmax->characterWidth == pmin->characterWidth) ?
30079                :                0 : N2dChars(pFont);
30080                :
30081                :        rlength = sizeof(xQueryFontReply) +
30082                :                     FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp)  +
30083                :                     nprotoxcistructs * sizeof(xCharInfo);
30084                :        reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength);
30085                :        if(!reply)
30086                :        {
30087                :            return(BadAlloc);
30088                :        }
30089                :
30090                :        reply->type = X_Reply;
30091                :        reply->length = (rlength - sizeof(xGenericReply)) >> 2;
30092                :        reply->sequenceNumber = client->sequence;
30093                :        QueryFont( pFont, reply, nprotoxcistructs);
30094                :
30095                :        WriteReplyToClient(client, rlength, reply);
30096                :        DEALLOCATE_LOCAL(reply);
30097                :        return(client->noClientException);
30098                :    }
30099                :}
30100                :
30101                :int
30102                :ProcQueryTextExtents(ClientPtr client)
30103                :{
30104                :    REQUEST(xQueryTextExtentsReq);
30105                :    xQueryTextExtentsReply reply;
30106                :    FontPtr pFont;
30107                :    GC *pGC;
30108                :    ExtentInfoRec info;
30109                :    unsigned long length;
30110                :
30111                :    REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
30112                :        
30113                :    pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT,
30114                :                                            DixReadAccess);
30115                :    if (!pFont)
30116                :    {
30117                :        pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC,
30118                :                                           DixReadAccess);
30119                :        if (!pGC)
30120                :        {
30121                :            client->errorValue = stuff->fid;
30122                :            return(BadFont);
30123                :        }
30124                :        pFont = pGC->font;
30125                :    }
30126                :    length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2);
30127                :    length = length << 1;
30128                :    if (stuff->oddLength)
30129                :    {
30130                :        if (length == 0)
30131                :            return(BadLength);
30132                :        length--;
30133                :    }
30134                :    if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info))
30135                :        return(BadAlloc);
30136                :    reply.type = X_Reply;
30137                :    reply.length = 0;
30138                :    reply.sequenceNumber = client->sequence;
30139                :    reply.drawDirection = info.drawDirection;
30140                :    reply.fontAscent = info.fontAscent;
30141                :    reply.fontDescent = info.fontDescent;
30142                :    reply.overallAscent = info.overallAscent;
30143                :    reply.overallDescent = info.overallDescent;
30144                :    reply.overallWidth = info.overallWidth;
30145                :    reply.overallLeft = info.overallLeft;
30146                :    reply.overallRight = info.overallRight;
30147                :    WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
30148                :    return(client->noClientException);
30149                :}
30150                :
30151                :int
30152                :ProcListFonts(ClientPtr client)
30153                :{
30154                :    REQUEST(xListFontsReq);
30155                :
30156                :    REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
30157                :
30158                :    return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, 
30159                :        stuff->maxNames);
30160                :}
30161                :
30162                :int
30163                :ProcListFontsWithInfo(ClientPtr client)
30164                :{
30165                :    REQUEST(xListFontsWithInfoReq);
30166                :
30167                :    REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
30168                :
30169                :    return StartListFontsWithInfo(client, stuff->nbytes,
30170                :                                  (unsigned char *) &stuff[1], stuff->maxNames);
30171                :}
30172                :
30173                :/**
30174                : *
30175                : *  \param value must conform to DeleteType
30176                : */
30177                :int
30178                :dixDestroyPixmap(pointer value, XID pid)
30179                :{
30180                :    PixmapPtr pPixmap = (PixmapPtr)value;
30181                :    return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
30182                :}
30183                :
30184                :int
30185                :ProcCreatePixmap(ClientPtr client)
30186      1  0.0011 :{ /* ProcCreatePixmap total:      9  0.0098 */
30187                :    PixmapPtr pMap;
30188                :    DrawablePtr pDraw;
30189                :    REQUEST(xCreatePixmapReq);
30190                :    DepthPtr pDepth;
30191                :    int i, rc;
30192                :
30193                :    REQUEST_SIZE_MATCH(xCreatePixmapReq);
30194                :    client->errorValue = stuff->pid;
30195      1  0.0011 :    LEGAL_NEW_RESOURCE(stuff->pid, client);
30196                :    
30197      1  0.0011 :    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
30198                :                           DixReadAccess);
30199                :    if (rc != Success)
30200                :        return rc;
30201                :
30202                :    if (!stuff->width || !stuff->height)
30203                :    {
30204                :        client->errorValue = 0;
30205                :        return BadValue;
30206                :    }
30207      1  0.0011 :    if (stuff->width > 32767 || stuff->height > 32767)
30208                :    {
30209                :        /* It is allowed to try and allocate a pixmap which is larger than
30210                :         * 32767 in either dimension. However, all of the framebuffer code
30211                :         * is buggy and does not reliably draw to such big pixmaps, basically
30212                :         * because the Region data structure operates with signed shorts
30213                :         * for the rectangles in it.
30214                :         *
30215                :         * Furthermore, several places in the X server computes the
30216                :         * size in bytes of the pixmap and tries to store it in an
30217                :         * integer. This integer can overflow and cause the allocated size
30218                :         * to be much smaller.
30219                :         *
30220                :         * So, such big pixmaps are rejected here with a BadAlloc
30221                :         */
30222                :        return BadAlloc;
30223                :    }
30224                :    if (stuff->depth != 1)
30225                :    {
30226      1  0.0011 :        pDepth = pDraw->pScreen->allowedDepths;
30227      1  0.0011 :        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
30228      2  0.0022 :           if (pDepth->depth == stuff->depth)
30229                :               goto CreatePmap;
30230                :        client->errorValue = stuff->depth;
30231                :        return BadValue;
30232                :    }
30233                :CreatePmap:
30234      1  0.0011 :    pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap)
30235                :                (pDraw->pScreen, stuff->width,
30236                :                 stuff->height, stuff->depth);
30237                :    if (pMap)
30238                :    {
30239                :        pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
30240                :        pMap->drawable.id = stuff->pid;
30241                :        if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
30242                :            return(client->noClientException);
30243                :    }
30244                :    return (BadAlloc);
30245                :}
30246                :
30247                :int
30248                :ProcFreePixmap(ClientPtr client)
30249      1  0.0011 :{ /* ProcFreePixmap total:      6  0.0065 */
30250                :    PixmapPtr pMap;
30251                :
30252                :    REQUEST(xResourceReq);
30253                :
30254      4  0.0044 :    REQUEST_SIZE_MATCH(xResourceReq);
30255                :    pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP,
30256                :                                             DixDestroyAccess);
30257                :    if (pMap) 
30258                :    {
30259      1  0.0011 :        FreeResource(stuff->id, RT_NONE);
30260                :        return(client->noClientException);
30261                :    }
30262                :    else 
30263                :    {
30264                :        client->errorValue = stuff->id;
30265                :        return (BadPixmap);
30266                :    }
30267                :}
30268                :
30269                :int
30270                :ProcCreateGC(ClientPtr client)
30271                :{
30272                :    int error, rc;
30273                :    GC *pGC;
30274                :    DrawablePtr pDraw;
30275                :    unsigned len;
30276                :    REQUEST(xCreateGCReq);
30277                :
30278                :    REQUEST_AT_LEAST_SIZE(xCreateGCReq);
30279                :    client->errorValue = stuff->gc;
30280                :    LEGAL_NEW_RESOURCE(stuff->gc, client);
30281                :    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess);
30282                :    if (rc != Success)
30283                :        return rc;
30284                :
30285                :    len = client->req_len -  (sizeof(xCreateGCReq) >> 2);
30286                :    if (len != Ones(stuff->mask))
30287                :        return BadLength;
30288                :    pGC = (GC *)CreateGC(pDraw, stuff->mask, 
30289                :                         (XID *) &stuff[1], &error);
30290                :    if (error != Success)
30291                :        return error;
30292                :    if (!AddResource(stuff->gc, RT_GC, (pointer)pGC))
30293                :        return (BadAlloc);
30294                :    return(client->noClientException);
30295                :}
30296                :
30297                :int
30298                :ProcChangeGC(ClientPtr client)
30299      1  0.0011 :{ /* ProcChangeGC total:      1  0.0011 */
30300                :    GC *pGC;
30301                :    int result;
30302                :    unsigned len;
30303                :    REQUEST(xChangeGCReq);
30304                :    REQUEST_AT_LEAST_SIZE(xChangeGCReq);
30305                :
30306                :    result = dixLookupGC(&pGC, stuff->gc, client, DixWriteAccess);
30307                :    if (result != Success)
30308                :        return result;
30309                :
30310                :    len = client->req_len -  (sizeof(xChangeGCReq) >> 2);
30311                :    if (len != Ones(stuff->mask))
30312                :        return BadLength;
30313                :
30314                :    result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0);
30315                :    if (client->noClientException != Success)
30316                :        return(client->noClientException);
30317                :    else
30318                :    {
30319                :        client->errorValue = clientErrorValue;
30320                :        return(result);
30321                :    }
30322                :}
30323                :
30324                :int
30325                :ProcCopyGC(ClientPtr client)
30326                :{
30327                :    GC *dstGC;
30328                :    GC *pGC;
30329                :    int result;
30330                :    REQUEST(xCopyGCReq);
30331                :    REQUEST_SIZE_MATCH(xCopyGCReq);
30332                :
30333                :    result = dixLookupGC(&pGC, stuff->srcGC, client, DixReadAccess);
30334                :    if (result != Success)
30335                :        return result;
30336                :    result = dixLookupGC(&dstGC, stuff->dstGC, client, DixWriteAccess);
30337                :    if (result != Success)
30338                :        return result;
30339                :    if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
30340                :        return (BadMatch);    
30341                :    result = CopyGC(pGC, dstGC, stuff->mask);
30342                :    if (client->noClientException != Success)
30343                :        return(client->noClientException);
30344                :    else
30345                :    {
30346                :        client->errorValue = clientErrorValue;
30347                :        return(result);
30348                :    }
30349                :}
30350                :
30351                :int
30352                :ProcSetDashes(ClientPtr client)
30353                :{
30354                :    GC *pGC;
30355                :    int result;
30356                :    REQUEST(xSetDashesReq);
30357                :
30358                :    REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
30359                :    if (stuff->nDashes == 0)
30360                :    {
30361                :         client->errorValue = 0;
30362                :         return BadValue;
30363                :    }
30364                :
30365                :    result = dixLookupGC(&pGC,stuff->gc, client, DixWriteAccess);
30366                :    if (result != Success)
30367                :        return result;
30368                :
30369                :    result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
30370                :                       (unsigned char *)&stuff[1]);
30371                :    if (client->noClientException != Success)
30372                :        return(client->noClientException);
30373                :    else
30374                :    {
30375                :        client->errorValue = clientErrorValue;
30376                :        return(result);
30377                :    }
30378                :}
30379                :
30380                :int
30381                :ProcSetClipRectangles(ClientPtr client)
30382                :{ /* ProcSetClipRectangles total:      1  0.0011 */
30383                :    int nr, result;
30384                :    GC *pGC;
30385                :    REQUEST(xSetClipRectanglesReq);
30386                :
30387                :    REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
30388                :    if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
30389                :        (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded))
30390                :    {
30391                :        client->errorValue = stuff->ordering;
30392                :        return BadValue;
30393                :    }
30394      1  0.0011 :    result = dixLookupGC(&pGC,stuff->gc, client, DixWriteAccess);
30395                :    if (result != Success)
30396                :        return result;
30397                :                 
30398                :    nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
30399                :    if (nr & 4)
30400                :        return(BadLength);
30401                :    nr >>= 3;
30402                :    result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
30403                :                          nr, (xRectangle *)&stuff[1], (int)stuff->ordering);
30404                :    if (client->noClientException != Success)
30405                :        return(client->noClientException);
30406                :    else
30407                :        return(result);
30408                :}
30409                :
30410                :int
30411                :ProcFreeGC(ClientPtr client)
30412                :{
30413                :    GC *pGC;
30414                :    int rc;
30415                :    REQUEST(xResourceReq);
30416                :    REQUEST_SIZE_MATCH(xResourceReq);
30417                :
30418                :    rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
30419                :    if (rc != Success)
30420                :        return rc;
30421                :
30422                :    FreeResource(stuff->id, RT_NONE);
30423                :    return(client->noClientException);
30424                :}
30425                :
30426                :int
30427                :ProcClearToBackground(ClientPtr client)
30428                :{
30429                :    REQUEST(xClearAreaReq);
30430                :    WindowPtr pWin;
30431                :    int rc;
30432                :
30433                :    REQUEST_SIZE_MATCH(xClearAreaReq);
30434                :    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
30435                :    if (rc != Success)
30436                :        return rc;
30437                :    if (pWin->drawable.class == InputOnly)
30438                :    {
30439                :        client->errorValue = stuff->window;
30440                :        return (BadMatch);
30441                :    }               
30442                :    if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse))
30443                :    {
30444                :        client->errorValue = stuff->exposures;
30445                :        return(BadValue);
30446                :    }
30447                :    (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y,
30448                :                               stuff->width, stuff->height,
30449                :                               (Bool)stuff->exposures);
30450                :    return(client->noClientException);
30451                :}
30452                :
30453                :int
30454                :ProcCopyArea(ClientPtr client)
30455      1  0.0011 :{ /* ProcCopyArea total:      1  0.0011 */
30456                :    DrawablePtr pDst;
30457                :    DrawablePtr pSrc;
30458                :    GC *pGC;
30459                :    REQUEST(xCopyAreaReq);
30460                :    RegionPtr pRgn;
30461                :    int rc;
30462                :
30463                :    REQUEST_SIZE_MATCH(xCopyAreaReq);
30464                :
30465                :    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); 
30466                :    if (stuff->dstDrawable != stuff->srcDrawable)
30467                :    {
30468                :        rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
30469                :                                 DixReadAccess);
30470                :        if (rc != Success)
30471                :            return rc;
30472                :        if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth))
30473                :        {
30474                :            client->errorValue = stuff->dstDrawable;
30475                :            return (BadMatch);
30476                :        }
30477                :    }
30478                :    else
30479                :        pSrc = pDst;
30480                :
30481                :    pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
30482                :                                 stuff->width, stuff->height, 
30483                :                                 stuff->dstX, stuff->dstY);
30484                :    if (pGC->graphicsExposures)
30485                :    {
30486                :        (*pDst->pScreen->SendGraphicsExpose)
30487                :                (client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
30488                :        if (pRgn)
30489                :            REGION_DESTROY(pDst->pScreen, pRgn);
30490                :    }
30491                :
30492                :    return(client->noClientException);
30493                :}
30494                :
30495                :int
30496                :ProcCopyPlane(ClientPtr client)
30497                :{
30498                :    DrawablePtr psrcDraw, pdstDraw;
30499                :    GC *pGC;
30500                :    REQUEST(xCopyPlaneReq);
30501                :    RegionPtr pRgn;
30502                :    int rc;
30503                :
30504                :    REQUEST_SIZE_MATCH(xCopyPlaneReq);
30505                :
30506                :    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client);
30507                :    if (stuff->dstDrawable != stuff->srcDrawable)
30508                :    {
30509                :        rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
30510                :                               DixReadAccess);
30511                :        if (rc != Success)
30512                :            return rc;
30513                :
30514                :        if (pdstDraw->pScreen != psrcDraw->pScreen)
30515                :        {
30516                :            client->errorValue = stuff->dstDrawable;
30517                :            return (BadMatch);
30518                :        }
30519                :    }
30520                :    else
30521                :        psrcDraw = pdstDraw;
30522                :
30523                :    /* Check to see if stuff->bitPlane has exactly ONE good bit set */
30524                :    if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
30525                :       (stuff->bitPlane > (1L << (psrcDraw->depth - 1))))
30526                :    {
30527                :       client->errorValue = stuff->bitPlane;
30528                :       return(BadValue);
30529                :    }
30530                :
30531                :    pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY,
30532                :                                 stuff->width, stuff->height, 
30533                :                                 stuff->dstX, stuff->dstY, stuff->bitPlane);
30534                :    if (pGC->graphicsExposures)
30535                :    {
30536                :        (*pdstDraw->pScreen->SendGraphicsExpose)
30537                :                (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
30538                :        if (pRgn)
30539                :            REGION_DESTROY(pdstDraw->pScreen, pRgn);
30540                :    }
30541                :    return(client->noClientException);
30542                :}
30543                :
30544                :int
30545                :ProcPolyPoint(ClientPtr client)
30546                :{
30547                :    int npoint;
30548                :    GC *pGC;
30549                :    DrawablePtr pDraw;
30550                :    REQUEST(xPolyPointReq);
30551                :
30552                :    REQUEST_AT_LEAST_SIZE(xPolyPointReq);
30553                :    if ((stuff->coordMode != CoordModeOrigin) && 
30554                :        (stuff->coordMode != CoordModePrevious))
30555                :    {
30556                :        client->errorValue = stuff->coordMode;
30557                :        return BadValue;
30558                :    }
30559                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); 
30560                :    npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2;
30561                :    if (npoint)
30562                :        (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint,
30563                :                          (xPoint *) &stuff[1]);
30564                :    return (client->noClientException);
30565                :}
30566                :
30567                :int
30568                :ProcPolyLine(ClientPtr client)
30569                :{
30570                :    int npoint;
30571                :    GC *pGC;
30572                :    DrawablePtr pDraw;
30573                :    REQUEST(xPolyLineReq);
30574                :
30575                :    REQUEST_AT_LEAST_SIZE(xPolyLineReq);
30576                :    if ((stuff->coordMode != CoordModeOrigin) && 
30577                :        (stuff->coordMode != CoordModePrevious))
30578                :    {
30579                :        client->errorValue = stuff->coordMode;
30580                :        return BadValue;
30581                :    }
30582                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
30583                :    npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2;
30584                :    if (npoint > 1)
30585                :        (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, 
30586                :                              (DDXPointPtr) &stuff[1]);
30587                :    return(client->noClientException);
30588                :}
30589                :
30590                :int
30591                :ProcPolySegment(ClientPtr client)
30592                :{
30593                :    int nsegs;
30594                :    GC *pGC;
30595                :    DrawablePtr pDraw;
30596                :    REQUEST(xPolySegmentReq);
30597                :
30598                :    REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
30599                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
30600                :    nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
30601                :    if (nsegs & 4)
30602                :        return(BadLength);
30603                :    nsegs >>= 3;
30604                :    if (nsegs)
30605                :        (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
30606                :    return (client->noClientException);
30607                :}
30608                :
30609                :int
30610                :ProcPolyRectangle (ClientPtr client)
30611                :{
30612                :    int nrects;
30613                :    GC *pGC;
30614                :    DrawablePtr pDraw;
30615                :    REQUEST(xPolyRectangleReq);
30616                :
30617                :    REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
30618                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
30619                :    nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
30620                :    if (nrects & 4)
30621                :        return(BadLength);
30622                :    nrects >>= 3;
30623                :    if (nrects)
30624                :        (*pGC->ops->PolyRectangle)(pDraw, pGC, 
30625                :                    nrects, (xRectangle *) &stuff[1]);
30626                :    return(client->noClientException);
30627                :}
30628                :
30629                :int
30630                :ProcPolyArc(ClientPtr client)
30631                :{
30632                :    int         narcs;
30633                :    GC *pGC;
30634                :    DrawablePtr pDraw;
30635                :    REQUEST(xPolyArcReq);
30636                :
30637                :    REQUEST_AT_LEAST_SIZE(xPolyArcReq);
30638                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
30639                :    narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
30640                :    if (narcs % sizeof(xArc))
30641                :        return(BadLength);
30642                :    narcs /= sizeof(xArc);
30643                :    if (narcs)
30644                :        (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]);
30645                :    return (client->noClientException);
30646                :}
30647                :
30648                :int
30649                :ProcFillPoly(ClientPtr client)
30650                :{
30651                :    int          things;
30652                :    GC *pGC;
30653                :    DrawablePtr pDraw;
30654                :    REQUEST(xFillPolyReq);
30655                :
30656                :    REQUEST_AT_LEAST_SIZE(xFillPolyReq);
30657                :    if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&  
30658                :        (stuff->shape != Convex))
30659                :    {
30660                :        client->errorValue = stuff->shape;
30661                :        return BadValue;
30662                :    }
30663                :    if ((stuff->coordMode != CoordModeOrigin) && 
30664                :        (stuff->coordMode != CoordModePrevious))
30665                :    {
30666                :        client->errorValue = stuff->coordMode;
30667                :        return BadValue;
30668                :    }
30669                :
30670                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
30671                :    things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2;
30672                :    if (things)
30673                :        (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
30674                :                         stuff->coordMode, things,
30675                :                         (DDXPointPtr) &stuff[1]);
30676                :    return(client->noClientException);
30677                :}
30678                :
30679                :int
30680                :ProcPolyFillRectangle(ClientPtr client)
30681                :{ /* ProcPolyFillRectangle total:      1  0.0011 */
30682                :    int             things;
30683                :    GC *pGC;
30684                :    DrawablePtr pDraw;
30685                :    REQUEST(xPolyFillRectangleReq);
30686                :
30687                :    REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
30688                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
30689                :    things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
30690                :    if (things & 4)
30691                :        return(BadLength);
30692      1  0.0011 :    things >>= 3;
30693                :
30694                :    if (things)
30695                :        (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
30696                :                      (xRectangle *) &stuff[1]);
30697                :    return (client->noClientException);
30698                :}
30699                :
30700                :int
30701                :ProcPolyFillArc(ClientPtr client)
30702                :{
30703                :    int         narcs;
30704                :    GC *pGC;
30705                :    DrawablePtr pDraw;
30706                :    REQUEST(xPolyFillArcReq);
30707                :
30708                :    REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
30709                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
30710                :    narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
30711                :    if (narcs % sizeof(xArc))
30712                :        return(BadLength);
30713                :    narcs /= sizeof(xArc);
30714                :    if (narcs)
30715                :        (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
30716                :    return (client->noClientException);
30717                :}
30718                :
30719                :#ifdef MATCH_CLIENT_ENDIAN
30720                :
30721                :int
30722                :ServerOrder (void)
30723                :{
30724                :    int     whichbyte = 1;
30725                :
30726                :    if (*((char *) &whichbyte))
30727                :        return LSBFirst;
30728                :    return MSBFirst;
30729                :}
30730                :
30731                :#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
30732                :
30733                :void
30734                :ReformatImage (char *base, int nbytes, int bpp, int order)
30735                :{
30736                :    switch (bpp) {
30737                :    case 1:     /* yuck */
30738                :        if (BITMAP_BIT_ORDER != order)
30739                :            BitOrderInvert ((unsigned char *) base, nbytes);
30740                :#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
30741                :        ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order);
30742                :#endif
30743                :        break;
30744                :    case 4:
30745                :        break;  /* yuck */
30746                :    case 8:
30747                :        break;
30748                :    case 16:
30749                :        if (IMAGE_BYTE_ORDER != order)
30750                :            TwoByteSwap ((unsigned char *) base, nbytes);
30751                :        break;
30752                :    case 32:
30753                :        if (IMAGE_BYTE_ORDER != order)
30754                :            FourByteSwap ((unsigned char *) base, nbytes);
30755                :        break;
30756                :    }
30757                :}
30758                :#else
30759                :#define ReformatImage(b,n,bpp,o)
30760                :#endif
30761                :
30762                :/* 64-bit server notes: the protocol restricts padding of images to
30763                : * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
30764                : * to use internally. Removes need for internal alignment checking.
30765                : * All of the PutImage functions could be changed individually, but
30766                : * as currently written, they call other routines which require things
30767                : * to be 64-bit padded on scanlines, so we changed things here.
30768                : * If an image would be padded differently for 64- versus 32-, then
30769                : * copy each scanline to a 64-bit padded scanline.
30770                : * Also, we need to make sure that the image is aligned on a 64-bit
30771                : * boundary, even if the scanlines are padded to our satisfaction.
30772                : */
30773                :int
30774                :ProcPutImage(ClientPtr client)
30775                :{
30776                :    GC *pGC;
30777                :    DrawablePtr pDraw;
30778                :    long        length;         /* length of scanline server padded */
30779                :    long        lengthProto;    /* length of scanline protocol padded */
30780                :    char        *tmpImage;
30781                :    REQUEST(xPutImageReq);
30782                :
30783                :    REQUEST_AT_LEAST_SIZE(xPutImageReq);
30784                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
30785                :    if (stuff->format == XYBitmap)
30786                :    {
30787                :        if ((stuff->depth != 1) ||
30788                :            (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad))
30789                :            return BadMatch;
30790                :        length      = BitmapBytePad(stuff->width + stuff->leftPad);
30791                :    }
30792                :    else if (stuff->format == XYPixmap)
30793                :    {
30794                :        if ((pDraw->depth != stuff->depth) || 
30795                :            (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad))
30796                :            return BadMatch;
30797                :        length      = BitmapBytePad(stuff->width + stuff->leftPad);
30798                :        length      *= stuff->depth;
30799                :    }
30800                :    else if (stuff->format == ZPixmap)
30801                :    {
30802                :        if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
30803                :            return BadMatch;
30804                :        length      = PixmapBytePad(stuff->width, stuff->depth);
30805                :    }
30806                :    else
30807                :    {
30808                :        client->errorValue = stuff->format;
30809                :        return BadValue;
30810                :    }
30811                :
30812                :    tmpImage = (char *)&stuff[1];
30813                :    lengthProto = length;
30814                :        
30815                :    if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + 
30816                :        (sizeof(xPutImageReq) >> 2)) != client->req_len)
30817                :        return BadLength;
30818                :
30819                :    ReformatImage (tmpImage, lengthProto * stuff->height, 
30820                :                   stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1,
30821                :                   ClientOrder(client));
30822                :    
30823                :    (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
30824                :                  stuff->width, stuff->height, 
30825                :                  stuff->leftPad, stuff->format, tmpImage);
30826                :
30827                :     return (client->noClientException);
30828                :}
30829                :
30830                :static int
30831                :DoGetImage(ClientPtr client, int format, Drawable drawable, 
30832                :           int x, int y, int width, int height, 
30833                :           Mask planemask, xGetImageReply **im_return)
30834                :{
30835                :    DrawablePtr         pDraw;
30836                :    int                 nlines, linesPerBuf, rc;
30837                :    int linesDone;
30838                :    long                widthBytesLine, length;
30839                :    Mask                plane = 0;
30840                :    char                *pBuf;
30841                :    xGetImageReply      xgi;
30842                :    RegionPtr pVisibleRegion = NULL;
30843                :
30844                :    if ((format != XYPixmap) && (format != ZPixmap))
30845                :    {
30846                :        client->errorValue = format;
30847                :        return(BadValue);
30848                :    }
30849                :    rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
30850                :    if (rc != Success)
30851                :        return rc;
30852                :
30853                :    if(pDraw->type == DRAWABLE_WINDOW)
30854                :    {
30855                :      if( /* check for being viewable */
30856                :         !((WindowPtr) pDraw)->realized ||
30857                :          /* check for being on screen */
30858                :         pDraw->x + x < 0 ||
30859                :         pDraw->x + x + width > pDraw->pScreen->width ||
30860                :         pDraw->y + y < 0 ||
30861                :         pDraw->y + y + height > pDraw->pScreen->height ||
30862                :          /* check for being inside of border */
30863                :         x < - wBorderWidth((WindowPtr)pDraw) ||
30864                :         x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
30865                :         y < -wBorderWidth((WindowPtr)pDraw) ||
30866                :         y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height
30867                :        )
30868                :            return(BadMatch);
30869                :        xgi.visual = wVisual (((WindowPtr) pDraw));
30870                :    }
30871                :    else
30872                :    {
30873                :      if(x < 0 ||
30874                :         x+width > (int)pDraw->width ||
30875                :         y < 0 ||
30876                :         y+height > (int)pDraw->height
30877                :        )
30878                :            return(BadMatch);
30879                :        xgi.visual = None;
30880                :    }
30881                :
30882                :    xgi.type = X_Reply;
30883                :    xgi.sequenceNumber = client->sequence;
30884                :    xgi.depth = pDraw->depth;
30885                :    if(format == ZPixmap)
30886                :    {
30887                :        widthBytesLine = PixmapBytePad(width, pDraw->depth);
30888                :        length = widthBytesLine * height;
30889                :
30890                :    }
30891                :    else 
30892                :    {
30893                :        widthBytesLine = BitmapBytePad(width);
30894                :        plane = ((Mask)1) << (pDraw->depth - 1);
30895                :        /* only planes asked for */
30896                :        length = widthBytesLine * height *
30897                :                 Ones(planemask & (plane | (plane - 1)));
30898                :
30899                :    }
30900                :
30901                :    xgi.length = length;
30902                :
30903                :    if (im_return) {
30904                :        pBuf = (char *)xalloc(sz_xGetImageReply + length);
30905                :        if (!pBuf)
30906                :            return (BadAlloc);
30907                :        if (widthBytesLine == 0)
30908                :            linesPerBuf = 0;
30909                :        else
30910                :            linesPerBuf = height;
30911                :        *im_return = (xGetImageReply *)pBuf;
30912                :        *(xGetImageReply *)pBuf = xgi;
30913                :        pBuf += sz_xGetImageReply;
30914                :    } else {
30915                :        xgi.length = (xgi.length + 3) >> 2;
30916                :        if (widthBytesLine == 0 || height == 0)
30917                :            linesPerBuf = 0;
30918                :        else if (widthBytesLine >= IMAGE_BUFSIZE)
30919                :            linesPerBuf = 1;
30920                :        else
30921                :        {
30922                :            linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
30923                :            if (linesPerBuf > height)
30924                :                linesPerBuf = height;
30925                :        }
30926                :        length = linesPerBuf * widthBytesLine;
30927                :        if (linesPerBuf < height)
30928                :        {
30929                :            /* we have to make sure intermediate buffers don't need padding */
30930                :            while ((linesPerBuf > 1) &&
30931                :                   (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)))
30932                :            {
30933                :                linesPerBuf--;
30934                :                length -= widthBytesLine;
30935                :            }
30936                :            while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))
30937                :            {
30938                :                linesPerBuf++;
30939                :                length += widthBytesLine;
30940                :            }
30941                :        }
30942                :        if(!(pBuf = (char *) ALLOCATE_LOCAL(length)))
30943                :            return (BadAlloc);
30944                :        WriteReplyToClient(client, sizeof (xGetImageReply), &xgi);
30945                :    }
30946                :
30947                :    if (pDraw->type == DRAWABLE_WINDOW &&
30948                :        !XaceHook(XACE_DRAWABLE_ACCESS, client, pDraw))
30949                :    {
30950                :        pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw);
30951                :        if (pVisibleRegion)
30952                :        {
30953                :            REGION_TRANSLATE(pDraw->pScreen, pVisibleRegion,
30954                :                             -pDraw->x, -pDraw->y);
30955                :        }
30956                :    }
30957                :
30958                :    if (linesPerBuf == 0)
30959                :    {
30960                :        /* nothing to do */
30961                :    }
30962                :    else if (format == ZPixmap)
30963                :    {
30964                :        linesDone = 0;
30965                :        while (height - linesDone > 0)
30966                :        {
30967                :            nlines = min(linesPerBuf, height - linesDone);
30968                :            (*pDraw->pScreen->GetImage) (pDraw,
30969                :                                         x,
30970                :                                         y + linesDone,
30971                :                                         width, 
30972                :                                         nlines,
30973                :                                         format,
30974                :                                         planemask,
30975                :                                         (pointer) pBuf);
30976                :            if (pVisibleRegion)
30977                :                XaceCensorImage(client, pVisibleRegion, widthBytesLine,
30978                :                        pDraw, x, y + linesDone, width, 
30979                :                        nlines, format, pBuf);
30980                :
30981                :            /* Note that this is NOT a call to WriteSwappedDataToClient,
30982                :               as we do NOT byte swap */
30983                :            if (!im_return)
30984                :            {
30985                :                ReformatImage (pBuf, (int)(nlines * widthBytesLine),
30986                :                               BitsPerPixel (pDraw->depth),
30987                :                               ClientOrder(client));
30988                :
30989                :/* Don't split me, gcc pukes when you do */
30990                :                (void)WriteToClient(client,
30991                :                                    (int)(nlines * widthBytesLine),
30992                :                                    pBuf);
30993                :            }
30994                :            linesDone += nlines;
30995                :        }
30996                :    }
30997                :    else /* XYPixmap */
30998                :    {
30999                :        for (; plane; plane >>= 1)
31000                :        {
31001                :            if (planemask & plane)
31002                :            {
31003                :                linesDone = 0;
31004                :                while (height - linesDone > 0)
31005                :                {
31006                :                    nlines = min(linesPerBuf, height - linesDone);
31007                :                    (*pDraw->pScreen->GetImage) (pDraw,
31008                :                                                 x,
31009                :                                                 y + linesDone,
31010                :                                                 width, 
31011                :                                                 nlines,
31012                :                                                 format,
31013                :                                                 plane,
31014                :                                                 (pointer)pBuf);
31015                :                    if (pVisibleRegion)
31016                :                        XaceCensorImage(client, pVisibleRegion,
31017                :                                widthBytesLine,
31018                :                                pDraw, x, y + linesDone, width, 
31019                :                                nlines, format, pBuf);
31020                :
31021                :                    /* Note: NOT a call to WriteSwappedDataToClient,
31022                :                       as we do NOT byte swap */
31023                :                    if (im_return) {
31024                :                        pBuf += nlines * widthBytesLine;
31025                :                    } else {
31026                :                        ReformatImage (pBuf, 
31027                :                                       (int)(nlines * widthBytesLine), 
31028                :                                       1,
31029                :                                       ClientOrder (client));
31030                :
31031                :/* Don't split me, gcc pukes when you do */
31032                :                        (void)WriteToClient(client,
31033                :                                        (int)(nlines * widthBytesLine),
31034                :                                        pBuf);
31035                :                    }
31036                :                    linesDone += nlines;
31037                :                }
31038                :            }
31039                :        }
31040                :    }
31041                :    if (pVisibleRegion)
31042                :        REGION_DESTROY(pDraw->pScreen, pVisibleRegion);
31043                :    if (!im_return)
31044                :        DEALLOCATE_LOCAL(pBuf);
31045                :    return (client->noClientException);
31046                :}
31047                :
31048                :int
31049                :ProcGetImage(ClientPtr client)
31050                :{
31051                :    REQUEST(xGetImageReq);
31052                :
31053                :    REQUEST_SIZE_MATCH(xGetImageReq);
31054                :
31055                :    return DoGetImage(client, stuff->format, stuff->drawable,
31056                :                      stuff->x, stuff->y,
31057                :                      (int)stuff->width, (int)stuff->height,
31058                :                      stuff->planeMask, (xGetImageReply **)NULL);
31059                :}
31060                :
31061                :int
31062                :ProcPolyText(ClientPtr client)
31063                :{
31064                :    int err;
31065                :    REQUEST(xPolyTextReq);
31066                :    DrawablePtr pDraw;
31067                :    GC *pGC;
31068                :
31069                :    REQUEST_AT_LEAST_SIZE(xPolyTextReq);
31070                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
31071                :
31072                :    err = PolyText(client,
31073                :                   pDraw,
31074                :                   pGC,
31075                :                   (unsigned char *)&stuff[1],
31076                :                   ((unsigned char *) stuff) + (client->req_len << 2),
31077                :                   stuff->x,
31078                :                   stuff->y,
31079                :                   stuff->reqType,
31080                :                   stuff->drawable);
31081                :
31082                :    if (err == Success)
31083                :    {
31084                :        return(client->noClientException);
31085                :    }
31086                :    else
31087                :        return err;
31088                :}
31089                :
31090                :int
31091                :ProcImageText8(ClientPtr client)
31092                :{
31093                :    int err;
31094                :    DrawablePtr pDraw;
31095                :    GC *pGC;
31096                :
31097                :    REQUEST(xImageTextReq);
31098                :
31099                :    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
31100                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
31101                :
31102                :    err = ImageText(client,
31103                :                    pDraw,
31104                :                    pGC,
31105                :                    stuff->nChars,
31106                :                    (unsigned char *)&stuff[1],
31107                :                    stuff->x,
31108                :                    stuff->y,
31109                :                    stuff->reqType,
31110                :                    stuff->drawable);
31111                :
31112                :    if (err == Success)
31113                :    {
31114                :        return(client->noClientException);
31115                :    }
31116                :    else
31117                :        return err;
31118                :}
31119                :
31120                :int
31121                :ProcImageText16(ClientPtr client)
31122                :{
31123                :    int err;
31124                :    DrawablePtr pDraw;
31125                :    GC *pGC;
31126                :
31127                :    REQUEST(xImageTextReq);
31128                :
31129                :    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
31130                :    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
31131                :
31132                :    err = ImageText(client,
31133                :                    pDraw,
31134                :                    pGC,
31135                :                    stuff->nChars,
31136                :                    (unsigned char *)&stuff[1],
31137                :                    stuff->x,
31138                :                    stuff->y,
31139                :                    stuff->reqType,
31140                :                    stuff->drawable);
31141                :
31142                :    if (err == Success)
31143                :    {
31144                :        return(client->noClientException);
31145                :    }
31146                :    else
31147                :        return err;
31148                :}
31149                :
31150                :
31151                :int
31152                :ProcCreateColormap(ClientPtr client)
31153                :{
31154                :    VisualPtr   pVisual;
31155                :    ColormapPtr pmap;
31156                :    Colormap    mid;
31157                :    WindowPtr   pWin;
31158                :    ScreenPtr pScreen;
31159                :    REQUEST(xCreateColormapReq);
31160                :    int i, result;
31161                :
31162                :    REQUEST_SIZE_MATCH(xCreateColormapReq);
31163                :
31164                :    if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll))
31165                :    {
31166                :        client->errorValue = stuff->alloc;
31167                :        return(BadValue);
31168                :    }
31169                :    mid = stuff->mid;
31170                :    LEGAL_NEW_RESOURCE(mid, client);
31171                :    result = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
31172                :    if (result != Success)
31173                :        return result;
31174                :
31175                :    pScreen = pWin->drawable.pScreen;
31176                :    for (i = 0, pVisual = pScreen->visuals;
31177                :         i < pScreen->numVisuals;
31178                :         i++, pVisual++)
31179                :    {
31180                :        if (pVisual->vid != stuff->visual)
31181                :            continue;
31182                :        result =  CreateColormap(mid, pScreen, pVisual, &pmap,
31183                :                                 (int)stuff->alloc, client->index);
31184                :        if (client->noClientException != Success)
31185                :            return(client->noClientException);
31186                :        else
31187                :            return(result);
31188                :    }
31189                :    client->errorValue = stuff->visual;
31190                :    return(BadMatch);
31191                :}
31192                :
31193                :int
31194                :ProcFreeColormap(ClientPtr client)
31195                :{
31196                :    ColormapPtr pmap;
31197                :    REQUEST(xResourceReq);
31198                :
31199                :    REQUEST_SIZE_MATCH(xResourceReq);
31200                :    pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP,
31201                :                                                DixDestroyAccess);
31202                :    if (pmap) 
31203                :    {
31204                :        /* Freeing a default colormap is a no-op */
31205                :        if (!(pmap->flags & IsDefault))
31206                :            FreeResource(stuff->id, RT_NONE);
31207                :        return (client->noClientException);
31208                :    }
31209                :    else 
31210                :    {
31211                :        client->errorValue = stuff->id;
31212                :        return (BadColor);
31213                :    }
31214                :}
31215                :
31216                :
31217                :int
31218                :ProcCopyColormapAndFree(ClientPtr client)
31219                :{
31220                :    Colormap    mid;
31221                :    ColormapPtr pSrcMap;
31222                :    REQUEST(xCopyColormapAndFreeReq);
31223                :    int result;
31224                :
31225                :    REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
31226                :    mid = stuff->mid;
31227                :    LEGAL_NEW_RESOURCE(mid, client);
31228                :    if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap,
31229                :                RT_COLORMAP, DixReadAccess|DixWriteAccess)) )
31230                :    {
31231                :        result = CopyColormapAndFree(mid, pSrcMap, client->index);
31232                :        if (client->noClientException != Success)
31233                :            return(client->noClientException);
31234                :        else
31235                :            return(result);
31236                :    }
31237                :    else
31238                :    {
31239                :        client->errorValue = stuff->srcCmap;
31240                :        return(BadColor);
31241                :    }
31242                :}
31243                :
31244                :int
31245                :ProcInstallColormap(ClientPtr client)
31246                :{
31247                :    ColormapPtr pcmp;
31248                :    REQUEST(xResourceReq);
31249                :
31250                :    REQUEST_SIZE_MATCH(xResourceReq);
31251                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id,
31252                :                                            RT_COLORMAP, DixReadAccess);
31253                :    if (pcmp)
31254                :    {
31255                :        (*(pcmp->pScreen->InstallColormap)) (pcmp);
31256                :        return (client->noClientException);        
31257                :    }
31258                :    else
31259                :    {
31260                :        client->errorValue = stuff->id;
31261                :        return (BadColor);
31262                :    }
31263                :}
31264                :
31265                :int
31266                :ProcUninstallColormap(ClientPtr client)
31267                :{
31268                :    ColormapPtr pcmp;
31269                :    REQUEST(xResourceReq);
31270                :
31271                :    REQUEST_SIZE_MATCH(xResourceReq);
31272                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id,
31273                :                                        RT_COLORMAP, DixReadAccess);
31274                :    if (pcmp)
31275                :    {
31276                :        if(pcmp->mid != pcmp->pScreen->defColormap)
31277                :            (*(pcmp->pScreen->UninstallColormap)) (pcmp);
31278                :        return (client->noClientException);        
31279                :    }
31280                :    else
31281                :    {
31282                :        client->errorValue = stuff->id;
31283                :        return (BadColor);
31284                :    }
31285                :}
31286                :
31287                :int
31288                :ProcListInstalledColormaps(ClientPtr client)
31289                :{
31290                :    xListInstalledColormapsReply *preply; 
31291                :    int nummaps, rc;
31292                :    WindowPtr pWin;
31293                :    REQUEST(xResourceReq);
31294                :
31295                :    REQUEST_SIZE_MATCH(xResourceReq);
31296                :    rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
31297                :    if (rc != Success)
31298                :        return rc;
31299                :
31300                :    preply = (xListInstalledColormapsReply *) 
31301                :                ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) +
31302                :                     pWin->drawable.pScreen->maxInstalledCmaps *
31303                :                     sizeof(Colormap));
31304                :    if(!preply)
31305                :        return(BadAlloc);
31306                :
31307                :    preply->type = X_Reply;
31308                :    preply->sequenceNumber = client->sequence;
31309                :    nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
31310                :        (pWin->drawable.pScreen, (Colormap *)&preply[1]);
31311                :    preply->nColormaps = nummaps;
31312                :    preply->length = nummaps;
31313                :    WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply);
31314                :    client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
31315                :    WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
31316                :    DEALLOCATE_LOCAL(preply);
31317                :    return(client->noClientException);
31318                :}
31319                :
31320                :int
31321                :ProcAllocColor (ClientPtr client)
31322                :{
31323                :    ColormapPtr pmap;
31324                :    int retval;
31325                :    xAllocColorReply acr;
31326                :    REQUEST(xAllocColorReq);
31327                :
31328                :    REQUEST_SIZE_MATCH(xAllocColorReq);
31329                :    pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31330                :                                        RT_COLORMAP, DixWriteAccess);
31331                :    if (pmap)
31332                :    {
31333                :        acr.type = X_Reply;
31334                :        acr.length = 0;
31335                :        acr.sequenceNumber = client->sequence;
31336                :        acr.red = stuff->red;
31337                :        acr.green = stuff->green;
31338                :        acr.blue = stuff->blue;
31339                :        acr.pixel = 0;
31340                :        if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
31341                :                               &acr.pixel, client->index)) )
31342                :        {
31343                :            if (client->noClientException != Success)
31344                :                return(client->noClientException);
31345                :            else
31346                :                return (retval);
31347                :        }
31348                :#ifdef PANORAMIX
31349                :        if (noPanoramiXExtension || !pmap->pScreen->myNum)
31350                :#endif
31351                :        WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
31352                :        return (client->noClientException);
31353                :
31354                :    }
31355                :    else
31356                :    {
31357                :        client->errorValue = stuff->cmap;
31358                :        return (BadColor);
31359                :    }
31360                :}
31361                :
31362                :int
31363                :ProcAllocNamedColor (ClientPtr client)
31364                :{
31365                :    ColormapPtr pcmp;
31366                :    REQUEST(xAllocNamedColorReq);
31367                :
31368                :    REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
31369                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31370                :                                            RT_COLORMAP, DixWriteAccess);
31371                :    if (pcmp)
31372                :    {
31373                :        int             retval;
31374                :
31375                :        xAllocNamedColorReply ancr;
31376                :
31377                :        ancr.type = X_Reply;
31378                :        ancr.length = 0;
31379                :        ancr.sequenceNumber = client->sequence;
31380                :
31381                :        if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes,
31382                :                         &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue))
31383                :        {
31384                :            ancr.screenRed = ancr.exactRed;
31385                :            ancr.screenGreen = ancr.exactGreen;
31386                :            ancr.screenBlue = ancr.exactBlue;
31387                :            ancr.pixel = 0;
31388                :            if( (retval = AllocColor(pcmp,
31389                :                         &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue,
31390                :                         &ancr.pixel, client->index)) )
31391                :            {
31392                :                if (client->noClientException != Success)
31393                :                    return(client->noClientException);
31394                :                else
31395                :                    return(retval);
31396                :            }
31397                :#ifdef PANORAMIX
31398                :            if (noPanoramiXExtension || !pcmp->pScreen->myNum)
31399                :#endif
31400                :            WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr);
31401                :            return (client->noClientException);
31402                :        }
31403                :        else
31404                :            return(BadName);
31405                :        
31406                :    }
31407                :    else
31408                :    {
31409                :        client->errorValue = stuff->cmap;
31410                :        return (BadColor);
31411                :    }
31412                :}
31413                :
31414                :int
31415                :ProcAllocColorCells (ClientPtr client)
31416                :{
31417                :    ColormapPtr pcmp;
31418                :    REQUEST(xAllocColorCellsReq);
31419                :
31420                :    REQUEST_SIZE_MATCH(xAllocColorCellsReq);
31421                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31422                :                                        RT_COLORMAP, DixWriteAccess);
31423                :    if (pcmp)
31424                :    {
31425                :        xAllocColorCellsReply   accr;
31426                :        int                     npixels, nmasks, retval;
31427                :        long                    length;
31428                :        Pixel                   *ppixels, *pmasks;
31429                :
31430                :        npixels = stuff->colors;
31431                :        if (!npixels)
31432                :        {
31433                :            client->errorValue = npixels;
31434                :            return (BadValue);
31435                :        }
31436                :        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse)
31437                :        {
31438                :            client->errorValue = stuff->contiguous;
31439                :            return (BadValue);
31440                :        }
31441                :        nmasks = stuff->planes;
31442                :        length = ((long)npixels + (long)nmasks) * sizeof(Pixel);
31443                :        ppixels = (Pixel *)ALLOCATE_LOCAL(length);
31444                :        if(!ppixels)
31445                :            return(BadAlloc);
31446                :        pmasks = ppixels + npixels;
31447                :
31448                :        if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, 
31449                :                                    (Bool)stuff->contiguous, ppixels, pmasks)) )
31450                :        {
31451                :            DEALLOCATE_LOCAL(ppixels);
31452                :            if (client->noClientException != Success)
31453                :                return(client->noClientException);
31454                :            else
31455                :                return(retval);
31456                :        }
31457                :#ifdef PANORAMIX
31458                :        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
31459                :#endif
31460                :        {
31461                :            accr.type = X_Reply;
31462                :            accr.length = length >> 2;
31463                :            accr.sequenceNumber = client->sequence;
31464                :            accr.nPixels = npixels;
31465                :            accr.nMasks = nmasks;
31466                :            WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr);
31467                :            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
31468                :            WriteSwappedDataToClient(client, length, ppixels);
31469                :        }
31470                :        DEALLOCATE_LOCAL(ppixels);
31471                :        return (client->noClientException);        
31472                :    }
31473                :    else
31474                :    {
31475                :        client->errorValue = stuff->cmap;
31476                :        return (BadColor);
31477                :    }
31478                :}
31479                :
31480                :int
31481                :ProcAllocColorPlanes(ClientPtr client)
31482                :{
31483                :    ColormapPtr pcmp;
31484                :    REQUEST(xAllocColorPlanesReq);
31485                :
31486                :    REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
31487                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31488                :                                        RT_COLORMAP, DixWriteAccess);
31489                :    if (pcmp)
31490                :    {
31491                :        xAllocColorPlanesReply  acpr;
31492                :        int                     npixels, retval;
31493                :        long                    length;
31494                :        Pixel                   *ppixels;
31495                :
31496                :        npixels = stuff->colors;
31497                :        if (!npixels)
31498                :        {
31499                :            client->errorValue = npixels;
31500                :            return (BadValue);
31501                :        }
31502                :        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse)
31503                :        {
31504                :            client->errorValue = stuff->contiguous;
31505                :            return (BadValue);
31506                :        }
31507                :        acpr.type = X_Reply;
31508                :        acpr.sequenceNumber = client->sequence;
31509                :        acpr.nPixels = npixels;
31510                :        length = (long)npixels * sizeof(Pixel);
31511                :        ppixels = (Pixel *)ALLOCATE_LOCAL(length);
31512                :        if(!ppixels)
31513                :            return(BadAlloc);
31514                :        if( (retval = AllocColorPlanes(client->index, pcmp, npixels,
31515                :            (int)stuff->red, (int)stuff->green, (int)stuff->blue,
31516                :            (Bool)stuff->contiguous, ppixels,
31517                :            &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) )
31518                :        {
31519                :            DEALLOCATE_LOCAL(ppixels);
31520                :            if (client->noClientException != Success)
31521                :                return(client->noClientException);
31522                :            else
31523                :                return(retval);
31524                :        }
31525                :        acpr.length = length >> 2;
31526                :#ifdef PANORAMIX
31527                :        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
31528                :#endif
31529                :        {
31530                :            WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
31531                :            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
31532                :            WriteSwappedDataToClient(client, length, ppixels);
31533                :        }
31534                :        DEALLOCATE_LOCAL(ppixels);
31535                :        return (client->noClientException);        
31536                :    }
31537                :    else
31538                :    {
31539                :        client->errorValue = stuff->cmap;
31540                :        return (BadColor);
31541                :    }
31542                :}
31543                :
31544                :int
31545                :ProcFreeColors(ClientPtr client)
31546                :{
31547                :    ColormapPtr pcmp;
31548                :    REQUEST(xFreeColorsReq);
31549                :
31550                :    REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
31551                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31552                :                                        RT_COLORMAP, DixWriteAccess);
31553                :    if (pcmp)
31554                :    {
31555                :        int     count;
31556                :        int     retval;
31557                :
31558                :        if(pcmp->flags & AllAllocated)
31559                :            return(BadAccess);
31560                :        count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2;
31561                :        retval =  FreeColors(pcmp, client->index, count,
31562                :            (Pixel *)&stuff[1], (Pixel)stuff->planeMask);
31563                :        if (client->noClientException != Success)
31564                :            return(client->noClientException);
31565                :        else
31566                :        {
31567                :            client->errorValue = clientErrorValue;
31568                :            return(retval);
31569                :        }
31570                :
31571                :    }
31572                :    else
31573                :    {
31574                :        client->errorValue = stuff->cmap;
31575                :        return (BadColor);
31576                :    }
31577                :}
31578                :
31579                :int
31580                :ProcStoreColors (ClientPtr client)
31581                :{
31582                :    ColormapPtr pcmp;
31583                :    REQUEST(xStoreColorsReq);
31584                :
31585                :    REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
31586                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31587                :                                        RT_COLORMAP, DixWriteAccess);
31588                :    if (pcmp)
31589                :    {
31590                :        int     count;
31591                :        int     retval;
31592                :
31593                :        count = (client->req_len << 2) - sizeof(xStoreColorsReq);
31594                :        if (count % sizeof(xColorItem))
31595                :            return(BadLength);
31596                :        count /= sizeof(xColorItem);
31597                :        retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]);
31598                :        if (client->noClientException != Success)
31599                :            return(client->noClientException);
31600                :        else
31601                :        {
31602                :            client->errorValue = clientErrorValue;
31603                :            return(retval);
31604                :        }
31605                :    }
31606                :    else
31607                :    {
31608                :        client->errorValue = stuff->cmap;
31609                :        return (BadColor);
31610                :    }
31611                :}
31612                :
31613                :int
31614                :ProcStoreNamedColor (ClientPtr client)
31615                :{
31616                :    ColormapPtr pcmp;
31617                :    REQUEST(xStoreNamedColorReq);
31618                :
31619                :    REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
31620                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31621                :                                        RT_COLORMAP, DixWriteAccess);
31622                :    if (pcmp)
31623                :    {
31624                :        xColorItem      def;
31625                :        int             retval;
31626                :
31627                :        if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1],
31628                :                         stuff->nbytes, &def.red, &def.green, &def.blue))
31629                :        {
31630                :            def.flags = stuff->flags;
31631                :            def.pixel = stuff->pixel;
31632                :            retval = StoreColors(pcmp, 1, &def);
31633                :            if (client->noClientException != Success)
31634                :                return(client->noClientException);
31635                :            else
31636                :                return(retval);
31637                :        }
31638                :        return (BadName);        
31639                :    }
31640                :    else
31641                :    {
31642                :        client->errorValue = stuff->cmap;
31643                :        return (BadColor);
31644                :    }
31645                :}
31646                :
31647                :int
31648                :ProcQueryColors(ClientPtr client)
31649                :{
31650                :    ColormapPtr pcmp;
31651                :    REQUEST(xQueryColorsReq);
31652                :
31653                :    REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
31654                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31655                :                                        RT_COLORMAP, DixReadAccess);
31656                :    if (pcmp)
31657                :    {
31658                :        int                     count, retval;
31659                :        xrgb                    *prgbs;
31660                :        xQueryColorsReply       qcr;
31661                :
31662                :        count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2;
31663                :        prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb));
31664                :        if(!prgbs && count)
31665                :            return(BadAlloc);
31666                :        if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) )
31667                :        {
31668                :            if (prgbs) DEALLOCATE_LOCAL(prgbs);
31669                :            if (client->noClientException != Success)
31670                :                return(client->noClientException);
31671                :            else
31672                :            {
31673                :                client->errorValue = clientErrorValue;
31674                :                return (retval);
31675                :            }
31676                :        }
31677                :        qcr.type = X_Reply;
31678                :        qcr.length = (count * sizeof(xrgb)) >> 2;
31679                :        qcr.sequenceNumber = client->sequence;
31680                :        qcr.nColors = count;
31681                :        WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
31682                :        if (count)
31683                :        {
31684                :            client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
31685                :            WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
31686                :        }
31687                :        if (prgbs) DEALLOCATE_LOCAL(prgbs);
31688                :        return(client->noClientException);
31689                :        
31690                :    }
31691                :    else
31692                :    {
31693                :        client->errorValue = stuff->cmap;
31694                :        return (BadColor);
31695                :    }
31696                :} 
31697                :
31698                :int
31699                :ProcLookupColor(ClientPtr client)
31700                :{
31701                :    ColormapPtr pcmp;
31702                :    REQUEST(xLookupColorReq);
31703                :
31704                :    REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
31705                :    pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap,
31706                :                                        RT_COLORMAP, DixReadAccess);
31707                :    if (pcmp)
31708                :    {
31709                :        xLookupColorReply lcr;
31710                :
31711                :        if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes,
31712                :                         &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue))
31713                :        {
31714                :            lcr.type = X_Reply;
31715                :            lcr.length = 0;
31716                :            lcr.sequenceNumber = client->sequence;
31717                :            lcr.screenRed = lcr.exactRed;
31718                :            lcr.screenGreen = lcr.exactGreen;
31719                :            lcr.screenBlue = lcr.exactBlue;
31720                :            (*pcmp->pScreen->ResolveColor)(&lcr.screenRed,
31721                :                                           &lcr.screenGreen,
31722                :                                           &lcr.screenBlue,
31723                :                                           pcmp->pVisual);
31724                :            WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
31725                :            return(client->noClientException);
31726                :        }
31727                :        return (BadName);        
31728                :    }
31729                :    else
31730                :    {
31731                :        client->errorValue = stuff->cmap;
31732                :        return (BadColor);
31733                :    }
31734                :}
31735                :
31736                :int
31737                :ProcCreateCursor (ClientPtr client)
31738                :{
31739                :    CursorPtr           pCursor;
31740                :    PixmapPtr           src;
31741                :    PixmapPtr           msk;
31742                :    unsigned char *     srcbits;
31743                :    unsigned char *     mskbits;
31744                :    unsigned short      width, height;
31745                :    long                n;
31746                :    CursorMetricRec     cm;
31747                :
31748                :
31749                :    REQUEST(xCreateCursorReq);
31750                :
31751                :    REQUEST_SIZE_MATCH(xCreateCursorReq);
31752                :    LEGAL_NEW_RESOURCE(stuff->cid, client);
31753                :
31754                :    src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source,
31755                :                                              RT_PIXMAP, DixReadAccess);
31756                :    msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask,
31757                :                                              RT_PIXMAP, DixReadAccess);
31758                :    if (   src == (PixmapPtr)NULL)
31759                :    {
31760                :        client->errorValue = stuff->source;
31761                :        return (BadPixmap);
31762                :    }
31763                :    if ( msk == (PixmapPtr)NULL)
31764                :    {
31765                :        if (stuff->mask != None)
31766                :        {
31767                :            client->errorValue = stuff->mask;
31768                :            return (BadPixmap);
31769                :        }
31770                :    }
31771                :    else if (  src->drawable.width != msk->drawable.width
31772                :            || src->drawable.height != msk->drawable.height
31773                :            || src->drawable.depth != 1
31774                :            || msk->drawable.depth != 1)
31775                :        return (BadMatch);
31776                :
31777                :    width = src->drawable.width;
31778                :    height = src->drawable.height;
31779                :
31780                :    if ( stuff->x > width 
31781                :      || stuff->y > height )
31782                :        return (BadMatch);
31783                :
31784                :    n = BitmapBytePad(width)*height;
31785                :    srcbits = (unsigned char *)xalloc(n);
31786                :    if (!srcbits)
31787                :        return (BadAlloc);
31788                :    mskbits = (unsigned char *)xalloc(n);
31789                :    if (!mskbits)
31790                :    {
31791                :        xfree(srcbits);
31792                :        return (BadAlloc);
31793                :    }
31794                :
31795                :    /* zeroing the (pad) bits helps some ddx cursor handling */
31796                :    bzero((char *)srcbits, n);
31797                :    (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height,
31798                :                                         XYPixmap, 1, (pointer)srcbits);
31799                :    if ( msk == (PixmapPtr)NULL)
31800                :    {
31801                :        unsigned char *bits = mskbits;
31802                :        while (--n >= 0)
31803                :            *bits++ = ~0;
31804                :    }
31805                :    else
31806                :    {
31807                :        /* zeroing the (pad) bits helps some ddx cursor handling */
31808                :        bzero((char *)mskbits, n);
31809                :        (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width,
31810                :                                        height, XYPixmap, 1, (pointer)mskbits);
31811                :    }
31812                :    cm.width = width;
31813                :    cm.height = height;
31814                :    cm.xhot = stuff->x;
31815                :    cm.yhot = stuff->y;
31816                :    pCursor = AllocCursor( srcbits, mskbits, &cm,
31817                :            stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
31818                :            stuff->backRed, stuff->backGreen, stuff->backBlue);
31819                :
31820                :    if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
31821                :            return (client->noClientException);
31822                :    return BadAlloc;
31823                :}
31824                :
31825                :int
31826                :ProcCreateGlyphCursor (ClientPtr client)
31827                :{
31828                :    CursorPtr pCursor;
31829                :    int res;
31830                :
31831                :    REQUEST(xCreateGlyphCursorReq);
31832                :
31833                :    REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
31834                :    LEGAL_NEW_RESOURCE(stuff->cid, client);
31835                :
31836                :    res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
31837                :                           stuff->mask, stuff->maskChar,
31838                :                           stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
31839                :                           stuff->backRed, stuff->backGreen, stuff->backBlue,
31840                :                           &pCursor, client);
31841                :    if (res != Success)
31842                :        return res;
31843                :    if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
31844                :        return client->noClientException;
31845                :    return BadAlloc;
31846                :}
31847                :
31848                :
31849                :int
31850                :ProcFreeCursor (ClientPtr client)
31851                :{
31852                :    CursorPtr pCursor;
31853                :    REQUEST(xResourceReq);
31854                :
31855                :    REQUEST_SIZE_MATCH(xResourceReq);
31856                :    pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id,
31857                :                                        RT_CURSOR, DixDestroyAccess);
31858                :    if (pCursor) 
31859                :    {
31860                :        FreeResource(stuff->id, RT_NONE);
31861                :        return (client->noClientException);
31862                :    }
31863                :    else 
31864                :    {
31865                :        client->errorValue = stuff->id;
31866                :        return (BadCursor);
31867                :    }
31868                :}
31869                :
31870                :int
31871                :ProcQueryBestSize (ClientPtr client)
31872                :{
31873                :    xQueryBestSizeReply reply;
31874                :    DrawablePtr pDraw;
31875                :    ScreenPtr pScreen;
31876                :    int rc;
31877                :    REQUEST(xQueryBestSizeReq);
31878                :    REQUEST_SIZE_MATCH(xQueryBestSizeReq);
31879                :
31880                :    if ((stuff->class != CursorShape) && 
31881                :        (stuff->class != TileShape) && 
31882                :        (stuff->class != StippleShape))
31883                :    {
31884                :        client->errorValue = stuff->class;
31885                :        return(BadValue);
31886                :    }
31887                :
31888                :    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
31889                :                           DixReadAccess);
31890                :    if (rc != Success)
31891                :        return rc;
31892                :    if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
31893                :        return (BadMatch);
31894                :    pScreen = pDraw->pScreen;
31895                :    (* pScreen->QueryBestSize)(stuff->class, &stuff->width,
31896                :                               &stuff->height, pScreen);
31897                :    reply.type = X_Reply;
31898                :    reply.length = 0;
31899                :    reply.sequenceNumber = client->sequence;
31900                :    reply.width = stuff->width;
31901                :    reply.height = stuff->height;
31902                :    WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
31903                :    return (client->noClientException);
31904                :}
31905                :
31906                :
31907                :int
31908                :ProcSetScreenSaver (ClientPtr client)
31909                :{
31910                :    int blankingOption, exposureOption;
31911                :    REQUEST(xSetScreenSaverReq);
31912                :
31913                :    REQUEST_SIZE_MATCH(xSetScreenSaverReq);
31914                :    blankingOption = stuff->preferBlank;
31915                :    if ((blankingOption != DontPreferBlanking) &&
31916                :        (blankingOption != PreferBlanking) &&
31917                :        (blankingOption != DefaultBlanking))
31918                :    {
31919                :        client->errorValue = blankingOption;
31920                :        return BadValue;
31921                :    }
31922                :    exposureOption = stuff->allowExpose;
31923                :    if ((exposureOption != DontAllowExposures) &&
31924                :        (exposureOption != AllowExposures) &&
31925                :        (exposureOption != DefaultExposures))
31926                :    {
31927                :        client->errorValue = exposureOption;
31928                :        return BadValue;
31929                :    }
31930                :    if (stuff->timeout < -1)
31931                :    {
31932                :        client->errorValue = stuff->timeout;
31933                :        return BadValue;
31934                :    }
31935                :    if (stuff->interval < -1)
31936                :    {
31937                :        client->errorValue = stuff->interval;
31938                :        return BadValue;
31939                :    }
31940                :
31941                :    if (blankingOption == DefaultBlanking)
31942                :        ScreenSaverBlanking = defaultScreenSaverBlanking;
31943                :    else
31944                :        ScreenSaverBlanking = blankingOption; 
31945                :    if (exposureOption == DefaultExposures)
31946                :        ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
31947                :    else
31948                :        ScreenSaverAllowExposures = exposureOption;
31949                :
31950                :    if (stuff->timeout >= 0)
31951                :        ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
31952                :    else 
31953                :        ScreenSaverTime = defaultScreenSaverTime;
31954                :    if (stuff->interval >= 0)
31955                :        ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
31956                :    else
31957                :        ScreenSaverInterval = defaultScreenSaverInterval;
31958                :
31959                :    SetScreenSaverTimer();
31960                :    return (client->noClientException);
31961                :}
31962                :
31963                :int
31964                :ProcGetScreenSaver(ClientPtr client)
31965                :{
31966                :    xGetScreenSaverReply rep;
31967                :
31968                :    REQUEST_SIZE_MATCH(xReq);
31969                :    rep.type = X_Reply;
31970                :    rep.length = 0;
31971                :    rep.sequenceNumber = client->sequence;
31972                :    rep.timeout = ScreenSaverTime / MILLI_PER_SECOND;
31973                :    rep.interval = ScreenSaverInterval / MILLI_PER_SECOND;
31974                :    rep.preferBlanking = ScreenSaverBlanking;
31975                :    rep.allowExposures = ScreenSaverAllowExposures;
31976                :    WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
31977                :    return (client->noClientException);
31978                :}
31979                :
31980                :int
31981                :ProcChangeHosts(ClientPtr client)
31982                :{
31983                :    REQUEST(xChangeHostsReq);
31984                :    int result;
31985                :
31986                :    REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
31987                :
31988                :    if(stuff->mode == HostInsert)
31989                :        result = AddHost(client, (int)stuff->hostFamily,
31990                :                         stuff->hostLength, (pointer)&stuff[1]);
31991                :    else if (stuff->mode == HostDelete)
31992                :        result = RemoveHost(client, (int)stuff->hostFamily, 
31993                :                            stuff->hostLength, (pointer)&stuff[1]);  
31994                :    else
31995                :    {
31996                :        client->errorValue = stuff->mode;
31997                :        return BadValue;
31998                :    }
31999                :    if (!result)
32000                :        result = client->noClientException;
32001                :    return (result);
32002                :}
32003                :
32004                :int
32005                :ProcListHosts(ClientPtr client)
32006                :{
32007                :    xListHostsReply reply;
32008                :    int len, nHosts, result;
32009                :    pointer     pdata;
32010                :    /* REQUEST(xListHostsReq); */
32011                :
32012                :    REQUEST_SIZE_MATCH(xListHostsReq);
32013                :
32014                :    /* untrusted clients can't list hosts */
32015                :    if (!XaceHook(XACE_HOSTLIST_ACCESS, client, DixReadAccess))
32016                :        return BadAccess;
32017                :
32018                :    result = GetHosts(&pdata, &nHosts, &len, &reply.enabled);
32019                :    if (result != Success)
32020                :        return(result);
32021                :    reply.type = X_Reply;
32022                :    reply.sequenceNumber = client->sequence;
32023                :    reply.nHosts = nHosts;
32024                :    reply.length = len >> 2;
32025                :    WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
32026                :    if (nHosts)
32027                :    {
32028                :        client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
32029                :        WriteSwappedDataToClient(client, len, pdata);
32030                :    }
32031                :    xfree(pdata);
32032                :    return (client->noClientException);
32033                :}
32034                :
32035                :int
32036                :ProcChangeAccessControl(ClientPtr client)
32037                :{
32038                :    int result;
32039                :    REQUEST(xSetAccessControlReq);
32040                :
32041                :    REQUEST_SIZE_MATCH(xSetAccessControlReq);
32042                :    if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess))
32043                :    {
32044                :        client->errorValue = stuff->mode;
32045                :        return BadValue;
32046                :    }
32047                :    result = ChangeAccessControl(client, stuff->mode == EnableAccess);
32048                :    if (!result)
32049                :        result = client->noClientException;
32050                :    return (result);
32051                :}
32052                :
32053                :/*********************
32054                : * CloseDownRetainedResources
32055                : *
32056                : *    Find all clients that are gone and have terminated in RetainTemporary 
32057                : *    and destroy their resources.
32058                : *********************/
32059                :
32060                :static void
32061                :CloseDownRetainedResources(void)
32062                :{
32063                :    int i;
32064                :    ClientPtr client;
32065                :
32066                :    for (i=1; i<currentMaxClients; i++)
32067                :    {
32068                :        client = clients[i];
32069                :        if (client && (client->closeDownMode == RetainTemporary)
32070                :            && (client->clientGone))
32071                :            CloseDownClient(client);
32072                :    }
32073                :}
32074                :
32075                :int
32076                :ProcKillClient(ClientPtr client)
32077                :{
32078                :    REQUEST(xResourceReq);
32079                :    ClientPtr killclient;
32080                :    int rc;
32081                :
32082                :    REQUEST_SIZE_MATCH(xResourceReq);
32083                :    if (stuff->id == AllTemporary)
32084                :    {
32085                :        CloseDownRetainedResources();
32086                :        return (client->noClientException);
32087                :    }
32088                :
32089                :    rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
32090                :    if (rc == Success) {
32091                :        CloseDownClient(killclient);
32092                :        /* if an LBX proxy gets killed, isItTimeToYield will be set */
32093                :        if (isItTimeToYield || (client == killclient))
32094                :        {
32095                :            /* force yield and return Success, so that Dispatch()
32096                :             * doesn't try to touch client
32097                :             */
32098                :            isItTimeToYield = TRUE;
32099                :            return (Success);
32100                :        }
32101                :        return (client->noClientException);
32102                :    }
32103                :    else
32104                :        return rc;
32105                :}
32106                :
32107                :int
32108                :ProcSetFontPath(ClientPtr client)
32109                :{
32110                :    unsigned char *ptr;
32111                :    unsigned long nbytes, total;
32112                :    long nfonts;
32113                :    int n, result;
32114                :    int error;
32115                :    REQUEST(xSetFontPathReq);
32116                :    
32117                :    REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
32118                :    
32119                :    nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
32120                :    total = nbytes;
32121                :    ptr = (unsigned char *)&stuff[1];
32122                :    nfonts = stuff->nFonts;
32123                :    while (--nfonts >= 0)
32124                :    {
32125                :        if ((total == 0) || (total < (n = (*ptr + 1))))
32126                :            return(BadLength);
32127                :        total -= n;
32128                :        ptr += n;
32129                :    }
32130                :    if (total >= 4)
32131                :        return(BadLength);
32132                :    result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1],
32133                :                         &error);
32134                :    if (!result)
32135                :    {
32136                :        result = client->noClientException;
32137                :        client->errorValue = error;
32138                :    }
32139                :    return (result);
32140                :}
32141                :
32142                :int
32143                :ProcGetFontPath(ClientPtr client)
32144                :{
32145                :    xGetFontPathReply reply;
32146                :    int stringLens, numpaths;
32147                :    unsigned char *bufferStart;
32148                :    /* REQUEST (xReq); */
32149                :
32150                :    REQUEST_SIZE_MATCH(xReq);
32151                :    bufferStart = GetFontPath(&numpaths, &stringLens);
32152                :
32153                :    reply.type = X_Reply;
32154                :    reply.sequenceNumber = client->sequence;
32155                :    reply.length = (stringLens + numpaths + 3) >> 2;
32156                :    reply.nPaths = numpaths;
32157                :
32158                :    WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
32159                :    if (stringLens || numpaths)
32160                :        (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart);
32161                :    return(client->noClientException);
32162                :}
32163                :
32164                :int
32165                :ProcChangeCloseDownMode(ClientPtr client)
32166                :{
32167                :    REQUEST(xSetCloseDownModeReq);
32168                :
32169                :    REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
32170                :    if ((stuff->mode == AllTemporary) ||
32171                :        (stuff->mode == RetainPermanent) ||
32172                :        (stuff->mode == RetainTemporary))
32173                :    {
32174                :        client->closeDownMode = stuff->mode;
32175                :        return (client->noClientException);
32176                :    }
32177                :    else   
32178                :    {
32179                :        client->errorValue = stuff->mode;
32180                :        return (BadValue);
32181                :    }
32182                :}
32183                :
32184                :int ProcForceScreenSaver(ClientPtr client)
32185                :{    
32186                :    REQUEST(xForceScreenSaverReq);
32187                :
32188                :    REQUEST_SIZE_MATCH(xForceScreenSaverReq);
32189                :    
32190                :    if ((stuff->mode != ScreenSaverReset) && 
32191                :        (stuff->mode != ScreenSaverActive))
32192                :    {
32193                :        client->errorValue = stuff->mode;
32194                :        return BadValue;
32195                :    }
32196                :    SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode);
32197                :    return client->noClientException;
32198                :}
32199                :
32200                :int ProcNoOperation(ClientPtr client)
32201                :{
32202                :    REQUEST_AT_LEAST_SIZE(xReq);
32203                :    
32204                :    /* noop -- don't do anything */
32205                :    return(client->noClientException);
32206                :}
32207                :
32208                :void
32209                :InitProcVectors(void)
32210                :{
32211                :    int i;
32212                :    for (i = 0; i<256; i++)
32213                :    {
32214                :        if(!ProcVector[i])
32215                :        {
32216                :            ProcVector[i] = SwappedProcVector[i] = ProcBadRequest;
32217                :            ReplySwapVector[i] = ReplyNotSwappd;
32218                :        }
32219                :    }
32220                :    for(i = LASTEvent; i < 128; i++)
32221                :    {
32222                :        EventSwapVector[i] = NotImplemented;
32223                :    }
32224                :    
32225                :}
32226                :
32227                :/**********************
32228                : * CloseDownClient
32229                : *
32230                : *  Client can either mark his resources destroy or retain.  If retained and
32231                : *  then killed again, the client is really destroyed.
32232                : *********************/
32233                :
32234                :char dispatchExceptionAtReset = DE_RESET;
32235                :
32236                :void
32237                :CloseDownClient(ClientPtr client)
32238                :{
32239                :    Bool really_close_down = client->clientGone ||
32240                :                             client->closeDownMode == DestroyAll;
32241                :
32242                :    if (!client->clientGone)
32243                :    {
32244                :        /* ungrab server if grabbing client dies */
32245                :        if (grabState != GrabNone && grabClient == client)
32246                :        {
32247                :            UngrabServer(client);
32248                :        }
32249                :        BITCLEAR(grabWaiters, client->index);
32250                :        DeleteClientFromAnySelections(client);
32251                :        ReleaseActiveGrabs(client);
32252                :        DeleteClientFontStuff(client);
32253                :        if (!really_close_down)
32254                :        {
32255                :            /*  This frees resources that should never be retained
32256                :             *  no matter what the close down mode is.  Actually we
32257                :             *  could do this unconditionally, but it's probably
32258                :             *  better not to traverse all the client's resources
32259                :             *  twice (once here, once a few lines down in
32260                :             *  FreeClientResources) in the common case of
32261                :             *  really_close_down == TRUE.
32262                :             */
32263                :            FreeClientNeverRetainResources(client);
32264                :            client->clientState = ClientStateRetained;
32265                :            if (ClientStateCallback)
32266                :            {
32267                :                NewClientInfoRec clientinfo;
32268                :
32269                :                clientinfo.client = client; 
32270                :                clientinfo.prefix = (xConnSetupPrefix *)NULL;  
32271                :                clientinfo.setup = (xConnSetup *) NULL;
32272                :                CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
32273                :            } 
32274                :        }
32275                :        client->clientGone = TRUE;  /* so events aren't sent to client */
32276                :        if (ClientIsAsleep(client))
32277                :            ClientSignal (client);
32278                :        ProcessWorkQueueZombies();
32279                :        CloseDownConnection(client);
32280                :
32281                :        /* If the client made it to the Running stage, nClients has
32282                :         * been incremented on its behalf, so we need to decrement it
32283                :         * now.  If it hasn't gotten to Running, nClients has *not*
32284                :         * been incremented, so *don't* decrement it.
32285                :         */
32286                :        if (client->clientState != ClientStateInitial &&
32287                :            client->clientState != ClientStateAuthenticating )
32288                :        {
32289                :            --nClients;
32290                :        }
32291                :    }
32292                :
32293                :    if (really_close_down)
32294                :    {
32295                :        if (client->clientState == ClientStateRunning && nClients == 0)
32296                :            dispatchException |= dispatchExceptionAtReset;
32297                :
32298                :        client->clientState = ClientStateGone;
32299                :        if (ClientStateCallback)
32300                :        {
32301                :            NewClientInfoRec clientinfo;
32302                :
32303                :            clientinfo.client = client; 
32304                :            clientinfo.prefix = (xConnSetupPrefix *)NULL;  
32305                :            clientinfo.setup = (xConnSetup *) NULL;
32306                :            CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
32307                :        }           
32308                :        FreeClientResources(client);
32309                :#ifdef XSERVER_DTRACE
32310                :        XSERVER_CLIENT_DISCONNECT(client->index);
32311                :#endif  
32312                :        if (client->index < nextFreeClientID)
32313                :            nextFreeClientID = client->index;
32314                :        clients[client->index] = NullClient;
32315                :#ifdef SMART_SCHEDULE
32316                :        SmartLastClient = NullClient;
32317                :#endif
32318                :        xfree(client);
32319                :
32320                :        while (!clients[currentMaxClients-1])
32321                :            currentMaxClients--;
32322                :    }
32323                :}
32324                :
32325                :static void
32326                :KillAllClients(void)
32327                :{
32328                :    int i;
32329                :    for (i=1; i<currentMaxClients; i++)
32330                :        if (clients[i]) {
32331                :            /* Make sure Retained clients are released. */
32332                :            clients[i]->closeDownMode = DestroyAll;
32333                :            CloseDownClient(clients[i]);     
32334                :        }
32335                :}
32336                :
32337                :extern int clientPrivateLen;
32338                :extern unsigned *clientPrivateSizes;
32339                :extern unsigned totalClientSize;
32340                :
32341                :void InitClient(ClientPtr client, int i, pointer ospriv)
32342                :{
32343                :    client->index = i;
32344                :    client->sequence = 0; 
32345                :    client->clientAsMask = ((Mask)i) << CLIENTOFFSET;
32346                :    client->clientGone = FALSE;
32347                :    if (i)
32348                :    {
32349                :        client->closeDownMode = DestroyAll;
32350                :        client->lastDrawable = (DrawablePtr)WindowTable[0];
32351                :        client->lastDrawableID = WindowTable[0]->drawable.id;
32352                :    }
32353                :    else
32354                :    {
32355                :        client->closeDownMode = RetainPermanent;
32356                :        client->lastDrawable = (DrawablePtr)NULL;
32357                :        client->lastDrawableID = INVALID;
32358                :    }
32359                :    client->lastGC = (GCPtr) NULL;
32360                :    client->lastGCID = INVALID;
32361                :    client->numSaved = 0;
32362                :    client->saveSet = (SaveSetElt *)NULL;
32363                :    client->noClientException = Success;
32364                :#ifdef DEBUG
32365                :    client->requestLogIndex = 0;
32366                :#endif
32367                :    client->requestVector = InitialVector;
32368                :    client->osPrivate = ospriv;
32369                :    client->swapped = FALSE;
32370                :    client->big_requests = FALSE;
32371                :    client->priority = 0;
32372                :    client->clientState = ClientStateInitial;
32373                :#ifdef XKB
32374                :    if (!noXkbExtension) {
32375                :        client->xkbClientFlags = 0;
32376                :        client->mapNotifyMask = 0;
32377                :        QueryMinMaxKeyCodes(&client->minKC,&client->maxKC);
32378                :    }
32379                :#endif
32380                :    client->replyBytesRemaining = 0;
32381                :#ifdef XAPPGROUP
32382                :    client->appgroup = NULL;
32383                :#endif
32384                :    client->fontResFunc = NULL;
32385                :#ifdef SMART_SCHEDULE
32386                :    client->smart_priority = 0;
32387                :    client->smart_start_tick = SmartScheduleTime;
32388                :    client->smart_stop_tick = SmartScheduleTime;
32389                :    client->smart_check_tick = SmartScheduleTime;
32390                :#endif
32391                :}
32392                :
32393                :int
32394                :InitClientPrivates(ClientPtr client)
32395                :{
32396                :    char *ptr;
32397                :    DevUnion *ppriv;
32398                :    unsigned *sizes;
32399                :    unsigned size;
32400                :    int i;
32401                :
32402                :    if (totalClientSize == sizeof(ClientRec))
32403                :        ppriv = (DevUnion *)NULL;
32404                :    else if (client->index)
32405                :        ppriv = (DevUnion *)(client + 1);
32406                :    else
32407                :    {
32408                :        ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec));
32409                :        if (!ppriv)
32410                :            return 0;
32411                :    }
32412                :    client->devPrivates = ppriv;
32413                :    sizes = clientPrivateSizes;
32414                :    ptr = (char *)(ppriv + clientPrivateLen);
32415                :    if (ppriv)
32416                :        bzero(ppriv, totalClientSize - sizeof(ClientRec));
32417                :    for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++)
32418                :    {
32419                :        if ( (size = *sizes) )
32420                :        {
32421                :            ppriv->ptr = (pointer)ptr;
32422                :            ptr += size;
32423                :        }
32424                :        else
32425                :            ppriv->ptr = (pointer)NULL;
32426                :    }
32427                :
32428                :    /* Allow registrants to initialize the serverClient devPrivates */
32429                :    if (!client->index && ClientStateCallback)
32430                :    {
32431                :        NewClientInfoRec clientinfo;
32432                :
32433                :        clientinfo.client = client; 
32434                :        clientinfo.prefix = (xConnSetupPrefix *)NULL;  
32435                :        clientinfo.setup = (xConnSetup *) NULL;
32436                :        CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
32437                :    } 
32438                :    return 1;
32439                :}
32440                :
32441                :/************************
32442                : * int NextAvailableClient(ospriv)
32443                : *
32444                : * OS dependent portion can't assign client id's because of CloseDownModes.
32445                : * Returns NULL if there are no free clients.
32446                : *************************/
32447                :
32448                :ClientPtr NextAvailableClient(pointer ospriv)
32449                :{
32450                :    int i;
32451                :    ClientPtr client;
32452                :    xReq data;
32453                :
32454                :    i = nextFreeClientID;
32455                :    if (i == MAXCLIENTS)
32456                :        return (ClientPtr)NULL;
32457                :    clients[i] = client = (ClientPtr)xalloc(totalClientSize);
32458                :    if (!client)
32459                :        return (ClientPtr)NULL;
32460                :    InitClient(client, i, ospriv);
32461                :    InitClientPrivates(client);
32462                :    if (!InitClientResources(client))
32463                :    {
32464                :        xfree(client);
32465                :        return (ClientPtr)NULL;
32466                :    }
32467                :    data.reqType = 1;
32468                :    data.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
32469                :    if (!InsertFakeRequest(client, (char *)&data, sz_xReq))
32470                :    {
32471                :        FreeClientResources(client);
32472                :        xfree(client);
32473                :        return (ClientPtr)NULL;
32474                :    }
32475                :    if (i == currentMaxClients)
32476                :        currentMaxClients++;
32477                :    while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
32478                :        nextFreeClientID++;
32479                :    if (ClientStateCallback)
32480                :    {
32481                :        NewClientInfoRec clientinfo;
32482                :
32483                :        clientinfo.client = client; 
32484                :        clientinfo.prefix = (xConnSetupPrefix *)NULL;  
32485                :        clientinfo.setup = (xConnSetup *) NULL;
32486                :        CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
32487                :    }   
32488                :    return(client);
32489                :}
32490                :
32491                :int
32492                :ProcInitialConnection(ClientPtr client)
32493                :{
32494                :    REQUEST(xReq);
32495                :    xConnClientPrefix *prefix;
32496                :    int whichbyte = 1;
32497                :
32498                :    prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
32499                :    if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
32500                :        return (client->noClientException = -1);
32501                :    if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
32502                :        (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l')))
32503                :    {
32504                :        client->swapped = TRUE;
32505                :        SwapConnClientPrefix(prefix);
32506                :    }
32507                :    stuff->reqType = 2;
32508                :    stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) +
32509                :                     ((prefix->nbytesAuthString + (unsigned)3) >> 2);
32510                :    if (client->swapped)
32511                :    {
32512                :        swaps(&stuff->length, whichbyte);
32513                :    }
32514                :    ResetCurrentRequest(client);
32515                :    return (client->noClientException);
32516                :}
32517                :
32518                :int
32519                :SendConnSetup(ClientPtr client, char *reason)
32520                :{
32521                :    xWindowRoot *root;
32522                :    int i;
32523                :    int numScreens;
32524                :    char* lConnectionInfo;
32525                :    xConnSetupPrefix* lconnSetupPrefix;
32526                :
32527                :    if (reason)
32528                :    {
32529                :        xConnSetupPrefix csp;
32530                :
32531                :        csp.success = xFalse;
32532                :        csp.lengthReason = strlen(reason);
32533                :        csp.length = (csp.lengthReason + (unsigned)3) >> 2;
32534                :        csp.majorVersion = X_PROTOCOL;
32535                :        csp.minorVersion = X_PROTOCOL_REVISION;
32536                :        if (client->swapped)
32537                :            WriteSConnSetupPrefix(client, &csp);
32538                :        else
32539                :            (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp);
32540                :        (void)WriteToClient(client, (int)csp.lengthReason, reason);
32541                :        return (client->noClientException = -1);
32542                :    }
32543                :
32544                :    numScreens = screenInfo.numScreens;
32545                :    lConnectionInfo = ConnectionInfo;
32546                :    lconnSetupPrefix = &connSetupPrefix;
32547                :
32548                :    /* We're about to start speaking X protocol back to the client by
32549                :     * sending the connection setup info.  This means the authorization
32550                :     * step is complete, and we can count the client as an
32551                :     * authorized one.
32552                :     */
32553                :    nClients++;
32554                :
32555                :    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
32556                :    client->sequence = 0;
32557                :#ifdef XAPPGROUP
32558                :    XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens);
32559                :#endif
32560                :    ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask;
32561                :    ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
32562                :#ifdef MATCH_CLIENT_ENDIAN
32563                :    ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client);
32564                :    ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client);
32565                :#endif
32566                :    /* fill in the "currentInputMask" */
32567                :    root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart);
32568                :#ifdef PANORAMIX
32569                :    if (noPanoramiXExtension)
32570                :        numScreens = screenInfo.numScreens;
32571                :    else 
32572                :        numScreens = ((xConnSetup *)ConnectionInfo)->numRoots;
32573                :#endif
32574                :
32575                :    for (i=0; i<numScreens; i++) 
32576                :    {
32577                :        unsigned int j;
32578                :        xDepth *pDepth;
32579                :
32580                :        root->currentInputMask = WindowTable[i]->eventMask |
32581                :                                 wOtherEventMasks (WindowTable[i]);
32582                :        pDepth = (xDepth *)(root + 1);
32583                :        for (j = 0; j < root->nDepths; j++)
32584                :        {
32585                :            pDepth = (xDepth *)(((char *)(pDepth + 1)) +
32586                :                                pDepth->nVisuals * sizeof(xVisualType));
32587                :        }
32588                :        root = (xWindowRoot *)pDepth;
32589                :    }
32590                :
32591                :    if (client->swapped)
32592                :    {
32593                :        WriteSConnSetupPrefix(client, lconnSetupPrefix);
32594                :        WriteSConnectionInfo(client,
32595                :                             (unsigned long)(lconnSetupPrefix->length << 2),
32596                :                             lConnectionInfo);
32597                :    }
32598                :    else
32599                :    {
32600                :        (void)WriteToClient(client, sizeof(xConnSetupPrefix),
32601                :                            (char *) lconnSetupPrefix);
32602                :        (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2),
32603                :                            lConnectionInfo);
32604                :    }
32605                :    client->clientState = ClientStateRunning;
32606                :    if (ClientStateCallback)
32607                :    {
32608                :        NewClientInfoRec clientinfo;
32609                :
32610                :        clientinfo.client = client; 
32611                :        clientinfo.prefix = lconnSetupPrefix;  
32612                :        clientinfo.setup = (xConnSetup *)lConnectionInfo;
32613                :        CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
32614                :    }   
32615                :    return (client->noClientException);
32616                :}
32617                :
32618                :int
32619                :ProcEstablishConnection(ClientPtr client)
32620                :{
32621                :    char *reason, *auth_proto, *auth_string;
32622                :    xConnClientPrefix *prefix;
32623                :    REQUEST(xReq);
32624                :
32625                :    prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
32626                :    auth_proto = (char *)prefix + sz_xConnClientPrefix;
32627                :    auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3);
32628                :    if ((prefix->majorVersion != X_PROTOCOL) ||
32629                :        (prefix->minorVersion != X_PROTOCOL_REVISION))
32630                :        reason = "Protocol version mismatch";
32631                :    else
32632                :        reason = ClientAuthorized(client,
32633                :                                  (unsigned short)prefix->nbytesAuthProto,
32634                :                                  auth_proto,
32635                :                                  (unsigned short)prefix->nbytesAuthString,
32636                :                                  auth_string);
32637                :    /*
32638                :     * If Kerberos is being used for this client, the clientState
32639                :     * will be set to ClientStateAuthenticating at this point.
32640                :     * More messages need to be exchanged among the X server, Kerberos
32641                :     * server, and client to figure out if everyone is authorized.
32642                :     * So we don't want to send the connection setup info yet, since
32643                :     * the auth step isn't really done.
32644                :     */
32645                :    if (client->clientState == ClientStateCheckingSecurity)
32646                :        client->clientState = ClientStateCheckedSecurity;
32647                :    else if (client->clientState != ClientStateAuthenticating)
32648                :        return(SendConnSetup(client, reason));
32649                :    return(client->noClientException);
32650                :}
32651                :
32652                :_X_EXPORT void
32653                :SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, 
32654                :                  XID resId, int errorCode)
32655                :{
32656                :    xError rep;
32657                :
32658                :    rep.type = X_Error;
32659                :    rep.sequenceNumber = client->sequence;
32660                :    rep.errorCode = errorCode;
32661                :    rep.majorCode = majorCode;
32662                :    rep.minorCode = minorCode;
32663                :    rep.resourceID = resId;
32664                :
32665                :    WriteEventsToClient (client, 1, (xEvent *)&rep);
32666                :}
32667                :
32668                :void
32669                :DeleteWindowFromAnySelections(WindowPtr pWin)
32670                :{
32671                :    int i;
32672                :
32673                :    for (i = 0; i< NumCurrentSelections; i++)
32674                :        if (CurrentSelections[i].pWin == pWin)
32675                :        {
32676                :            if (SelectionCallback)
32677                :            {
32678                :                SelectionInfoRec    info;
32679                :
32680                :                info.selection = &CurrentSelections[i];
32681                :                info.kind = SelectionWindowDestroy;
32682                :                CallCallbacks(&SelectionCallback, &info);
32683                :            }
32684                :            CurrentSelections[i].pWin = (WindowPtr)NULL;
32685                :            CurrentSelections[i].window = None;
32686                :            CurrentSelections[i].client = NullClient;
32687                :        }
32688                :}
32689                :
32690                :static void
32691                :DeleteClientFromAnySelections(ClientPtr client)
32692                :{
32693                :    int i;
32694                :
32695                :    for (i = 0; i< NumCurrentSelections; i++)
32696                :        if (CurrentSelections[i].client == client)
32697                :        {
32698                :            if (SelectionCallback)
32699                :            {
32700                :                SelectionInfoRec    info;
32701                :
32702                :                info.selection = &CurrentSelections[i];
32703                :                info.kind = SelectionWindowDestroy;
32704                :                CallCallbacks(&SelectionCallback, &info);
32705                :            }
32706                :            CurrentSelections[i].pWin = (WindowPtr)NULL;
32707                :            CurrentSelections[i].window = None;
32708                :            CurrentSelections[i].client = NullClient;
32709                :        }
32710                :}
32711                :
32712                :void
32713                :MarkClientException(ClientPtr client)
32714                :{
32715                :    client->noClientException = -1;
32716                :}
32717                :
32718                :#ifdef XSERVER_DTRACE
32719                :#include <ctype.h>
32720                :
32721                :/* Load table of request names for dtrace probes */
32722                :static void LoadRequestNames(void)
32723                :{
32724                :    int i;
32725                :    FILE *xedb;
32726                :    extern void LoadExtensionNames(char **RequestNames);
32727                :
32728                :    bzero(RequestNames, 256 * sizeof(char *));
32729                :
32730                :    xedb = fopen(XERRORDB_PATH, "r");
32731                :    if (xedb != NULL) {
32732                :        char buf[256];
32733                :        while (fgets(buf, sizeof(buf), xedb)) {
32734                :            if ((strncmp("XRequest.", buf, 9) == 0) && (isdigit(buf[9]))) {
32735                :                char *name;
32736                :                i = strtol(buf + 9, &name, 10);
32737                :                if (RequestNames[i] == 0) {
32738                :                    char *end = strchr(name, '\n');
32739                :                    if (end) { *end = '\0'; }
32740                :                    RequestNames[i] = strdup(name + 1);
32741                :                }
32742                :            }
32743                :        }
32744                :        fclose(xedb);
32745                :    }
32746                :
32747                :    LoadExtensionNames(RequestNames);
32748                :
32749                :    for (i = 0; i < 256; i++) {
32750                :        if (RequestNames[i] == 0) {
32751                :#define RN_SIZE 12 /* "Request#' + up to 3 digits + \0 */
32752                :            RequestNames[i] = xalloc(RN_SIZE);
32753                :            if (RequestNames[i]) {
32754                :                snprintf(RequestNames[i], RN_SIZE, "Request#%d", i);
32755                :            }
32756                :        }
32757                :        /* fprintf(stderr, "%d: %s\n", i, RequestNames[i]); */
32758                :    }
32759                :}
32760                :
32761                :static void FreeRequestNames(void)
32762                :{
32763                :    int i;
32764                :
32765                :    for (i = 0; i < 256; i++) {
32766                :        if (RequestNames[i] != 0) {
32767                :            free(RequestNames[i]);
32768                :            RequestNames[i] = 0;
32769                :        }
32770                :    }
32771                :}
32772                :
32773                :#endif
32774 /* 
32775  * Total samples for file : "/home/cworth/src/xorg/xserver/dix/gc.c"
32776  * 
32777  *     57  0.0621
32778  */
32779
32780
32781                :/***********************************************************
32782                :
32783                :Copyright 1987, 1998  The Open Group
32784                :
32785                :Permission to use, copy, modify, distribute, and sell this software and its
32786                :documentation for any purpose is hereby granted without fee, provided that
32787                :the above copyright notice appear in all copies and that both that
32788                :copyright notice and this permission notice appear in supporting
32789                :documentation.
32790                :
32791                :The above copyright notice and this permission notice shall be included in
32792                :all copies or substantial portions of the Software.
32793                :
32794                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32795                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32796                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
32797                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
32798                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32799                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32800                :
32801                :Except as contained in this notice, the name of The Open Group shall not be
32802                :used in advertising or otherwise to promote the sale, use or other dealings
32803                :in this Software without prior written authorization from The Open Group.
32804                :
32805                :
32806                :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
32807                :
32808                :                        All Rights Reserved
32809                :
32810                :Permission to use, copy, modify, and distribute this software and its 
32811                :documentation for any purpose and without fee is hereby granted, 
32812                :provided that the above copyright notice appear in all copies and that
32813                :both that copyright notice and this permission notice appear in 
32814                :supporting documentation, and that the name of Digital not be
32815                :used in advertising or publicity pertaining to distribution of the
32816                :software without specific, written prior permission.  
32817                :
32818                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
32819                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
32820                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
32821                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
32822                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
32823                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
32824                :SOFTWARE.
32825                :
32826                :******************************************************************/
32827                :
32828                :
32829                :#ifdef HAVE_DIX_CONFIG_H
32830                :#include <dix-config.h>
32831                :#endif
32832                :
32833                :#include <X11/X.h>
32834                :#include <X11/Xmd.h>
32835                :#include <X11/Xproto.h>
32836                :#include "misc.h"
32837                :#include "resource.h"
32838                :#include "gcstruct.h"
32839                :#include "pixmapstr.h"
32840                :#include "dixfontstr.h"
32841                :#include "scrnintstr.h"
32842                :#include "region.h"
32843                :
32844                :#include "dix.h"
32845                :#include <assert.h>
32846                :
32847                :extern XID clientErrorValue;
32848                :extern FontPtr defaultFont;
32849                :
32850                :static Bool CreateDefaultTile(GCPtr pGC);
32851                :
32852                :static unsigned char DefaultDash[2] = {4, 4};
32853                :
32854                :_X_EXPORT void
32855                :ValidateGC(DrawablePtr pDraw, GC *pGC)
32856      3  0.0033 :{ /* ValidateGC total:      3  0.0033 */
32857                :    (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw);
32858                :    pGC->stateChanges = 0;
32859                :    pGC->serialNumber = pDraw->serialNumber;
32860                :}
32861                :
32862                :
32863                :/* dixChangeGC(client, pGC, mask, pC32, pUnion)
32864                : * 
32865                : * This function was created as part of the Security extension
32866                : * implementation.  The client performing the gc change must be passed so
32867                : * that access checks can be performed on any tiles, stipples, or fonts
32868                : * that are specified.  ddxen can call this too; they should normally
32869                : * pass NullClient for the client since any access checking should have
32870                : * already been done at a higher level.
32871                : * 
32872                : * Since we had to create a new function anyway, we decided to change the
32873                : * way the list of gc values is passed to eliminate the compiler warnings
32874                : * caused by the DoChangeGC interface.  You can pass the values via pC32
32875                : * or pUnion, but not both; one of them must be NULL.  If you don't need
32876                : * to pass any pointers, you can use either one:
32877                : * 
32878                : *     example calling dixChangeGC using pC32 parameter
32879                : *
32880                : *     CARD32 v[2];
32881                : *     v[0] = foreground;
32882                : *     v[1] = background;
32883                : *     dixChangeGC(client, pGC, GCForeground|GCBackground, v, NULL);
32884                : * 
32885                : *     example calling dixChangeGC using pUnion parameter;
32886                : *     same effect as above
32887                : *
32888                : *     ChangeGCVal v[2];
32889                : *     v[0].val = foreground;
32890                : *     v[1].val = background;
32891                : *     dixChangeGC(client, pGC, GCForeground|GCBackground, NULL, v);
32892                : * 
32893                : * However, if you need to pass a pointer to a pixmap or font, you MUST
32894                : * use the pUnion parameter.
32895                : * 
32896                : *     example calling dixChangeGC passing pointers in the value list
32897                : *     v[1].ptr is a pointer to a pixmap
32898                : *
32899                : *     ChangeGCVal v[2];
32900                : *     v[0].val = FillTiled;
32901                : *     v[1].ptr = pPixmap;
32902                : *     dixChangeGC(client, pGC, GCFillStyle|GCTile, NULL, v);
32903                : * 
32904                : * Note: we could have gotten by with just the pUnion parameter, but on
32905                : * 64 bit machines that would have forced us to copy the value list that
32906                : * comes in the ChangeGC request.
32907                : * 
32908                : * Ideally, we'd change all the DoChangeGC calls to dixChangeGC, but this
32909                : * is far too many changes to consider at this time, so we've only
32910                : * changed the ones that caused compiler warnings.  New code should use
32911                : * dixChangeGC.
32912                : * 
32913                : * dpw
32914                : */
32915                :
32916                :#define NEXTVAL(_type, _var) { \
32917                :      if (pC32) _var = (_type)*pC32++; \
32918                :      else { \
32919                :        _var = (_type)(pUnion->val); pUnion++; \
32920                :      } \
32921                :    }
32922                :
32923                :#define NEXT_PTR(_type, _var) { \
32924                :    assert(pUnion); _var = (_type)pUnion->ptr; pUnion++; }
32925                :
32926                :_X_EXPORT int
32927                :dixChangeGC(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32, ChangeGCValPtr pUnion)
32928                :{ /* dixChangeGC total:     24  0.0261 */
32929                :    BITS32      index2;
32930                :    int         error = 0;
32931                :    PixmapPtr   pPixmap;
32932                :    BITS32      maskQ;
32933                :
32934                :    assert( (pC32 && !pUnion) || (!pC32 && pUnion) );
32935                :    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
32936                :
32937                :    maskQ = mask;       /* save these for when we walk the GCque */
32938      5  0.0054 :    while (mask && !error) 
32939                :    {
32940      1  0.0011 :        index2 = (BITS32) lowbit (mask);
32941      7  0.0076 :        mask &= ~index2;
32942                :        pGC->stateChanges |= index2;
32943      1  0.0011 :        switch (index2)
32944                :        {
32945                :            case GCFunction:
32946                :            {
32947                :                CARD8 newalu;
32948      3  0.0033 :                NEXTVAL(CARD8, newalu);
32949                :                if (newalu <= GXset)
32950      1  0.0011 :                    pGC->alu = newalu;
32951                :                else
32952                :                {
32953                :                    clientErrorValue = newalu;
32954                :                    error = BadValue;
32955                :                }
32956                :                break;
32957                :            }
32958                :            case GCPlaneMask:
32959                :                NEXTVAL(unsigned long, pGC->planemask);
32960                :                break;
32961                :            case GCForeground:
32962      1  0.0011 :                NEXTVAL(unsigned long, pGC->fgPixel);
32963                :                /*
32964                :                 * this is for CreateGC
32965                :                 */
32966                :                if (!pGC->tileIsPixel && !pGC->tile.pixmap)
32967                :                {
32968                :                    pGC->tileIsPixel = TRUE;
32969                :                    pGC->tile.pixel = pGC->fgPixel;
32970                :                }
32971                :                break;
32972                :            case GCBackground:
32973                :                NEXTVAL(unsigned long, pGC->bgPixel);
32974                :                break;
32975                :            case GCLineWidth:           /* ??? line width is a CARD16 */
32976                :                 NEXTVAL(CARD16, pGC->lineWidth);
32977                :                break;
32978                :            case GCLineStyle:
32979                :            {
32980                :                unsigned int newlinestyle;
32981                :                NEXTVAL(unsigned int, newlinestyle);
32982                :                if (newlinestyle <= LineDoubleDash)
32983                :                    pGC->lineStyle = newlinestyle;
32984                :                else
32985                :                {
32986                :                    clientErrorValue = newlinestyle;
32987                :                    error = BadValue;
32988                :                }
32989                :                break;
32990                :            }
32991                :            case GCCapStyle:
32992                :            {
32993                :                unsigned int newcapstyle;
32994                :                NEXTVAL(unsigned int, newcapstyle);
32995                :                if (newcapstyle <= CapProjecting)
32996                :                    pGC->capStyle = newcapstyle;
32997                :                else
32998                :                {
32999                :                    clientErrorValue = newcapstyle;
33000                :                    error = BadValue;
33001                :                }
33002                :                break;
33003                :            }
33004                :            case GCJoinStyle:
33005                :            {
33006                :                unsigned int newjoinstyle;
33007                :                NEXTVAL(unsigned int, newjoinstyle);
33008                :                if (newjoinstyle <= JoinBevel)
33009                :                    pGC->joinStyle = newjoinstyle;
33010                :                else
33011                :                {
33012                :                    clientErrorValue = newjoinstyle;
33013                :                    error = BadValue;
33014                :                }
33015                :                break;
33016                :            }
33017                :            case GCFillStyle:
33018                :            {
33019                :                unsigned int newfillstyle;
33020                :                NEXTVAL(unsigned int, newfillstyle);
33021                :                if (newfillstyle <= FillOpaqueStippled)
33022                :                    pGC->fillStyle = newfillstyle;
33023                :                else
33024                :                {
33025                :                    clientErrorValue = newfillstyle;
33026                :                    error = BadValue;
33027                :                }
33028                :                break;
33029                :            }
33030                :            case GCFillRule:
33031                :            {
33032                :                unsigned int newfillrule;
33033                :                NEXTVAL(unsigned int, newfillrule);
33034                :                if (newfillrule <= WindingRule)
33035                :                    pGC->fillRule = newfillrule;
33036                :                else
33037                :                {
33038                :                    clientErrorValue = newfillrule;
33039                :                    error = BadValue;
33040                :                }
33041                :                break;
33042                :            }
33043                :            case GCTile:
33044                :            {
33045                :                XID newpix = 0;
33046                :                if (pUnion)
33047                :                {
33048                :                    NEXT_PTR(PixmapPtr, pPixmap);
33049                :                }
33050                :                else
33051                :                {
33052                :                    NEXTVAL(XID, newpix);
33053                :                    pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
33054                :                                        newpix, RT_PIXMAP, DixReadAccess);
33055                :                }
33056                :                if (pPixmap)
33057                :                {
33058                :                    if ((pPixmap->drawable.depth != pGC->depth) ||
33059                :                        (pPixmap->drawable.pScreen != pGC->pScreen))
33060                :                    {
33061                :                        error = BadMatch;
33062                :                    }
33063                :                    else
33064                :                    {
33065                :                        pPixmap->refcnt++;
33066                :                        if (!pGC->tileIsPixel)
33067                :                            (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
33068                :                        pGC->tileIsPixel = FALSE;
33069                :                        pGC->tile.pixmap = pPixmap;
33070                :                    }
33071                :                }
33072                :                else
33073                :                {
33074                :                    clientErrorValue = newpix;
33075                :                    error = BadPixmap;
33076                :                }
33077                :                break;
33078                :            }
33079                :            case GCStipple:
33080                :            {
33081                :                XID newstipple = 0;
33082                :                if (pUnion)
33083                :                {
33084                :                    NEXT_PTR(PixmapPtr, pPixmap);
33085                :                }
33086                :                else
33087                :                {
33088                :                    NEXTVAL(XID, newstipple)
33089                :                    pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
33090                :                                newstipple, RT_PIXMAP, DixReadAccess);
33091                :                }
33092                :                if (pPixmap)
33093                :                {
33094                :                    if ((pPixmap->drawable.depth != 1) ||
33095                :                        (pPixmap->drawable.pScreen != pGC->pScreen))
33096                :                    {
33097                :                        error = BadMatch;
33098                :                    }
33099                :                    else
33100                :                    {
33101                :                        pPixmap->refcnt++;
33102                :                        if (pGC->stipple)
33103                :                            (* pGC->pScreen->DestroyPixmap)(pGC->stipple);
33104                :                        pGC->stipple = pPixmap;
33105                :                    }
33106                :                }
33107                :                else
33108                :                {
33109                :                    clientErrorValue = newstipple;
33110                :                    error = BadPixmap;
33111                :                }
33112                :                break;
33113                :            }
33114                :            case GCTileStipXOrigin:
33115                :                NEXTVAL(INT16, pGC->patOrg.x);
33116                :                break;
33117                :            case GCTileStipYOrigin:
33118                :                NEXTVAL(INT16, pGC->patOrg.y);
33119                :                break;
33120                :            case GCFont:
33121                :            {
33122                :                FontPtr pFont;
33123                :                XID newfont = 0;
33124                :                if (pUnion)
33125                :                {
33126                :                    NEXT_PTR(FontPtr, pFont);
33127                :                }
33128                :                else
33129                :                {
33130                :                    NEXTVAL(XID, newfont)
33131                :                    pFont = (FontPtr)SecurityLookupIDByType(client, newfont,
33132                :                                                RT_FONT, DixReadAccess);
33133                :                }
33134                :                if (pFont)
33135                :                {
33136                :                    pFont->refcnt++;
33137                :                    if (pGC->font)
33138                :                        CloseFont(pGC->font, (Font)0);
33139                :                    pGC->font = pFont;
33140                :                 }
33141                :                else
33142                :                {
33143                :                    clientErrorValue = newfont;
33144                :                    error = BadFont;
33145                :                }
33146                :                break;
33147                :            }
33148                :            case GCSubwindowMode:
33149                :            {
33150                :                unsigned int newclipmode;
33151      1  0.0011 :                NEXTVAL(unsigned int, newclipmode);
33152                :                if (newclipmode <= IncludeInferiors)
33153      1  0.0011 :                    pGC->subWindowMode = newclipmode;
33154                :                else
33155                :                {
33156                :                    clientErrorValue = newclipmode;
33157                :                    error = BadValue;
33158                :                }
33159                :                break;
33160                :            }
33161                :            case GCGraphicsExposures:
33162                :            {
33163                :                unsigned int newge;
33164                :                NEXTVAL(unsigned int, newge);
33165                :                if (newge <= xTrue)
33166                :                    pGC->graphicsExposures = newge;
33167                :                else
33168                :                {
33169                :                    clientErrorValue = newge;
33170                :                    error = BadValue;
33171                :                }
33172                :                break;
33173                :            }
33174                :            case GCClipXOrigin:
33175      2  0.0022 :                NEXTVAL(INT16, pGC->clipOrg.x);
33176                :                break;
33177                :            case GCClipYOrigin:
33178                :                NEXTVAL(INT16, pGC->clipOrg.y);
33179                :                break;
33180                :            case GCClipMask:
33181                :            {
33182                :                Pixmap pid = 0;
33183                :                int    clipType = 0;
33184                :
33185                :                if (pUnion)
33186                :                {
33187                :                    NEXT_PTR(PixmapPtr, pPixmap);
33188                :                }
33189                :                else
33190                :                {
33191                :                    NEXTVAL(Pixmap, pid)
33192                :                    if (pid == None)
33193                :                    {
33194                :                        clipType = CT_NONE;
33195                :                        pPixmap = NullPixmap;
33196                :                    }
33197                :                    else
33198                :                        pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
33199                :                                        pid, RT_PIXMAP, DixReadAccess);
33200                :                }
33201                :
33202                :                if (pPixmap)
33203                :                {
33204                :                    if ((pPixmap->drawable.depth != 1) ||
33205                :                        (pPixmap->drawable.pScreen != pGC->pScreen))
33206                :                    {
33207                :                        error = BadMatch;
33208                :                    }
33209                :                    else
33210                :                    {
33211                :                        clipType = CT_PIXMAP;
33212                :                        pPixmap->refcnt++;
33213                :                    }
33214                :                }
33215                :                else if (!pUnion && (pid != None))
33216                :                {
33217                :                    clientErrorValue = pid;
33218                :                    error = BadPixmap;
33219                :                }
33220                :                if(error == Success)
33221                :                {
33222                :                    (*pGC->funcs->ChangeClip)(pGC, clipType,
33223                :                                              (pointer)pPixmap, 0);
33224                :                }
33225                :                break;
33226                :            }
33227                :            case GCDashOffset:
33228                :                NEXTVAL(INT16, pGC->dashOffset);
33229                :                break;
33230                :            case GCDashList:
33231                :            {
33232                :                CARD8 newdash;
33233                :                NEXTVAL(CARD8, newdash);
33234                :                if (newdash == 4)
33235                :                {
33236                :                    if (pGC->dash != DefaultDash)
33237                :                    {
33238                :                        xfree(pGC->dash);
33239                :                        pGC->numInDashList = 2;
33240                :                        pGC->dash = DefaultDash;
33241                :                    }
33242                :                }
33243                :                else if (newdash != 0)
33244                :                {
33245                :                    unsigned char *dash;
33246                :
33247                :                    dash = (unsigned char *)xalloc(2 * sizeof(unsigned char));
33248                :                    if (dash)
33249                :                    {
33250                :                        if (pGC->dash != DefaultDash)
33251                :                            xfree(pGC->dash);
33252                :                        pGC->numInDashList = 2;
33253                :                        pGC->dash = dash;
33254                :                        dash[0] = newdash;
33255                :                        dash[1] = newdash;
33256                :                    }
33257                :                    else
33258                :                        error = BadAlloc;
33259                :                }
33260                :                else
33261                :                {
33262                :                   clientErrorValue = newdash;
33263                :                   error = BadValue;
33264                :                }
33265                :                break;
33266                :            }
33267                :            case GCArcMode:
33268                :            {
33269                :                unsigned int newarcmode;
33270                :                NEXTVAL(unsigned int, newarcmode);
33271                :                if (newarcmode <= ArcPieSlice)
33272                :                    pGC->arcMode = newarcmode;
33273                :                else
33274                :                {
33275                :                    clientErrorValue = newarcmode;
33276                :                    error = BadValue;
33277                :                }
33278                :                break;
33279                :            }
33280                :            default:
33281                :                clientErrorValue = maskQ;
33282                :                error = BadValue;
33283                :                break;
33284                :        }
33285                :    } /* end while mask && !error */
33286                :
33287      1  0.0011 :    if (pGC->fillStyle == FillTiled && pGC->tileIsPixel)
33288                :    {
33289                :        if (!CreateDefaultTile (pGC))
33290                :        {
33291                :            pGC->fillStyle = FillSolid;
33292                :            error = BadAlloc;
33293                :        }
33294                :    }
33295                :    (*pGC->funcs->ChangeGC)(pGC, maskQ);
33296                :    return error;
33297                :}
33298                :
33299                :#undef NEXTVAL
33300                :#undef NEXT_PTR
33301                :
33302                :/* Publically defined entry to ChangeGC.  Just calls dixChangeGC and tells
33303                : * it that all of the entries are constants or IDs */
33304                :_X_EXPORT int
33305                :ChangeGC(GC *pGC, BITS32 mask, XID *pval)
33306      2  0.0022 :{ /* ChangeGC total:      5  0.0054 */
33307      3  0.0033 :    return (dixChangeGC(NullClient, pGC, mask, pval, NULL));
33308                :}
33309                :
33310                :/* DoChangeGC(pGC, mask, pval, fPointer)
33311                :   mask is a set of bits indicating which values to change.
33312                :   pval contains an appropriate value for each mask.
33313                :   fPointer is true if the values for tiles, stipples, fonts or clipmasks
33314                :   are pointers instead of IDs.  Note: if you are passing pointers you
33315                :   MUST declare the array of values as type pointer!  Other data types
33316                :   may not be large enough to hold pointers on some machines.  Yes,
33317                :   this means you have to cast to (XID *) when you pass the array to
33318                :   DoChangeGC.  Similarly, if you are not passing pointers (fPointer = 0) you
33319                :   MUST declare the array as type XID (not unsigned long!), or again the wrong
33320                :   size data type may be used.  To avoid this cruftiness, use dixChangeGC
33321                :   above.
33322                :
33323                :   if there is an error, the value is marked as changed 
33324                :   anyway, which is probably wrong, but infrequent.
33325                :
33326                :NOTE:
33327                :        all values sent over the protocol for ChangeGC requests are
33328                :32 bits long
33329                :*/
33330                :_X_EXPORT int
33331                :DoChangeGC(GC *pGC, BITS32 mask, XID *pval, int fPointer)
33332                :{
33333                :    if (fPointer)
33334                :    /* XXX might be a problem on 64 bit big-endian servers */
33335                :        return dixChangeGC(NullClient, pGC, mask, NULL, (ChangeGCValPtr)pval);
33336                :    else
33337                :        return dixChangeGC(NullClient, pGC, mask, pval, NULL);
33338                :}
33339                :
33340                :
33341                :/* CreateGC(pDrawable, mask, pval, pStatus)
33342                :   creates a default GC for the given drawable, using mask to fill
33343                :   in any non-default values.
33344                :   Returns a pointer to the new GC on success, NULL otherwise.
33345                :   returns status of non-default fields in pStatus
33346                :BUG:
33347                :   should check for failure to create default tile
33348                :
33349                :*/
33350                :
33351                :static GCPtr
33352                :AllocateGC(ScreenPtr pScreen)
33353                :{ /* AllocateGC total:      2  0.0022 */
33354                :    GCPtr pGC;
33355                :    char *ptr;
33356                :    DevUnion *ppriv;
33357                :    unsigned *sizes;
33358                :    unsigned size;
33359                :    int i;
33360                :
33361                :    pGC = (GCPtr)xalloc(pScreen->totalGCSize);
33362                :    if (pGC)
33363                :    {
33364                :        ppriv = (DevUnion *)(pGC + 1);
33365                :        pGC->devPrivates = ppriv;
33366                :        sizes = pScreen->GCPrivateSizes;
33367                :        ptr = (char *)(ppriv + pScreen->GCPrivateLen);
33368                :        for (i = pScreen->GCPrivateLen; --i >= 0; ppriv++, sizes++)
33369                :        {
33370                :            if ( (size = *sizes) )
33371                :            {
33372                :                ppriv->ptr = (pointer)ptr;
33373                :                ptr += size;
33374                :            }
33375                :            else
33376      1  0.0011 :                ppriv->ptr = (pointer)NULL;
33377                :        }
33378                :    }
33379                :    return pGC;
33380      1  0.0011 :}
33381                :
33382                :_X_EXPORT GCPtr
33383                :CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus)
33384                :{ /* CreateGC total:      1  0.0011 */
33385                :    GCPtr pGC;
33386                :
33387                :    pGC = AllocateGC(pDrawable->pScreen);
33388                :    if (!pGC)
33389                :    {
33390                :        *pStatus = BadAlloc;
33391                :        return (GCPtr)NULL;
33392                :    }
33393                :
33394                :    pGC->pScreen = pDrawable->pScreen;
33395                :    pGC->depth = pDrawable->depth;
33396                :    pGC->alu = GXcopy; /* dst <- src */
33397                :    pGC->planemask = ~0;
33398                :    pGC->serialNumber = GC_CHANGE_SERIAL_BIT;
33399                :    pGC->funcs = 0;
33400                :
33401                :    pGC->fgPixel = 0;
33402                :    pGC->bgPixel = 1;
33403                :    pGC->lineWidth = 0;
33404                :    pGC->lineStyle = LineSolid;
33405                :    pGC->capStyle = CapButt;
33406                :    pGC->joinStyle = JoinMiter;
33407                :    pGC->fillStyle = FillSolid;
33408                :    pGC->fillRule = EvenOddRule;
33409                :    pGC->arcMode = ArcPieSlice;
33410                :    if (mask & GCForeground)
33411                :    {
33412                :        /*
33413                :         * magic special case -- ChangeGC checks for this condition
33414                :         * and snags the Foreground value to create a pseudo default-tile
33415                :         */
33416                :        pGC->tileIsPixel = FALSE;
33417                :        pGC->tile.pixmap = NullPixmap;
33418                :    }
33419                :    else
33420                :    {
33421                :        pGC->tileIsPixel = TRUE;
33422                :        pGC->tile.pixel = 0;
33423                :    }
33424                :
33425      1  0.0011 :    pGC->patOrg.x = 0;
33426                :    pGC->patOrg.y = 0;
33427                :    pGC->subWindowMode = ClipByChildren;
33428                :    pGC->graphicsExposures = TRUE;
33429                :    pGC->clipOrg.x = 0;
33430                :    pGC->clipOrg.y = 0;
33431                :    pGC->clientClipType = CT_NONE;
33432                :    pGC->clientClip = (pointer)NULL;
33433                :    pGC->numInDashList = 2;
33434                :    pGC->dash = DefaultDash;
33435                :    pGC->dashOffset = 0;
33436                :    pGC->lastWinOrg.x = 0;
33437                :    pGC->lastWinOrg.y = 0;
33438                :
33439                :    /* use the default font and stipple */
33440                :    pGC->font = defaultFont;
33441                :    defaultFont->refcnt++;
33442                :    pGC->stipple = pGC->pScreen->PixmapPerDepth[0];
33443                :    pGC->stipple->refcnt++;
33444                :
33445                :    pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
33446                :    if (!(*pGC->pScreen->CreateGC)(pGC))
33447                :        *pStatus = BadAlloc;
33448                :    else if (mask)
33449                :        *pStatus = ChangeGC(pGC, mask, pval);
33450                :    else
33451                :        *pStatus = Success;
33452                :    if (*pStatus != Success)
33453                :    {
33454                :        if (!pGC->tileIsPixel && !pGC->tile.pixmap)
33455                :            pGC->tileIsPixel = TRUE; /* undo special case */
33456                :        FreeGC(pGC, (XID)0);
33457                :        pGC = (GCPtr)NULL;
33458                :    }
33459                :
33460                :    return (pGC);
33461                :}
33462                :
33463                :static Bool
33464                :CreateDefaultTile (GCPtr pGC)
33465                :{
33466                :    XID         tmpval[3];
33467                :    PixmapPtr   pTile;
33468                :    GCPtr       pgcScratch;
33469                :    xRectangle  rect;
33470                :    CARD16      w, h;
33471                :
33472                :    w = 1;
33473                :    h = 1;
33474                :    (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen);
33475                :    pTile = (PixmapPtr)
33476                :            (*pGC->pScreen->CreatePixmap)(pGC->pScreen,
33477                :                                          w, h, pGC->depth);
33478                :    pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen);
33479                :    if (!pTile || !pgcScratch)
33480                :    {
33481                :        if (pTile)
33482                :            (*pTile->drawable.pScreen->DestroyPixmap)(pTile);
33483                :        if (pgcScratch)
33484                :            FreeScratchGC(pgcScratch);
33485                :        return FALSE;
33486                :    }
33487                :    tmpval[0] = GXcopy;
33488                :    tmpval[1] = pGC->tile.pixel;
33489                :    tmpval[2] = FillSolid;
33490                :    (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle, 
33491                :                   tmpval);
33492                :    ValidateGC((DrawablePtr)pTile, pgcScratch);
33493                :    rect.x = 0;
33494                :    rect.y = 0;
33495                :    rect.width = w;
33496                :    rect.height = h;
33497                :    (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect);
33498                :    /* Always remember to free the scratch graphics context after use. */
33499                :    FreeScratchGC(pgcScratch);
33500                :
33501                :    pGC->tileIsPixel = FALSE;
33502                :    pGC->tile.pixmap = pTile;
33503                :    return TRUE;
33504                :}
33505                :
33506                :_X_EXPORT int
33507                :CopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask)
33508                :{
33509                :    BITS32      index2;
33510                :    BITS32      maskQ;
33511                :    int         error = 0;
33512                :
33513                :    if (pgcSrc == pgcDst)
33514                :        return Success;
33515                :    pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
33516                :    pgcDst->stateChanges |= mask;
33517                :    maskQ = mask;
33518                :    while (mask)
33519                :    {
33520                :        index2 = (BITS32) lowbit (mask);
33521                :        mask &= ~index2;
33522                :        switch (index2)
33523                :        {
33524                :            case GCFunction:
33525                :                pgcDst->alu = pgcSrc->alu;
33526                :                break;
33527                :            case GCPlaneMask:
33528                :                pgcDst->planemask = pgcSrc->planemask;
33529                :                break;
33530                :            case GCForeground:
33531                :                pgcDst->fgPixel = pgcSrc->fgPixel;
33532                :                break;
33533                :            case GCBackground:
33534                :                pgcDst->bgPixel = pgcSrc->bgPixel;
33535                :                break;
33536                :            case GCLineWidth:
33537                :                pgcDst->lineWidth = pgcSrc->lineWidth;
33538                :                break;
33539                :            case GCLineStyle:
33540                :                pgcDst->lineStyle = pgcSrc->lineStyle;
33541                :                break;
33542                :            case GCCapStyle:
33543                :                pgcDst->capStyle = pgcSrc->capStyle;
33544                :                break;
33545                :            case GCJoinStyle:
33546                :                pgcDst->joinStyle = pgcSrc->joinStyle;
33547                :                break;
33548                :            case GCFillStyle:
33549                :                pgcDst->fillStyle = pgcSrc->fillStyle;
33550                :                break;
33551                :            case GCFillRule:
33552                :                pgcDst->fillRule = pgcSrc->fillRule;
33553                :                break;
33554                :            case GCTile:
33555                :                {
33556                :                    if (EqualPixUnion(pgcDst->tileIsPixel,
33557                :                                      pgcDst->tile,
33558                :                                      pgcSrc->tileIsPixel,
33559                :                                      pgcSrc->tile))
33560                :                    {
33561                :                        break;
33562                :                    }
33563                :                    if (!pgcDst->tileIsPixel)
33564                :                        (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap);
33565                :                    pgcDst->tileIsPixel = pgcSrc->tileIsPixel;
33566                :                    pgcDst->tile = pgcSrc->tile;
33567                :                    if (!pgcDst->tileIsPixel)
33568                :                       pgcDst->tile.pixmap->refcnt++;
33569                :                    break;
33570                :                }
33571                :            case GCStipple:
33572                :                {
33573                :                    if (pgcDst->stipple == pgcSrc->stipple)
33574                :                        break;
33575                :                    if (pgcDst->stipple)
33576                :                        (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple);
33577                :                    pgcDst->stipple = pgcSrc->stipple;
33578                :                    if (pgcDst->stipple)
33579                :                        pgcDst->stipple->refcnt ++;
33580                :                    break;
33581                :                }
33582                :            case GCTileStipXOrigin:
33583                :                pgcDst->patOrg.x = pgcSrc->patOrg.x;
33584                :                break;
33585                :            case GCTileStipYOrigin:
33586                :                pgcDst->patOrg.y = pgcSrc->patOrg.y;
33587                :                break;
33588                :            case GCFont:
33589                :                if (pgcDst->font == pgcSrc->font)
33590                :                    break;
33591                :                if (pgcDst->font)
33592                :                    CloseFont(pgcDst->font, (Font)0);
33593                :                if ((pgcDst->font = pgcSrc->font) != NullFont)
33594                :                    (pgcDst->font)->refcnt++;
33595                :                break;
33596                :            case GCSubwindowMode:
33597                :                pgcDst->subWindowMode = pgcSrc->subWindowMode;
33598                :                break;
33599                :            case GCGraphicsExposures:
33600                :                pgcDst->graphicsExposures = pgcSrc->graphicsExposures;
33601                :                break;
33602                :            case GCClipXOrigin:
33603                :                pgcDst->clipOrg.x = pgcSrc->clipOrg.x;
33604                :                break;
33605                :            case GCClipYOrigin:
33606                :                pgcDst->clipOrg.y = pgcSrc->clipOrg.y;
33607                :                break;
33608                :            case GCClipMask:
33609                :                (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
33610                :                break;
33611                :            case GCDashOffset:
33612                :                pgcDst->dashOffset = pgcSrc->dashOffset;
33613                :                break;
33614                :            case GCDashList:
33615                :                if (pgcSrc->dash == DefaultDash)
33616                :                {
33617                :                    if (pgcDst->dash != DefaultDash)
33618                :                    {
33619                :                        xfree(pgcDst->dash);
33620                :                        pgcDst->numInDashList = pgcSrc->numInDashList;
33621                :                        pgcDst->dash = pgcSrc->dash;
33622                :                    }
33623                :                }
33624                :                else
33625                :                {
33626                :                    unsigned char *dash;
33627                :                    unsigned int i;
33628                :
33629                :                    dash = (unsigned char *)xalloc(pgcSrc->numInDashList *
33630                :                                                   sizeof(unsigned char));
33631                :                    if (dash)
33632                :                    {
33633                :                        if (pgcDst->dash != DefaultDash)
33634                :                            xfree(pgcDst->dash);
33635                :                        pgcDst->numInDashList = pgcSrc->numInDashList;
33636                :                        pgcDst->dash = dash;
33637                :                        for (i=0; i<pgcSrc->numInDashList; i++)
33638                :                            dash[i] = pgcSrc->dash[i];
33639                :                    }
33640                :                    else
33641                :                        error = BadAlloc;
33642                :                }
33643                :                break;
33644                :            case GCArcMode:
33645                :                pgcDst->arcMode = pgcSrc->arcMode;
33646                :                break;
33647                :            default:
33648                :                clientErrorValue = maskQ;
33649                :                error = BadValue;
33650                :                break;
33651                :        }
33652                :    }
33653                :    if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel)
33654                :    {
33655                :        if (!CreateDefaultTile (pgcDst))
33656                :        {
33657                :            pgcDst->fillStyle = FillSolid;
33658                :            error = BadAlloc;
33659                :        }
33660                :    }
33661                :    (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst);
33662                :    return error;
33663                :}
33664                :
33665                :/**
33666                : * does the diX part of freeing the characteristics in the GC.
33667                : *
33668                : *  \param value  must conform to DeleteType
33669                : */
33670                :_X_EXPORT int
33671                :FreeGC(pointer value, XID gid)
33672                :{ /* FreeGC total:      1  0.0011 */
33673                :    GCPtr pGC = (GCPtr)value;
33674                :
33675                :    CloseFont(pGC->font, (Font)0);
33676                :    (* pGC->funcs->DestroyClip)(pGC);
33677                :
33678                :    if (!pGC->tileIsPixel)
33679                :        (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
33680                :    if (pGC->stipple)
33681                :        (* pGC->pScreen->DestroyPixmap)(pGC->stipple);
33682                :
33683                :    (*pGC->funcs->DestroyGC) (pGC);
33684      1  0.0011 :    if (pGC->dash != DefaultDash)
33685                :        xfree(pGC->dash);
33686                :    xfree(pGC);
33687                :    return(Success);
33688                :}
33689                :
33690                :/* CreateScratchGC(pScreen, depth)
33691                :    like CreateGC, but doesn't do the default tile or stipple,
33692                :since we can't create them without already having a GC.  any code
33693                :using the tile or stipple has to set them explicitly anyway,
33694                :since the state of the scratch gc is unknown.  This is OK
33695                :because ChangeGC() has to be able to deal with NULL tiles and
33696                :stipples anyway (in case the CreateGC() call has provided a 
33697                :value for them -- we can't set the default tile until the
33698                :client-supplied attributes are installed, since the fgPixel
33699                :is what fills the default tile.  (maybe this comment should
33700                :go with CreateGC() or ChangeGC().)
33701                :*/
33702                :
33703                :_X_EXPORT GCPtr
33704                :CreateScratchGC(ScreenPtr pScreen, unsigned depth)
33705                :{
33706                :    GCPtr pGC;
33707                :
33708                :    pGC = AllocateGC(pScreen);
33709                :    if (!pGC)
33710                :        return (GCPtr)NULL;
33711                :
33712                :    pGC->pScreen = pScreen;
33713                :    pGC->depth = depth;
33714                :    pGC->alu = GXcopy; /* dst <- src */
33715                :    pGC->planemask = ~0;
33716                :    pGC->serialNumber = 0;
33717                :
33718                :    pGC->fgPixel = 0;
33719                :    pGC->bgPixel = 1;
33720                :    pGC->lineWidth = 0;
33721                :    pGC->lineStyle = LineSolid;
33722                :    pGC->capStyle = CapButt;
33723                :    pGC->joinStyle = JoinMiter;
33724                :    pGC->fillStyle = FillSolid;
33725                :    pGC->fillRule = EvenOddRule;
33726                :    pGC->arcMode = ArcPieSlice;
33727                :    pGC->font = defaultFont;
33728                :    if ( pGC->font)  /* necessary, because open of default font could fail */
33729                :        pGC->font->refcnt++;
33730                :    pGC->tileIsPixel = TRUE;
33731                :    pGC->tile.pixel = 0;
33732                :    pGC->stipple = NullPixmap;
33733                :    pGC->patOrg.x = 0;
33734                :    pGC->patOrg.y = 0;
33735                :    pGC->subWindowMode = ClipByChildren;
33736                :    pGC->graphicsExposures = TRUE;
33737                :    pGC->clipOrg.x = 0;
33738                :    pGC->clipOrg.y = 0;
33739                :    pGC->clientClipType = CT_NONE;
33740                :    pGC->dashOffset = 0;
33741                :    pGC->numInDashList = 2;
33742                :    pGC->dash = DefaultDash;
33743                :    pGC->lastWinOrg.x = 0;
33744                :    pGC->lastWinOrg.y = 0;
33745                :
33746                :    pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
33747                :    if (!(*pScreen->CreateGC)(pGC))
33748                :    {
33749                :        FreeGC(pGC, (XID)0);
33750                :        pGC = (GCPtr)NULL;
33751                :    }
33752                :    return pGC;
33753                :}
33754                :
33755                :void
33756                :FreeGCperDepth(int screenNum)
33757                :{
33758                :    int i;
33759                :    ScreenPtr pScreen;
33760                :    GCPtr *ppGC;
33761                :
33762                :    pScreen = screenInfo.screens[screenNum];
33763                :    ppGC = pScreen->GCperDepth;
33764                :
33765                :    for (i = 0; i <= pScreen->numDepths; i++)
33766                :        (void)FreeGC(ppGC[i], (XID)0);
33767                :    pScreen->rgf = ~0L;
33768                :}
33769                :
33770                :
33771                :Bool
33772                :CreateGCperDepth(int screenNum)
33773                :{
33774                :    int i;
33775                :    ScreenPtr pScreen;
33776                :    DepthPtr pDepth;
33777                :    GCPtr *ppGC;
33778                :
33779                :    pScreen = screenInfo.screens[screenNum];
33780                :    pScreen->rgf = 0;
33781                :    ppGC = pScreen->GCperDepth;
33782                :    /* do depth 1 separately because it's not included in list */
33783                :    if (!(ppGC[0] = CreateScratchGC(pScreen, 1)))
33784                :        return FALSE;
33785                :    ppGC[0]->graphicsExposures = FALSE;
33786                :    /* Make sure we don't overflow GCperDepth[] */
33787                :    if( pScreen->numDepths > MAXFORMATS )
33788                :            return FALSE;
33789                :
33790                :    pDepth = pScreen->allowedDepths;
33791                :    for (i=0; i<pScreen->numDepths; i++, pDepth++)
33792                :    {
33793                :        if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth)))
33794                :        {
33795                :            for (; i >= 0; i--)
33796                :                (void)FreeGC(ppGC[i], (XID)0);
33797                :            return FALSE;
33798                :        }
33799                :        ppGC[i+1]->graphicsExposures = FALSE;
33800                :    }
33801                :    return TRUE;
33802                :}
33803                :
33804                :Bool
33805                :CreateDefaultStipple(int screenNum)
33806                :{
33807                :    ScreenPtr pScreen;
33808                :    XID tmpval[3];
33809                :    xRectangle rect;
33810                :    CARD16 w, h;
33811                :    GCPtr pgcScratch;
33812                :
33813                :    pScreen = screenInfo.screens[screenNum];
33814                :
33815                :    w = 16;
33816                :    h = 16;
33817                :    (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen);
33818                :    if (!(pScreen->PixmapPerDepth[0] =
33819                :                        (*pScreen->CreatePixmap)(pScreen, w, h, 1)))
33820                :        return FALSE;
33821                :    /* fill stipple with 1 */
33822                :    tmpval[0] = GXcopy; tmpval[1] = 1; tmpval[2] = FillSolid;
33823                :    pgcScratch = GetScratchGC(1, pScreen);
33824                :    if (!pgcScratch)
33825                :    {
33826                :        (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]);
33827                :        return FALSE;
33828                :    }
33829                :    (void)ChangeGC(pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval);
33830                :    ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch);
33831                :    rect.x = 0;
33832                :    rect.y = 0;
33833                :    rect.width = w;
33834                :    rect.height = h;
33835                :    (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], 
33836                :                                     pgcScratch, 1, &rect);
33837                :    FreeScratchGC(pgcScratch);
33838                :    return TRUE;
33839                :}
33840                :
33841                :void
33842                :FreeDefaultStipple(int screenNum)
33843                :{
33844                :    ScreenPtr pScreen = screenInfo.screens[screenNum];
33845                :    (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]);
33846                :}
33847                :
33848                :_X_EXPORT int
33849                :SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash)
33850                :{
33851                :    long i;
33852                :    unsigned char *p, *indash;
33853                :    BITS32 maskQ = 0;
33854                :
33855                :    i = ndash;
33856                :    p = pdash;
33857                :    while (i--)
33858                :    {
33859                :        if (!*p++)
33860                :        {
33861                :            /* dash segment must be > 0 */
33862                :            clientErrorValue = 0;
33863                :            return BadValue;
33864                :        }
33865                :    }
33866                :
33867                :    if (ndash & 1)
33868                :        p = (unsigned char *)xalloc(2 * ndash * sizeof(unsigned char));
33869                :    else
33870                :        p = (unsigned char *)xalloc(ndash * sizeof(unsigned char));
33871                :    if (!p)
33872                :        return BadAlloc;
33873                :
33874                :    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
33875                :    if (offset != pGC->dashOffset)
33876                :    {
33877                :        pGC->dashOffset = offset;
33878                :        pGC->stateChanges |= GCDashOffset;
33879                :        maskQ |= GCDashOffset;
33880                :    }
33881                :
33882                :    if (pGC->dash != DefaultDash)
33883                :        xfree(pGC->dash);
33884                :    pGC->numInDashList = ndash;
33885                :    pGC->dash = p;
33886                :    if (ndash & 1)
33887                :    {
33888                :        pGC->numInDashList += ndash;
33889                :        indash = pdash;
33890                :        i = ndash;
33891                :        while (i--)
33892                :            *p++ = *indash++;
33893                :    }
33894                :    while(ndash--)
33895                :        *p++ = *pdash++;
33896                :    pGC->stateChanges |= GCDashList;
33897                :    maskQ |= GCDashList;
33898                :
33899                :    if (pGC->funcs->ChangeGC)
33900                :        (*pGC->funcs->ChangeGC) (pGC, maskQ);
33901                :    return Success;
33902                :}
33903                :
33904                :_X_EXPORT int
33905                :VerifyRectOrder(int nrects, xRectangle *prects, int ordering)
33906                :{ /* VerifyRectOrder total:      1  0.0011 */
33907                :    xRectangle  *prectP, *prectN;
33908                :    int i;
33909                :
33910                :    switch(ordering)
33911                :    {
33912                :      case Unsorted:
33913                :          return CT_UNSORTED;
33914                :      case YSorted:
33915                :          if(nrects > 1)
33916                :          {
33917                :              for(i = 1, prectP = prects, prectN = prects + 1;
33918                :                  i < nrects;
33919                :                  i++, prectP++, prectN++)
33920                :                  if(prectN->y < prectP->y)
33921                :                      return -1;
33922                :          }
33923                :          return CT_YSORTED;
33924                :      case YXSorted:
33925                :          if(nrects > 1)
33926                :          {
33927                :              for(i = 1, prectP = prects, prectN = prects + 1;
33928                :                  i < nrects;
33929                :                  i++, prectP++, prectN++)
33930                :                  if((prectN->y < prectP->y) ||
33931                :                      ( (prectN->y == prectP->y) &&
33932                :                        (prectN->x < prectP->x) ) )
33933                :                      return -1;
33934                :          }
33935                :          return CT_YXSORTED;
33936                :      case YXBanded:
33937      1  0.0011 :          if(nrects > 1)
33938                :          {
33939                :              for(i = 1, prectP = prects, prectN = prects + 1;
33940                :                  i < nrects;
33941                :                  i++, prectP++, prectN++)
33942                :                  if((prectN->y != prectP->y &&
33943                :                      prectN->y < prectP->y + (int) prectP->height) ||
33944                :                     ((prectN->y == prectP->y) &&
33945                :                      (prectN->height != prectP->height ||
33946                :                       prectN->x < prectP->x + (int) prectP->width)))
33947                :                      return -1;
33948                :          }
33949                :          return CT_YXBANDED;
33950                :    }
33951                :    return -1;
33952                :}
33953                :
33954                :_X_EXPORT int
33955                :SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, 
33956                :             xRectangle *prects, int ordering)
33957                :{ /* SetClipRects total:      2  0.0022 */
33958                :    int                 newct, size;
33959                :    xRectangle          *prectsNew;
33960                :
33961                :    newct = VerifyRectOrder(nrects, prects, ordering);
33962                :    if (newct < 0)
33963                :        return(BadMatch);
33964                :    size = nrects * sizeof(xRectangle);
33965                :    prectsNew = (xRectangle *) xalloc(size);
33966                :    if (!prectsNew && size)
33967                :        return BadAlloc;
33968                :
33969                :    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
33970      1  0.0011 :    pGC->clipOrg.x = xOrigin;
33971                :    pGC->stateChanges |= GCClipXOrigin;
33972                :                 
33973                :    pGC->clipOrg.y = yOrigin;
33974                :    pGC->stateChanges |= GCClipYOrigin;
33975                :
33976                :    if (size)
33977                :        memmove((char *)prectsNew, (char *)prects, size);
33978                :    (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects);
33979      1  0.0011 :    if (pGC->funcs->ChangeGC)
33980                :        (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask);
33981                :    return Success;
33982                :}
33983                :
33984                :
33985                :/*
33986                :   sets reasonable defaults 
33987                :   if we can get a pre-allocated one, use it and mark it as used.
33988                :   if we can't, create one out of whole cloth (The Velveteen GC -- if
33989                :   you use it often enough it will become real.)
33990                :*/
33991                :_X_EXPORT GCPtr
33992                :GetScratchGC(unsigned depth, ScreenPtr pScreen)
33993      2  0.0022 :{ /* GetScratchGC total:      8  0.0087 */
33994                :    int i;
33995                :    GCPtr pGC;
33996                :
33997                :    for (i=0; i<=pScreen->numDepths; i++)
33998      2  0.0022 :        if ( pScreen->GCperDepth[i]->depth == depth &&
33999                :             !(pScreen->rgf & (1L << (i+1)))
34000                :           )
34001                :        {
34002                :            pScreen->rgf |= (1L << (i+1));
34003                :            pGC = (pScreen->GCperDepth[i]);
34004                :
34005                :            pGC->alu = GXcopy;
34006                :            pGC->planemask = ~0;
34007                :            pGC->serialNumber = 0;
34008                :            pGC->fgPixel = 0;
34009                :            pGC->bgPixel = 1;
34010                :            pGC->lineWidth = 0;
34011                :            pGC->lineStyle = LineSolid;
34012                :            pGC->capStyle = CapButt;
34013                :            pGC->joinStyle = JoinMiter;
34014                :            pGC->fillStyle = FillSolid;
34015                :            pGC->fillRule = EvenOddRule;
34016                :            pGC->arcMode = ArcChord;
34017      3  0.0033 :            pGC->patOrg.x = 0;
34018                :            pGC->patOrg.y = 0;
34019                :            pGC->subWindowMode = ClipByChildren;
34020                :            pGC->graphicsExposures = FALSE;
34021                :            pGC->clipOrg.x = 0;
34022                :            pGC->clipOrg.y = 0;
34023                :            if (pGC->clientClipType != CT_NONE)
34024                :                (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0);
34025                :            pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
34026                :            return pGC;
34027                :        }
34028                :    /* if we make it this far, need to roll our own */
34029                :    pGC = CreateScratchGC(pScreen, depth);
34030                :    if (pGC)
34031                :        pGC->graphicsExposures = FALSE;
34032                :    return pGC;
34033      1  0.0011 :}
34034                :
34035                :/*
34036                :   if the gc to free is in the table of pre-existing ones,
34037                :mark it as available.
34038                :   if not, free it for real
34039                :*/
34040                :_X_EXPORT void
34041                :FreeScratchGC(GCPtr pGC)
34042      4  0.0044 :{ /* FreeScratchGC total:     10  0.0109 */
34043                :    ScreenPtr pScreen = pGC->pScreen;
34044                :    int i;
34045                :
34046      1  0.0011 :    for (i=0; i<=pScreen->numDepths; i++)
34047                :    {
34048      3  0.0033 :        if ( pScreen->GCperDepth[i] == pGC)
34049                :        {
34050                :            pScreen->rgf &= ~(1L << (i+1));
34051      1  0.0011 :            return;
34052                :        }
34053                :    }
34054                :    (void)FreeGC(pGC, (GContext)0);
34055      1  0.0011 :}
34056 /* 
34057  * Total samples for file : "/home/cworth/src/xorg/xserver/Xext/security.c"
34058  * 
34059  *     50  0.0545
34060  */
34061
34062
34063                :/*
34064                :
34065                :Copyright 1996, 1998  The Open Group
34066                :
34067                :Permission to use, copy, modify, distribute, and sell this software and its
34068                :documentation for any purpose is hereby granted without fee, provided that
34069                :the above copyright notice appear in all copies and that both that
34070                :copyright notice and this permission notice appear in supporting
34071                :documentation.
34072                :
34073                :The above copyright notice and this permission notice shall be included in
34074                :all copies or substantial portions of the Software.
34075                :
34076                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34077                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34078                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
34079                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
34080                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34081                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34082                :
34083                :Except as contained in this notice, the name of The Open Group shall not be
34084                :used in advertising or otherwise to promote the sale, use or other dealings
34085                :in this Software without prior written authorization from The Open Group.
34086                :
34087                :*/
34088                :
34089                :#ifdef HAVE_DIX_CONFIG_H
34090                :#include <dix-config.h>
34091                :#endif
34092                :
34093                :#include "dixstruct.h"
34094                :#include "extnsionst.h"
34095                :#include "windowstr.h"
34096                :#include "inputstr.h"
34097                :#include "scrnintstr.h"
34098                :#include "gcstruct.h"
34099                :#include "colormapst.h"
34100                :#include "propertyst.h"
34101                :#include "xacestr.h"
34102                :#include "securitysrv.h"
34103                :#include <X11/extensions/securstr.h>
34104                :#include <assert.h>
34105                :#include <stdarg.h>
34106                :#ifdef XAPPGROUP
34107                :#include "appgroup.h"
34108                :#endif
34109                :#include <stdio.h>  /* for file reading operations */
34110                :#include <X11/Xatom.h>  /* for XA_STRING */
34111                :
34112                :#ifndef DEFAULTPOLICYFILE
34113                :# define DEFAULTPOLICYFILE NULL
34114                :#endif
34115                :#if defined(WIN32) || defined(__CYGWIN__)
34116                :#include <X11/Xos.h>
34117                :#undef index
34118                :#endif
34119                :
34120                :#include "modinit.h"
34121                :
34122                :static int SecurityErrorBase;  /* first Security error number */
34123                :static int SecurityEventBase;  /* first Security event number */
34124                :static int securityClientPrivateIndex;
34125                :static int securityExtnsnPrivateIndex;
34126                :
34127                :/* this is what we store as client security state */
34128                :typedef struct {
34129                :    unsigned int trustLevel;
34130                :    XID authId;
34131                :} SecurityClientStateRec;
34132                :
34133                :#define STATEVAL(extnsn) \
34134                :    ((extnsn)->devPrivates[securityExtnsnPrivateIndex].val)
34135                :#define STATEPTR(client) \
34136                :    ((client)->devPrivates[securityClientPrivateIndex].ptr)
34137                :#define TRUSTLEVEL(client) \
34138                :    (((SecurityClientStateRec*)STATEPTR(client))->trustLevel)
34139                :#define AUTHID(client) \
34140                :    (((SecurityClientStateRec*)STATEPTR(client))->authId)
34141                :
34142                :static CallbackListPtr SecurityValidateGroupCallback = NULL;
34143                :
34144                :RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */
34145                :
34146                :static RESTYPE RTEventClient;
34147                :
34148                :#define CALLBACK(name) static void \
34149                :name(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
34150                :
34151                :/* SecurityAudit
34152                : *
34153                : * Arguments:
34154                : *      format is the formatting string to be used to interpret the
34155                : *        remaining arguments.
34156                : *
34157                : * Returns: nothing.
34158                : *
34159                : * Side Effects:
34160                : *      Writes the message to the log file if security logging is on.
34161                : */
34162                :
34163                :static void
34164                :SecurityAudit(char *format, ...)
34165                :{
34166                :    va_list args;
34167                :
34168                :    if (auditTrailLevel < SECURITY_AUDIT_LEVEL)
34169                :        return;
34170                :    va_start(args, format);
34171                :    VAuditF(format, args);
34172                :    va_end(args);
34173                :} /* SecurityAudit */
34174                :
34175                :#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
34176                :
34177                :/* SecurityDeleteAuthorization
34178                : *
34179                : * Arguments:
34180                : *      value is the authorization to delete.
34181                : *      id is its resource ID.
34182                : *
34183                : * Returns: Success.
34184                : *
34185                : * Side Effects:
34186                : *      Frees everything associated with the authorization.
34187                : */
34188                :
34189                :static int
34190                :SecurityDeleteAuthorization(
34191                :    pointer value,
34192                :    XID id)
34193                :{
34194                :    SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value;
34195                :    unsigned short name_len, data_len;
34196                :    char *name, *data;
34197                :    int status;
34198                :    int i;
34199                :    OtherClientsPtr pEventClient;
34200                :
34201                :    /* Remove the auth using the os layer auth manager */
34202                :
34203                :    status = AuthorizationFromID(pAuth->id, &name_len, &name,
34204                :                                 &data_len, &data);
34205                :    assert(status);
34206                :    status = RemoveAuthorization(name_len, name, data_len, data);
34207                :    assert(status);
34208                :    (void)status;
34209                :
34210                :    /* free the auth timer if there is one */
34211                :
34212                :    if (pAuth->timer) TimerFree(pAuth->timer);
34213                :
34214                :    /* send revoke events */
34215                :
34216                :    while ((pEventClient = pAuth->eventClients))
34217                :    {
34218                :        /* send revocation event event */
34219                :        ClientPtr client = rClient(pEventClient);
34220                :
34221                :        if (!client->clientGone)
34222                :        {
34223                :            xSecurityAuthorizationRevokedEvent are;
34224                :            are.type = SecurityEventBase + XSecurityAuthorizationRevoked;
34225                :            are.sequenceNumber = client->sequence;
34226                :            are.authId = pAuth->id;
34227                :            WriteEventsToClient(client, 1, (xEvent *)&are);
34228                :        }
34229                :        FreeResource(pEventClient->resource, RT_NONE);
34230                :    }
34231                :
34232                :    /* kill all clients using this auth */
34233                :
34234                :    for (i = 1; i<currentMaxClients; i++)
34235                :    {
34236                :        if (clients[i] && (AUTHID(clients[i]) == pAuth->id))
34237                :            CloseDownClient(clients[i]);
34238                :    }
34239                :
34240                :    SecurityAudit("revoked authorization ID %d\n", pAuth->id);
34241                :    xfree(pAuth);
34242                :    return Success;
34243                :
34244                :} /* SecurityDeleteAuthorization */
34245                :
34246                :
34247                :/* resource delete function for RTEventClient */
34248                :static int
34249                :SecurityDeleteAuthorizationEventClient(
34250                :    pointer value,
34251                :    XID id)
34252                :{
34253                :    OtherClientsPtr pEventClient, prev = NULL;
34254                :    SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value;
34255                :
34256                :    for (pEventClient = pAuth->eventClients;
34257                :         pEventClient;
34258                :         pEventClient = pEventClient->next)
34259                :    {
34260                :        if (pEventClient->resource == id)
34261                :        {
34262                :            if (prev)
34263                :                prev->next = pEventClient->next;
34264                :            else
34265                :                pAuth->eventClients = pEventClient->next;
34266                :            xfree(pEventClient);
34267                :            return(Success);
34268                :        }
34269                :        prev = pEventClient;
34270                :    }
34271                :    /*NOTREACHED*/
34272                :    return -1; /* make compiler happy */
34273                :} /* SecurityDeleteAuthorizationEventClient */
34274                :
34275                :
34276                :/* SecurityComputeAuthorizationTimeout
34277                : *
34278                : * Arguments:
34279                : *      pAuth is the authorization for which we are computing the timeout
34280                : *      seconds is the number of seconds we want to wait
34281                : *
34282                : * Returns:
34283                : *      the number of milliseconds that the auth timer should be set to
34284                : *
34285                : * Side Effects:
34286                : *      Sets pAuth->secondsRemaining to any "overflow" amount of time
34287                : *      that didn't fit in 32 bits worth of milliseconds
34288                : */
34289                :
34290                :static CARD32
34291                :SecurityComputeAuthorizationTimeout(
34292                :    SecurityAuthorizationPtr pAuth,
34293                :    unsigned int seconds)
34294                :{
34295                :    /* maxSecs is the number of full seconds that can be expressed in
34296                :     * 32 bits worth of milliseconds
34297                :     */
34298                :    CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND;
34299                :
34300                :    if (seconds > maxSecs)
34301                :    { /* only come here if we want to wait more than 49 days */
34302                :        pAuth->secondsRemaining = seconds - maxSecs;
34303                :        return maxSecs * MILLI_PER_SECOND;
34304                :    }
34305                :    else
34306                :    { /* by far the common case */
34307                :        pAuth->secondsRemaining = 0;
34308                :        return seconds * MILLI_PER_SECOND;
34309                :    }
34310                :} /* SecurityStartAuthorizationTimer */
34311                :
34312                :/* SecurityAuthorizationExpired
34313                : *
34314                : * This function is passed as an argument to TimerSet and gets called from
34315                : * the timer manager in the os layer when its time is up.
34316                : *
34317                : * Arguments:
34318                : *      timer is the timer for this authorization.
34319                : *      time is the current time.
34320                : *      pval is the authorization whose time is up.
34321                : *
34322                : * Returns:
34323                : *      A new time delay in milliseconds if the timer should wait some
34324                : *      more, else zero.
34325                : *
34326                : * Side Effects:
34327                : *      Frees the authorization resource if the timeout period is really
34328                : *      over, otherwise recomputes pAuth->secondsRemaining.
34329                : */
34330                :
34331                :static CARD32
34332                :SecurityAuthorizationExpired(
34333                :    OsTimerPtr timer,
34334                :    CARD32 time,
34335                :    pointer pval)
34336                :{
34337                :    SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval;
34338                :
34339                :    assert(pAuth->timer == timer);
34340                :
34341                :    if (pAuth->secondsRemaining)
34342                :    {
34343                :        return SecurityComputeAuthorizationTimeout(pAuth,
34344                :                                                   pAuth->secondsRemaining);
34345                :    }
34346                :    else
34347                :    {
34348                :        FreeResource(pAuth->id, RT_NONE);
34349                :        return 0;
34350                :    }
34351                :} /* SecurityAuthorizationExpired */
34352                :
34353                :/* SecurityStartAuthorizationTimer
34354                : *
34355                : * Arguments:
34356                : *      pAuth is the authorization whose timer should be started.
34357                : *
34358                : * Returns: nothing.
34359                : *
34360                : * Side Effects:
34361                : *      A timer is started, set to expire after the timeout period for
34362                : *      this authorization.  When it expires, the function
34363                : *      SecurityAuthorizationExpired will be called.
34364                : */
34365                :
34366                :static void
34367                :SecurityStartAuthorizationTimer(
34368                :    SecurityAuthorizationPtr pAuth)
34369                :{
34370                :    pAuth->timer = TimerSet(pAuth->timer, 0,
34371                :        SecurityComputeAuthorizationTimeout(pAuth, pAuth->timeout),
34372                :                            SecurityAuthorizationExpired, pAuth);
34373                :} /* SecurityStartAuthorizationTimer */
34374                :
34375                :
34376                :/* Proc functions all take a client argument, execute the request in
34377                : * client->requestBuffer, and return a protocol error status.
34378                : */
34379                :
34380                :static int
34381                :ProcSecurityQueryVersion(
34382                :    ClientPtr client)
34383                :{
34384                :    /* REQUEST(xSecurityQueryVersionReq); */
34385                :    xSecurityQueryVersionReply  rep;
34386                :
34387                :    /* paranoia: this "can't happen" because this extension is hidden
34388                :     * from untrusted clients, but just in case...
34389                :     */
34390                :    if (TRUSTLEVEL(client) != XSecurityClientTrusted)
34391                :        return BadRequest;
34392                :
34393                :    REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
34394                :    rep.type            = X_Reply;
34395                :    rep.sequenceNumber  = client->sequence;
34396                :    rep.length          = 0;
34397                :    rep.majorVersion    = SECURITY_MAJOR_VERSION;
34398                :    rep.minorVersion    = SECURITY_MINOR_VERSION;
34399                :    if(client->swapped)
34400                :    {
34401                :        register char n;
34402                :        swaps(&rep.sequenceNumber, n);
34403                :        swaps(&rep.majorVersion, n);
34404                :        swaps(&rep.minorVersion, n);
34405                :    }
34406                :    (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply),
34407                :                        (char *)&rep);
34408                :    return (client->noClientException);
34409                :} /* ProcSecurityQueryVersion */
34410                :
34411                :
34412                :static int
34413                :SecurityEventSelectForAuthorization(
34414                :    SecurityAuthorizationPtr pAuth,
34415                :    ClientPtr client,
34416                :    Mask mask)
34417                :{
34418                :    OtherClients *pEventClient;
34419                :
34420                :    for (pEventClient = pAuth->eventClients;
34421                :         pEventClient;
34422                :         pEventClient = pEventClient->next)
34423                :    {
34424                :        if (SameClient(pEventClient, client))
34425                :        {
34426                :            if (mask == 0)
34427                :                FreeResource(pEventClient->resource, RT_NONE);
34428                :            else
34429                :                pEventClient->mask = mask;
34430                :            return Success;
34431                :        }
34432                :    }
34433                :    
34434                :    pEventClient = (OtherClients *) xalloc(sizeof(OtherClients));
34435                :    if (!pEventClient)
34436                :        return BadAlloc;
34437                :    pEventClient->mask = mask;
34438                :    pEventClient->resource = FakeClientID(client->index);
34439                :    pEventClient->next = pAuth->eventClients;
34440                :    if (!AddResource(pEventClient->resource, RTEventClient,
34441                :                     (pointer)pAuth))
34442                :    {
34443                :        xfree(pEventClient);
34444                :        return BadAlloc;
34445                :    }
34446                :    pAuth->eventClients = pEventClient;
34447                :
34448                :    return Success;
34449                :} /* SecurityEventSelectForAuthorization */
34450                :
34451                :
34452                :static int
34453                :ProcSecurityGenerateAuthorization(
34454                :    ClientPtr client)
34455                :{
34456                :    REQUEST(xSecurityGenerateAuthorizationReq);
34457                :    int len;                    /* request length in CARD32s*/
34458                :    Bool removeAuth = FALSE;    /* if bailout, call RemoveAuthorization? */
34459                :    SecurityAuthorizationPtr pAuth = NULL;  /* auth we are creating */
34460                :    int err;                    /* error to return from this function */
34461                :    XID authId;                 /* authorization ID assigned by os layer */
34462                :    xSecurityGenerateAuthorizationReply rep; /* reply struct */
34463                :    unsigned int trustLevel;    /* trust level of new auth */
34464                :    XID group;                  /* group of new auth */
34465                :    CARD32 timeout;             /* timeout of new auth */
34466                :    CARD32 *values;             /* list of supplied attributes */
34467                :    char *protoname;            /* auth proto name sent in request */
34468                :    char *protodata;            /* auth proto data sent in request */
34469                :    unsigned int authdata_len;  /* # bytes of generated auth data */
34470                :    char *pAuthdata;            /* generated auth data */
34471                :    Mask eventMask;             /* what events on this auth does client want */
34472                :
34473                :    /* paranoia: this "can't happen" because this extension is hidden
34474                :     * from untrusted clients, but just in case...
34475                :     */
34476                :    if (TRUSTLEVEL(client) != XSecurityClientTrusted)
34477                :        return BadRequest;
34478                :
34479                :    /* check request length */
34480                :
34481                :    REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
34482                :    len = SIZEOF(xSecurityGenerateAuthorizationReq) >> 2;
34483                :    len += (stuff->nbytesAuthProto + (unsigned)3) >> 2;
34484                :    len += (stuff->nbytesAuthData  + (unsigned)3) >> 2;
34485                :    values = ((CARD32 *)stuff) + len;
34486                :    len += Ones(stuff->valueMask);
34487                :    if (client->req_len != len)
34488                :        return BadLength;
34489                :
34490                :    /* check valuemask */
34491                :    if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes)
34492                :    {
34493                :        client->errorValue = stuff->valueMask;
34494                :        return BadValue;
34495                :    }
34496                :
34497                :    /* check timeout */
34498                :    timeout = 60;
34499                :    if (stuff->valueMask & XSecurityTimeout)
34500                :    {
34501                :        timeout = *values++;
34502                :    }
34503                :
34504                :    /* check trustLevel */
34505                :    trustLevel = XSecurityClientUntrusted;
34506                :    if (stuff->valueMask & XSecurityTrustLevel)
34507                :    {
34508                :        trustLevel = *values++;
34509                :        if (trustLevel != XSecurityClientTrusted &&
34510                :            trustLevel != XSecurityClientUntrusted)
34511                :        {
34512                :            client->errorValue = trustLevel;
34513                :            return BadValue;
34514                :        }
34515                :    }
34516                :
34517                :    /* check group */
34518                :    group = None;
34519                :    if (stuff->valueMask & XSecurityGroup)
34520                :    {
34521                :        group = *values++;
34522                :        if (SecurityValidateGroupCallback)
34523                :        {
34524                :            SecurityValidateGroupInfoRec vgi;
34525                :            vgi.group = group;
34526                :            vgi.valid = FALSE;
34527                :            CallCallbacks(&SecurityValidateGroupCallback, (pointer)&vgi);
34528                :
34529                :            /* if nobody said they recognized it, it's an error */
34530                :
34531                :            if (!vgi.valid)
34532                :            {
34533                :                client->errorValue = group;
34534                :                return BadValue;
34535                :            }
34536                :        }
34537                :    }
34538                :
34539                :    /* check event mask */
34540                :    eventMask = 0;
34541                :    if (stuff->valueMask & XSecurityEventMask)
34542                :    {
34543                :        eventMask = *values++;
34544                :        if (eventMask & ~XSecurityAllEventMasks)
34545                :        {
34546                :            client->errorValue = eventMask;
34547                :            return BadValue;
34548                :        }
34549                :    }
34550                :
34551                :    protoname = (char *)&stuff[1];
34552                :    protodata = protoname + ((stuff->nbytesAuthProto + (unsigned)3) >> 2);
34553                :
34554                :    /* call os layer to generate the authorization */
34555                :
34556                :    authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname,
34557                :                                   stuff->nbytesAuthData,  protodata,
34558                :                                   &authdata_len, &pAuthdata);
34559                :    if ((XID) ~0L == authId)
34560                :    {
34561                :        err = SecurityErrorBase + XSecurityBadAuthorizationProtocol;
34562                :        goto bailout;
34563                :    }
34564                :
34565                :    /* now that we've added the auth, remember to remove it if we have to
34566                :     * abort the request for some reason (like allocation failure)
34567                :     */
34568                :    removeAuth = TRUE;
34569                :
34570                :    /* associate additional information with this auth ID */
34571                :
34572                :    pAuth = (SecurityAuthorizationPtr)xalloc(sizeof(SecurityAuthorizationRec));
34573                :    if (!pAuth)
34574                :    {
34575                :        err = BadAlloc;
34576                :        goto bailout;
34577                :    }
34578                :
34579                :    /* fill in the auth fields */
34580                :
34581                :    pAuth->id = authId;
34582                :    pAuth->timeout = timeout;
34583                :    pAuth->group = group;
34584                :    pAuth->trustLevel = trustLevel;
34585                :    pAuth->refcnt = 0;  /* the auth was just created; nobody's using it yet */
34586                :    pAuth->secondsRemaining = 0;
34587                :    pAuth->timer = NULL;
34588                :    pAuth->eventClients = NULL;
34589                :
34590                :    /* handle event selection */
34591                :    if (eventMask)
34592                :    {
34593                :        err = SecurityEventSelectForAuthorization(pAuth, client, eventMask);
34594                :        if (err != Success)
34595                :            goto bailout;
34596                :    }
34597                :
34598                :    if (!AddResource(authId, SecurityAuthorizationResType, pAuth))
34599                :    {
34600                :        err = BadAlloc;
34601                :        goto bailout;
34602                :    }
34603                :
34604                :    /* start the timer ticking */
34605                :
34606                :    if (pAuth->timeout != 0)
34607                :        SecurityStartAuthorizationTimer(pAuth);
34608                :
34609                :    /* tell client the auth id and data */
34610                :
34611                :    rep.type = X_Reply;
34612                :    rep.length = (authdata_len + 3) >> 2;
34613                :    rep.sequenceNumber = client->sequence;
34614                :    rep.authId = authId;
34615                :    rep.dataLength = authdata_len;
34616                :
34617                :    if (client->swapped)
34618                :    {
34619                :        register char n;
34620                :        swapl(&rep.length, n);
34621                :        swaps(&rep.sequenceNumber, n);
34622                :        swapl(&rep.authId, n);
34623                :        swaps(&rep.dataLength, n);
34624                :    }
34625                :
34626                :    WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply),
34627                :                  (char *)&rep);
34628                :    WriteToClient(client, authdata_len, pAuthdata);
34629                :
34630                :    SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n",
34631                :                  client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout,
34632                :                  pAuth->group, eventMask);
34633                :
34634                :    /* the request succeeded; don't call RemoveAuthorization or free pAuth */
34635                :
34636                :    removeAuth = FALSE;
34637                :    pAuth = NULL;
34638                :    err = client->noClientException;
34639                :
34640                :bailout:
34641                :    if (removeAuth)
34642                :        RemoveAuthorization(stuff->nbytesAuthProto, protoname,
34643                :                            authdata_len, pAuthdata);
34644                :    if (pAuth) xfree(pAuth);
34645                :    return err;
34646                :
34647                :} /* ProcSecurityGenerateAuthorization */
34648                :
34649                :static int
34650                :ProcSecurityRevokeAuthorization(
34651                :    ClientPtr client)
34652                :{
34653                :    REQUEST(xSecurityRevokeAuthorizationReq);
34654                :    SecurityAuthorizationPtr pAuth;
34655                :
34656                :    /* paranoia: this "can't happen" because this extension is hidden
34657                :     * from untrusted clients, but just in case...
34658                :     */
34659                :    if (TRUSTLEVEL(client) != XSecurityClientTrusted)
34660                :        return BadRequest;
34661                :
34662                :    REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
34663                :
34664                :    pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(client,
34665                :        stuff->authId, SecurityAuthorizationResType, DixDestroyAccess);
34666                :    if (!pAuth)
34667                :        return SecurityErrorBase + XSecurityBadAuthorization;
34668                :
34669                :    FreeResource(stuff->authId, RT_NONE);
34670                :    return Success;
34671                :} /* ProcSecurityRevokeAuthorization */
34672                :
34673                :
34674                :static int
34675                :ProcSecurityDispatch(
34676                :    ClientPtr client)
34677                :{
34678                :    REQUEST(xReq);
34679                :
34680                :    switch (stuff->data)
34681                :    {
34682                :        case X_SecurityQueryVersion:
34683                :            return ProcSecurityQueryVersion(client);
34684                :        case X_SecurityGenerateAuthorization:
34685                :            return ProcSecurityGenerateAuthorization(client);
34686                :        case X_SecurityRevokeAuthorization:
34687                :            return ProcSecurityRevokeAuthorization(client);
34688                :        default:
34689                :            return BadRequest;
34690                :    }
34691                :} /* ProcSecurityDispatch */
34692                :
34693                :static int
34694                :SProcSecurityQueryVersion(
34695                :    ClientPtr client)
34696                :{
34697                :    REQUEST(xSecurityQueryVersionReq);
34698                :    register char       n;
34699                :
34700                :    swaps(&stuff->length, n);
34701                :    REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
34702                :    swaps(&stuff->majorVersion, n);
34703                :    swaps(&stuff->minorVersion,n);
34704                :    return ProcSecurityQueryVersion(client);
34705                :} /* SProcSecurityQueryVersion */
34706                :
34707                :
34708                :static int
34709                :SProcSecurityGenerateAuthorization(
34710                :    ClientPtr client)
34711                :{
34712                :    REQUEST(xSecurityGenerateAuthorizationReq);
34713                :    register char       n;
34714                :    CARD32 *values;
34715                :    unsigned long nvalues;
34716                :
34717                :    swaps(&stuff->length, n);
34718                :    REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
34719                :    swaps(&stuff->nbytesAuthProto, n);
34720                :    swaps(&stuff->nbytesAuthData, n);
34721                :    swapl(&stuff->valueMask, n);
34722                :    values = (CARD32 *)(&stuff[1]) +
34723                :        ((stuff->nbytesAuthProto + (unsigned)3) >> 2) +
34724                :        ((stuff->nbytesAuthData + (unsigned)3) >> 2);
34725                :    nvalues = (((CARD32 *)stuff) + stuff->length) - values;
34726                :    SwapLongs(values, nvalues);
34727                :    return ProcSecurityGenerateAuthorization(client);
34728                :} /* SProcSecurityGenerateAuthorization */
34729                :
34730                :
34731                :static int
34732                :SProcSecurityRevokeAuthorization(
34733                :    ClientPtr client)
34734                :{
34735                :    REQUEST(xSecurityRevokeAuthorizationReq);
34736                :    register char       n;
34737                :
34738                :    swaps(&stuff->length, n);
34739                :    REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
34740                :    swapl(&stuff->authId, n);
34741                :    return ProcSecurityRevokeAuthorization(client);
34742                :} /* SProcSecurityRevokeAuthorization */
34743                :
34744                :
34745                :static int
34746                :SProcSecurityDispatch(
34747                :    ClientPtr client)
34748                :{
34749                :    REQUEST(xReq);
34750                :
34751                :    switch (stuff->data)
34752                :    {
34753                :        case X_SecurityQueryVersion:
34754                :            return SProcSecurityQueryVersion(client);
34755                :        case X_SecurityGenerateAuthorization:
34756                :            return SProcSecurityGenerateAuthorization(client);
34757                :        case X_SecurityRevokeAuthorization:
34758                :            return SProcSecurityRevokeAuthorization(client);
34759                :        default:
34760                :            return BadRequest;
34761                :    }
34762                :} /* SProcSecurityDispatch */
34763                :
34764                :static void 
34765                :SwapSecurityAuthorizationRevokedEvent(
34766                :    xSecurityAuthorizationRevokedEvent *from,
34767                :    xSecurityAuthorizationRevokedEvent *to)
34768                :{
34769                :    to->type = from->type;
34770                :    to->detail = from->detail;
34771                :    cpswaps(from->sequenceNumber, to->sequenceNumber);
34772                :    cpswapl(from->authId, to->authId);
34773                :}
34774                :
34775                :/* SecurityDetermineEventPropogationLimits
34776                : *
34777                : * This is a helper function for SecurityCheckDeviceAccess.
34778                : *
34779                : * Arguments:
34780                : *      dev is the device for which the starting and stopping windows for
34781                : *      event propogation should be determined.
34782                : *      The values pointed to by ppWin and ppStopWin are not used.
34783                : *
34784                : * Returns:
34785                : *      ppWin is filled in with a pointer to the window at which event
34786                : *      propogation for the given device should start given the current
34787                : *      state of the server (pointer position, window layout, etc.)
34788                : *      ppStopWin is filled in with the window at which event propogation
34789                : *      should stop; events should not go to ppStopWin.
34790                : *
34791                : * Side Effects: none.
34792                : */
34793                :
34794                :static void
34795                :SecurityDetermineEventPropogationLimits(
34796                :    DeviceIntPtr dev,
34797                :    WindowPtr *ppWin,
34798                :    WindowPtr *ppStopWin)
34799                :{
34800                :    WindowPtr pFocusWin = dev->focus ? dev->focus->win : NoneWin;
34801                :
34802                :    if (pFocusWin == NoneWin)
34803                :    { /* no focus -- events don't go anywhere */
34804                :        *ppWin = *ppStopWin = NULL;
34805                :        return;
34806                :    }
34807                :
34808                :    if (pFocusWin == PointerRootWin)
34809                :    { /* focus follows the pointer */
34810                :        *ppWin = GetSpriteWindow();
34811                :        *ppStopWin = NULL; /* propogate all the way to the root */
34812                :    }
34813                :    else
34814                :    { /* a real window is set for the focus */
34815                :        WindowPtr pSpriteWin = GetSpriteWindow();
34816                :        *ppStopWin = pFocusWin->parent; /* don't go past the focus window */
34817                :
34818                :        /* if the pointer is in a subwindow of the focus window, start
34819                :         * at that subwindow, else start at the focus window itself
34820                :         */
34821                :        if (IsParent(pFocusWin, pSpriteWin))
34822                :             *ppWin = pSpriteWin;
34823                :        else *ppWin = pFocusWin;
34824                :    }
34825                :} /* SecurityDetermineEventPropogationLimits */
34826                :
34827                :
34828                :/* SecurityCheckDeviceAccess
34829                : *
34830                : * Arguments:
34831                : *      client is the client attempting to access a device.
34832                : *      dev is the device being accessed.
34833                : *      fromRequest is TRUE if the device access is a direct result of
34834                : *        the client executing some request and FALSE if it is a
34835                : *        result of the server trying to send an event (e.g. KeymapNotify)
34836                : *        to the client.
34837                : * Returns:
34838                : *      TRUE if the device access should be allowed, else FALSE.
34839                : *
34840                : * Side Effects:
34841                : *      An audit message is generated if access is denied.
34842                : */
34843                :
34844                :CALLBACK(SecurityCheckDeviceAccess)
34845                :{
34846                :    XaceDeviceAccessRec *rec = (XaceDeviceAccessRec*)calldata;
34847                :    ClientPtr client = rec->client;
34848                :    DeviceIntPtr dev = rec->dev;
34849                :    Bool fromRequest = rec->fromRequest;
34850                :    WindowPtr pWin, pStopWin;
34851                :    Bool untrusted_got_event;
34852                :    Bool found_event_window;
34853                :    Mask eventmask;
34854                :    int reqtype = 0;
34855                :
34856                :    /* trusted clients always allowed to do anything */
34857                :    if (TRUSTLEVEL(client) == XSecurityClientTrusted)
34858                :        return;
34859                :
34860                :    /* device security other than keyboard is not implemented yet */
34861                :    if (dev != inputInfo.keyboard)
34862                :        return;
34863                :
34864                :    /* some untrusted client wants access */
34865                :
34866                :    if (fromRequest)
34867                :    {
34868                :        reqtype = ((xReq *)client->requestBuffer)->reqType;
34869                :        switch (reqtype)
34870                :        {
34871                :            /* never allow these */
34872                :            case X_ChangeKeyboardMapping:
34873                :            case X_ChangeKeyboardControl:
34874                :            case X_SetModifierMapping:
34875                :                SecurityAudit("client %d attempted request %d\n",
34876                :                              client->index, reqtype);
34877                :                rec->rval = FALSE;
34878                :                return;
34879                :            default:
34880                :                break;
34881                :        }
34882                :    }
34883                :
34884                :    untrusted_got_event = FALSE;
34885                :    found_event_window = FALSE;
34886                :
34887                :    if (dev->grab)
34888                :    {
34889                :        untrusted_got_event =
34890                :            (TRUSTLEVEL(rClient(dev->grab)) != XSecurityClientTrusted);
34891                :    }
34892                :    else
34893                :    {
34894                :        SecurityDetermineEventPropogationLimits(dev, &pWin, &pStopWin);
34895                :
34896                :        eventmask = KeyPressMask | KeyReleaseMask;
34897                :        while ( (pWin != pStopWin) && !found_event_window)
34898                :        {
34899                :            OtherClients *other;
34900                :
34901                :            if (pWin->eventMask & eventmask)
34902                :            {
34903                :                found_event_window = TRUE;
34904                :                client = wClient(pWin);
34905                :                if (TRUSTLEVEL(client) != XSecurityClientTrusted)
34906                :                {
34907                :                    untrusted_got_event = TRUE;
34908                :                }
34909                :            }
34910                :            if (wOtherEventMasks(pWin) & eventmask)
34911                :            {
34912                :                found_event_window = TRUE;
34913                :                for (other = wOtherClients(pWin); other; other = other->next)
34914                :                {
34915                :                    if (other->mask & eventmask)
34916                :                    {
34917                :                        client = rClient(other);
34918                :                        if (TRUSTLEVEL(client) != XSecurityClientTrusted)
34919                :                        {
34920                :                            untrusted_got_event = TRUE;
34921                :                            break;
34922                :                        }
34923                :                    }
34924                :                }
34925                :            }
34926                :            if (wDontPropagateMask(pWin) & eventmask)
34927                :                break;
34928                :            pWin = pWin->parent;
34929                :        } /* while propogating the event */
34930                :    }
34931                :
34932                :    /* allow access by untrusted clients only if an event would have gone 
34933                :     * to an untrusted client
34934                :     */
34935                :    
34936                :    if (!untrusted_got_event)
34937                :    {
34938                :        char *devname = dev->name;
34939                :        if (!devname) devname = "unnamed";
34940                :        if (fromRequest)
34941                :            SecurityAudit("client %d attempted request %d device %d (%s)\n",
34942                :                          client->index, reqtype, dev->id, devname);
34943                :        else
34944                :            SecurityAudit("client %d attempted to access device %d (%s)\n",
34945                :                          client->index, dev->id, devname);
34946                :        rec->rval = FALSE;
34947                :    }
34948                :    return;
34949                :} /* SecurityCheckDeviceAccess */
34950                :
34951                :
34952                :
34953                :/* SecurityAuditResourceIDAccess
34954                : *
34955                : * Arguments:
34956                : *      client is the client doing the resource access.
34957                : *      id is the resource id.
34958                : *
34959                : * Returns: NULL
34960                : *
34961                : * Side Effects:
34962                : *      An audit message is generated with details of the denied
34963                : *      resource access.
34964                : */
34965                :
34966                :static pointer
34967                :SecurityAuditResourceIDAccess(
34968                :    ClientPtr client,
34969                :    XID id)
34970                :{
34971                :    int cid = CLIENT_ID(id);
34972                :    int reqtype = ((xReq *)client->requestBuffer)->reqType;
34973                :    switch (reqtype)
34974                :    {
34975                :        case X_ChangeProperty:
34976                :        case X_DeleteProperty:
34977                :        case X_GetProperty:
34978                :        {
34979                :            xChangePropertyReq *req =
34980                :                (xChangePropertyReq *)client->requestBuffer;
34981                :            int propertyatom = req->property;
34982                :            char *propertyname = NameForAtom(propertyatom);
34983                :
34984                :            SecurityAudit("client %d attempted request %d with window 0x%x property %s of client %d\n",
34985                :                   client->index, reqtype, id, propertyname, cid);
34986                :            break;
34987                :        }
34988                :        default:
34989                :        {
34990                :            SecurityAudit("client %d attempted request %d with resource 0x%x of client %d\n",
34991                :                   client->index, reqtype, id, cid);
34992                :            break;
34993                :        }   
34994                :    }
34995                :    return NULL;
34996                :} /* SecurityAuditResourceIDAccess */
34997                :
34998                :
34999                :/* SecurityCheckResourceIDAccess
35000                : *
35001                : * This function gets plugged into client->CheckAccess and is called from
35002                : * SecurityLookupIDByType/Class to determine if the client can access the
35003                : * resource.
35004                : *
35005                : * Arguments:
35006                : *      client is the client doing the resource access.
35007                : *      id is the resource id.
35008                : *      rtype is its type or class.
35009                : *      access_mode represents the intended use of the resource; see
35010                : *        resource.h.
35011                : *      res is a pointer to the resource structure for this resource.
35012                : *
35013                : * Returns:
35014                : *      If access is granted, the value of rval that was passed in, else FALSE.
35015                : *
35016                : * Side Effects:
35017                : *      Disallowed resource accesses are audited.
35018                : */
35019                :
35020                :CALLBACK(SecurityCheckResourceIDAccess)
35021      8  0.0087 :{ /* SecurityCheckResourceIDAccess total:     36  0.0392 */
35022                :    XaceResourceAccessRec *rec = (XaceResourceAccessRec*)calldata;
35023                :    ClientPtr client = rec->client;
35024      1  0.0011 :    XID id = rec->id;
35025      3  0.0033 :    RESTYPE rtype = rec->rtype;
35026                :    Mask access_mode = rec->access_mode;
35027                :    pointer rval = rec->res;
35028                :    int cid, reqtype;
35029                :
35030     22  0.0240 :    if (TRUSTLEVEL(client) == XSecurityClientTrusted ||
35031                :        DixUnknownAccess == access_mode)
35032                :        return;       /* for compatibility, we have to allow access */
35033                :
35034                :    cid = CLIENT_ID(id);
35035                :    reqtype = ((xReq *)client->requestBuffer)->reqType;
35036                :    switch (reqtype)
35037                :    { /* these are always allowed */
35038                :        case X_QueryTree:
35039                :        case X_TranslateCoords:
35040                :        case X_GetGeometry:
35041                :        /* property access is controlled in SecurityCheckPropertyAccess */
35042                :        case X_GetProperty:
35043                :        case X_ChangeProperty:
35044                :        case X_DeleteProperty:
35045                :        case X_RotateProperties:
35046                :        case X_ListProperties:
35047                :            return;
35048                :        default:
35049                :            break;
35050                :    }
35051                :
35052                :    if (cid != 0)
35053                :    { /* not a server-owned resource */
35054                :     /*
35055                :      * The following 'if' restricts clients to only access resources at
35056                :      * the same trustLevel.  Since there are currently only two trust levels,
35057                :      * and trusted clients never call this function, this degenerates into
35058                :      * saying that untrusted clients can only access resources of other
35059                :      * untrusted clients.  One way to add the notion of groups would be to
35060                :      * allow values other than Trusted (0) and Untrusted (1) for this field.
35061                :      * Clients at the same trust level would be able to use each other's
35062                :      * resources, but not those of clients at other trust levels.  I haven't
35063                :      * tried it, but this probably mostly works already.  The obvious
35064                :      * competing alternative for grouping clients for security purposes is to
35065                :      * use app groups.  dpw
35066                :      */
35067                :        if (TRUSTLEVEL(client) == TRUSTLEVEL(clients[cid])
35068                :#ifdef XAPPGROUP
35069                :            || (RT_COLORMAP == rtype && 
35070                :                XagDefaultColormap (client) == (Colormap) id)
35071                :#endif
35072                :        )
35073                :            return;
35074                :        else
35075                :            goto deny;
35076                :    }
35077                :    else /* server-owned resource - probably a default colormap or root window */
35078                :    {
35079                :        if (RT_WINDOW == rtype || RC_DRAWABLE == rtype)
35080                :        {
35081                :            switch (reqtype)
35082                :            {   /* the following operations are allowed on root windows */
35083                :                case X_CreatePixmap:
35084                :                case X_CreateGC:
35085                :                case X_CreateWindow:
35086                :                case X_CreateColormap:
35087                :                case X_ListProperties:
35088                :                case X_GrabPointer:
35089                :                case X_UngrabButton:
35090                :                case X_QueryBestSize:
35091                :                case X_GetWindowAttributes:
35092                :                    break;
35093                :                case X_SendEvent:
35094                :                { /* see if it is an event specified by the ICCCM */
35095                :                    xSendEventReq *req = (xSendEventReq *)
35096                :                                                (client->requestBuffer);
35097                :                    if (req->propagate == xTrue
35098                :                        ||
35099                :                          (req->eventMask != ColormapChangeMask &&
35100                :                           req->eventMask != StructureNotifyMask &&
35101                :                           req->eventMask !=
35102                :                              (SubstructureRedirectMask|SubstructureNotifyMask)
35103                :                          )
35104                :                        ||
35105                :                          (req->event.u.u.type != UnmapNotify &&
35106                :                           req->event.u.u.type != ConfigureRequest &&
35107                :                           req->event.u.u.type != ClientMessage
35108                :                          )
35109                :                       )
35110                :                    { /* not an ICCCM event */
35111                :                        goto deny;
35112                :                    }
35113                :                    break;
35114                :                } /* case X_SendEvent on root */
35115                :
35116                :                case X_ChangeWindowAttributes:
35117                :                { /* Allow selection of PropertyNotify and StructureNotify
35118                :                   * events on the root.
35119                :                   */
35120                :                    xChangeWindowAttributesReq *req =
35121                :                        (xChangeWindowAttributesReq *)(client->requestBuffer);
35122                :                    if (req->valueMask == CWEventMask)
35123                :                    {
35124                :                        CARD32 value = *((CARD32 *)(req + 1));
35125                :                        if ( (value &
35126                :                              ~(PropertyChangeMask|StructureNotifyMask)) == 0)
35127                :                            break;
35128                :                    }
35129                :                    goto deny;
35130                :                } /* case X_ChangeWindowAttributes on root */
35131                :
35132                :                default:
35133                :                {
35134                :                    /* others not allowed */
35135                :                    goto deny;
35136                :                }
35137                :            }
35138                :        } /* end server-owned window or drawable */
35139                :        else if (SecurityAuthorizationResType == rtype)
35140                :        {
35141                :            SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)rval;
35142                :            if (pAuth->trustLevel != TRUSTLEVEL(client))
35143                :                goto deny;
35144                :        }
35145                :        else if (RT_COLORMAP != rtype)
35146                :        { /* don't allow anything else besides colormaps */
35147                :            goto deny;
35148                :        }
35149                :    }
35150                :    return;
35151                :  deny:
35152                :    SecurityAuditResourceIDAccess(client, id);
35153                :    rec->rval = FALSE;  /* deny access */
35154      2  0.0022 :} /* SecurityCheckResourceIDAccess */
35155                :
35156                :
35157                :/* SecurityClientStateCallback
35158                : *
35159                : * Arguments:
35160                : *      pcbl is &ClientStateCallback.
35161                : *      nullata is NULL.
35162                : *      calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
35163                : *      which contains information about client state changes.
35164                : *
35165                : * Returns: nothing.
35166                : *
35167                : * Side Effects:
35168                : * 
35169                : * If a new client is connecting, its authorization ID is copied to
35170                : * client->authID.  If this is a generated authorization, its reference
35171                : * count is bumped, its timer is cancelled if it was running, and its
35172                : * trustlevel is copied to TRUSTLEVEL(client).
35173                : * 
35174                : * If a client is disconnecting and the client was using a generated
35175                : * authorization, the authorization's reference count is decremented, and
35176                : * if it is now zero, the timer for this authorization is started.
35177                : */
35178                :
35179                :CALLBACK(SecurityClientStateCallback)
35180                :{
35181                :    NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
35182                :    ClientPtr client = pci->client;
35183                :
35184                :    switch (client->clientState)
35185                :    {
35186                :    case ClientStateInitial:
35187                :        TRUSTLEVEL(client) = XSecurityClientTrusted;
35188                :        AUTHID(client) = None;
35189                :        break;
35190                :
35191                :    case ClientStateRunning:
35192                :        { 
35193                :            XID authId = AuthorizationIDOfClient(client);
35194                :            SecurityAuthorizationPtr pAuth;
35195                :
35196                :            TRUSTLEVEL(client) = XSecurityClientTrusted;
35197                :            AUTHID(client) = authId;
35198                :            pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
35199                :                                                SecurityAuthorizationResType);
35200                :            if (pAuth)
35201                :            { /* it is a generated authorization */
35202                :                pAuth->refcnt++;
35203                :                if (pAuth->refcnt == 1)
35204                :                {
35205                :                    if (pAuth->timer) TimerCancel(pAuth->timer);
35206                :                }
35207                :                TRUSTLEVEL(client) = pAuth->trustLevel;
35208                :            }
35209                :            break;
35210                :        }
35211                :    case ClientStateGone:
35212                :    case ClientStateRetained: /* client disconnected */
35213                :        {
35214                :            SecurityAuthorizationPtr pAuth;
35215                :
35216                :            /* client may not have any state (bad authorization) */
35217                :            if (!STATEPTR(client))
35218                :                break;
35219                :
35220                :            pAuth = (SecurityAuthorizationPtr)LookupIDByType(AUTHID(client),
35221                :                                                SecurityAuthorizationResType);
35222                :            if (pAuth)
35223                :            { /* it is a generated authorization */
35224                :                pAuth->refcnt--;
35225                :                if (pAuth->refcnt == 0)
35226                :                {
35227                :                    SecurityStartAuthorizationTimer(pAuth);
35228                :                }
35229                :            }       
35230                :            break;
35231                :        }
35232                :    default: break; 
35233                :    }
35234                :} /* SecurityClientStateCallback */
35235                :
35236                :CALLBACK(SecurityCheckDrawableAccess)
35237                :{
35238                :    XaceDrawableAccessRec *rec = (XaceDrawableAccessRec*)calldata;
35239                :
35240                :    if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
35241                :        rec->rval = FALSE;
35242                :}
35243                :
35244                :CALLBACK(SecurityCheckMapAccess)
35245                :{
35246                :    XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata;
35247                :    WindowPtr pWin = rec->pWin;
35248                :
35249                :    if (STATEPTR(rec->client) &&
35250                :        (TRUSTLEVEL(rec->client) != XSecurityClientTrusted) &&
35251                :        (pWin->drawable.class == InputOnly) &&
35252                :        pWin->parent && pWin->parent->parent &&
35253                :        (TRUSTLEVEL(wClient(pWin->parent)) == XSecurityClientTrusted))
35254                :
35255                :        rec->rval = FALSE;
35256                :}
35257                :
35258                :CALLBACK(SecurityCheckBackgrndAccess)
35259                :{
35260                :    XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata;
35261                :
35262                :    if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
35263                :        rec->rval = FALSE;
35264                :}
35265                :
35266                :CALLBACK(SecurityCheckExtAccess)
35267      3  0.0033 :{ /* SecurityCheckExtAccess total:     14  0.0153 */
35268                :    XaceExtAccessRec *rec = (XaceExtAccessRec*)calldata;
35269                :
35270     10  0.0109 :    if ((TRUSTLEVEL(rec->client) != XSecurityClientTrusted) &&
35271                :        !STATEVAL(rec->ext))
35272                :
35273                :        rec->rval = FALSE;
35274      1  0.0011 :}
35275                :
35276                :CALLBACK(SecurityCheckHostlistAccess)
35277                :{
35278                :    XaceHostlistAccessRec *rec = (XaceHostlistAccessRec*)calldata;
35279                : 
35280                :    if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
35281                :    {
35282                :        rec->rval = FALSE;
35283                :        if (rec->access_mode == DixWriteAccess)
35284                :            SecurityAudit("client %d attempted to change host access\n",
35285                :                          rec->client->index);
35286                :        else
35287                :            SecurityAudit("client %d attempted to list hosts\n",
35288                :                          rec->client->index);
35289                :    }
35290                :}
35291                :
35292                :CALLBACK(SecurityDeclareExtSecure)
35293                :{
35294                :    XaceDeclareExtSecureRec *rec = (XaceDeclareExtSecureRec*)calldata;
35295                :
35296                :    /* security state for extensions is simply a boolean trust value */
35297                :    STATEVAL(rec->ext) = rec->secure;
35298                :}
35299                :
35300                :/**********************************************************************/
35301                :
35302                :typedef struct _PropertyAccessRec {
35303                :    ATOM name;
35304                :    ATOM mustHaveProperty;
35305                :    char *mustHaveValue;
35306                :    char windowRestriction;
35307                :#define SecurityAnyWindow          0
35308                :#define SecurityRootWindow         1
35309                :#define SecurityWindowWithProperty 2
35310                :    char readAction;
35311                :    char writeAction;
35312                :    char destroyAction;
35313                :    struct _PropertyAccessRec *next;
35314                :} PropertyAccessRec, *PropertyAccessPtr;
35315                :
35316                :static PropertyAccessPtr PropertyAccessList = NULL;
35317                :static char SecurityDefaultAction = XaceErrorOperation;
35318                :static char *SecurityPolicyFile = DEFAULTPOLICYFILE;
35319                :static ATOM SecurityMaxPropertyName = 0;
35320                :
35321                :static char *SecurityKeywords[] = {
35322                :#define SecurityKeywordComment 0
35323                :    "#",
35324                :#define SecurityKeywordProperty 1
35325                :    "property",
35326                :#define SecurityKeywordSitePolicy 2
35327                :    "sitepolicy",
35328                :#define SecurityKeywordRoot 3
35329                :    "root",
35330                :#define SecurityKeywordAny 4
35331                :    "any"
35332                :};
35333                :
35334                :#define NUMKEYWORDS (sizeof(SecurityKeywords) / sizeof(char *))
35335                :
35336                :#undef PROPDEBUG
35337                :/*#define PROPDEBUG  1*/
35338                :
35339                :static void
35340                :SecurityFreePropertyAccessList(void)
35341                :{
35342                :    while (PropertyAccessList)
35343                :    {
35344                :        PropertyAccessPtr freeit = PropertyAccessList;
35345                :        PropertyAccessList = PropertyAccessList->next;
35346                :        xfree(freeit);
35347                :    }
35348                :} /* SecurityFreePropertyAccessList */
35349                :
35350                :#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') )
35351                :
35352                :static char *
35353                :SecuritySkipWhitespace(
35354                :    char *p)
35355                :{
35356                :    while (SecurityIsWhitespace(*p))
35357                :        p++;
35358                :    return p;
35359                :} /* SecuritySkipWhitespace */
35360                :
35361                :
35362                :static char *
35363                :SecurityParseString(
35364                :    char **rest)
35365                :{
35366                :    char *startOfString;
35367                :    char *s = *rest;
35368                :    char endChar = 0;
35369                :
35370                :    s = SecuritySkipWhitespace(s);
35371                :
35372                :    if (*s == '"' || *s == '\'')
35373                :    {
35374                :        endChar = *s++;
35375                :        startOfString = s;
35376                :        while (*s && (*s != endChar))
35377                :            s++;
35378                :    }
35379                :    else
35380                :    {
35381                :        startOfString = s;
35382                :        while (*s && !SecurityIsWhitespace(*s))
35383                :            s++;
35384                :    }
35385                :    if (*s)
35386                :    {
35387                :        *s = '\0';
35388                :        *rest = s + 1;
35389                :        return startOfString;
35390                :    }
35391                :    else
35392                :    {
35393                :        *rest = s;
35394                :        return (endChar) ? NULL : startOfString;
35395                :    }
35396                :} /* SecurityParseString */
35397                :
35398                :
35399                :static int
35400                :SecurityParseKeyword(
35401                :    char **p)
35402                :{
35403                :    int i;
35404                :    char *s = *p;
35405                :    s = SecuritySkipWhitespace(s);
35406                :    for (i = 0; i < NUMKEYWORDS; i++)
35407                :    {
35408                :        int len = strlen(SecurityKeywords[i]);
35409                :        if (strncmp(s, SecurityKeywords[i], len) == 0)
35410                :        {
35411                :            *p = s + len;
35412                :            return (i);
35413                :        }
35414                :    }
35415                :    *p = s;
35416                :    return -1;
35417                :} /* SecurityParseKeyword */
35418                :
35419                :
35420                :static Bool
35421                :SecurityParsePropertyAccessRule(
35422                :    char *p)
35423                :{
35424                :    char *propname;
35425                :    char c;
35426                :    char action = SecurityDefaultAction;
35427                :    char readAction, writeAction, destroyAction;
35428                :    PropertyAccessPtr pacl, prev, cur;
35429                :    char *mustHaveProperty = NULL;
35430                :    char *mustHaveValue = NULL;
35431                :    Bool invalid;
35432                :    char windowRestriction;
35433                :    int size;
35434                :    int keyword;
35435                :
35436                :    /* get property name */
35437                :    propname = SecurityParseString(&p);
35438                :    if (!propname || (strlen(propname) == 0))
35439                :        return FALSE;
35440                :
35441                :    /* get window on which property must reside for rule to apply */
35442                :
35443                :    keyword = SecurityParseKeyword(&p);
35444                :    if (keyword == SecurityKeywordRoot)
35445                :        windowRestriction = SecurityRootWindow;
35446                :    else if (keyword == SecurityKeywordAny) 
35447                :        windowRestriction = SecurityAnyWindow;
35448                :    else /* not root or any, must be a property name */
35449                :    {
35450                :        mustHaveProperty = SecurityParseString(&p);
35451                :        if (!mustHaveProperty || (strlen(mustHaveProperty) == 0))
35452                :            return FALSE;
35453                :        windowRestriction = SecurityWindowWithProperty;
35454                :        p = SecuritySkipWhitespace(p);
35455                :        if (*p == '=')
35456                :        { /* property value is specified too */
35457                :            p++; /* skip over '=' */
35458                :            mustHaveValue = SecurityParseString(&p);
35459                :            if (!mustHaveValue)
35460                :                return FALSE;
35461                :        }
35462                :    }
35463                :
35464                :    /* get operations and actions */
35465                :
35466                :    invalid = FALSE;
35467                :    readAction = writeAction = destroyAction = SecurityDefaultAction;
35468                :    while ( (c = *p++) && !invalid)
35469                :    {
35470                :        switch (c)
35471                :        {
35472                :            case 'i': action = XaceIgnoreOperation; break;
35473                :            case 'a': action = XaceAllowOperation;  break;
35474                :            case 'e': action = XaceErrorOperation;  break;
35475                :
35476                :            case 'r': readAction    = action; break;
35477                :            case 'w': writeAction   = action; break;
35478                :            case 'd': destroyAction = action; break;
35479                :
35480                :            default :
35481                :                if (!SecurityIsWhitespace(c))
35482                :                    invalid = TRUE;
35483                :            break;
35484                :        }
35485                :    }
35486                :    if (invalid)
35487                :        return FALSE;
35488                :
35489                :    /* We've successfully collected all the information needed for this
35490                :     * property access rule.  Now record it in a PropertyAccessRec.
35491                :     */
35492                :    size = sizeof(PropertyAccessRec);
35493                :
35494                :    /* If there is a property value string, allocate space for it 
35495                :     * right after the PropertyAccessRec.
35496                :     */
35497                :    if (mustHaveValue)
35498                :        size += strlen(mustHaveValue) + 1;
35499                :    pacl = (PropertyAccessPtr)Xalloc(size);
35500                :    if (!pacl)
35501                :        return FALSE;
35502                :
35503                :    pacl->name = MakeAtom(propname, strlen(propname), TRUE);
35504                :    if (pacl->name == BAD_RESOURCE)
35505                :    {
35506                :        Xfree(pacl);
35507                :        return FALSE;
35508                :    }
35509                :    if (mustHaveProperty)
35510                :    {
35511                :        pacl->mustHaveProperty = MakeAtom(mustHaveProperty,
35512                :                                          strlen(mustHaveProperty), TRUE);
35513                :        if (pacl->mustHaveProperty == BAD_RESOURCE)
35514                :        {
35515                :            Xfree(pacl);
35516                :            return FALSE;
35517                :        }
35518                :    }
35519                :    else
35520                :        pacl->mustHaveProperty = 0;
35521                :
35522                :    if (mustHaveValue)
35523                :    {
35524                :        pacl->mustHaveValue = (char *)(pacl + 1);
35525                :        strcpy(pacl->mustHaveValue, mustHaveValue);
35526                :    }
35527                :    else
35528                :        pacl->mustHaveValue = NULL;
35529                :
35530                :    SecurityMaxPropertyName = max(SecurityMaxPropertyName, pacl->name);
35531                :
35532                :    pacl->windowRestriction = windowRestriction;
35533                :    pacl->readAction  = readAction;
35534                :    pacl->writeAction = writeAction;
35535                :    pacl->destroyAction = destroyAction;
35536                :
35537                :    /* link the new rule into the list of rules in order of increasing
35538                :     * property name (atom) value to make searching easier
35539                :     */
35540                :
35541                :    for (prev = NULL,  cur = PropertyAccessList;
35542                :         cur && cur->name <= pacl->name;
35543                :         prev = cur, cur = cur->next)
35544                :        ;
35545                :    if (!prev)
35546                :    {
35547                :        pacl->next = cur;
35548                :        PropertyAccessList = pacl;
35549                :    }
35550                :    else
35551                :    {
35552                :        prev->next = pacl;
35553                :        pacl->next = cur;
35554                :    }
35555                :    return TRUE;
35556                :} /* SecurityParsePropertyAccessRule */
35557                :
35558                :static char **SecurityPolicyStrings = NULL;
35559                :static int nSecurityPolicyStrings = 0;
35560                :
35561                :static Bool
35562                :SecurityParseSitePolicy(
35563                :    char *p)
35564                :{
35565                :    char *policyStr = SecurityParseString(&p);
35566                :    char *copyPolicyStr;
35567                :    char **newStrings;
35568                :
35569                :    if (!policyStr)
35570                :        return FALSE;
35571                :
35572                :    copyPolicyStr = (char *)Xalloc(strlen(policyStr) + 1);
35573                :    if (!copyPolicyStr)
35574                :        return TRUE;
35575                :    strcpy(copyPolicyStr, policyStr);
35576                :    newStrings = (char **)Xrealloc(SecurityPolicyStrings,
35577                :                          sizeof (char *) * (nSecurityPolicyStrings + 1));
35578                :    if (!newStrings)
35579                :    {
35580                :        Xfree(copyPolicyStr);
35581                :        return TRUE;
35582                :    }
35583                :
35584                :    SecurityPolicyStrings = newStrings;
35585                :    SecurityPolicyStrings[nSecurityPolicyStrings++] = copyPolicyStr;
35586                :
35587                :    return TRUE;
35588                :
35589                :} /* SecurityParseSitePolicy */
35590                :
35591                :
35592                :char **
35593                :SecurityGetSitePolicyStrings(n)
35594                :    int *n;
35595                :{
35596                :    *n = nSecurityPolicyStrings;
35597                :    return SecurityPolicyStrings;
35598                :} /* SecurityGetSitePolicyStrings */
35599                :
35600                :static void
35601                :SecurityFreeSitePolicyStrings(void)
35602                :{
35603                :    if (SecurityPolicyStrings)
35604                :    {
35605                :        assert(nSecurityPolicyStrings);
35606                :        while (nSecurityPolicyStrings--)
35607                :        {
35608                :            Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]);
35609                :        }
35610                :        Xfree(SecurityPolicyStrings);
35611                :        SecurityPolicyStrings = NULL;
35612                :        nSecurityPolicyStrings = 0;
35613                :    }
35614                :} /* SecurityFreeSitePolicyStrings */
35615                :
35616                :
35617                :static void
35618                :SecurityLoadPropertyAccessList(void)
35619                :{
35620                :    FILE *f;
35621                :    int lineNumber = 0;
35622                :
35623                :    SecurityMaxPropertyName = 0;
35624                :
35625                :    if (!SecurityPolicyFile)
35626                :        return;
35627                :
35628                :    f = fopen(SecurityPolicyFile, "r");
35629                :    if (!f)
35630                :    {
35631                :        ErrorF("error opening security policy file %s\n",
35632                :               SecurityPolicyFile);
35633                :        return;
35634                :    }
35635                :
35636                :    while (!feof(f))
35637                :    {
35638                :        char buf[200];
35639                :        Bool validLine;
35640                :        char *p;
35641                :
35642                :        if (!(p = fgets(buf, sizeof(buf), f)))
35643                :            break;
35644                :        lineNumber++;
35645                :
35646                :        /* if first line, check version number */
35647                :        if (lineNumber == 1)
35648                :        {
35649                :            char *v = SecurityParseString(&p);
35650                :            if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0)
35651                :            {
35652                :                ErrorF("%s: invalid security policy file version, ignoring file\n",
35653                :                       SecurityPolicyFile);
35654                :                break;
35655                :            }
35656                :            validLine = TRUE;
35657                :        }
35658                :        else
35659                :        {
35660                :            switch (SecurityParseKeyword(&p))
35661                :            {
35662                :                case SecurityKeywordComment:
35663                :                    validLine = TRUE;
35664                :                break;
35665                :
35666                :                case SecurityKeywordProperty:
35667                :                    validLine = SecurityParsePropertyAccessRule(p);
35668                :                break;
35669                :
35670                :                case SecurityKeywordSitePolicy:
35671                :                    validLine = SecurityParseSitePolicy(p);
35672                :                break;
35673                :
35674                :                default:
35675                :                    validLine = (*p == '\0'); /* blank lines OK, others not */
35676                :                break;
35677                :            }
35678                :        }
35679                :
35680                :        if (!validLine)
35681                :            ErrorF("Line %d of %s invalid, ignoring\n",
35682                :                   lineNumber, SecurityPolicyFile);
35683                :    } /* end while more input */
35684                :
35685                :#ifdef PROPDEBUG
35686                :    {
35687                :        PropertyAccessPtr pacl;
35688                :        char *op = "aie";
35689                :        for (pacl = PropertyAccessList; pacl; pacl = pacl->next)
35690                :        {
35691                :            ErrorF("property %s ", NameForAtom(pacl->name));
35692                :            switch (pacl->windowRestriction)
35693                :            {
35694                :                case SecurityAnyWindow: ErrorF("any "); break;
35695                :                case SecurityRootWindow: ErrorF("root "); break;
35696                :                case SecurityWindowWithProperty:
35697                :                {
35698                :                    ErrorF("%s ", NameForAtom(pacl->mustHaveProperty));
35699                :                    if (pacl->mustHaveValue)
35700                :                        ErrorF(" = \"%s\" ", pacl->mustHaveValue);
35701                :
35702                :                }
35703                :                break;
35704                :            }
35705                :            ErrorF("%cr %cw %cd\n", op[pacl->readAction],
35706                :                   op[pacl->writeAction], op[pacl->destroyAction]);
35707                :        }
35708                :    }
35709                :#endif /* PROPDEBUG */
35710                :
35711                :    fclose(f);
35712                :} /* SecurityLoadPropertyAccessList */
35713                :
35714                :
35715                :static Bool
35716                :SecurityMatchString(
35717                :    char *ws,
35718                :    char *cs)
35719                :{
35720                :    while (*ws && *cs)
35721                :    {
35722                :        if (*ws == '*')
35723                :        {
35724                :            Bool match = FALSE;
35725                :            ws++;
35726                :            while (!(match = SecurityMatchString(ws, cs)) && *cs)
35727                :            {
35728                :                cs++;
35729                :            }
35730                :            return match;
35731                :        }
35732                :        else if (*ws == *cs)
35733                :        {
35734                :            ws++;
35735                :            cs++;
35736                :        }
35737                :        else break;
35738                :    }
35739                :    return ( ( (*ws == '\0') || ((*ws == '*') && *(ws+1) == '\0') )
35740                :             && (*cs == '\0') );
35741                :} /* SecurityMatchString */
35742                :
35743                :#ifdef PROPDEBUG
35744                :#include <sys/types.h>
35745                :#include <sys/stat.h>
35746                :#endif
35747                :
35748                :
35749                :CALLBACK(SecurityCheckPropertyAccess)
35750                :{    
35751                :    XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata;
35752                :    ClientPtr client = rec->client;
35753                :    WindowPtr pWin = rec->pWin;
35754                :    ATOM propertyName = rec->propertyName;
35755                :    Mask access_mode = rec->access_mode;
35756                :    PropertyAccessPtr pacl;
35757                :    char action = SecurityDefaultAction;
35758                :
35759                :    /* if client trusted or window untrusted, allow operation */
35760                :
35761                :    if ( (TRUSTLEVEL(client) == XSecurityClientTrusted) ||
35762                :         (TRUSTLEVEL(wClient(pWin)) != XSecurityClientTrusted) )
35763                :        return;
35764                :
35765                :#ifdef PROPDEBUG
35766                :    /* For testing, it's more convenient if the property rules file gets
35767                :     * reloaded whenever it changes, so we can rapidly try things without
35768                :     * having to reset the server.
35769                :     */
35770                :    {
35771                :        struct stat buf;
35772                :        static time_t lastmod = 0;
35773                :        int ret = stat(SecurityPolicyFile , &buf);
35774                :        if ( (ret == 0) && (buf.st_mtime > lastmod) )
35775                :        {
35776                :            ErrorF("reloading property rules\n");
35777                :            SecurityFreePropertyAccessList();
35778                :            SecurityLoadPropertyAccessList();
35779                :            lastmod = buf.st_mtime;
35780                :        }
35781                :    }
35782                :#endif
35783                :
35784                :    /* If the property atom is bigger than any atoms on the list, 
35785                :     * we know we won't find it, so don't even bother looking.
35786                :     */
35787                :    if (propertyName <= SecurityMaxPropertyName)
35788                :    {
35789                :        /* untrusted client operating on trusted window; see if it's allowed */
35790                :
35791                :        for (pacl = PropertyAccessList; pacl; pacl = pacl->next)
35792                :        {
35793                :            if (pacl->name < propertyName)
35794                :                continue;
35795                :            if (pacl->name > propertyName)
35796                :                break;
35797                :
35798                :            /* pacl->name == propertyName, so see if it applies to this window */
35799                :
35800                :            switch (pacl->windowRestriction)
35801                :            {
35802                :                case SecurityAnyWindow: /* always applies */
35803                :                    break;
35804                :
35805                :                case SecurityRootWindow:
35806                :                {
35807                :                    /* if not a root window, this rule doesn't apply */
35808                :                    if (pWin->parent)
35809                :                        continue;
35810                :                }
35811                :                break;
35812                :
35813                :                case SecurityWindowWithProperty:
35814                :                {
35815                :                    PropertyPtr pProp = wUserProps (pWin);
35816                :                    Bool match = FALSE;
35817                :                    char *p;
35818                :                    char *pEndData;
35819                :
35820                :                    while (pProp)
35821                :                    {
35822                :                        if (pProp->propertyName == pacl->mustHaveProperty)
35823                :                            break;
35824                :                        pProp = pProp->next;
35825                :                    }
35826                :                    if (!pProp)
35827                :                        continue;
35828                :                    if (!pacl->mustHaveValue)
35829                :                        break;
35830                :                    if (pProp->type != XA_STRING || pProp->format != 8)
35831                :                        continue;
35832                :
35833                :                    p = pProp->data;
35834                :                    pEndData = ((char *)pProp->data) + pProp->size;
35835                :                    while (!match && p < pEndData)
35836                :                    {
35837                :                         if (SecurityMatchString(pacl->mustHaveValue, p))
35838                :                             match = TRUE;
35839                :                         else
35840                :                         { /* skip to the next string */
35841                :                             while (*p++ && p < pEndData)
35842                :                                 ;
35843                :                         }
35844                :                    }
35845                :                    if (!match)
35846                :                        continue;
35847                :                }
35848                :                break; /* end case SecurityWindowWithProperty */
35849                :            } /* end switch on windowRestriction */
35850                :
35851                :            /* If we get here, the property access rule pacl applies.
35852                :             * If pacl doesn't apply, something above should have
35853                :             * executed a continue, which will skip the follwing code.
35854                :             */
35855                :            action = XaceAllowOperation;
35856                :            if (access_mode & DixReadAccess)
35857                :                action = max(action, pacl->readAction);
35858                :            if (access_mode & DixWriteAccess)
35859                :                action = max(action, pacl->writeAction);
35860                :            if (access_mode & DixDestroyAccess)
35861                :                action = max(action, pacl->destroyAction);
35862                :            break;
35863                :        } /* end for each pacl */
35864                :    } /* end if propertyName <= SecurityMaxPropertyName */
35865                :
35866                :    if (XaceAllowOperation != action)
35867                :    { /* audit the access violation */
35868                :        int cid = CLIENT_ID(pWin->drawable.id);
35869                :        int reqtype = ((xReq *)client->requestBuffer)->reqType;
35870                :        char *actionstr = (XaceIgnoreOperation == action) ?
35871                :                                                        "ignored" : "error";
35872                :        SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n",
35873                :                client->index, reqtype, pWin->drawable.id,
35874                :                      NameForAtom(propertyName), propertyName, cid, actionstr);
35875                :    }
35876                :    /* return codes increase with strictness */
35877                :    if (action > rec->rval)
35878                :        rec->rval = action;
35879                :} /* SecurityCheckPropertyAccess */
35880                :
35881                :
35882                :/* SecurityResetProc
35883                : *
35884                : * Arguments:
35885                : *      extEntry is the extension information for the security extension.
35886                : *
35887                : * Returns: nothing.
35888                : *
35889                : * Side Effects:
35890                : *      Performs any cleanup needed by Security at server shutdown time.
35891                : */
35892                :
35893                :static void
35894                :SecurityResetProc(
35895                :    ExtensionEntry *extEntry)
35896                :{
35897                :    SecurityFreePropertyAccessList();
35898                :    SecurityFreeSitePolicyStrings();
35899                :} /* SecurityResetProc */
35900                :
35901                :
35902                :int
35903                :XSecurityOptions(argc, argv, i)
35904                :    int argc;
35905                :    char **argv;
35906                :    int i;
35907                :{
35908                :    if (strcmp(argv[i], "-sp") == 0)
35909                :    {
35910                :        if (i < argc)
35911                :            SecurityPolicyFile = argv[++i];
35912                :        return (i + 1);
35913                :    }
35914                :    return (i);
35915                :} /* XSecurityOptions */
35916                :
35917                :
35918                :/* SecurityExtensionSetup
35919                : *
35920                : * Arguments: none.
35921                : *
35922                : * Returns: nothing.
35923                : *
35924                : * Side Effects:
35925                : *      Sets up the Security extension if possible.
35926                : *      This function contains things that need to be done
35927                : *      before any other extension init functions get called.
35928                : */
35929                :
35930                :void
35931                :SecurityExtensionSetup(INITARGS)
35932                :{
35933                :    /* Allocate the client private index */
35934                :    securityClientPrivateIndex = AllocateClientPrivateIndex();
35935                :    if (!AllocateClientPrivate(securityClientPrivateIndex,
35936                :                               sizeof (SecurityClientStateRec)))
35937                :        FatalError("SecurityExtensionSetup: Can't allocate client private.\n");
35938                :
35939                :    /* Allocate the extension private index */
35940                :    securityExtnsnPrivateIndex = AllocateExtensionPrivateIndex();
35941                :    if (!AllocateExtensionPrivate(securityExtnsnPrivateIndex, 0))
35942                :        FatalError("SecurityExtensionSetup: Can't allocate extnsn private.\n");
35943                :
35944                :    /* register callbacks */
35945                :#define XaceRC XaceRegisterCallback
35946                :    XaceRC(XACE_RESOURCE_ACCESS, SecurityCheckResourceIDAccess, NULL);
35947                :    XaceRC(XACE_DEVICE_ACCESS, SecurityCheckDeviceAccess, NULL);
35948                :    XaceRC(XACE_PROPERTY_ACCESS, SecurityCheckPropertyAccess, NULL);
35949                :    XaceRC(XACE_DRAWABLE_ACCESS, SecurityCheckDrawableAccess, NULL);
35950                :    XaceRC(XACE_MAP_ACCESS, SecurityCheckMapAccess, NULL);
35951                :    XaceRC(XACE_BACKGRND_ACCESS, SecurityCheckBackgrndAccess, NULL);
35952                :    XaceRC(XACE_EXT_DISPATCH, SecurityCheckExtAccess, NULL);
35953                :    XaceRC(XACE_EXT_ACCESS, SecurityCheckExtAccess, NULL);
35954                :    XaceRC(XACE_HOSTLIST_ACCESS, SecurityCheckHostlistAccess, NULL);
35955                :    XaceRC(XACE_DECLARE_EXT_SECURE, SecurityDeclareExtSecure, NULL);
35956                :} /* SecurityExtensionSetup */
35957                :
35958                :
35959                :/* SecurityExtensionInit
35960                : *
35961                : * Arguments: none.
35962                : *
35963                : * Returns: nothing.
35964                : *
35965                : * Side Effects:
35966                : *      Enables the Security extension if possible.
35967                : */
35968                :
35969                :void
35970                :SecurityExtensionInit(INITARGS)
35971                :{
35972                :    ExtensionEntry      *extEntry;
35973                :
35974                :    SecurityAuthorizationResType =
35975                :        CreateNewResourceType(SecurityDeleteAuthorization);
35976                :
35977                :    RTEventClient = CreateNewResourceType(
35978                :                                SecurityDeleteAuthorizationEventClient);
35979                :
35980                :    if (!SecurityAuthorizationResType || !RTEventClient)
35981                :        return;
35982                :
35983                :    RTEventClient |= RC_NEVERRETAIN;
35984                :
35985                :    if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL))
35986                :        return;
35987                :
35988                :    extEntry = AddExtension(SECURITY_EXTENSION_NAME,
35989                :                            XSecurityNumberEvents, XSecurityNumberErrors,
35990                :                            ProcSecurityDispatch, SProcSecurityDispatch,
35991                :                            SecurityResetProc, StandardMinorOpcode);
35992                :
35993                :    SecurityErrorBase = extEntry->errorBase;
35994                :    SecurityEventBase = extEntry->eventBase;
35995                :
35996                :    EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
35997                :        (EventSwapPtr)SwapSecurityAuthorizationRevokedEvent;
35998                :
35999                :    SecurityLoadPropertyAccessList();
36000                :
36001                :} /* SecurityExtensionInit */
36002 /* 
36003  * Total samples for file : "/home/cworth/src/xorg/xserver/hw/xfree86/dri/dri.c"
36004  * 
36005  *     41  0.0447
36006  */
36007
36008
36009                :/**************************************************************************
36010                :
36011                :Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
36012                :Copyright 2000 VA Linux Systems, Inc.
36013                :All Rights Reserved.
36014                :
36015                :Permission is hereby granted, free of charge, to any person obtaining a
36016                :copy of this software and associated documentation files (the
36017                :"Software"), to deal in the Software without restriction, including
36018                :without limitation the rights to use, copy, modify, merge, publish,
36019                :distribute, sub license, and/or sell copies of the Software, and to
36020                :permit persons to whom the Software is furnished to do so, subject to
36021                :the following conditions:
36022                :
36023                :The above copyright notice and this permission notice (including the
36024                :next paragraph) shall be included in all copies or substantial portions
36025                :of the Software.
36026                :
36027                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
36028                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36029                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
36030                :IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
36031                :ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
36032                :TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
36033                :SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36034                :
36035                :**************************************************************************/
36036                :
36037                :/*
36038                : * Authors:
36039                : *   Jens Owen <jens@tungstengraphics.com>
36040                : *   Rickard E. (Rik) Faith <faith@valinux.com>
36041                : *
36042                : */
36043                :
36044                :#ifdef HAVE_XORG_CONFIG_H
36045                :#include <xorg-config.h>
36046                :#endif
36047                :
36048                :#include "xf86.h"
36049                :#include <sys/time.h>
36050                :#include <unistd.h>
36051                :#include <string.h>
36052                :#include <stdio.h>
36053                :#include <sys/ioctl.h>
36054                :#include <errno.h>
36055                :
36056                :#define NEED_REPLIES
36057                :#define NEED_EVENTS
36058                :#include <X11/X.h>
36059                :#include <X11/Xproto.h>
36060                :#include "xf86drm.h"
36061                :#include "misc.h"
36062                :#include "dixstruct.h"
36063                :#include "extnsionst.h"
36064                :#include "colormapst.h"
36065                :#include "cursorstr.h"
36066                :#include "scrnintstr.h"
36067                :#include "windowstr.h"
36068                :#include "servermd.h"
36069                :#define _XF86DRI_SERVER_
36070                :#include "xf86dristr.h"
36071                :#include "swaprep.h"
36072                :#include "xf86str.h"
36073                :#include "dri.h"
36074                :#include "sarea.h"
36075                :#include "dristruct.h"
36076                :#include "xf86.h"
36077                :#include "xf86drm.h"
36078                :#include "glxserver.h"
36079                :#include "mi.h"
36080                :#include "mipointer.h"
36081                :#include "xf86_OSproc.h"
36082                :
36083                :#define PCI_BUS_NO_DOMAIN(bus) ((bus) & 0xffu)
36084                :
36085                :#if !defined(PANORAMIX)
36086                :extern Bool noPanoramiXExtension;
36087                :#endif
36088                :
36089                :static int DRIEntPrivIndex = -1;
36090                :static int DRIScreenPrivIndex = -1;
36091                :static int DRIWindowPrivIndex = -1;
36092                :static unsigned long DRIGeneration = 0;
36093                :static unsigned int DRIDrawableValidationStamp = 0;
36094                :
36095                :static RESTYPE DRIDrawablePrivResType;
36096                :static RESTYPE DRIContextPrivResType;
36097                :static void    DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv);
36098                :
36099                :drmServerInfo DRIDRMServerInfo;
36100                :
36101                :                                /* Wrapper just like xf86DrvMsg, but
36102                :                                   without the verbosity level checking.
36103                :                                   This will make it easy to turn off some
36104                :                                   messages later, based on verbosity
36105                :                                   level. */
36106                :
36107                :/*
36108                : * Since we're already referencing things from the XFree86 common layer in
36109                : * this file, we'd might as well just call xf86VDrvMsgVerb, and have
36110                : * consistent message formatting.  The verbosity of these messages can be
36111                : * easily changed here.
36112                : */
36113                :#define DRI_MSG_VERBOSITY 1
36114                :static void
36115                :DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
36116                :{
36117                :    va_list     ap;
36118                :
36119                :    va_start(ap, format);
36120                :    xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap);
36121                :    va_end(ap);
36122                :}
36123                :
36124                :
36125                :static void
36126                :DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv)
36127                :{
36128                :    if (pDRIEntPriv->pLSAREA != NULL) {
36129                :        drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize);
36130                :        pDRIEntPriv->pLSAREA = NULL;
36131                :    }
36132                :    if (pDRIEntPriv->hLSAREA != 0) {
36133                :        drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA);
36134                :    }
36135                :    if (pDRIEntPriv->drmFD >= 0) {
36136                :        drmClose(pDRIEntPriv->drmFD);
36137                :        pDRIEntPriv->drmFD = 0;
36138                :    }
36139                :}
36140                :
36141                :int
36142                :DRIMasterFD(ScrnInfoPtr pScrn)
36143                :{
36144                :    return DRI_ENT_PRIV(pScrn)->drmFD;
36145                :}
36146                :
36147                :void *
36148                :DRIMasterSareaPointer(ScrnInfoPtr pScrn)
36149                :{
36150                :    return DRI_ENT_PRIV(pScrn)->pLSAREA;
36151                :}
36152                :
36153                :drm_handle_t
36154                :DRIMasterSareaHandle(ScrnInfoPtr pScrn)
36155                :{
36156                :    return DRI_ENT_PRIV(pScrn)->hLSAREA;
36157                :}
36158                :
36159                :
36160                :Bool
36161                :DRIOpenDRMMaster(ScrnInfoPtr pScrn,
36162                :                 unsigned long sAreaSize,
36163                :                 const char *busID,
36164                :                 const char *drmDriverName)
36165                :{
36166                :    drmSetVersion saveSv, sv;
36167                :    Bool drmWasAvailable;
36168                :    DRIEntPrivPtr pDRIEntPriv;
36169                :    DRIEntPrivRec tmp;
36170                :    drmVersionPtr drmlibv;
36171                :    int drmlibmajor, drmlibminor;
36172                :    const char *openBusID;
36173                :    int count;
36174                :    int err;
36175                :
36176                :    if (DRIEntPrivIndex == -1)
36177                :        DRIEntPrivIndex = xf86AllocateEntityPrivateIndex();
36178                :
36179                :    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
36180                :
36181                :    if (pDRIEntPriv && pDRIEntPriv->drmFD != -1)
36182                :        return TRUE;
36183                :
36184                :    drmWasAvailable = drmAvailable();
36185                :
36186                :    memset(&tmp, 0, sizeof(tmp));
36187                :
36188                :    /* Check the DRM lib version.
36189                :     * drmGetLibVersion was not supported in version 1.0, so check for
36190                :     * symbol first to avoid possible crash or hang.
36191                :     */
36192                :
36193                :    drmlibmajor = 1;
36194                :    drmlibminor = 0;
36195                :    if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
36196                :        drmlibv = drmGetLibVersion(-1);
36197                :        if (drmlibv != NULL) {
36198                :            drmlibmajor = drmlibv->version_major;
36199                :            drmlibminor = drmlibv->version_minor;
36200                :            drmFreeVersion(drmlibv);
36201                :        }
36202                :    }
36203                :
36204                :    /* Check if the libdrm can handle falling back to loading based on name
36205                :     * if a busid string is passed.
36206                :     */
36207                :    openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL;
36208                :
36209                :    tmp.drmFD = -1;
36210                :    sv.drm_di_major = 1;
36211                :    sv.drm_di_minor = 1;
36212                :    sv.drm_dd_major = -1;
36213                :
36214                :    saveSv = sv;
36215                :    count = 10;
36216                :    while (count--) {
36217                :        tmp.drmFD = drmOpen(drmDriverName, openBusID);
36218                :
36219                :        if (tmp.drmFD < 0) {
36220                :            DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n");
36221                :            goto out_err;
36222                :        }
36223                :
36224                :        err = drmSetInterfaceVersion(tmp.drmFD, &sv);
36225                :
36226                :        if (err != -EPERM)
36227                :            break;
36228                :
36229                :        sv = saveSv;
36230                :        drmClose(tmp.drmFD);
36231                :        tmp.drmFD = -1;
36232                :        usleep(100000);
36233                :    }
36234                :
36235                :    if (tmp.drmFD <= 0) {
36236                :        DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n");
36237                :        goto out_err;
36238                :    }
36239                :
36240                :    if (!drmWasAvailable) {
36241                :        DRIDrvMsg(-1, X_INFO,
36242                :                  "[drm] loaded kernel module for \"%s\" driver.\n",
36243                :                  drmDriverName);
36244                :    }
36245                :
36246                :    if (err != 0) {
36247                :        sv.drm_di_major = 1;
36248                :        sv.drm_di_minor = 0;
36249                :    }
36250                :
36251                :    DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n",
36252                :              sv.drm_di_major, sv.drm_di_minor);
36253                :
36254                :    if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1)
36255                :        err = 0;
36256                :    else
36257                :        err = drmSetBusid(tmp.drmFD, busID);
36258                :
36259                :    if (err) {
36260                :        DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n");
36261                :        goto out_err;
36262                :    }
36263                :
36264                :    /*
36265                :     * Create a lock-containing sarea.
36266                :     */
36267                :
36268                :    if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM,
36269                :                   DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) {
36270                :        DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n");
36271                :        tmp.hLSAREA = 0;
36272                :        goto out_err;
36273                :    }
36274                :
36275                :    if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize,
36276                :                (drmAddressPtr)(&tmp.pLSAREA)) < 0) {
36277                :        DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n");
36278                :        tmp.pLSAREA = NULL;
36279                :        goto out_err;
36280                :    }
36281                :
36282                :    memset(tmp.pLSAREA, 0, sAreaSize);
36283                :
36284                :    /*
36285                :     * Reserved contexts are handled by the first opened screen.
36286                :     */
36287                :
36288                :    tmp.resOwner = NULL;
36289                :
36290                :    if (!pDRIEntPriv)
36291                :        pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1);
36292                :
36293                :    if (!pDRIEntPriv) {
36294                :        DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for "
36295                :                  "DRM device.\n");
36296                :        goto out_err;
36297                :    }
36298                :    *pDRIEntPriv = tmp;
36299                :    xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr =
36300                :        pDRIEntPriv;
36301                :
36302                :    DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n");
36303                :    return TRUE;
36304                :
36305                :  out_err:
36306                :
36307                :    DRIOpenDRMCleanup(&tmp);
36308                :    return FALSE;
36309                :}
36310                :
36311                :
36312                :Bool
36313                :DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
36314                :{
36315                :    DRIScreenPrivPtr    pDRIPriv;
36316                :    drm_context_t *       reserved;
36317                :    int                 reserved_count;
36318                :    int                 i;
36319                :    Bool                xineramaInCore = FALSE;
36320                :    DRIEntPrivPtr       pDRIEntPriv;
36321                :    ScrnInfoPtr         pScrn = xf86Screens[pScreen->myNum];
36322                :
36323                :    /* If the DRI extension is disabled, do not initialize the DRI */
36324                :    if (noXFree86DRIExtension) {
36325                :        DRIDrvMsg(pScreen->myNum, X_WARNING,
36326                :                  "Direct rendering has been disabled.\n");
36327                :        return FALSE;
36328                :    }
36329                :
36330                :    /*
36331                :     * If Xinerama is on, don't allow DRI to initialise.  It won't be usable
36332                :     * anyway.
36333                :     */
36334                :    if (xf86LoaderCheckSymbol("noPanoramiXExtension"))
36335                :        xineramaInCore = TRUE;
36336                :
36337                :    if (xineramaInCore) {
36338                :        if (!noPanoramiXExtension) {
36339                :            DRIDrvMsg(pScreen->myNum, X_WARNING,
36340                :                "Direct rendering is not supported when Xinerama is enabled\n");
36341                :            return FALSE;
36342                :        }
36343                :    }
36344                :
36345                :    if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize,
36346                :                          pDRIInfo->busIdString,
36347                :                          pDRIInfo->drmDriverName))
36348                :        return FALSE;
36349                :
36350                :    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
36351                :
36352                :    if (DRIGeneration != serverGeneration) {
36353                :        if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0)
36354                :            return FALSE;
36355                :        DRIGeneration = serverGeneration;
36356                :    }
36357                :
36358                :    pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec));
36359                :    if (!pDRIPriv) {
36360                :        pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
36361                :        DRIScreenPrivIndex = -1;
36362                :        return FALSE;
36363                :    }
36364                :
36365                :    pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv;
36366                :    pDRIPriv->drmFD = pDRIEntPriv->drmFD;
36367                :    pDRIPriv->directRenderingSupport = TRUE;
36368                :    pDRIPriv->pDriverInfo = pDRIInfo;
36369                :    pDRIPriv->nrWindows = 0;
36370                :    pDRIPriv->nrWindowsVisible = 0;
36371                :    pDRIPriv->fullscreen = NULL;
36372                :
36373                :    pDRIPriv->createDummyCtx     = pDRIInfo->createDummyCtx;
36374                :    pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv;
36375                :
36376                :    pDRIPriv->grabbedDRILock = FALSE;
36377                :    pDRIPriv->drmSIGIOHandlerInstalled = FALSE;
36378                :    *pDRMFD = pDRIPriv->drmFD;
36379                :
36380                :    if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) {
36381                :
36382                :        if (drmAddMap( pDRIPriv->drmFD,
36383                :                       0,
36384                :                       pDRIPriv->pDriverInfo->SAREASize,
36385                :                       DRM_SHM,
36386                :                       0,
36387                :                       &pDRIPriv->hSAREA) < 0)
36388                :        {
36389                :            pDRIPriv->directRenderingSupport = FALSE;
36390                :            pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
36391                :            drmClose(pDRIPriv->drmFD);
36392                :            DRIDrvMsg(pScreen->myNum, X_INFO,
36393                :                      "[drm] drmAddMap failed\n");
36394                :            return FALSE;
36395                :        }
36396                :        DRIDrvMsg(pScreen->myNum, X_INFO,
36397                :                  "[drm] added %d byte SAREA at %p\n",
36398                :                  pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA);
36399                :
36400                :        /* Backwards compat. */
36401                :        if (drmMap( pDRIPriv->drmFD,
36402                :                    pDRIPriv->hSAREA,
36403                :                    pDRIPriv->pDriverInfo->SAREASize,
36404                :                    (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0)
36405                :        {
36406                :            pDRIPriv->directRenderingSupport = FALSE;
36407                :            pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
36408                :            drmClose(pDRIPriv->drmFD);
36409                :            DRIDrvMsg(pScreen->myNum, X_INFO,
36410                :                      "[drm] drmMap failed\n");
36411                :            return FALSE;
36412                :        }
36413                :        DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n",
36414                :                  pDRIPriv->hSAREA, pDRIPriv->pSAREA);
36415                :        memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize);
36416                :    } else {
36417                :        DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock "
36418                :                  "SAREA also for drawables.\n");
36419                :        pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA;
36420                :        pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA;
36421                :        pDRIEntPriv->sAreaGrabbed = TRUE;
36422                :    }
36423                :
36424                :    pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA;
36425                :    pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA;
36426                :
36427                :    if (drmAddMap( pDRIPriv->drmFD,
36428                :                   (drm_handle_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress,
36429                :                   pDRIPriv->pDriverInfo->frameBufferSize,
36430                :                   DRM_FRAME_BUFFER,
36431                :                   0,
36432                :                   &pDRIPriv->hFrameBuffer) < 0)
36433                :    {
36434                :        pDRIPriv->directRenderingSupport = FALSE;
36435                :        pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
36436                :        drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize);
36437                :        drmClose(pDRIPriv->drmFD);
36438                :        DRIDrvMsg(pScreen->myNum, X_INFO,
36439                :                  "[drm] drmAddMap failed\n");
36440                :        return FALSE;
36441                :    }
36442                :    DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n",
36443                :              pDRIPriv->hFrameBuffer);
36444                :
36445                :    if (pDRIEntPriv->resOwner == NULL) {
36446                :        pDRIEntPriv->resOwner = pScreen;
36447                :
36448                :        /* Add tags for reserved contexts */
36449                :        if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
36450                :                                                  &reserved_count))) {
36451                :            int  i;
36452                :            void *tag;
36453                :
36454                :            for (i = 0; i < reserved_count; i++) {
36455                :                tag = DRICreateContextPrivFromHandle(pScreen,
36456                :                                                     reserved[i],
36457                :                                                     DRI_CONTEXT_RESERVED);
36458                :                drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag);
36459                :            }
36460                :            drmFreeReservedContextList(reserved);
36461                :            DRIDrvMsg(pScreen->myNum, X_INFO,
36462                :                      "[drm] added %d reserved context%s for kernel\n",
36463                :                      reserved_count, reserved_count > 1 ? "s" : "");
36464                :        }
36465                :    }
36466                :
36467                :    /* validate max drawable table entry set by driver */
36468                :    if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) ||
36469                :        (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) {
36470                :            DRIDrvMsg(pScreen->myNum, X_ERROR,
36471                :                      "Invalid max drawable table size set by driver: %d\n",
36472                :                      pDRIPriv->pDriverInfo->maxDrawableTableEntry);
36473                :    }
36474                :
36475                :    /* Initialize drawable tables (screen private and SAREA) */
36476                :    for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) {
36477                :        pDRIPriv->DRIDrawables[i] = NULL;
36478                :        pDRIPriv->pSAREA->drawableTable[i].stamp = 0;
36479                :        pDRIPriv->pSAREA->drawableTable[i].flags = 0;
36480                :    }
36481                :
36482                :    pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount;
36483                :    pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext;
36484                :
36485                :    if (!pDRIEntPriv->keepFDOpen)
36486                :        pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen;
36487                :
36488                :    pDRIEntPriv->refCount++;
36489                :
36490                :    return TRUE;
36491                :}
36492                :
36493                :Bool
36494                :DRIFinishScreenInit(ScreenPtr pScreen)
36495                :{
36496                :    DRIScreenPrivPtr  pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36497                :    DRIInfoPtr        pDRIInfo = pDRIPriv->pDriverInfo;
36498                :    DRIContextFlags   flags    = 0;
36499                :    DRIContextPrivPtr pDRIContextPriv;
36500                :
36501                :                                /* Set up flags for DRICreateContextPriv */
36502                :    switch (pDRIInfo->driverSwapMethod) {
36503                :    case DRI_KERNEL_SWAP:    flags = DRI_CONTEXT_2DONLY;    break;
36504                :    case DRI_HIDE_X_CONTEXT: flags = DRI_CONTEXT_PRESERVED; break;
36505                :    }
36506                :
36507                :    if (!(pDRIContextPriv = DRICreateContextPriv(pScreen,
36508                :                                                 &pDRIPriv->myContext,
36509                :                                                 flags))) {
36510                :        DRIDrvMsg(pScreen->myNum, X_ERROR,
36511                :                  "failed to create server context\n");
36512                :        return FALSE;
36513                :    }
36514                :    pDRIPriv->myContextPriv = pDRIContextPriv;
36515                :
36516                :    DRIDrvMsg(pScreen->myNum, X_INFO,
36517                :              "X context handle = %p\n", pDRIPriv->myContext);
36518                :
36519                :    /* Now that we have created the X server's context, we can grab the
36520                :     * hardware lock for the X server.
36521                :     */
36522                :    DRILock(pScreen, 0);
36523                :    pDRIPriv->grabbedDRILock = TRUE;
36524                :
36525                :    /* pointers so that we can prevent memory leaks later */
36526                :    pDRIPriv->hiddenContextStore    = NULL;
36527                :    pDRIPriv->partial3DContextStore = NULL;
36528                :
36529                :    switch(pDRIInfo->driverSwapMethod) {
36530                :    case DRI_HIDE_X_CONTEXT:
36531                :        /* Server will handle 3D swaps, and hide 2D swaps from kernel.
36532                :         * Register server context as a preserved context.
36533                :         */
36534                :
36535                :        /* allocate memory for hidden context store */
36536                :        pDRIPriv->hiddenContextStore
36537                :            = (void *)xcalloc(1, pDRIInfo->contextSize);
36538                :        if (!pDRIPriv->hiddenContextStore) {
36539                :            DRIDrvMsg(pScreen->myNum, X_ERROR,
36540                :                      "failed to allocate hidden context\n");
36541                :            DRIDestroyContextPriv(pDRIContextPriv);
36542                :            return FALSE;
36543                :        }
36544                :
36545                :        /* allocate memory for partial 3D context store */
36546                :        pDRIPriv->partial3DContextStore
36547                :            = (void *)xcalloc(1, pDRIInfo->contextSize);
36548                :        if (!pDRIPriv->partial3DContextStore) {
36549                :            DRIDrvMsg(pScreen->myNum, X_ERROR,
36550                :                      "[DRI] failed to allocate partial 3D context\n");
36551                :            xfree(pDRIPriv->hiddenContextStore);
36552                :            DRIDestroyContextPriv(pDRIContextPriv);
36553                :            return FALSE;
36554                :        }
36555                :
36556                :        /* save initial context store */
36557                :        if (pDRIInfo->SwapContext) {
36558                :            (*pDRIInfo->SwapContext)(
36559                :                pScreen,
36560                :                DRI_NO_SYNC,
36561                :                DRI_2D_CONTEXT,
36562                :                pDRIPriv->hiddenContextStore,
36563                :                DRI_NO_CONTEXT,
36564                :                NULL);
36565                :        }
36566                :        /* fall through */
36567                :
36568                :    case DRI_SERVER_SWAP:
36569                :        /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT
36570                :         * setup signal handler for receiving swap requests from kernel
36571                :         */
36572                :        if (!(pDRIPriv->drmSIGIOHandlerInstalled =
36573                :              drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) {
36574                :            DRIDrvMsg(pScreen->myNum, X_ERROR,
36575                :                      "[drm] failed to setup DRM signal handler\n");
36576                :            if (pDRIPriv->hiddenContextStore)
36577                :                xfree(pDRIPriv->hiddenContextStore);
36578                :            if (pDRIPriv->partial3DContextStore)
36579                :                xfree(pDRIPriv->partial3DContextStore);
36580                :            DRIDestroyContextPriv(pDRIContextPriv);
36581                :            return FALSE;
36582                :        } else {
36583                :            DRIDrvMsg(pScreen->myNum, X_INFO,
36584                :                      "[drm] installed DRM signal handler\n");
36585                :        }
36586                :
36587                :    default:
36588                :        break;
36589                :    }
36590                :
36591                :    /* Wrap DRI support */
36592                :    if (pDRIInfo->wrap.ValidateTree) {
36593                :        pDRIPriv->wrap.ValidateTree     = pScreen->ValidateTree;
36594                :        pScreen->ValidateTree           = pDRIInfo->wrap.ValidateTree;
36595                :    }
36596                :    if (pDRIInfo->wrap.PostValidateTree) {
36597                :        pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
36598                :        pScreen->PostValidateTree       = pDRIInfo->wrap.PostValidateTree;
36599                :    }
36600                :    if (pDRIInfo->wrap.WindowExposures) {
36601                :        pDRIPriv->wrap.WindowExposures  = pScreen->WindowExposures;
36602                :        pScreen->WindowExposures        = pDRIInfo->wrap.WindowExposures;
36603                :    }
36604                :    if (pDRIInfo->wrap.CopyWindow) {
36605                :        pDRIPriv->wrap.CopyWindow       = pScreen->CopyWindow;
36606                :        pScreen->CopyWindow             = pDRIInfo->wrap.CopyWindow;
36607                :    }
36608                :    if (pDRIInfo->wrap.ClipNotify) {
36609                :        pDRIPriv->wrap.ClipNotify       = pScreen->ClipNotify;
36610                :        pScreen->ClipNotify             = pDRIInfo->wrap.ClipNotify;
36611                :    }
36612                :    if (pDRIInfo->wrap.AdjustFrame) {
36613                :        ScrnInfoPtr pScrn               = xf86Screens[pScreen->myNum];
36614                :        pDRIPriv->wrap.AdjustFrame      = pScrn->AdjustFrame;
36615                :        pScrn->AdjustFrame              = pDRIInfo->wrap.AdjustFrame;
36616                :    }
36617                :    pDRIPriv->wrapped = TRUE;
36618                :
36619                :    DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n");
36620                :
36621                :    return TRUE;
36622                :}
36623                :
36624                :void
36625                :DRICloseScreen(ScreenPtr pScreen)
36626                :{
36627                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36628                :    DRIInfoPtr       pDRIInfo;
36629                :    drm_context_t *    reserved;
36630                :    int              reserved_count;
36631                :    ScrnInfoPtr      pScrn = xf86Screens[pScreen->myNum];
36632                :    DRIEntPrivPtr    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
36633                :    Bool closeMaster;
36634                :
36635                :    if (pDRIPriv) {
36636                :
36637                :        pDRIInfo = pDRIPriv->pDriverInfo;
36638                :
36639                :        if (pDRIPriv->wrapped) {
36640                :            /* Unwrap DRI Functions */
36641                :            if (pDRIInfo->wrap.ValidateTree) {
36642                :                pScreen->ValidateTree           = pDRIPriv->wrap.ValidateTree;
36643                :                pDRIPriv->wrap.ValidateTree     = NULL;
36644                :            }
36645                :            if (pDRIInfo->wrap.PostValidateTree) {
36646                :                pScreen->PostValidateTree       = pDRIPriv->wrap.PostValidateTree;
36647                :                pDRIPriv->wrap.PostValidateTree = NULL;
36648                :            }
36649                :            if (pDRIInfo->wrap.WindowExposures) {
36650                :                pScreen->WindowExposures        = pDRIPriv->wrap.WindowExposures;
36651                :                pDRIPriv->wrap.WindowExposures  = NULL;
36652                :            }
36653                :            if (pDRIInfo->wrap.CopyWindow) {
36654                :                pScreen->CopyWindow             = pDRIPriv->wrap.CopyWindow;
36655                :                pDRIPriv->wrap.CopyWindow       = NULL;
36656                :            }
36657                :            if (pDRIInfo->wrap.ClipNotify) {
36658                :                pScreen->ClipNotify             = pDRIPriv->wrap.ClipNotify;
36659                :                pDRIPriv->wrap.ClipNotify       = NULL;
36660                :            }
36661                :            if (pDRIInfo->wrap.AdjustFrame) {
36662                :                ScrnInfoPtr pScrn               = xf86Screens[pScreen->myNum];
36663                :                pScrn->AdjustFrame              = pDRIPriv->wrap.AdjustFrame;
36664                :                pDRIPriv->wrap.AdjustFrame      = NULL;
36665                :            }
36666                :            pDRIPriv->wrapped = FALSE;
36667                :        }
36668                :
36669                :        if (pDRIPriv->drmSIGIOHandlerInstalled) {
36670                :            if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) {
36671                :                DRIDrvMsg(pScreen->myNum, X_ERROR,
36672                :                          "[drm] failed to remove DRM signal handler\n");
36673                :            }
36674                :        }
36675                :
36676                :        if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) {
36677                :            DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv);
36678                :        }
36679                :
36680                :        if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) {
36681                :            DRIDrvMsg(pScreen->myNum, X_ERROR,
36682                :                      "failed to destroy server context\n");
36683                :        }
36684                :
36685                :                                /* Remove tags for reserved contexts */
36686                :        if (pDRIEntPriv->resOwner == pScreen) {
36687                :            pDRIEntPriv->resOwner = NULL;
36688                :
36689                :            if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
36690                :                                                  &reserved_count))) {
36691                :                int  i;
36692                :
36693                :                for (i = 0; i < reserved_count; i++) {
36694                :                    DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD,
36695                :                                                           reserved[i]));
36696                :                }
36697                :                drmFreeReservedContextList(reserved);
36698                :                DRIDrvMsg(pScreen->myNum, X_INFO,
36699                :                          "[drm] removed %d reserved context%s for kernel\n",
36700                :                          reserved_count, reserved_count > 1 ? "s" : "");
36701                :            }
36702                :        }
36703                :
36704                :        /* Make sure signals get unblocked etc. */
36705                :        drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext);
36706                :        pDRIPriv->pLockRefCount = NULL;
36707                :        closeMaster = (--pDRIEntPriv->refCount == 0) &&
36708                :            !pDRIEntPriv->keepFDOpen;
36709                :        if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) {
36710                :            DRIDrvMsg(pScreen->myNum, X_INFO,
36711                :                      "[drm] unmapping %d bytes of SAREA %p at %p\n",
36712                :                      pDRIInfo->SAREASize,
36713                :                      pDRIPriv->hSAREA,
36714                :                      pDRIPriv->pSAREA);
36715                :            if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) {
36716                :                DRIDrvMsg(pScreen->myNum, X_ERROR,
36717                :                          "[drm] unable to unmap %d bytes"
36718                :                          " of SAREA %p at %p\n",
36719                :                          pDRIInfo->SAREASize,
36720                :                          pDRIPriv->hSAREA,
36721                :                          pDRIPriv->pSAREA);
36722                :            }
36723                :        } else {
36724                :            pDRIEntPriv->sAreaGrabbed = FALSE;
36725                :        }
36726                :
36727                :        if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) {
36728                :            drmClose(pDRIPriv->drmFD);
36729                :            if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) {
36730                :                DRIDrvMsg(pScreen->myNum, X_INFO,
36731                :                          "[drm] Closed DRM master.\n");
36732                :                pDRIEntPriv->drmFD = -1;
36733                :            }
36734                :        }
36735                :
36736                :        xfree(pDRIPriv);
36737                :        pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
36738                :        DRIScreenPrivIndex = -1;
36739                :    }
36740                :}
36741                :
36742                :#define DRM_MSG_VERBOSITY 3
36743                :
36744                :static int dri_drm_debug_print(const char *format, va_list ap)
36745                :{
36746                :  xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
36747                :  return 0;
36748                :}
36749                :
36750                :static void dri_drm_get_perms(gid_t *group, mode_t *mode)
36751                :{
36752                :  *group = xf86ConfigDRI.group;
36753                :  *mode = xf86ConfigDRI.mode;
36754                :}
36755                :
36756                :drmServerInfo DRIDRMServerInfo =  {
36757                :  dri_drm_debug_print,
36758                :  xf86LoadKernelModule,
36759                :  dri_drm_get_perms,
36760                :};
36761                :
36762                :Bool
36763                :DRIExtensionInit(void)
36764                :{
36765                :    int                 i;
36766                :    ScreenPtr           pScreen;
36767                :
36768                :    if (DRIScreenPrivIndex < 0 || DRIGeneration != serverGeneration) {
36769                :        return FALSE;
36770                :    }
36771                :
36772                :    /* Allocate a window private index with a zero sized private area for
36773                :     * each window, then should a window become a DRI window, we'll hang
36774                :     * a DRIWindowPrivateRec off of this private index.
36775                :     */
36776                :    if ((DRIWindowPrivIndex = AllocateWindowPrivateIndex()) < 0)
36777                :        return FALSE;
36778                :
36779                :    DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete);
36780                :    DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete);
36781                :
36782                :    for (i = 0; i < screenInfo.numScreens; i++)
36783                :    {
36784                :        pScreen = screenInfo.screens[i];
36785                :        if (!AllocateWindowPrivate(pScreen, DRIWindowPrivIndex, 0))
36786                :            return FALSE;
36787                :    }
36788                :
36789                :    RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL);
36790                :
36791                :    return TRUE;
36792                :}
36793                :
36794                :void
36795                :DRIReset(void)
36796                :{
36797                :    /*
36798                :     * This stub routine is called when the X Server recycles, resources
36799                :     * allocated by DRIExtensionInit need to be managed here.
36800                :     *
36801                :     * Currently this routine is a stub because all the interesting resources
36802                :     * are managed via the screen init process.
36803                :     */
36804                :}
36805                :
36806                :Bool
36807                :DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
36808                :{
36809                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36810                :
36811                :    if (pDRIPriv)
36812                :        *isCapable = pDRIPriv->directRenderingSupport;
36813                :    else
36814                :        *isCapable = FALSE;
36815                :
36816                :    return TRUE;
36817                :}
36818                :
36819                :Bool
36820                :DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString)
36821                :{
36822                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36823                :
36824                :    *hSAREA           = pDRIPriv->hSAREA;
36825                :    *busIdString      = pDRIPriv->pDriverInfo->busIdString;
36826                :
36827                :    return TRUE;
36828                :}
36829                :
36830                :Bool
36831                :DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic)
36832                :{
36833                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36834                :
36835                :    if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
36836                :    return TRUE;
36837                :}
36838                :
36839                :Bool
36840                :DRICloseConnection(ScreenPtr pScreen)
36841                :{
36842                :    return TRUE;
36843                :}
36844                :
36845                :Bool
36846                :DRIGetClientDriverName(ScreenPtr pScreen,
36847                :                       int *ddxDriverMajorVersion,
36848                :                       int *ddxDriverMinorVersion,
36849                :                       int *ddxDriverPatchVersion,
36850                :                       char **clientDriverName)
36851                :{
36852                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36853                :
36854                :    *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion;
36855                :    *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion;
36856                :    *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion;
36857                :    *clientDriverName      = pDRIPriv->pDriverInfo->clientDriverName;
36858                :
36859                :    return TRUE;
36860                :}
36861                :
36862                :/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper
36863                :   functions that layer on drmCreateContext and drmAddContextTag.
36864                :
36865                :   DRICreateContextPriv always creates a kernel drm_context_t and then calls
36866                :   DRICreateContextPrivFromHandle to create a DRIContextPriv structure for
36867                :   DRI tracking.  For the SIGIO handler, the drm_context_t is associated with
36868                :   DRIContextPrivPtr.  Any special flags are stored in the DRIContextPriv
36869                :   area and are passed to the kernel (if necessary).
36870                :
36871                :   DRICreateContextPriv returns a pointer to newly allocated
36872                :   DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */
36873                :
36874                :DRIContextPrivPtr
36875                :DRICreateContextPriv(ScreenPtr pScreen,
36876                :                     drm_context_t * pHWContext,
36877                :                     DRIContextFlags flags)
36878                :{
36879                :    DRIScreenPrivPtr  pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36880                :
36881                :    if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) {
36882                :        return NULL;
36883                :    }
36884                :
36885                :    return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags);
36886                :}
36887                :
36888                :DRIContextPrivPtr
36889                :DRICreateContextPrivFromHandle(ScreenPtr pScreen,
36890                :                               drm_context_t hHWContext,
36891                :                               DRIContextFlags flags)
36892                :{
36893                :    DRIScreenPrivPtr  pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36894                :    DRIContextPrivPtr pDRIContextPriv;
36895                :    int               contextPrivSize;
36896                :
36897                :    contextPrivSize = sizeof(DRIContextPrivRec) +
36898                :                            pDRIPriv->pDriverInfo->contextSize;
36899                :    if (!(pDRIContextPriv = xcalloc(1, contextPrivSize))) {
36900                :        return NULL;
36901                :    }
36902                :    pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1);
36903                :
36904                :    drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv);
36905                :
36906                :    pDRIContextPriv->hwContext = hHWContext;
36907                :    pDRIContextPriv->pScreen   = pScreen;
36908                :    pDRIContextPriv->flags     = flags;
36909                :    pDRIContextPriv->valid3D   = FALSE;
36910                :
36911                :    if (flags & DRI_CONTEXT_2DONLY) {
36912                :        if (drmSetContextFlags(pDRIPriv->drmFD,
36913                :                               hHWContext,
36914                :                               DRM_CONTEXT_2DONLY)) {
36915                :            DRIDrvMsg(pScreen->myNum, X_ERROR,
36916                :                      "[drm] failed to set 2D context flag\n");
36917                :            DRIDestroyContextPriv(pDRIContextPriv);
36918                :            return NULL;
36919                :        }
36920                :    }
36921                :    if (flags & DRI_CONTEXT_PRESERVED) {
36922                :        if (drmSetContextFlags(pDRIPriv->drmFD,
36923                :                               hHWContext,
36924                :                               DRM_CONTEXT_PRESERVED)) {
36925                :            DRIDrvMsg(pScreen->myNum, X_ERROR,
36926                :                      "[drm] failed to set preserved flag\n");
36927                :            DRIDestroyContextPriv(pDRIContextPriv);
36928                :            return NULL;
36929                :        }
36930                :    }
36931                :    return pDRIContextPriv;
36932                :}
36933                :
36934                :Bool
36935                :DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv)
36936                :{
36937                :    DRIScreenPrivPtr pDRIPriv;
36938                :
36939                :    if (!pDRIContextPriv) return TRUE;
36940                :
36941                :    pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen);
36942                :
36943                :    if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) {
36944                :                                /* Don't delete reserved contexts from
36945                :                                   kernel area -- the kernel manages its
36946                :                                   reserved contexts itself. */
36947                :        if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext))
36948                :            return FALSE;
36949                :    }
36950                :
36951                :                                /* Remove the tag last to prevent a race
36952                :                                   condition where the context has pending
36953                :                                   buffers.  The context can't be re-used
36954                :                                   while in this thread, but buffers can be
36955                :                                   dispatched asynchronously. */
36956                :    drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext);
36957                :    xfree(pDRIContextPriv);
36958                :    return TRUE;
36959                :}
36960                :
36961                :static Bool
36962                :DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv)
36963                :{
36964                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
36965                :    __GLXscreen *pGLXScreen = __glXgetActiveScreen(pScreen->myNum);
36966                :    __GLcontextModes *modes = pGLXScreen->modes;
36967                :    void **pVisualConfigPriv = pGLXScreen->pVisualPriv;
36968                :    DRIContextPrivPtr pDRIContextPriv;
36969                :    void *contextStore;
36970                :    VisualPtr visual;
36971                :    int visNum;
36972                :
36973                :    visual = pScreen->visuals;
36974                :
36975                :    /* Find the X visual that corresponds the the first GLX visual */
36976                :    for (visNum = 0;
36977                :         visNum < pScreen->numVisuals;
36978                :         visNum++, visual++) {
36979                :        if (modes->visualID == visual->vid)
36980                :            break;
36981                :    }
36982                :    if (visNum == pScreen->numVisuals) return FALSE;
36983                :
36984                :    if (!(pDRIContextPriv =
36985                :          DRICreateContextPriv(pScreen,
36986                :                               &pDRIPriv->pSAREA->dummy_context, 0))) {
36987                :        return FALSE;
36988                :    }
36989                :
36990                :    contextStore = DRIGetContextStore(pDRIContextPriv);
36991                :    if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) {
36992                :        if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, visual,
36993                :                                                  pDRIPriv->pSAREA->dummy_context,
36994                :                                                  *pVisualConfigPriv,
36995                :                                                  (DRIContextType)(long)contextStore)) {
36996                :            DRIDestroyContextPriv(pDRIContextPriv);
36997                :            return FALSE;
36998                :        }
36999                :    }
37000                :
37001                :    pDRIPriv->dummyCtxPriv = pDRIContextPriv;
37002                :    return TRUE;
37003                :}
37004                :
37005                :static void
37006                :DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv)
37007                :{
37008                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37009                :    DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv;
37010                :    void *contextStore;
37011                :
37012                :    if (!pDRIContextPriv) return;
37013                :    if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) {
37014                :        contextStore = DRIGetContextStore(pDRIContextPriv);
37015                :        pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen,
37016                :                                              pDRIContextPriv->hwContext,
37017                :                                              (DRIContextType)(long)contextStore);
37018                :    }
37019                :
37020                :    DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv);
37021                :    pDRIPriv->dummyCtxPriv = NULL;
37022                :}
37023                :
37024                :Bool
37025                :DRICreateContext(ScreenPtr pScreen, VisualPtr visual,
37026                :                 XID context, drm_context_t * pHWContext)
37027                :{
37028                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37029                :    __GLXscreen *pGLXScreen = __glXgetActiveScreen(pScreen->myNum);
37030                :    __GLcontextModes *modes = pGLXScreen->modes;
37031                :    void **pVisualConfigPriv = pGLXScreen->pVisualPriv;
37032                :    DRIContextPrivPtr pDRIContextPriv;
37033                :    void *contextStore;
37034                :
37035                :    if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) {
37036                :        if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) {
37037                :            DRIDrvMsg(pScreen->myNum, X_INFO,
37038                :                      "[drm] Could not create dummy context\n");
37039                :            return FALSE;
37040                :        }
37041                :    }
37042                :
37043                :    /* Find the GLX visual associated with the one requested */
37044                :    for (modes = pGLXScreen->modes; modes != NULL; modes = modes->next) {
37045                :        if (modes->visualID == visual->vid)
37046                :            break;
37047                :        pVisualConfigPriv++;
37048                :    }
37049                :
37050                :    if (modes == NULL) {
37051                :        /* No matching GLX visual found */
37052                :        return FALSE;
37053                :    }
37054                :
37055                :    if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) {
37056                :        return FALSE;
37057                :    }
37058                :
37059                :    contextStore = DRIGetContextStore(pDRIContextPriv);
37060                :    if (pDRIPriv->pDriverInfo->CreateContext) {
37061                :        if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, visual,
37062                :                *pHWContext, *pVisualConfigPriv,
37063                :                (DRIContextType)(long)contextStore))) {
37064                :            DRIDestroyContextPriv(pDRIContextPriv);
37065                :            return FALSE;
37066                :        }
37067                :    }
37068                :
37069                :    /* track this in case the client dies before cleanup */
37070                :    AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv);
37071                :
37072                :    return TRUE;
37073                :}
37074                :
37075                :Bool
37076                :DRIDestroyContext(ScreenPtr pScreen, XID context)
37077                :{
37078                :    FreeResourceByType(context, DRIContextPrivResType, FALSE);
37079                :
37080                :    return TRUE;
37081                :}
37082                :
37083                :/* DRIContextPrivDelete is called by the resource manager. */
37084                :Bool
37085                :DRIContextPrivDelete(pointer pResource, XID id)
37086                :{
37087                :    DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource;
37088                :    DRIScreenPrivPtr pDRIPriv;
37089                :    void *contextStore;
37090                :
37091                :    pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen);
37092                :    if (pDRIPriv->pDriverInfo->DestroyContext) {
37093                :      contextStore = DRIGetContextStore(pDRIContextPriv);
37094                :      pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen,
37095                :                                            pDRIContextPriv->hwContext,
37096                :                                            (DRIContextType)(long)contextStore);
37097                :    }
37098                :    return DRIDestroyContextPriv(pDRIContextPriv);
37099                :}
37100                :
37101                :
37102                :/* This walks the drawable timestamp array and invalidates all of them
37103                : * in the case of transition from private to shared backbuffers.  It's
37104                : * not necessary for correctness, because DRIClipNotify gets called in
37105                : * time to prevent any conflict, but the transition from
37106                : * shared->private is sometimes missed if we don't do this.
37107                : */
37108                :static void
37109                :DRIClipNotifyAllDrawables(ScreenPtr pScreen)
37110                :{
37111                :   int i;
37112                :   DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37113                :
37114                :   for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) {
37115                :      pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++;
37116                :   }
37117                :}
37118                :
37119                :
37120                :static void
37121                :DRITransitionToSharedBuffers(ScreenPtr pScreen)
37122                :{
37123                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37124                :    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
37125                :
37126                :    DRIClipNotifyAllDrawables( pScreen );
37127                :
37128                :    if (pDRIInfo->TransitionSingleToMulti3D)
37129                :        pDRIInfo->TransitionSingleToMulti3D( pScreen );
37130                :}
37131                :
37132                :
37133                :static void
37134                :DRITransitionToPrivateBuffers(ScreenPtr pScreen)
37135                :{
37136                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37137                :    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
37138                :
37139                :    DRIClipNotifyAllDrawables( pScreen );
37140                :
37141                :    if (pDRIInfo->TransitionMultiToSingle3D)
37142                :        pDRIInfo->TransitionMultiToSingle3D( pScreen );
37143                :}
37144                :
37145                :
37146                :static void
37147                :DRITransitionTo3d(ScreenPtr pScreen)
37148                :{
37149                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37150                :    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
37151                :
37152                :    DRIClipNotifyAllDrawables( pScreen );
37153                :
37154                :    if (pDRIInfo->TransitionTo3d)
37155                :        pDRIInfo->TransitionTo3d( pScreen );
37156                :}
37157                :
37158                :static void
37159                :DRITransitionTo2d(ScreenPtr pScreen)
37160                :{
37161                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37162                :    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
37163                :
37164                :    DRIClipNotifyAllDrawables( pScreen );
37165                :
37166                :    if (pDRIInfo->TransitionTo2d)
37167                :        pDRIInfo->TransitionTo2d( pScreen );
37168                :}
37169                :
37170                :
37171                :static int
37172                :DRIDCNTreeTraversal(WindowPtr pWin, pointer data)
37173                :{
37174                :    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
37175                :
37176                :    if (pDRIDrawablePriv) {
37177                :        ScreenPtr pScreen = pWin->drawable.pScreen;
37178                :        DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37179                :
37180                :        if (REGION_NUM_RECTS(&pWin->clipList) > 0) {
37181                :            WindowPtr *pDRIWindows = (WindowPtr*)data;
37182                :            int i = 0;
37183                :
37184                :            while (pDRIWindows[i])
37185                :                i++;
37186                :
37187                :            pDRIWindows[i] = pWin;
37188                :
37189                :            pDRIPriv->nrWalked++;
37190                :        }
37191                :
37192                :        if (pDRIPriv->nrWindows == pDRIPriv->nrWalked)
37193                :            return WT_STOPWALKING;
37194                :    }
37195                :
37196                :    return WT_WALKCHILDREN;
37197                :}
37198                :
37199                :static void
37200                :DRIDriverClipNotify(ScreenPtr pScreen)
37201                :{
37202                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37203                :
37204                :    if (pDRIPriv->pDriverInfo->ClipNotify) {
37205                :        WindowPtr *pDRIWindows = xcalloc(sizeof(WindowPtr), pDRIPriv->nrWindows);
37206                :        DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
37207                :
37208                :        if (pDRIPriv->nrWindows > 0) {
37209                :            pDRIPriv->nrWalked = 0;
37210                :            TraverseTree(WindowTable[pScreen->myNum], DRIDCNTreeTraversal,
37211                :                         (pointer)pDRIWindows);
37212                :        }
37213                :
37214                :        pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows);
37215                :
37216                :        xfree(pDRIWindows);
37217                :    }
37218                :}
37219                :
37220                :static void
37221                :DRIIncreaseNumberVisible(ScreenPtr pScreen)
37222                :{
37223                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37224                :
37225                :    switch (++pDRIPriv->nrWindowsVisible) {
37226                :    case 1:
37227                :        DRITransitionTo3d( pScreen );
37228                :        break;
37229                :    case 2:
37230                :        DRITransitionToSharedBuffers( pScreen );
37231                :        break;
37232                :    default:
37233                :        break;
37234                :    }
37235                :
37236                :    DRIDriverClipNotify(pScreen);
37237                :}
37238                :
37239                :static void
37240                :DRIDecreaseNumberVisible(ScreenPtr pScreen)
37241                :{
37242                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37243                :
37244                :    switch (--pDRIPriv->nrWindowsVisible) {
37245                :    case 0:
37246                :        DRITransitionTo2d( pScreen );
37247                :        break;
37248                :    case 1:
37249                :        DRITransitionToPrivateBuffers( pScreen );
37250                :        break;
37251                :    default:
37252                :        break;
37253                :    }
37254                :
37255                :    DRIDriverClipNotify(pScreen);
37256                :}
37257                :
37258                :Bool
37259                :DRICreateDrawable(ScreenPtr pScreen, Drawable id,
37260                :                  DrawablePtr pDrawable, drm_drawable_t * hHWDrawable)
37261                :{
37262                :    DRIScreenPrivPtr    pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37263                :    DRIDrawablePrivPtr  pDRIDrawablePriv;
37264                :    WindowPtr           pWin;
37265                :
37266                :    if (pDrawable->type == DRAWABLE_WINDOW) {
37267                :        pWin = (WindowPtr)pDrawable;
37268                :        if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
37269                :            pDRIDrawablePriv->refCount++;
37270                :
37271                :            if (!pDRIDrawablePriv->hwDrawable) {
37272                :                drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable);
37273                :            }
37274                :        }
37275                :        else {
37276                :            /* allocate a DRI Window Private record */
37277                :            if (!(pDRIDrawablePriv = xalloc(sizeof(DRIDrawablePrivRec)))) {
37278                :                return FALSE;
37279                :            }
37280                :
37281                :            /* Only create a drm_drawable_t once */
37282                :            if (drmCreateDrawable(pDRIPriv->drmFD,
37283                :                                  &pDRIDrawablePriv->hwDrawable)) {
37284                :                xfree(pDRIDrawablePriv);
37285                :                return FALSE;
37286                :            }
37287                :
37288                :            /* add it to the list of DRI drawables for this screen */
37289                :            pDRIDrawablePriv->pScreen = pScreen;
37290                :            pDRIDrawablePriv->refCount = 1;
37291                :            pDRIDrawablePriv->drawableIndex = -1;
37292                :            pDRIDrawablePriv->nrects = REGION_NUM_RECTS(&pWin->clipList);
37293                :
37294                :            /* save private off of preallocated index */
37295                :            pWin->devPrivates[DRIWindowPrivIndex].ptr =
37296                :                                                (pointer)pDRIDrawablePriv;
37297                :
37298                :            pDRIPriv->nrWindows++;
37299                :
37300                :            if (pDRIDrawablePriv->nrects)
37301                :                DRIIncreaseNumberVisible(pScreen);
37302                :
37303                :            /* track this in case this window is destroyed */
37304                :            AddResource(id, DRIDrawablePrivResType, (pointer)pWin);
37305                :        }
37306                :
37307                :        if (pDRIDrawablePriv->hwDrawable) {
37308                :            drmUpdateDrawableInfo(pDRIPriv->drmFD,
37309                :                                  pDRIDrawablePriv->hwDrawable,
37310                :                                  DRM_DRAWABLE_CLIPRECTS,
37311                :                                  REGION_NUM_RECTS(&pWin->clipList),
37312                :                                  REGION_RECTS(&pWin->clipList));
37313                :            *hHWDrawable = pDRIDrawablePriv->hwDrawable;
37314                :        }
37315                :    }
37316                :    else { /* pixmap (or for GLX 1.3, a PBuffer) */
37317                :        /* NOT_DONE */
37318                :        return FALSE;
37319                :    }
37320                :
37321                :    return TRUE;
37322                :}
37323                :
37324                :Bool
37325                :DRIDestroyDrawable(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable)
37326                :{
37327                :    DRIDrawablePrivPtr  pDRIDrawablePriv;
37328                :    WindowPtr           pWin;
37329                :
37330                :
37331                :    if (pDrawable->type == DRAWABLE_WINDOW) {
37332                :        pWin = (WindowPtr)pDrawable;
37333                :        pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
37334                :        pDRIDrawablePriv->refCount--;
37335                :        if (pDRIDrawablePriv->refCount <= 0) {
37336                :            /* This calls back DRIDrawablePrivDelete which frees private area */
37337                :            FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
37338                :        }
37339                :    }
37340                :    else { /* pixmap (or for GLX 1.3, a PBuffer) */
37341                :        /* NOT_DONE */
37342                :        return FALSE;
37343                :    }
37344                :
37345                :    return TRUE;
37346                :}
37347                :
37348                :Bool
37349                :DRIDrawablePrivDelete(pointer pResource, XID id)
37350                :{
37351                :    DrawablePtr         pDrawable = (DrawablePtr)pResource;
37352                :    DRIScreenPrivPtr    pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen);
37353                :    DRIDrawablePrivPtr  pDRIDrawablePriv;
37354                :    WindowPtr           pWin;
37355                :
37356                :    if (pDrawable->type == DRAWABLE_WINDOW) {
37357                :        pWin = (WindowPtr)pDrawable;
37358                :        pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
37359                :
37360                :        if (pDRIDrawablePriv->drawableIndex != -1) {
37361                :            /* bump stamp to force outstanding 3D requests to resync */
37362                :            pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
37363                :                = DRIDrawableValidationStamp++;
37364                :
37365                :            /* release drawable table entry */
37366                :            pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
37367                :        }
37368                :
37369                :        if (drmDestroyDrawable(pDRIPriv->drmFD,
37370                :                               pDRIDrawablePriv->hwDrawable)) {
37371                :            return FALSE;
37372                :        }
37373                :
37374                :        xfree(pDRIDrawablePriv);
37375                :        pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL;
37376                :
37377                :        pDRIPriv->nrWindows--;
37378                :
37379                :        if (REGION_NUM_RECTS(&pWin->clipList))
37380                :            DRIDecreaseNumberVisible(pDrawable->pScreen);
37381                :    }
37382                :    else { /* pixmap (or for GLX 1.3, a PBuffer) */
37383                :        /* NOT_DONE */
37384                :        return FALSE;
37385                :    }
37386                :
37387                :    return TRUE;
37388                :}
37389                :
37390                :Bool
37391                :DRIGetDrawableInfo(ScreenPtr pScreen,
37392                :                   DrawablePtr pDrawable,
37393                :                   unsigned int* index,
37394                :                   unsigned int* stamp,
37395                :                   int* X,
37396                :                   int* Y,
37397                :                   int* W,
37398                :                   int* H,
37399                :                   int* numClipRects,
37400                :                   drm_clip_rect_t ** pClipRects,
37401                :                   int* backX,
37402                :                   int* backY,
37403                :                   int* numBackClipRects,
37404                :                   drm_clip_rect_t ** pBackClipRects)
37405                :{
37406                :    DRIScreenPrivPtr    pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37407                :    DRIDrawablePrivPtr  pDRIDrawablePriv, pOldDrawPriv;
37408                :    WindowPtr           pWin, pOldWin;
37409                :    int                 i;
37410                :
37411                :#if 0
37412                :    printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry);
37413                :#endif
37414                :
37415                :    if (pDrawable->type == DRAWABLE_WINDOW) {
37416                :        pWin = (WindowPtr)pDrawable;
37417                :        if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
37418                :
37419                :            /* Manage drawable table */
37420                :            if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */
37421                :
37422                :                /* Search table for empty entry */
37423                :                i = 0;
37424                :                while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) {
37425                :                    if (!(pDRIPriv->DRIDrawables[i])) {
37426                :                        pDRIPriv->DRIDrawables[i] = pDrawable;
37427                :                        pDRIDrawablePriv->drawableIndex = i;
37428                :                        pDRIPriv->pSAREA->drawableTable[i].stamp =
37429                :                                            DRIDrawableValidationStamp++;
37430                :                        break;
37431                :                    }
37432                :                    i++;
37433                :                }
37434                :
37435                :                /* Search table for oldest entry */
37436                :                if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) {
37437                :                    unsigned int oldestStamp = ~0;
37438                :                    int oldestIndex = 0;
37439                :                    i = pDRIPriv->pDriverInfo->maxDrawableTableEntry;
37440                :                    while (i--) {
37441                :                        if (pDRIPriv->pSAREA->drawableTable[i].stamp <
37442                :                                                                oldestStamp) {
37443                :                            oldestIndex = i;
37444                :                            oldestStamp =
37445                :                                pDRIPriv->pSAREA->drawableTable[i].stamp;
37446                :                        }
37447                :                    }
37448                :                    pDRIDrawablePriv->drawableIndex = oldestIndex;
37449                :
37450                :                    /* release oldest drawable table entry */
37451                :                    pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex];
37452                :                    pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin);
37453                :                    pOldDrawPriv->drawableIndex = -1;
37454                :
37455                :                    /* claim drawable table entry */
37456                :                    pDRIPriv->DRIDrawables[oldestIndex] = pDrawable;
37457                :
37458                :                    /* validate SAREA entry */
37459                :                    pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp =
37460                :                                        DRIDrawableValidationStamp++;
37461                :
37462                :                    /* check for stamp wrap around */
37463                :                    if (oldestStamp > DRIDrawableValidationStamp) {
37464                :
37465                :                        /* walk SAREA table and invalidate all drawables */
37466                :                        for( i=0;
37467                :                             i < pDRIPriv->pDriverInfo->maxDrawableTableEntry;
37468                :                             i++) {
37469                :                                pDRIPriv->pSAREA->drawableTable[i].stamp =
37470                :                                        DRIDrawableValidationStamp++;
37471                :                        }
37472                :                    }
37473                :                }
37474                :
37475                :                /* If the driver wants to be notified when the index is
37476                :                 * set for a drawable, let it know now.
37477                :                 */
37478                :                if (pDRIPriv->pDriverInfo->SetDrawableIndex)
37479                :                        pDRIPriv->pDriverInfo->SetDrawableIndex(pWin,
37480                :                                pDRIDrawablePriv->drawableIndex);
37481                :
37482                :                /* reinit drawable ID if window is visible */
37483                :                if ((pWin->viewable) &&
37484                :                    (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS))
37485                :                {
37486                :                    (*pDRIPriv->pDriverInfo->InitBuffers)(pWin,
37487                :                            &pWin->clipList, pDRIDrawablePriv->drawableIndex);
37488                :                }
37489                :            }
37490                :
37491                :            *index = pDRIDrawablePriv->drawableIndex;
37492                :            *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp;
37493                :            *X = (int)(pWin->drawable.x);
37494                :            *Y = (int)(pWin->drawable.y);
37495                :#if 0
37496                :            *W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1);
37497                :            *H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
37498                :#endif
37499                :            *W = (int)(pWin->drawable.width);
37500                :            *H = (int)(pWin->drawable.height);
37501                :            *numClipRects = REGION_NUM_RECTS(&pWin->clipList);
37502                :            *pClipRects = (drm_clip_rect_t *)REGION_RECTS(&pWin->clipList);
37503                :
37504                :            if (!*numClipRects && pDRIPriv->fullscreen) {
37505                :                                /* use fake full-screen clip rect */
37506                :                pDRIPriv->fullscreen_rect.x1 = *X;
37507                :                pDRIPriv->fullscreen_rect.y1 = *Y;
37508                :                pDRIPriv->fullscreen_rect.x2 = *X + *W;
37509                :                pDRIPriv->fullscreen_rect.y2 = *Y + *H;
37510                :
37511                :                *numClipRects = 1;
37512                :                *pClipRects   = &pDRIPriv->fullscreen_rect;
37513                :            }
37514                :
37515                :            *backX = *X;
37516                :            *backY = *Y;
37517                :
37518                :            if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) {
37519                :               /* Use a single cliprect. */
37520                :
37521                :               int x0 = *X;
37522                :               int y0 = *Y;
37523                :               int x1 = x0 + *W;
37524                :               int y1 = y0 + *H;
37525                :
37526                :               if (x0 < 0) x0 = 0;
37527                :               if (y0 < 0) y0 = 0;
37528                :               if (x1 > pScreen->width) x1 = pScreen->width;
37529                :               if (y1 > pScreen->height) y1 = pScreen->height;
37530                :
37531                :               if (y0 >= y1 || x0 >= x1) {
37532                :                    *numBackClipRects = 0;
37533                :                    *pBackClipRects = NULL;
37534                :               } else {
37535                :                    pDRIPriv->private_buffer_rect.x1 = x0;
37536                :                    pDRIPriv->private_buffer_rect.y1 = y0;
37537                :                    pDRIPriv->private_buffer_rect.x2 = x1;
37538                :                    pDRIPriv->private_buffer_rect.y2 = y1;
37539                :
37540                :                    *numBackClipRects = 1;
37541                :                    *pBackClipRects = &(pDRIPriv->private_buffer_rect);
37542                :               }
37543                :            } else {
37544                :               /* Use the frontbuffer cliprects for back buffers.  */
37545                :               *numBackClipRects = 0;
37546                :               *pBackClipRects = 0;
37547                :            }
37548                :        }
37549                :        else {
37550                :            /* Not a DRIDrawable */
37551                :            return FALSE;
37552                :        }
37553                :    }
37554                :    else { /* pixmap (or for GLX 1.3, a PBuffer) */
37555                :        /* NOT_DONE */
37556                :        return FALSE;
37557                :    }
37558                :
37559                :    return TRUE;
37560                :}
37561                :
37562                :Bool
37563                :DRIGetDeviceInfo(ScreenPtr pScreen,
37564                :                 drm_handle_t * hFrameBuffer,
37565                :                 int* fbOrigin,
37566                :                 int* fbSize,
37567                :                 int* fbStride,
37568                :                 int* devPrivateSize,
37569                :                 void** pDevPrivate)
37570                :{
37571                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37572                :
37573                :    *hFrameBuffer = pDRIPriv->hFrameBuffer;
37574                :    *fbOrigin = 0;
37575                :    *fbSize = pDRIPriv->pDriverInfo->frameBufferSize;
37576                :    *fbStride = pDRIPriv->pDriverInfo->frameBufferStride;
37577                :    *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize;
37578                :    *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate;
37579                :
37580                :    return TRUE;
37581                :}
37582                :
37583                :DRIInfoPtr
37584                :DRICreateInfoRec(void)
37585                :{
37586                :    DRIInfoPtr inforec = (DRIInfoPtr)xcalloc(1, sizeof(DRIInfoRec));
37587                :    if (!inforec) return NULL;
37588                :
37589                :    /* Initialize defaults */
37590                :    inforec->busIdString = NULL;
37591                :
37592                :    /* Wrapped function defaults */
37593                :    inforec->wrap.WakeupHandler         = DRIDoWakeupHandler;
37594                :    inforec->wrap.BlockHandler          = DRIDoBlockHandler;
37595                :    inforec->wrap.WindowExposures       = DRIWindowExposures;
37596                :    inforec->wrap.CopyWindow            = DRICopyWindow;
37597                :    inforec->wrap.ValidateTree          = DRIValidateTree;
37598                :    inforec->wrap.PostValidateTree      = DRIPostValidateTree;
37599                :    inforec->wrap.ClipNotify            = DRIClipNotify;
37600                :    inforec->wrap.AdjustFrame           = DRIAdjustFrame;
37601                :
37602                :    inforec->TransitionTo2d = 0;
37603                :    inforec->TransitionTo3d = 0;
37604                :    inforec->SetDrawableIndex = 0;
37605                :
37606                :    return inforec;
37607                :}
37608                :
37609                :void
37610                :DRIDestroyInfoRec(DRIInfoPtr DRIInfo)
37611                :{
37612                :    if (DRIInfo->busIdString) xfree(DRIInfo->busIdString);
37613                :    xfree((char*)DRIInfo);
37614                :}
37615                :
37616                :
37617                :void
37618                :DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask)
37619                :{
37620                :    int i;
37621                :
37622                :    for (i = 0; i < screenInfo.numScreens; i++) {
37623                :        ScreenPtr        pScreen  = screenInfo.screens[i];
37624                :        DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37625                :
37626                :        if (pDRIPriv &&
37627                :            pDRIPriv->pDriverInfo->wrap.WakeupHandler)
37628                :            (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData,
37629                :                                                         result, pReadmask);
37630                :    }
37631                :}
37632                :
37633                :void
37634                :DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
37635                :{
37636                :    int i;
37637                :
37638                :    for (i = 0; i < screenInfo.numScreens; i++) {
37639                :        ScreenPtr        pScreen  = screenInfo.screens[i];
37640                :        DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37641                :
37642                :        if (pDRIPriv &&
37643                :            pDRIPriv->pDriverInfo->wrap.BlockHandler)
37644                :            (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData,
37645                :                                                        pTimeout, pReadmask);
37646                :    }
37647                :}
37648                :
37649                :void
37650                :DRIDoWakeupHandler(int screenNum, pointer wakeupData,
37651                :                   unsigned long result, pointer pReadmask)
37652                :{
37653                :    ScreenPtr pScreen = screenInfo.screens[screenNum];
37654                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37655                :
37656                :    DRILock(pScreen, 0);
37657                :    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
37658                :        /* hide X context by swapping 2D component here */
37659                :        (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
37660                :                                              DRI_3D_SYNC,
37661                :                                              DRI_2D_CONTEXT,
37662                :                                              pDRIPriv->partial3DContextStore,
37663                :                                              DRI_2D_CONTEXT,
37664                :                                              pDRIPriv->hiddenContextStore);
37665                :    }
37666                :}
37667                :
37668                :void
37669                :DRIDoBlockHandler(int screenNum, pointer blockData,
37670                :                  pointer pTimeout, pointer pReadmask)
37671                :{
37672                :    ScreenPtr pScreen = screenInfo.screens[screenNum];
37673                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37674                :
37675                :    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
37676                :        /* hide X context by swapping 2D component here */
37677                :        (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
37678                :                                              DRI_2D_SYNC,
37679                :                                              DRI_NO_CONTEXT,
37680                :                                              NULL,
37681                :                                              DRI_2D_CONTEXT,
37682                :                                              pDRIPriv->partial3DContextStore);
37683                :    }
37684                :
37685                :    if (pDRIPriv->windowsTouched)
37686                :        DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1);
37687                :    pDRIPriv->windowsTouched = FALSE;
37688                :
37689                :    DRIUnlock(pScreen);
37690                :}
37691                :
37692                :void
37693                :DRISwapContext(int drmFD, void *oldctx, void *newctx)
37694                :{
37695                :    DRIContextPrivPtr oldContext      = (DRIContextPrivPtr)oldctx;
37696                :    DRIContextPrivPtr newContext      = (DRIContextPrivPtr)newctx;
37697                :    ScreenPtr         pScreen         = newContext->pScreen;
37698                :    DRIScreenPrivPtr  pDRIPriv        = DRI_SCREEN_PRIV(pScreen);
37699                :    void*             oldContextStore = NULL;
37700                :    DRIContextType    oldContextType;
37701                :    void*             newContextStore = NULL;
37702                :    DRIContextType    newContextType;
37703                :    DRISyncType       syncType;
37704                :#ifdef DEBUG
37705                :    static int        count = 0;
37706                :
37707                :    if (!newContext) {
37708                :        DRIDrvMsg(pScreen->myNum, X_ERROR,
37709                :                  "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n",
37710                :                  oldContext, newContext);
37711                :        return;
37712                :    }
37713                :
37714                :    /* usefull for debugging, just print out after n context switches */
37715                :    if (!count || !(count % 1)) {
37716                :        DRIDrvMsg(pScreen->myNum, X_INFO,
37717                :                  "[DRI] Context switch %5d from %p/0x%08x (%d)\n",
37718                :                  count,
37719                :                  oldContext,
37720                :                  oldContext ? oldContext->flags : 0,
37721                :                  oldContext ? oldContext->hwContext : -1);
37722                :        DRIDrvMsg(pScreen->myNum, X_INFO,
37723                :                  "[DRI] Context switch %5d to   %p/0x%08x (%d)\n",
37724                :                  count,
37725                :                  newContext,
37726                :                  newContext ? newContext->flags : 0,
37727                :                  newContext ? newContext->hwContext : -1);
37728                :    }
37729                :    ++count;
37730                :#endif
37731                :
37732                :    if (!pDRIPriv->pDriverInfo->SwapContext) {
37733                :        DRIDrvMsg(pScreen->myNum, X_ERROR,
37734                :                  "[DRI] DDX driver missing context swap call back\n");
37735                :        return;
37736                :    }
37737                :
37738                :    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
37739                :
37740                :        /* only 3D contexts are swapped in this case */
37741                :        if (oldContext) {
37742                :            oldContextStore     = DRIGetContextStore(oldContext);
37743                :            oldContext->valid3D = TRUE;
37744                :            oldContextType      = DRI_3D_CONTEXT;
37745                :        } else {
37746                :            oldContextType      = DRI_NO_CONTEXT;
37747                :        }
37748                :        newContextStore = DRIGetContextStore(newContext);
37749                :        if ((newContext->valid3D) &&
37750                :          (newContext->hwContext != pDRIPriv->myContext)) {
37751                :            newContextType = DRI_3D_CONTEXT;
37752                :        }
37753                :        else {
37754                :            newContextType = DRI_2D_CONTEXT;
37755                :        }
37756                :        syncType = DRI_3D_SYNC;
37757                :    }
37758                :    else /* default: driverSwapMethod == DRI_SERVER_SWAP */ {
37759                :
37760                :        /* optimize 2D context swaps */
37761                :
37762                :        if (newContext->flags & DRI_CONTEXT_2DONLY) {
37763                :            /* go from 3D context to 2D context and only save 2D
37764                :             * subset of 3D state
37765                :             */
37766                :            oldContextStore = DRIGetContextStore(oldContext);
37767                :            oldContextType = DRI_2D_CONTEXT;
37768                :            newContextStore = DRIGetContextStore(newContext);
37769                :            newContextType = DRI_2D_CONTEXT;
37770                :            syncType = DRI_3D_SYNC;
37771                :            pDRIPriv->lastPartial3DContext = oldContext;
37772                :        }
37773                :        else if (oldContext->flags & DRI_CONTEXT_2DONLY) {
37774                :            if (pDRIPriv->lastPartial3DContext == newContext) {
37775                :                /* go from 2D context back to previous 3D context and
37776                :                 * only restore 2D subset of previous 3D state
37777                :                 */
37778                :                oldContextStore = DRIGetContextStore(oldContext);
37779                :                oldContextType = DRI_2D_CONTEXT;
37780                :                newContextStore = DRIGetContextStore(newContext);
37781                :                newContextType = DRI_2D_CONTEXT;
37782                :                syncType = DRI_2D_SYNC;
37783                :            }
37784                :            else {
37785                :                /* go from 2D context to a different 3D context */
37786                :
37787                :                /* call DDX driver to do partial restore */
37788                :                oldContextStore = DRIGetContextStore(oldContext);
37789                :                newContextStore =
37790                :                        DRIGetContextStore(pDRIPriv->lastPartial3DContext);
37791                :                (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
37792                :                                                      DRI_2D_SYNC,
37793                :                                                      DRI_2D_CONTEXT,
37794                :                                                      oldContextStore,
37795                :                                                      DRI_2D_CONTEXT,
37796                :                                                      newContextStore);
37797                :
37798                :                /* now setup for a complete 3D swap */
37799                :                oldContextStore = newContextStore;
37800                :                oldContext->valid3D = TRUE;
37801                :                oldContextType = DRI_3D_CONTEXT;
37802                :                newContextStore = DRIGetContextStore(newContext);
37803                :                if ((newContext->valid3D) &&
37804                :                  (newContext->hwContext != pDRIPriv->myContext)) {
37805                :                    newContextType = DRI_3D_CONTEXT;
37806                :                }
37807                :                else {
37808                :                    newContextType = DRI_2D_CONTEXT;
37809                :                }
37810                :                syncType = DRI_NO_SYNC;
37811                :            }
37812                :        }
37813                :        else {
37814                :            /* now setup for a complete 3D swap */
37815                :            oldContextStore = newContextStore;
37816                :            oldContext->valid3D = TRUE;
37817                :            oldContextType = DRI_3D_CONTEXT;
37818                :            newContextStore = DRIGetContextStore(newContext);
37819                :            if ((newContext->valid3D) &&
37820                :              (newContext->hwContext != pDRIPriv->myContext)) {
37821                :                newContextType = DRI_3D_CONTEXT;
37822                :            }
37823                :            else {
37824                :                newContextType = DRI_2D_CONTEXT;
37825                :            }
37826                :            syncType = DRI_3D_SYNC;
37827                :        }
37828                :    }
37829                :
37830                :    /* call DDX driver to perform the swap */
37831                :    (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
37832                :                                          syncType,
37833                :                                          oldContextType,
37834                :                                          oldContextStore,
37835                :                                          newContextType,
37836                :                                          newContextStore);
37837                :}
37838                :
37839                :void* 
37840                :DRIGetContextStore(DRIContextPrivPtr context)
37841                :{
37842                :    return((void *)context->pContextStore);
37843                :}
37844                :
37845                :void
37846                :DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg)
37847                :{
37848                :    ScreenPtr pScreen = pWin->drawable.pScreen;
37849                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37850                :    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
37851                :
37852                :    if(pDRIDrawablePriv) {
37853                :         (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn,
37854                :                                               pDRIDrawablePriv->drawableIndex);
37855                :    }
37856                :
37857                :    /* call lower wrapped functions */
37858                :    if (pDRIPriv && pDRIPriv->wrap.WindowExposures) {
37859                :
37860                :        /* unwrap */
37861                :        pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
37862                :
37863                :        /* call lower layers */
37864                :        (*pScreen->WindowExposures)(pWin, prgn, bsreg);
37865                :
37866                :        /* rewrap */
37867                :        pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
37868                :        pScreen->WindowExposures = DRIWindowExposures;
37869                :    }
37870                :}
37871                :
37872                :
37873                :static int
37874                :DRITreeTraversal(WindowPtr pWin, pointer data)
37875                :{
37876                :    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
37877                :
37878                :    if(pDRIDrawablePriv) {
37879                :        ScreenPtr pScreen = pWin->drawable.pScreen;
37880                :        DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37881                :
37882                :        if(REGION_NUM_RECTS(&(pWin->clipList)) > 0) {
37883                :           RegionPtr reg = (RegionPtr)data;
37884                :
37885                :           REGION_UNION(pScreen, reg, reg, &(pWin->clipList));
37886                :           pDRIPriv->nrWalked++;
37887                :        }
37888                :
37889                :        if(pDRIPriv->nrWindows == pDRIPriv->nrWalked)
37890                :           return WT_STOPWALKING;
37891                :    }
37892                :    return WT_WALKCHILDREN;
37893                :}
37894                :
37895                :void
37896                :DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
37897                :{
37898                :    ScreenPtr pScreen = pWin->drawable.pScreen;
37899                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37900                :
37901                :    if(!pDRIPriv) return;
37902                :
37903                :    if(pDRIPriv->nrWindowsVisible > 0) {
37904                :       RegionRec reg;
37905                :
37906                :       REGION_NULL(pScreen, &reg);
37907                :       pDRIPriv->nrWalked = 0;
37908                :       TraverseTree(pWin, DRITreeTraversal, (pointer)(&reg));
37909                :
37910                :       if(REGION_NOTEMPTY(pScreen, &reg)) {
37911                :           REGION_TRANSLATE(pScreen, &reg, ptOldOrg.x - pWin->drawable.x,  
37912                :                                        ptOldOrg.y - pWin->drawable.y);
37913                :           REGION_INTERSECT(pScreen, &reg, &reg, prgnSrc);
37914                :
37915                :           /* The MoveBuffers interface is not ideal */
37916                :           (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, &reg,
37917                :                                pDRIPriv->pDriverInfo->ddxDrawableTableEntry);
37918                :       }
37919                :
37920                :       REGION_UNINIT(pScreen, &reg);
37921                :    }
37922                :
37923                :    /* call lower wrapped functions */
37924                :    if(pDRIPriv->wrap.CopyWindow) {
37925                :        /* unwrap */
37926                :        pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
37927                :
37928                :        /* call lower layers */
37929                :        (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
37930                :
37931                :        /* rewrap */
37932                :        pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
37933                :        pScreen->CopyWindow = DRICopyWindow;
37934                :    }
37935                :}
37936                :
37937                :static void
37938                :DRIGetSecs(long *secs, long *usecs)
37939                :{
37940                :    struct timeval tv;
37941                :
37942                :    gettimeofday(&tv, NULL);
37943                :
37944                :    *secs  = tv.tv_sec;
37945                :    *usecs = tv.tv_usec;
37946                :}
37947                :
37948                :static unsigned long
37949                :DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs,
37950                :                       unsigned long f_secs, unsigned long f_usecs)
37951                :{
37952                :    if (f_usecs < s_usecs) {
37953                :        --f_secs;
37954                :        f_usecs += 1000000;
37955                :    }
37956                :    return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000;
37957                :}
37958                :
37959                :static void
37960                :DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */)
37961                :{
37962                :    int  count = 10000;
37963                :#if !defined(__alpha__) && !defined(__powerpc__)
37964                :    char ret;
37965                :#else
37966                :    int ret;
37967                :#endif
37968                :    long s_secs, s_usecs;
37969                :    long f_secs, f_usecs;
37970                :    long msecs;
37971                :    long prev  = 0;
37972                :
37973                :    DRIGetSecs(&s_secs, &s_usecs);
37974                :
37975                :    do {
37976                :        DRM_SPINLOCK_COUNT(lock, val, count, ret);
37977                :        if (!ret) return;       /* Got lock */
37978                :        DRIGetSecs(&f_secs, &f_usecs);
37979                :        msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs);
37980                :        if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */
37981                :    } while (msecs < timeout);
37982                :
37983                :                                /* Didn't get lock, so take it.  The worst
37984                :                                   that can happen is that there is some
37985                :                                   garbage written to the wrong part of the
37986                :                                   framebuffer that a refresh will repair.
37987                :                                   That's undesirable, but better than
37988                :                                   locking the server.  This should be a
37989                :                                   very rare event. */
37990                :    DRM_SPINLOCK_TAKE(lock, val);
37991                :}
37992                :
37993                :static void
37994                :DRILockTree(ScreenPtr pScreen)
37995                :{
37996                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
37997                :
37998                :    if(!pDRIPriv) return;
37999                :
38000                :    /* Restore the last known 3D context if the X context is hidden */
38001                :    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
38002                :        (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
38003                :                                              DRI_2D_SYNC,
38004                :                                              DRI_NO_CONTEXT,
38005                :                                              NULL,
38006                :                                              DRI_2D_CONTEXT,
38007                :                                              pDRIPriv->partial3DContextStore);
38008                :    }
38009                :
38010                :    /* Call kernel to release lock */
38011                :    DRIUnlock(pScreen);
38012                :
38013                :    /* Grab drawable spin lock: a time out between 10 and 30 seconds is
38014                :       appropriate, since this should never time out except in the case of
38015                :       client death while the lock is being held.  The timeout must be
38016                :       greater than any reasonable rendering time. */
38017                :    DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/
38018                :
38019                :    /* Call kernel flush outstanding buffers and relock */
38020                :    DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL);
38021                :
38022                :    /* Switch back to our 2D context if the X context is hidden */
38023                :    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
38024                :        /* hide X context by swapping 2D component here */
38025                :        (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
38026                :                                              DRI_3D_SYNC,
38027                :                                              DRI_2D_CONTEXT,
38028                :                                              pDRIPriv->partial3DContextStore,
38029                :                                              DRI_2D_CONTEXT,
38030                :                                              pDRIPriv->hiddenContextStore);
38031                :    }
38032                :}
38033                :
38034                :int
38035                :DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
38036                :{
38037                :    ScreenPtr pScreen = pParent->drawable.pScreen;
38038                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38039                :
38040                :    int returnValue = 1; /* always return 1, not checked by dix/window.c */
38041                :
38042                :    if(!pDRIPriv) return returnValue;
38043                :
38044                :    /* call lower wrapped functions */
38045                :    if(pDRIPriv->wrap.ValidateTree) {
38046                :        /* unwrap */
38047                :        pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
38048                :
38049                :        /* call lower layers */
38050                :        returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
38051                :
38052                :        /* rewrap */
38053                :        pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
38054                :        pScreen->ValidateTree = DRIValidateTree;
38055                :    }
38056                :
38057                :    return returnValue;
38058                :}
38059                :
38060                :void
38061                :DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
38062                :{
38063                :    ScreenPtr pScreen;
38064                :    DRIScreenPrivPtr pDRIPriv;
38065                :
38066                :    if (pParent) {
38067                :        pScreen = pParent->drawable.pScreen;
38068                :    } else {
38069                :        pScreen = pChild->drawable.pScreen;
38070                :    }
38071                :    if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return;
38072                :
38073                :    if (pDRIPriv->wrap.PostValidateTree) {
38074                :        /* unwrap */
38075                :        pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
38076                :
38077                :        /* call lower layers */
38078                :        (*pScreen->PostValidateTree)(pParent, pChild, kind);
38079                :
38080                :        /* rewrap */
38081                :        pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
38082                :        pScreen->PostValidateTree = DRIPostValidateTree;
38083                :    }
38084                :}
38085                :
38086                :void
38087                :DRIClipNotify(WindowPtr pWin, int dx, int dy)
38088                :{
38089                :    ScreenPtr pScreen = pWin->drawable.pScreen;
38090                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38091                :    DRIDrawablePrivPtr  pDRIDrawablePriv;
38092                :
38093                :    if(!pDRIPriv) return;
38094                :
38095                :    if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
38096                :        int nrects = REGION_NUM_RECTS(&pWin->clipList);
38097                :
38098                :        if(!pDRIPriv->windowsTouched) {
38099                :            DRILockTree(pScreen);
38100                :            pDRIPriv->windowsTouched = TRUE;
38101                :        }
38102                :
38103                :        if (nrects && !pDRIDrawablePriv->nrects)
38104                :            DRIIncreaseNumberVisible(pScreen);
38105                :        else if (!nrects && pDRIDrawablePriv->nrects)
38106                :            DRIDecreaseNumberVisible(pScreen);
38107                :        else
38108                :            DRIDriverClipNotify(pScreen);
38109                :
38110                :        pDRIDrawablePriv->nrects = nrects;
38111                :
38112                :        pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
38113                :            = DRIDrawableValidationStamp++;
38114                :
38115                :        drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable,
38116                :                              DRM_DRAWABLE_CLIPRECTS,
38117                :                              nrects, REGION_RECTS(&pWin->clipList));
38118                :    }
38119                :
38120                :    /* call lower wrapped functions */
38121                :    if(pDRIPriv->wrap.ClipNotify) {
38122                :
38123                :        /* unwrap */
38124                :        pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
38125                :
38126                :        /* call lower layers */
38127                :        (*pScreen->ClipNotify)(pWin, dx, dy);
38128                :
38129                :        /* rewrap */
38130                :        pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
38131                :        pScreen->ClipNotify = DRIClipNotify;
38132                :    }
38133                :}
38134                :
38135                :CARD32
38136                :DRIGetDrawableIndex(WindowPtr pWin)
38137                :{
38138                :    ScreenPtr pScreen = pWin->drawable.pScreen;
38139                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38140                :    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
38141                :    CARD32 index;
38142                :
38143                :    if (pDRIDrawablePriv) {
38144                :        index = pDRIDrawablePriv->drawableIndex;
38145                :    }
38146                :    else {
38147                :        index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry;
38148                :    }
38149                :
38150                :    return index;
38151                :}
38152                :
38153                :unsigned int
38154                :DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index)
38155                :{
38156                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38157                :    return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp;
38158                :}
38159                :
38160                :
38161                :void
38162                :DRIPrintDrawableLock(ScreenPtr pScreen, char *msg)
38163                :{
38164                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38165                :
38166                :    ErrorF("%s: %d\n", msg,  pDRIPriv->pSAREA->drawable_lock.lock);
38167                :}
38168                :
38169                :void
38170                :DRILock(ScreenPtr pScreen, int flags)
38171                :{
38172                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38173                :
38174                :    if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
38175                :
38176                :    if (!*pDRIPriv->pLockRefCount) {
38177                :        DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags);
38178                :        *pDRIPriv->pLockingContext = pDRIPriv->myContext;
38179                :    } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) {
38180                :        DRIDrvMsg(pScreen->myNum, X_ERROR,
38181                :                  "[DRI] Locking deadlock.\n"
38182                :                  "\tAlready locked with context %d,\n"
38183                :                  "\ttrying to lock with context %d.\n",
38184                :                  pDRIPriv->pLockingContext,
38185                :                  pDRIPriv->myContext);
38186                :    }
38187                :    (*pDRIPriv->pLockRefCount)++;
38188                :}
38189                :
38190                :void
38191                :DRIUnlock(ScreenPtr pScreen)
38192                :{
38193                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38194                :
38195                :    if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
38196                :
38197                :    if (*pDRIPriv->pLockRefCount > 0) {
38198                :        if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) {
38199                :            DRIDrvMsg(pScreen->myNum, X_ERROR,
38200                :                      "[DRI] Unlocking inconsistency:\n"
38201                :                      "\tContext %d trying to unlock lock held by context %d\n",
38202                :                      pDRIPriv->pLockingContext,
38203                :                      pDRIPriv->myContext);
38204                :        }
38205                :        (*pDRIPriv->pLockRefCount)--;
38206                :    } else {
38207                :        DRIDrvMsg(pScreen->myNum, X_ERROR,
38208                :                  "DRIUnlock called when not locked.\n");
38209                :        return;
38210                :    }
38211                :    if (! *pDRIPriv->pLockRefCount)
38212                :        DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext);
38213                :}
38214                :
38215                :void *
38216                :DRIGetSAREAPrivate(ScreenPtr pScreen)
38217      6  0.0065 :{ /* DRIGetSAREAPrivate total:     25  0.0272 */
38218      4  0.0044 :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38219      2  0.0022 :    if (!pDRIPriv) return 0;
38220                :
38221      1  0.0011 :    return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec));
38222     12  0.0131 :}
38223                :
38224                :drm_context_t
38225                :DRIGetContext(ScreenPtr pScreen)
38226      8  0.0087 :{ /* DRIGetContext total:     16  0.0174 */
38227                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38228      1  0.0011 :    if (!pDRIPriv) return 0;
38229                :
38230                :    return pDRIPriv->myContext;
38231      7  0.0076 :}
38232                :
38233                :void
38234                :DRIGetTexOffsetFuncs(ScreenPtr pScreen,
38235                :                     DRITexOffsetStartProcPtr *texOffsetStartFunc,
38236                :                     DRITexOffsetFinishProcPtr *texOffsetFinishFunc)
38237                :{
38238                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38239                :
38240                :    if (!pDRIPriv) return;
38241                :
38242                :    *texOffsetStartFunc  = pDRIPriv->pDriverInfo->texOffsetStart;
38243                :    *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish;
38244                :}
38245                :
38246                :/* This lets get at the unwrapped functions so that they can correctly
38247                : * call the lowerlevel functions, and choose whether they will be
38248                : * called at every level of recursion (eg in validatetree).
38249                : */
38250                :DRIWrappedFuncsRec *
38251                :DRIGetWrappedFuncs(ScreenPtr pScreen)
38252                :{
38253                :    return &(DRI_SCREEN_PRIV(pScreen)->wrap);
38254                :}
38255                :
38256                :/* note that this returns the library version, not the protocol version */
38257                :void
38258                :DRIQueryVersion(int *majorVersion,
38259                :                int *minorVersion,
38260                :                int *patchVersion)
38261                :{
38262                :    *majorVersion = DRIINFO_MAJOR_VERSION;
38263                :    *minorVersion = DRIINFO_MINOR_VERSION;
38264                :    *patchVersion = DRIINFO_PATCH_VERSION;
38265                :}
38266                :
38267                :static void
38268                :_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y)
38269                :{
38270                :    pDRIPriv->pSAREA->frame.x      = x;
38271                :    pDRIPriv->pSAREA->frame.y      = y;
38272                :    pDRIPriv->pSAREA->frame.width  = pScrn->frameX1 - x + 1;
38273                :    pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1;
38274                :}
38275                :
38276                :void
38277                :DRIAdjustFrame(int scrnIndex, int x, int y, int flags)
38278                :{
38279                :    ScreenPtr        pScreen  = screenInfo.screens[scrnIndex];
38280                :    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
38281                :    ScrnInfoPtr      pScrn    = xf86Screens[pScreen->myNum];
38282                :    int              px, py;
38283                :
38284                :    if (!pDRIPriv || !pDRIPriv->pSAREA) {
38285                :        DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n",
38286                :                  pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL);
38287                :        return;
38288                :    }
38289                :
38290                :    if (pDRIPriv->fullscreen) {
38291                :                                /* Fix up frame */
38292                :        pScrn->frameX0 = pDRIPriv->pSAREA->frame.x;
38293                :        pScrn->frameY0 = pDRIPriv->pSAREA->frame.y;
38294                :        pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1;
38295                :        pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1;
38296                :
38297                :                                /* Fix up cursor */
38298                :        miPointerPosition(&px, &py);
38299                :        if (px < pScrn->frameX0) px = pScrn->frameX0;
38300                :        if (px > pScrn->frameX1) px = pScrn->frameX1;
38301                :        if (py < pScrn->frameY0) py = pScrn->frameY0;
38302                :        if (py > pScrn->frameY1) py = pScrn->frameY1;
38303                :        pScreen->SetCursorPosition(pScreen, px, py, TRUE);
38304                :        return;
38305                :    }
38306                :
38307                :    if (pDRIPriv->wrap.AdjustFrame) {
38308                :        /* unwrap */
38309                :        pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame;
38310                :        /* call lower layers */
38311                :        (*pScrn->AdjustFrame)(scrnIndex, x, y, flags);
38312                :        /* rewrap */
38313                :        pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame;
38314                :        pScrn->AdjustFrame         = DRIAdjustFrame;
38315                :    }
38316                :
38317                :    _DRIAdjustFrame(pScrn, pDRIPriv, x, y);
38318                :}
38319                :
38320                :/* 
38321                : * DRIMoveBuffersHelper swaps the regions rects in place leaving you
38322                : * a region with the rects in the order that you need to blit them,
38323                : * but it is possibly (likely) an invalid region afterwards.  If you
38324                : * need to use the region again for anything you have to call 
38325                : * REGION_VALIDATE on it, or better yet, save a copy first.
38326                : */
38327                :
38328                :void
38329                :DRIMoveBuffersHelper(
38330                :   ScreenPtr pScreen, 
38331                :   int dx,
38332                :   int dy,
38333                :   int *xdir, 
38334                :   int *ydir, 
38335                :   RegionPtr reg
38336                :)
38337                :{
38338                :   BoxPtr extents, pbox, firstBox, lastBox;
38339                :   BoxRec tmpBox;
38340                :   int y, nbox;
38341                :
38342                :   extents = REGION_EXTENTS(pScreen, reg);
38343                :   nbox = REGION_NUM_RECTS(reg);
38344                :   pbox = REGION_RECTS(reg);
38345                :
38346                :   if((dy > 0) && (dy < (extents->y2 - extents->y1))) {
38347                :     *ydir = -1;
38348                :     if(nbox > 1) {
38349                :        firstBox = pbox;
38350                :        lastBox = pbox + nbox - 1;
38351                :        while((unsigned long)firstBox < (unsigned long)lastBox) {
38352                :           tmpBox = *firstBox;
38353                :           *firstBox = *lastBox;
38354                :           *lastBox = tmpBox;
38355                :           firstBox++;
38356                :           lastBox--;
38357                :        }
38358                :     }
38359                :   } else *ydir = 1;
38360                :
38361                :   if((dx > 0) && (dx < (extents->x2 - extents->x1))) {
38362                :     *xdir = -1;
38363                :     if(nbox > 1) {
38364                :        firstBox = lastBox = pbox;
38365                :        y = pbox->y1;
38366                :        while(--nbox) {
38367                :           pbox++;
38368                :           if(pbox->y1 == y) lastBox++;
38369                :           else {
38370                :              while((unsigned long)firstBox < (unsigned long)lastBox) {
38371                :                 tmpBox = *firstBox;
38372                :                 *firstBox = *lastBox;
38373                :                 *lastBox = tmpBox;
38374                :                 firstBox++;
38375                :                 lastBox--;
38376                :              }
38377                :
38378                :              firstBox = lastBox = pbox;
38379                :              y = pbox->y1;
38380                :           }
38381                :         }
38382                :         while((unsigned long)firstBox < (unsigned long)lastBox) {
38383                :           tmpBox = *firstBox;
38384                :           *firstBox = *lastBox;
38385                :           *lastBox = tmpBox;
38386                :           firstBox++;
38387                :           lastBox--;
38388                :        }
38389                :     }
38390                :   } else *xdir = 1;
38391                :
38392                :}
38393                :
38394                :char *
38395                :DRICreatePCIBusID(pciVideoPtr PciInfo)
38396                :{
38397                :    char *busID;
38398                :    int domain;
38399                :    PCITAG tag;
38400                :
38401                :    busID = xalloc(20);
38402                :    if (busID == NULL)
38403                :        return NULL;
38404                :
38405                :    tag = pciTag(PciInfo->bus, PciInfo->device, PciInfo->func);
38406                :    domain = xf86GetPciDomain(tag);
38407                :    snprintf(busID, 20, "pci:%04x:%02x:%02x.%d", domain,
38408                :        PCI_BUS_NO_DOMAIN(PciInfo->bus), PciInfo->device, PciInfo->func);
38409                :    return busID;
38410                :}
38411                :
38412                :static void drmSIGIOHandler(int interrupt, void *closure)
38413                :{
38414                :    unsigned long key;
38415                :    void          *value;
38416                :    ssize_t       count;
38417                :    drm_ctx_t     ctx;
38418                :    typedef void  (*_drmCallback)(int, void *, void *);
38419                :    char          buf[256];
38420                :    drm_context_t    old;
38421                :    drm_context_t    new;
38422                :    void          *oldctx;
38423                :    void          *newctx;
38424                :    char          *pt;
38425                :    drmHashEntry  *entry;
38426                :    void *hash_table;
38427                :
38428                :    hash_table = drmGetHashTable();
38429                :
38430                :    if (!hash_table) return;
38431                :    if (drmHashFirst(hash_table, &key, &value)) {
38432                :        entry = value;
38433                :        do {
38434                :#if 0
38435                :            fprintf(stderr, "Trying %d\n", entry->fd);
38436                :#endif
38437                :            if ((count = read(entry->fd, buf, sizeof(buf))) > 0) {
38438                :                buf[count] = '\0';
38439                :#if 0
38440                :                fprintf(stderr, "Got %s\n", buf);
38441                :#endif
38442                :
38443                :                for (pt = buf; *pt != ' '; ++pt); /* Find first space */
38444                :                ++pt;
38445                :                old    = strtol(pt, &pt, 0);
38446                :                new    = strtol(pt, NULL, 0);
38447                :                oldctx = drmGetContextTag(entry->fd, old);
38448                :                newctx = drmGetContextTag(entry->fd, new);
38449                :#if 0
38450                :                fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx);
38451                :#endif
38452                :                ((_drmCallback)entry->f)(entry->fd, oldctx, newctx);
38453                :                ctx.handle = new;
38454                :                ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
38455                :            }
38456                :        } while (drmHashNext(hash_table, &key, &value));
38457                :    }
38458                :}
38459                :
38460                :
38461                :int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *))
38462                :{
38463                :    drmHashEntry     *entry;
38464                :
38465                :    entry     = drmGetEntry(fd);
38466                :    entry->f  = f;
38467                :
38468                :    return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
38469                :}
38470                :
38471                :int drmRemoveSIGIOHandler(int fd)
38472                :{
38473                :    drmHashEntry     *entry = drmGetEntry(fd);
38474                :
38475                :    entry->f = NULL;
38476                :
38477                :    return xf86RemoveSIGIOHandler(fd);
38478                :}
38479 /* 
38480  * Total samples for file : "/home/cworth/src/xorg/xserver/render/filter.c"
38481  * 
38482  *     34  0.0370
38483  */
38484
38485
38486                :/*
38487                : * Copyright Â© 2002 Keith Packard
38488                : *
38489                : * Permission to use, copy, modify, distribute, and sell this software and its
38490                : * documentation for any purpose is hereby granted without fee, provided that
38491                : * the above copyright notice appear in all copies and that both that
38492                : * copyright notice and this permission notice appear in supporting
38493                : * documentation, and that the name of Keith Packard not be used in
38494                : * advertising or publicity pertaining to distribution of the software without
38495                : * specific, written prior permission.  Keith Packard makes no
38496                : * representations about the suitability of this software for any purpose.  It
38497                : * is provided "as is" without express or implied warranty.
38498                : *
38499                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
38500                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
38501                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
38502                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
38503                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38504                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
38505                : * PERFORMANCE OF THIS SOFTWARE.
38506                : */
38507                :
38508                :#ifdef HAVE_DIX_CONFIG_H
38509                :#include <dix-config.h>
38510                :#endif
38511                :
38512                :#include "misc.h"
38513                :#include "scrnintstr.h"
38514                :#include "os.h"
38515                :#include "regionstr.h"
38516                :#include "validate.h"
38517                :#include "windowstr.h"
38518                :#include "input.h"
38519                :#include "resource.h"
38520                :#include "colormapst.h"
38521                :#include "cursorstr.h"
38522                :#include "dixstruct.h"
38523                :#include "gcstruct.h"
38524                :#include "servermd.h"
38525                :#include "picturestr.h"
38526                :
38527                :static char **filterNames;
38528                :static int  nfilterNames;
38529                :
38530                :/*
38531                : * standard but not required filters don't have constant indices
38532                : */
38533                :
38534                :int
38535                :PictureGetFilterId (char *filter, int len, Bool makeit)
38536      3  0.0033 :{ /* PictureGetFilterId total:     16  0.0174 */
38537                :    int     i;
38538                :    char    *name;
38539                :    char    **names;
38540                :
38541                :    if (len < 0)
38542      7  0.0076 :        len = strlen (filter);
38543                :    for (i = 0; i < nfilterNames; i++)
38544      6  0.0065 :        if (!CompareISOLatin1Lowered ((unsigned char *) filterNames[i], -1, (unsigned char *) filter, len))
38545                :            return i;
38546                :    if (!makeit)
38547                :        return -1;
38548                :    name = xalloc (len + 1);
38549                :    if (!name)
38550                :        return -1;
38551                :    memcpy (name, filter, len);
38552                :    name[len] = '\0';
38553                :    if (filterNames)
38554                :        names = xrealloc (filterNames, (nfilterNames + 1) * sizeof (char *));
38555                :    else
38556                :        names = xalloc (sizeof (char *));
38557                :    if (!names)
38558                :    {
38559                :        xfree (name);
38560                :        return -1;
38561                :    }
38562                :    filterNames = names;
38563                :    i = nfilterNames++;
38564                :    filterNames[i] = name;
38565                :    return i;
38566                :}
38567                :
38568                :static Bool
38569                :PictureSetDefaultIds (void)
38570                :{
38571                :    /* careful here -- this list must match the #define values */
38572                :
38573                :    if (PictureGetFilterId (FilterNearest, -1, TRUE) != PictFilterNearest)
38574                :        return FALSE;
38575                :    if (PictureGetFilterId (FilterBilinear, -1, TRUE) != PictFilterBilinear)
38576                :        return FALSE;
38577                :
38578                :    if (PictureGetFilterId (FilterFast, -1, TRUE) != PictFilterFast)
38579                :        return FALSE;
38580                :    if (PictureGetFilterId (FilterGood, -1, TRUE) != PictFilterGood)
38581                :        return FALSE;
38582                :    if (PictureGetFilterId (FilterBest, -1, TRUE) != PictFilterBest)
38583                :        return FALSE;
38584                :
38585                :    if (PictureGetFilterId (FilterConvolution, -1, TRUE) != PictFilterConvolution)
38586                :        return FALSE;
38587                :    return TRUE;
38588                :}
38589                :
38590                :char *
38591                :PictureGetFilterName (int id)
38592                :{
38593                :    if (0 <= id && id < nfilterNames)
38594                :        return filterNames[id];
38595                :    else
38596                :        return 0;
38597                :}
38598                :
38599                :static void
38600                :PictureFreeFilterIds (void)
38601                :{
38602                :    int     i;
38603                :
38604                :    for (i = 0; i < nfilterNames; i++)
38605                :        xfree (filterNames[i]);
38606                :    xfree (filterNames);
38607                :    nfilterNames = 0;
38608                :    filterNames = 0;
38609                :}
38610                :
38611                :_X_EXPORT int
38612                :PictureAddFilter (ScreenPtr                         pScreen,
38613                :                  char                              *filter,
38614                :                  PictFilterValidateParamsProcPtr   ValidateParams)
38615                :{
38616                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
38617                :    int                 id = PictureGetFilterId (filter, -1,  TRUE);
38618                :    int                 i;
38619                :    PictFilterPtr       filters;
38620                :
38621                :    if (id < 0)
38622                :        return -1;
38623                :    /*
38624                :     * It's an error to attempt to reregister a filter
38625                :     */
38626                :    for (i = 0; i < ps->nfilters; i++)
38627                :        if (ps->filters[i].id == id)
38628                :            return -1;
38629                :    if (ps->filters)
38630                :        filters = xrealloc (ps->filters, (ps->nfilters + 1) * sizeof (PictFilterRec));
38631                :    else
38632                :        filters = xalloc (sizeof (PictFilterRec));
38633                :    if (!filters)
38634                :        return -1;
38635                :    ps->filters = filters;
38636                :    i = ps->nfilters++;
38637                :    ps->filters[i].name = PictureGetFilterName (id);
38638                :    ps->filters[i].id = id;
38639                :    ps->filters[i].ValidateParams = ValidateParams;
38640                :    return id;
38641                :}
38642                :
38643                :_X_EXPORT Bool
38644                :PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias)
38645                :{
38646                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
38647                :    int                 filter_id = PictureGetFilterId (filter, -1, FALSE);
38648                :    int                 alias_id = PictureGetFilterId (alias, -1, TRUE);
38649                :    int                 i;
38650                :
38651                :    if (filter_id < 0 || alias_id < 0)
38652                :        return FALSE;
38653                :    for (i = 0; i < ps->nfilterAliases; i++)
38654                :        if (ps->filterAliases[i].alias_id == alias_id)
38655                :            break;
38656                :    if (i == ps->nfilterAliases)
38657                :    {
38658                :        PictFilterAliasPtr  aliases;
38659                :
38660                :        if (ps->filterAliases)
38661                :            aliases = xrealloc (ps->filterAliases,
38662                :                                (ps->nfilterAliases + 1) *
38663                :                                sizeof (PictFilterAliasRec));
38664                :        else
38665                :            aliases = xalloc (sizeof (PictFilterAliasRec));
38666                :        if (!aliases)
38667                :            return FALSE;
38668                :        ps->filterAliases = aliases;
38669                :        ps->filterAliases[i].alias = PictureGetFilterName (alias_id);
38670                :        ps->filterAliases[i].alias_id = alias_id;
38671                :        ps->nfilterAliases++;
38672                :    }
38673                :    ps->filterAliases[i].filter_id = filter_id;
38674                :    return TRUE;
38675                :}
38676                :
38677                :PictFilterPtr
38678                :PictureFindFilter (ScreenPtr pScreen, char *name, int len)
38679      2  0.0022 :{ /* PictureFindFilter total:      8  0.0087 */
38680      1  0.0011 :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
38681                :    int                 id = PictureGetFilterId (name, len, FALSE);
38682                :    int                 i;
38683                :
38684                :    if (id < 0)
38685                :        return 0;
38686                :    /* Check for an alias, allow them to recurse */
38687                :    for (i = 0; i < ps->nfilterAliases; i++)
38688      4  0.0044 :        if (ps->filterAliases[i].alias_id == id)
38689                :        {
38690                :            id = ps->filterAliases[i].filter_id;
38691                :            i = 0;
38692                :        }
38693                :    /* find the filter */
38694                :    for (i = 0; i < ps->nfilters; i++)
38695                :        if (ps->filters[i].id == id)
38696                :            return &ps->filters[i];
38697                :    return 0;
38698      1  0.0011 :}
38699                :
38700                :static Bool
38701                :convolutionFilterValidateParams (PicturePtr pPicture,
38702                :                                 int       filter,
38703                :                                 xFixed    *params,
38704                :                                 int       nparams)
38705                :{
38706                :    if (nparams < 3)
38707                :        return FALSE;
38708                :
38709                :    if (xFixedFrac (params[0]) || xFixedFrac (params[1]))
38710                :        return FALSE;
38711                :
38712                :    nparams -= 2;
38713                :    if ((xFixedToInt (params[0]) * xFixedToInt (params[1])) > nparams)
38714                :        return FALSE;
38715                :
38716                :    return TRUE;
38717                :}
38718                :
38719                :
38720                :Bool
38721                :PictureSetDefaultFilters (ScreenPtr pScreen)
38722                :{
38723                :    if (!filterNames)
38724                :        if (!PictureSetDefaultIds ())
38725                :            return FALSE;
38726                :    if (PictureAddFilter (pScreen, FilterNearest, 0) < 0)
38727                :        return FALSE;
38728                :    if (PictureAddFilter (pScreen, FilterBilinear, 0) < 0)
38729                :        return FALSE;
38730                :
38731                :    if (!PictureSetFilterAlias (pScreen, FilterNearest, FilterFast))
38732                :        return FALSE;
38733                :    if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterGood))
38734                :        return FALSE;
38735                :    if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterBest))
38736                :        return FALSE;
38737                :
38738                :    if (PictureAddFilter (pScreen, FilterConvolution, convolutionFilterValidateParams) < 0)
38739                :        return FALSE;
38740                :
38741                :    return TRUE;
38742                :}
38743                :
38744                :void
38745                :PictureResetFilters (ScreenPtr pScreen)
38746                :{
38747                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
38748                :
38749                :    xfree (ps->filters);
38750                :    xfree (ps->filterAliases);
38751                :    PictureFreeFilterIds ();
38752                :}
38753                :
38754                :int
38755                :SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams)
38756                :{ /* SetPictureFilter total:     10  0.0109 */
38757                :    PictFilterPtr       pFilter;
38758                :    xFixed              *new_params;
38759                :    int                 i, s, result;
38760                :
38761      3  0.0033 :    pFilter = PictureFindFilter (screenInfo.screens[0], name, len);
38762                :
38763                :    if (pPicture->pDrawable == NULL) {
38764                :        /* For source pictures, the picture isn't tied to a screen.  So, ensure
38765                :         * that all screens can handle a filter we set for the picture.
38766                :         */
38767                :        for (s = 0; s < screenInfo.numScreens; s++) {
38768                :            if (PictureFindFilter (screenInfo.screens[s], name, len)->id !=
38769                :                pFilter->id)
38770                :            {
38771                :                return BadMatch;
38772                :            }
38773                :        }
38774                :    }
38775                :
38776                :    if (!pFilter)
38777                :        return BadName;
38778                :    if (pFilter->ValidateParams)
38779                :    {
38780                :        if (!(*pFilter->ValidateParams) (pPicture, pFilter->id, params, nparams))
38781                :            return BadMatch;
38782                :    }
38783                :    else if (nparams)
38784                :        return BadMatch;
38785                :
38786      5  0.0054 :    if (nparams != pPicture->filter_nparams)
38787                :    {
38788                :        new_params = xalloc (nparams * sizeof (xFixed));
38789                :        if (!new_params)
38790                :            return BadAlloc;
38791                :        xfree (pPicture->filter_params);
38792                :        pPicture->filter_params = new_params;
38793                :        pPicture->filter_nparams = nparams;
38794                :    }
38795                :    for (i = 0; i < nparams; i++)
38796                :        pPicture->filter_params[i] = params[i];
38797                :    pPicture->filter = pFilter->id;
38798                :
38799                :    if (pPicture->pDrawable) {
38800                :        ScreenPtr pScreen = pPicture->pDrawable->pScreen;
38801                :        PictureScreenPtr ps = GetPictureScreen(pScreen);
38802                :
38803      1  0.0011 :        result = (*ps->ChangePictureFilter) (pPicture, pPicture->filter,
38804                :                                             params, nparams);
38805                :        return result;
38806                :    }
38807                :    return Success;
38808      1  0.0011 :}
38809 /* 
38810  * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbgc.c"
38811  * 
38812  *     34  0.0370
38813  */
38814
38815
38816                :/*
38817                : * Copyright Â© 1998 Keith Packard
38818                : *
38819                : * Permission to use, copy, modify, distribute, and sell this software and its
38820                : * documentation for any purpose is hereby granted without fee, provided that
38821                : * the above copyright notice appear in all copies and that both that
38822                : * copyright notice and this permission notice appear in supporting
38823                : * documentation, and that the name of Keith Packard not be used in
38824                : * advertising or publicity pertaining to distribution of the software without
38825                : * specific, written prior permission.  Keith Packard makes no
38826                : * representations about the suitability of this software for any purpose.  It
38827                : * is provided "as is" without express or implied warranty.
38828                : *
38829                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
38830                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
38831                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
38832                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
38833                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38834                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
38835                : * PERFORMANCE OF THIS SOFTWARE.
38836                : */
38837                :
38838                :#ifdef HAVE_DIX_CONFIG_H
38839                :#include <dix-config.h>
38840                :#endif
38841                :
38842                :#include <stdlib.h>
38843                :
38844                :#include "fb.h"
38845                :
38846                :const GCFuncs fbGCFuncs = {
38847                :    fbValidateGC,
38848                :    miChangeGC,
38849                :    miCopyGC,
38850                :    miDestroyGC,
38851                :    miChangeClip,
38852                :    miDestroyClip,
38853                :    miCopyClip,
38854                :};
38855                :
38856                :const GCOps     fbGCOps = {
38857                :    fbFillSpans,
38858                :    fbSetSpans,
38859                :    fbPutImage,
38860                :    fbCopyArea,
38861                :    fbCopyPlane,
38862                :    fbPolyPoint,
38863                :    fbPolyLine,
38864                :    fbPolySegment,
38865                :    fbPolyRectangle,
38866                :    fbPolyArc,
38867                :    miFillPolygon,
38868                :    fbPolyFillRect,
38869                :    fbPolyFillArc,
38870                :    miPolyText8,
38871                :    miPolyText16,
38872                :    miImageText8,
38873                :    miImageText16,
38874                :    fbImageGlyphBlt,
38875                :    fbPolyGlyphBlt,
38876                :    fbPushPixels
38877                :};
38878                :
38879                :Bool
38880                :fbCreateGC(GCPtr pGC)
38881                :{
38882                :    pGC->clientClip = NULL;
38883                :    pGC->clientClipType = CT_NONE;
38884                :
38885                :    pGC->ops = (GCOps *) &fbGCOps;
38886                :    pGC->funcs = (GCFuncs *) &fbGCFuncs;
38887                :
38888                :    /* fb wants to translate before scan conversion */
38889                :    pGC->miTranslate = 1;
38890                :
38891                :    fbGetRotatedPixmap(pGC) = 0;
38892                :    fbGetExpose(pGC) = 1;
38893                :    fbGetFreeCompClip(pGC) = 0;
38894                :    fbGetCompositeClip(pGC) = 0;
38895                :    fbGetGCPrivate(pGC)->bpp = BitsPerPixel (pGC->depth);
38896                :    return TRUE;
38897                :}
38898                :
38899                :/*
38900                : * Pad pixmap to FB_UNIT bits wide
38901                : */
38902                :void
38903                :fbPadPixmap (PixmapPtr pPixmap)
38904                :{
38905                :    int     width;
38906                :    FbBits  *bits;
38907                :    FbBits  b;
38908                :    FbBits  mask;
38909                :    int     height;
38910                :    int     w;
38911                :    int     stride;
38912                :    int     bpp;
38913                :    int     xOff, yOff;
38914                :
38915                :    fbGetDrawable (&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
38916                :
38917                :    width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
38918                :    height = pPixmap->drawable.height;
38919                :    mask = FbBitsMask (0, width);
38920                :    while (height--)
38921                :    {
38922                :        b = READ(bits) & mask;
38923                :        w = width;
38924                :        while (w < FB_UNIT)
38925                :        {
38926                :            b = b | FbScrRight(b, w);
38927                :            w <<= 1;
38928                :        }
38929                :        WRITE(bits, b);
38930                :        bits += stride;
38931                :    }
38932                :
38933                :    fbFinishAccess (&pPixmap->drawable);
38934                :}
38935                :
38936                :/*
38937                : * Verify that 'bits' repeats every 'len' bits
38938                : */
38939                :static Bool
38940                :fbBitsRepeat (FbBits bits, int len, int width)
38941                :{
38942                :    FbBits  mask = FbBitsMask(0, len);
38943                :    FbBits  orig = bits & mask;
38944                :    int     i;
38945                :    
38946                :    if (width > FB_UNIT)
38947                :        width = FB_UNIT;
38948                :    for (i = 0; i < width / len; i++)
38949                :    {
38950                :        if ((bits & mask) != orig)
38951                :            return FALSE;
38952                :        bits = FbScrLeft(bits,len);
38953                :    }
38954                :    return TRUE;
38955                :}
38956                :
38957                :/*
38958                : * Check whether an entire bitmap line is a repetition of
38959                : * the first 'len' bits
38960                : */
38961                :static Bool
38962                :fbLineRepeat (FbBits *bits, int len, int width)
38963                :{
38964                :    FbBits  first = bits[0];
38965                :    
38966                :    if (!fbBitsRepeat (first, len, width))
38967                :        return FALSE;
38968                :    width = (width + FB_UNIT-1) >> FB_SHIFT;
38969                :    bits++;
38970                :    while (--width)
38971                :        if (READ(bits) != first)
38972                :            return FALSE;
38973                :    return TRUE;
38974                :}
38975                :
38976                :/*
38977                : * The even stipple code wants the first FB_UNIT/bpp bits on
38978                : * each scanline to represent the entire stipple
38979                : */
38980                :static Bool
38981                :fbCanEvenStipple (PixmapPtr pStipple, int bpp)
38982                :{
38983                :    int     len = FB_UNIT / bpp;
38984                :    FbBits  *bits;
38985                :    int     stride;
38986                :    int     stip_bpp;
38987                :    int     stipXoff, stipYoff;
38988                :    int     h;
38989                :
38990                :    /* can't even stipple 24bpp drawables */
38991                :    if ((bpp & (bpp-1)) != 0)
38992                :        return FALSE;
38993                :    /* make sure the stipple width is a multiple of the even stipple width */
38994                :    if (pStipple->drawable.width % len != 0)
38995                :        return FALSE;
38996                :    fbGetDrawable (&pStipple->drawable, bits, stride, stip_bpp, stipXoff, stipYoff);
38997                :    h = pStipple->drawable.height;
38998                :    /* check to see that the stipple repeats horizontally */
38999                :    while (h--)
39000                :    {
39001                :        if (!fbLineRepeat (bits, len, pStipple->drawable.width)) {
39002                :            fbFinishAccess (&pStipple->drawable);
39003                :            return FALSE;
39004                :        }
39005                :        bits += stride;
39006                :    }
39007                :    fbFinishAccess (&pStipple->drawable);
39008                :    return TRUE;
39009                :}
39010                :
39011                :void
39012                :fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
39013      2  0.0022 :{ /* fbValidateGC total:     34  0.0370 */
39014                :    FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
39015                :    FbBits      mask;
39016                :
39017      1  0.0011 :    pGC->lastWinOrg.x = pDrawable->x;
39018                :    pGC->lastWinOrg.y = pDrawable->y;
39019                :
39020                :    /*
39021                :     * if the client clip is different or moved OR the subwindowMode has
39022                :     * changed OR the window's clip has changed since the last validation
39023                :     * we need to recompute the composite clip 
39024                :     */
39025                :
39026                :    if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
39027                :        (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
39028                :        )
39029                :    {
39030                :        miComputeCompositeClip (pGC, pDrawable);
39031      1  0.0011 :        pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1;
39032                :    }
39033                :    
39034                :#ifdef FB_24_32BIT    
39035                :    if (pPriv->bpp != pDrawable->bitsPerPixel)
39036                :    {
39037                :        changes |= GCStipple|GCForeground|GCBackground|GCPlaneMask;
39038                :        pPriv->bpp = pDrawable->bitsPerPixel;
39039                :    }
39040                :    if ((changes & GCTile) && fbGetRotatedPixmap(pGC))
39041                :    {
39042                :        (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
39043                :        fbGetRotatedPixmap(pGC) = 0;
39044                :    }
39045                :        
39046                :    if (pGC->fillStyle == FillTiled)
39047                :    {
39048                :        PixmapPtr       pOldTile, pNewTile;
39049                :
39050                :        pOldTile = pGC->tile.pixmap;
39051                :        if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
39052                :        {
39053                :            pNewTile = fbGetRotatedPixmap(pGC);
39054                :            if (!pNewTile || pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
39055                :            {
39056                :                if (pNewTile)
39057                :                    (*pGC->pScreen->DestroyPixmap) (pNewTile);
39058                :                pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel);
39059                :            }
39060                :            if (pNewTile)
39061                :            {
39062                :                fbGetRotatedPixmap(pGC) = pOldTile;
39063                :                pGC->tile.pixmap = pNewTile;
39064                :                changes |= GCTile;
39065                :            }
39066                :        }
39067                :    }
39068                :#endif
39069                :    if (changes & GCTile)
39070                :    {
39071                :        if (!pGC->tileIsPixel && 
39072                :            FbEvenTile (pGC->tile.pixmap->drawable.width *
39073                :                        pDrawable->bitsPerPixel))
39074                :            fbPadPixmap (pGC->tile.pixmap);
39075                :    }
39076      1  0.0011 :    if (changes & GCStipple)
39077                :    {
39078                :        pPriv->evenStipple = FALSE;
39079                :
39080      3  0.0033 :        if (pGC->stipple) {
39081                :
39082                :            /* can we do an even stipple ?? */
39083                :            if (FbEvenStip (pGC->stipple->drawable.width,
39084                :                                                pDrawable->bitsPerPixel) &&
39085                :               (fbCanEvenStipple (pGC->stipple, pDrawable->bitsPerPixel)))
39086                :                pPriv->evenStipple = TRUE;
39087                :
39088                :            if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel < FB_UNIT)
39089                :                fbPadPixmap (pGC->stipple);
39090                :        }
39091                :    }
39092                :    /*
39093                :     * Recompute reduced rop values
39094                :     */
39095      3  0.0033 :    if (changes & (GCForeground|GCBackground|GCPlaneMask|GCFunction))
39096                :    {
39097                :        int     s;
39098                :        FbBits  depthMask;
39099                :        
39100      3  0.0033 :        mask = FbFullMask(pDrawable->bitsPerPixel);
39101      2  0.0022 :        depthMask = FbFullMask(pDrawable->depth);
39102                :        
39103      1  0.0011 :        pPriv->fg = pGC->fgPixel & mask;
39104      1  0.0011 :        pPriv->bg = pGC->bgPixel & mask;
39105                :        
39106                :        if ((pGC->planemask & depthMask) == depthMask)
39107      2  0.0022 :            pPriv->pm = mask;
39108                :        else
39109                :            pPriv->pm = pGC->planemask & mask;    
39110                :        
39111      1  0.0011 :        s = pDrawable->bitsPerPixel;
39112                :        while (s < FB_UNIT)
39113                :        {
39114                :            pPriv->fg |= pPriv->fg << s;
39115                :            pPriv->bg |= pPriv->bg << s;
39116                :            pPriv->pm |= pPriv->pm << s;
39117                :            s <<= 1;
39118                :        }
39119      7  0.0076 :        pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm);
39120      1  0.0011 :        pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm);
39121                :        pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm);
39122      3  0.0033 :        pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm);
39123                :    }
39124                :    if (changes & GCDashList)
39125                :    {
39126                :        unsigned short  n = pGC->numInDashList;
39127                :        unsigned char   *dash = pGC->dash;
39128                :        unsigned int    dashLength = 0;
39129                :
39130                :        while (n--)
39131      1  0.0011 :            dashLength += (unsigned int ) *dash++;
39132                :        pPriv->dashLength = dashLength;
39133                :    }
39134      1  0.0011 :}
39135 /* 
39136  * Total samples for file : "pixman-mmx.c"
39137  * 
39138  *     33  0.0359
39139  */
39140
39141 <credited to line zero>     33  0.0359 :
39142  /* __i686.get_pc_thunk.bx total:     15  0.0163 */
39143  /* __divdi3 total:     18  0.0196 */
39144 /* 
39145  * Total samples for file : "/home/cworth/src/xorg/xserver/mi/migc.c"
39146  * 
39147  *     31  0.0338
39148  */
39149
39150
39151                :/*
39152                :
39153                :Copyright 1993, 1998  The Open Group
39154                :
39155                :Permission to use, copy, modify, distribute, and sell this software and its
39156                :documentation for any purpose is hereby granted without fee, provided that
39157                :the above copyright notice appear in all copies and that both that
39158                :copyright notice and this permission notice appear in supporting
39159                :documentation.
39160                :
39161                :The above copyright notice and this permission notice shall be included
39162                :in all copies or substantial portions of the Software.
39163                :
39164                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
39165                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39166                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
39167                :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
39168                :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
39169                :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
39170                :OTHER DEALINGS IN THE SOFTWARE.
39171                :
39172                :Except as contained in this notice, the name of The Open Group shall
39173                :not be used in advertising or otherwise to promote the sale, use or
39174                :other dealings in this Software without prior written authorization
39175                :from The Open Group.
39176                :
39177                :*/
39178                :
39179                :
39180                :#ifdef HAVE_DIX_CONFIG_H
39181                :#include <dix-config.h>
39182                :#endif
39183                :
39184                :#include "scrnintstr.h"
39185                :#include "gcstruct.h"
39186                :#include "pixmapstr.h"
39187                :#include "windowstr.h"
39188                :#include "migc.h"
39189                :
39190                :/* ARGSUSED */
39191                :_X_EXPORT void
39192                :miChangeGC(pGC, mask)
39193                :    GCPtr           pGC;
39194                :    unsigned long   mask;
39195      6  0.0065 :{ /* miChangeGC total:      6  0.0065 */
39196                :    return;
39197                :}
39198                :
39199                :_X_EXPORT void
39200                :miDestroyGC(pGC)
39201                :    GCPtr           pGC;
39202                :{
39203                :    if (pGC->pRotatedPixmap)
39204                :        (*pGC->pScreen->DestroyPixmap) (pGC->pRotatedPixmap);
39205                :    if (pGC->freeCompClip)
39206                :        REGION_DESTROY(pGC->pScreen, pGC->pCompositeClip);
39207                :    miDestroyGCOps(pGC->ops);
39208                :}
39209                :
39210                :/*
39211                : * create a private op array for a gc
39212                : */
39213                :
39214                :_X_EXPORT GCOpsPtr
39215                :miCreateGCOps(prototype)
39216                :    GCOpsPtr        prototype;
39217                :{
39218                :    GCOpsPtr        ret;
39219                :
39220                :     /* XXX */ Must_have_memory = TRUE;
39221                :    ret = (GCOpsPtr) xalloc(sizeof(GCOps));
39222                :     /* XXX */ Must_have_memory = FALSE;
39223                :    if (!ret)
39224                :        return 0;
39225                :    *ret = *prototype;
39226                :    ret->devPrivate.val = 1;
39227                :    return ret;
39228                :}
39229                :
39230                :_X_EXPORT void
39231                :miDestroyGCOps(ops)
39232                :    GCOpsPtr        ops;
39233                :{
39234                :    if (ops->devPrivate.val)
39235                :        xfree(ops);
39236                :}
39237                :
39238                :
39239                :_X_EXPORT void
39240                :miDestroyClip(pGC)
39241                :    GCPtr           pGC;
39242      1  0.0011 :{ /* miDestroyClip total:      1  0.0011 */
39243                :    if (pGC->clientClipType == CT_NONE)
39244                :        return;
39245                :    else if (pGC->clientClipType == CT_PIXMAP)
39246                :    {
39247                :        (*pGC->pScreen->DestroyPixmap) ((PixmapPtr) (pGC->clientClip));
39248                :    }
39249                :    else
39250                :    {
39251                :        /*
39252                :         * we know we'll never have a list of rectangles, since ChangeClip
39253                :         * immediately turns them into a region
39254                :         */
39255                :        REGION_DESTROY(pGC->pScreen, pGC->clientClip);
39256                :    }
39257                :    pGC->clientClip = NULL;
39258                :    pGC->clientClipType = CT_NONE;
39259                :}
39260                :
39261                :_X_EXPORT void
39262                :miChangeClip(pGC, type, pvalue, nrects)
39263                :    GCPtr           pGC;
39264                :    int             type;
39265                :    pointer         pvalue;
39266                :    int             nrects;
39267      3  0.0033 :{ /* miChangeClip total:      4  0.0044 */
39268                :    (*pGC->funcs->DestroyClip) (pGC);
39269                :    if (type == CT_PIXMAP)
39270                :    {
39271                :        /* convert the pixmap to a region */
39272                :        pGC->clientClip = (pointer) BITMAP_TO_REGION(pGC->pScreen,
39273                :                                                        (PixmapPtr) pvalue);
39274                :        (*pGC->pScreen->DestroyPixmap) (pvalue);
39275                :    }
39276                :    else if (type == CT_REGION)
39277                :    {
39278                :        /* stuff the region in the GC */
39279                :        pGC->clientClip = pvalue;
39280                :    }
39281      1  0.0011 :    else if (type != CT_NONE)
39282                :    {
39283                :        pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nrects,
39284                :                                                      (xRectangle *) pvalue,
39285                :                                                                    type);
39286                :        xfree(pvalue);
39287                :    }
39288                :    pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION : CT_NONE;
39289                :    pGC->stateChanges |= GCClipMask;
39290                :}
39291                :
39292                :_X_EXPORT void
39293                :miCopyClip(pgcDst, pgcSrc)
39294                :    GCPtr           pgcDst, pgcSrc;
39295                :{
39296                :    RegionPtr       prgnNew;
39297                :
39298                :    switch (pgcSrc->clientClipType)
39299                :    {
39300                :      case CT_PIXMAP:
39301                :        ((PixmapPtr) pgcSrc->clientClip)->refcnt++;
39302                :        /* Fall through !! */
39303                :      case CT_NONE:
39304                :        (*pgcDst->funcs->ChangeClip) (pgcDst, (int) pgcSrc->clientClipType,
39305                :                                   pgcSrc->clientClip, 0);
39306                :        break;
39307                :      case CT_REGION:
39308                :        prgnNew = REGION_CREATE(pgcSrc->pScreen, NULL, 1);
39309                :        REGION_COPY(pgcDst->pScreen, prgnNew,
39310                :                                        (RegionPtr) (pgcSrc->clientClip));
39311                :        (*pgcDst->funcs->ChangeClip) (pgcDst, CT_REGION, (pointer) prgnNew, 0);
39312                :        break;
39313                :    }
39314                :}
39315                :
39316                :/* ARGSUSED */
39317                :_X_EXPORT void
39318                :miCopyGC(pGCSrc, changes, pGCDst)
39319                :    GCPtr           pGCSrc;
39320                :    unsigned long   changes;
39321                :    GCPtr           pGCDst;
39322                :{
39323                :    return;
39324                :}
39325                :
39326                :_X_EXPORT void
39327                :miComputeCompositeClip(pGC, pDrawable)
39328                :    GCPtr           pGC;
39329                :    DrawablePtr     pDrawable;
39330      4  0.0044 :{ /* miComputeCompositeClip total:     20  0.0218 */
39331                :    ScreenPtr       pScreen;
39332                :
39333                :    /* This prevents warnings about pScreen not being used. */
39334                :    pGC->pScreen = pScreen = pGC->pScreen;
39335                :
39336                :    if (pDrawable->type == DRAWABLE_WINDOW)
39337                :    {
39338                :        WindowPtr       pWin = (WindowPtr) pDrawable;
39339                :        RegionPtr       pregWin;
39340                :        Bool            freeTmpClip, freeCompClip;
39341                :
39342                :        if (pGC->subWindowMode == IncludeInferiors)
39343                :        {
39344                :            pregWin = NotClippedByChildren(pWin);
39345                :            freeTmpClip = TRUE;
39346                :        }
39347                :        else
39348                :        {
39349                :            pregWin = &pWin->clipList;
39350                :            freeTmpClip = FALSE;
39351                :        }
39352                :        freeCompClip = pGC->freeCompClip;
39353                :
39354                :        /*
39355                :         * if there is no client clip, we can get by with just keeping the
39356                :         * pointer we got, and remembering whether or not should destroy (or
39357                :         * maybe re-use) it later.  this way, we avoid unnecessary copying of
39358                :         * regions.  (this wins especially if many clients clip by children
39359                :         * and have no client clip.)
39360                :         */
39361                :        if (pGC->clientClipType == CT_NONE)
39362                :        {
39363                :            if (freeCompClip)
39364                :                REGION_DESTROY(pScreen, pGC->pCompositeClip);
39365                :            pGC->pCompositeClip = pregWin;
39366                :            pGC->freeCompClip = freeTmpClip;
39367                :        }
39368                :        else
39369                :        {
39370                :            /*
39371                :             * we need one 'real' region to put into the composite clip. if
39372                :             * pregWin the current composite clip are real, we can get rid of
39373                :             * one. if pregWin is real and the current composite clip isn't,
39374                :             * use pregWin for the composite clip. if the current composite
39375                :             * clip is real and pregWin isn't, use the current composite
39376                :             * clip. if neither is real, create a new region.
39377                :             */
39378                :
39379                :            REGION_TRANSLATE(pScreen, pGC->clientClip,
39380                :                                         pDrawable->x + pGC->clipOrg.x,
39381                :                                         pDrawable->y + pGC->clipOrg.y);
39382                :
39383                :            if (freeCompClip)
39384                :            {
39385                :                REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
39386                :                                            pregWin, pGC->clientClip);
39387                :                if (freeTmpClip)
39388                :                    REGION_DESTROY(pScreen, pregWin);
39389                :            }
39390                :            else if (freeTmpClip)
39391                :            {
39392                :                REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip);
39393                :                pGC->pCompositeClip = pregWin;
39394                :            }
39395                :            else
39396                :            {
39397      1  0.0011 :                pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
39398                :                REGION_INTERSECT(pScreen, pGC->pCompositeClip,
39399                :                                       pregWin, pGC->clientClip);
39400                :            }
39401                :            pGC->freeCompClip = TRUE;
39402                :            REGION_TRANSLATE(pScreen, pGC->clientClip,
39403                :                                         -(pDrawable->x + pGC->clipOrg.x),
39404                :                                         -(pDrawable->y + pGC->clipOrg.y));
39405                :        }
39406                :    }   /* end of composite clip for a window */
39407                :    else
39408                :    {
39409                :        BoxRec          pixbounds;
39410                :
39411                :        /* XXX should we translate by drawable.x/y here ? */
39412                :        /* If you want pixmaps in offscreen memory, yes */
39413      3  0.0033 :        pixbounds.x1 = pDrawable->x;
39414      1  0.0011 :        pixbounds.y1 = pDrawable->y;
39415                :        pixbounds.x2 = pDrawable->x + pDrawable->width;
39416                :        pixbounds.y2 = pDrawable->y + pDrawable->height;
39417                :
39418      1  0.0011 :        if (pGC->freeCompClip)
39419                :        {
39420      8  0.0087 :            REGION_RESET(pScreen, pGC->pCompositeClip, &pixbounds);
39421                :        }
39422                :        else
39423                :        {
39424                :            pGC->freeCompClip = TRUE;
39425                :            pGC->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1);
39426                :        }
39427                :
39428                :        if (pGC->clientClipType == CT_REGION)
39429                :        {
39430                :            if(pDrawable->x || pDrawable->y) {
39431                :                REGION_TRANSLATE(pScreen, pGC->clientClip,
39432                :                                          pDrawable->x + pGC->clipOrg.x, 
39433                :                                          pDrawable->y + pGC->clipOrg.y);
39434                :                REGION_INTERSECT(pScreen, pGC->pCompositeClip,
39435                :                                pGC->pCompositeClip, pGC->clientClip);
39436                :                REGION_TRANSLATE(pScreen, pGC->clientClip,
39437                :                                          -(pDrawable->x + pGC->clipOrg.x), 
39438                :                                          -(pDrawable->y + pGC->clipOrg.y));
39439                :            } else {
39440      1  0.0011 :                REGION_TRANSLATE(pScreen, pGC->pCompositeClip,
39441                :                                         -pGC->clipOrg.x, -pGC->clipOrg.y);
39442                :                REGION_INTERSECT(pScreen, pGC->pCompositeClip,
39443                :                                pGC->pCompositeClip, pGC->clientClip);
39444                :                REGION_TRANSLATE(pScreen, pGC->pCompositeClip,
39445                :                                         pGC->clipOrg.x, pGC->clipOrg.y);
39446                :            }
39447                :        }
39448                :    }   /* end of composite clip for pixmap */
39449      1  0.0011 :} /* end miComputeCompositeClip */
39450 /* 
39451  * Total samples for file : "/home/cworth/src/xorg/xserver/Xext/xvmain.c"
39452  * 
39453  *     26  0.0283
39454  */
39455
39456
39457                :/***********************************************************
39458                :Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
39459                :and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
39460                :
39461                :                        All Rights Reserved
39462                :
39463                :Permission to use, copy, modify, and distribute this software and its 
39464                :documentation for any purpose and without fee is hereby granted, 
39465                :provided that the above copyright notice appear in all copies and that
39466                :both that copyright notice and this permission notice appear in 
39467                :supporting documentation, and that the names of Digital or MIT not be
39468                :used in advertising or publicity pertaining to distribution of the
39469                :software without specific, written prior permission.  
39470                :
39471                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39472                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39473                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
39474                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39475                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
39476                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
39477                :SOFTWARE.
39478                :
39479                :******************************************************************/
39480                :
39481                :/*
39482                :** File: 
39483                :**
39484                :**   xvmain.c --- Xv server extension main device independent module.
39485                :**   
39486                :** Author: 
39487                :**
39488                :**   David Carver (Digital Workstation Engineering/Project Athena)
39489                :**
39490                :** Revisions:
39491                :**
39492                :**   04.09.91 Carver
39493                :**     - change: stop video always generates an event even when video
39494                :**       wasn't active
39495                :**
39496                :**   29.08.91 Carver
39497                :**     - change: unrealizing windows no longer preempts video
39498                :**
39499                :**   11.06.91 Carver
39500                :**     - changed SetPortControl to SetPortAttribute
39501                :**     - changed GetPortControl to GetPortAttribute
39502                :**     - changed QueryBestSize
39503                :**
39504                :**   28.05.91 Carver
39505                :**     - fixed Put and Get requests to not preempt operations to same drawable
39506                :**
39507                :**   15.05.91 Carver
39508                :**     - version 2.0 upgrade
39509                :**
39510                :**   19.03.91 Carver
39511                :**     - fixed Put and Get requests to honor grabbed ports.
39512                :**     - fixed Video requests to update di structure with new drawable, and
39513                :**       client after calling ddx.
39514                :**
39515                :**   24.01.91 Carver
39516                :**     - version 1.4 upgrade
39517                :**       
39518                :** Notes:
39519                :**
39520                :**   Port structures reference client structures in a two different
39521                :**   ways: when grabs, or video is active.  Each reference is encoded
39522                :**   as fake client resources and thus when the client is goes away so
39523                :**   does the reference (it is zeroed).  No other action is taken, so
39524                :**   video doesn't necessarily stop.  It probably will as a result of
39525                :**   other resources going away, but if a client starts video using
39526                :**   none of its own resources, then the video will continue to play
39527                :**   after the client disappears.
39528                :**
39529                :**
39530                :*/
39531                :
39532                :#ifdef HAVE_DIX_CONFIG_H
39533                :#include <dix-config.h>
39534                :#endif
39535                :
39536                :#include <string.h>
39537                :
39538                :#include <X11/X.h>
39539                :#include <X11/Xproto.h>
39540                :#include "misc.h"
39541                :#include "os.h"
39542                :#include "scrnintstr.h"
39543                :#include "windowstr.h"
39544                :#include "pixmapstr.h"
39545                :#include "gc.h"
39546                :#include "extnsionst.h"
39547                :#include "dixstruct.h"
39548                :#include "resource.h"
39549                :#include "opaque.h"
39550                :#include "input.h"
39551                :
39552                :#define GLOBAL
39553                :
39554                :#include <X11/extensions/Xv.h>
39555                :#include <X11/extensions/Xvproto.h>
39556                :#include "xvdix.h"
39557                :
39558                :#ifdef PANORAMIX
39559                :#include "panoramiX.h"
39560                :#include "panoramiXsrv.h"
39561                :#include "xvdisp.h"
39562                :#endif
39563                :
39564                :int  XvScreenIndex = -1;
39565                :unsigned long XvExtensionGeneration = 0;
39566                :unsigned long XvScreenGeneration = 0;
39567                :unsigned long XvResourceGeneration = 0;
39568                :
39569                :int XvReqCode;
39570                :int XvEventBase;
39571                :int XvErrorBase;
39572                :
39573                :unsigned long XvRTPort;
39574                :unsigned long XvRTEncoding;
39575                :unsigned long XvRTGrab;
39576                :unsigned long XvRTVideoNotify;
39577                :unsigned long XvRTVideoNotifyList;
39578                :unsigned long XvRTPortNotify;
39579                :
39580                :
39581                :
39582                :/* EXTERNAL */
39583                :
39584                :extern XID clientErrorValue;
39585                :
39586                :static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
39587                :static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
39588                :static Bool CreateResourceTypes(void);
39589                :
39590                :static Bool XvCloseScreen(int, ScreenPtr);
39591                :static Bool XvDestroyPixmap(PixmapPtr);
39592                :static Bool XvDestroyWindow(WindowPtr);
39593                :static void XvResetProc(ExtensionEntry*);
39594                :static int XvdiDestroyGrab(pointer, XID);
39595                :static int XvdiDestroyEncoding(pointer, XID);
39596                :static int XvdiDestroyVideoNotify(pointer, XID);
39597                :static int XvdiDestroyPortNotify(pointer, XID);
39598                :static int XvdiDestroyVideoNotifyList(pointer, XID);
39599                :static int XvdiDestroyPort(pointer, XID);
39600                :static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
39601                :
39602                :
39603                :
39604                :
39605                :/*
39606                :** XvExtensionInit
39607                :**
39608                :**
39609                :*/
39610                :
39611                :void 
39612                :XvExtensionInit(void)
39613                :{
39614                :  ExtensionEntry *extEntry;
39615                :
39616                :  /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN
39617                :     INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */
39618                :  if (XvScreenGeneration != serverGeneration)
39619                :    {
39620                :      if (!CreateResourceTypes())
39621                :        {
39622                :          ErrorF("XvExtensionInit: Unable to allocate resource types\n");
39623                :          return;
39624                :        }
39625                :      XvScreenIndex = AllocateScreenPrivateIndex ();
39626                :      if (XvScreenIndex < 0)
39627                :        {
39628                :          ErrorF("XvExtensionInit: Unable to allocate screen private index\n");
39629                :          return;
39630                :        }
39631                :#ifdef PANORAMIX
39632                :        XineramaRegisterConnectionBlockCallback(XineramifyXv);
39633                :#endif
39634                :      XvScreenGeneration = serverGeneration;
39635                :    }
39636                :
39637                :  if (XvExtensionGeneration != serverGeneration)
39638                :    {
39639                :      XvExtensionGeneration = serverGeneration;
39640                :
39641                :      extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors, 
39642                :                              ProcXvDispatch, SProcXvDispatch,
39643                :                              XvResetProc, StandardMinorOpcode);
39644                :      if (!extEntry) 
39645                :        {
39646                :          FatalError("XvExtensionInit: AddExtensions failed\n");
39647                :        }
39648                :
39649                :      XvReqCode = extEntry->base;
39650                :      XvEventBase = extEntry->eventBase;
39651                :      XvErrorBase = extEntry->errorBase;
39652                :
39653                :      EventSwapVector[XvEventBase+XvVideoNotify] = 
39654                :        (EventSwapPtr)WriteSwappedVideoNotifyEvent;
39655                :      EventSwapVector[XvEventBase+XvPortNotify] = 
39656                :        (EventSwapPtr)WriteSwappedPortNotifyEvent;
39657                :
39658                :      (void)MakeAtom(XvName, strlen(XvName), xTrue);
39659                :
39660                :    }
39661                :}
39662                :
39663                :static Bool
39664                :CreateResourceTypes(void)
39665                :
39666                :{
39667                :  
39668                :  if (XvResourceGeneration == serverGeneration) return TRUE;
39669                :
39670                :  XvResourceGeneration = serverGeneration;
39671                :
39672                :  if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort)))
39673                :    {
39674                :      ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
39675                :      return FALSE;
39676                :    }
39677                :  
39678                :  if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab)))
39679                :    {
39680                :      ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
39681                :      return FALSE;
39682                :    }
39683                :  
39684                :  if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding)))
39685                :    {
39686                :      ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
39687                :      return FALSE;
39688                :    }
39689                :  
39690                :  if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify)))
39691                :    {
39692                :      ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n");
39693                :      return FALSE;
39694                :    }
39695                :  
39696                :  if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList)))
39697                :    {
39698                :      ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n");
39699                :      return FALSE;
39700                :    }
39701                :
39702                :  if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify)))
39703                :    {
39704                :      ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n");
39705                :      return FALSE;
39706                :    }
39707                :
39708                :  return TRUE;
39709                :
39710                :}
39711                :
39712                :_X_EXPORT int
39713                :XvScreenInit(ScreenPtr pScreen)
39714                :{
39715                :  XvScreenPtr pxvs;
39716                :
39717                :  if (XvScreenGeneration != serverGeneration)
39718                :    {
39719                :      if (!CreateResourceTypes())
39720                :        {
39721                :          ErrorF("XvScreenInit: Unable to allocate resource types\n");
39722                :          return BadAlloc;
39723                :        }
39724                :      XvScreenIndex = AllocateScreenPrivateIndex ();
39725                :      if (XvScreenIndex < 0)
39726                :        {
39727                :          ErrorF("XvScreenInit: Unable to allocate screen private index\n");
39728                :          return BadAlloc;
39729                :        }
39730                :#ifdef PANORAMIX
39731                :        XineramaRegisterConnectionBlockCallback(XineramifyXv);
39732                :#endif
39733                :      XvScreenGeneration = serverGeneration; 
39734                :    }
39735                :
39736                :  if (pScreen->devPrivates[XvScreenIndex].ptr)
39737                :    {
39738                :      ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
39739                :    }
39740                :
39741                :  /* ALLOCATE SCREEN PRIVATE RECORD */
39742                :  
39743                :  pxvs = (XvScreenPtr) xalloc (sizeof (XvScreenRec));
39744                :  if (!pxvs)
39745                :    {
39746                :      ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
39747                :      return BadAlloc;
39748                :    }
39749                :
39750                :  pScreen->devPrivates[XvScreenIndex].ptr = (pointer)pxvs;
39751                :
39752                :  
39753                :  pxvs->DestroyPixmap = pScreen->DestroyPixmap;
39754                :  pxvs->DestroyWindow = pScreen->DestroyWindow;
39755                :  pxvs->CloseScreen = pScreen->CloseScreen;
39756                :  
39757                :  pScreen->DestroyPixmap = XvDestroyPixmap;
39758                :  pScreen->DestroyWindow = XvDestroyWindow;
39759                :  pScreen->CloseScreen = XvCloseScreen;
39760                :
39761                :  return Success;
39762                :}
39763                :
39764                :static Bool
39765                :XvCloseScreen(
39766                :  int ii,
39767                :  ScreenPtr pScreen
39768                :){
39769                :
39770                :  XvScreenPtr pxvs;
39771                :
39772                :  pxvs = (XvScreenPtr) pScreen->devPrivates[XvScreenIndex].ptr;
39773                :
39774                :  pScreen->DestroyPixmap = pxvs->DestroyPixmap;
39775                :  pScreen->DestroyWindow = pxvs->DestroyWindow;
39776                :  pScreen->CloseScreen = pxvs->CloseScreen;
39777                :
39778                :  (* pxvs->ddCloseScreen)(ii, pScreen); 
39779                :
39780                :  xfree(pxvs);
39781                :
39782                :  pScreen->devPrivates[XvScreenIndex].ptr = (pointer)NULL;
39783                :
39784                :  return (*pScreen->CloseScreen)(ii, pScreen);
39785                :
39786                :}
39787                :
39788                :static void
39789                :XvResetProc(ExtensionEntry* extEntry)
39790                :{
39791                :}
39792                :
39793                :_X_EXPORT int
39794                :XvGetScreenIndex(void)
39795                :{
39796                :  return XvScreenIndex;
39797                :}
39798                :
39799                :_X_EXPORT unsigned long
39800                :XvGetRTPort(void)
39801                :{
39802                :  return XvRTPort;
39803                :}
39804                :
39805                :static Bool
39806                :XvDestroyPixmap(PixmapPtr pPix)
39807      4  0.0044 :{ /* XvDestroyPixmap total:     26  0.0283 */
39808                :  Bool status;
39809                :  ScreenPtr pScreen;
39810                :  XvScreenPtr pxvs;
39811                :  XvAdaptorPtr pa;
39812                :  int na;
39813                :  XvPortPtr pp;
39814                :  int np;
39815                :
39816      2  0.0022 :  pScreen = pPix->drawable.pScreen;
39817                :
39818      1  0.0011 :  SCREEN_PROLOGUE(pScreen, DestroyPixmap);
39819                :
39820                :  pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr;
39821                :
39822                :  /* CHECK TO SEE IF THIS PORT IS IN USE */
39823                :
39824                :  pa = pxvs->pAdaptors;
39825      1  0.0011 :  na = pxvs->nAdaptors;
39826      1  0.0011 :  while (na--)
39827                :    {
39828      1  0.0011 :      np = pa->nPorts;
39829      1  0.0011 :      pp = pa->pPorts;
39830                :
39831      3  0.0033 :      while (np--)
39832                :        {
39833      2  0.0022 :          if (pp->pDraw == (DrawablePtr)pPix)
39834                :            {
39835                :              XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
39836                :
39837                :              (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, 
39838                :                                                  pp->pDraw);
39839                :
39840                :              pp->pDraw = (DrawablePtr)NULL;
39841                :              pp->client = (ClientPtr)NULL;
39842      4  0.0044 :              pp->time = currentTime;
39843                :            }
39844      4  0.0044 :          pp++;
39845                :        }
39846                :      pa++;
39847                :    }
39848                :  
39849                :  status = (* pScreen->DestroyPixmap)(pPix);
39850                :
39851      1  0.0011 :  SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
39852                :
39853                :  return status;
39854                :
39855      1  0.0011 :}
39856                :
39857                :static Bool
39858                :XvDestroyWindow(WindowPtr pWin)
39859                :{
39860                :  Bool status;
39861                :  ScreenPtr pScreen;
39862                :  XvScreenPtr pxvs;
39863                :  XvAdaptorPtr pa;
39864                :  int na;
39865                :  XvPortPtr pp;
39866                :  int np;
39867                :
39868                :  pScreen = pWin->drawable.pScreen;
39869                :
39870                :  SCREEN_PROLOGUE(pScreen, DestroyWindow);
39871                :
39872                :  pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr;
39873                :
39874                :  /* CHECK TO SEE IF THIS PORT IS IN USE */
39875                :
39876                :  pa = pxvs->pAdaptors;
39877                :  na = pxvs->nAdaptors;
39878                :  while (na--)
39879                :    {
39880                :      np = pa->nPorts;
39881                :      pp = pa->pPorts;
39882                :
39883                :      while (np--)
39884                :        {
39885                :          if (pp->pDraw == (DrawablePtr)pWin)
39886                :            {
39887                :              XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
39888                :
39889                :              (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, 
39890                :                                                  pp->pDraw);
39891                :
39892                :              pp->pDraw = (DrawablePtr)NULL;
39893                :              pp->client = (ClientPtr)NULL;
39894                :              pp->time = currentTime;
39895                :            }
39896                :          pp++;
39897                :        }
39898                :      pa++;
39899                :    }
39900                :
39901                :  
39902                :  status = (* pScreen->DestroyWindow)(pWin);
39903                :
39904                :  SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
39905                :
39906                :  return status;
39907                :
39908                :}
39909                :
39910                :/* The XvdiVideoStopped procedure is a hook for the device dependent layer.
39911                :   It provides a way for the dd layer to inform the di layer that video has
39912                :   stopped in a port for reasons that the di layer had no control over; note
39913                :   that it doesn't call back into the dd layer */
39914                :
39915                :int
39916                :XvdiVideoStopped(XvPortPtr pPort, int reason)
39917                :{
39918                :  
39919                :  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
39920                :
39921                :  if (!pPort->pDraw) return Success;
39922                :
39923                :  XvdiSendVideoNotify(pPort, pPort->pDraw, reason);
39924                :
39925                :  pPort->pDraw = (DrawablePtr)NULL;
39926                :  pPort->client = (ClientPtr)NULL;
39927                :  pPort->time = currentTime;
39928                :
39929                :  return Success;
39930                :
39931                :}
39932                :
39933                :static int 
39934                :XvdiDestroyPort(pointer pPort, XID id)
39935                :{
39936                :  return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort);
39937                :}
39938                :
39939                :static int
39940                :XvdiDestroyGrab(pointer pGrab, XID id)
39941                :{
39942                :  ((XvGrabPtr)pGrab)->client = (ClientPtr)NULL;
39943                :  return Success;
39944                :}
39945                :
39946                :static int
39947                :XvdiDestroyVideoNotify(pointer pn, XID id)
39948                :{
39949                :  /* JUST CLEAR OUT THE client POINTER FIELD */
39950                :
39951                :  ((XvVideoNotifyPtr)pn)->client = (ClientPtr)NULL;
39952                :  return Success;
39953                :}
39954                :
39955                :static int
39956                :XvdiDestroyPortNotify(pointer pn, XID id)
39957                :{
39958                :  /* JUST CLEAR OUT THE client POINTER FIELD */
39959                :
39960                :  ((XvPortNotifyPtr)pn)->client = (ClientPtr)NULL;
39961                :  return Success;
39962                :}
39963                :
39964                :static int
39965                :XvdiDestroyVideoNotifyList(pointer pn, XID id)
39966                :{
39967                :  XvVideoNotifyPtr npn,cpn;
39968                :
39969                :  /* ACTUALLY DESTROY THE NOTITY LIST */
39970                :
39971                :  cpn = (XvVideoNotifyPtr)pn;
39972                :
39973                :  while (cpn)
39974                :    {
39975                :      npn = cpn->next;
39976                :      if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify);
39977                :      xfree(cpn);
39978                :      cpn = npn;
39979                :    }
39980                :  return Success;
39981                :}
39982                :
39983                :static int
39984                :XvdiDestroyEncoding(pointer value, XID id)
39985                :{
39986                :  return Success;
39987                :}
39988                :
39989                :static int
39990                :XvdiSendVideoNotify(pPort, pDraw, reason)
39991                :
39992                :XvPortPtr pPort;
39993                :DrawablePtr pDraw;
39994                :int reason;
39995                :
39996                :{
39997                :  xvEvent event;
39998                :  XvVideoNotifyPtr pn;
39999                :
40000                :  pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList);
40001                :
40002                :  while (pn) 
40003                :    {
40004                :      if (pn->client)
40005                :        {
40006                :          event.u.u.type = XvEventBase + XvVideoNotify;
40007                :          event.u.u.sequenceNumber = pn->client->sequence;
40008                :          event.u.videoNotify.time = currentTime.milliseconds;
40009                :          event.u.videoNotify.drawable = pDraw->id;
40010                :          event.u.videoNotify.port = pPort->id;
40011                :          event.u.videoNotify.reason = reason;
40012                :          (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask,
40013                :                                 NoEventMask, NullGrab);
40014                :        }
40015                :      pn = pn->next;
40016                :    }
40017                :
40018                :  return Success;
40019                :
40020                :}
40021                :
40022                :
40023                :int
40024                :XvdiSendPortNotify(
40025                :  XvPortPtr pPort,
40026                :  Atom attribute,
40027                :  INT32 value
40028                :){
40029                :  xvEvent event;
40030                :  XvPortNotifyPtr pn;
40031                :
40032                :  pn = pPort->pNotify;
40033                :
40034                :  while (pn) 
40035                :    {
40036                :      if (pn->client)
40037                :        {
40038                :          event.u.u.type = XvEventBase + XvPortNotify;
40039                :          event.u.u.sequenceNumber = pn->client->sequence;
40040                :          event.u.portNotify.time = currentTime.milliseconds;
40041                :          event.u.portNotify.port = pPort->id;
40042                :          event.u.portNotify.attribute = attribute;
40043                :          event.u.portNotify.value = value;
40044                :          (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask,
40045                :                                 NoEventMask, NullGrab);
40046                :        }
40047                :      pn = pn->next;
40048                :    }
40049                :
40050                :  return Success;
40051                :
40052                :}
40053                :
40054                :
40055                :#define CHECK_SIZE(dw, dh, sw, sh) {                                  \
40056                :  if(!dw || !dh || !sw || !sh)  return Success;                       \
40057                :  /* The region code will break these if they are too large */        \
40058                :  if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767))    \
40059                :        return BadValue;                                              \
40060                :}
40061                :
40062                :
40063                :int
40064                :XvdiPutVideo(   
40065                :   ClientPtr client,
40066                :   DrawablePtr pDraw,
40067                :   XvPortPtr pPort,
40068                :   GCPtr pGC,
40069                :   INT16 vid_x, INT16 vid_y, 
40070                :   CARD16 vid_w, CARD16 vid_h, 
40071                :   INT16 drw_x, INT16 drw_y,
40072                :   CARD16 drw_w, CARD16 drw_h
40073                :){
40074                :  DrawablePtr pOldDraw;
40075                :
40076                :  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
40077                :
40078                :  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
40079                :
40080                :  UpdateCurrentTime();
40081                :
40082                :  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
40083                :     INFORM CLIENT OF ITS FAILURE */
40084                :
40085                :  if (pPort->grab.client && (pPort->grab.client != client))
40086                :    {
40087                :      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
40088                :      return Success;
40089                :    }
40090                :
40091                :  /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
40092                :     EVENTS TO ANY CLIENTS WHO WANT THEM */
40093                :
40094                :  pOldDraw = pPort->pDraw;
40095                :  if ((pOldDraw) && (pOldDraw != pDraw))
40096                :    {
40097                :      XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
40098                :    }
40099                :
40100                :  (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC,
40101                :                                           vid_x, vid_y, vid_w, vid_h, 
40102                :                                           drw_x, drw_y, drw_w, drw_h);
40103                :
40104                :  if ((pPort->pDraw) && (pOldDraw != pDraw))
40105                :    {
40106                :      pPort->client = client;
40107                :      XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
40108                :    }
40109                :
40110                :  pPort->time = currentTime;
40111                :
40112                :  return (Success);
40113                :
40114                :}
40115                :
40116                :int
40117                :XvdiPutStill(   
40118                :   ClientPtr client,
40119                :   DrawablePtr pDraw,
40120                :   XvPortPtr pPort,
40121                :   GCPtr pGC,
40122                :   INT16 vid_x, INT16 vid_y, 
40123                :   CARD16 vid_w, CARD16 vid_h, 
40124                :   INT16 drw_x, INT16 drw_y,
40125                :   CARD16 drw_w, CARD16 drw_h
40126                :){
40127                :  int status;
40128                :
40129                :  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
40130                :
40131                :  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
40132                :
40133                :  UpdateCurrentTime();
40134                :
40135                :  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
40136                :     INFORM CLIENT OF ITS FAILURE */
40137                :
40138                :  if (pPort->grab.client && (pPort->grab.client != client))
40139                :    {
40140                :      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
40141                :      return Success;
40142                :    }
40143                :
40144                :  pPort->time = currentTime;
40145                :
40146                :  status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC, 
40147                :                                           vid_x, vid_y, vid_w, vid_h, 
40148                :                                           drw_x, drw_y, drw_w, drw_h);
40149                :
40150                :  return status;
40151                :
40152                :}
40153                :
40154                :int
40155                :XvdiPutImage(   
40156                :   ClientPtr client, 
40157                :   DrawablePtr pDraw, 
40158                :   XvPortPtr pPort, 
40159                :   GCPtr pGC,
40160                :   INT16 src_x, INT16 src_y, 
40161                :   CARD16 src_w, CARD16 src_h, 
40162                :   INT16 drw_x, INT16 drw_y,
40163                :   CARD16 drw_w, CARD16 drw_h,
40164                :   XvImagePtr image,
40165                :   unsigned char* data,
40166                :   Bool sync,
40167                :   CARD16 width, CARD16 height
40168                :){
40169                :  CHECK_SIZE(drw_w, drw_h, src_w, src_h);
40170                :
40171                :  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
40172                :
40173                :  UpdateCurrentTime();
40174                :
40175                :  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
40176                :     INFORM CLIENT OF ITS FAILURE */
40177                :
40178                :  if (pPort->grab.client && (pPort->grab.client != client))
40179                :    {
40180                :      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
40181                :      return Success;
40182                :    }
40183                :
40184                :  pPort->time = currentTime;
40185                :
40186                :  return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC, 
40187                :                                           src_x, src_y, src_w, src_h, 
40188                :                                           drw_x, drw_y, drw_w, drw_h,
40189                :                                           image, data, sync, width, height);
40190                :}
40191                :
40192                :
40193                :int
40194                :XvdiGetVideo(
40195                :   ClientPtr client,
40196                :   DrawablePtr pDraw,
40197                :   XvPortPtr pPort,
40198                :   GCPtr pGC,
40199                :   INT16 vid_x, INT16 vid_y, 
40200                :   CARD16 vid_w, CARD16 vid_h, 
40201                :   INT16 drw_x, INT16 drw_y,
40202                :   CARD16 drw_w, CARD16 drw_h
40203                :){
40204                :  DrawablePtr pOldDraw;
40205                :
40206                :  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
40207                :
40208                :  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
40209                :
40210                :  UpdateCurrentTime();
40211                :
40212                :  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
40213                :     INFORM CLIENT OF ITS FAILURE */
40214                :
40215                :  if (pPort->grab.client && (pPort->grab.client != client))
40216                :    {
40217                :      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
40218                :      return Success;
40219                :    }
40220                :
40221                :  /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
40222                :     EVENTS TO ANY CLIENTS WHO WANT THEM */
40223                :
40224                :  pOldDraw = pPort->pDraw;
40225                :  if ((pOldDraw) && (pOldDraw != pDraw))
40226                :    {
40227                :      XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
40228                :    }
40229                :
40230                :  (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC,
40231                :                                           vid_x, vid_y, vid_w, vid_h, 
40232                :                                           drw_x, drw_y, drw_w, drw_h);
40233                :
40234                :  if ((pPort->pDraw) && (pOldDraw != pDraw))
40235                :    {
40236                :      pPort->client = client;
40237                :      XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
40238                :    }
40239                :
40240                :  pPort->time = currentTime;
40241                :
40242                :  return (Success);
40243                :
40244                :}
40245                :
40246                :int
40247                :XvdiGetStill(
40248                :   ClientPtr client,
40249                :   DrawablePtr pDraw,
40250                :   XvPortPtr pPort,
40251                :   GCPtr pGC,
40252                :   INT16 vid_x, INT16 vid_y, 
40253                :   CARD16 vid_w, CARD16 vid_h, 
40254                :   INT16 drw_x, INT16 drw_y,
40255                :   CARD16 drw_w, CARD16 drw_h
40256                :){
40257                :  int status;
40258                :
40259                :  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
40260                :
40261                :  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
40262                :
40263                :  UpdateCurrentTime();
40264                :
40265                :  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
40266                :     INFORM CLIENT OF ITS FAILURE */
40267                :
40268                :  if (pPort->grab.client && (pPort->grab.client != client))
40269                :    {
40270                :      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
40271                :      return Success;
40272                :    }
40273                :
40274                :  status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC, 
40275                :                                           vid_x, vid_y, vid_w, vid_h, 
40276                :                                           drw_x, drw_y, drw_w, drw_h);
40277                :
40278                :  pPort->time = currentTime;
40279                :
40280                :  return status;
40281                :
40282                :}
40283                :
40284                :int
40285                :XvdiGrabPort(
40286                :   ClientPtr client,
40287                :   XvPortPtr pPort,
40288                :   Time ctime,
40289                :   int *p_result
40290                :){
40291                :  unsigned long id;
40292                :  TimeStamp time;
40293                :
40294                :  UpdateCurrentTime();
40295                :  time = ClientTimeToServerTime(ctime);
40296                :
40297                :  if (pPort->grab.client && (client != pPort->grab.client))
40298                :    {
40299                :      *p_result = XvAlreadyGrabbed;
40300                :      return Success;
40301                :    }
40302                :
40303                :  if ((CompareTimeStamps(time, currentTime) == LATER) ||
40304                :      (CompareTimeStamps(time, pPort->time) == EARLIER))
40305                :    {
40306                :      *p_result = XvInvalidTime;
40307                :      return Success;
40308                :    }
40309                :
40310                :  if (client == pPort->grab.client)
40311                :    {
40312                :      *p_result = Success;
40313                :      return Success;
40314                :    }
40315                :
40316                :  id = FakeClientID(client->index);
40317                :
40318                :  if (!AddResource(id, XvRTGrab, &pPort->grab))
40319                :    {
40320                :      return BadAlloc;
40321                :    }
40322                :
40323                :  /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
40324                :
40325                :  if ((pPort->pDraw) && (client != pPort->client))
40326                :    {
40327                :      XVCALL(diStopVideo)((ClientPtr)NULL, pPort, pPort->pDraw);
40328                :    }
40329                :
40330                :  pPort->grab.client = client;
40331                :  pPort->grab.id = id;
40332                :
40333                :  pPort->time = currentTime;
40334                :
40335                :  *p_result = Success;
40336                :
40337                :  return Success;
40338                :
40339                :}
40340                :
40341                :int
40342                :XvdiUngrabPort(
40343                :  ClientPtr client,
40344                :  XvPortPtr pPort,
40345                :  Time ctime
40346                :){
40347                :  TimeStamp time;
40348                :
40349                :  UpdateCurrentTime();
40350                :  time = ClientTimeToServerTime(ctime);
40351                :
40352                :  if ((!pPort->grab.client) || (client != pPort->grab.client))
40353                :    {
40354                :      return Success;
40355                :    }
40356                :
40357                :  if ((CompareTimeStamps(time, currentTime) == LATER) ||
40358                :      (CompareTimeStamps(time, pPort->time) == EARLIER))
40359                :    {
40360                :      return Success;
40361                :    }
40362                :
40363                :  /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
40364                :
40365                :  FreeResource(pPort->grab.id, XvRTGrab);
40366                :  pPort->grab.client = (ClientPtr)NULL;
40367                :
40368                :  pPort->time = currentTime;
40369                :
40370                :  return Success;
40371                :
40372                :}
40373                :
40374                :
40375                :int
40376                :XvdiSelectVideoNotify(
40377                :  ClientPtr client,
40378                :  DrawablePtr pDraw,
40379                :  BOOL onoff
40380                :){
40381                :  XvVideoNotifyPtr pn,tpn,fpn;
40382                :
40383                :  /* FIND VideoNotify LIST */
40384                :
40385                :  pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList);
40386                :
40387                :  /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
40388                :
40389                :  if (!onoff && !pn) return Success;
40390                :
40391                :  /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
40392                :     WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
40393                :
40394                :  if (!pn) 
40395                :    {
40396                :      if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec))))
40397                :        return BadAlloc;
40398                :      tpn->next = (XvVideoNotifyPtr)NULL;
40399                :      if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
40400                :        {
40401                :          xfree(tpn);
40402                :          return BadAlloc;
40403                :        }
40404                :    }
40405                :  else
40406                :    {
40407                :      /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
40408                :
40409                :      fpn = (XvVideoNotifyPtr)NULL;
40410                :      tpn = pn;
40411                :      while (tpn)
40412                :        {
40413                :          if (tpn->client == client) 
40414                :            {
40415                :              if (!onoff) tpn->client = (ClientPtr)NULL;
40416                :              return Success;
40417                :            }
40418                :          if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
40419                :          tpn = tpn->next;
40420                :        }
40421                :
40422                :      /* IF TUNNING OFF, THEN JUST RETURN */
40423                :
40424                :      if (!onoff) return Success;
40425                :
40426                :      /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
40427                :
40428                :      if (fpn)
40429                :        {
40430                :          tpn = fpn;
40431                :        }
40432                :      else
40433                :        {
40434                :          if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec))))
40435                :            return BadAlloc;
40436                :          tpn->next = pn->next;
40437                :          pn->next = tpn;
40438                :        }
40439                :    }
40440                :
40441                :  /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
40442                :  /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
40443                :
40444                :  tpn->client = (ClientPtr)NULL;
40445                :  tpn->id = FakeClientID(client->index);
40446                :  AddResource(tpn->id, XvRTVideoNotify, tpn);
40447                :
40448                :  tpn->client = client;
40449                :  return Success;
40450                :
40451                :}
40452                :
40453                :int
40454                :XvdiSelectPortNotify(
40455                :   ClientPtr client,
40456                :   XvPortPtr pPort,
40457                :   BOOL onoff
40458                :){
40459                :  XvPortNotifyPtr pn,tpn;
40460                :
40461                :  /* SEE IF CLIENT IS ALREADY IN LIST */
40462                :
40463                :  tpn = (XvPortNotifyPtr)NULL;
40464                :  pn = pPort->pNotify;
40465                :  while (pn)
40466                :    {
40467                :      if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */
40468                :      if (pn->client == client) break;
40469                :      pn = pn->next;
40470                :    }
40471                :
40472                :  /* IS THE CLIENT ALREADY ON THE LIST? */
40473                :
40474                :  if (pn)
40475                :    {
40476                :      /* REMOVE IT? */
40477                :
40478                :      if (!onoff)
40479                :        {
40480                :          pn->client = (ClientPtr)NULL;
40481                :          FreeResource(pn->id, XvRTPortNotify);
40482                :        }
40483                :
40484                :      return Success;
40485                :    }
40486                :
40487                :  /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE 
40488                :     CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
40489                :
40490                :  if (!tpn)
40491                :    {
40492                :      if (!(tpn = (XvPortNotifyPtr)xalloc(sizeof(XvPortNotifyRec))))
40493                :        return BadAlloc;
40494                :      tpn->next = pPort->pNotify;
40495                :      pPort->pNotify = tpn;
40496                :    }
40497                :
40498                :  tpn->client = client;
40499                :  tpn->id = FakeClientID(client->index);
40500                :  AddResource(tpn->id, XvRTPortNotify, tpn);
40501                :
40502                :  return Success;
40503                :
40504                :}
40505                :
40506                :int
40507                :XvdiStopVideo(
40508                :  ClientPtr client,
40509                :  XvPortPtr pPort,
40510                :  DrawablePtr pDraw
40511                :){
40512                :  int status;
40513                :
40514                :  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
40515                :
40516                :  if (!pPort->pDraw || (pPort->pDraw != pDraw)) 
40517                :    {
40518                :      XvdiSendVideoNotify(pPort, pDraw, XvStopped);
40519                :      return Success;
40520                :    }
40521                :
40522                :  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
40523                :     INFORM CLIENT OF ITS FAILURE */
40524                :
40525                :  if ((client) && (pPort->grab.client) && (pPort->grab.client != client))
40526                :    {
40527                :      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
40528                :      return Success;
40529                :    }
40530                :
40531                :  XvdiSendVideoNotify(pPort, pDraw, XvStopped);
40532                :
40533                :  status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw);
40534                :
40535                :  pPort->pDraw = (DrawablePtr)NULL;
40536                :  pPort->client = (ClientPtr)client;
40537                :  pPort->time = currentTime;
40538                :
40539                :  return status;
40540                :
40541                :}
40542                :
40543                :int
40544                :XvdiPreemptVideo(
40545                :  ClientPtr client,
40546                :  XvPortPtr pPort,
40547                :  DrawablePtr pDraw
40548                :){
40549                :  int status;
40550                :
40551                :  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
40552                :
40553                :  if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success;
40554                :
40555                :  XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
40556                :
40557                :  status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw);
40558                :
40559                :  pPort->pDraw = (DrawablePtr)NULL;
40560                :  pPort->client = (ClientPtr)client;
40561                :  pPort->time = currentTime;
40562                :
40563                :  return status;
40564                :
40565                :}
40566                :
40567                :int
40568                :XvdiMatchPort(
40569                :  XvPortPtr pPort,
40570                :  DrawablePtr pDraw
40571                :){
40572                :
40573                :  XvAdaptorPtr pa;
40574                :  XvFormatPtr pf;
40575                :  int nf;
40576                :
40577                :  pa = pPort->pAdaptor;
40578                :
40579                :  if (pa->pScreen != pDraw->pScreen) return BadMatch;
40580                :
40581                :  nf = pa->nFormats;
40582                :  pf = pa->pFormats;
40583                :
40584                :  while (nf--)
40585                :    {
40586                :      if ((pf->depth == pDraw->depth) 
40587                :#if 0
40588                :         && ((pDraw->type == DRAWABLE_PIXMAP) || 
40589                :           (wVisual(((WindowPtr)pDraw)) == pf->visual))
40590                :#endif
40591                :        )
40592                :        return Success;
40593                :      pf++;
40594                :    }
40595                :
40596                :  return BadMatch;
40597                :
40598                :}
40599                :
40600                :int
40601                :XvdiSetPortAttribute(
40602                :  ClientPtr client,
40603                :  XvPortPtr pPort,
40604                :  Atom attribute,
40605                :  INT32 value
40606                :){
40607                :
40608                :    XvdiSendPortNotify(pPort, attribute, value);
40609                :
40610                :  return 
40611                :    (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value);
40612                :
40613                :}
40614                :
40615                :int
40616                :XvdiGetPortAttribute(
40617                :  ClientPtr client,
40618                :  XvPortPtr pPort,
40619                :  Atom attribute,
40620                :  INT32 *p_value
40621                :){
40622                :
40623                :  return 
40624                :    (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value);
40625                :
40626                :}
40627                :
40628                :static void
40629                :WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to)
40630                :
40631                :{
40632                :
40633                :  to->u.u.type = from->u.u.type;
40634                :  to->u.u.detail = from->u.u.detail;
40635                :  cpswaps(from->u.videoNotify.sequenceNumber, 
40636                :          to->u.videoNotify.sequenceNumber);
40637                :  cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
40638                :  cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
40639                :  cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
40640                :
40641                :}
40642                :
40643                :static void
40644                :WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to)
40645                :
40646                :{
40647                :
40648                :  to->u.u.type = from->u.u.type;
40649                :  to->u.u.detail = from->u.u.detail;
40650                :  cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
40651                :  cpswapl(from->u.portNotify.time, to->u.portNotify.time);
40652                :  cpswapl(from->u.portNotify.port, to->u.portNotify.port);
40653                :  cpswapl(from->u.portNotify.value, to->u.portNotify.value);
40654                :
40655                :}
40656 /* 
40657  * Total samples for file : "/home/cworth/src/xorg/xserver/render/mirect.c"
40658  * 
40659  *     24  0.0261
40660  */
40661
40662
40663                :/*
40664                : *
40665                : * Copyright Â© 2000 Keith Packard, member of The XFree86 Project, Inc.
40666                : *
40667                : * Permission to use, copy, modify, distribute, and sell this software and its
40668                : * documentation for any purpose is hereby granted without fee, provided that
40669                : * the above copyright notice appear in all copies and that both that
40670                : * copyright notice and this permission notice appear in supporting
40671                : * documentation, and that the name of Keith Packard not be used in
40672                : * advertising or publicity pertaining to distribution of the software without
40673                : * specific, written prior permission.  Keith Packard makes no
40674                : * representations about the suitability of this software for any purpose.  It
40675                : * is provided "as is" without express or implied warranty.
40676                : *
40677                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
40678                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
40679                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
40680                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
40681                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
40682                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
40683                : * PERFORMANCE OF THIS SOFTWARE.
40684                : */
40685                :
40686                :#ifdef HAVE_DIX_CONFIG_H
40687                :#include <dix-config.h>
40688                :#endif
40689                :
40690                :#include "scrnintstr.h"
40691                :#include "gcstruct.h"
40692                :#include "pixmapstr.h"
40693                :#include "windowstr.h"
40694                :#include "mi.h"
40695                :#include "picturestr.h"
40696                :#include "mipict.h"
40697                :
40698                :static void
40699                :miColorRects (PicturePtr    pDst,
40700                :              PicturePtr    pClipPict,
40701                :              xRenderColor  *color,
40702                :              int           nRect,
40703                :              xRectangle    *rects,
40704                :              int           xoff,
40705                :              int           yoff)
40706      1  0.0011 :{ /* miColorRects total:     15  0.0163 */
40707                :    ScreenPtr           pScreen = pDst->pDrawable->pScreen;
40708                :    CARD32              pixel;
40709                :    GCPtr               pGC;
40710                :    CARD32              tmpval[5];
40711                :    RegionPtr           pClip;
40712                :    unsigned long       mask;
40713                :
40714      1  0.0011 :    miRenderColorToPixel (pDst->pFormat, color, &pixel);
40715                :
40716                :    pGC = GetScratchGC (pDst->pDrawable->depth, pScreen);
40717                :    if (!pGC)
40718                :        return;
40719                :    tmpval[0] = GXcopy;
40720                :    tmpval[1] = pixel;
40721      1  0.0011 :    tmpval[2] = pDst->subWindowMode;
40722                :    mask = GCFunction | GCForeground | GCSubwindowMode;
40723      4  0.0044 :    if (pClipPict->clientClipType == CT_REGION)
40724                :    {
40725      1  0.0011 :        tmpval[3] = pDst->clipOrigin.x - xoff;
40726                :        tmpval[4] = pDst->clipOrigin.y - yoff;
40727                :        mask |= GCClipXOrigin|GCClipYOrigin;
40728                :        
40729                :        pClip = REGION_CREATE (pScreen, NULL, 1);
40730                :        REGION_COPY (pScreen, pClip,
40731                :                     (RegionPtr) pClipPict->clientClip);
40732                :        (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0);
40733                :    }
40734                :
40735      1  0.0011 :    ChangeGC (pGC, mask, tmpval);
40736      2  0.0022 :    ValidateGC (pDst->pDrawable, pGC);
40737      1  0.0011 :    if (xoff || yoff)
40738                :    {
40739                :        int     i;
40740                :        for (i = 0; i < nRect; i++)
40741                :        {
40742                :            rects[i].x -= xoff;
40743                :            rects[i].y -= yoff;
40744                :        }
40745                :    }
40746      3  0.0033 :    (*pGC->ops->PolyFillRect) (pDst->pDrawable, pGC, nRect, rects);
40747                :    if (xoff || yoff)
40748                :    {
40749                :        int     i;
40750                :        for (i = 0; i < nRect; i++)
40751                :        {
40752                :            rects[i].x += xoff;
40753                :            rects[i].y += yoff;
40754                :        }
40755                :    }
40756                :    FreeScratchGC (pGC);
40757                :}
40758                :
40759                :_X_EXPORT void
40760                :miCompositeRects (CARD8         op,
40761                :                  PicturePtr    pDst,
40762                :                  xRenderColor  *color,
40763                :                  int           nRect,
40764                :                  xRectangle    *rects)
40765      3  0.0033 :{ /* miCompositeRects total:      9  0.0098 */
40766                :    ScreenPtr           pScreen = pDst->pDrawable->pScreen;
40767                :    
40768                :    if (color->alpha == 0xffff)
40769                :    {
40770      2  0.0022 :        if (op == PictOpOver)
40771                :            op = PictOpSrc;
40772                :    }
40773      1  0.0011 :    if (op == PictOpClear)
40774                :        color->red = color->green = color->blue = color->alpha = 0;
40775                :    
40776      1  0.0011 :    if (op == PictOpSrc || op == PictOpClear)
40777                :    {
40778                :        miColorRects (pDst, pDst, color, nRect, rects, 0, 0);
40779      1  0.0011 :        if (pDst->alphaMap)
40780                :            miColorRects (pDst->alphaMap, pDst,
40781                :                          color, nRect, rects,
40782                :                          pDst->alphaOrigin.x,
40783                :                          pDst->alphaOrigin.y);
40784                :    }
40785                :    else
40786                :    {
40787                :        PictFormatPtr   rgbaFormat;
40788                :        PixmapPtr       pPixmap;
40789                :        PicturePtr      pSrc;
40790                :        xRectangle      one;
40791                :        int             error;
40792                :        Pixel           pixel;
40793                :        GCPtr           pGC;
40794                :        CARD32          tmpval[2];
40795                :
40796                :        rgbaFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
40797                :        if (!rgbaFormat)
40798                :            goto bail1;
40799                :        
40800                :        pPixmap = (*pScreen->CreatePixmap) (pScreen, 1, 1,
40801                :                                            rgbaFormat->depth);
40802                :        if (!pPixmap)
40803                :            goto bail2;
40804                :        
40805                :        miRenderColorToPixel (rgbaFormat, color, &pixel);
40806                :
40807                :        pGC = GetScratchGC (rgbaFormat->depth, pScreen);
40808                :        if (!pGC)
40809                :            goto bail3;
40810                :        tmpval[0] = GXcopy;
40811                :        tmpval[1] = pixel;
40812                :
40813                :        ChangeGC (pGC, GCFunction | GCForeground, tmpval);
40814                :        ValidateGC (&pPixmap->drawable, pGC);
40815                :        one.x = 0;
40816                :        one.y = 0;
40817                :        one.width = 1;
40818                :        one.height = 1;
40819                :        (*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &one);
40820                :        
40821                :        tmpval[0] = xTrue;
40822                :        pSrc = CreatePicture (0, &pPixmap->drawable, rgbaFormat,
40823                :                              CPRepeat, tmpval, 0, &error);
40824                :                              
40825                :        if (!pSrc)
40826                :            goto bail4;
40827                :
40828                :        while (nRect--)
40829                :        {
40830                :            CompositePicture (op, pSrc, 0, pDst, 0, 0, 0, 0, 
40831                :                              rects->x,
40832                :                              rects->y,
40833                :                              rects->width,
40834                :                              rects->height);
40835                :            rects++;
40836                :        }
40837                :
40838                :        FreePicture ((pointer) pSrc, 0);
40839                :bail4:
40840                :        FreeScratchGC (pGC);
40841                :bail3:
40842                :        (*pScreen->DestroyPixmap) (pPixmap);
40843                :bail2:
40844                :bail1:
40845                :        ;
40846                :    }
40847      1  0.0011 :}
40848 /* 
40849  * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-utils.c"
40850  * 
40851  *     24  0.0261
40852  */
40853
40854
40855                :/*
40856                : * Copyright Â© 2000 SuSE, Inc.
40857                : *
40858                : * Permission to use, copy, modify, distribute, and sell this software and its
40859                : * documentation for any purpose is hereby granted without fee, provided that
40860                : * the above copyright notice appear in all copies and that both that
40861                : * copyright notice and this permission notice appear in supporting
40862                : * documentation, and that the name of SuSE not be used in advertising or
40863                : * publicity pertaining to distribution of the software without specific,
40864                : * written prior permission.  SuSE makes no representations about the
40865                : * suitability of this software for any purpose.  It is provided "as is"
40866                : * without express or implied warranty.
40867                : *
40868                : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
40869                : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
40870                : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
40871                : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
40872                : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
40873                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40874                : *
40875                : * Author:  Keith Packard, SuSE, Inc.
40876                : */
40877                :
40878                :#include <config.h>
40879                :#include "pixman.h"
40880                :#include "pixman-private.h"
40881                :#include "pixman-mmx.h"
40882                :
40883                :pixman_bool_t
40884                :pixman_transform_point_3d (pixman_transform_t *transform,
40885                :                           pixman_vector_t *vector)
40886                :{
40887                :    pixman_vector_t             result;
40888                :    int                         i, j;
40889                :    pixman_fixed_32_32_t        partial;
40890                :    pixman_fixed_48_16_t        v;
40891                :
40892                :    for (j = 0; j < 3; j++)
40893                :    {
40894                :        v = 0;
40895                :        for (i = 0; i < 3; i++)
40896                :        {
40897                :            partial = ((pixman_fixed_48_16_t) transform->matrix[j][i] *
40898                :                       (pixman_fixed_48_16_t) vector->vector[i]);
40899                :            v += partial >> 16;
40900                :        }
40901                :
40902                :        if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
40903                :            return FALSE;
40904                :
40905                :        result.vector[j] = (pixman_fixed_48_16_t) v;
40906                :    }
40907                :    
40908                :    if (!result.vector[2])
40909                :        return FALSE;
40910                :    
40911                :    *vector = result;
40912                :    return TRUE;
40913                :}
40914                :
40915                :pixman_bool_t
40916                :pixman_blt (uint32_t *src_bits,
40917                :            uint32_t *dst_bits,
40918                :            int src_stride,
40919                :            int dst_stride,
40920                :            int src_bpp,
40921                :            int dst_bpp,
40922                :            int src_x, int src_y,
40923                :            int dst_x, int dst_y,
40924                :            int width, int height)
40925                :{
40926                :#ifdef USE_MMX
40927                :    if (pixman_have_mmx())
40928                :    {
40929                :        return pixman_blt_mmx (src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
40930                :                               src_x, src_y, dst_x, dst_y, width, height);
40931                :    }
40932                :    else
40933                :#endif
40934                :        return FALSE;
40935                :}
40936                :
40937                :static void
40938                :pixman_fill8 (uint32_t  *bits,
40939                :              int       stride,
40940                :              int       x,
40941                :              int       y,
40942                :              int       width,
40943                :              int       height,
40944                :              uint32_t  xor)
40945                :{
40946                :    int byte_stride = stride * sizeof (uint32_t);
40947                :    uint8_t *dst = (uint8_t *) bits;
40948                :    uint8_t v = xor & 0xff;
40949                :    int i;
40950                :
40951                :    dst = dst + y * byte_stride + x;
40952                :
40953                :    while (height--)
40954                :    {
40955                :        for (i = 0; i < width; ++i)
40956                :            dst[i] = v;
40957                :
40958                :        dst += byte_stride;
40959                :    }
40960                :}
40961                :
40962                :static void
40963                :pixman_fill16 (uint32_t *bits,
40964                :               int       stride,
40965                :               int       x,
40966                :               int       y,
40967                :               int       width,
40968                :               int       height,
40969                :               uint32_t  xor)
40970                :{
40971                :    int short_stride = (stride * sizeof (uint32_t)) / sizeof (uint16_t);
40972                :    uint16_t *dst = (uint16_t *)bits;
40973                :    uint16_t v = xor & 0xffff;
40974                :    int i;
40975                :
40976                :    dst = dst + y * short_stride + x;
40977                :
40978                :    while (height--)
40979                :    {
40980                :        for (i = 0; i < width; ++i)
40981                :            dst[i] = v;
40982                :
40983                :        dst += short_stride;
40984                :    }
40985                :}
40986                :
40987                :static void
40988                :pixman_fill32 (uint32_t *bits,
40989                :               int       stride,
40990                :               int       x,
40991                :               int       y,
40992                :               int       width,
40993                :               int       height,
40994                :               uint32_t  xor)
40995                :{
40996                :    int i;
40997                :    
40998                :    bits = bits + y * stride + x;
40999                :    
41000                :    while (height--)
41001                :    {
41002                :        for (i = 0; i < width; ++i)
41003                :            bits[i] = xor;
41004                :
41005                :        bits += stride;
41006                :    }
41007                :}
41008                :
41009                :pixman_bool_t
41010                :pixman_fill (uint32_t *bits,
41011                :             int stride,
41012                :             int bpp,
41013                :             int x,
41014                :             int y,
41015                :             int width,
41016                :             int height,
41017                :             uint32_t xor)
41018                :{
41019                :#if 0
41020                :    printf ("filling: %d %d %d %d (stride: %d, bpp: %d)   pixel: %x\n",
41021                :            x, y, width, height, stride, bpp, xor);
41022                :#endif
41023                :    
41024                :#ifdef USE_MMX
41025                :    if (!pixman_have_mmx() || !pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor))
41026                :#endif
41027                :    {
41028                :        switch (bpp)
41029                :        {
41030                :        case 8:
41031                :            pixman_fill8 (bits, stride, x, y, width, height, xor);
41032                :            break;
41033                :            
41034                :        case 16:
41035                :            pixman_fill16 (bits, stride, x, y, width, height, xor);
41036                :            break;
41037                :            
41038                :        case 32:
41039                :            pixman_fill32 (bits, stride, x, y, width, height, xor);
41040                :            break;
41041                :
41042                :        default:
41043                :            return FALSE;
41044                :            break;
41045                :        }
41046                :    }
41047                :        
41048                :    return TRUE;
41049                :}
41050                :            
41051                :
41052                :/*
41053                : * Compute the smallest value no less than y which is on a
41054                : * grid row
41055                : */
41056                :
41057                :pixman_fixed_t
41058                :pixman_sample_ceil_y (pixman_fixed_t y, int n)
41059                :{ /* pixman_sample_ceil_y total:      1  0.0011 */
41060                :    pixman_fixed_t   f = pixman_fixed_frac(y);
41061                :    pixman_fixed_t   i = pixman_fixed_floor(y);
41062                :    
41063      1  0.0011 :    f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
41064                :    if (f > Y_FRAC_LAST(n))
41065                :    {
41066                :        f = Y_FRAC_FIRST(n);
41067                :        i += pixman_fixed_1;
41068                :    }
41069                :    return (i | f);
41070                :}
41071                :
41072                :#define _div(a,b)    ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b)))
41073                :
41074                :/*
41075                : * Compute the largest value no greater than y which is on a
41076                : * grid row
41077                : */
41078                :pixman_fixed_t
41079                :pixman_sample_floor_y (pixman_fixed_t y, int n)
41080                :{ /* pixman_sample_floor_y total:      5  0.0054 */
41081                :    pixman_fixed_t   f = pixman_fixed_frac(y);
41082      1  0.0011 :    pixman_fixed_t   i = pixman_fixed_floor (y);
41083                :    
41084      4  0.0044 :    f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
41085                :    if (f < Y_FRAC_FIRST(n))
41086                :    {
41087                :        f = Y_FRAC_LAST(n);
41088                :        i -= pixman_fixed_1;
41089                :    }
41090                :    return (i | f);
41091                :}
41092                :
41093                :/*
41094                : * Step an edge by any amount (including negative values)
41095                : */
41096                :void
41097                :pixman_edge_step (pixman_edge_t *e, int n)
41098                :{ /* pixman_edge_step total:      3  0.0033 */
41099                :    pixman_fixed_48_16_t        ne;
41100                :
41101                :    e->x += n * e->stepx;
41102                :    
41103                :    ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
41104                :    
41105                :    if (n >= 0)
41106                :    {
41107      1  0.0011 :        if (ne > 0)
41108                :        {
41109      2  0.0022 :            int nx = (ne + e->dy - 1) / e->dy;
41110                :            e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
41111                :            e->x += nx * e->signdx;
41112                :        }
41113                :    }
41114                :    else
41115                :    {
41116                :        if (ne <= -e->dy)
41117                :        {
41118                :            int nx = (-ne) / e->dy;
41119                :            e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
41120                :            e->x -= nx * e->signdx;
41121                :        }
41122                :    }
41123                :}
41124                :
41125                :/*
41126                : * A private routine to initialize the multi-step
41127                : * elements of an edge structure
41128                : */
41129                :static void
41130                :_pixman_edge_tMultiInit (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p)
41131      2  0.0022 :{ /* _pixman_edge_tMultiInit total:      7  0.0076 */
41132                :    pixman_fixed_t      stepx;
41133                :    pixman_fixed_48_16_t        ne;
41134                :    
41135      2  0.0022 :    ne = n * (pixman_fixed_48_16_t) e->dx;
41136                :    stepx = n * e->stepx;
41137                :    if (ne > 0)
41138                :    {
41139      1  0.0011 :        int nx = ne / e->dy;
41140                :        ne -= nx * e->dy;
41141      1  0.0011 :        stepx += nx * e->signdx;
41142                :    }
41143      1  0.0011 :    *dx_p = ne;
41144                :    *stepx_p = stepx;
41145                :}
41146                :
41147                :/*
41148                : * Initialize one edge structure given the line endpoints and a
41149                : * starting y value
41150                : */
41151                :void
41152                :pixman_edge_init (pixman_edge_t *e,
41153                :                  int           n,
41154                :                  pixman_fixed_t                y_start,
41155                :                  pixman_fixed_t                x_top,
41156                :                  pixman_fixed_t                y_top,
41157                :                  pixman_fixed_t                x_bot,
41158                :                  pixman_fixed_t                y_bot)
41159      2  0.0022 :{ /* pixman_edge_init total:      7  0.0076 */
41160                :    pixman_fixed_t      dx, dy;
41161                :
41162                :    e->x = x_top;
41163                :    e->e = 0;
41164                :    dx = x_bot - x_top;
41165                :    dy = y_bot - y_top;
41166                :    e->dy = dy;
41167                :    e->dx = 0;
41168                :    if (dy)
41169                :    {
41170                :        if (dx >= 0)
41171                :        {
41172                :            e->signdx = 1;
41173                :            e->stepx = dx / dy;
41174                :            e->dx = dx % dy;
41175                :            e->e = -dy;
41176                :        }
41177                :        else
41178                :        {
41179      1  0.0011 :            e->signdx = -1;
41180                :            e->stepx = -(-dx / dy);
41181                :            e->dx = -dx % dy;
41182                :            e->e = 0;
41183                :        }
41184                :    
41185      3  0.0033 :        _pixman_edge_tMultiInit (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small);
41186                :        _pixman_edge_tMultiInit (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big);
41187                :    }
41188      1  0.0011 :    pixman_edge_step (e, y_start - y_top);
41189                :}
41190                :
41191                :/*
41192                : * Initialize one edge structure given a line, starting y value
41193                : * and a pixel offset for the line
41194                : */
41195                :void
41196                :pixman_line_fixed_edge_init (pixman_edge_t *e,
41197                :                             int            n,
41198                :                             pixman_fixed_t         y,
41199                :                             const pixman_line_fixed_t *line,
41200                :                             int            x_off,
41201                :                             int            y_off)
41202      1  0.0011 :{ /* pixman_line_fixed_edge_init total:      1  0.0011 */
41203                :    pixman_fixed_t      x_off_fixed = pixman_int_to_fixed(x_off);
41204                :    pixman_fixed_t      y_off_fixed = pixman_int_to_fixed(y_off);
41205                :    const pixman_point_fixed_t *top, *bot;
41206                :
41207                :    if (line->p1.y <= line->p2.y)
41208                :    {
41209                :        top = &line->p1;
41210                :        bot = &line->p2;
41211                :    }
41212                :    else
41213                :    {
41214                :        top = &line->p2;
41215                :        bot = &line->p1;
41216                :    }
41217                :    pixman_edge_init (e, n, y,
41218                :                    top->x + x_off_fixed,
41219                :                    top->y + y_off_fixed,
41220                :                    bot->x + x_off_fixed,
41221                :                    bot->y + y_off_fixed);
41222                :}
41223 /* 
41224  * Total samples for file : "/home/cworth/src/xorg/xserver/os/utils.c"
41225  * 
41226  *     21  0.0229
41227  */
41228
41229
41230                :/*
41231                :
41232                :Copyright 1987, 1998  The Open Group
41233                :
41234                :Permission to use, copy, modify, distribute, and sell this software and its
41235                :documentation for any purpose is hereby granted without fee, provided that
41236                :the above copyright notice appear in all copies and that both that
41237                :copyright notice and this permission notice appear in supporting
41238                :documentation.
41239                :
41240                :The above copyright notice and this permission notice shall be included
41241                :in all copies or substantial portions of the Software.
41242                :
41243                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
41244                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
41245                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
41246                :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
41247                :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
41248                :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
41249                :OTHER DEALINGS IN THE SOFTWARE.
41250                :
41251                :Except as contained in this notice, the name of The Open Group shall
41252                :not be used in advertising or otherwise to promote the sale, use or
41253                :other dealings in this Software without prior written authorization
41254                :from The Open Group.
41255                :
41256                :
41257                :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
41258                :Copyright 1994 Quarterdeck Office Systems.
41259                :
41260                :                        All Rights Reserved
41261                :
41262                :Permission to use, copy, modify, and distribute this software and its
41263                :documentation for any purpose and without fee is hereby granted,
41264                :provided that the above copyright notice appear in all copies and that
41265                :both that copyright notice and this permission notice appear in
41266                :supporting documentation, and that the names of Digital and
41267                :Quarterdeck not be used in advertising or publicity pertaining to
41268                :distribution of the software without specific, written prior
41269                :permission.
41270                :
41271                :DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
41272                :SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
41273                :FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
41274                :OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
41275                :OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
41276                :OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
41277                :OR PERFORMANCE OF THIS SOFTWARE.
41278                :
41279                :*/
41280                :
41281                :#ifdef HAVE_DIX_CONFIG_H
41282                :#include <dix-config.h>
41283                :#endif
41284                :
41285                :#ifdef __CYGWIN__
41286                :#include <stdlib.h>
41287                :#include <signal.h>
41288                :#endif
41289                :
41290                :#if defined(WIN32) && !defined(__CYGWIN__)
41291                :#include <X11/Xwinsock.h>
41292                :#endif
41293                :#include <X11/Xos.h>
41294                :#include <stdio.h>
41295                :#include <time.h>
41296                :#if !defined(WIN32) || !defined(__MINGW32__)
41297                :#include <sys/time.h>
41298                :#include <sys/resource.h>
41299                :#endif
41300                :#include "misc.h"
41301                :#include <X11/X.h>
41302                :#define XSERV_t
41303                :#define TRANS_SERVER
41304                :#define TRANS_REOPEN
41305                :#include <X11/Xtrans/Xtrans.h>
41306                :#include "input.h"
41307                :#include "dixfont.h"
41308                :#include "osdep.h"
41309                :#include "extension.h"
41310                :#ifdef X_POSIX_C_SOURCE
41311                :#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
41312                :#include <signal.h>
41313                :#undef _POSIX_C_SOURCE
41314                :#else
41315                :#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
41316                :#include <signal.h>
41317                :#else
41318                :#define _POSIX_SOURCE
41319                :#include <signal.h>
41320                :#undef _POSIX_SOURCE
41321                :#endif
41322                :#endif
41323                :#ifndef WIN32
41324                :#include <sys/wait.h>
41325                :#endif
41326                :#if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4)
41327                :#include <sys/resource.h>
41328                :#endif
41329                :#include <sys/stat.h>
41330                :#include <ctype.h>    /* for isspace */
41331                :#include <stdarg.h>
41332                :
41333                :#if defined(DGUX)
41334                :#include <sys/resource.h>
41335                :#include <netdb.h>
41336                :#endif
41337                :
41338                :#include <stdlib.h>     /* for malloc() */
41339                :
41340                :#if defined(TCPCONN) || defined(STREAMSCONN)
41341                :# ifndef WIN32
41342                :#  include <netdb.h>
41343                :# endif
41344                :#endif
41345                :
41346                :#include "opaque.h"
41347                :
41348                :#ifdef SMART_SCHEDULE
41349                :#include "dixstruct.h"
41350                :#endif
41351                :
41352                :#ifdef XKB
41353                :#include <xkbsrv.h>
41354                :#endif
41355                :#ifdef XCSECURITY
41356                :#include "securitysrv.h"
41357                :#endif
41358                :
41359                :#ifdef RENDER
41360                :#include "picture.h"
41361                :#endif
41362                :
41363                :#ifdef XPRINT
41364                :#include "DiPrint.h"
41365                :#endif
41366                :
41367                :_X_EXPORT Bool noTestExtensions;
41368                :#ifdef BIGREQS
41369                :_X_EXPORT Bool noBigReqExtension = FALSE;
41370                :#endif
41371                :#ifdef COMPOSITE
41372                :_X_EXPORT Bool noCompositeExtension = FALSE;
41373                :#endif
41374                :
41375                :#ifdef DAMAGE
41376                :_X_EXPORT Bool noDamageExtension = FALSE;
41377                :#endif
41378                :#ifdef DBE
41379                :_X_EXPORT Bool noDbeExtension = FALSE;
41380                :#endif
41381                :#ifdef DPMSExtension
41382                :_X_EXPORT Bool noDPMSExtension = FALSE;
41383                :#endif
41384                :#ifdef EVI
41385                :_X_EXPORT Bool noEVIExtension = FALSE;
41386                :#endif
41387                :#ifdef FONTCACHE
41388                :_X_EXPORT Bool noFontCacheExtension = FALSE;
41389                :#endif
41390                :#ifdef GLXEXT
41391                :_X_EXPORT Bool noGlxExtension = FALSE;
41392                :#endif
41393                :#ifdef SCREENSAVER
41394                :_X_EXPORT Bool noScreenSaverExtension = FALSE;
41395                :#endif
41396                :#ifdef MITSHM
41397                :_X_EXPORT Bool noMITShmExtension = FALSE;
41398                :#endif
41399                :#ifdef MITMISC
41400                :_X_EXPORT Bool noMITMiscExtension = FALSE;
41401                :#endif
41402                :#ifdef MULTIBUFFER
41403                :_X_EXPORT Bool noMultibufferExtension = FALSE;
41404                :#endif
41405                :#ifdef RANDR
41406                :_X_EXPORT Bool noRRExtension = FALSE;
41407                :#endif
41408                :#ifdef RENDER
41409                :_X_EXPORT Bool noRenderExtension = FALSE;
41410                :#endif
41411                :#ifdef SHAPE
41412                :_X_EXPORT Bool noShapeExtension = FALSE;
41413                :#endif
41414                :#ifdef XCSECURITY
41415                :_X_EXPORT Bool noSecurityExtension = FALSE;
41416                :#endif
41417                :#ifdef XSYNC
41418                :_X_EXPORT Bool noSyncExtension = FALSE;
41419                :#endif
41420                :#ifdef TOGCUP
41421                :_X_EXPORT Bool noXcupExtension = FALSE;
41422                :#endif
41423                :#ifdef RES
41424                :_X_EXPORT Bool noResExtension = FALSE;
41425                :#endif
41426                :#ifdef XAPPGROUP
41427                :_X_EXPORT Bool noXagExtension = FALSE;
41428                :#endif
41429                :#ifdef XCMISC
41430                :_X_EXPORT Bool noXCMiscExtension = FALSE;
41431                :#endif
41432                :#ifdef XEVIE
41433                :/* Xevie is disabled by default for now until the
41434                : * interface is stable */
41435                :_X_EXPORT Bool noXevieExtension = TRUE;
41436                :#endif
41437                :#ifdef XF86BIGFONT
41438                :_X_EXPORT Bool noXFree86BigfontExtension = FALSE;
41439                :#endif
41440                :#ifdef XFreeXDGA
41441                :_X_EXPORT Bool noXFree86DGAExtension = FALSE;
41442                :#endif
41443                :#ifdef XF86DRI
41444                :_X_EXPORT Bool noXFree86DRIExtension = FALSE;
41445                :#endif
41446                :#ifdef XF86MISC
41447                :_X_EXPORT Bool noXFree86MiscExtension = FALSE;
41448                :#endif
41449                :#ifdef XF86VIDMODE
41450                :_X_EXPORT Bool noXFree86VidModeExtension = FALSE;
41451                :#endif
41452                :#ifdef XFIXES
41453                :_X_EXPORT Bool noXFixesExtension = FALSE;
41454                :#endif
41455                :/* |noXkbExtension| is defined in xc/programs/Xserver/xkb/xkbInit.c */
41456                :#ifdef PANORAMIX
41457                :/* Xinerama is disabled by default unless enabled via +xinerama */
41458                :_X_EXPORT Bool noPanoramiXExtension = TRUE;
41459                :#endif
41460                :#ifdef XINPUT
41461                :_X_EXPORT Bool noXInputExtension = FALSE;
41462                :#endif
41463                :#ifdef XIDLE
41464                :_X_EXPORT Bool noXIdleExtension = FALSE;
41465                :#endif
41466                :#ifdef XV
41467                :_X_EXPORT Bool noXvExtension = FALSE;
41468                :#endif
41469                :
41470                :#define X_INCLUDE_NETDB_H
41471                :#include <X11/Xos_r.h>
41472                :
41473                :#include <errno.h>
41474                :
41475                :Bool CoreDump;
41476                :
41477                :#ifdef PANORAMIX
41478                :Bool PanoramiXExtensionDisabledHack = FALSE;
41479                :#endif
41480                :
41481                :int auditTrailLevel = 1;
41482                :
41483                :_X_EXPORT Bool Must_have_memory = FALSE;
41484                :
41485                :#ifdef AIXV3
41486                :int SyncOn  = 0;
41487                :extern int SelectWaitTime;
41488                :#endif
41489                :
41490                :#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
41491                :#define HAS_SAVED_IDS_AND_SETEUID
41492                :#endif
41493                :
41494                :#ifdef MEMBUG
41495                :#define MEM_FAIL_SCALE 100000
41496                :long Memory_fail = 0;
41497                :#include <stdlib.h>  /* for random() */
41498                :#endif
41499                :
41500                :static char *dev_tty_from_init = NULL;  /* since we need to parse it anyway */
41501                :
41502                :OsSigHandlerPtr
41503                :OsSignal(sig, handler)
41504                :    int sig;
41505                :    OsSigHandlerPtr handler;
41506                :{
41507                :#ifdef X_NOT_POSIX
41508                :    return signal(sig, handler);
41509                :#else
41510                :    struct sigaction act, oact;
41511                :
41512                :    sigemptyset(&act.sa_mask);
41513                :    if (handler != SIG_IGN)
41514                :        sigaddset(&act.sa_mask, sig);
41515                :    act.sa_flags = 0;
41516                :    act.sa_handler = handler;
41517                :    sigaction(sig, &act, &oact);
41518                :    return oact.sa_handler;
41519                :#endif
41520                :}
41521                :        
41522                :#ifdef SERVER_LOCK
41523                :/*
41524                : * Explicit support for a server lock file like the ones used for UUCP.
41525                : * For architectures with virtual terminals that can run more than one
41526                : * server at a time.  This keeps the servers from stomping on each other
41527                : * if the user forgets to give them different display numbers.
41528                : */
41529                :#define LOCK_DIR "/tmp"
41530                :#define LOCK_TMP_PREFIX "/.tX"
41531                :#define LOCK_PREFIX "/.X"
41532                :#define LOCK_SUFFIX "-lock"
41533                :
41534                :#if defined(DGUX)
41535                :#include <limits.h>
41536                :#include <sys/param.h>
41537                :#endif
41538                :
41539                :#ifndef PATH_MAX
41540                :#ifndef Lynx
41541                :#include <sys/param.h>
41542                :#else
41543                :#include <param.h>
41544                :#endif
41545                :#ifndef PATH_MAX
41546                :#ifdef MAXPATHLEN
41547                :#define PATH_MAX MAXPATHLEN
41548                :#else
41549                :#define PATH_MAX 1024
41550                :#endif
41551                :#endif
41552                :#endif
41553                :
41554                :static Bool StillLocking = FALSE;
41555                :static char LockFile[PATH_MAX];
41556                :static Bool nolock = FALSE;
41557                :
41558                :/*
41559                : * LockServer --
41560                : *      Check if the server lock file exists.  If so, check if the PID
41561                : *      contained inside is valid.  If so, then die.  Otherwise, create
41562                : *      the lock file containing the PID.
41563                : */
41564                :void
41565                :LockServer(void)
41566                :{
41567                :  char tmp[PATH_MAX], pid_str[12];
41568                :  int lfd, i, haslock, l_pid, t;
41569                :  char *tmppath = NULL;
41570                :  int len;
41571                :  char port[20];
41572                :
41573                :  if (nolock) return;
41574                :  /*
41575                :   * Path names
41576                :   */
41577                :  tmppath = LOCK_DIR;
41578                :
41579                :  sprintf(port, "%d", atoi(display));
41580                :  len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
41581                :                                                strlen(LOCK_TMP_PREFIX);
41582                :  len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1;
41583                :  if (len > sizeof(LockFile))
41584                :    FatalError("Display name `%s' is too long\n", port);
41585                :  (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
41586                :  (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
41587                :
41588                :  /*
41589                :   * Create a temporary file containing our PID.  Attempt three times
41590                :   * to create the file.
41591                :   */
41592                :  StillLocking = TRUE;
41593                :  i = 0;
41594                :  do {
41595                :    i++;
41596                :    lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
41597                :    if (lfd < 0)
41598                :       sleep(2);
41599                :    else
41600                :       break;
41601                :  } while (i < 3);
41602                :  if (lfd < 0) {
41603                :    unlink(tmp);
41604                :    i = 0;
41605                :    do {
41606                :      i++;
41607                :      lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
41608                :      if (lfd < 0)
41609                :         sleep(2);
41610                :      else
41611                :         break;
41612                :    } while (i < 3);
41613                :  }
41614                :  if (lfd < 0)
41615                :    FatalError("Could not create lock file in %s\n", tmp);
41616                :  (void) sprintf(pid_str, "%10ld\n", (long)getpid());
41617                :  (void) write(lfd, pid_str, 11);
41618                :#ifndef USE_CHMOD
41619                :  (void) fchmod(lfd, 0444);
41620                :#else
41621                :  (void) chmod(tmp, 0444);
41622                :#endif
41623                :  (void) close(lfd);
41624                :
41625                :  /*
41626                :   * OK.  Now the tmp file exists.  Try three times to move it in place
41627                :   * for the lock.
41628                :   */
41629                :  i = 0;
41630                :  haslock = 0;
41631                :  while ((!haslock) && (i++ < 3)) {
41632                :    haslock = (link(tmp,LockFile) == 0);
41633                :    if (haslock) {
41634                :      /*
41635                :       * We're done.
41636                :       */
41637                :      break;
41638                :    }
41639                :    else {
41640                :      /*
41641                :       * Read the pid from the existing file
41642                :       */
41643                :      lfd = open(LockFile, O_RDONLY);
41644                :      if (lfd < 0) {
41645                :        unlink(tmp);
41646                :        FatalError("Can't read lock file %s\n", LockFile);
41647                :      }
41648                :      pid_str[0] = '\0';
41649                :      if (read(lfd, pid_str, 11) != 11) {
41650                :        /*
41651                :         * Bogus lock file.
41652                :         */
41653                :        unlink(LockFile);
41654                :        close(lfd);
41655                :        continue;
41656                :      }
41657                :      pid_str[11] = '\0';
41658                :      sscanf(pid_str, "%d", &l_pid);
41659                :      close(lfd);
41660                :
41661                :      /*
41662                :       * Now try to kill the PID to see if it exists.
41663                :       */
41664                :      errno = 0;
41665                :      t = kill(l_pid, 0);
41666                :      if ((t< 0) && (errno == ESRCH)) {
41667                :        /*
41668                :         * Stale lock file.
41669                :         */
41670                :        unlink(LockFile);
41671                :        continue;
41672                :      }
41673                :      else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
41674                :        /*
41675                :         * Process is still active.
41676                :         */
41677                :        unlink(tmp);
41678                :        FatalError("Server is already active for display %s\n%s %s\n%s\n",
41679                :                   port, "\tIf this server is no longer running, remove",
41680                :                   LockFile, "\tand start again.");
41681                :      }
41682                :    }
41683                :  }
41684                :  unlink(tmp);
41685                :  if (!haslock)
41686                :    FatalError("Could not create server lock file: %s\n", LockFile);
41687                :  StillLocking = FALSE;
41688                :}
41689                :
41690                :/*
41691                : * UnlockServer --
41692                : *      Remove the server lock file.
41693                : */
41694                :void
41695                :UnlockServer(void)
41696                :{
41697                :  if (nolock) return;
41698                :
41699                :  if (!StillLocking){
41700                :
41701                :  (void) unlink(LockFile);
41702                :  }
41703                :}
41704                :#endif /* SERVER_LOCK */
41705                :
41706                :/* Force connections to close on SIGHUP from init */
41707                :
41708                :/*ARGSUSED*/
41709                :SIGVAL
41710                :AutoResetServer (int sig)
41711                :{
41712                :    int olderrno = errno;
41713                :
41714                :    dispatchException |= DE_RESET;
41715                :    isItTimeToYield = TRUE;
41716                :#ifdef GPROF
41717                :    chdir ("/tmp");
41718                :    exit (0);
41719                :#endif
41720                :#if defined(SYSV) && defined(X_NOT_POSIX)
41721                :    OsSignal (SIGHUP, AutoResetServer);
41722                :#endif
41723                :    errno = olderrno;
41724                :}
41725                :
41726                :/* Force connections to close and then exit on SIGTERM, SIGINT */
41727                :
41728                :/*ARGSUSED*/
41729                :_X_EXPORT SIGVAL
41730                :GiveUp(int sig)
41731                :{
41732                :    int olderrno = errno;
41733                :
41734                :    dispatchException |= DE_TERMINATE;
41735                :    isItTimeToYield = TRUE;
41736                :#if defined(SYSV) && defined(X_NOT_POSIX)
41737                :    if (sig)
41738                :        OsSignal(sig, SIG_IGN);
41739                :#endif
41740                :    errno = olderrno;
41741                :}
41742                :
41743                :#if defined WIN32 && defined __MINGW32__
41744                :_X_EXPORT CARD32
41745                :GetTimeInMillis (void)
41746                :{
41747                :  return GetTickCount ();
41748                :}
41749                :#else
41750                :_X_EXPORT CARD32
41751                :GetTimeInMillis(void)
41752      1  0.0011 :{ /* GetTimeInMillis total:      1  0.0011 */
41753                :    struct timeval tv;
41754                :
41755                :#ifdef MONOTONIC_CLOCK
41756                :    struct timespec tp;
41757                :    if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
41758                :        return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
41759                :#endif
41760                :
41761                :    X_GETTIMEOFDAY(&tv);
41762                :    return(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
41763                :}
41764                :#endif
41765                :
41766                :_X_EXPORT void
41767                :AdjustWaitForDelay (pointer waitTime, unsigned long newdelay)
41768                :{
41769                :    static struct timeval   delay_val;
41770                :    struct timeval          **wt = (struct timeval **) waitTime;
41771                :    unsigned long           olddelay;
41772                :
41773                :    if (*wt == NULL)
41774                :    {
41775                :        delay_val.tv_sec = newdelay / 1000;
41776                :        delay_val.tv_usec = 1000 * (newdelay % 1000);
41777                :        *wt = &delay_val;
41778                :    }
41779                :    else
41780                :    {
41781                :        olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
41782                :        if (newdelay < olddelay)
41783                :        {
41784                :            (*wt)->tv_sec = newdelay / 1000;
41785                :            (*wt)->tv_usec = 1000 * (newdelay % 1000);
41786                :        }
41787                :    }
41788                :}
41789                :
41790                :void UseMsg(void)
41791                :{
41792                :#if !defined(AIXrt) && !defined(AIX386)
41793                :    ErrorF("use: X [:<display>] [option]\n");
41794                :    ErrorF("-a #                   mouse acceleration (pixels)\n");
41795                :    ErrorF("-ac                    disable access control restrictions\n");
41796                :#ifdef MEMBUG
41797                :    ErrorF("-alloc int             chance alloc should fail\n");
41798                :#endif
41799                :    ErrorF("-audit int             set audit trail level\n");   
41800                :    ErrorF("-auth file             select authorization file\n");       
41801                :    ErrorF("-br                    create root window with black background\n");
41802                :    ErrorF("+bs                    enable any backing store support\n");
41803                :    ErrorF("-bs                    disable any backing store support\n");
41804                :    ErrorF("-c                     turns off key-click\n");
41805                :    ErrorF("c #                    key-click volume (0-100)\n");
41806                :    ErrorF("-cc int                default color visual class\n");
41807                :    ErrorF("-co file               color database file\n");
41808                :#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
41809                :    ErrorF("-config file           read options from file\n");
41810                :#endif
41811                :    ErrorF("-core                  generate core dump on fatal error\n");
41812                :    ErrorF("-dpi int               screen resolution in dots per inch\n");
41813                :#ifdef DPMSExtension
41814                :    ErrorF("dpms                   enables VESA DPMS monitor control\n");
41815                :    ErrorF("-dpms                  disables VESA DPMS monitor control\n");
41816                :#endif
41817                :    ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
41818                :    ErrorF("-f #                   bell base (0-100)\n");
41819                :    ErrorF("-fc string             cursor font\n");
41820                :    ErrorF("-fn string             default font name\n");
41821                :    ErrorF("-fp string             default font path\n");
41822                :    ErrorF("-help                  prints message with these options\n");
41823                :    ErrorF("-I                     ignore all remaining arguments\n");
41824                :#ifdef RLIMIT_DATA
41825                :    ErrorF("-ld int                limit data space to N Kb\n");
41826                :#endif
41827                :#ifdef RLIMIT_NOFILE
41828                :    ErrorF("-lf int                limit number of open files to N\n");
41829                :#endif
41830                :#ifdef RLIMIT_STACK
41831                :    ErrorF("-ls int                limit stack space to N Kb\n");
41832                :#endif
41833                :#ifdef SERVER_LOCK
41834                :    ErrorF("-nolock                disable the locking mechanism\n");
41835                :#endif
41836                :#ifndef NOLOGOHACK
41837                :    ErrorF("-logo                  enable logo in screen saver\n");
41838                :    ErrorF("nologo                 disable logo in screen saver\n");
41839                :#endif
41840                :    ErrorF("-nolisten string       don't listen on protocol\n");
41841                :    ErrorF("-noreset               don't reset after last client exists\n");
41842                :    ErrorF("-reset                 reset after last client exists\n");
41843                :    ErrorF("-p #                   screen-saver pattern duration (minutes)\n");
41844                :    ErrorF("-pn                    accept failure to listen on all ports\n");
41845                :    ErrorF("-nopn                  reject failure to listen on all ports\n");
41846                :    ErrorF("-r                     turns off auto-repeat\n");
41847                :    ErrorF("r                      turns on auto-repeat \n");
41848                :#ifdef RENDER
41849                :    ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
41850                :#endif
41851                :    ErrorF("-s #                   screen-saver timeout (minutes)\n");
41852                :#ifdef XCSECURITY
41853                :    ErrorF("-sp file               security policy file\n");
41854                :#endif
41855                :#ifdef XPRINT
41856                :    PrinterUseMsg();
41857                :#endif
41858                :    ErrorF("-su                    disable any save under support\n");
41859                :    ErrorF("-t #                   mouse threshold (pixels)\n");
41860                :    ErrorF("-terminate             terminate at server reset\n");
41861                :    ErrorF("-to #                  connection time out\n");
41862                :    ErrorF("-tst                   disable testing extensions\n");
41863                :    ErrorF("ttyxx                  server started from init on /dev/ttyxx\n");
41864                :    ErrorF("v                      video blanking for screen-saver\n");
41865                :    ErrorF("-v                     screen-saver without video blanking\n");
41866                :    ErrorF("-wm                    WhenMapped default backing-store\n");
41867                :    ErrorF("-wr                    create root window with white background\n");
41868                :    ErrorF("-x string              loads named extension at init time \n");
41869                :    ErrorF("-maxbigreqsize         set maximal bigrequest size \n");
41870                :#ifdef PANORAMIX
41871                :    ErrorF("+xinerama              Enable XINERAMA extension\n");
41872                :    ErrorF("-xinerama              Disable XINERAMA extension\n");
41873                :#endif
41874                :#ifdef SMART_SCHEDULE
41875                :    ErrorF("-dumbSched             Disable smart scheduling, enable old behavior\n");
41876                :    ErrorF("-schedInterval int     Set scheduler interval in msec\n");
41877                :#endif
41878                :    ErrorF("+extension name        Enable extension\n");
41879                :    ErrorF("-extension name        Disable extension\n");
41880                :#ifdef XDMCP
41881                :    XdmcpUseMsg();
41882                :#endif
41883                :#endif /* !AIXrt && ! AIX386 */
41884                :#ifdef XKB
41885                :    XkbUseMsg();
41886                :#endif
41887                :    ddxUseMsg();
41888                :}
41889                :
41890                :/*  This function performs a rudimentary sanity check
41891                : *  on the display name passed in on the command-line,
41892                : *  since this string is used to generate filenames.
41893                : *  It is especially important that the display name
41894                : *  not contain a "/" and not start with a "-".
41895                : *                                            --kvajk
41896                : */
41897                :static int 
41898                :VerifyDisplayName(const char *d)
41899                :{
41900                :    if ( d == (char *)0 ) return( 0 );  /*  null  */
41901                :    if ( *d == '\0' ) return( 0 );  /*  empty  */
41902                :    if ( *d == '-' ) return( 0 );  /*  could be confused for an option  */
41903                :    if ( *d == '.' ) return( 0 );  /*  must not equal "." or ".."  */
41904                :    if ( strchr(d, '/') != (char *)0 ) return( 0 );  /*  very important!!!  */
41905                :    return( 1 );
41906                :}
41907                :
41908                :/*
41909                : * This function is responsible for doing initalisation of any global
41910                : * variables at an very early point of server startup (even before
41911                : * |ProcessCommandLine()|. 
41912                : */
41913                :void InitGlobals(void)
41914                :{
41915                :    ddxInitGlobals();
41916                :}
41917                :
41918                :
41919                :/*
41920                : * This function parses the command line. Handles device-independent fields
41921                : * and allows ddx to handle additional fields.  It is not allowed to modify
41922                : * argc or any of the strings pointed to by argv.
41923                : */
41924                :void
41925                :ProcessCommandLine(int argc, char *argv[])
41926                :{
41927                :    int i, skip;
41928                :
41929                :    defaultKeyboardControl.autoRepeat = TRUE;
41930                :
41931                :#ifdef NO_PART_NET
41932                :    PartialNetwork = FALSE;
41933                :#else
41934                :    PartialNetwork = TRUE;
41935                :#endif
41936                :
41937                :    for ( i = 1; i < argc; i++ )
41938                :    {
41939                :        /* call ddx first, so it can peek/override if it wants */
41940                :        if((skip = ddxProcessArgument(argc, argv, i)))
41941                :        {
41942                :            i += (skip - 1);
41943                :        }
41944                :        else if(argv[i][0] ==  ':')  
41945                :        {
41946                :            /* initialize display */
41947                :            display = argv[i];
41948                :            display++;
41949                :            if( ! VerifyDisplayName( display ) ) {
41950                :                ErrorF("Bad display name: %s\n", display);
41951                :                UseMsg();
41952                :                FatalError("Bad display name, exiting: %s\n", display);
41953                :            }
41954                :        }
41955                :        else if ( strcmp( argv[i], "-a") == 0)
41956                :        {
41957                :            if(++i < argc)
41958                :                defaultPointerControl.num = atoi(argv[i]);
41959                :            else
41960                :                UseMsg();
41961                :        }
41962                :        else if ( strcmp( argv[i], "-ac") == 0)
41963                :        {
41964                :            defeatAccessControl = TRUE;
41965                :        }
41966                :#ifdef MEMBUG
41967                :        else if ( strcmp( argv[i], "-alloc") == 0)
41968                :        {
41969                :            if(++i < argc)
41970                :                Memory_fail = atoi(argv[i]);
41971                :            else
41972                :                UseMsg();
41973                :        }
41974                :#endif
41975                :        else if ( strcmp( argv[i], "-audit") == 0)
41976                :        {
41977                :            if(++i < argc)
41978                :                auditTrailLevel = atoi(argv[i]);
41979                :            else
41980                :                UseMsg();
41981                :        }
41982                :        else if ( strcmp( argv[i], "-auth") == 0)
41983                :        {
41984                :            if(++i < argc)
41985                :                InitAuthorization (argv[i]);
41986                :            else
41987                :                UseMsg();
41988                :        }
41989                :        else if ( strcmp( argv[i], "-br") == 0)
41990                :            blackRoot = TRUE;
41991                :        else if ( strcmp( argv[i], "+bs") == 0)
41992                :            enableBackingStore = TRUE;
41993                :        else if ( strcmp( argv[i], "-bs") == 0)
41994                :            disableBackingStore = TRUE;
41995                :        else if ( strcmp( argv[i], "c") == 0)
41996                :        {
41997                :            if(++i < argc)
41998                :                defaultKeyboardControl.click = atoi(argv[i]);
41999                :            else
42000                :                UseMsg();
42001                :        }
42002                :        else if ( strcmp( argv[i], "-c") == 0)
42003                :        {
42004                :            defaultKeyboardControl.click = 0;
42005                :        }
42006                :        else if ( strcmp( argv[i], "-cc") == 0)
42007                :        {
42008                :            if(++i < argc)
42009                :                defaultColorVisualClass = atoi(argv[i]);
42010                :            else
42011                :                UseMsg();
42012                :        }
42013                :        else if ( strcmp( argv[i], "-co") == 0)
42014                :        {
42015                :            if(++i < argc)
42016                :                rgbPath = argv[i];
42017                :            else
42018                :                UseMsg();
42019                :        }
42020                :        else if ( strcmp( argv[i], "-core") == 0)
42021                :        {
42022                :            CoreDump = TRUE;
42023                :#if !defined(WIN32) || !defined(__MINGW32__)
42024                :            struct rlimit   core_limit;
42025                :            getrlimit (RLIMIT_CORE, &core_limit);
42026                :            core_limit.rlim_cur = core_limit.rlim_max;
42027                :            setrlimit (RLIMIT_CORE, &core_limit);
42028                :#endif
42029                :        }
42030                :        else if ( strcmp( argv[i], "-dpi") == 0)
42031                :        {
42032                :            if(++i < argc)
42033                :                monitorResolution = atoi(argv[i]);
42034                :            else
42035                :                UseMsg();
42036                :        }
42037                :#ifdef DPMSExtension
42038                :        else if ( strcmp( argv[i], "dpms") == 0)
42039                :            DPMSEnabledSwitch = TRUE;
42040                :        else if ( strcmp( argv[i], "-dpms") == 0)
42041                :            DPMSDisabledSwitch = TRUE;
42042                :#endif
42043                :        else if ( strcmp( argv[i], "-deferglyphs") == 0)
42044                :        {
42045                :            if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
42046                :                UseMsg();
42047                :        }
42048                :        else if ( strcmp( argv[i], "-f") == 0)
42049                :        {
42050                :            if(++i < argc)
42051                :                defaultKeyboardControl.bell = atoi(argv[i]);
42052                :            else
42053                :                UseMsg();
42054                :        }
42055                :        else if ( strcmp( argv[i], "-fc") == 0)
42056                :        {
42057                :            if(++i < argc)
42058                :                defaultCursorFont = argv[i];
42059                :            else
42060                :                UseMsg();
42061                :        }
42062                :        else if ( strcmp( argv[i], "-fn") == 0)
42063                :        {
42064                :            if(++i < argc)
42065                :                defaultTextFont = argv[i];
42066                :            else
42067                :                UseMsg();
42068                :        }
42069                :        else if ( strcmp( argv[i], "-fp") == 0)
42070                :        {
42071                :            if(++i < argc)
42072                :            {
42073                :                defaultFontPath = argv[i];
42074                :            }
42075                :            else
42076                :                UseMsg();
42077                :        }
42078                :        else if ( strcmp( argv[i], "-help") == 0)
42079                :        {
42080                :            UseMsg();
42081                :            exit(0);
42082                :        }
42083                :#ifdef XKB
42084                :        else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
42085                :            if (skip>0)
42086                :                 i+= skip-1;
42087                :            else UseMsg();
42088                :        }
42089                :#endif
42090                :#ifdef RLIMIT_DATA
42091                :        else if ( strcmp( argv[i], "-ld") == 0)
42092                :        {
42093                :            if(++i < argc)
42094                :            {
42095                :                limitDataSpace = atoi(argv[i]);
42096                :                if (limitDataSpace > 0)
42097                :                    limitDataSpace *= 1024;
42098                :            }
42099                :            else
42100                :                UseMsg();
42101                :        }
42102                :#endif
42103                :#ifdef RLIMIT_NOFILE
42104                :        else if ( strcmp( argv[i], "-lf") == 0)
42105                :        {
42106                :            if(++i < argc)
42107                :                limitNoFile = atoi(argv[i]);
42108                :            else
42109                :                UseMsg();
42110                :        }
42111                :#endif
42112                :#ifdef RLIMIT_STACK
42113                :        else if ( strcmp( argv[i], "-ls") == 0)
42114                :        {
42115                :            if(++i < argc)
42116                :            {
42117                :                limitStackSpace = atoi(argv[i]);
42118                :                if (limitStackSpace > 0)
42119                :                    limitStackSpace *= 1024;
42120                :            }
42121                :            else
42122                :                UseMsg();
42123                :        }
42124                :#endif
42125                :#ifdef SERVER_LOCK
42126                :        else if ( strcmp ( argv[i], "-nolock") == 0)
42127                :        {
42128                :#if !defined(WIN32) && !defined(__CYGWIN__)
42129                :          if (getuid() != 0)
42130                :            ErrorF("Warning: the -nolock option can only be used by root\n");
42131                :          else
42132                :#endif
42133                :            nolock = TRUE;
42134                :        }
42135                :#endif
42136                :#ifndef NOLOGOHACK
42137                :        else if ( strcmp( argv[i], "-logo") == 0)
42138                :        {
42139                :            logoScreenSaver = 1;
42140                :        }
42141                :        else if ( strcmp( argv[i], "nologo") == 0)
42142                :        {
42143                :            logoScreenSaver = 0;
42144                :        }
42145                :#endif
42146                :        else if ( strcmp( argv[i], "-nolisten") == 0)
42147                :        {
42148                :            if(++i < argc) {
42149                :                if (_XSERVTransNoListen(argv[i])) 
42150                :                    FatalError ("Failed to disable listen for %s transport",
42151                :                                argv[i]);
42152                :           } else
42153                :                UseMsg();
42154                :        }
42155                :        else if ( strcmp( argv[i], "-noreset") == 0)
42156                :        {
42157                :            dispatchExceptionAtReset = 0;
42158                :        }
42159                :        else if ( strcmp( argv[i], "-reset") == 0)
42160                :        {
42161                :            dispatchExceptionAtReset = DE_RESET;
42162                :        }
42163                :        else if ( strcmp( argv[i], "-p") == 0)
42164                :        {
42165                :            if(++i < argc)
42166                :                defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
42167                :                                             MILLI_PER_MIN;
42168                :            else
42169                :                UseMsg();
42170                :        }
42171                :        else if ( strcmp( argv[i], "-pn") == 0)
42172                :            PartialNetwork = TRUE;
42173                :        else if ( strcmp( argv[i], "-nopn") == 0)
42174                :            PartialNetwork = FALSE;
42175                :        else if ( strcmp( argv[i], "r") == 0)
42176                :            defaultKeyboardControl.autoRepeat = TRUE;
42177                :        else if ( strcmp( argv[i], "-r") == 0)
42178                :            defaultKeyboardControl.autoRepeat = FALSE;
42179                :        else if ( strcmp( argv[i], "-s") == 0)
42180                :        {
42181                :            if(++i < argc)
42182                :                defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
42183                :                                         MILLI_PER_MIN;
42184                :            else
42185                :                UseMsg();
42186                :        }
42187                :        else if ( strcmp( argv[i], "-su") == 0)
42188                :            disableSaveUnders = TRUE;
42189                :        else if ( strcmp( argv[i], "-t") == 0)
42190                :        {
42191                :            if(++i < argc)
42192                :                defaultPointerControl.threshold = atoi(argv[i]);
42193                :            else
42194                :                UseMsg();
42195                :        }
42196                :        else if ( strcmp( argv[i], "-terminate") == 0)
42197                :        {
42198                :            dispatchExceptionAtReset = DE_TERMINATE;
42199                :        }
42200                :        else if ( strcmp( argv[i], "-to") == 0)
42201                :        {
42202                :            if(++i < argc)
42203                :                TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
42204                :            else
42205                :                UseMsg();
42206                :        }
42207                :        else if ( strcmp( argv[i], "-tst") == 0)
42208                :        {
42209                :            noTestExtensions = TRUE;
42210                :        }
42211                :        else if ( strcmp( argv[i], "v") == 0)
42212                :            defaultScreenSaverBlanking = PreferBlanking;
42213                :        else if ( strcmp( argv[i], "-v") == 0)
42214                :            defaultScreenSaverBlanking = DontPreferBlanking;
42215                :        else if ( strcmp( argv[i], "-wm") == 0)
42216                :            defaultBackingStore = WhenMapped;
42217                :        else if ( strcmp( argv[i], "-wr") == 0)
42218                :            whiteRoot = TRUE;
42219                :        else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
42220                :             if(++i < argc) {
42221                :                 long reqSizeArg = atol(argv[i]);
42222                :
42223                :                 /* Request size > 128MB does not make much sense... */
42224                :                 if( reqSizeArg > 0L && reqSizeArg < 128L ) {
42225                :                     maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
42226                :                 }
42227                :                 else
42228                :                 {
42229                :                     UseMsg();
42230                :                 }
42231                :             }
42232                :             else
42233                :             {
42234                :                 UseMsg();
42235                :             }
42236                :         }
42237                :#ifdef PANORAMIX
42238                :        else if ( strcmp( argv[i], "+xinerama") == 0){
42239                :            noPanoramiXExtension = FALSE;
42240                :        }
42241                :        else if ( strcmp( argv[i], "-xinerama") == 0){
42242                :            noPanoramiXExtension = TRUE;
42243                :        }
42244                :        else if ( strcmp( argv[i], "-disablexineramaextension") == 0){
42245                :            PanoramiXExtensionDisabledHack = TRUE;
42246                :        }
42247                :#endif
42248                :        else if ( strcmp( argv[i], "-x") == 0)
42249                :        {
42250                :            if(++i >= argc)
42251                :                UseMsg();
42252                :            /* For U**x, which doesn't support dynamic loading, there's nothing
42253                :             * to do when we see a -x.  Either the extension is linked in or
42254                :             * it isn't */
42255                :        }
42256                :        else if ( strcmp( argv[i], "-I") == 0)
42257                :        {
42258                :            /* ignore all remaining arguments */
42259                :            break;
42260                :        }
42261                :        else if (strncmp (argv[i], "tty", 3) == 0)
42262                :        {
42263                :            /* just in case any body is interested */
42264                :            dev_tty_from_init = argv[i];
42265                :        }
42266                :#ifdef XDMCP
42267                :        else if ((skip = XdmcpOptions(argc, argv, i)) != i)
42268                :        {
42269                :            i = skip - 1;
42270                :        }
42271                :#endif
42272                :#ifdef XPRINT
42273                :        else if ((skip = PrinterOptions(argc, argv, i)) != i)
42274                :        {
42275                :            i = skip - 1;
42276                :        }
42277                :#endif
42278                :#ifdef XCSECURITY
42279                :        else if ((skip = XSecurityOptions(argc, argv, i)) != i)
42280                :        {
42281                :            i = skip - 1;
42282                :        }
42283                :#endif
42284                :#ifdef AIXV3
42285                :        else if ( strcmp( argv[i], "-timeout") == 0)
42286                :        {
42287                :            if(++i < argc)
42288                :                SelectWaitTime = atoi(argv[i]);
42289                :            else
42290                :                UseMsg();
42291                :        }
42292                :        else if ( strcmp( argv[i], "-sync") == 0)
42293                :        {
42294                :            SyncOn++;
42295                :        }
42296                :#endif
42297                :#ifdef SMART_SCHEDULE
42298                :        else if ( strcmp( argv[i], "-dumbSched") == 0)
42299                :        {
42300                :            SmartScheduleDisable = TRUE;
42301                :        }
42302                :        else if ( strcmp( argv[i], "-schedInterval") == 0)
42303                :        {
42304                :            if (++i < argc)
42305                :            {
42306                :                SmartScheduleInterval = atoi(argv[i]);
42307                :                SmartScheduleSlice = SmartScheduleInterval;
42308                :            }
42309                :            else
42310                :                UseMsg();
42311                :        }
42312                :        else if ( strcmp( argv[i], "-schedMax") == 0)
42313                :        {
42314                :            if (++i < argc)
42315                :            {
42316                :                SmartScheduleMaxSlice = atoi(argv[i]);
42317                :            }
42318                :            else
42319                :                UseMsg();
42320                :        }
42321                :#endif
42322                :#ifdef RENDER
42323                :        else if ( strcmp( argv[i], "-render" ) == 0)
42324                :        {
42325                :            if (++i < argc)
42326                :            {
42327                :                int policy = PictureParseCmapPolicy (argv[i]);
42328                :
42329                :                if (policy != PictureCmapPolicyInvalid)
42330                :                    PictureCmapPolicy = policy;
42331                :                else
42332                :                    UseMsg ();
42333                :            }
42334                :            else
42335                :                UseMsg ();
42336                :        }
42337                :#endif
42338                :        else if ( strcmp( argv[i], "+extension") == 0)
42339                :        {
42340                :            if (++i < argc)
42341                :            {
42342                :                if (!EnableDisableExtension(argv[i], TRUE))
42343                :                    EnableDisableExtensionError(argv[i], TRUE);
42344                :            }
42345                :            else
42346                :                UseMsg();
42347                :        }
42348                :        else if ( strcmp( argv[i], "-extension") == 0)
42349                :        {
42350                :            if (++i < argc)
42351                :            {
42352                :                if (!EnableDisableExtension(argv[i], FALSE))
42353                :                    EnableDisableExtensionError(argv[i], FALSE);
42354                :            }
42355                :            else
42356                :                UseMsg();
42357                :        }
42358                :        else
42359                :        {
42360                :            ErrorF("Unrecognized option: %s\n", argv[i]);
42361                :            UseMsg();
42362                :            FatalError("Unrecognized option: %s\n", argv[i]);
42363                :        }
42364                :    }
42365                :}
42366                :
42367                :#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
42368                :static void
42369                :InsertFileIntoCommandLine(
42370                :    int *resargc, char ***resargv, 
42371                :    int prefix_argc, char **prefix_argv,
42372                :    char *filename, 
42373                :    int suffix_argc, char **suffix_argv)
42374                :{
42375                :    struct stat     st;
42376                :    FILE           *f;
42377                :    char           *p;
42378                :    char           *q;
42379                :    int             insert_argc;
42380                :    char           *buf;
42381                :    int             len;
42382                :    int             i;
42383                :
42384                :    f = fopen(filename, "r");
42385                :    if (!f)
42386                :        FatalError("Can't open option file %s\n", filename);
42387                :
42388                :    fstat(fileno(f), &st);
42389                :
42390                :    buf = (char *) xalloc((unsigned) st.st_size + 1);
42391                :    if (!buf)
42392                :        FatalError("Out of Memory\n");
42393                :
42394                :    len = fread(buf, 1, (unsigned) st.st_size, f);
42395                :
42396                :    fclose(f);
42397                :
42398                :    if (len < 0)
42399                :        FatalError("Error reading option file %s\n", filename);
42400                :
42401                :    buf[len] = '\0';
42402                :
42403                :    p = buf;
42404                :    q = buf;
42405                :    insert_argc = 0;
42406                :
42407                :    while (*p)
42408                :    {
42409                :        while (isspace(*p))
42410                :            p++;
42411                :        if (!*p)
42412                :            break;
42413                :        if (*p == '#')
42414                :        {
42415                :            while (*p && *p != '\n')
42416                :                p++;
42417                :        } else
42418                :        {
42419                :            while (*p && !isspace(*p))
42420                :                *q++ = *p++;
42421                :            /* Since p and q might still be pointing at the same place, we       */
42422                :            /* need to step p over the whitespace now before we add the null.    */
42423                :            if (*p)
42424                :                p++;
42425                :            *q++ = '\0';
42426                :            insert_argc++;
42427                :        }
42428                :    }
42429                :
42430                :    buf = (char *) xrealloc(buf, q - buf);
42431                :    if (!buf)
42432                :        FatalError("Out of memory reallocing option buf\n");
42433                :
42434                :    *resargc = prefix_argc + insert_argc + suffix_argc;
42435                :    *resargv = (char **) xalloc((*resargc + 1) * sizeof(char *));
42436                :    if (!*resargv)
42437                :        FatalError("Out of Memory\n");
42438                :
42439                :    memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *));
42440                :
42441                :    p = buf;
42442                :    for (i = 0; i < insert_argc; i++)
42443                :    {
42444                :        (*resargv)[prefix_argc + i] = p;
42445                :        p += strlen(p) + 1;
42446                :    }
42447                :
42448                :    memcpy(*resargv + prefix_argc + insert_argc,
42449                :           suffix_argv, suffix_argc * sizeof(char *));
42450                :
42451                :    (*resargv)[*resargc] = NULL;
42452                :} /* end InsertFileIntoCommandLine */
42453                :
42454                :
42455                :void
42456                :ExpandCommandLine(int *pargc, char ***pargv)
42457                :{
42458                :    int i;
42459                :
42460                :#if !defined(WIN32) && !defined(__CYGWIN__)
42461                :    if (getuid() != geteuid())
42462                :        return;
42463                :#endif
42464                :
42465                :    for (i = 1; i < *pargc; i++)
42466                :    {
42467                :        if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) )
42468                :        {
42469                :            InsertFileIntoCommandLine(pargc, pargv,
42470                :                                          i, *pargv,
42471                :                                          (*pargv)[i+1], /* filename */
42472                :                                          *pargc - i - 2, *pargv + i + 2);
42473                :            i--;
42474                :        }
42475                :    }
42476                :} /* end ExpandCommandLine */
42477                :#endif
42478                :
42479                :/* Implement a simple-minded font authorization scheme.  The authorization
42480                :   name is "hp-hostname-1", the contents are simply the host name. */
42481                :int
42482                :set_font_authorizations(char **authorizations, int *authlen, pointer client)
42483                :{
42484                :#define AUTHORIZATION_NAME "hp-hostname-1"
42485                :#if defined(TCPCONN) || defined(STREAMSCONN)
42486                :    static char *result = NULL;
42487                :    static char *p = NULL;
42488                :
42489                :    if (p == NULL)
42490                :    {
42491                :        char hname[1024], *hnameptr;
42492                :        unsigned int len;
42493                :#if defined(IPv6) && defined(AF_INET6)
42494                :        struct addrinfo hints, *ai = NULL;
42495                :#else
42496                :        struct hostent *host;
42497                :#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
42498                :        _Xgethostbynameparams hparams;
42499                :#endif
42500                :#endif
42501                :
42502                :        gethostname(hname, 1024);
42503                :#if defined(IPv6) && defined(AF_INET6)
42504                :        bzero(&hints, sizeof(hints));
42505                :        hints.ai_flags = AI_CANONNAME;
42506                :        if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
42507                :            hnameptr = ai->ai_canonname;
42508                :        } else {
42509                :            hnameptr = hname;
42510                :        }
42511                :#else
42512                :        host = _XGethostbyname(hname, hparams);
42513                :        if (host == NULL)
42514                :            hnameptr = hname;
42515                :        else
42516                :            hnameptr = host->h_name;
42517                :#endif
42518                :
42519                :        len = strlen(hnameptr) + 1;
42520                :        result = xalloc(len + sizeof(AUTHORIZATION_NAME) + 4);
42521                :
42522                :        p = result;
42523                :        *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
42524                :        *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
42525                :        *p++ = (len) >> 8;
42526                :        *p++ = (len & 0xff);
42527                :
42528                :        memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
42529                :        p += sizeof(AUTHORIZATION_NAME);
42530                :        memmove(p, hnameptr, len);
42531                :        p += len;
42532                :#if defined(IPv6) && defined(AF_INET6)
42533                :        if (ai) {
42534                :            freeaddrinfo(ai);
42535                :        }
42536                :#endif
42537                :    }
42538                :    *authlen = p - result;
42539                :    *authorizations = result;
42540                :    return 1;
42541                :#else /* TCPCONN */
42542                :    return 0;
42543                :#endif /* TCPCONN */
42544                :}
42545                :
42546                :/* XALLOC -- X's internal memory allocator.  Why does it return unsigned
42547                : * long * instead of the more common char *?  Well, if you read K&R you'll
42548                : * see they say that alloc must return a pointer "suitable for conversion"
42549                : * to whatever type you really want.  In a full-blown generic allocator
42550                : * there's no way to solve the alignment problems without potentially
42551                : * wasting lots of space.  But we have a more limited problem. We know
42552                : * we're only ever returning pointers to structures which will have to
42553                : * be long word aligned.  So we are making a stronger guarantee.  It might
42554                : * have made sense to make Xalloc return char * to conform with people's
42555                : * expectations of malloc, but this makes lint happier.
42556                : */
42557                :
42558                :#ifndef INTERNAL_MALLOC
42559                :
42560                :_X_EXPORT void * 
42561                :Xalloc(unsigned long amount)
42562      6  0.0065 :{ /* Xalloc total:     10  0.0109 */
42563                :    register pointer  ptr;
42564                :        
42565      1  0.0011 :    if ((long)amount <= 0) {
42566                :        return (unsigned long *)NULL;
42567                :    }
42568                :    /* aligned extra on long word boundary */
42569                :    amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
42570                :#ifdef MEMBUG
42571                :    if (!Must_have_memory && Memory_fail &&
42572                :        ((random() % MEM_FAIL_SCALE) < Memory_fail))
42573                :        return (unsigned long *)NULL;
42574                :#endif
42575      1  0.0011 :    if ((ptr = (pointer)malloc(amount))) {
42576                :        return (unsigned long *)ptr;
42577                :    }
42578                :    if (Must_have_memory)
42579                :        FatalError("Out of memory");
42580                :    return (unsigned long *)NULL;
42581      2  0.0022 :}
42582                :
42583                :/*****************
42584                : * XNFalloc 
42585                : * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory
42586                : *****************/
42587                :
42588                :_X_EXPORT void *
42589                :XNFalloc(unsigned long amount)
42590                :{
42591                :    register pointer ptr;
42592                :
42593                :    if ((long)amount <= 0)
42594                :    {
42595                :        return (unsigned long *)NULL;
42596                :    }
42597                :    /* aligned extra on long word boundary */
42598                :    amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
42599                :    ptr = (pointer)malloc(amount);
42600                :    if (!ptr)
42601                :    {
42602                :        FatalError("Out of memory");
42603                :    }
42604                :    return ((unsigned long *)ptr);
42605                :}
42606                :
42607                :/*****************
42608                : * Xcalloc
42609                : *****************/
42610                :
42611                :_X_EXPORT void *
42612                :Xcalloc(unsigned long amount)
42613                :{
42614                :    unsigned long   *ret;
42615                :
42616                :    ret = Xalloc (amount);
42617                :    if (ret)
42618                :        bzero ((char *) ret, (int) amount);
42619                :    return ret;
42620                :}
42621                :
42622                :/*****************
42623                : * XNFcalloc
42624                : *****************/
42625                :
42626                :_X_EXPORT void *
42627                :XNFcalloc(unsigned long amount)
42628                :{
42629                :    unsigned long   *ret;
42630                :
42631                :    ret = Xalloc (amount);
42632                :    if (ret)
42633                :        bzero ((char *) ret, (int) amount);
42634                :    else if ((long)amount > 0)
42635                :        FatalError("Out of memory");
42636                :    return ret;
42637                :}
42638                :
42639                :/*****************
42640                : * Xrealloc
42641                : *****************/
42642                :
42643                :_X_EXPORT void *
42644                :Xrealloc(pointer ptr, unsigned long amount)
42645                :{
42646                :#ifdef MEMBUG
42647                :    if (!Must_have_memory && Memory_fail &&
42648                :        ((random() % MEM_FAIL_SCALE) < Memory_fail))
42649                :        return (unsigned long *)NULL;
42650                :#endif
42651                :    if ((long)amount <= 0)
42652                :    {
42653                :        if (ptr && !amount)
42654                :            free(ptr);
42655                :        return (unsigned long *)NULL;
42656                :    }
42657                :    amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
42658                :    if (ptr)
42659                :        ptr = (pointer)realloc((char *)ptr, amount);
42660                :    else
42661                :        ptr = (pointer)malloc(amount);
42662                :    if (ptr)
42663                :        return (unsigned long *)ptr;
42664                :    if (Must_have_memory)
42665                :        FatalError("Out of memory");
42666                :    return (unsigned long *)NULL;
42667                :}
42668                :                    
42669                :/*****************
42670                : * XNFrealloc 
42671                : * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory
42672                : *****************/
42673                :
42674                :_X_EXPORT void *
42675                :XNFrealloc(pointer ptr, unsigned long amount)
42676                :{
42677                :    if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL)
42678                :    {
42679                :        if ((long)amount > 0)
42680                :            FatalError( "Out of memory" );
42681                :    }
42682                :    return ((unsigned long *)ptr);
42683                :}
42684                :
42685                :/*****************
42686                : *  Xfree
42687                : *    calls free 
42688                : *****************/    
42689                :
42690                :_X_EXPORT void
42691                :Xfree(pointer ptr)
42692      7  0.0076 :{ /* Xfree total:     10  0.0109 */
42693      1  0.0011 :    if (ptr)
42694      1  0.0011 :        free((char *)ptr); 
42695      1  0.0011 :}
42696                :
42697                :void
42698                :OsInitAllocator (void)
42699                :{
42700                :#ifdef MEMBUG
42701                :    static int  been_here;
42702                :
42703                :    /* Check the memory system after each generation */
42704                :    if (been_here)
42705                :        CheckMemory ();
42706                :    else
42707                :        been_here = 1;
42708                :#endif
42709                :}
42710                :#endif /* !INTERNAL_MALLOC */
42711                :
42712                :
42713                :char *
42714                :Xstrdup(const char *s)
42715                :{
42716                :    char *sd;
42717                :
42718                :    if (s == NULL)
42719                :        return NULL;
42720                :
42721                :    sd = (char *)Xalloc(strlen(s) + 1);
42722                :    if (sd != NULL)
42723                :        strcpy(sd, s);
42724                :    return sd;
42725                :}
42726                :
42727                :
42728                :_X_EXPORT char *
42729                :XNFstrdup(const char *s)
42730                :{
42731                :    char *sd;
42732                :
42733                :    if (s == NULL)
42734                :        return NULL;
42735                :
42736                :    sd = (char *)XNFalloc(strlen(s) + 1);
42737                :    strcpy(sd, s);
42738                :    return sd;
42739                :}
42740                :
42741                :#ifdef SMART_SCHEDULE
42742                :
42743                :unsigned long   SmartScheduleIdleCount;
42744                :Bool            SmartScheduleIdle;
42745                :Bool            SmartScheduleTimerStopped;
42746                :
42747                :#ifdef SIGVTALRM
42748                :#define SMART_SCHEDULE_POSSIBLE
42749                :#endif
42750                :
42751                :#ifdef SMART_SCHEDULE_POSSIBLE
42752                :#define SMART_SCHEDULE_SIGNAL           SIGALRM
42753                :#define SMART_SCHEDULE_TIMER            ITIMER_REAL
42754                :#endif
42755                :
42756                :static void
42757                :SmartScheduleStopTimer (void)
42758                :{
42759                :#ifdef SMART_SCHEDULE_POSSIBLE
42760                :    struct itimerval    timer;
42761                :    
42762                :    timer.it_interval.tv_sec = 0;
42763                :    timer.it_interval.tv_usec = 0;
42764                :    timer.it_value.tv_sec = 0;
42765                :    timer.it_value.tv_usec = 0;
42766                :    (void) setitimer (ITIMER_REAL, &timer, 0);
42767                :    SmartScheduleTimerStopped = TRUE;
42768                :#endif
42769                :}
42770                :
42771                :Bool
42772                :SmartScheduleStartTimer (void)
42773                :{
42774                :#ifdef SMART_SCHEDULE_POSSIBLE
42775                :    struct itimerval    timer;
42776                :    
42777                :    SmartScheduleTimerStopped = FALSE;
42778                :    timer.it_interval.tv_sec = 0;
42779                :    timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
42780                :    timer.it_value.tv_sec = 0;
42781                :    timer.it_value.tv_usec = SmartScheduleInterval * 1000;
42782                :    return setitimer (ITIMER_REAL, &timer, 0) >= 0;
42783                :#endif
42784                :    return FALSE;
42785                :}
42786                :
42787                :#ifdef SMART_SCHEDULE_POSSIBLE
42788                :static void
42789                :SmartScheduleTimer (int sig)
42790                :{
42791                :    int olderrno = errno;
42792                :
42793                :    SmartScheduleTime += SmartScheduleInterval;
42794                :    if (SmartScheduleIdle)
42795                :    {
42796                :        SmartScheduleStopTimer ();
42797                :    }
42798                :    errno = olderrno;
42799                :}
42800                :#endif
42801                :
42802                :Bool
42803                :SmartScheduleInit (void)
42804                :{
42805                :#ifdef SMART_SCHEDULE_POSSIBLE
42806                :    struct sigaction    act;
42807                :
42808                :    if (SmartScheduleDisable)
42809                :        return TRUE;
42810                :    
42811                :    bzero ((char *) &act, sizeof(struct sigaction));
42812                :
42813                :    /* Set up the timer signal function */
42814                :    act.sa_handler = SmartScheduleTimer;
42815                :    sigemptyset (&act.sa_mask);
42816                :    sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL);
42817                :    if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0)
42818                :    {
42819                :        perror ("sigaction for smart scheduler");
42820                :        return FALSE;
42821                :    }
42822                :    /* Set up the virtual timer */
42823                :    if (!SmartScheduleStartTimer ())
42824                :    {
42825                :        perror ("scheduling timer");
42826                :        return FALSE;
42827                :    }
42828                :    /* stop the timer and wait for WaitForSomething to start it */
42829                :    SmartScheduleStopTimer ();
42830                :    return TRUE;
42831                :#else
42832                :    return FALSE;
42833                :#endif
42834                :}
42835                :#endif
42836                :
42837                :#ifdef SIG_BLOCK
42838                :static sigset_t PreviousSignalMask;
42839                :static int      BlockedSignalCount;
42840                :#endif
42841                :
42842                :void
42843                :OsBlockSignals (void)
42844                :{
42845                :#ifdef SIG_BLOCK
42846                :    if (BlockedSignalCount++ == 0)
42847                :    {
42848                :        sigset_t    set;
42849                :        
42850                :        sigemptyset (&set);
42851                :#ifdef SIGALRM
42852                :        sigaddset (&set, SIGALRM);
42853                :#endif
42854                :#ifdef SIGVTALRM
42855                :        sigaddset (&set, SIGVTALRM);
42856                :#endif
42857                :#ifdef SIGWINCH
42858                :        sigaddset (&set, SIGWINCH);
42859                :#endif
42860                :#ifdef SIGIO
42861                :        sigaddset (&set, SIGIO);
42862                :#endif
42863                :#ifdef SIGTSTP
42864                :        sigaddset (&set, SIGTSTP);
42865                :#endif
42866                :#ifdef SIGTTIN
42867                :        sigaddset (&set, SIGTTIN);
42868                :#endif
42869                :#ifdef SIGTTOU
42870                :        sigaddset (&set, SIGTTOU);
42871                :#endif
42872                :#ifdef SIGCHLD
42873                :        sigaddset (&set, SIGCHLD);
42874                :#endif
42875                :        sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
42876                :    }
42877                :#endif
42878                :}
42879                :
42880                :void
42881                :OsReleaseSignals (void)
42882                :{
42883                :#ifdef SIG_BLOCK
42884                :    if (--BlockedSignalCount == 0)
42885                :    {
42886                :        sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
42887                :    }
42888                :#endif
42889                :}
42890                :
42891                :#if !defined(WIN32)
42892                :/*
42893                : * "safer" versions of system(3), popen(3) and pclose(3) which give up
42894                : * all privs before running a command.
42895                : *
42896                : * This is based on the code in FreeBSD 2.2 libc.
42897                : *
42898                : * XXX It'd be good to redirect stderr so that it ends up in the log file
42899                : * as well.  As it is now, xkbcomp messages don't end up in the log file.
42900                : */
42901                :
42902                :int
42903                :System(char *command)
42904                :{
42905                :    int pid, p;
42906                :#ifdef SIGCHLD
42907                :    void (*csig)(int);
42908                :#endif
42909                :    int status;
42910                :
42911                :    if (!command)
42912                :        return(1);
42913                :
42914                :#ifdef SIGCHLD
42915                :    csig = signal(SIGCHLD, SIG_DFL);
42916                :#endif
42917                :
42918                :#ifdef DEBUG
42919                :    ErrorF("System: `%s'\n", command);
42920                :#endif
42921                :
42922                :    switch (pid = fork()) {
42923                :    case -1:    /* error */
42924                :        p = -1;
42925                :    case 0:     /* child */
42926                :        if (setgid(getgid()) == -1)
42927                :            _exit(127);
42928                :        if (setuid(getuid()) == -1)
42929                :            _exit(127);
42930                :        execl("/bin/sh", "sh", "-c", command, (char *)NULL);
42931                :        _exit(127);
42932                :    default:    /* parent */
42933                :        do {
42934                :            p = waitpid(pid, &status, 0);
42935                :        } while (p == -1 && errno == EINTR);
42936                :        
42937                :    }
42938                :
42939                :#ifdef SIGCHLD
42940                :    signal(SIGCHLD, csig);
42941                :#endif
42942                :
42943                :    return p == -1 ? -1 : status;
42944                :}
42945                :
42946                :static struct pid {
42947                :    struct pid *next;
42948                :    FILE *fp;
42949                :    int pid;
42950                :} *pidlist;
42951                :
42952                :pointer
42953                :Popen(char *command, char *type)
42954                :{
42955                :    struct pid *cur;
42956                :    FILE *iop;
42957                :    int pdes[2], pid;
42958                :
42959                :    if (command == NULL || type == NULL)
42960                :        return NULL;
42961                :
42962                :    if ((*type != 'r' && *type != 'w') || type[1])
42963                :        return NULL;
42964                :
42965                :    if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL)
42966                :        return NULL;
42967                :
42968                :    if (pipe(pdes) < 0) {
42969                :        xfree(cur);
42970                :        return NULL;
42971                :    }
42972                :
42973                :    switch (pid = fork()) {
42974                :    case -1:    /* error */
42975                :        close(pdes[0]);
42976                :        close(pdes[1]);
42977                :        xfree(cur);
42978                :        return NULL;
42979                :    case 0:     /* child */
42980                :        if (setgid(getgid()) == -1)
42981                :            _exit(127);
42982                :        if (setuid(getuid()) == -1)
42983                :            _exit(127);
42984                :        if (*type == 'r') {
42985                :            if (pdes[1] != 1) {
42986                :                /* stdout */
42987                :                dup2(pdes[1], 1);
42988                :                close(pdes[1]);
42989                :            }
42990                :            close(pdes[0]);
42991                :        } else {
42992                :            if (pdes[0] != 0) {
42993                :                /* stdin */
42994                :                dup2(pdes[0], 0);
42995                :                close(pdes[0]);
42996                :            }
42997                :            close(pdes[1]);
42998                :        }
42999                :        execl("/bin/sh", "sh", "-c", command, (char *)NULL);
43000                :        _exit(127);
43001                :    }
43002                :
43003                :    /* Avoid EINTR during stdio calls */
43004                :    OsBlockSignals ();
43005                :    
43006                :    /* parent */
43007                :    if (*type == 'r') {
43008                :        iop = fdopen(pdes[0], type);
43009                :        close(pdes[1]);
43010                :    } else {
43011                :        iop = fdopen(pdes[1], type);
43012                :        close(pdes[0]);
43013                :    }
43014                :
43015                :    cur->fp = iop;
43016                :    cur->pid = pid;
43017                :    cur->next = pidlist;
43018                :    pidlist = cur;
43019                :
43020                :#ifdef DEBUG
43021                :    ErrorF("Popen: `%s', fp = %p\n", command, iop);
43022                :#endif
43023                :
43024                :    return iop;
43025                :}
43026                :
43027                :/* fopen that drops privileges */
43028                :pointer
43029                :Fopen(char *file, char *type)
43030                :{
43031                :    FILE *iop;
43032                :#ifndef HAS_SAVED_IDS_AND_SETEUID
43033                :    struct pid *cur;
43034                :    int pdes[2], pid;
43035                :
43036                :    if (file == NULL || type == NULL)
43037                :        return NULL;
43038                :
43039                :    if ((*type != 'r' && *type != 'w') || type[1])
43040                :        return NULL;
43041                :
43042                :    if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL)
43043                :        return NULL;
43044                :
43045                :    if (pipe(pdes) < 0) {
43046                :        xfree(cur);
43047                :        return NULL;
43048                :    }
43049                :
43050                :    switch (pid = fork()) {
43051                :    case -1:    /* error */
43052                :        close(pdes[0]);
43053                :        close(pdes[1]);
43054                :        xfree(cur);
43055                :        return NULL;
43056                :    case 0:     /* child */
43057                :        if (setgid(getgid()) == -1)
43058                :            _exit(127);
43059                :        if (setuid(getuid()) == -1)
43060                :            _exit(127);
43061                :        if (*type == 'r') {
43062                :            if (pdes[1] != 1) {
43063                :                /* stdout */
43064                :                dup2(pdes[1], 1);
43065                :                close(pdes[1]);
43066                :            }
43067                :            close(pdes[0]);
43068                :        } else {
43069                :            if (pdes[0] != 0) {
43070                :                /* stdin */
43071                :                dup2(pdes[0], 0);
43072                :                close(pdes[0]);
43073                :            }
43074                :            close(pdes[1]);
43075                :        }
43076                :        execl("/bin/cat", "cat", file, (char *)NULL);
43077                :        _exit(127);
43078                :    }
43079                :
43080                :    /* Avoid EINTR during stdio calls */
43081                :    OsBlockSignals ();
43082                :    
43083                :    /* parent */
43084                :    if (*type == 'r') {
43085                :        iop = fdopen(pdes[0], type);
43086                :        close(pdes[1]);
43087                :    } else {
43088                :        iop = fdopen(pdes[1], type);
43089                :        close(pdes[0]);
43090                :    }
43091                :
43092                :    cur->fp = iop;
43093                :    cur->pid = pid;
43094                :    cur->next = pidlist;
43095                :    pidlist = cur;
43096                :
43097                :#ifdef DEBUG
43098                :    ErrorF("Fopen(%s), fp = %p\n", file, iop);
43099                :#endif
43100                :
43101                :    return iop;
43102                :#else
43103                :    int ruid, euid;
43104                :
43105                :    ruid = getuid();
43106                :    euid = geteuid();
43107                :    
43108                :    if (seteuid(ruid) == -1) {
43109                :            return NULL;
43110                :    }
43111                :    iop = fopen(file, type);
43112                :
43113                :    if (seteuid(euid) == -1) {
43114                :            fclose(iop);
43115                :            return NULL;
43116                :    }
43117                :    return iop;
43118                :#endif /* HAS_SAVED_IDS_AND_SETEUID */
43119                :}
43120                :
43121                :int
43122                :Pclose(pointer iop)
43123                :{
43124                :    struct pid *cur, *last;
43125                :    int pstat;
43126                :    int pid;
43127                :
43128                :#ifdef DEBUG
43129                :    ErrorF("Pclose: fp = %p\n", iop);
43130                :#endif
43131                :
43132                :    fclose(iop);
43133                :
43134                :    for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
43135                :        if (cur->fp == iop)
43136                :            break;
43137                :    if (cur == NULL)
43138                :        return -1;
43139                :
43140                :    do {
43141                :        pid = waitpid(cur->pid, &pstat, 0);
43142                :    } while (pid == -1 && errno == EINTR);
43143                :
43144                :    if (last == NULL)
43145                :        pidlist = cur->next;
43146                :    else
43147                :        last->next = cur->next;
43148                :    xfree(cur);
43149                :
43150                :    /* allow EINTR again */
43151                :    OsReleaseSignals ();
43152                :    
43153                :    return pid == -1 ? -1 : pstat;
43154                :}
43155                :
43156                :int 
43157                :Fclose(pointer iop)
43158                :{
43159                :#ifdef HAS_SAVED_IDS_AND_SETEUID
43160                :    return fclose(iop);
43161                :#else
43162                :    return Pclose(iop);
43163                :#endif
43164                :}
43165                :
43166                :#endif /* !WIN32 */
43167                :
43168                :
43169                :/*
43170                : * CheckUserParameters: check for long command line arguments and long
43171                : * environment variables.  By default, these checks are only done when
43172                : * the server's euid != ruid.  In 3.3.x, these checks were done in an
43173                : * external wrapper utility.
43174                : */
43175                :
43176                :/* Consider LD* variables insecure? */
43177                :#ifndef REMOVE_ENV_LD
43178                :#define REMOVE_ENV_LD 1
43179                :#endif
43180                :
43181                :/* Remove long environment variables? */
43182                :#ifndef REMOVE_LONG_ENV
43183                :#define REMOVE_LONG_ENV 1
43184                :#endif
43185                :
43186                :/*
43187                : * Disallow stdout or stderr as pipes?  It's possible to block the X server
43188                : * when piping stdout+stderr to a pipe.
43189                : *
43190                : * Don't enable this because it looks like it's going to cause problems.
43191                : */
43192                :#ifndef NO_OUTPUT_PIPES
43193                :#define NO_OUTPUT_PIPES 0
43194                :#endif
43195                :
43196                :
43197                :/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
43198                :#ifndef CHECK_EUID
43199                :#ifndef WIN32
43200                :#define CHECK_EUID 1
43201                :#else
43202                :#define CHECK_EUID 0
43203                :#endif
43204                :#endif
43205                :
43206                :/*
43207                : * Maybe the locale can be faked to make isprint(3) report that everything
43208                : * is printable?  Avoid it by default.
43209                : */
43210                :#ifndef USE_ISPRINT
43211                :#define USE_ISPRINT 0
43212                :#endif
43213                :
43214                :#define MAX_ARG_LENGTH          128
43215                :#define MAX_ENV_LENGTH          256
43216                :#define MAX_ENV_PATH_LENGTH     2048    /* Limit for *PATH and TERMCAP */
43217                :
43218                :#if USE_ISPRINT
43219                :#include <ctype.h>
43220                :#define checkPrintable(c) isprint(c)
43221                :#else
43222                :#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
43223                :#endif
43224                :
43225                :enum BadCode {
43226                :    NotBad = 0,
43227                :    UnsafeArg,
43228                :    ArgTooLong,
43229                :    UnprintableArg,
43230                :    EnvTooLong,
43231                :    OutputIsPipe,
43232                :    InternalError
43233                :};
43234                :
43235                :#if defined(VENDORSUPPORT)
43236                :#define BUGADDRESS VENDORSUPPORT
43237                :#elif defined(BUILDERADDR)
43238                :#define BUGADDRESS BUILDERADDR
43239                :#else
43240                :#define BUGADDRESS "xorg@freedesktop.org"
43241                :#endif
43242                :
43243                :#define ARGMSG \
43244                :    "\nIf the arguments used are valid, and have been rejected incorrectly\n" \
43245                :      "please send details of the arguments and why they are valid to\n" \
43246                :      "%s.  In the meantime, you can start the Xserver as\n" \
43247                :      "the \"super user\" (root).\n"   
43248                :
43249                :#define ENVMSG \
43250                :    "\nIf the environment is valid, and have been rejected incorrectly\n" \
43251                :      "please send details of the environment and why it is valid to\n" \
43252                :      "%s.  In the meantime, you can start the Xserver as\n" \
43253                :      "the \"super user\" (root).\n"
43254                :
43255                :void
43256                :CheckUserParameters(int argc, char **argv, char **envp)
43257                :{
43258                :    enum BadCode bad = NotBad;
43259                :    int i = 0, j;
43260                :    char *a, *e = NULL;
43261                :#if defined(__QNX__) && !defined(__QNXNTO__)
43262                :    char cmd_name[64];
43263                :#endif
43264                :
43265                :#if CHECK_EUID
43266                :    if (geteuid() == 0 && getuid() != geteuid())
43267                :#endif
43268                :    {
43269                :        /* Check each argv[] */
43270                :        for (i = 1; i < argc; i++) {
43271                :            if (strcmp(argv[i], "-fp") == 0)
43272                :            {
43273                :                i++; /* continue with next argument. skip the length check */
43274                :                if (i >= argc)
43275                :                    break;
43276                :            } else
43277                :            {
43278                :                if (strlen(argv[i]) > MAX_ARG_LENGTH) {
43279                :                    bad = ArgTooLong;
43280                :                    break;
43281                :                }
43282                :            }
43283                :            a = argv[i];
43284                :            while (*a) {
43285                :                if (checkPrintable(*a) == 0) {
43286                :                    bad = UnprintableArg;
43287                :                    break;
43288                :                }
43289                :                a++;
43290                :            }
43291                :            if (bad)
43292                :                break;
43293                :        }
43294                :        if (!bad) {
43295                :            /* Check each envp[] */
43296                :            for (i = 0; envp[i]; i++) {
43297                :
43298                :                /* Check for bad environment variables and values */
43299                :#if REMOVE_ENV_LD
43300                :                while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
43301                :#ifdef ENVDEBUG
43302                :                    ErrorF("CheckUserParameters: removing %s from the "
43303                :                           "environment\n", strtok(envp[i], "="));
43304                :#endif
43305                :                    for (j = i; envp[j]; j++) {
43306                :                        envp[j] = envp[j+1];
43307                :                    }
43308                :                }
43309                :#endif   
43310                :                if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
43311                :#if REMOVE_LONG_ENV
43312                :#ifdef ENVDEBUG
43313                :                    ErrorF("CheckUserParameters: removing %s from the "
43314                :                           "environment\n", strtok(envp[i], "="));
43315                :#endif
43316                :                    for (j = i; envp[j]; j++) {
43317                :                        envp[j] = envp[j+1];
43318                :                    }
43319                :                    i--;
43320                :#else
43321                :                    char *eq;
43322                :                    int len;
43323                :
43324                :                    eq = strchr(envp[i], '=');
43325                :                    if (!eq)
43326                :                        continue;
43327                :                    len = eq - envp[i];
43328                :                    e = malloc(len + 1);
43329                :                    if (!e) {
43330                :                        bad = InternalError;
43331                :                        break;
43332                :                    }
43333                :                    strncpy(e, envp[i], len);
43334                :                    e[len] = 0;
43335                :                    if (len >= 4 &&
43336                :                        (strcmp(e + len - 4, "PATH") == 0 ||
43337                :                         strcmp(e, "TERMCAP") == 0)) {
43338                :                        if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
43339                :                            bad = EnvTooLong;
43340                :                            break;
43341                :                        } else {
43342                :                            free(e);
43343                :                        }
43344                :                    } else {
43345                :                        bad = EnvTooLong;
43346                :                        break;
43347                :                    }
43348                :#endif
43349                :                }
43350                :            }
43351                :        }
43352                :#if NO_OUTPUT_PIPES
43353                :        if (!bad) {
43354                :            struct stat buf;
43355                :
43356                :            if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
43357                :                bad = OutputIsPipe;
43358                :            if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
43359                :                bad = OutputIsPipe;
43360                :        }
43361                :#endif
43362                :    }
43363                :    switch (bad) {
43364                :    case NotBad:
43365                :        return;
43366                :    case UnsafeArg:
43367                :        ErrorF("Command line argument number %d is unsafe\n", i);
43368                :        ErrorF(ARGMSG, BUGADDRESS);
43369                :        break;
43370                :    case ArgTooLong:
43371                :        ErrorF("Command line argument number %d is too long\n", i);
43372                :        ErrorF(ARGMSG, BUGADDRESS);
43373                :        break;
43374                :    case UnprintableArg:
43375                :        ErrorF("Command line argument number %d contains unprintable"
43376                :                " characters\n", i);
43377                :        ErrorF(ARGMSG, BUGADDRESS);
43378                :        break;
43379                :    case EnvTooLong:
43380                :        ErrorF("Environment variable `%s' is too long\n", e);
43381                :        ErrorF(ENVMSG, BUGADDRESS);
43382                :        break;
43383                :    case OutputIsPipe:
43384                :        ErrorF("Stdout and/or stderr is a pipe\n");
43385                :        break;
43386                :    case InternalError:
43387                :        ErrorF("Internal Error\n");
43388                :        break;
43389                :    default:
43390                :        ErrorF("Unknown error\n");
43391                :        ErrorF(ARGMSG, BUGADDRESS);
43392                :        ErrorF(ENVMSG, BUGADDRESS);
43393                :        break;
43394                :    }
43395                :    FatalError("X server aborted because of unsafe environment\n");
43396                :}
43397                :
43398                :/*
43399                : * CheckUserAuthorization: check if the user is allowed to start the
43400                : * X server.  This usually means some sort of PAM checking, and it is
43401                : * usually only done for setuid servers (uid != euid).
43402                : */
43403                :
43404                :#ifdef USE_PAM
43405                :#include <security/pam_appl.h>
43406                :#include <security/pam_misc.h>
43407                :#include <pwd.h>
43408                :#endif /* USE_PAM */
43409                :
43410                :void
43411                :CheckUserAuthorization(void)
43412                :{
43413                :#ifdef USE_PAM
43414                :    static struct pam_conv conv = {
43415                :        misc_conv,
43416                :        NULL
43417                :    };
43418                :
43419                :    pam_handle_t *pamh = NULL;
43420                :    struct passwd *pw;
43421                :    int retval;
43422                :
43423                :    if (getuid() != geteuid()) {
43424                :        pw = getpwuid(getuid());
43425                :        if (pw == NULL)
43426                :            FatalError("getpwuid() failed for uid %d\n", getuid());
43427                :
43428                :        retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
43429                :        if (retval != PAM_SUCCESS)
43430                :            FatalError("pam_start() failed.\n"
43431                :                        "\tMissing or mangled PAM config file or module?\n");
43432                :
43433                :        retval = pam_authenticate(pamh, 0);
43434                :        if (retval != PAM_SUCCESS) {
43435                :            pam_end(pamh, retval);
43436                :            FatalError("PAM authentication failed, cannot start X server.\n"
43437                :                        "\tPerhaps you do not have console ownership?\n");
43438                :        }
43439                :
43440                :        retval = pam_acct_mgmt(pamh, 0);
43441                :        if (retval != PAM_SUCCESS) {
43442                :            pam_end(pamh, retval);
43443                :            FatalError("PAM authentication failed, cannot start X server.\n"
43444                :                        "\tPerhaps you do not have console ownership?\n");
43445                :        }
43446                :
43447                :        /* this is not a session, so do not do session management */
43448                :        pam_end(pamh, PAM_SUCCESS);
43449                :    }
43450                :#endif
43451                :}
43452                :
43453                :#ifdef __SCO__
43454                :#include <fcntl.h>
43455                :
43456                :static void
43457                :lockit (int fd, short what)
43458                :{
43459                :  struct flock lck;
43460                :
43461                :  lck.l_whence = 0;
43462                :  lck.l_start = 0;
43463                :  lck.l_len = 1;
43464                :  lck.l_type = what;
43465                :
43466                :  (void)fcntl (fd, F_SETLKW, &lck);
43467                :}
43468                :
43469                :/* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */
43470                :ssize_t
43471                :pread (int fd, void *buf, size_t nbytes, off_t offset)
43472                :{
43473                :  off_t saved;
43474                :  ssize_t ret;
43475                :
43476                :  lockit (fd, F_RDLCK);
43477                :  saved = lseek (fd, 0, SEEK_CUR);
43478                :  lseek (fd, offset, SEEK_SET);
43479                :  ret = read (fd, buf, nbytes);
43480                :  lseek (fd, saved, SEEK_SET);
43481                :  lockit (fd, F_UNLCK);
43482                :
43483                :  return ret;
43484                :}
43485                :
43486                :ssize_t
43487                :pwrite (int fd, const void *buf, size_t nbytes, off_t offset)
43488                :{
43489                :  off_t saved;
43490                :  ssize_t ret;
43491                :
43492                :  lockit (fd, F_WRLCK);
43493                :  saved = lseek (fd, 0, SEEK_CUR);
43494                :  lseek (fd, offset, SEEK_SET);
43495                :  ret = write (fd, buf, nbytes);
43496                :  lseek (fd, saved, SEEK_SET);
43497                :  lockit (fd, F_UNLCK);
43498                :
43499                :  return ret;
43500                :}
43501                :#endif /* __SCO__ */
43502 /* 
43503  * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbpixmap.c"
43504  * 
43505  *     21  0.0229
43506  */
43507
43508
43509                :/*
43510                : * Copyright Â© 1998 Keith Packard
43511                : *
43512                : * Permission to use, copy, modify, distribute, and sell this software and its
43513                : * documentation for any purpose is hereby granted without fee, provided that
43514                : * the above copyright notice appear in all copies and that both that
43515                : * copyright notice and this permission notice appear in supporting
43516                : * documentation, and that the name of Keith Packard not be used in
43517                : * advertising or publicity pertaining to distribution of the software without
43518                : * specific, written prior permission.  Keith Packard makes no
43519                : * representations about the suitability of this software for any purpose.  It
43520                : * is provided "as is" without express or implied warranty.
43521                : *
43522                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43523                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
43524                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
43525                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
43526                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
43527                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
43528                : * PERFORMANCE OF THIS SOFTWARE.
43529                : */
43530                :
43531                :#ifdef HAVE_DIX_CONFIG_H
43532                :#include <dix-config.h>
43533                :#endif
43534                :
43535                :#include <stdlib.h>
43536                :
43537                :#include "fb.h"
43538                :
43539                :PixmapPtr
43540                :fbCreatePixmapBpp (ScreenPtr pScreen, int width, int height, int depth, int bpp)
43541                :{ /* fbCreatePixmapBpp total:     10  0.0109 */
43542                :    PixmapPtr   pPixmap;
43543                :    size_t      datasize;
43544                :    size_t      paddedWidth;
43545                :    int         adjust;
43546                :    int         base;
43547                :
43548      1  0.0011 :    paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits);
43549                :    if (paddedWidth / 4 > 32767 || height > 32767)
43550                :        return NullPixmap;
43551                :    datasize = height * paddedWidth;
43552      1  0.0011 :    base = pScreen->totalPixmapSize;
43553                :    adjust = 0;
43554      1  0.0011 :    if (base & 7)
43555                :        adjust = 8 - (base & 7);
43556                :    datasize += adjust;
43557                :#ifdef FB_DEBUG
43558                :    datasize += 2 * paddedWidth;
43559                :#endif
43560      1  0.0011 :    pPixmap = AllocatePixmap(pScreen, datasize);
43561                :    if (!pPixmap)
43562                :        return NullPixmap;
43563                :    pPixmap->drawable.type = DRAWABLE_PIXMAP;
43564                :    pPixmap->drawable.class = 0;
43565                :    pPixmap->drawable.pScreen = pScreen;
43566                :    pPixmap->drawable.depth = depth;
43567                :    pPixmap->drawable.bitsPerPixel = bpp;
43568                :    pPixmap->drawable.id = 0;
43569      2  0.0022 :    pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
43570                :    pPixmap->drawable.x = 0;
43571                :    pPixmap->drawable.y = 0;
43572                :    pPixmap->drawable.width = width;
43573      1  0.0011 :    pPixmap->drawable.height = height;
43574                :    pPixmap->devKind = paddedWidth;
43575                :    pPixmap->refcnt = 1;
43576      2  0.0022 :    pPixmap->devPrivate.ptr = (pointer) ((char *)pPixmap + base + adjust);
43577                :#ifdef FB_DEBUG
43578                :    pPixmap->devPrivate.ptr = (void *) ((char *) pPixmap->devPrivate.ptr + paddedWidth);
43579                :    fbInitializeDrawable (&pPixmap->drawable);
43580                :#endif
43581                :
43582                :#ifdef COMPOSITE
43583                :    pPixmap->screen_x = 0;
43584                :    pPixmap->screen_y = 0;
43585                :#endif
43586                :
43587                :    return pPixmap;
43588      1  0.0011 :}
43589                :
43590                :PixmapPtr
43591                :fbCreatePixmap (ScreenPtr pScreen, int width, int height, int depth)
43592      2  0.0022 :{ /* fbCreatePixmap total:     10  0.0109 */
43593                :    int bpp;
43594      4  0.0044 :    bpp = BitsPerPixel (depth);
43595                :#ifdef FB_SCREEN_PRIVATE
43596      1  0.0011 :    if (bpp == 32 && depth <= 24)
43597                :        bpp = fbGetScreenPrivate(pScreen)->pix32bpp;
43598                :#endif
43599      2  0.0022 :    return fbCreatePixmapBpp (pScreen, width, height, depth, bpp);
43600      1  0.0011 :}
43601                :
43602                :Bool
43603                :fbDestroyPixmap (PixmapPtr pPixmap)
43604      1  0.0011 :{ /* fbDestroyPixmap total:      1  0.0011 */
43605                :    if(--pPixmap->refcnt)
43606                :        return TRUE;
43607                :    xfree(pPixmap);
43608                :    return TRUE;
43609                :}
43610                :
43611                :#define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2)                       \
43612                :if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&                       \
43613                :    (!((reg)->data->numRects &&                                 \
43614                :       ((r-1)->y1 == (ry1)) &&                                  \
43615                :       ((r-1)->y2 == (ry2)) &&                                  \
43616                :       ((r-1)->x1 <= (rx1)) &&                                  \
43617                :       ((r-1)->x2 >= (rx2)))))                                  \
43618                :{                                                               \
43619                :    if ((reg)->data->numRects == (reg)->data->size)             \
43620                :    {                                                           \
43621                :        miRectAlloc(reg, 1);                                    \
43622                :        fr = REGION_BOXPTR(reg);                                \
43623                :        r = fr + (reg)->data->numRects;                         \
43624                :    }                                                           \
43625                :    r->x1 = (rx1);                                              \
43626                :    r->y1 = (ry1);                                              \
43627                :    r->x2 = (rx2);                                              \
43628                :    r->y2 = (ry2);                                              \
43629                :    (reg)->data->numRects++;                                    \
43630                :    if(r->x1 < (reg)->extents.x1)                               \
43631                :        (reg)->extents.x1 = r->x1;                              \
43632                :    if(r->x2 > (reg)->extents.x2)                               \
43633                :        (reg)->extents.x2 = r->x2;                              \
43634                :    r++;                                                        \
43635                :}
43636                :
43637                :/* Convert bitmap clip mask into clipping region. 
43638                : * First, goes through each line and makes boxes by noting the transitions
43639                : * from 0 to 1 and 1 to 0.
43640                : * Then it coalesces the current line with the previous if they have boxes
43641                : * at the same X coordinates.
43642                : */
43643                :RegionPtr
43644                :fbPixmapToRegion(PixmapPtr pPix)
43645                :{
43646                :    register RegionPtr  pReg;
43647                :    FbBits              *pw, w;
43648                :    register int        ib;
43649                :    int                 width, h, base, rx1 = 0, crects;
43650                :    FbBits              *pwLineEnd;
43651                :    int                 irectPrevStart, irectLineStart;
43652                :    register BoxPtr     prectO, prectN;
43653                :    BoxPtr              FirstRect, rects, prectLineStart;
43654                :    Bool                fInBox, fSame;
43655                :    register FbBits     mask0 = FB_ALLONES & ~FbScrRight(FB_ALLONES, 1);
43656                :    FbBits              *pwLine;
43657                :    int                 nWidth;
43658                :    
43659                :    pReg = REGION_CREATE(pPix->drawable.pScreen, NULL, 1);
43660                :    if(!pReg)
43661                :        return NullRegion;
43662                :    FirstRect = REGION_BOXPTR(pReg);
43663                :    rects = FirstRect;
43664                :
43665                :    fbPrepareAccess(&pPix->drawable);
43666                :
43667                :    pwLine = (FbBits *) pPix->devPrivate.ptr;
43668                :    nWidth = pPix->devKind >> (FB_SHIFT-3);
43669                :
43670                :    width = pPix->drawable.width;
43671                :    pReg->extents.x1 = width - 1;
43672                :    pReg->extents.x2 = 0;
43673                :    irectPrevStart = -1;
43674                :    for(h = 0; h < pPix->drawable.height; h++)
43675                :    {
43676                :        pw = pwLine;
43677                :        pwLine += nWidth;
43678                :        irectLineStart = rects - FirstRect;
43679                :        /* If the Screen left most bit of the word is set, we're starting in
43680                :         * a box */
43681                :        if(READ(pw) & mask0)
43682                :        {
43683                :            fInBox = TRUE;
43684                :            rx1 = 0;
43685                :        }
43686                :        else
43687                :            fInBox = FALSE;
43688                :        /* Process all words which are fully in the pixmap */
43689                :        pwLineEnd = pw + (width >> FB_SHIFT);
43690                :        for (base = 0; pw < pwLineEnd; base += FB_UNIT)
43691                :        {
43692                :            w = READ(pw++);
43693                :            if (fInBox)
43694                :            {
43695                :                if (!~w)
43696                :                    continue;
43697                :            }
43698                :            else
43699                :            {
43700                :                if (!w)
43701                :                    continue;
43702                :            }
43703                :            for(ib = 0; ib < FB_UNIT; ib++)
43704                :            {
43705                :                /* If the Screen left most bit of the word is set, we're
43706                :                 * starting a box */
43707                :                if(w & mask0)
43708                :                {
43709                :                    if(!fInBox)
43710                :                    {
43711                :                        rx1 = base + ib;
43712                :                        /* start new box */
43713                :                        fInBox = TRUE;
43714                :                    }
43715                :                }
43716                :                else
43717                :                {
43718                :                    if(fInBox)
43719                :                    {
43720                :                        /* end box */
43721                :                        ADDRECT(pReg, rects, FirstRect,
43722                :                                rx1, h, base + ib, h + 1);
43723                :                        fInBox = FALSE;
43724                :                    }
43725                :                }
43726                :                /* Shift the word VISUALLY left one. */
43727                :                w = FbScrLeft(w, 1);
43728                :            }
43729                :        }
43730                :        if(width & FB_MASK)
43731                :        {
43732                :            /* Process final partial word on line */
43733                :            w = READ(pw++);
43734                :            for(ib = 0; ib < (width & FB_MASK); ib++)
43735                :            {
43736                :                /* If the Screen left most bit of the word is set, we're
43737                :                 * starting a box */
43738                :                if(w & mask0)
43739                :                {
43740                :                    if(!fInBox)
43741                :                    {
43742                :                        rx1 = base + ib;
43743                :                        /* start new box */
43744                :                        fInBox = TRUE;
43745                :                    }
43746                :                }
43747                :                else
43748                :                {
43749                :                    if(fInBox)
43750                :                    {
43751                :                        /* end box */
43752                :                        ADDRECT(pReg, rects, FirstRect,
43753                :                                rx1, h, base + ib, h + 1);
43754                :                        fInBox = FALSE;
43755                :                    }
43756                :                }
43757                :                /* Shift the word VISUALLY left one. */
43758                :                w = FbScrLeft(w, 1);
43759                :            }
43760                :        }
43761                :        /* If scanline ended with last bit set, end the box */
43762                :        if(fInBox)
43763                :        {
43764                :            ADDRECT(pReg, rects, FirstRect,
43765                :                    rx1, h, base + (width & FB_MASK), h + 1);
43766                :        }
43767                :        /* if all rectangles on this line have the same x-coords as
43768                :         * those on the previous line, then add 1 to all the previous  y2s and 
43769                :         * throw away all the rectangles from this line 
43770                :         */
43771                :        fSame = FALSE;
43772                :        if(irectPrevStart != -1)
43773                :        {
43774                :            crects = irectLineStart - irectPrevStart;
43775                :            if(crects == ((rects - FirstRect) - irectLineStart))
43776                :            {
43777                :                prectO = FirstRect + irectPrevStart;
43778                :                prectN = prectLineStart = FirstRect + irectLineStart;
43779                :                fSame = TRUE;
43780                :                while(prectO < prectLineStart)
43781                :                {
43782                :                    if((prectO->x1 != prectN->x1) || (prectO->x2 != prectN->x2))
43783                :                    {
43784                :                          fSame = FALSE;
43785                :                          break;
43786                :                    }
43787                :                    prectO++;
43788                :                    prectN++;
43789                :                }
43790                :                if (fSame)
43791                :                {
43792                :                    prectO = FirstRect + irectPrevStart;
43793                :                    while(prectO < prectLineStart)
43794                :                    {
43795                :                        prectO->y2 += 1;
43796                :                        prectO++;
43797                :                    }
43798                :                    rects -= crects;
43799                :                    pReg->data->numRects -= crects;
43800                :                }
43801                :            }
43802                :        }
43803                :        if(!fSame)
43804                :            irectPrevStart = irectLineStart;
43805                :    }
43806                :    if (!pReg->data->numRects)
43807                :        pReg->extents.x1 = pReg->extents.x2 = 0;
43808                :    else
43809                :    {
43810                :        pReg->extents.y1 = REGION_BOXPTR(pReg)->y1;
43811                :        pReg->extents.y2 = REGION_END(pReg)->y2;
43812                :        if (pReg->data->numRects == 1)
43813                :        {
43814                :            xfree(pReg->data);
43815                :            pReg->data = (RegDataPtr)NULL;
43816                :        }
43817                :    }
43818                :
43819                :    fbFinishAccess(&pPix->drawable);
43820                :#ifdef DEBUG
43821                :    if (!miValidRegion(pReg))
43822                :        FatalError("Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__);
43823                :#endif
43824                :    return(pReg);
43825                :}
43826                :
43827                :#ifdef FB_DEBUG
43828                :
43829                :#ifndef WIN32
43830                :#include <stdio.h>
43831                :#else
43832                :#include <dbg.h>
43833                :#endif
43834                :
43835                :static Bool
43836                :fbValidateBits (FbStip *bits, int stride, FbStip data)
43837                :{
43838                :    while (stride--)
43839                :    {
43840                :        if (*bits != data)
43841                :        {
43842                :#ifdef WIN32
43843                :            NCD_DEBUG ((DEBUG_FAILURE, "fdValidateBits failed at 0x%x (is 0x%x want 0x%x)",
43844                :                        bits, *bits, data));
43845                :#else
43846                :            fprintf (stderr, "fbValidateBits failed\n");
43847                :#endif
43848                :            return FALSE;
43849                :        }
43850                :        bits++;
43851                :    }
43852                :}
43853                :
43854                :void
43855                :fbValidateDrawable (DrawablePtr pDrawable)
43856                :{
43857                :    FbStip      *bits, *first, *last;
43858                :    int         stride, bpp;
43859                :    int         xoff, yoff;
43860                :    int         height;
43861                :    Bool        failed;
43862                :    
43863                :    if (pDrawable->type != DRAWABLE_PIXMAP)
43864                :        pDrawable = (DrawablePtr) fbGetWindowPixmap(pDrawable);
43865                :    fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff);
43866                :    first = bits - stride;
43867                :    last = bits + stride * pDrawable->height;
43868                :    if (!fbValidateBits (first, stride, FB_HEAD_BITS) ||
43869                :        !fbValidateBits (last, stride, FB_TAIL_BITS))
43870                :        fbInitializeDrawable(pDrawable);
43871                :    fbFinishAccess (pDrawable);
43872                :}
43873                :
43874                :void
43875                :fbSetBits (FbStip *bits, int stride, FbStip data)
43876                :{
43877                :    while (stride--)
43878                :        *bits++ = data;
43879                :}
43880                :
43881                :void
43882                :fbInitializeDrawable (DrawablePtr pDrawable)
43883                :{
43884                :    FbStip  *bits, *first, *last;
43885                :    int     stride, bpp;
43886                :    int     xoff, yoff;
43887                :    
43888                :    fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff);
43889                :    first = bits - stride;
43890                :    last = bits + stride * pDrawable->height;
43891                :    fbSetBits (first, stride, FB_HEAD_BITS);
43892                :    fbSetBits (last, stride, FB_TAIL_BITS);
43893                :    fbFinishAccess (pDrawable);
43894                :}
43895                :#endif /* FB_DEBUG */
43896 /* 
43897  * Total samples for file : "/home/cworth/src/xorg/xserver/render/miglyph.c"
43898  * 
43899  *     16  0.0174
43900  */
43901
43902
43903                :/*
43904                : *
43905                : * Copyright Â© 2000 SuSE, Inc.
43906                : *
43907                : * Permission to use, copy, modify, distribute, and sell this software and its
43908                : * documentation for any purpose is hereby granted without fee, provided that
43909                : * the above copyright notice appear in all copies and that both that
43910                : * copyright notice and this permission notice appear in supporting
43911                : * documentation, and that the name of SuSE not be used in advertising or
43912                : * publicity pertaining to distribution of the software without specific,
43913                : * written prior permission.  SuSE makes no representations about the
43914                : * suitability of this software for any purpose.  It is provided "as is"
43915                : * without express or implied warranty.
43916                : *
43917                : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
43918                : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
43919                : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43920                : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
43921                : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
43922                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
43923                : *
43924                : * Author:  Keith Packard, SuSE, Inc.
43925                : */
43926                :
43927                :#ifdef HAVE_DIX_CONFIG_H
43928                :#include <dix-config.h>
43929                :#endif
43930                :
43931                :#include "scrnintstr.h"
43932                :#include "gcstruct.h"
43933                :#include "pixmapstr.h"
43934                :#include "windowstr.h"
43935                :#include "mi.h"
43936                :#include "picturestr.h"
43937                :#include "mipict.h"
43938                :
43939                :Bool
43940                :miRealizeGlyph (ScreenPtr pScreen,
43941                :                GlyphPtr  glyph)
43942                :{
43943                :    return TRUE;
43944                :}
43945                :
43946                :void
43947                :miUnrealizeGlyph (ScreenPtr pScreen,
43948                :                  GlyphPtr  glyph)
43949                :{
43950                :}
43951                :
43952                :_X_EXPORT void
43953                :miGlyphExtents (int             nlist,
43954                :                GlyphListPtr    list,
43955                :                GlyphPtr        *glyphs,
43956                :                BoxPtr          extents)
43957      2  0.0022 :{ /* miGlyphExtents total:     16  0.0174 */
43958                :    int         x1, x2, y1, y2;
43959                :    int         n;
43960                :    GlyphPtr    glyph;
43961                :    int         x, y;
43962                :    
43963                :    x = 0;
43964                :    y = 0;
43965                :    extents->x1 = MAXSHORT;
43966                :    extents->x2 = MINSHORT;
43967                :    extents->y1 = MAXSHORT;
43968                :    extents->y2 = MINSHORT;
43969                :    while (nlist--)
43970                :    {
43971                :        x += list->xOff;
43972                :        y += list->yOff;
43973                :        n = list->len;
43974                :        list++;
43975                :        while (n--)
43976                :        {
43977                :            glyph = *glyphs++;
43978      1  0.0011 :            x1 = x - glyph->info.x;
43979                :            if (x1 < MINSHORT)
43980                :                x1 = MINSHORT;
43981      5  0.0054 :            y1 = y - glyph->info.y;
43982                :            if (y1 < MINSHORT)
43983                :                y1 = MINSHORT;
43984      2  0.0022 :            x2 = x1 + glyph->info.width;
43985                :            if (x2 > MAXSHORT)
43986                :                x2 = MAXSHORT;
43987                :            y2 = y1 + glyph->info.height;
43988                :            if (y2 > MAXSHORT)
43989                :                y2 = MAXSHORT;
43990                :            if (x1 < extents->x1)
43991                :                extents->x1 = x1;
43992                :            if (x2 > extents->x2)
43993                :                extents->x2 = x2;
43994      4  0.0044 :            if (y1 < extents->y1)
43995                :                extents->y1 = y1;
43996      1  0.0011 :            if (y2 > extents->y2)
43997                :                extents->y2 = y2;
43998                :            x += glyph->info.xOff;
43999      1  0.0011 :            y += glyph->info.yOff;
44000                :        }
44001                :    }
44002                :}
44003                :
44004                :#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
44005                :
44006                :_X_EXPORT void
44007                :miGlyphs (CARD8         op,
44008                :          PicturePtr    pSrc,
44009                :          PicturePtr    pDst,
44010                :          PictFormatPtr maskFormat,
44011                :          INT16         xSrc,
44012                :          INT16         ySrc,
44013                :          int           nlist,
44014                :          GlyphListPtr  list,
44015                :          GlyphPtr      *glyphs)
44016                :{
44017                :    PixmapPtr   pPixmap = 0;
44018                :    PicturePtr  pPicture;
44019                :    PixmapPtr   pMaskPixmap = 0;
44020                :    PicturePtr  pMask;
44021                :    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
44022                :    int         width = 0, height = 0;
44023                :    int         x, y;
44024                :    int         xDst = list->xOff, yDst = list->yOff;
44025                :    int         n;
44026                :    GlyphPtr    glyph;
44027                :    int         error;
44028                :    BoxRec      extents;
44029                :    CARD32      component_alpha;
44030                :    
44031                :    if (maskFormat)
44032                :    {
44033                :        GCPtr       pGC;
44034                :        xRectangle  rect;
44035                :        
44036                :        miGlyphExtents (nlist, list, glyphs, &extents);
44037                :        
44038                :        if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
44039                :            return;
44040                :        width = extents.x2 - extents.x1;
44041                :        height = extents.y2 - extents.y1;
44042                :        pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth);
44043                :        if (!pMaskPixmap)
44044                :            return;
44045                :        component_alpha = NeedsComponent(maskFormat->format);
44046                :        pMask = CreatePicture (0, &pMaskPixmap->drawable,
44047                :                               maskFormat, CPComponentAlpha, &component_alpha,
44048                :                               serverClient, &error);
44049                :        if (!pMask)
44050                :        {
44051                :            (*pScreen->DestroyPixmap) (pMaskPixmap);
44052                :            return;
44053                :        }
44054                :        pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
44055                :        ValidateGC (&pMaskPixmap->drawable, pGC);
44056                :        rect.x = 0;
44057                :        rect.y = 0;
44058                :        rect.width = width;
44059                :        rect.height = height;
44060                :        (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
44061                :        FreeScratchGC (pGC);
44062                :        x = -extents.x1;
44063                :        y = -extents.y1;
44064                :    }
44065                :    else
44066                :    {
44067                :        pMask = pDst;
44068                :        x = 0;
44069                :        y = 0;
44070                :    }
44071                :    pPicture = 0;
44072                :    while (nlist--)
44073                :    {
44074                :        x += list->xOff;
44075                :        y += list->yOff;
44076                :        n = list->len;
44077                :        while (n--)
44078                :        {
44079                :            glyph = *glyphs++;
44080                :            if (!pPicture)
44081                :            {
44082                :                pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, 
44083                :                                                  list->format->depth,
44084                :                                                  list->format->depth, 
44085                :                                                  0, (pointer) (glyph + 1));
44086                :                if (!pPixmap)
44087                :                    return;
44088                :                component_alpha = NeedsComponent(list->format->format);
44089                :                pPicture = CreatePicture (0, &pPixmap->drawable, list->format,
44090                :                                          CPComponentAlpha, &component_alpha, 
44091                :                                          serverClient, &error);
44092                :                if (!pPicture)
44093                :                {
44094                :                    FreeScratchPixmapHeader (pPixmap);
44095                :                    return;
44096                :                }
44097                :            }
44098                :            (*pScreen->ModifyPixmapHeader) (pPixmap, 
44099                :                                            glyph->info.width, glyph->info.height,
44100                :                                            0, 0, -1, (pointer) (glyph + 1));
44101                :            pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
44102                :            if (maskFormat)
44103                :            {
44104                :                CompositePicture (PictOpAdd,
44105                :                                  pPicture,
44106                :                                  None,
44107                :                                  pMask,
44108                :                                  0, 0,
44109                :                                  0, 0,
44110                :                                  x - glyph->info.x,
44111                :                                  y - glyph->info.y,
44112                :                                  glyph->info.width,
44113                :                                  glyph->info.height);
44114                :            }
44115                :            else
44116                :            {
44117                :                CompositePicture (op,
44118                :                                  pSrc,
44119                :                                  pPicture,
44120                :                                  pDst,
44121                :                                  xSrc + (x - glyph->info.x) - xDst,
44122                :                                  ySrc + (y - glyph->info.y) - yDst,
44123                :                                  0, 0,
44124                :                                  x - glyph->info.x,
44125                :                                  y - glyph->info.y,
44126                :                                  glyph->info.width,
44127                :                                  glyph->info.height);
44128                :            }
44129                :            x += glyph->info.xOff;
44130                :            y += glyph->info.yOff;
44131                :        }
44132                :        list++;
44133                :        if (pPicture)
44134                :        {
44135                :            FreeScratchPixmapHeader (pPixmap);
44136                :            FreePicture ((pointer) pPicture, 0);
44137                :            pPicture = 0;
44138                :            pPixmap = 0;
44139                :        }
44140                :    }
44141                :    if (maskFormat)
44142                :    {
44143                :        x = extents.x1;
44144                :        y = extents.y1;
44145                :        CompositePicture (op,
44146                :                          pSrc,
44147                :                          pMask,
44148                :                          pDst,
44149                :                          xSrc + x - xDst,
44150                :                          ySrc + y - yDst,
44151                :                          0, 0,
44152                :                          x, y,
44153                :                          width, height);
44154                :        FreePicture ((pointer) pMask, (XID) 0);
44155                :        (*pScreen->DestroyPixmap) (pMaskPixmap);
44156                :    }
44157                :}
44158 /* 
44159  * Total samples for file : "/home/cworth/src/xorg/xserver/dix/pixmap.c"
44160  * 
44161  *     16  0.0174
44162  */
44163
44164
44165                :/*
44166                :
44167                :Copyright 1993, 1998  The Open Group
44168                :
44169                :Permission to use, copy, modify, distribute, and sell this software and its
44170                :documentation for any purpose is hereby granted without fee, provided that
44171                :the above copyright notice appear in all copies and that both that
44172                :copyright notice and this permission notice appear in supporting
44173                :documentation.
44174                :
44175                :The above copyright notice and this permission notice shall be included
44176                :in all copies or substantial portions of the Software.
44177                :
44178                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
44179                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44180                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
44181                :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
44182                :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
44183                :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
44184                :OTHER DEALINGS IN THE SOFTWARE.
44185                :
44186                :Except as contained in this notice, the name of The Open Group shall
44187                :not be used in advertising or otherwise to promote the sale, use or
44188                :other dealings in this Software without prior written authorization
44189                :from The Open Group.
44190                :
44191                :*/
44192                :
44193                :#ifdef HAVE_DIX_CONFIG_H
44194                :#include <dix-config.h>
44195                :#endif
44196                :
44197                :#include <X11/X.h>
44198                :#include "scrnintstr.h"
44199                :#include "misc.h"
44200                :#include "os.h"
44201                :#include "windowstr.h"
44202                :#include "resource.h"
44203                :#include "dixstruct.h"
44204                :#include "gcstruct.h"
44205                :#include "servermd.h"
44206                :#include "site.h"
44207                :
44208                :
44209                :/*
44210                : *  Scratch pixmap management and device independent pixmap allocation
44211                : *  function.
44212                : */
44213                :
44214                :
44215                :/* callable by ddx */
44216                :_X_EXPORT PixmapPtr
44217                :GetScratchPixmapHeader(ScreenPtr pScreen, int width, int height, int depth, 
44218                :                       int bitsPerPixel, int devKind, pointer pPixData)
44219      1  0.0011 :{ /* GetScratchPixmapHeader total:      1  0.0011 */
44220                :    PixmapPtr pPixmap = pScreen->pScratchPixmap;
44221                :
44222                :    if (pPixmap)
44223                :        pScreen->pScratchPixmap = NULL;
44224                :    else
44225                :        /* width and height of 0 means don't allocate any pixmap data */
44226                :        pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth);
44227                :
44228                :    if (pPixmap) {
44229                :        if ((*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth,
44230                :                                           bitsPerPixel, devKind, pPixData))
44231                :            return pPixmap;
44232                :        (*pScreen->DestroyPixmap)(pPixmap);
44233                :    }
44234                :    return NullPixmap;
44235                :}
44236                :
44237                :
44238                :/* callable by ddx */
44239                :_X_EXPORT void
44240                :FreeScratchPixmapHeader(PixmapPtr pPixmap)
44241      1  0.0011 :{ /* FreeScratchPixmapHeader total:      2  0.0022 */
44242                :    if (pPixmap)
44243                :    {
44244                :        ScreenPtr pScreen = pPixmap->drawable.pScreen;
44245                :
44246                :        pPixmap->devPrivate.ptr = NULL; /* lest ddx chases bad ptr */
44247                :        if (pScreen->pScratchPixmap)
44248                :            (*pScreen->DestroyPixmap)(pPixmap);
44249                :        else
44250                :            pScreen->pScratchPixmap = pPixmap;
44251                :    }
44252      1  0.0011 :}
44253                :
44254                :
44255                :Bool
44256                :CreateScratchPixmapsForScreen(int scrnum)
44257                :{
44258                :    /* let it be created on first use */
44259                :    screenInfo.screens[scrnum]->pScratchPixmap = NULL;
44260                :    return TRUE;
44261                :}
44262                :
44263                :
44264                :void
44265                :FreeScratchPixmapsForScreen(int scrnum)
44266                :{
44267                :    FreeScratchPixmapHeader(screenInfo.screens[scrnum]->pScratchPixmap);
44268                :}
44269                :
44270                :
44271                :/* callable by ddx */
44272                :_X_EXPORT PixmapPtr
44273                :AllocatePixmap(ScreenPtr pScreen, int pixDataSize)
44274      3  0.0033 :{ /* AllocatePixmap total:     13  0.0142 */
44275                :    PixmapPtr pPixmap;
44276                :    char *ptr;
44277                :    DevUnion *ppriv;
44278                :    unsigned *sizes;
44279                :    unsigned size;
44280                :    int i;
44281                :
44282                :    if (pScreen->totalPixmapSize > ((size_t)-1) - pixDataSize)
44283                :        return NullPixmap;
44284                :    
44285                :    pPixmap = (PixmapPtr)xalloc(pScreen->totalPixmapSize + pixDataSize);
44286                :    if (!pPixmap)
44287                :        return NullPixmap;
44288                :    ppriv = (DevUnion *)(pPixmap + 1);
44289                :    pPixmap->devPrivates = ppriv;
44290                :    sizes = pScreen->PixmapPrivateSizes;
44291      1  0.0011 :    ptr = (char *)(ppriv + pScreen->PixmapPrivateLen);
44292      1  0.0011 :    for (i = pScreen->PixmapPrivateLen; --i >= 0; ppriv++, sizes++)
44293                :    {
44294      2  0.0022 :        if ((size = *sizes) != 0)
44295                :        {
44296      1  0.0011 :            ppriv->ptr = (pointer)ptr;
44297      1  0.0011 :            ptr += size;
44298                :        }
44299                :        else
44300      2  0.0022 :            ppriv->ptr = (pointer)NULL;
44301                :    }
44302                :
44303                :#ifdef _XSERVER64
44304                :    if (pPixmap) {
44305                :        pPixmap->drawable.pad0 = 0;
44306                :        pPixmap->drawable.pad1 = 0;
44307                :    }
44308                :#endif
44309                :
44310                :    return pPixmap;
44311      2  0.0022 :}
44312 /* 
44313  * Total samples for file : "fbpseudocolor.c"
44314  * 
44315  *     14  0.0153
44316  */
44317
44318 <credited to line zero>     14  0.0153 :
44319  /* __i686.get_pc_thunk.cx total:      2  0.0022 */
44320  /* __i686.get_pc_thunk.bx total:     12  0.0131 */
44321 /* 
44322  * Total samples for file : "/home/cworth/src/xorg/xserver/render/mitrap.c"
44323  * 
44324  *     12  0.0131
44325  */
44326
44327
44328                :/*
44329                : *
44330                : * Copyright Â© 2002 Keith Packard, member of The XFree86 Project, Inc.
44331                : *
44332                : * Permission to use, copy, modify, distribute, and sell this software and its
44333                : * documentation for any purpose is hereby granted without fee, provided that
44334                : * the above copyright notice appear in all copies and that both that
44335                : * copyright notice and this permission notice appear in supporting
44336                : * documentation, and that the name of Keith Packard not be used in
44337                : * advertising or publicity pertaining to distribution of the software without
44338                : * specific, written prior permission.  Keith Packard makes no
44339                : * representations about the suitability of this software for any purpose.  It
44340                : * is provided "as is" without express or implied warranty.
44341                : *
44342                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
44343                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
44344                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
44345                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
44346                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
44347                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
44348                : * PERFORMANCE OF THIS SOFTWARE.
44349                : */
44350                :
44351                :#ifdef HAVE_DIX_CONFIG_H
44352                :#include <dix-config.h>
44353                :#endif
44354                :
44355                :#include "scrnintstr.h"
44356                :#include "gcstruct.h"
44357                :#include "pixmapstr.h"
44358                :#include "windowstr.h"
44359                :#include "servermd.h"
44360                :#include "mi.h"
44361                :#include "picturestr.h"
44362                :#include "mipict.h"
44363                :
44364                :PicturePtr
44365                :miCreateAlphaPicture (ScreenPtr     pScreen, 
44366                :                      PicturePtr    pDst,
44367                :                      PictFormatPtr pPictFormat,
44368                :                      CARD16        width,
44369                :                      CARD16        height)
44370                :{
44371                :    PixmapPtr       pPixmap;
44372                :    PicturePtr      pPicture;
44373                :    GCPtr           pGC;
44374                :    int             error;
44375                :    xRectangle      rect;
44376                :
44377                :    if (width > 32767 || height > 32767)
44378                :        return 0;
44379                :
44380                :    if (!pPictFormat)
44381                :    {
44382                :        if (pDst->polyEdge == PolyEdgeSharp)
44383                :            pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
44384                :        else
44385                :            pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
44386                :        if (!pPictFormat)
44387                :            return 0;
44388                :    }
44389                :
44390                :    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 
44391                :                                        pPictFormat->depth);
44392                :    if (!pPixmap)
44393                :        return 0;
44394                :    pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
44395                :    if (!pGC)
44396                :    {
44397                :        (*pScreen->DestroyPixmap) (pPixmap);
44398                :        return 0;
44399                :    }
44400                :    ValidateGC (&pPixmap->drawable, pGC);
44401                :    rect.x = 0;
44402                :    rect.y = 0;
44403                :    rect.width = width;
44404                :    rect.height = height;
44405                :    (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect);
44406                :    FreeScratchGC (pGC);
44407                :    pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
44408                :                              0, 0, serverClient, &error);
44409                :    (*pScreen->DestroyPixmap) (pPixmap);
44410                :    return pPicture;
44411                :}
44412                :
44413                :static xFixed
44414                :miLineFixedX (xLineFixed *l, xFixed y, Bool ceil)
44415                :{ /* miLineFixedX total:      8  0.0087 */
44416                :    xFixed          dx = l->p2.x - l->p1.x;
44417      1  0.0011 :    xFixed_32_32    ex = (xFixed_32_32) (y - l->p1.y) * dx;
44418      1  0.0011 :    xFixed          dy = l->p2.y - l->p1.y;
44419                :    if (ceil)
44420      4  0.0044 :        ex += (dy - 1);
44421                :    return l->p1.x + (xFixed) (ex / dy);
44422      2  0.0022 :}
44423                :
44424                :void
44425                :miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box)
44426                :{ /* miTrapezoidBounds total:      3  0.0033 */
44427                :    box->y1 = MAXSHORT;
44428                :    box->y2 = MINSHORT;
44429                :    box->x1 = MAXSHORT;
44430                :    box->x2 = MINSHORT;
44431                :    for (; ntrap; ntrap--, traps++)
44432                :    {
44433                :        INT16 x1, y1, x2, y2;
44434                :
44435                :        if (!xTrapezoidValid(traps))
44436                :            continue;
44437                :        y1 = xFixedToInt (traps->top);
44438                :        if (y1 < box->y1)
44439                :            box->y1 = y1;
44440                :        
44441                :        y2 = xFixedToInt (xFixedCeil (traps->bottom));
44442                :        if (y2 > box->y2)
44443                :            box->y2 = y2;
44444                :        
44445                :        x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE),
44446                :                               miLineFixedX (&traps->left, traps->bottom, FALSE)));
44447                :        if (x1 < box->x1)
44448                :            box->x1 = x1;
44449                :        
44450      3  0.0033 :        x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE),
44451                :                                           miLineFixedX (&traps->right, traps->bottom, TRUE))));
44452                :        if (x2 > box->x2)
44453                :            box->x2 = x2;
44454                :    }
44455                :}
44456                :
44457                :void
44458                :miTrapezoids (CARD8         op,
44459                :              PicturePtr    pSrc,
44460                :              PicturePtr    pDst,
44461                :              PictFormatPtr maskFormat,
44462                :              INT16         xSrc,
44463                :              INT16         ySrc,
44464                :              int           ntrap,
44465                :              xTrapezoid    *traps)
44466                :{ /* miTrapezoids total:      1  0.0011 */
44467                :    ScreenPtr           pScreen = pDst->pDrawable->pScreen;
44468                :    PictureScreenPtr    ps = GetPictureScreen(pScreen);
44469                :
44470                :    /*
44471                :     * Check for solid alpha add
44472                :     */
44473                :    if (op == PictOpAdd && miIsSolidAlpha (pSrc))
44474                :    {
44475                :        for (; ntrap; ntrap--, traps++)
44476                :            (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
44477                :    } 
44478                :    else if (maskFormat)
44479                :    {
44480                :        PicturePtr      pPicture;
44481                :        BoxRec          bounds;
44482                :        INT16           xDst, yDst;
44483                :        INT16           xRel, yRel;
44484                :        
44485                :        xDst = traps[0].left.p1.x >> 16;
44486                :        yDst = traps[0].left.p1.y >> 16;
44487                :
44488                :        miTrapezoidBounds (ntrap, traps, &bounds);
44489                :        if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
44490                :            return;
44491                :        pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat,
44492                :                                         bounds.x2 - bounds.x1,
44493                :                                         bounds.y2 - bounds.y1);
44494                :        if (!pPicture)
44495                :            return;
44496      1  0.0011 :        for (; ntrap; ntrap--, traps++)
44497                :            (*ps->RasterizeTrapezoid) (pPicture, traps, 
44498                :                                       -bounds.x1, -bounds.y1);
44499                :        xRel = bounds.x1 + xSrc - xDst;
44500                :        yRel = bounds.y1 + ySrc - yDst;
44501                :        CompositePicture (op, pSrc, pPicture, pDst,
44502                :                          xRel, yRel, 0, 0, bounds.x1, bounds.y1,
44503                :                          bounds.x2 - bounds.x1,
44504                :                          bounds.y2 - bounds.y1);
44505                :        FreePicture (pPicture, 0);
44506                :    }
44507                :    else
44508                :    {
44509                :        if (pDst->polyEdge == PolyEdgeSharp)
44510                :            maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
44511                :        else
44512                :            maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
44513                :        for (; ntrap; ntrap--, traps++)
44514                :            miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
44515                :    }
44516                :}
44517 /* 
44518  * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-image.c"
44519  * 
44520  *     10  0.0109
44521  */
44522
44523
44524                :/*
44525                : * Copyright Â© 2000 SuSE, Inc.
44526                : * Copyright Â© 2007 Red Hat, Inc.
44527                : *
44528                : * Permission to use, copy, modify, distribute, and sell this software and its
44529                : * documentation for any purpose is hereby granted without fee, provided that
44530                : * the above copyright notice appear in all copies and that both that
44531                : * copyright notice and this permission notice appear in supporting
44532                : * documentation, and that the name of SuSE not be used in advertising or
44533                : * publicity pertaining to distribution of the software without specific,
44534                : * written prior permission.  SuSE makes no representations about the
44535                : * suitability of this software for any purpose.  It is provided "as is"
44536                : * without express or implied warranty.
44537                : *
44538                : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
44539                : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
44540                : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
44541                : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
44542                : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
44543                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44544                : */
44545                :
44546                :#include <config.h>
44547                :
44548                :#include <stdlib.h>
44549                :#include <stdio.h>
44550                :#include <string.h>
44551                :
44552                :#include "pixman.h"
44553                :#include "pixman-private.h"
44554                :
44555                :static void
44556                :init_source_image (source_image_t *image)
44557                :{
44558                :    image->class = SOURCE_IMAGE_CLASS_UNKNOWN;
44559                :}
44560                :
44561                :static pixman_bool_t
44562                :init_gradient (gradient_t     *gradient,
44563                :               const pixman_gradient_stop_t *stops,
44564                :               int             n_stops)
44565                :{
44566                :    return_val_if_fail (n_stops > 0, FALSE);
44567                :
44568                :    init_source_image (&gradient->common);
44569                :
44570                :    gradient->stops = malloc (n_stops * sizeof (pixman_gradient_stop_t));
44571                :    if (!gradient->stops)
44572                :        return FALSE;
44573                :
44574                :    memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
44575                :    
44576                :    gradient->n_stops = n_stops;
44577                :
44578                :    gradient->stop_range = 0xffff;
44579                :    gradient->color_table = NULL;
44580                :    gradient->color_table_size = 0;
44581                :
44582                :    return TRUE;
44583                :}
44584                :
44585                :static uint32_t
44586                :color_to_uint32 (const pixman_color_t *color)
44587                :{
44588                :    return
44589                :        (color->alpha >> 8 << 24) |
44590                :        (color->red >> 8 << 16) |
44591                :        (color->green & 0xff00) |
44592                :        (color->blue >> 8);
44593                :}
44594                :
44595                :static pixman_image_t *image_cache;
44596                :
44597                :static pixman_image_t *
44598                :new_image (void)
44599                :{
44600                :    pixman_image_t *image;
44601                :
44602                :    if (image_cache)
44603                :    {
44604                :        image = image_cache;
44605                :        image_cache = image->next;
44606                :    }
44607                :    else
44608                :    {
44609                :        image = malloc (sizeof (pixman_image_t));
44610                :    }
44611                :
44612                :    return image;
44613                :}
44614                :
44615                :static void
44616                :delete_image (pixman_image_t *image)
44617                :{
44618                :    image->next = image_cache;
44619                :    image_cache = image;
44620                :}
44621                :
44622                :static pixman_image_t *
44623                :allocate_image (void)
44624                :{ /* allocate_image total:      7  0.0076 */
44625                :    pixman_image_t *image = new_image();
44626                :    
44627                :    if (image)
44628                :    {
44629                :        image_common_t *common = &image->common;
44630                :
44631                :        pixman_region_init (&common->full_region);
44632      1  0.0011 :        pixman_region_init (&common->clip_region);
44633                :        common->src_clip = &common->full_region;
44634                :        common->has_client_clip = FALSE;
44635                :        common->transform = NULL;
44636                :        common->repeat = PIXMAN_REPEAT_NONE;
44637                :        common->filter = PIXMAN_FILTER_NEAREST;
44638                :        common->filter_params = NULL;
44639      1  0.0011 :        common->n_filter_params = 0;
44640      1  0.0011 :        common->alpha_map = NULL;
44641                :        common->component_alpha = FALSE;
44642      1  0.0011 :        common->ref_count = 1;
44643                :        common->read_func = NULL;
44644      1  0.0011 :        common->write_func = NULL;
44645                :    }
44646                :
44647                :    return image;
44648      2  0.0022 :}
44649                :
44650                :/* Ref Counting */
44651                :pixman_image_t *
44652                :pixman_image_ref (pixman_image_t *image)
44653                :{
44654                :    image->common.ref_count++;
44655                :
44656                :    return image;
44657                :}
44658                :
44659                :void
44660                :pixman_image_unref (pixman_image_t *image)
44661      1  0.0011 :{ /* pixman_image_unref total:      2  0.0022 */
44662                :    image_common_t *common = (image_common_t *)image;
44663                :
44664                :    common->ref_count--;
44665                :
44666                :    if (common->ref_count == 0)
44667                :    {
44668                :        pixman_region_fini (&common->clip_region);
44669                :        pixman_region_fini (&common->full_region);
44670                :
44671                :        if (common->transform)
44672                :            free (common->transform);
44673                :
44674                :        if (common->filter_params)
44675                :            free (common->filter_params);
44676                :
44677                :        if (common->alpha_map)
44678                :            pixman_image_unref ((pixman_image_t *)common->alpha_map);
44679                :
44680                :#if 0
44681                :        if (image->type == BITS && image->bits.indexed)
44682                :            free (image->bits.indexed);
44683                :#endif
44684                :        
44685                :#if 0
44686                :        memset (image, 0xaa, sizeof (pixman_image_t));
44687                :#endif
44688                :        if (image->type == LINEAR || image->type == RADIAL || image->type == CONICAL)
44689                :        {
44690                :            if (image->gradient.stops)
44691                :                free (image->gradient.stops);
44692                :        }
44693                :
44694                :        
44695                :        if (image->type == BITS && image->bits.free_me)
44696                :            free (image->bits.free_me);
44697                :        
44698                :        delete_image (image);
44699                :    }
44700                :}
44701                :
44702                :/* Constructors */
44703                :pixman_image_t *
44704                :pixman_image_create_solid_fill (pixman_color_t *color)
44705                :{
44706                :    pixman_image_t *img = allocate_image();
44707                :    if (!img)
44708                :        return NULL;
44709                :    
44710                :    init_source_image (&img->solid.common);
44711                :    
44712                :    img->type = SOLID;
44713                :    img->solid.color = color_to_uint32 (color);
44714                :
44715                :    return img;
44716                :}
44717                :
44718                :pixman_image_t *
44719                :pixman_image_create_linear_gradient (pixman_point_fixed_t         *p1,
44720                :                                     pixman_point_fixed_t         *p2,
44721                :                                     const pixman_gradient_stop_t *stops,
44722                :                                     int                           n_stops)
44723                :{
44724                :    pixman_image_t *image;
44725                :    linear_gradient_t *linear;
44726                :
44727                :    return_val_if_fail (n_stops >= 2, NULL);
44728                :    
44729                :    image = allocate_image();
44730                :    
44731                :    if (!image)
44732                :        return NULL;
44733                :
44734                :    linear = &image->linear;
44735                :    
44736                :    if (!init_gradient (&linear->common, stops, n_stops))
44737                :    {
44738                :        free (image);
44739                :        return NULL;
44740                :    }
44741                :
44742                :    linear->p1 = *p1;
44743                :    linear->p2 = *p2;
44744                :
44745                :    image->type = LINEAR;
44746                :
44747                :    return image;
44748                :}
44749                :
44750                :
44751                :pixman_image_t *
44752                :pixman_image_create_radial_gradient (pixman_point_fixed_t         *inner,
44753                :                                     pixman_point_fixed_t         *outer,
44754                :                                     pixman_fixed_t                inner_radius,
44755                :                                     pixman_fixed_t                outer_radius,
44756                :                                     const pixman_gradient_stop_t *stops,
44757                :                                     int                           n_stops)
44758                :{
44759                :    pixman_image_t *image;
44760                :    radial_gradient_t *radial;
44761                :
44762                :    return_val_if_fail (n_stops >= 2, NULL);
44763                :    
44764                :    image = allocate_image();
44765                :
44766                :    if (!image)
44767                :        return NULL;
44768                :
44769                :    radial = &image->radial;
44770                :
44771                :    if (!init_gradient (&radial->common, stops, n_stops))
44772                :    {
44773                :        free (image);
44774                :        return NULL;
44775                :    }
44776                :
44777                :    image->type = RADIAL;
44778                :    
44779                :    radial->c1.x = inner->x;
44780                :    radial->c1.y = inner->y;
44781                :    radial->c1.radius = inner_radius;
44782                :    radial->c2.x = outer->x;
44783                :    radial->c2.y = outer->y;
44784                :    radial->c2.radius = outer_radius;
44785                :    radial->cdx = pixman_fixed_to_double (radial->c2.x - radial->c1.x);
44786                :    radial->cdy = pixman_fixed_to_double (radial->c2.y - radial->c1.y);
44787                :    radial->dr = pixman_fixed_to_double (radial->c2.radius - radial->c1.radius);
44788                :    radial->A = (radial->cdx * radial->cdx
44789                :                 + radial->cdy * radial->cdy
44790                :                 - radial->dr  * radial->dr);
44791                :    
44792                :    return image;
44793                :}
44794                :
44795                :pixman_image_t *
44796                :pixman_image_create_conical_gradient (pixman_point_fixed_t *center,
44797                :                                      pixman_fixed_t angle,
44798                :                                      const pixman_gradient_stop_t *stops,
44799                :                                      int n_stops)
44800                :{
44801                :    pixman_image_t *image = allocate_image();
44802                :    conical_gradient_t *conical;
44803                :
44804                :    if (!image)
44805                :        return NULL;
44806                :
44807                :    conical = &image->conical;
44808                :    
44809                :    if (!init_gradient (&conical->common, stops, n_stops))
44810                :    {
44811                :        free (image);
44812                :        return NULL;
44813                :    }
44814                :
44815                :    image->type = CONICAL;
44816                :    conical->center = *center;
44817                :    conical->angle = angle;
44818                :
44819                :    return image;
44820                :}
44821                :
44822                :static uint32_t *
44823                :create_bits (pixman_format_code_t format,
44824                :             int                  width,
44825                :             int                  height,
44826                :             int                 *rowstride_bytes)
44827                :{
44828                :    int stride;
44829                :    int buf_size;
44830                :    int bpp;
44831                :    
44832                :    bpp = PIXMAN_FORMAT_BPP (format);
44833                :    stride = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (uint32_t);
44834                :    buf_size = height * stride;
44835                :
44836                :    if (rowstride_bytes)
44837                :        *rowstride_bytes = stride;
44838                :
44839                :    return calloc (buf_size, 1);
44840                :}
44841                :
44842                :static void
44843                :reset_clip_region (pixman_image_t *image)
44844                :{
44845                :    pixman_region_fini (&image->common.clip_region);
44846                :    
44847                :    if (image->type == BITS)
44848                :    {
44849                :        pixman_region_init_rect (&image->common.clip_region, 0, 0,
44850                :                                 image->bits.width, image->bits.height);        
44851                :    }
44852                :    else
44853                :    {
44854                :        pixman_region_init (&image->common.clip_region);
44855                :    }
44856                :}
44857                :
44858                :pixman_image_t *
44859                :pixman_image_create_bits (pixman_format_code_t  format,
44860                :                          int                   width,
44861                :                          int                   height,
44862                :                          uint32_t             *bits,
44863                :                          int                   rowstride_bytes)
44864      1  0.0011 :{ /* pixman_image_create_bits total:      1  0.0011 */
44865                :    pixman_image_t *image;
44866                :    uint32_t *free_me = NULL;
44867                :
44868                :    /* must be a whole number of uint32_t's 
44869                :     */
44870                :    return_val_if_fail (bits == NULL ||
44871                :                        (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); 
44872                :
44873                :    if (!bits)
44874                :    {
44875                :        free_me = bits = create_bits (format, width, height, &rowstride_bytes);
44876                :        if (!bits)
44877                :            return NULL;
44878                :    }
44879                :    
44880                :    image = allocate_image();
44881                :
44882                :    if (!image)
44883                :        return NULL;
44884                :    
44885                :    image->type = BITS;
44886                :    image->bits.format = format;
44887                :    image->bits.width = width;
44888                :    image->bits.height = height;
44889                :    image->bits.bits = bits;
44890                :    image->bits.free_me = free_me;
44891                :    
44892                :    image->bits.rowstride = rowstride_bytes / sizeof (uint32_t); /* we store it in number
44893                :                                                                  * of uint32_t's
44894                :                                                                  */
44895                :    image->bits.indexed = NULL;
44896                :
44897                :    pixman_region_fini (&image->common.full_region);
44898                :    pixman_region_init_rect (&image->common.full_region, 0, 0,
44899                :                             image->bits.width, image->bits.height);
44900                :
44901                :    reset_clip_region (image);
44902                :    return image;
44903                :}
44904                :
44905                :pixman_bool_t
44906                :pixman_image_set_clip_region (pixman_image_t    *image,
44907                :                              pixman_region16_t *region)
44908                :{
44909                :    image_common_t *common = (image_common_t *)image;
44910                :
44911                :    if (region)
44912                :    {
44913                :        return pixman_region_copy (&common->clip_region, region);
44914                :    }
44915                :    else
44916                :    {
44917                :        reset_clip_region (image);
44918                :        
44919                :        return TRUE;
44920                :    }
44921                :}
44922                :
44923                :/* Sets whether the clip region includes a clip region set by the client
44924                : */
44925                :void
44926                :pixman_image_set_has_client_clip (pixman_image_t *image,
44927                :                                  pixman_bool_t   client_clip)
44928                :{
44929                :    image->common.has_client_clip = client_clip;
44930                :}
44931                :
44932                :pixman_bool_t
44933                :pixman_image_set_transform (pixman_image_t           *image,
44934                :                            const pixman_transform_t *transform)
44935                :{
44936                :    static const pixman_transform_t id =
44937                :    {
44938                :        { { pixman_fixed_1, 0, 0 },
44939                :          { 0, pixman_fixed_1, 0 },
44940                :          { 0, 0, pixman_fixed_1 }
44941                :        }
44942                :    };
44943                :    
44944                :    image_common_t *common = (image_common_t *)image;
44945                :
44946                :    if (common->transform == transform)
44947                :        return TRUE;
44948                :
44949                :    if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
44950                :    {
44951                :        transform = NULL;
44952                :        return TRUE;
44953                :    }
44954                :    
44955                :    if (common->transform)
44956                :        free (common->transform);
44957                :
44958                :    if (transform)
44959                :    {
44960                :        common->transform = malloc (sizeof (pixman_transform_t));
44961                :        if (!common->transform)
44962                :            return FALSE;
44963                :
44964                :        *common->transform = *transform;
44965                :    }
44966                :    else
44967                :    {
44968                :        common->transform = NULL;
44969                :    }
44970                :
44971                :    return TRUE;
44972                :}
44973                :
44974                :void
44975                :pixman_image_set_repeat (pixman_image_t  *image,
44976                :                         pixman_repeat_t  repeat)
44977      1  0.0011 :{ /* pixman_image_set_repeat total:      1  0.0011 */
44978                :    image->common.repeat = repeat;
44979                :}
44980                :
44981                :pixman_bool_t 
44982                :pixman_image_set_filter (pixman_image_t       *image,
44983                :                         pixman_filter_t       filter,
44984                :                         const pixman_fixed_t *params,
44985                :                         int                   n_params)
44986                :{
44987                :    image_common_t *common = (image_common_t *)image;
44988                :    pixman_fixed_t *new_params;
44989                :
44990                :    if (params == common->filter_params && filter == common->filter)
44991                :        return TRUE;
44992                :
44993                :    new_params = NULL;
44994                :    if (params)
44995                :    {
44996                :        new_params = malloc (n_params * sizeof (pixman_fixed_t));
44997                :        if (!new_params)
44998                :            return FALSE;
44999                :
45000                :        memcpy (new_params,
45001                :                params, n_params * sizeof (pixman_fixed_t));
45002                :    }
45003                :
45004                :    common->filter = filter;
45005                :        
45006                :    if (common->filter_params)
45007                :        free (common->filter_params);
45008                :
45009                :    common->filter_params = new_params;
45010                :    common->n_filter_params = n_params;
45011                :    return TRUE;
45012                :}
45013                :
45014                :/* Unlike all the other property setters, this function does not
45015                : * copy the content of indexed. Doing this copying is simply
45016                : * way, way too expensive.
45017                : */
45018                :void
45019                :pixman_image_set_indexed (pixman_image_t         *image,
45020                :                          const pixman_indexed_t *indexed)
45021                :{
45022                :    bits_image_t *bits = (bits_image_t *)image;
45023                :
45024                :    bits->indexed = indexed;
45025                :}
45026                :
45027                :void
45028                :pixman_image_set_alpha_map (pixman_image_t *image,
45029                :                            pixman_image_t *alpha_map,
45030                :                            int16_t         x,
45031                :                            int16_t         y)
45032                :{
45033                :    image_common_t *common = (image_common_t *)image;
45034                :    
45035                :    return_if_fail (!alpha_map || alpha_map->type == BITS);
45036                :
45037                :    if (common->alpha_map != (bits_image_t *)alpha_map)
45038                :    {
45039                :        if (common->alpha_map)
45040                :            pixman_image_unref ((pixman_image_t *)common->alpha_map);
45041                :
45042                :        if (alpha_map)
45043                :            common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
45044                :        else
45045                :            common->alpha_map = NULL;
45046                :    }
45047                :
45048                :    common->alpha_origin.x = x;
45049                :    common->alpha_origin.y = y;
45050                :}
45051                :
45052                :void
45053                :pixman_image_set_component_alpha   (pixman_image_t       *image,
45054                :                                    pixman_bool_t         component_alpha)
45055                :{
45056                :    image->common.component_alpha = component_alpha;
45057                :}
45058                :
45059                :
45060                :void
45061                :pixman_image_set_accessors (pixman_image_t             *image,
45062                :                            pixman_read_memory_func_t   read_func,
45063                :                            pixman_write_memory_func_t  write_func)
45064                :{
45065                :    return_if_fail (image != NULL);
45066                :
45067                :    image->common.read_func = read_func;
45068                :    image->common.write_func = write_func;
45069                :}
45070                :
45071                :uint32_t *
45072                :pixman_image_get_data (pixman_image_t *image)
45073                :{
45074                :    if (image->type == BITS)
45075                :        return image->bits.bits;
45076                :
45077                :    return NULL;
45078                :}
45079                :
45080                :int
45081                :pixman_image_get_width (pixman_image_t *image)
45082                :{
45083                :    if (image->type == BITS)
45084                :        return image->bits.width;
45085                :
45086                :    return 0;
45087                :}
45088                :
45089                :int
45090                :pixman_image_get_height (pixman_image_t *image)
45091                :{
45092                :    if (image->type == BITS)
45093                :        return image->bits.height;
45094                :
45095                :    return 0;
45096                :}
45097                :
45098                :int
45099                :pixman_image_get_stride (pixman_image_t *image)
45100                :{
45101                :    if (image->type == BITS)
45102                :        return image->bits.rowstride * sizeof (uint32_t);
45103                :
45104                :    return 0;
45105                :}
45106                :
45107                :int
45108                :pixman_image_get_depth (pixman_image_t *image)
45109                :{
45110                :    if (image->type == BITS)
45111                :        return PIXMAN_FORMAT_DEPTH (image->bits.format);
45112                :
45113                :    return 0;
45114                :}
45115                :
45116                :pixman_bool_t
45117                :color_to_pixel (pixman_color_t *color,
45118                :                uint32_t       *pixel,
45119                :                pixman_format_code_t format)
45120                :{
45121                :    uint32_t c = color_to_uint32 (color);
45122                :
45123                :    if (!(format == PIXMAN_a8r8g8b8     ||
45124                :          format == PIXMAN_x8r8g8b8     ||
45125                :          format == PIXMAN_a8b8g8r8     ||
45126                :          format == PIXMAN_x8b8g8r8     ||
45127                :          format == PIXMAN_r5g6b5       ||
45128                :          format == PIXMAN_b5g6r5       ||
45129                :          format == PIXMAN_a8))
45130                :    {
45131                :        return FALSE;
45132                :    }
45133                :    
45134                :    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
45135                :    {
45136                :        c = ((c & 0xff000000) >>  0) |
45137                :            ((c & 0x00ff0000) >> 16) |
45138                :            ((c & 0x0000ff00) >>  0) |
45139                :            ((c & 0x000000ff) << 16);
45140                :    }
45141                :
45142                :    if (format == PIXMAN_a8)
45143                :        c = c >> 24;
45144                :    else if (format == PIXMAN_r5g6b5 ||
45145                :             format == PIXMAN_b5g6r5)
45146                :        c = cvt8888to0565 (c);
45147                :
45148                :#if 0
45149                :    printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
45150                :    printf ("pixel: %x\n", c);
45151                :#endif
45152                :    
45153                :    *pixel = c;
45154                :    return TRUE;
45155                :}
45156                :
45157                :pixman_bool_t
45158                :pixman_image_fill_rectangles (pixman_op_t                   op,
45159                :                              pixman_image_t               *dest,
45160                :                              pixman_color_t               *color,
45161                :                              int                           n_rects,
45162                :                              const pixman_rectangle16_t   *rects)
45163                :{
45164                :    pixman_image_t *solid;
45165                :    pixman_color_t c;
45166                :    int i;
45167                :    
45168                :    if (color->alpha == 0xffff)
45169                :    {
45170                :        if (op == PIXMAN_OP_OVER)
45171                :            op = PIXMAN_OP_SRC;
45172                :    }
45173                :
45174                :    if (op == PIXMAN_OP_CLEAR)
45175                :    {
45176                :        c.red = 0;
45177                :        c.green = 0;
45178                :        c.blue = 0;
45179                :        c.alpha = 0;
45180                :
45181                :        color = &c;
45182                :        
45183                :        op = PIXMAN_OP_SRC;
45184                :    }
45185                :
45186                :    if (op == PIXMAN_OP_SRC)
45187                :    {
45188                :        uint32_t pixel;
45189                :        
45190                :        if (color_to_pixel (color, &pixel, dest->bits.format))
45191                :        {
45192                :            for (i = 0; i < n_rects; ++i)
45193                :            {
45194                :                pixman_region16_t fill_region;
45195                :                int n_boxes, j;
45196                :                pixman_box16_t *boxes;
45197                :                
45198                :                pixman_region_init_rect (&fill_region, rects[i].x, rects[i].y, rects[i].width, rects[i].height);
45199                :                pixman_region_intersect (&fill_region, &fill_region, &dest->common.clip_region);
45200                :
45201                :                boxes = pixman_region_rectangles (&fill_region, &n_boxes);
45202                :                for (j = 0; j < n_boxes; ++j)
45203                :                {
45204                :                    const pixman_box16_t *box = &(boxes[j]);
45205                :                    pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
45206                :                                 box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1,
45207                :                                 pixel);
45208                :                }
45209                :
45210                :                pixman_region_fini (&fill_region);
45211                :            }
45212                :            return TRUE;
45213                :        }
45214                :    }
45215                :    
45216                :    solid = pixman_image_create_solid_fill (color);
45217                :    if (!solid)
45218                :        return FALSE;
45219                :
45220                :    for (i = 0; i < n_rects; ++i)
45221                :    {
45222                :        const pixman_rectangle16_t *rect = &(rects[i]);
45223                :        
45224                :        pixman_image_composite (op, solid, NULL, dest,
45225                :                                0, 0, 0, 0,
45226                :                                rect->x, rect->y,
45227                :                                rect->width, rect->height);
45228                :    }
45229                :    
45230                :    pixman_image_unref (solid);
45231                :
45232                :    return TRUE;
45233                :}
45234 /* 
45235  * Total samples for file : "/home/cworth/src/xorg/xserver/mi/mibstore.c"
45236  * 
45237  *      9  0.0098
45238  */
45239
45240
45241                :/***********************************************************
45242                :
45243                :Copyright 1987, 1998  The Open Group
45244                :
45245                :Permission to use, copy, modify, distribute, and sell this software and its
45246                :documentation for any purpose is hereby granted without fee, provided that
45247                :the above copyright notice appear in all copies and that both that
45248                :copyright notice and this permission notice appear in supporting
45249                :documentation.
45250                :
45251                :The above copyright notice and this permission notice shall be included in
45252                :all copies or substantial portions of the Software.
45253                :
45254                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45255                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45256                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
45257                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
45258                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
45259                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45260                :
45261                :Except as contained in this notice, the name of The Open Group shall not be
45262                :used in advertising or otherwise to promote the sale, use or other dealings
45263                :in this Software without prior written authorization from The Open Group.
45264                :
45265                :
45266                :Copyright 1987 by the Regents of the University of California
45267                :
45268                :                        All Rights Reserved
45269                :
45270                :Permission to use, copy, modify, and distribute this software and its
45271                :documentation for any purpose and without fee is hereby granted, provided
45272                :that the above copyright notice appear in all copies and that both that
45273                :copyright notice and this permission notice appear in supporting
45274                :documentation, and that the name The Open Group not be used in advertising or publicity
45275                :pertaining to distribution of the software without specific, written prior
45276                :permission.  
45277                :
45278                :The University of California makes no representations about the suitability
45279                :of this software for any purpose.  It is provided "as is" without express or
45280                :implied warranty.
45281                :
45282                :******************************************************************/
45283                :
45284                :
45285                :#define NEED_EVENTS
45286                :#ifdef HAVE_DIX_CONFIG_H
45287                :#include <dix-config.h>
45288                :#endif
45289                :
45290                :#include <X11/X.h>
45291                :#include <X11/Xmd.h>
45292                :#include <X11/Xproto.h>
45293                :#include "misc.h"
45294                :#include "regionstr.h"
45295                :#include "scrnintstr.h"
45296                :#include "gcstruct.h"
45297                :#include "windowstr.h"
45298                :#include "pixmapstr.h"
45299                :#include <X11/fonts/fontstruct.h>
45300                :#include "dixfontstr.h"
45301                :#include "dixstruct.h"          /* For requestingClient */
45302                :#include "mi.h"
45303                :#include "mibstorest.h"
45304                :
45305                :/*
45306                : * When the server fails to allocate a backing store pixmap, if you want
45307                : * it to dynamically retry to allocate backing store on every subsequent
45308                : * graphics op, you can enable BSEAGER; otherwise, backing store will be
45309                : * disabled on the window until it is unmapped and then remapped.
45310                : */
45311                :/* #define BSEAGER */
45312                :
45313                :/*-
45314                : * NOTES ON USAGE:
45315                : *
45316                : * The functions in this file implement a machine-independent backing-store
45317                : * scheme. To use it, the output library must do the following:
45318                : *      - Provide a SaveAreas function that takes a destination pixmap, a
45319                : *          region of the areas to save (in the pixmap's coordinate system)
45320                : *          and the screen origin of the region. It should copy the areas from
45321                : *          the screen into the pixmap.
45322                : *      - Provide a RestoreAreas function that takes a source pixmap, a region
45323                : *          of the areas to restore (in the screen's coordinate system) and the
45324                : *          origin of the pixmap on the screen. It should copy the areas from
45325                : *          the pixmap into the screen.
45326                : *      - Provide a SetClipmaskRgn function that takes a gc and a region
45327                : *          and merges the region into any CT_PIXMAP client clip that
45328                : *          is specified in the GC.  This routine is only needed if
45329                : *          miValidateBackingStore will see CT_PIXMAP clip lists; not
45330                : *          true for any of the sample servers (which convert the PIXMAP
45331                : *          clip lists into CT_REGION clip lists; an expensive but simple
45332                : *          to code option).
45333                : *      - The function placed in a window's ClearToBackground vector must call
45334                : *          pScreen->ClearBackingStore with the window, followed by
45335                : *          the window-relative x and y coordinates, followed by the width and
45336                : *          height of the area to be cleared, followed by the generateExposures
45337                : *          flag. This has been taken care of in miClearToBackground.
45338                : *      - Whatever determines GraphicsExpose events for the CopyArea and
45339                : *          CopyPlane requests should call pWin->backStorage->ExposeCopy
45340                : *          with the source and destination drawables, the GC used, a source-
45341                : *          window-relative region of exposed areas, the source and destination
45342                : *          coordinates and the bitplane copied, if CopyPlane, or 0, if
45343                : *          CopyArea.
45344                : *
45345                : * JUSTIFICATION
45346                : *    This is a cross between saving everything and just saving the
45347                : * obscued areas (as in Pike's layers.)  This method has the advantage
45348                : * of only doing each output operation once per pixel, visible or
45349                : * invisible, and avoids having to do all the crufty storage
45350                : * management of keeping several separate rectangles.  Since the
45351                : * ddx layer ouput primitives are required to draw through clipping
45352                : * rectangles anyway, sending multiple drawing requests for each of
45353                : * several rectangles isn't necessary.  (Of course, it could be argued
45354                : * that the ddx routines should just take one rectangle each and
45355                : * get called multiple times, but that would make taking advantage of
45356                : * smart hardware harder, and probably be slower as well.)
45357                : */
45358                :
45359                :#define SETUP_BACKING_TERSE(pGC) \
45360                :    miBSGCPtr   pGCPrivate = (miBSGCPtr)(pGC)->devPrivates[miBSGCIndex].ptr; \
45361                :    GCFuncs     *oldFuncs = pGC->funcs;
45362                :
45363                :#define SETUP_BACKING(pDrawable,pGC) \
45364                :    miBSWindowPtr pBackingStore = \
45365                :        (miBSWindowPtr)((WindowPtr)(pDrawable))->backStorage; \
45366                :    DrawablePtr   pBackingDrawable = (DrawablePtr) \
45367                :        pBackingStore->pBackingPixmap; \
45368                :    SETUP_BACKING_TERSE(pGC) \
45369                :    GCPtr       pBackingGC = pGCPrivate->pBackingGC;
45370                :
45371                :#define PROLOGUE(pGC) { \
45372                :    pGC->ops = pGCPrivate->wrapOps;\
45373                :    pGC->funcs = pGCPrivate->wrapFuncs; \
45374                :    }
45375                :
45376                :#define EPILOGUE(pGC) { \
45377                :    pGCPrivate->wrapOps = (pGC)->ops; \
45378                :    (pGC)->ops = &miBSGCOps; \
45379                :    (pGC)->funcs = oldFuncs; \
45380                :    }
45381                :   
45382                :static void         miCreateBSPixmap(WindowPtr pWin, BoxPtr pExtents);
45383                :static void         miDestroyBSPixmap(WindowPtr pWin);
45384                :static void         miTileVirtualBS(WindowPtr pWin);
45385                :static void         miBSAllocate(WindowPtr pWin), miBSFree(WindowPtr pWin);
45386                :static Bool         miBSCreateGCPrivate(GCPtr pGC);
45387                :static void         miBSClearBackingRegion(WindowPtr pWin, RegionPtr pRgn);
45388                :
45389                :#define MoreCopy0 ;
45390                :#define MoreCopy2 *dstCopy++ = *srcCopy++; *dstCopy++ = *srcCopy++;
45391                :#define MoreCopy4 MoreCopy2 MoreCopy2
45392                :
45393                :#define copyData(src,dst,n,morecopy) \
45394                :{ \
45395                :    short *srcCopy = (short *)(src); \
45396                :    short *dstCopy = (short *)(dst); \
45397                :    int i; \
45398                :    int bsx = pBackingStore->x; \
45399                :    int bsy = pBackingStore->y; \
45400                :    for (i = n; --i >= 0; ) \
45401                :    { \
45402                :        *dstCopy++ = *srcCopy++ - bsx; \
45403                :        *dstCopy++ = *srcCopy++ - bsy; \
45404                :        morecopy \
45405                :    } \
45406                :}
45407                :
45408                :#define copyPoints(src,dst,n,mode) \
45409                :if (mode == CoordModeOrigin) \
45410                :{ \
45411                :    copyData(src,dst,n,MoreCopy0); \
45412                :} \
45413                :else \
45414                :{ \
45415                :    memmove((char *)(dst), (char *)(src), (n) << 2); \
45416                :    *((short *)(dst)) -= pBackingStore->x; \
45417                :    *((short *)(dst) + 1) -= pBackingStore->y; \
45418                :}
45419                :
45420                :/*
45421                : * wrappers for screen funcs
45422                : */
45423                :
45424                :static int  miBSScreenIndex;
45425                :static unsigned long miBSGeneration = 0;
45426                :
45427                :static Bool         miBSCloseScreen(int i, ScreenPtr pScreen);
45428                :static void         miBSGetImage(DrawablePtr pDrawable, int sx, int sy,
45429                :                                 int w, int h, unsigned int format,
45430                :                                 unsigned long planemask, char *pdstLine);
45431                :static void         miBSGetSpans(DrawablePtr pDrawable, int wMax,
45432                :                                 DDXPointPtr ppt, int *pwidth, int nspans,
45433                :                                 char *pdstStart);
45434                :static Bool         miBSChangeWindowAttributes(WindowPtr pWin,
45435                :                                               unsigned long mask);
45436                :static Bool         miBSCreateGC(GCPtr pGC);
45437                :static Bool         miBSDestroyWindow(WindowPtr pWin);
45438                :
45439                :/*
45440                : * backing store screen functions
45441                : */
45442                :
45443                :static void         miBSSaveDoomedAreas(WindowPtr pWin, RegionPtr pObscured,
45444                :                                        int dx, int dy);
45445                :static RegionPtr    miBSRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
45446                :static void         miBSExposeCopy(WindowPtr pSrc, DrawablePtr pDst,
45447                :                                   GCPtr pGC, RegionPtr prgnExposed,
45448                :                                   int srcx, int srcy, int dstx, int dsty,
45449                :                                   unsigned long plane);
45450                :static RegionPtr    miBSTranslateBackingStore(WindowPtr pWin, int windx,
45451                :                                              int windy, RegionPtr oldClip,
45452                :                                              int oldx, int oldy);
45453                :static RegionPtr    miBSClearBackingStore(WindowPtr pWin, int x, int y,
45454                :                                          int w, int h, Bool generateExposures);
45455                :static void         miBSDrawGuarantee(WindowPtr pWin, GCPtr pGC,
45456                :                                      int guarantee);
45457                :
45458                :/*
45459                : * wrapper vectors for GC funcs and ops
45460                : */
45461                :
45462                :static int  miBSGCIndex;
45463                :
45464                :static void miBSValidateGC(GCPtr pGC, unsigned long stateChanges,
45465                :                           DrawablePtr pDrawable);
45466                :static void miBSCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
45467                :static void miBSDestroyGC(GCPtr pGC);
45468                :static void miBSChangeGC(GCPtr pGC, unsigned long mask);
45469                :static void miBSChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
45470                :static void miBSDestroyClip(GCPtr pGC);
45471                :static void miBSCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
45472                :
45473                :static GCFuncs  miBSGCFuncs = {
45474                :    miBSValidateGC,
45475                :    miBSChangeGC,
45476                :    miBSCopyGC,
45477                :    miBSDestroyGC,
45478                :    miBSChangeClip,
45479                :    miBSDestroyClip,
45480                :    miBSCopyClip,
45481                :};
45482                :
45483                :static void         miBSFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
45484                :                                  DDXPointPtr pptInit, int *pwidthInit,
45485                :                                  int fSorted);
45486                :static void         miBSSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
45487                :                                 DDXPointPtr ppt, int *pwidth, int nspans,
45488                :                                 int fSorted);
45489                :static void         miBSPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
45490                :                                 int x, int y, int w, int h, int leftPad,
45491                :                                 int format, char *pBits);
45492                :static RegionPtr    miBSCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
45493                :                                 GCPtr pGC, int srcx, int srcy, int w, int h,
45494                :                                 int dstx, int dsty);
45495                :static RegionPtr    miBSCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
45496                :                                  GCPtr pGC, int srcx, int srcy, int w, int h,
45497                :                                  int dstx, int dsty, unsigned long plane);
45498                :static void         miBSPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
45499                :                                  int npt, xPoint *pptInit);
45500                :static void         miBSPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
45501                :                                  int npt, DDXPointPtr pptInit);
45502                :static void         miBSPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
45503                :                                    xSegment *pSegs);
45504                :static void         miBSPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
45505                :                                      int nrects, xRectangle *pRects);
45506                :static void         miBSPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
45507                :                                xArc *parcs);
45508                :static void         miBSFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
45509                :                                    int shape, int mode, int count,
45510                :                                    DDXPointPtr pPts);
45511                :static void         miBSPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
45512                :                                     int nrectFill, xRectangle *prectInit);
45513                :static void         miBSPolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
45514                :                                    int narcs, xArc *parcs);
45515                :static int          miBSPolyText8(DrawablePtr pDrawable, GCPtr pGC,
45516                :                                  int x, int y, int count, char *chars);
45517                :static int          miBSPolyText16(DrawablePtr pDrawable, GCPtr pGC,
45518                :                                   int x, int y, int count,
45519                :                                   unsigned short *chars);
45520                :static void         miBSImageText8(DrawablePtr pDrawable, GCPtr pGC,
45521                :                                   int x, int y, int count, char *chars);
45522                :static void         miBSImageText16(DrawablePtr pDrawable, GCPtr pGC,
45523                :                                    int x, int y, int count,
45524                :                                    unsigned short *chars);
45525                :static void         miBSImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
45526                :                                      int x, int y, unsigned int nglyph,
45527                :                                      CharInfoPtr *ppci, pointer pglyphBase);
45528                :static void         miBSPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
45529                :                                     int x, int y, unsigned int nglyph,
45530                :                                     CharInfoPtr *ppci, pointer pglyphBase);
45531                :static void         miBSPushPixels(GCPtr pGC, PixmapPtr pBitMap,
45532                :                                   DrawablePtr pDst, int w, int h,
45533                :                                   int x, int y);
45534                :
45535                :static GCOps miBSGCOps = {
45536                :    miBSFillSpans,      miBSSetSpans,       miBSPutImage,       
45537                :    miBSCopyArea,       miBSCopyPlane,      miBSPolyPoint,
45538                :    miBSPolylines,      miBSPolySegment,    miBSPolyRectangle,
45539                :    miBSPolyArc,        miBSFillPolygon,    miBSPolyFillRect,
45540                :    miBSPolyFillArc,    miBSPolyText8,      miBSPolyText16,
45541                :    miBSImageText8,     miBSImageText16,    miBSImageGlyphBlt,
45542                :    miBSPolyGlyphBlt,   miBSPushPixels
45543                :};
45544                :
45545                :#define FUNC_PROLOGUE(pGC, pPriv) \
45546                :    ((pGC)->funcs = pPriv->wrapFuncs),\
45547                :    ((pGC)->ops = pPriv->wrapOps)
45548                :
45549                :#define FUNC_EPILOGUE(pGC, pPriv) \
45550                :    ((pGC)->funcs = &miBSGCFuncs),\
45551                :    ((pGC)->ops = &miBSGCOps)
45552                :
45553                :/*
45554                : * every GC in the server is initially wrapped with these
45555                : * "cheap" functions.  This allocates no memory and is used
45556                : * to discover GCs used with windows which have backing
45557                : * store enabled
45558                : */
45559                :
45560                :static void miBSCheapValidateGC(GCPtr pGC, unsigned long stateChanges,
45561                :                                DrawablePtr pDrawable);
45562                :static void miBSCheapCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
45563                :static void miBSCheapDestroyGC(GCPtr pGC);
45564                :static void miBSCheapChangeGC(GCPtr pGC, unsigned long mask);
45565                :static void miBSCheapChangeClip(GCPtr pGC, int type, pointer pvalue,
45566                :                                int nrects);
45567                :static void miBSCheapDestroyClip(GCPtr pGC);
45568                :static void miBSCheapCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
45569                :
45570                :static GCFuncs miBSCheapGCFuncs = {
45571                :    miBSCheapValidateGC,
45572                :    miBSCheapChangeGC,
45573                :    miBSCheapCopyGC,
45574                :    miBSCheapDestroyGC,
45575                :    miBSCheapChangeClip,
45576                :    miBSCheapDestroyClip,
45577                :    miBSCheapCopyClip,
45578                :};
45579                :
45580                :#define CHEAP_FUNC_PROLOGUE(pGC) \
45581                :    ((pGC)->funcs = (GCFuncs *) (pGC)->devPrivates[miBSGCIndex].ptr)
45582                :
45583                :#define CHEAP_FUNC_EPILOGUE(pGC) \
45584                :    ((pGC)->funcs = &miBSCheapGCFuncs)
45585                :
45586                :/*
45587                : * called from device screen initialization proc.  Gets a GCPrivateIndex
45588                : * and wraps appropriate per-screen functions.  pScreen->BackingStoreFuncs
45589                : * must be previously initialized.
45590                : */
45591                :
45592                :_X_EXPORT void
45593                :miInitializeBackingStore (pScreen)
45594                :    ScreenPtr   pScreen;
45595                :{
45596                :    miBSScreenPtr    pScreenPriv;
45597                :
45598                :    if (miBSGeneration != serverGeneration)
45599                :    {
45600                :        miBSScreenIndex = AllocateScreenPrivateIndex ();
45601                :        if (miBSScreenIndex < 0)
45602                :            return;
45603                :        miBSGCIndex = AllocateGCPrivateIndex ();
45604                :        miBSGeneration = serverGeneration;
45605                :    }
45606                :    if (!AllocateGCPrivate(pScreen, miBSGCIndex, 0))
45607                :        return;
45608                :    pScreenPriv = (miBSScreenPtr) xalloc (sizeof (miBSScreenRec));
45609                :    if (!pScreenPriv)
45610                :        return;
45611                :
45612                :    pScreenPriv->CloseScreen = pScreen->CloseScreen;
45613                :    pScreenPriv->GetImage = pScreen->GetImage;
45614                :    pScreenPriv->GetSpans = pScreen->GetSpans;
45615                :    pScreenPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
45616                :    pScreenPriv->CreateGC = pScreen->CreateGC;
45617                :    pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
45618                :
45619                :    pScreen->CloseScreen = miBSCloseScreen;
45620                :    pScreen->GetImage = miBSGetImage;
45621                :    pScreen->GetSpans = miBSGetSpans;
45622                :    pScreen->ChangeWindowAttributes = miBSChangeWindowAttributes;
45623                :    pScreen->CreateGC = miBSCreateGC;
45624                :    pScreen->DestroyWindow = miBSDestroyWindow;
45625                :
45626                :    pScreen->SaveDoomedAreas = miBSSaveDoomedAreas;
45627                :    pScreen->RestoreAreas = miBSRestoreAreas;
45628                :    pScreen->ExposeCopy = miBSExposeCopy;
45629                :    pScreen->TranslateBackingStore = miBSTranslateBackingStore;
45630                :    pScreen->ClearBackingStore = miBSClearBackingStore;
45631                :    pScreen->DrawGuarantee = miBSDrawGuarantee;
45632                :
45633                :    pScreen->devPrivates[miBSScreenIndex].ptr = (pointer) pScreenPriv;
45634                :}
45635                :
45636                :/*
45637                : * Screen function wrappers
45638                : */
45639                :
45640                :#define SCREEN_PROLOGUE(pScreen, field)\
45641                :  ((pScreen)->field = \
45642                :   ((miBSScreenPtr) \
45643                :    (pScreen)->devPrivates[miBSScreenIndex].ptr)->field)
45644                :
45645                :#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
45646                :    ((pScreen)->field = wrapper)
45647                :
45648                :/*
45649                : * CloseScreen wrapper -- unwrap everything, free the private data
45650                : * and call the wrapped function
45651                : */
45652                :
45653                :static Bool
45654                :miBSCloseScreen (i, pScreen)
45655                :    int         i;
45656                :    ScreenPtr   pScreen;
45657                :{
45658                :    miBSScreenPtr   pScreenPriv;
45659                :
45660                :    pScreenPriv = (miBSScreenPtr) pScreen->devPrivates[miBSScreenIndex].ptr;
45661                :
45662                :    pScreen->CloseScreen = pScreenPriv->CloseScreen;
45663                :    pScreen->GetImage = pScreenPriv->GetImage;
45664                :    pScreen->GetSpans = pScreenPriv->GetSpans;
45665                :    pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes;
45666                :    pScreen->CreateGC = pScreenPriv->CreateGC;
45667                :
45668                :    xfree ((pointer) pScreenPriv);
45669                :
45670                :    return (*pScreen->CloseScreen) (i, pScreen);
45671                :}
45672                :
45673                :static void miBSFillVirtualBits(DrawablePtr pDrawable, GCPtr pGC,
45674                :                                RegionPtr pRgn, int x, int y, int state,
45675                :                                PixUnion pixunion, unsigned long planemask);
45676                :
45677                :static void
45678                :miBSGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
45679                :    DrawablePtr     pDrawable;
45680                :    int             sx, sy, w, h;
45681                :    unsigned int    format;
45682                :    unsigned long   planemask;
45683                :    char            *pdstLine;
45684                :{
45685                :    ScreenPtr               pScreen = pDrawable->pScreen;
45686                :    BoxRec                  bounds;
45687                :    unsigned char           depth;
45688                :    
45689                :    SCREEN_PROLOGUE (pScreen, GetImage);
45690                :
45691                :    if (pDrawable->type != DRAWABLE_PIXMAP &&
45692                :        ((WindowPtr) pDrawable)->visibility != VisibilityUnobscured)
45693                :    {
45694                :        PixmapPtr       pPixmap;
45695                :        miBSWindowPtr   pWindowPriv;
45696                :        GCPtr           pGC = NULL;
45697                :        WindowPtr       pWin, pSrcWin;
45698                :        int             xoff, yoff;
45699                :        RegionRec       Remaining;
45700                :        RegionRec       Border;
45701                :        RegionRec       Inside;
45702                :        BoxPtr          pBox;
45703                :        int             n;
45704                :
45705                :        pWin = (WindowPtr) pDrawable;
45706                :        pPixmap = 0;
45707                :        depth = pDrawable->depth;
45708                :        bounds.x1 = sx + pDrawable->x;
45709                :        bounds.y1 = sy + pDrawable->y;
45710                :        bounds.x2 = bounds.x1 + w;
45711                :        bounds.y2 = bounds.y1 + h;
45712                :        REGION_INIT(pScreen, &Remaining, &bounds, 0);
45713                :        for (;;)
45714                :        {
45715                :            bounds.x1 = sx + pDrawable->x - pWin->drawable.x;
45716                :            bounds.y1 = sy + pDrawable->y - pWin->drawable.y;
45717                :            bounds.x2 = bounds.x1 + w;
45718                :            bounds.y2 = bounds.y1 + h;
45719                :            if (pWin->viewable && pWin->backStorage &&
45720                :                pWin->drawable.depth == depth &&
45721                :                (RECT_IN_REGION(pScreen, &(pWindowPriv =
45722                :                    (miBSWindowPtr) pWin->backStorage)->SavedRegion,
45723                :                    &bounds) != rgnOUT ||
45724                :                 RECT_IN_REGION(pScreen, &Remaining,
45725                :                  REGION_EXTENTS(pScreen, &pWin->borderSize)) != rgnOUT))
45726                :            {
45727                :                if (!pPixmap)
45728                :                {
45729                :                    XID subWindowMode = IncludeInferiors;
45730                :                    int x, y;
45731                :
45732                :                    pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, depth);
45733                :                    if (!pPixmap)
45734                :                        goto punt;
45735                :                    pGC = GetScratchGC (depth, pScreen);
45736                :                    if (!pGC)
45737                :                    {
45738                :                        (*pScreen->DestroyPixmap) (pPixmap);
45739                :                        goto punt;
45740                :                    }
45741                :                    ChangeGC (pGC, GCSubwindowMode, &subWindowMode);
45742                :                    ValidateGC ((DrawablePtr)pPixmap, pGC);
45743                :                    REGION_NULL(pScreen, &Border);
45744                :                    REGION_NULL(pScreen, &Inside);
45745                :                    pSrcWin = (WindowPtr) pDrawable;
45746                :                    x = sx;
45747                :                    y = sy;
45748                :                    if (pSrcWin->parent)
45749                :                    {
45750                :                        x += pSrcWin->origin.x;
45751                :                        y += pSrcWin->origin.y;
45752                :                        pSrcWin = pSrcWin->parent;
45753                :                    }
45754                :                    (*pGC->ops->CopyArea) ((DrawablePtr)pSrcWin,
45755                :                                            (DrawablePtr)pPixmap, pGC,
45756                :                                            x, y, w, h,
45757                :                                            0, 0);
45758                :                    REGION_SUBTRACT(pScreen, &Remaining, &Remaining,
45759                :                                    &((WindowPtr) pDrawable)->borderClip);
45760                :                }
45761                :
45762                :                REGION_INTERSECT(pScreen, &Inside, &Remaining, &pWin->winSize);
45763                :                REGION_TRANSLATE(pScreen, &Inside,
45764                :                                             -pWin->drawable.x,
45765                :                                             -pWin->drawable.y);
45766                :                REGION_INTERSECT(pScreen, &Inside, &Inside,
45767                :                                 &pWindowPriv->SavedRegion);
45768                :
45769                :                /* offset of sub-window in GetImage pixmap */
45770                :                xoff = pWin->drawable.x - pDrawable->x - sx;
45771                :                yoff = pWin->drawable.y - pDrawable->y - sy;
45772                :
45773                :                if (REGION_NUM_RECTS(&Inside) > 0)
45774                :                {
45775                :                    switch (pWindowPriv->status)
45776                :                    {
45777                :                    case StatusContents:
45778                :                        pBox = REGION_RECTS(&Inside);
45779                :                        for (n = REGION_NUM_RECTS(&Inside); --n >= 0;)
45780                :                        {
45781                :                            (*pGC->ops->CopyArea) (
45782                :                                (DrawablePtr)pWindowPriv->pBackingPixmap,
45783                :                                                   (DrawablePtr)pPixmap, pGC,
45784                :                                                   pBox->x1 - pWindowPriv->x,
45785                :                                                   pBox->y1 - pWindowPriv->y,
45786                :                                                   pBox->x2 - pBox->x1,
45787                :                                                   pBox->y2 - pBox->y1,
45788                :                                                   pBox->x1 + xoff,
45789                :                                                   pBox->y1 + yoff);
45790                :                            ++pBox;
45791                :                        }
45792                :                        break;
45793                :                    case StatusVirtual:
45794                :                    case StatusVDirty:
45795                :                        if (pWindowPriv->backgroundState == BackgroundPixmap ||
45796                :                            pWindowPriv->backgroundState == BackgroundPixel)
45797                :                        miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Inside,
45798                :                                            xoff, yoff,
45799                :                                            (int) pWindowPriv->backgroundState,
45800                :                                            pWindowPriv->background, ~0L);
45801                :                        break;
45802                :                    }
45803                :                }
45804                :                REGION_SUBTRACT(pScreen, &Border, &pWin->borderSize,
45805                :                                &pWin->winSize);
45806                :                REGION_INTERSECT(pScreen, &Border, &Border, &Remaining);
45807                :                if (REGION_NUM_RECTS(&Border) > 0)
45808                :                {
45809                :                    REGION_TRANSLATE(pScreen, &Border, -pWin->drawable.x,
45810                :                                                  -pWin->drawable.y);
45811                :                    miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Border,
45812                :                                        xoff, yoff,
45813                :                                        pWin->borderIsPixel ? (int)BackgroundPixel : (int)BackgroundPixmap,
45814                :                                        pWin->border, ~0L);
45815                :                }
45816                :            }
45817                :
45818                :            if (pWin->viewable && pWin->firstChild)
45819                :                pWin = pWin->firstChild;
45820                :            else
45821                :            {
45822                :                while (!pWin->nextSib && pWin != (WindowPtr) pDrawable)
45823                :                    pWin = pWin->parent;
45824                :                if (pWin == (WindowPtr) pDrawable)
45825                :                    break;
45826                :                pWin = pWin->nextSib;
45827                :            }
45828                :        }
45829                :
45830                :        REGION_UNINIT(pScreen, &Remaining);
45831                :
45832                :        if (pPixmap)
45833                :        {
45834                :            REGION_UNINIT(pScreen, &Border);
45835                :            REGION_UNINIT(pScreen, &Inside);
45836                :            (*pScreen->GetImage) ((DrawablePtr) pPixmap,
45837                :                0, 0, w, h, format, planemask, pdstLine);
45838                :            (*pScreen->DestroyPixmap) (pPixmap);
45839                :            FreeScratchGC (pGC);
45840                :        }
45841                :        else
45842                :        {
45843                :            goto punt;
45844                :        }
45845                :    }
45846                :    else
45847                :    {
45848                :punt:   ;
45849                :        (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
45850                :                              format, planemask, pdstLine);
45851                :    }
45852                :
45853                :    SCREEN_EPILOGUE (pScreen, GetImage, miBSGetImage);
45854                :}
45855                :
45856                :static void
45857                :miBSGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
45858                :    DrawablePtr pDrawable;
45859                :    int         wMax;
45860                :    DDXPointPtr ppt;
45861                :    int         *pwidth;
45862                :    int         nspans;
45863                :    char        *pdstStart;
45864                :{
45865                :    ScreenPtr               pScreen = pDrawable->pScreen;
45866                :    BoxRec                  bounds;
45867                :    int                     i;
45868                :    WindowPtr               pWin;
45869                :    int                     dx, dy;
45870                :    
45871                :    SCREEN_PROLOGUE (pScreen, GetSpans);
45872                :
45873                :    if (pDrawable->type != DRAWABLE_PIXMAP && ((WindowPtr) pDrawable)->backStorage)
45874                :    {
45875                :        PixmapPtr       pPixmap;
45876                :        miBSWindowPtr   pWindowPriv;
45877                :        GCPtr           pGC;
45878                :
45879                :        pWin = (WindowPtr) pDrawable;
45880                :        pWindowPriv = (miBSWindowPtr) pWin->backStorage;
45881                :        pPixmap = pWindowPriv->pBackingPixmap;
45882                :
45883                :        bounds.x1 = ppt->x;
45884                :        bounds.y1 = ppt->y;
45885                :        bounds.x2 = bounds.x1 + *pwidth;
45886                :        bounds.y2 = ppt->y;
45887                :        for (i = 0; i < nspans; i++)
45888                :        {
45889                :            if (ppt[i].x < bounds.x1)
45890                :                bounds.x1 = ppt[i].x;
45891                :            if (ppt[i].x + pwidth[i] > bounds.x2)
45892                :                bounds.x2 = ppt[i].x + pwidth[i];
45893                :            if (ppt[i].y < bounds.y1)
45894                :                bounds.y1 = ppt[i].y;
45895                :            else if (ppt[i].y > bounds.y2)
45896                :                bounds.y2 = ppt[i].y;
45897                :        }
45898                :    
45899                :        switch (RECT_IN_REGION(pScreen, &pWindowPriv->SavedRegion, &bounds))
45900                :        {
45901                :        case rgnPART:
45902                :            if (!pPixmap)
45903                :            {
45904                :                miCreateBSPixmap (pWin, NullBox);
45905                :                if (!(pPixmap = pWindowPriv->pBackingPixmap))
45906                :                    break;
45907                :            }
45908                :            pWindowPriv->status = StatusNoPixmap;
45909                :            pGC = GetScratchGC(pPixmap->drawable.depth,
45910                :                               pPixmap->drawable.pScreen);
45911                :            if (pGC)
45912                :            {
45913                :                ValidateGC ((DrawablePtr) pPixmap, pGC);
45914                :                (*pGC->ops->CopyArea)
45915                :                    (pDrawable, (DrawablePtr) pPixmap, pGC,
45916                :                    bounds.x1, bounds.y1,
45917                :                    bounds.x2 - bounds.x1, bounds.y2 - bounds.y1,
45918                :                    bounds.x1 + pPixmap->drawable.x - pWin->drawable.x -
45919                :                     pWindowPriv->x,
45920                :                    bounds.y1 + pPixmap->drawable.y - pWin->drawable.y -
45921                :                     pWindowPriv->y);
45922                :                FreeScratchGC(pGC);
45923                :            }
45924                :            pWindowPriv->status = StatusContents;
45925                :            /* fall through */
45926                :        case rgnIN:
45927                :            if (!pPixmap)
45928                :            {
45929                :                miCreateBSPixmap (pWin, NullBox);
45930                :                if (!(pPixmap = pWindowPriv->pBackingPixmap))
45931                :                    break;
45932                :            }
45933                :            dx = pPixmap->drawable.x - pWin->drawable.x - pWindowPriv->x;
45934                :            dy = pPixmap->drawable.y - pWin->drawable.y - pWindowPriv->y;
45935                :            for (i = 0; i < nspans; i++)
45936                :            {
45937                :                ppt[i].x += dx;
45938                :                ppt[i].y += dy;
45939                :            }
45940                :            (*pScreen->GetSpans) ((DrawablePtr) pPixmap, wMax, ppt, pwidth,
45941                :                                  nspans, pdstStart);
45942                :            break;
45943                :        case rgnOUT:
45944                :            (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans,
45945                :                                  pdstStart);
45946                :            break;
45947                :        }
45948                :    }
45949                :    else
45950                :    {
45951                :        (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
45952                :    }
45953                :
45954                :    SCREEN_EPILOGUE (pScreen, GetSpans, miBSGetSpans);
45955                :}
45956                :
45957                :static Bool
45958                :miBSChangeWindowAttributes (pWin, mask)
45959                :    WindowPtr       pWin;
45960                :    unsigned long   mask;
45961                :{
45962                :    ScreenPtr   pScreen;
45963                :    Bool        ret;
45964                :
45965                :    pScreen = pWin->drawable.pScreen;
45966                :
45967                :    SCREEN_PROLOGUE (pScreen, ChangeWindowAttributes);
45968                :
45969                :    ret = (*pScreen->ChangeWindowAttributes) (pWin, mask);
45970                :
45971                :    if (ret && (mask & CWBackingStore))
45972                :    {
45973                :        if (pWin->backingStore != NotUseful || pWin->DIXsaveUnder)
45974                :            miBSAllocate (pWin);
45975                :        else
45976                :            miBSFree (pWin);
45977                :    }
45978                :
45979                :    SCREEN_EPILOGUE (pScreen, ChangeWindowAttributes, miBSChangeWindowAttributes);
45980                :
45981                :    return ret;
45982                :}
45983                :
45984                :/*
45985                : * GC Create wrapper.  Set up the cheap GC func wrappers to track
45986                : * GC validation on BackingStore windows
45987                : */
45988                :
45989                :static Bool
45990                :miBSCreateGC (pGC)
45991                :    GCPtr   pGC;
45992                :{
45993                :    ScreenPtr   pScreen = pGC->pScreen;
45994                :    Bool        ret;
45995                :
45996                :    SCREEN_PROLOGUE (pScreen, CreateGC);
45997                :    
45998                :    if ( (ret = (*pScreen->CreateGC) (pGC)) )
45999                :    {
46000                :        pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs;
46001                :        pGC->funcs = &miBSCheapGCFuncs;
46002                :    }
46003                :
46004                :    SCREEN_EPILOGUE (pScreen, CreateGC, miBSCreateGC);
46005                :
46006                :    return ret;
46007                :}
46008                :
46009                :static Bool
46010                :miBSDestroyWindow (pWin)
46011                :    WindowPtr   pWin;
46012                :{
46013                :    ScreenPtr   pScreen = pWin->drawable.pScreen;
46014                :    Bool        ret;
46015                :
46016                :    SCREEN_PROLOGUE (pScreen, DestroyWindow);
46017                :    
46018                :    ret = (*pScreen->DestroyWindow) (pWin);
46019                :
46020                :    miBSFree (pWin);
46021                :
46022                :    SCREEN_EPILOGUE (pScreen, DestroyWindow, miBSDestroyWindow);
46023                :
46024                :    return ret;
46025                :}
46026                :
46027                :/*
46028                : * cheap GC func wrappers.  Simply track validation on windows
46029                : * with backing store to enable the real func/op wrappers
46030                : */
46031                :
46032                :static void
46033                :miBSCheapValidateGC (pGC, stateChanges, pDrawable)
46034                :    GCPtr           pGC;
46035                :    unsigned long   stateChanges;
46036                :    DrawablePtr     pDrawable;
46037      1  0.0011 :{ /* miBSCheapValidateGC total:      5  0.0054 */
46038                :    CHEAP_FUNC_PROLOGUE (pGC);
46039                :    
46040      1  0.0011 :    if (pDrawable->type != DRAWABLE_PIXMAP &&
46041                :        ((WindowPtr) pDrawable)->backStorage != NULL &&
46042                :        miBSCreateGCPrivate (pGC))
46043                :    {
46044                :        (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
46045                :    }
46046                :    else
46047                :    {
46048                :        (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
46049                :
46050                :        /* rewrap funcs as Validate may have changed them */
46051                :        pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs;
46052                :
46053      1  0.0011 :        CHEAP_FUNC_EPILOGUE (pGC);
46054                :    }
46055      2  0.0022 :}
46056                :
46057                :static void
46058                :miBSCheapChangeGC (pGC, mask)
46059                :    GCPtr   pGC;
46060                :    unsigned long   mask;
46061      1  0.0011 :{ /* miBSCheapChangeGC total:      1  0.0011 */
46062                :    CHEAP_FUNC_PROLOGUE (pGC);
46063                :
46064                :    (*pGC->funcs->ChangeGC) (pGC, mask);
46065                :
46066                :    CHEAP_FUNC_EPILOGUE (pGC);
46067                :}
46068                :
46069                :static void
46070                :miBSCheapCopyGC (pGCSrc, mask, pGCDst)
46071                :    GCPtr   pGCSrc, pGCDst;
46072                :    unsigned long   mask;
46073                :{
46074                :    CHEAP_FUNC_PROLOGUE (pGCDst);
46075                :
46076                :    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
46077                :
46078                :    CHEAP_FUNC_EPILOGUE (pGCDst);
46079                :}
46080                :
46081                :static void
46082                :miBSCheapDestroyGC (pGC)
46083                :    GCPtr   pGC;
46084                :{
46085                :    CHEAP_FUNC_PROLOGUE (pGC);
46086                :
46087                :    (*pGC->funcs->DestroyGC) (pGC);
46088                :
46089                :    /* leave it unwrapped */
46090                :}
46091                :
46092                :static void
46093                :miBSCheapChangeClip (pGC, type, pvalue, nrects)
46094                :    GCPtr   pGC;
46095                :    int         type;
46096                :    pointer     pvalue;
46097                :    int         nrects;
46098      1  0.0011 :{ /* miBSCheapChangeClip total:      3  0.0033 */
46099                :    CHEAP_FUNC_PROLOGUE (pGC);
46100                :
46101                :    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
46102                :
46103                :    CHEAP_FUNC_EPILOGUE (pGC);
46104      2  0.0022 :}
46105                :
46106                :static void
46107                :miBSCheapCopyClip(pgcDst, pgcSrc)
46108                :    GCPtr pgcDst, pgcSrc;
46109                :{
46110                :    CHEAP_FUNC_PROLOGUE (pgcDst);
46111                :
46112                :    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
46113                :
46114                :    CHEAP_FUNC_EPILOGUE (pgcDst);
46115                :}
46116                :
46117                :static void
46118                :miBSCheapDestroyClip(pGC)
46119                :    GCPtr       pGC;
46120                :{
46121                :    CHEAP_FUNC_PROLOGUE (pGC);
46122                :
46123                :    (* pGC->funcs->DestroyClip)(pGC);
46124                :
46125                :    CHEAP_FUNC_EPILOGUE (pGC);
46126                :}
46127                :
46128                :/*
46129                : * create the full func/op wrappers for a GC
46130                : */
46131                :
46132                :static Bool
46133                :miBSCreateGCPrivate (pGC)
46134                :    GCPtr   pGC;
46135                :{
46136                :    miBSGCRec   *pPriv;
46137                :
46138                :    pPriv = (miBSGCRec *) xalloc (sizeof (miBSGCRec));
46139                :    if (!pPriv)
46140                :        return FALSE;
46141                :    pPriv->pBackingGC = NULL;
46142                :    pPriv->guarantee = GuaranteeNothing;
46143                :    pPriv->serialNumber = 0;
46144                :    pPriv->stateChanges = (1 << (GCLastBit + 1)) - 1;
46145                :    pPriv->wrapOps = pGC->ops;
46146                :    pPriv->wrapFuncs = pGC->funcs;
46147                :    pGC->funcs = &miBSGCFuncs;
46148                :    pGC->ops = &miBSGCOps;
46149                :    pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv;
46150                :    return TRUE;
46151                :}
46152                :
46153                :static void
46154                :miBSDestroyGCPrivate (GCPtr pGC)
46155                :{
46156                :    miBSGCRec   *pPriv;
46157                :
46158                :    pPriv = (miBSGCRec *) pGC->devPrivates[miBSGCIndex].ptr;
46159                :    if (pPriv)
46160                :    {
46161                :        pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv->wrapFuncs;
46162                :        pGC->funcs = &miBSCheapGCFuncs;
46163                :        pGC->ops = pPriv->wrapOps;
46164                :        if (pPriv->pBackingGC)
46165                :            FreeGC (pPriv->pBackingGC, (GContext) 0);
46166                :        xfree ((pointer) pPriv);
46167                :    }
46168                :}
46169                :
46170                :/*
46171                : * GC ops -- wrap each GC operation with our own function
46172                : */
46173                :
46174                :/*-
46175                : *-----------------------------------------------------------------------
46176                : * miBSFillSpans --
46177                : *      Perform a FillSpans, routing output to backing-store as needed.
46178                : *
46179                : * Results:
46180                : *      None.
46181                : *
46182                : * Side Effects:
46183                : *
46184                : *-----------------------------------------------------------------------
46185                : */
46186                :static void
46187                :miBSFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
46188                :    DrawablePtr pDrawable;
46189                :    GCPtr       pGC;
46190                :    int         nInit;                  /* number of spans to fill */
46191                :    DDXPointPtr pptInit;                /* pointer to list of start points */
46192                :    int         *pwidthInit;            /* pointer to list of n widths */
46193                :    int         fSorted;
46194                :{
46195                :    DDXPointPtr pptCopy, pptReset;
46196                :    int         *pwidthCopy;
46197                :    SETUP_BACKING (pDrawable, pGC);
46198                :
46199                :    PROLOGUE(pGC);
46200                :
46201                :    pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nInit*sizeof(DDXPointRec));
46202                :    pwidthCopy=(int *)ALLOCATE_LOCAL(nInit*sizeof(int));
46203                :    if (pptCopy && pwidthCopy)
46204                :    {
46205                :        copyData(pptInit, pptCopy, nInit, MoreCopy0);
46206                :        memmove((char *)pwidthCopy,(char *)pwidthInit,nInit*sizeof(int));
46207                :
46208                :        (* pGC->ops->FillSpans)(pDrawable, pGC, nInit, pptInit,
46209                :                             pwidthInit, fSorted);
46210                :        if (pGC->miTranslate)
46211                :        {
46212                :            int dx, dy;
46213                :            int nReset;
46214                :
46215                :            pptReset = pptCopy;
46216                :            dx = pDrawable->x - pBackingDrawable->x;
46217                :            dy = pDrawable->y - pBackingDrawable->y;
46218                :            nReset = nInit;
46219                :            while (nReset--)
46220                :            {
46221                :                pptReset->x -= dx;
46222                :                pptReset->y -= dy;
46223                :                ++pptReset;
46224                :            }
46225                :        }
46226                :        (* pBackingGC->ops->FillSpans)(pBackingDrawable,
46227                :                                  pBackingGC, nInit, pptCopy, pwidthCopy,
46228                :                                  fSorted);
46229                :    }
46230                :    if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy);
46231                :    if (pptCopy) DEALLOCATE_LOCAL(pptCopy);
46232                :
46233                :    EPILOGUE (pGC);
46234                :}
46235                :
46236                :/*-
46237                : *-----------------------------------------------------------------------
46238                : * miBSSetSpans --
46239                : *      Perform a SetSpans, routing output to backing-store as needed.
46240                : *
46241                : * Results:
46242                : *      None.
46243                : *
46244                : * Side Effects:
46245                : *
46246                : *-----------------------------------------------------------------------
46247                : */
46248                :static void
46249                :miBSSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
46250                :    DrawablePtr         pDrawable;
46251                :    GCPtr               pGC;
46252                :    char                *psrc;
46253                :    DDXPointPtr         ppt;
46254                :    int                 *pwidth;
46255                :    int                 nspans;
46256                :    int                 fSorted;
46257                :{
46258                :    DDXPointPtr pptCopy, pptReset;
46259                :    int         *pwidthCopy;
46260                :    SETUP_BACKING (pDrawable, pGC);
46261                :
46262                :    PROLOGUE(pGC);
46263                :
46264                :    pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nspans*sizeof(DDXPointRec));
46265                :    pwidthCopy=(int *)ALLOCATE_LOCAL(nspans*sizeof(int));
46266                :    if (pptCopy && pwidthCopy)
46267                :    {
46268                :        copyData(ppt, pptCopy, nspans, MoreCopy0);
46269                :        memmove((char *)pwidthCopy,(char *)pwidth,nspans*sizeof(int));
46270                :
46271                :        (* pGC->ops->SetSpans)(pDrawable, pGC, psrc, ppt, pwidth,
46272                :                               nspans, fSorted);
46273                :        if (pGC->miTranslate)
46274                :        {
46275                :            int dx, dy;
46276                :            int nReset;
46277                :
46278                :            pptReset = pptCopy;
46279                :            dx = pDrawable->x - pBackingDrawable->x;
46280                :            dy = pDrawable->y - pBackingDrawable->y;
46281                :            nReset = nspans;
46282                :            while (nReset--)
46283                :            {
46284                :                pptReset->x -= dx;
46285                :                pptReset->y -= dy;
46286                :                ++pptReset;
46287                :            }
46288                :        }
46289                :        (* pBackingGC->ops->SetSpans)(pBackingDrawable, pBackingGC,
46290                :                                psrc, pptCopy, pwidthCopy, nspans, fSorted);
46291                :    }
46292                :    if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy);
46293                :    if (pptCopy) DEALLOCATE_LOCAL(pptCopy);
46294                :
46295                :    EPILOGUE (pGC);
46296                :}
46297                :
46298                :/*-
46299                : *-----------------------------------------------------------------------
46300                : * miBSPutImage --
46301                : *      Perform a PutImage, routing output to backing-store as needed.
46302                : *
46303                : * Results:
46304                : *      None.
46305                : *
46306                : * Side Effects:
46307                : *
46308                : *-----------------------------------------------------------------------
46309                : */
46310                :static void
46311                :miBSPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
46312                :    DrawablePtr   pDrawable;
46313                :    GCPtr         pGC;
46314                :    int           depth;
46315                :    int           x;
46316                :    int           y;
46317                :    int           w;
46318                :    int           h;
46319                :    int           leftPad;
46320                :    int           format;
46321                :    char          *pBits;
46322                :{
46323                :    SETUP_BACKING (pDrawable, pGC);
46324                :
46325                :    PROLOGUE(pGC);
46326                :
46327                :    (*pGC->ops->PutImage)(pDrawable, pGC,
46328                :                     depth, x, y, w, h, leftPad, format, pBits);
46329                :    (*pBackingGC->ops->PutImage)(pBackingDrawable, pBackingGC,
46330                :                     depth, x - pBackingStore->x, y - pBackingStore->y,
46331                :                     w, h, leftPad, format, pBits);
46332                :
46333                :    EPILOGUE (pGC);
46334                :}
46335                :
46336                :typedef RegionPtr (* CopyAreaProcPtr)(DrawablePtr, DrawablePtr, GCPtr,
46337                :                                      int, int, int, int, int, int);
46338                :typedef RegionPtr (* CopyPlaneProcPtr)(DrawablePtr, DrawablePtr, GCPtr,
46339                :                                      int, int, int, int, int, int,
46340                :                                      unsigned long bitPlane);
46341                :/*-
46342                : *-----------------------------------------------------------------------
46343                : * miBSDoCopy --
46344                : *      Perform a CopyArea or CopyPlane within a window that has backing
46345                : *      store enabled.
46346                : *
46347                : * Results:
46348                : *      TRUE if the copy was performed or FALSE if a regular one should
46349                : *      be done.
46350                : *
46351                : * Side Effects:
46352                : *      Things are copied (no s***!)
46353                : *
46354                : * Notes:
46355                : *      The idea here is to form two regions that cover the source box.
46356                : *      One contains the exposed rectangles while the other contains
46357                : *      the obscured ones. An array of <box, drawable> pairs is then
46358                : *      formed where the <box> indicates the area to be copied and the
46359                : *      <drawable> indicates from where it is to be copied (exposed regions
46360                : *      come from the screen while obscured ones come from the backing
46361                : *      pixmap). The array 'sequence' is then filled with the indices of
46362                : *      the pairs in the order in which they should be copied to prevent
46363                : *      things from getting screwed up. A call is also made through the
46364                : *      backingGC to take care of any copying into the backing pixmap.
46365                : *
46366                : *-----------------------------------------------------------------------
46367                : */
46368                :static Bool
46369                :miBSDoCopy(
46370                :    WindowPtr     pWin,             /* Window being scrolled */
46371                :    GCPtr         pGC,              /* GC we're called through */
46372                :    int           srcx,             /* X of source rectangle */
46373                :    int           srcy,             /* Y of source rectangle */
46374                :    int           w,                /* Width of source rectangle */
46375                :    int           h,                /* Height of source rectangle */
46376                :    int           dstx,             /* X of destination rectangle */
46377                :    int           dsty,             /* Y of destination rectangle */
46378                :    unsigned long plane,            /* Plane to copy (0 for CopyArea) */
46379                :    CopyPlaneProcPtr copyProc,      /* Procedure to call to perform the copy */
46380                :    RegionPtr     *ppRgn)           /* resultant Graphics Expose region */
46381                :{
46382                :    RegionPtr           pRgnExp;    /* Exposed region */
46383                :    RegionPtr           pRgnObs;    /* Obscured region */
46384                :    BoxRec              box;        /* Source box (screen coord) */
46385                :    struct BoxDraw {
46386                :        BoxPtr          pBox;           /* Source box */
46387                :        enum {
46388                :            win, pix
46389                :        }               source;         /* Place from which to copy */
46390                :    }                   *boxes;     /* Array of box/drawable pairs covering
46391                :                                     * source box. */
46392                :    int                 *sequence;  /* Sequence of boxes to move */
46393                :    int                 i, j, k, l, y;
46394                :    BoxPtr              pBox;
46395                :    int                 dx, dy, nrects;
46396                :    Bool                graphicsExposures;
46397                :    CopyPlaneProcPtr    pixCopyProc;
46398                :    int                 numRectsExp, numRectsObs;
46399                :    BoxPtr              pBoxExp, pBoxObs;
46400                :
46401                :    SETUP_BACKING (pWin, pGC);
46402                :    (void)oldFuncs;
46403                :
46404                :    /*
46405                :     * Create a region of exposed boxes in pRgnExp.
46406                :     */
46407                :    box.x1 = srcx + pWin->drawable.x;
46408                :    box.x2 = box.x1 + w;
46409                :    box.y1 = srcy + pWin->drawable.y;
46410                :    box.y2 = box.y1 + h;
46411                :    
46412                :    pRgnExp = REGION_CREATE(pGC->pScreen, &box, 1);
46413                :    REGION_INTERSECT(pGC->pScreen, pRgnExp, pRgnExp, &pWin->clipList);
46414                :    pRgnObs = REGION_CREATE(pGC->pScreen, NULL, 1);
46415                :    REGION_INVERSE( pGC->pScreen, pRgnObs, pRgnExp, &box);
46416                :
46417                :    /*
46418                :     * Translate regions into window coordinates for proper calls
46419                :     * to the copyProc, then make sure none of the obscured region sticks
46420                :     * into invalid areas of the backing pixmap.
46421                :     */
46422                :    REGION_TRANSLATE(pGC->pScreen, pRgnExp,
46423                :                                      -pWin->drawable.x,
46424                :                                      -pWin->drawable.y);
46425                :    REGION_TRANSLATE(pGC->pScreen, pRgnObs,
46426                :                                      -pWin->drawable.x,
46427                :                                      -pWin->drawable.y);
46428                :    REGION_INTERSECT(pGC->pScreen, pRgnObs, pRgnObs, &pBackingStore->SavedRegion);
46429                :
46430                :    /*
46431                :     * If the obscured region is empty, there's no point being fancy.
46432                :     */
46433                :    if (!REGION_NOTEMPTY(pGC->pScreen, pRgnObs))
46434                :    {
46435                :        REGION_DESTROY(pGC->pScreen, pRgnExp);
46436                :        REGION_DESTROY(pGC->pScreen, pRgnObs);
46437                :
46438                :        return (FALSE);
46439                :    }
46440                :
46441                :    numRectsExp = REGION_NUM_RECTS(pRgnExp);
46442                :    pBoxExp = REGION_RECTS(pRgnExp);
46443                :    pBoxObs = REGION_RECTS(pRgnObs);
46444                :    numRectsObs = REGION_NUM_RECTS(pRgnObs);
46445                :    nrects = numRectsExp + numRectsObs;
46446                :    
46447                :    boxes = (struct BoxDraw *)ALLOCATE_LOCAL(nrects * sizeof(struct BoxDraw));
46448                :    sequence = (int *) ALLOCATE_LOCAL(nrects * sizeof(int));
46449                :    *ppRgn = NULL;
46450                :
46451                :    if (!boxes || !sequence)
46452                :    {
46453                :        if (sequence) DEALLOCATE_LOCAL(sequence);
46454                :        if (boxes) DEALLOCATE_LOCAL(boxes);
46455                :        REGION_DESTROY(pGC->pScreen, pRgnExp);
46456                :        REGION_DESTROY(pGC->pScreen, pRgnObs);
46457                :
46458                :        return(TRUE);
46459                :    }
46460                :
46461                :    /*
46462                :     * Order the boxes in the two regions so we know from which drawable
46463                :     * to copy which box, storing the result in the boxes array
46464                :     */
46465                :    for (i = 0, j = 0, k = 0;
46466                :         (i < numRectsExp) && (j < numRectsObs);
46467                :         k++)
46468                :    {
46469                :        if (pBoxExp[i].y1 < pBoxObs[j].y1)
46470                :        {
46471                :            boxes[k].pBox = &pBoxExp[i];
46472                :            boxes[k].source = win;
46473                :            i++;
46474                :        }
46475                :        else if ((pBoxObs[j].y1 < pBoxExp[i].y1) ||
46476                :                 (pBoxObs[j].x1 < pBoxExp[i].x1))
46477                :        {
46478                :            boxes[k].pBox = &pBoxObs[j];
46479                :            boxes[k].source = pix;
46480                :            j++;
46481                :        }
46482                :        else
46483                :        {
46484                :            boxes[k].pBox = &pBoxExp[i];
46485                :            boxes[k].source = win;
46486                :            i++;
46487                :        }
46488                :    }
46489                :
46490                :    /*
46491                :     * Catch any leftover boxes from either region (note that only
46492                :     * one can have leftover boxes...)
46493                :     */
46494                :    if (i != numRectsExp)
46495                :    {
46496                :        do
46497                :        {
46498                :            boxes[k].pBox = &pBoxExp[i];
46499                :            boxes[k].source = win;
46500                :            i++;
46501                :            k++;
46502                :        } while (i < numRectsExp);
46503                :
46504                :    }
46505                :    else
46506                :    {
46507                :        do
46508                :        {
46509                :            boxes[k].pBox = &pBoxObs[j];
46510                :            boxes[k].source = pix;
46511                :            j++;
46512                :            k++;
46513                :        } while (j < numRectsObs);
46514                :    }
46515                :    
46516                :    if (dsty <= srcy)
46517                :    {
46518                :        /*
46519                :         * Scroll up or vertically stationary, so vertical order is ok.
46520                :         */
46521                :        if (dstx <= srcx)
46522                :        {
46523                :            /*
46524                :             * Scroll left or horizontally stationary, so horizontal order
46525                :             * is ok as well.
46526                :             */
46527                :            for (i = 0; i < nrects; i++)
46528                :            {
46529                :                sequence[i] = i;
46530                :            }
46531                :        }
46532                :        else
46533                :        {
46534                :            /*
46535                :             * Scroll right. Need to reverse the rectangles within each
46536                :             * band.
46537                :             */
46538                :            for (i = 0, j = 1, k = 0;
46539                :                 i < nrects;
46540                :                 j = i + 1, k = i)
46541                :            {
46542                :                y = boxes[i].pBox->y1;
46543                :                while ((j < nrects) && (boxes[j].pBox->y1 == y))
46544                :                {
46545                :                    j++;
46546                :                }
46547                :                for (j--; j >= k; j--, i++)
46548                :                {
46549                :                    sequence[i] = j;
46550                :                }
46551                :            }
46552                :        }
46553                :    }
46554                :    else
46555                :    {
46556                :        /*
46557                :         * Scroll down. Must reverse vertical banding, at least.
46558                :         */
46559                :        if (dstx < srcx)
46560                :        {
46561                :            /*
46562                :             * Scroll left. Horizontal order is ok.
46563                :             */
46564                :            for (i = nrects - 1, j = i - 1, k = i, l = 0;
46565                :                 i >= 0;
46566                :                 j = i - 1, k = i)
46567                :            {
46568                :                /*
46569                :                 * Find extent of current horizontal band, then reverse
46570                :                 * the order of the whole band.
46571                :                 */
46572                :                y = boxes[i].pBox->y1;
46573                :                while ((j >= 0) && (boxes[j].pBox->y1 == y))
46574                :                {
46575                :                    j--;
46576                :                }
46577                :                for (j++; j <= k; j++, i--, l++)
46578                :                {
46579                :                    sequence[l] = j;
46580                :                }
46581                :            }
46582                :        }
46583                :        else
46584                :        {
46585                :            /*
46586                :             * Scroll right or horizontal stationary.
46587                :             * Reverse horizontal order as well (if stationary, horizontal
46588                :             * order can be swapped without penalty and this is faster
46589                :             * to compute).
46590                :             */
46591                :            for (i = 0, j = nrects - 1; i < nrects; i++, j--)
46592                :            {
46593                :                sequence[i] = j;
46594                :            }
46595                :        }
46596                :    }
46597                :            
46598                :    /*
46599                :     * XXX: To avoid getting multiple NoExpose events from this operation,
46600                :     * we turn OFF graphicsExposures in the gc and deal with any uncopied
46601                :     * areas later, if there's something not in backing-store.
46602                :     */
46603                :
46604                :    graphicsExposures = pGC->graphicsExposures;
46605                :    pGC->graphicsExposures = FALSE;
46606                :    
46607                :    dx = dstx - srcx;
46608                :    dy = dsty - srcy;
46609                :
46610                :    /*
46611                :     * Figure out which copy procedure to use from the backing GC. Note we
46612                :     * must do this because some implementations (sun's, e.g.) have
46613                :     * pBackingGC a fake GC with the real one below it, thus the devPriv for
46614                :     * pBackingGC won't be what the output library expects.
46615                :     */
46616                :    if (plane != 0)
46617                :    {
46618                :        pixCopyProc = pBackingGC->ops->CopyPlane;
46619                :    }
46620                :    else
46621                :    {
46622                :        pixCopyProc = (CopyPlaneProcPtr)pBackingGC->ops->CopyArea;
46623                :    }
46624                :    
46625                :    for (i = 0; i < nrects; i++)
46626                :    {
46627                :        pBox = boxes[sequence[i]].pBox;
46628                :        
46629                :        /*
46630                :         * If we're copying from the pixmap, we need to place its contents
46631                :         * onto the screen before scrolling the pixmap itself. If we're copying
46632                :         * from the window, we need to copy its contents into the pixmap before
46633                :         * we scroll the window itself.
46634                :         */
46635                :        if (boxes[sequence[i]].source == pix)
46636                :        {
46637                :            (void) (* copyProc) (pBackingDrawable, &(pWin->drawable), pGC,
46638                :                          pBox->x1 - pBackingStore->x,
46639                :                          pBox->y1 - pBackingStore->y,
46640                :                          pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
46641                :                          pBox->x1 + dx, pBox->y1 + dy, plane);
46642                :            (void) (* pixCopyProc) (pBackingDrawable, pBackingDrawable, pBackingGC,
46643                :                             pBox->x1 - pBackingStore->x,
46644                :                             pBox->y1 - pBackingStore->y,
46645                :                             pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
46646                :                             pBox->x1 + dx - pBackingStore->x,
46647                :                             pBox->y1 + dy - pBackingStore->y, plane);
46648                :        }
46649                :        else
46650                :        {
46651                :            (void) (* pixCopyProc) (&(pWin->drawable), pBackingDrawable, pBackingGC,
46652                :                             pBox->x1, pBox->y1,
46653                :                             pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
46654                :                             pBox->x1 + dx - pBackingStore->x,
46655                :                             pBox->y1 + dy - pBackingStore->y, plane);
46656                :            (void) (* copyProc) (&(pWin->drawable), &(pWin->drawable), pGC,
46657                :                          pBox->x1, pBox->y1,
46658                :                          pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
46659                :                          pBox->x1 + dx, pBox->y1 + dy, plane);
46660                :        }
46661                :    }
46662                :    DEALLOCATE_LOCAL(sequence);
46663                :    DEALLOCATE_LOCAL(boxes);
46664                :
46665                :    pGC->graphicsExposures = graphicsExposures;
46666                :    /*
46667                :     * Form union of rgnExp and rgnObs and see if covers entire area
46668                :     * to be copied.  Store the resultant region for miBSCopyArea
46669                :     * to return to dispatch which will send the appropriate expose
46670                :     * events.
46671                :     */
46672                :    REGION_UNION(pGC->pScreen, pRgnExp, pRgnExp, pRgnObs);
46673                :    box.x1 = srcx;
46674                :    box.x2 = srcx + w;
46675                :    box.y1 = srcy;
46676                :    box.y2 = srcy + h;
46677                :    if (RECT_IN_REGION(pGC->pScreen, pRgnExp, &box) == rgnIN)
46678                :    {
46679                :        REGION_EMPTY(pGC->pScreen, pRgnExp);
46680                :    }
46681                :    else
46682                :    {
46683                :        REGION_INVERSE( pGC->pScreen, pRgnExp, pRgnExp, &box);
46684                :        REGION_TRANSLATE( pGC->pScreen, pRgnExp,
46685                :                                           dx + pWin->drawable.x,
46686                :                                           dy + pWin->drawable.y);
46687                :        REGION_INTERSECT( pGC->pScreen, pRgnObs, pRgnExp, &pWin->clipList);
46688                :        (*pWin->drawable.pScreen->PaintWindowBackground) (pWin,
46689                :                                                pRgnObs, PW_BACKGROUND);
46690                :        REGION_TRANSLATE( pGC->pScreen, pRgnExp,
46691                :                                           -pWin->drawable.x,
46692                :                                           -pWin->drawable.y);
46693                :        miBSClearBackingRegion (pWin, pRgnExp);
46694                :    }
46695                :    if (graphicsExposures)
46696                :        *ppRgn = pRgnExp;
46697                :    else
46698                :        REGION_DESTROY(pGC->pScreen, pRgnExp);
46699                :    REGION_DESTROY(pGC->pScreen, pRgnObs);
46700                :
46701                :    return (TRUE);
46702                :}
46703                :
46704                :/*-
46705                : *-----------------------------------------------------------------------
46706                : * miBSCopyArea --
46707                : *      Perform a CopyArea from the source to the destination, extracting
46708                : *      from the source's backing-store and storing into the destination's
46709                : *      backing-store without messing anything up. If the source and
46710                : *      destination are different, there's not too much to worry about:
46711                : *      we can just issue several calls to the regular CopyArea function.
46712                : *
46713                : * Results:
46714                : *      None.
46715                : *
46716                : * Side Effects:
46717                : *
46718                : *-----------------------------------------------------------------------
46719                : */
46720                :static RegionPtr
46721                :miBSCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
46722                :    DrawablePtr   pSrc;
46723                :    DrawablePtr   pDst;
46724                :    GCPtr         pGC;
46725                :    int           srcx;
46726                :    int           srcy;
46727                :    int           w;
46728                :    int           h;
46729                :    int           dstx;
46730                :    int           dsty;
46731                :{
46732                :    BoxPtr      pExtents;
46733                :    long        dx, dy;
46734                :    int         bsrcx, bsrcy, bw, bh, bdstx, bdsty;
46735                :    RegionPtr   pixExposed = 0, winExposed = 0;
46736                :
46737                :    SETUP_BACKING(pDst, pGC);
46738                :
46739                :    PROLOGUE(pGC);
46740                :
46741                :    if ((pSrc != pDst) ||
46742                :        (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty,
46743                :                     (unsigned long) 0, (CopyPlaneProcPtr)pGC->ops->CopyArea,
46744                :                     &winExposed)))
46745                :    {
46746                :        /*
46747                :         * always copy to the backing store first, miBSDoCopy
46748                :         * returns FALSE if the *source* region is disjoint
46749                :         * from the backing store saved region.  So, copying
46750                :         * *to* the backing store is always safe
46751                :         */
46752                :        if (pGC->clientClipType != CT_PIXMAP)
46753                :        {
46754                :            /*
46755                :             * adjust srcx, srcy, w, h, dstx, dsty to be clipped to
46756                :             * the backing store.  An unnecessary optimisation,
46757                :             * but a useful one when GetSpans is slow.
46758                :             */
46759                :            pExtents = REGION_EXTENTS(pDst->pScreen,
46760                :                                      (RegionPtr)pBackingGC->clientClip);
46761                :            bsrcx = srcx;
46762                :            bsrcy = srcy;
46763                :            bw = w;
46764                :            bh = h;
46765                :            bdstx = dstx;
46766                :            bdsty = dsty;
46767                :            dx = pExtents->x1 - bdstx;
46768                :            if (dx > 0)
46769                :            {
46770                :                bsrcx += dx;
46771                :                bdstx += dx;
46772                :                bw -= dx;
46773                :            }
46774                :            dy = pExtents->y1 - bdsty;
46775                :            if (dy > 0)
46776                :            {
46777                :                bsrcy += dy;
46778                :                bdsty += dy;
46779                :                bh -= dy;
46780                :            }
46781                :            dx = (bdstx + bw) - pExtents->x2;
46782                :            if (dx > 0)
46783                :                bw -= dx;
46784                :            dy = (bdsty + bh) - pExtents->y2;
46785                :            if (dy > 0)
46786                :                bh -= dy;
46787                :            if (bw > 0 && bh > 0)
46788                :                pixExposed = (* pBackingGC->ops->CopyArea) (pSrc, 
46789                :                            pBackingDrawable, pBackingGC, 
46790                :                            bsrcx, bsrcy, bw, bh, bdstx - pBackingStore->x,
46791                :                            bdsty - pBackingStore->y);
46792                :        }
46793                :        else
46794                :            pixExposed = (* pBackingGC->ops->CopyArea) (pSrc, 
46795                :                            pBackingDrawable, pBackingGC,
46796                :                            srcx, srcy, w, h,
46797                :                            dstx - pBackingStore->x, dsty - pBackingStore->y);
46798                :
46799                :        winExposed = (* pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
46800                :    }
46801                :
46802                :    /*
46803                :     * compute the composite graphics exposure region
46804                :     */
46805                :    if (winExposed)
46806                :    {
46807                :        if (pixExposed){
46808                :            REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed);
46809                :            REGION_DESTROY(pDst->pScreen, pixExposed);
46810                :        }
46811                :    } else
46812                :        winExposed = pixExposed;
46813                :
46814                :    EPILOGUE (pGC);
46815                :
46816                :    return winExposed;
46817                :}
46818                :
46819                :/*-
46820                : *-----------------------------------------------------------------------
46821                : * miBSCopyPlane --
46822                : *
46823                : * Results:
46824                : *      None.
46825                : *
46826                : * Side Effects:
46827                : *
46828                : *-----------------------------------------------------------------------
46829                : */
46830                :static RegionPtr
46831                :miBSCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
46832                :    DrawablePtr   pSrc;
46833                :    DrawablePtr   pDst;
46834                :    GC           *pGC;
46835                :    int           srcx,
46836                :                  srcy;
46837                :    int           w,
46838                :                  h;
46839                :    int           dstx,
46840                :                  dsty;
46841                :    unsigned long  plane;
46842                :{
46843                :    BoxPtr      pExtents;
46844                :    long        dx, dy;
46845                :    int         bsrcx, bsrcy, bw, bh, bdstx, bdsty;
46846                :    RegionPtr   winExposed = 0, pixExposed = 0;
46847                :    SETUP_BACKING(pDst, pGC);
46848                :
46849                :    PROLOGUE(pGC);
46850                :
46851                :    if ((pSrc != pDst) ||
46852                :        (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty,
46853                :                     plane,  pGC->ops->CopyPlane, &winExposed)))
46854                :    {
46855                :        /*
46856                :         * always copy to the backing store first, miBSDoCopy
46857                :         * returns FALSE if the *source* region is disjoint
46858                :         * from the backing store saved region.  So, copying
46859                :         * *to* the backing store is always safe
46860                :         */
46861                :        if (pGC->clientClipType != CT_PIXMAP)
46862                :        {
46863                :            /*
46864                :             * adjust srcx, srcy, w, h, dstx, dsty to be clipped to
46865                :             * the backing store.  An unnecessary optimisation,
46866                :             * but a useful one when GetSpans is slow.
46867                :             */
46868                :            pExtents = REGION_EXTENTS(pDst->pScreen,
46869                :                                      (RegionPtr)pBackingGC->clientClip);
46870                :            bsrcx = srcx;
46871                :            bsrcy = srcy;
46872                :            bw = w;
46873                :            bh = h;
46874                :            bdstx = dstx;
46875                :            bdsty = dsty;
46876                :            dx = pExtents->x1 - bdstx;
46877                :            if (dx > 0)
46878                :            {
46879                :                bsrcx += dx;
46880                :                bdstx += dx;
46881                :                bw -= dx;
46882                :            }
46883                :            dy = pExtents->y1 - bdsty;
46884                :            if (dy > 0)
46885                :            {
46886                :                bsrcy += dy;
46887                :                bdsty += dy;
46888                :                bh -= dy;
46889                :            }
46890                :            dx = (bdstx + bw) - pExtents->x2;
46891                :            if (dx > 0)
46892                :                bw -= dx;
46893                :            dy = (bdsty + bh) - pExtents->y2;
46894                :            if (dy > 0)
46895                :                bh -= dy;
46896                :            if (bw > 0 && bh > 0)
46897                :                pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc, 
46898                :                                    pBackingDrawable,
46899                :                                    pBackingGC, bsrcx, bsrcy, bw, bh,
46900                :                                    bdstx - pBackingStore->x,
46901                :                                    bdsty - pBackingStore->y, plane);
46902                :        }
46903                :        else
46904                :            pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc, 
46905                :                                    pBackingDrawable,
46906                :                                    pBackingGC, srcx, srcy, w, h,
46907                :                                    dstx - pBackingStore->x,
46908                :                                    dsty - pBackingStore->y, plane);
46909                :
46910                :        winExposed = (* pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
46911                :                              dstx, dsty, plane);
46912                :        
46913                :    }
46914                :
46915                :    /*
46916                :     * compute the composite graphics exposure region
46917                :     */
46918                :    if (winExposed)
46919                :    {
46920                :        if (pixExposed)
46921                :        {
46922                :            REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed);
46923                :            REGION_DESTROY(pDst->pScreen, pixExposed);
46924                :        }
46925                :    } else
46926                :        winExposed = pixExposed;
46927                :
46928                :    EPILOGUE (pGC);
46929                :
46930                :    return winExposed;
46931                :}
46932                :
46933                :/*-
46934                : *-----------------------------------------------------------------------
46935                : * miBSPolyPoint --
46936                : *      Perform a PolyPoint, routing output to backing-store as needed.
46937                : *
46938                : * Results:
46939                : *      None.
46940                : *
46941                : * Side Effects:
46942                : *
46943                : *-----------------------------------------------------------------------
46944                : */
46945                :static void
46946                :miBSPolyPoint (pDrawable, pGC, mode, npt, pptInit)
46947                :    DrawablePtr pDrawable;
46948                :    GCPtr       pGC;
46949                :    int         mode;           /* Origin or Previous */
46950                :    int         npt;
46951                :    xPoint      *pptInit;
46952                :{
46953                :    xPoint        *pptCopy;
46954                :    SETUP_BACKING (pDrawable, pGC);
46955                :
46956                :    PROLOGUE(pGC);
46957                :
46958                :    pptCopy = (xPoint *)ALLOCATE_LOCAL(npt*sizeof(xPoint));
46959                :    if (pptCopy)
46960                :    {
46961                :        copyPoints(pptInit, pptCopy, npt, mode);
46962                :
46963                :        (* pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
46964                :
46965                :        (* pBackingGC->ops->PolyPoint) (pBackingDrawable,
46966                :                                   pBackingGC, mode, npt, pptCopy);
46967                :
46968                :        DEALLOCATE_LOCAL(pptCopy);
46969                :    }
46970                :
46971                :    EPILOGUE (pGC);
46972                :}
46973                :
46974                :/*-
46975                : *-----------------------------------------------------------------------
46976                : * miBSPolyLines --
46977                : *      Perform a Polylines, routing output to backing-store as needed.
46978                : *
46979                : * Results:
46980                : *
46981                : * Side Effects:
46982                : *
46983                : *-----------------------------------------------------------------------
46984                : */
46985                :static void
46986                :miBSPolylines (pDrawable, pGC, mode, npt, pptInit)
46987                :    DrawablePtr   pDrawable;
46988                :    GCPtr         pGC;
46989                :    int           mode;
46990                :    int           npt;
46991                :    DDXPointPtr   pptInit;
46992                :{
46993                :    DDXPointPtr pptCopy;
46994                :    SETUP_BACKING (pDrawable, pGC);
46995                :
46996                :    PROLOGUE(pGC);
46997                :
46998                :    pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(npt*sizeof(DDXPointRec));
46999                :    if (pptCopy)
47000                :    {
47001                :        copyPoints(pptInit, pptCopy, npt, mode);
47002                :
47003                :        (* pGC->ops->Polylines)(pDrawable, pGC, mode, npt, pptInit);
47004                :        (* pBackingGC->ops->Polylines)(pBackingDrawable,
47005                :                                  pBackingGC, mode, npt, pptCopy);
47006                :        DEALLOCATE_LOCAL(pptCopy);
47007                :    }
47008                :
47009                :    EPILOGUE (pGC);
47010                :}
47011                :
47012                :/*-
47013                : *-----------------------------------------------------------------------
47014                : * miBSPolySegment --
47015                : *      Perform a PolySegment, routing output to backing-store as needed.
47016                : *
47017                : * Results:
47018                : *      None.
47019                : *
47020                : * Side Effects:
47021                : *
47022                : *-----------------------------------------------------------------------
47023                : */
47024                :static void
47025                :miBSPolySegment(pDrawable, pGC, nseg, pSegs)
47026                :    DrawablePtr pDrawable;
47027                :    GCPtr       pGC;
47028                :    int         nseg;
47029                :    xSegment    *pSegs;
47030                :{
47031                :    xSegment    *pSegsCopy;
47032                :
47033                :    SETUP_BACKING (pDrawable, pGC);
47034                :
47035                :    PROLOGUE(pGC);
47036                :
47037                :    pSegsCopy = (xSegment *)ALLOCATE_LOCAL(nseg*sizeof(xSegment));
47038                :    if (pSegsCopy)
47039                :    {
47040                :        copyData(pSegs, pSegsCopy, nseg << 1, MoreCopy0);
47041                :
47042                :        (* pGC->ops->PolySegment)(pDrawable, pGC, nseg, pSegs);
47043                :        (* pBackingGC->ops->PolySegment)(pBackingDrawable,
47044                :                                    pBackingGC, nseg, pSegsCopy);
47045                :
47046                :        DEALLOCATE_LOCAL(pSegsCopy);
47047                :    }
47048                :
47049                :    EPILOGUE (pGC);
47050                :}
47051                :
47052                :/*-
47053                : *-----------------------------------------------------------------------
47054                : * miBSPolyRectangle --
47055                : *      Perform a PolyRectangle, routing output to backing-store as needed.
47056                : *
47057                : * Results:
47058                : *      None
47059                : *
47060                : * Side Effects:
47061                : *
47062                : *-----------------------------------------------------------------------
47063                : */
47064                :static void
47065                :miBSPolyRectangle(pDrawable, pGC, nrects, pRects)
47066                :    DrawablePtr pDrawable;
47067                :    GCPtr       pGC;
47068                :    int         nrects;
47069                :    xRectangle  *pRects;
47070                :{
47071                :    xRectangle  *pRectsCopy;
47072                :    SETUP_BACKING (pDrawable, pGC);
47073                :
47074                :    PROLOGUE(pGC);
47075                :
47076                :    pRectsCopy =(xRectangle *)ALLOCATE_LOCAL(nrects*sizeof(xRectangle));
47077                :    if (pRectsCopy)
47078                :    {
47079                :        copyData(pRects, pRectsCopy, nrects, MoreCopy2);
47080                :
47081                :        (* pGC->ops->PolyRectangle)(pDrawable, pGC, nrects, pRects);
47082                :        (* pBackingGC->ops->PolyRectangle)(pBackingDrawable,
47083                :                                      pBackingGC, nrects, pRectsCopy);
47084                :
47085                :        DEALLOCATE_LOCAL(pRectsCopy);
47086                :    }
47087                :
47088                :    EPILOGUE (pGC);
47089                :}
47090                :
47091                :/*-
47092                : *-----------------------------------------------------------------------
47093                : * miBSPolyArc --
47094                : *      Perform a PolyArc, routing output to backing-store as needed.
47095                : *
47096                : * Results:
47097                : *
47098                : * Side Effects:
47099                : *
47100                : *-----------------------------------------------------------------------
47101                : */
47102                :static void
47103                :miBSPolyArc(pDrawable, pGC, narcs, parcs)
47104                :    DrawablePtr pDrawable;
47105                :    GCPtr       pGC;
47106                :    int         narcs;
47107                :    xArc        *parcs;
47108                :{
47109                :    xArc  *pArcsCopy;
47110                :    SETUP_BACKING (pDrawable, pGC);
47111                :
47112                :    PROLOGUE(pGC);
47113                :
47114                :    pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc));
47115                :    if (pArcsCopy)
47116                :    {
47117                :        copyData(parcs, pArcsCopy, narcs, MoreCopy4);
47118                :
47119                :        (* pGC->ops->PolyArc)(pDrawable, pGC, narcs, parcs);
47120                :        (* pBackingGC->ops->PolyArc)(pBackingDrawable, pBackingGC,
47121                :                                narcs, pArcsCopy);
47122                :
47123                :        DEALLOCATE_LOCAL(pArcsCopy);
47124                :    }
47125                :
47126                :    EPILOGUE (pGC);
47127                :}
47128                :
47129                :/*-
47130                : *-----------------------------------------------------------------------
47131                : * miBSFillPolygon --
47132                : *      Perform a FillPolygon, routing output to backing-store as needed.
47133                : *
47134                : * Results:
47135                : *      None.
47136                : *
47137                : * Side Effects:
47138                : *
47139                : *-----------------------------------------------------------------------
47140                : */
47141                :static void
47142                :miBSFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
47143                :    DrawablePtr         pDrawable;
47144                :    GCPtr               pGC;
47145                :    int                 shape, mode;
47146                :    int                 count;
47147                :    DDXPointPtr         pPts;
47148                :{
47149                :    DDXPointPtr pPtsCopy;
47150                :    SETUP_BACKING (pDrawable, pGC);
47151                :
47152                :    PROLOGUE(pGC);
47153                :
47154                :    pPtsCopy = (DDXPointPtr)ALLOCATE_LOCAL(count*sizeof(DDXPointRec));
47155                :    if (pPtsCopy)
47156                :    {
47157                :        copyPoints(pPts, pPtsCopy, count, mode);
47158                :        (* pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, count, pPts);
47159                :        (* pBackingGC->ops->FillPolygon)(pBackingDrawable,
47160                :                                    pBackingGC, shape, mode,
47161                :                                    count, pPtsCopy);
47162                :
47163                :        DEALLOCATE_LOCAL(pPtsCopy);
47164                :    }
47165                :
47166                :    EPILOGUE (pGC);
47167                :}
47168                :
47169                :/*-
47170                : *-----------------------------------------------------------------------
47171                : * miBSPolyFillRect --
47172                : *      Perform a PolyFillRect, routing output to backing-store as needed.
47173                : *
47174                : * Results:
47175                : *      None.
47176                : *
47177                : * Side Effects:
47178                : *
47179                : *-----------------------------------------------------------------------
47180                : */
47181                :static void
47182                :miBSPolyFillRect(pDrawable, pGC, nrectFill, prectInit)
47183                :    DrawablePtr pDrawable;
47184                :    GCPtr       pGC;
47185                :    int         nrectFill;      /* number of rectangles to fill */
47186                :    xRectangle  *prectInit;     /* Pointer to first rectangle to fill */
47187                :{
47188                :    xRectangle  *pRectCopy;
47189                :    SETUP_BACKING (pDrawable, pGC);
47190                :
47191                :    PROLOGUE(pGC);
47192                :
47193                :    pRectCopy =
47194                :        (xRectangle *)ALLOCATE_LOCAL(nrectFill*sizeof(xRectangle));
47195                :    if (pRectCopy)
47196                :    {
47197                :        copyData(prectInit, pRectCopy, nrectFill, MoreCopy2);
47198                :
47199                :        (* pGC->ops->PolyFillRect)(pDrawable, pGC, nrectFill, prectInit);
47200                :        (* pBackingGC->ops->PolyFillRect)(pBackingDrawable,
47201                :                                     pBackingGC, nrectFill, pRectCopy);
47202                :
47203                :        DEALLOCATE_LOCAL(pRectCopy);
47204                :    }
47205                :
47206                :    EPILOGUE (pGC);
47207                :}
47208                :
47209                :/*-
47210                : *-----------------------------------------------------------------------
47211                : * miBSPolyFillArc --
47212                : *      Perform a PolyFillArc, routing output to backing-store as needed.
47213                : *
47214                : * Results:
47215                : *      None.
47216                : *
47217                : * Side Effects:
47218                : *
47219                : *-----------------------------------------------------------------------
47220                : */
47221                :static void
47222                :miBSPolyFillArc(pDrawable, pGC, narcs, parcs)
47223                :    DrawablePtr pDrawable;
47224                :    GCPtr       pGC;
47225                :    int         narcs;
47226                :    xArc        *parcs;
47227                :{
47228                :    xArc  *pArcsCopy;
47229                :    SETUP_BACKING (pDrawable, pGC);
47230                :
47231                :    PROLOGUE(pGC);
47232                :
47233                :    pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc));
47234                :    if (pArcsCopy)
47235                :    {
47236                :        copyData(parcs, pArcsCopy, narcs, MoreCopy4);
47237                :        (* pGC->ops->PolyFillArc)(pDrawable, pGC, narcs, parcs);
47238                :        (* pBackingGC->ops->PolyFillArc)(pBackingDrawable,
47239                :                                    pBackingGC, narcs, pArcsCopy);
47240                :        DEALLOCATE_LOCAL(pArcsCopy);
47241                :    }
47242                :
47243                :    EPILOGUE (pGC);
47244                :}
47245                :
47246                :
47247                :/*-
47248                : *-----------------------------------------------------------------------
47249                : * miBSPolyText8 --
47250                : *      Perform a PolyText8, routing output to backing-store as needed.
47251                : *
47252                : * Results:
47253                : *
47254                : * Side Effects:
47255                : *
47256                : *-----------------------------------------------------------------------
47257                : */
47258                :static int
47259                :miBSPolyText8(pDrawable, pGC, x, y, count, chars)
47260                :    DrawablePtr pDrawable;
47261                :    GCPtr       pGC;
47262                :    int         x, y;
47263                :    int         count;
47264                :    char        *chars;
47265                :{
47266                :    int     result;
47267                :    SETUP_BACKING (pDrawable, pGC);
47268                :
47269                :    PROLOGUE(pGC);
47270                :
47271                :    result = (* pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
47272                :    (* pBackingGC->ops->PolyText8)(pBackingDrawable, pBackingGC,
47273                :                                   x - pBackingStore->x, y - pBackingStore->y,
47274                :                                   count, chars);
47275                :
47276                :    EPILOGUE (pGC);
47277                :    return result;
47278                :}
47279                :
47280                :/*-
47281                : *-----------------------------------------------------------------------
47282                : * miBSPolyText16 --
47283                : *      Perform a PolyText16, routing output to backing-store as needed.
47284                : *
47285                : * Results:
47286                : *
47287                : * Side Effects:
47288                : *
47289                : *-----------------------------------------------------------------------
47290                : */
47291                :static int
47292                :miBSPolyText16(pDrawable, pGC, x, y, count, chars)
47293                :    DrawablePtr pDrawable;
47294                :    GCPtr       pGC;
47295                :    int         x, y;
47296                :    int         count;
47297                :    unsigned short *chars;
47298                :{
47299                :    int result;
47300                :    SETUP_BACKING (pDrawable, pGC);
47301                :
47302                :    PROLOGUE(pGC);
47303                :
47304                :    result = (* pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
47305                :    (* pBackingGC->ops->PolyText16)(pBackingDrawable, pBackingGC,
47306                :                                    x - pBackingStore->x, y - pBackingStore->y,
47307                :                                    count, chars);
47308                :
47309                :    EPILOGUE (pGC);
47310                :
47311                :    return result;
47312                :}
47313                :
47314                :/*-
47315                : *-----------------------------------------------------------------------
47316                : * miBSImageText8 --
47317                : *      Perform a ImageText8, routing output to backing-store as needed.
47318                : *
47319                : * Results:
47320                : *
47321                : * Side Effects:
47322                : *
47323                : *-----------------------------------------------------------------------
47324                : */
47325                :static void
47326                :miBSImageText8(pDrawable, pGC, x, y, count, chars)
47327                :    DrawablePtr pDrawable;
47328                :    GCPtr       pGC;
47329                :    int         x, y;
47330                :    int         count;
47331                :    char        *chars;
47332                :{
47333                :    SETUP_BACKING (pDrawable, pGC);
47334                :    PROLOGUE(pGC);
47335                :
47336                :    (* pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
47337                :    (* pBackingGC->ops->ImageText8)(pBackingDrawable, pBackingGC,
47338                :                                    x - pBackingStore->x, y - pBackingStore->y,
47339                :                                    count, chars);
47340                :
47341                :    EPILOGUE (pGC);
47342                :}
47343                :
47344                :/*-
47345                : *-----------------------------------------------------------------------
47346                : * miBSImageText16 --
47347                : *      Perform a ImageText16, routing output to backing-store as needed.
47348                : *
47349                : * Results:
47350                : *
47351                : * Side Effects:
47352                : *
47353                : *-----------------------------------------------------------------------
47354                : */
47355                :static void
47356                :miBSImageText16(pDrawable, pGC, x, y, count, chars)
47357                :    DrawablePtr pDrawable;
47358                :    GCPtr       pGC;
47359                :    int         x, y;
47360                :    int         count;
47361                :    unsigned short *chars;
47362                :{
47363                :    SETUP_BACKING (pDrawable, pGC);
47364                :    PROLOGUE(pGC);
47365                :
47366                :    (* pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
47367                :    (* pBackingGC->ops->ImageText16)(pBackingDrawable, pBackingGC,
47368                :                                    x - pBackingStore->x, y - pBackingStore->y,
47369                :                                     count, chars);
47370                :
47371                :    EPILOGUE (pGC);
47372                :}
47373                :
47374                :/*-
47375                : *-----------------------------------------------------------------------
47376                : * miBSImageGlyphBlt --
47377                : *      Perform a ImageGlyphBlt, routing output to backing-store as needed.
47378                : *
47379                : * Results:
47380                : *
47381                : * Side Effects:
47382                : *
47383                : *-----------------------------------------------------------------------
47384                : */
47385                :static void
47386                :miBSImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
47387                :    DrawablePtr pDrawable;
47388                :    GCPtr       pGC;
47389                :    int         x, y;
47390                :    unsigned int nglyph;
47391                :    CharInfoPtr *ppci;          /* array of character info */
47392                :    pointer     pglyphBase;     /* start of array of glyphs */
47393                :{
47394                :    SETUP_BACKING (pDrawable, pGC);
47395                :    PROLOGUE(pGC);
47396                :
47397                :    (* pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci,
47398                :                             pglyphBase);
47399                :    (* pBackingGC->ops->ImageGlyphBlt)(pBackingDrawable, pBackingGC,
47400                :                                    x - pBackingStore->x, y - pBackingStore->y,
47401                :                                       nglyph, ppci, pglyphBase);
47402                :
47403                :    EPILOGUE (pGC);
47404                :}
47405                :
47406                :/*-
47407                : *-----------------------------------------------------------------------
47408                : * miBSPolyGlyphBlt --
47409                : *      Perform a PolyGlyphBlt, routing output to backing-store as needed.
47410                : *
47411                : * Results:
47412                : *
47413                : * Side Effects:
47414                : *
47415                : *-----------------------------------------------------------------------
47416                : */
47417                :static void
47418                :miBSPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
47419                :    DrawablePtr pDrawable;
47420                :    GCPtr       pGC;
47421                :    int         x, y;
47422                :    unsigned int nglyph;
47423                :    CharInfoPtr *ppci;          /* array of character info */
47424                :    pointer     pglyphBase;     /* start of array of glyphs */
47425                :{
47426                :    SETUP_BACKING (pDrawable, pGC);
47427                :    PROLOGUE(pGC);
47428                :
47429                :    (* pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
47430                :                            ppci, pglyphBase);
47431                :    (* pBackingGC->ops->PolyGlyphBlt)(pBackingDrawable, pBackingGC,
47432                :                                    x - pBackingStore->x, y - pBackingStore->y,
47433                :                                      nglyph, ppci, pglyphBase);
47434                :    EPILOGUE (pGC);
47435                :}
47436                :
47437                :/*-
47438                : *-----------------------------------------------------------------------
47439                : * miBSPushPixels --
47440                : *      Perform a PushPixels, routing output to backing-store as needed.
47441                : *
47442                : * Results:
47443                : *
47444                : * Side Effects:
47445                : *
47446                : *-----------------------------------------------------------------------
47447                : */
47448                :static void
47449                :miBSPushPixels(pGC, pBitMap, pDst, w, h, x, y)
47450                :    GCPtr       pGC;
47451                :    PixmapPtr   pBitMap;
47452                :    DrawablePtr pDst;
47453                :    int         w, h, x, y;
47454                :{
47455                :    SETUP_BACKING (pDst, pGC);
47456                :    PROLOGUE(pGC);
47457                :
47458                :    (* pGC->ops->PushPixels)(pGC, pBitMap, pDst, w, h, x, y);
47459                :    if (pGC->miTranslate) {
47460                :        x -= pDst->x;
47461                :        y -= pDst->y;
47462                :    }
47463                :    (* pBackingGC->ops->PushPixels)(pBackingGC, pBitMap,
47464                :                               pBackingDrawable, w, h,
47465                :                               x - pBackingStore->x, y - pBackingStore->y);
47466                :
47467                :    EPILOGUE (pGC);
47468                :}
47469                :
47470                :/*-
47471                : *-----------------------------------------------------------------------
47472                : * miBSClearBackingStore --
47473                : *      Clear the given area of the backing pixmap with the background of
47474                : *      the window, whatever it is. If generateExposures is TRUE, generate
47475                : *      exposure events for the area. Note that if the area has any
47476                : *      part outside the saved portions of the window, we do not allow the
47477                : *      count in the expose events to be 0, since there will be more
47478                : *      expose events to come.
47479                : *
47480                : * Results:
47481                : *      None.
47482                : *
47483                : * Side Effects:
47484                : *      Areas of pixmap are cleared and Expose events are generated.
47485                : *
47486                : *-----------------------------------------------------------------------
47487                : */
47488                :static RegionPtr
47489                :miBSClearBackingStore(pWin, x, y, w, h, generateExposures)
47490                :    WindowPtr           pWin;
47491                :    int                 x;
47492                :    int                 y;
47493                :    int                 w;
47494                :    int                 h;
47495                :    Bool                generateExposures;
47496                :{
47497                :    RegionPtr           pRgn;
47498                :    int                 i;
47499                :    miBSWindowPtr       pBackingStore;
47500                :    ScreenPtr           pScreen;
47501                :    GCPtr               pGC;
47502                :    int                 ts_x_origin,
47503                :                        ts_y_origin;
47504                :    pointer             gcvalues[4];
47505                :    unsigned long       gcmask;
47506                :    xRectangle          *rects;
47507                :    BoxPtr              pBox;
47508                :    BoxRec              box;
47509                :    PixUnion            background;
47510                :    char                backgroundState;
47511                :    int                 numRects;
47512                :
47513                :    pBackingStore = (miBSWindowPtr)pWin->backStorage;
47514                :    pScreen = pWin->drawable.pScreen;
47515                :
47516                :    if ((pBackingStore->status == StatusNoPixmap) ||
47517                :        (pBackingStore->status == StatusBadAlloc))
47518                :        return NullRegion;
47519                :    
47520                :    if (w == 0)
47521                :        w = (int) pWin->drawable.width - x;
47522                :    if (h == 0)
47523                :        h = (int) pWin->drawable.height - y;
47524                :
47525                :    box.x1 = x;
47526                :    box.y1 = y;
47527                :    box.x2 = x + w;
47528                :    box.y2 = y + h;
47529                :    pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1);
47530                :    if (!pRgn)
47531                :        return NullRegion;
47532                :    REGION_INTERSECT( pScreen, pRgn, pRgn, &pBackingStore->SavedRegion);
47533                :
47534                :    if (REGION_NOTEMPTY( pScreen, pRgn))
47535                :    {
47536                :        /*
47537                :         * if clearing entire window, simply make new virtual
47538                :         * tile.  For the root window, we also destroy the pixmap
47539                :         * to save a pile of memory
47540                :         */
47541                :        if (x == 0 && y == 0 &&
47542                :            w == pWin->drawable.width &&
47543                :            h == pWin->drawable.height)
47544                :        {
47545                :            if (!pWin->parent)
47546                :                miDestroyBSPixmap (pWin);
47547                :            if (pBackingStore->status != StatusContents)
47548                :                 miTileVirtualBS (pWin);
47549                :        }
47550                :
47551                :        ts_x_origin = ts_y_origin = 0;
47552                :
47553                :        backgroundState = pWin->backgroundState;
47554                :        background = pWin->background;
47555                :        if (backgroundState == ParentRelative) {
47556                :            WindowPtr   pParent;
47557                :
47558                :            pParent = pWin;
47559                :            while (pParent->backgroundState == ParentRelative) {
47560                :                ts_x_origin -= pParent->origin.x;
47561                :                ts_y_origin -= pParent->origin.y;
47562                :                pParent = pParent->parent;
47563                :            }
47564                :            backgroundState = pParent->backgroundState;
47565                :            background = pParent->background;
47566                :        }
47567                :
47568                :        if ((backgroundState != None) &&
47569                :            ((pBackingStore->status == StatusContents) ||
47570                :             !SameBackground (pBackingStore->backgroundState,
47571                :                              pBackingStore->background,
47572                :                              backgroundState,
47573                :                              background)))
47574                :        {
47575                :            if (!pBackingStore->pBackingPixmap)
47576                :                miCreateBSPixmap(pWin, NullBox);
47577                :
47578                :            pGC = GetScratchGC(pWin->drawable.depth, pScreen);
47579                :            if (pGC && pBackingStore->pBackingPixmap)
47580                :            {
47581                :                /*
47582                :                 * First take care of any ParentRelative stuff by altering the
47583                :                 * tile/stipple origin to match the coordinates of the upper-left
47584                :                 * corner of the first ancestor without a ParentRelative background.
47585                :                 * This coordinate is, of course, negative.
47586                :                 */
47587                :            
47588                :                if (backgroundState == BackgroundPixel)
47589                :                {
47590                :                    gcvalues[0] = (pointer) background.pixel;
47591                :                    gcvalues[1] = (pointer)FillSolid;
47592                :                    gcmask = GCForeground|GCFillStyle;
47593                :                }
47594                :                else
47595                :                {
47596                :                    gcvalues[0] = (pointer)FillTiled;
47597                :                    gcvalues[1] = (pointer) background.pixmap;
47598                :                    gcmask = GCFillStyle|GCTile;
47599                :                }
47600                :                gcvalues[2] = (pointer)(long)(ts_x_origin - pBackingStore->x);
47601                :                gcvalues[3] = (pointer)(long)(ts_y_origin - pBackingStore->y);
47602                :                gcmask |= GCTileStipXOrigin|GCTileStipYOrigin;
47603                :                DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE);
47604                :                ValidateGC((DrawablePtr)pBackingStore->pBackingPixmap, pGC);
47605                :    
47606                :                /*
47607                :                 * Figure out the array of rectangles to fill and fill them with
47608                :                 * PolyFillRect in the proper mode, as set in the GC above.
47609                :                 */
47610                :                numRects = REGION_NUM_RECTS(pRgn);
47611                :                rects = (xRectangle *)ALLOCATE_LOCAL(numRects*sizeof(xRectangle));
47612                :            
47613                :                if (rects)
47614                :                {
47615                :                    for (i = 0, pBox = REGION_RECTS(pRgn);
47616                :                         i < numRects;
47617                :                         i++, pBox++)
47618                :                    {
47619                :                        rects[i].x = pBox->x1 - pBackingStore->x;
47620                :                        rects[i].y = pBox->y1 - pBackingStore->y;
47621                :                        rects[i].width = pBox->x2 - pBox->x1;
47622                :                        rects[i].height = pBox->y2 - pBox->y1;
47623                :                    }
47624                :                    (* pGC->ops->PolyFillRect) (
47625                :                                (DrawablePtr)pBackingStore->pBackingPixmap,
47626                :                                       pGC, numRects, rects);
47627                :                    DEALLOCATE_LOCAL(rects);
47628                :                }       
47629                :                FreeScratchGC(pGC);
47630                :            }
47631                :        }       
47632                :
47633                :        if (!generateExposures)
47634                :        {
47635                :            REGION_DESTROY(pScreen, pRgn);
47636                :            pRgn = NULL;
47637                :        }
47638                :        else
47639                :        {
47640                :            /*
47641                :             * result must be screen relative, but is currently
47642                :             * drawable relative.
47643                :             */
47644                :            REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x,
47645                :                             pWin->drawable.y);
47646                :        }
47647                :    }
47648                :    else
47649                :    {
47650                :        REGION_DESTROY( pScreen, pRgn);
47651                :        pRgn = NULL;
47652                :    }
47653                :    return pRgn;
47654                :}
47655                :
47656                :static void
47657                :miBSClearBackingRegion (pWin, pRgn)
47658                :    WindowPtr   pWin;
47659                :    RegionPtr   pRgn;
47660                :{
47661                :    BoxPtr      pBox;
47662                :    int         i;
47663                :
47664                :    i = REGION_NUM_RECTS(pRgn);
47665                :    pBox = REGION_RECTS(pRgn);
47666                :    while (i--)
47667                :    {
47668                :        (void) miBSClearBackingStore(pWin, pBox->x1, pBox->y1,
47669                :                                        pBox->x2 - pBox->x1,
47670                :                                        pBox->y2 - pBox->y1,
47671                :                                        FALSE);
47672                :        pBox++;
47673                :    }
47674                :}
47675                :
47676                :/*
47677                : * fill a region of the destination with virtual bits
47678                : *
47679                : * pRgn is to be translated by (x,y)
47680                : */
47681                :
47682                :static void
47683                :miBSFillVirtualBits (pDrawable, pGC, pRgn, x, y, state, pixunion, planeMask)
47684                :    DrawablePtr         pDrawable;
47685                :    GCPtr               pGC;
47686                :    RegionPtr           pRgn;
47687                :    int                 x, y;
47688                :    int                 state;
47689                :    PixUnion            pixunion;
47690                :    unsigned long       planeMask;
47691                :{
47692                :    int         i;
47693                :    BITS32      gcmask;
47694                :    pointer     gcval[5];
47695                :    xRectangle  *pRect;
47696                :    BoxPtr      pBox;
47697                :    WindowPtr   pWin;
47698                :    int         numRects;
47699                :
47700                :    if (state == None)
47701                :        return;
47702                :    numRects = REGION_NUM_RECTS(pRgn);
47703                :    pRect = (xRectangle *)ALLOCATE_LOCAL(numRects * sizeof(xRectangle));
47704                :    if (!pRect)
47705                :        return;
47706                :    pWin = 0;
47707                :    if (pDrawable->type != DRAWABLE_PIXMAP)
47708                :    {
47709                :        pWin = (WindowPtr) pDrawable;
47710                :        if (!pWin->backStorage)
47711                :            pWin = 0;
47712                :    }
47713                :    i = 0;
47714                :    gcmask = 0;
47715                :    gcval[i++] = (pointer)planeMask;
47716                :    gcmask |= GCPlaneMask;
47717                :    if (state == BackgroundPixel)
47718                :    {
47719                :        if (pGC->fgPixel != pixunion.pixel)
47720                :        {
47721                :            gcval[i++] = (pointer)pixunion.pixel;
47722                :            gcmask |= GCForeground;
47723                :        }
47724                :        if (pGC->fillStyle != FillSolid)
47725                :        {
47726                :            gcval[i++] = (pointer)FillSolid;
47727                :            gcmask |= GCFillStyle;
47728                :        }
47729                :    }
47730                :    else
47731                :    {
47732                :        if (pGC->fillStyle != FillTiled)
47733                :        {
47734                :            gcval[i++] = (pointer)FillTiled;
47735                :            gcmask |= GCFillStyle;
47736                :        }
47737                :        if (pGC->tileIsPixel || pGC->tile.pixmap != pixunion.pixmap)
47738                :        {
47739                :            gcval[i++] = (pointer)pixunion.pixmap;
47740                :            gcmask |= GCTile;
47741                :        }
47742                :        if (pGC->patOrg.x != x)
47743                :        {
47744                :            gcval[i++] = (pointer)(long)x;
47745                :            gcmask |= GCTileStipXOrigin;
47746                :        }
47747                :        if (pGC->patOrg.y != y)
47748                :        {
47749                :            gcval[i++] = (pointer)(long)y;
47750                :            gcmask |= GCTileStipYOrigin;
47751                :        }
47752                :    }
47753                :    if (gcmask)
47754                :        DoChangeGC (pGC, gcmask, (XID *)gcval, 1);
47755                :
47756                :    if (pWin)
47757                :        (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
47758                :
47759                :    if (pDrawable->serialNumber != pGC->serialNumber)
47760                :        ValidateGC (pDrawable, pGC);
47761                :
47762                :    pBox = REGION_RECTS(pRgn);
47763                :    for (i = numRects; --i >= 0; pBox++, pRect++)
47764                :    {
47765                :        pRect->x = pBox->x1 + x;
47766                :        pRect->y = pBox->y1 + y;
47767                :        pRect->width = pBox->x2 - pBox->x1;
47768                :        pRect->height = pBox->y2 - pBox->y1;
47769                :    }
47770                :    pRect -= numRects;
47771                :    (*pGC->ops->PolyFillRect) (pDrawable, pGC, numRects, pRect);
47772                :    if (pWin)
47773                :        (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
47774                :    DEALLOCATE_LOCAL (pRect);
47775                :}
47776                :
47777                :/*-
47778                : *-----------------------------------------------------------------------
47779                : * miBSAllocate --
47780                : *      Create and install backing store info for a window
47781                : *
47782                : *-----------------------------------------------------------------------
47783                : */
47784                :
47785                :static void
47786                :miBSAllocate(pWin)
47787                :    WindowPtr     pWin;
47788                :{
47789                :    miBSWindowPtr       pBackingStore;
47790                :    ScreenPtr           pScreen;
47791                :        
47792                :    if (pWin->drawable.pScreen->backingStoreSupport == NotUseful)
47793                :        return;
47794                :    pScreen = pWin->drawable.pScreen;
47795                :    if (!(pBackingStore = (miBSWindowPtr)pWin->backStorage))
47796                :    {
47797                :
47798                :        pBackingStore = (miBSWindowPtr)xalloc(sizeof(miBSWindowRec));
47799                :        if (!pBackingStore)
47800                :            return;
47801                :
47802                :        pBackingStore->pBackingPixmap = NullPixmap;
47803                :        pBackingStore->x = 0;
47804                :        pBackingStore->y = 0;
47805                :        REGION_NULL( pScreen, &pBackingStore->SavedRegion);
47806                :        pBackingStore->viewable = (char)pWin->viewable;
47807                :        pBackingStore->status = StatusNoPixmap;
47808                :        pBackingStore->backgroundState = None;
47809                :        pWin->backStorage = (pointer) pBackingStore;
47810                :    }
47811                :        
47812                :    /*
47813                :     * Now want to initialize the backing pixmap and SavedRegion if
47814                :     * necessary. The initialization consists of finding all the
47815                :     * currently-obscured regions, by taking the inverse of the window's
47816                :     * clip list, storing the result in SavedRegion, and exposing those
47817                :     * areas of the window.
47818                :     */
47819                :
47820                :    if (pBackingStore->status == StatusNoPixmap &&
47821                :        ((pWin->backingStore == WhenMapped && pWin->viewable) ||
47822                :         (pWin->backingStore == Always)))
47823                :    {
47824                :        BoxRec          box;
47825                :        RegionPtr       pSavedRegion;
47826                :
47827                :        pSavedRegion = &pBackingStore->SavedRegion;
47828                :
47829                :        box.x1 = pWin->drawable.x;
47830                :        box.x2 = box.x1 + (int) pWin->drawable.width;
47831                :        box.y1 = pWin->drawable.y;
47832                :        box.y2 = pWin->drawable.y + (int) pWin->drawable.height;
47833                :
47834                :        REGION_INVERSE( pScreen, pSavedRegion, &pWin->clipList,  &box);
47835                :        REGION_TRANSLATE( pScreen, pSavedRegion,
47836                :                                      -pWin->drawable.x,
47837                :                                      -pWin->drawable.y);
47838                :#ifdef SHAPE
47839                :        if (wBoundingShape (pWin))
47840                :            REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion,
47841                :                             wBoundingShape (pWin));
47842                :        if (wClipShape (pWin))
47843                :            REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion,
47844                :                             wClipShape (pWin));
47845                :#endif
47846                :        /* if window is already on-screen, assume it has been drawn to */
47847                :        if (pWin->viewable)
47848                :            pBackingStore->status = StatusVDirty;
47849                :        miTileVirtualBS (pWin);
47850                :        
47851                :        /*
47852                :         * deliver all the newly available regions
47853                :         * as exposure events to the window
47854                :         */
47855                :
47856                :        miSendExposures(pWin, pSavedRegion, 0, 0);
47857                :    }
47858                :    else if (!pWin->viewable)
47859                :    {
47860                :        /*
47861                :         * Turn off backing store when we're not supposed to
47862                :         * be saving anything
47863                :         */
47864                :        if (pBackingStore->status != StatusNoPixmap)
47865                :        {
47866                :            REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
47867                :            miDestroyBSPixmap (pWin);
47868                :        }
47869                :    }
47870                :}
47871                :
47872                :/*-
47873                : *-----------------------------------------------------------------------
47874                : * miBSFree --
47875                : *      Destroy and free all the stuff associated with the backing-store
47876                : *      for the given window.
47877                : *
47878                : * Results:
47879                : *      None.
47880                : *
47881                : * Side Effects:
47882                : *      The backing pixmap and all the regions and GC's are destroyed.
47883                : *
47884                : *-----------------------------------------------------------------------
47885                : */
47886                :static void
47887                :miBSFree(pWin)
47888                :    WindowPtr pWin;
47889                :{
47890                :    miBSWindowPtr       pBackingStore;
47891                :    ScreenPtr           pScreen;
47892                :
47893                :    pScreen = pWin->drawable.pScreen;
47894                :
47895                :    pBackingStore = (miBSWindowPtr)pWin->backStorage;
47896                :    if (pBackingStore)
47897                :    {
47898                :        miDestroyBSPixmap (pWin);
47899                :
47900                :        REGION_UNINIT( pScreen, &pBackingStore->SavedRegion);
47901                :
47902                :        xfree(pBackingStore);
47903                :        pWin->backStorage = NULL;
47904                :    }
47905                :}
47906                :
47907                :/*-
47908                : *-----------------------------------------------------------------------
47909                : * miResizeBackingStore --
47910                : *      Alter the size of the backing pixmap as necessary when the
47911                : *      SavedRegion changes size. The contents of the old pixmap are
47912                : *      copied/shifted into the new/same pixmap.
47913                : *
47914                : * Results:
47915                : *      The new Pixmap is created as necessary.
47916                : *
47917                : * Side Effects:
47918                : *      The old pixmap is destroyed.
47919                : *
47920                : *-----------------------------------------------------------------------
47921                : */
47922                :static void
47923                :miResizeBackingStore(
47924                :    WindowPtr   pWin,
47925                :    int         dx,         /* bits are moving this far */
47926                :    int         dy,         /* bits are moving this far */
47927                :    Bool        saveBits)   /* bits are useful */
47928                :{
47929                :    miBSWindowPtr pBackingStore;
47930                :    PixmapPtr pBackingPixmap;
47931                :    ScreenPtr pScreen;
47932                :    GC     *pGC;
47933                :    BoxPtr  extents;
47934                :    PixmapPtr pNewPixmap;
47935                :    int nx, ny;
47936                :    int nw, nh;
47937                :
47938                :    pBackingStore = (miBSWindowPtr)(pWin->backStorage);
47939                :    pBackingPixmap = pBackingStore->pBackingPixmap;
47940                :    if (!pBackingPixmap)
47941                :        return;
47942                :    pScreen = pWin->drawable.pScreen;
47943                :    extents = REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion);
47944                :    pNewPixmap = pBackingPixmap;
47945                :
47946                :    nw = extents->x2 - extents->x1;
47947                :    nh = extents->y2 - extents->y1;
47948                :
47949                :    /* the policy here could be more sophisticated */
47950                :    if (nw != pBackingPixmap->drawable.width ||
47951                :        nh != pBackingPixmap->drawable.height)
47952                :    {
47953                :        if (!saveBits || !nw || !nh)
47954                :        {
47955                :            pNewPixmap = NullPixmap;
47956                :            pBackingStore->status = StatusNoPixmap;
47957                :        }
47958                :        else
47959                :        {
47960                :            pNewPixmap = (PixmapPtr)(*pScreen->CreatePixmap)
47961                :                                            (pScreen,
47962                :                                             nw, nh,
47963                :                                             pWin->drawable.depth);
47964                :            if (!pNewPixmap)
47965                :            {
47966                :#ifdef BSEAGER
47967                :                pBackingStore->status = StatusNoPixmap;
47968                :#else
47969                :                pBackingStore->status = StatusBadAlloc;
47970                :#endif
47971                :            }
47972                :        }
47973                :    }
47974                :    if (!pNewPixmap)
47975                :    {
47976                :        pBackingStore->x = 0;
47977                :        pBackingStore->y = 0;
47978                :    }
47979                :    else
47980                :    {
47981                :        nx = pBackingStore->x - extents->x1 + dx;
47982                :        ny = pBackingStore->y - extents->y1 + dy;
47983                :        pBackingStore->x = extents->x1;
47984                :        pBackingStore->y = extents->y1;
47985                :        
47986                :        if (saveBits && (pNewPixmap != pBackingPixmap || nx != 0 || ny != 0))
47987                :        {
47988                :            pGC = GetScratchGC(pNewPixmap->drawable.depth, pScreen);
47989                :            if (pGC)
47990                :            {
47991                :                ValidateGC((DrawablePtr)pNewPixmap, pGC);
47992                :                /* if we implement a policy where the pixmap can be larger than
47993                :                 * the region extents, we might want to optimize this copyarea
47994                :                 * by only copying the old extents, rather than the entire
47995                :                 * pixmap
47996                :                 */
47997                :                (*pGC->ops->CopyArea)((DrawablePtr)pBackingPixmap,
47998                :                                      (DrawablePtr)pNewPixmap, pGC,
47999                :                                      0, 0,
48000                :                                      pBackingPixmap->drawable.width,
48001                :                                      pBackingPixmap->drawable.height,
48002                :                                      nx, ny);
48003                :                FreeScratchGC(pGC);
48004                :            }
48005                :        }
48006                :    }
48007                :    /* SavedRegion is used in the backingGC clip; force an update */
48008                :    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
48009                :    if (pNewPixmap != pBackingPixmap)
48010                :    {
48011                :        (* pScreen->DestroyPixmap)(pBackingPixmap);
48012                :        pBackingStore->pBackingPixmap = pNewPixmap;
48013                :    }
48014                :}
48015                :
48016                :/*-
48017                : *-----------------------------------------------------------------------
48018                : * miBSSaveDoomedAreas --
48019                : *      Saved the areas of the given window that are about to be
48020                : *      obscured.  If the window has moved, pObscured is expected to
48021                : *      be at the new screen location and (dx,dy) is expected to be the offset
48022                : *      to the window's previous location.
48023                : *
48024                : * Results:
48025                : *      None.
48026                : *
48027                : * Side Effects:
48028                : *      The region is copied from the screen into pBackingPixmap and
48029                : *      SavedRegion is updated.
48030                : *
48031                : *-----------------------------------------------------------------------
48032                : */
48033                :static void
48034                :miBSSaveDoomedAreas(pWin, pObscured, dx, dy)
48035                :    WindowPtr           pWin;
48036                :    RegionPtr           pObscured;
48037                :    int                 dx, dy;
48038                :{
48039                :    miBSWindowPtr       pBackingStore;
48040                :    ScreenPtr           pScreen;
48041                :    int                 x, y;
48042                :
48043                :    pBackingStore = (miBSWindowPtr)pWin->backStorage;
48044                :    pScreen = pWin->drawable.pScreen;
48045                :
48046                :    /*
48047                :     * If the window isn't realized, it's being unmapped, thus we don't
48048                :     * want to save anything if backingStore isn't Always.
48049                :     */
48050                :    if (!pWin->realized)
48051                :    {
48052                :        pBackingStore->viewable = (char)pWin->viewable;
48053                :        if (pWin->backingStore != Always)
48054                :        {
48055                :            REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
48056                :            miDestroyBSPixmap (pWin);
48057                :            return;
48058                :        }
48059                :        if (pBackingStore->status == StatusBadAlloc)
48060                :            pBackingStore->status = StatusNoPixmap;
48061                :    }
48062                :
48063                :    /* Don't even pretend to save anything for a virtual background None */
48064                :    if ((pBackingStore->status == StatusVirtual) &&
48065                :        (pBackingStore->backgroundState == None))
48066                :        return;
48067                :
48068                :    if (REGION_NOTEMPTY(pScreen, pObscured))
48069                :    {
48070                :        BoxRec  oldExtents;
48071                :        x = pWin->drawable.x;
48072                :        y = pWin->drawable.y;
48073                :        REGION_TRANSLATE(pScreen, pObscured, -x, -y);
48074                :        oldExtents = *REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion);
48075                :        REGION_UNION( pScreen, &pBackingStore->SavedRegion,
48076                :                           &pBackingStore->SavedRegion,
48077                :                           pObscured);
48078                :        /*
48079                :         * only save the bits if we've actually
48080                :         * started using backing store
48081                :         */
48082                :        if (pBackingStore->status != StatusVirtual)
48083                :        {
48084                :            if (!pBackingStore->pBackingPixmap)
48085                :                miCreateBSPixmap (pWin, &oldExtents);
48086                :            else
48087                :                miResizeBackingStore(pWin, 0, 0, TRUE);
48088                :
48089                :            if (pBackingStore->pBackingPixmap) {
48090                :                if (pBackingStore->x | pBackingStore->y)
48091                :                {
48092                :                    REGION_TRANSLATE( pScreen, pObscured,
48093                :                                                  -pBackingStore->x,
48094                :                                                  -pBackingStore->y);
48095                :                    x += pBackingStore->x;
48096                :                    y += pBackingStore->y;
48097                :                }
48098                :                (* pScreen->BackingStoreFuncs.SaveAreas)
48099                :                    (pBackingStore->pBackingPixmap, pObscured,
48100                :                     x - dx, y - dy, pWin);
48101                :            }
48102                :        }
48103                :        REGION_TRANSLATE(pScreen, pObscured, x, y);
48104                :    }
48105                :    else
48106                :    {
48107                :        if (REGION_BROKEN (pScreen, pObscured))
48108                :        {
48109                :            REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
48110                :            miDestroyBSPixmap (pWin);
48111                :            return;
48112                :        }
48113                :    }
48114                :}
48115                :
48116                :/*-
48117                : *-----------------------------------------------------------------------
48118                : * miBSRestoreAreas --
48119                : *      Restore areas from backing-store that are no longer obscured.
48120                : *      expects prgnExposed to contain a screen-relative area.
48121                : *
48122                : * Results:
48123                : *      The region to generate exposure events on (which may be
48124                : *      different from the region to paint).
48125                : *
48126                : * Side Effects:
48127                : *      Areas are copied from pBackingPixmap to the screen. prgnExposed
48128                : *      is altered to contain the region that could not be restored from
48129                : *      backing-store.
48130                : *
48131                : * Notes:
48132                : *      This is called before sending any exposure events to the client,
48133                : *      and so might be called if the window has grown.  Changing the backing
48134                : *      pixmap doesn't require revalidating the backingGC because the
48135                : *      client's next output request will result in a call to ValidateGC,
48136                : *      since the window clip region has changed, which will in turn call
48137                : *      miValidateBackingStore.
48138                : *-----------------------------------------------------------------------
48139                : */
48140                :static RegionPtr
48141                :miBSRestoreAreas(pWin, prgnExposed)
48142                :    WindowPtr pWin;
48143                :    RegionPtr prgnExposed;
48144                :{
48145                :    PixmapPtr pBackingPixmap;
48146                :    miBSWindowPtr pBackingStore;
48147                :    RegionPtr prgnSaved;
48148                :    RegionPtr prgnRestored;
48149                :    ScreenPtr pScreen;
48150                :    RegionPtr exposures = prgnExposed;
48151                :
48152                :    pScreen = pWin->drawable.pScreen;
48153                :    pBackingStore = (miBSWindowPtr)pWin->backStorage;
48154                :    pBackingPixmap = pBackingStore->pBackingPixmap;
48155                :
48156                :    prgnSaved = &pBackingStore->SavedRegion;
48157                :
48158                :    if (pBackingStore->status == StatusContents)
48159                :    {
48160                :        REGION_TRANSLATE(pScreen, prgnSaved, pWin->drawable.x,
48161                :                         pWin->drawable.y);
48162                :
48163                :        prgnRestored = REGION_CREATE( pScreen, (BoxPtr)NULL, 1);
48164                :        REGION_INTERSECT( pScreen, prgnRestored, prgnExposed, prgnSaved);
48165                :        
48166                :        /*
48167                :         * Since prgnExposed is no longer obscured, we no longer
48168                :         * will have a valid copy of it in backing-store, but there is a valid
48169                :         * copy of it on screen, so subtract the area we just restored from
48170                :         * from the area to be exposed.
48171                :         */
48172                :
48173                :        if (REGION_NOTEMPTY( pScreen, prgnRestored))
48174                :        {
48175                :            REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed);
48176                :            REGION_SUBTRACT( pScreen, prgnExposed, prgnExposed, prgnRestored);
48177                :
48178                :            /*
48179                :             * Do the actual restoration
48180                :             */
48181                :            (* pScreen->BackingStoreFuncs.RestoreAreas) (pBackingPixmap,
48182                :                                          prgnRestored,
48183                :                                          pWin->drawable.x + pBackingStore->x,
48184                :                                          pWin->drawable.y + pBackingStore->y,
48185                :                                          pWin);
48186                :            /*
48187                :             * if the saved region is completely empty, dispose of the
48188                :             * backing pixmap, otherwise, retranslate the saved
48189                :             * region to window relative
48190                :             */
48191                :
48192                :            if (REGION_NOTEMPTY(pScreen, prgnSaved))
48193                :            {
48194                :                REGION_TRANSLATE(pScreen, prgnSaved,
48195                :                                             -pWin->drawable.x,
48196                :                                             -pWin->drawable.y);
48197                :                miResizeBackingStore(pWin, 0, 0, TRUE);
48198                :            }
48199                :            else
48200                :                miDestroyBSPixmap (pWin);
48201                :        }
48202                :        else
48203                :            REGION_TRANSLATE(pScreen, prgnSaved,
48204                :                                -pWin->drawable.x, -pWin->drawable.y);
48205                :        REGION_DESTROY( pScreen, prgnRestored);
48206                :
48207                :    }
48208                :    else if ((pBackingStore->status == StatusVirtual) ||
48209                :             (pBackingStore->status == StatusVDirty))
48210                :    {
48211                :        REGION_TRANSLATE(pScreen, prgnSaved,
48212                :                                     pWin->drawable.x, pWin->drawable.y);
48213                :        exposures = REGION_CREATE( pScreen, NullBox, 1);
48214                :        if (SameBackground (pBackingStore->backgroundState,
48215                :                            pBackingStore->background,
48216                :                            pWin->backgroundState,
48217                :                            pWin->background))
48218                :        {
48219                :            REGION_SUBTRACT( pScreen, exposures, prgnExposed, prgnSaved);
48220                :        }
48221                :        else
48222                :        {
48223                :            miTileVirtualBS(pWin);
48224                :
48225                :            /* we need to expose all we have (virtually) retiled */
48226                :            REGION_UNION( pScreen, exposures, prgnExposed, prgnSaved);
48227                :        }
48228                :        REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed);
48229                :        REGION_TRANSLATE(pScreen, prgnSaved,
48230                :                                     -pWin->drawable.x, -pWin->drawable.y);
48231                :    }
48232                :    else if (pWin->viewable && !pBackingStore->viewable &&
48233                :             pWin->backingStore != Always)
48234                :    {
48235                :        /*
48236                :         * The window was just mapped and nothing has been saved in
48237                :         * backing-store from the last time it was mapped. We want to capture
48238                :         * any output to regions that are already obscured but there are no
48239                :         * bits to snag off the screen, so we initialize things just as we did
48240                :         * in miBSAllocate, above.
48241                :         */
48242                :        BoxRec  box;
48243                :        
48244                :        prgnSaved = &pBackingStore->SavedRegion;
48245                :
48246                :        box.x1 = pWin->drawable.x;
48247                :        box.x2 = box.x1 + (int) pWin->drawable.width;
48248                :        box.y1 = pWin->drawable.y;
48249                :        box.y2 = box.y1 + (int) pWin->drawable.height;
48250                :        
48251                :        REGION_INVERSE( pScreen, prgnSaved, &pWin->clipList,  &box);
48252                :        REGION_TRANSLATE( pScreen, prgnSaved,
48253                :                                      -pWin->drawable.x,
48254                :                                      -pWin->drawable.y);
48255                :#ifdef SHAPE
48256                :        if (wBoundingShape (pWin))
48257                :            REGION_INTERSECT(pScreen, prgnSaved, prgnSaved,
48258                :                             wBoundingShape (pWin));
48259                :        if (wClipShape (pWin))
48260                :            REGION_INTERSECT(pScreen, prgnSaved, prgnSaved,
48261                :                             wClipShape (pWin));
48262                :#endif
48263                :        miTileVirtualBS(pWin);
48264                :
48265                :        exposures = REGION_CREATE( pScreen, &box, 1);
48266                :    }
48267                :    pBackingStore->viewable = (char)pWin->viewable;
48268                :    return exposures;
48269                :}
48270                :
48271                :
48272                :/*-
48273                : *-----------------------------------------------------------------------
48274                : * miBSTranslateBackingStore --
48275                : *      Shift the backing-store in the given direction. Called when bit
48276                : *      gravity is shifting things around. 
48277                : *
48278                : * Results:
48279                : *      An occluded region of the window which should be sent exposure events.
48280                : *      This region should be in absolute coordinates (i.e. include
48281                : *      new window position).
48282                : *
48283                : * Side Effects:
48284                : *      If the window changed size as well as position, the backing pixmap
48285                : *      is resized. The contents of the backing pixmap are shifted
48286                : *
48287                : * Warning:
48288                : *      Bob and I have rewritten this routine quite a few times, each
48289                : *      time it gets a few more cases correct, and introducing some
48290                : *      interesting bugs.  Naturally, I think the code is correct this
48291                : *      time.
48292                : *
48293                : *      Let me try to explain what this routine is for:
48294                : *
48295                : *      It's called from SlideAndSizeWindow whenever a window
48296                : *      with backing store is resized.  There are two separate
48297                : *      possibilities:
48298                : *
48299                : *      a)  The window has ForgetGravity
48300                : *
48301                : *          In this case, windx, windy will be 0 and oldClip will
48302                : *          be NULL.  This indicates that all of the window contents
48303                : *          currently saved offscreen should be discarded, and the
48304                : *          entire window exposed.  TranslateBackingStore, then, should
48305                : *          prepare a completely new backing store region based on the
48306                : *          new window clipList and return that region for exposure.
48307                : *
48308                : *      b)  The window has some other gravity
48309                : *
48310                : *          In this case, windx, windy will be set to the distance
48311                : *          that the bits should move within the window.  oldClip
48312                : *          will be set to the old visible portion of the window.
48313                : *          TranslateBackingStore, then, should adjust the backing
48314                : *          store to accommodate the portion of the existing backing
48315                : *          store bits which coorespond to backing store bits which
48316                : *          will still be occluded in the new configuration.  oldx,oldy
48317                : *          are set to the old position of the window on the screen.
48318                : *
48319                : *          Furthermore, in this case any contents of the screen which
48320                : *          are about to become occluded should be fetched from the screen
48321                : *          and placed in backing store.  This is to avoid the eventual
48322                : *          occlusion by the win gravity shifting the child window bits around
48323                : *          on top of this window, and potentially losing information
48324                : *
48325                : *      It's also called from SetShape, but I think (he says not
48326                : *      really knowing for sure) that this code will even work
48327                : *      in that case.
48328                : *-----------------------------------------------------------------------
48329                : */
48330                :
48331                :static RegionPtr
48332                :miBSTranslateBackingStore(pWin, windx, windy, oldClip, oldx, oldy)
48333                :    WindowPtr     pWin;
48334                :    int           windx;        /* bit translation distance in window */
48335                :    int           windy;
48336                :    RegionPtr     oldClip;      /* Region being copied */
48337                :    int           oldx;         /* old window position */
48338                :    int           oldy;
48339                :{
48340                :    miBSWindowPtr       pBackingStore;
48341                :    RegionPtr           pSavedRegion;
48342                :    RegionPtr           newSaved, doomed;
48343                :    ScreenPtr           pScreen;
48344                :    BoxRec              extents;
48345                :    int                 scrdx;  /* bit translation distance on screen */
48346                :    int                 scrdy;
48347                :    int                 dx;             /* distance window moved  on screen */
48348                :    int                 dy;
48349                :
48350                :    pScreen = pWin->drawable.pScreen;
48351                :    pBackingStore = (miBSWindowPtr)(pWin->backStorage);
48352                :    if ((pBackingStore->status == StatusNoPixmap) ||
48353                :        (pBackingStore->status == StatusBadAlloc))
48354                :        return NullRegion;
48355                :
48356                :    /*
48357                :     * Compute the new saved region
48358                :     */
48359                :
48360                :    newSaved = REGION_CREATE( pScreen, NullBox, 1);
48361                :    extents.x1 = pWin->drawable.x;
48362                :    extents.x2 = pWin->drawable.x + (int) pWin->drawable.width;
48363                :    extents.y1 = pWin->drawable.y;
48364                :    extents.y2 = pWin->drawable.y + (int) pWin->drawable.height;
48365                :    REGION_INVERSE( pScreen, newSaved, &pWin->clipList, &extents);
48366                :
48367                :    REGION_TRANSLATE( pScreen, newSaved,
48368                :                        -pWin->drawable.x, -pWin->drawable.y);
48369                :#ifdef SHAPE
48370                :    if (wBoundingShape (pWin) || wClipShape (pWin)) {
48371                :        if (wBoundingShape (pWin))
48372                :            REGION_INTERSECT( pScreen, newSaved, newSaved,
48373                :                                wBoundingShape (pWin));
48374                :        if (wClipShape (pWin))
48375                :            REGION_INTERSECT( pScreen, newSaved, newSaved, wClipShape (pWin));
48376                :    }
48377                :#endif
48378                :    
48379                :    pSavedRegion = &pBackingStore->SavedRegion;
48380                :
48381                :    /* now find any visible areas we can save from the screen */
48382                :    /* and then translate newSaved to old local coordinates */
48383                :    if (oldClip)
48384                :    {
48385                :        /* bit gravity makes things virtually too hard, punt */
48386                :        if (((windx != 0) || (windy != 0)) &&
48387                :            (pBackingStore->status != StatusContents))
48388                :            miCreateBSPixmap(pWin, NullBox);
48389                :    
48390                :        /*
48391                :         * The window is moving this far on the screen
48392                :         */
48393                :        dx = pWin->drawable.x - oldx;
48394                :        dy = pWin->drawable.y - oldy;
48395                :        /*
48396                :         * The bits will be moving on the screen by the
48397                :         * amount the window is moving + the amount the
48398                :         * bits are moving within the window
48399                :         */
48400                :        scrdx = windx + dx;
48401                :        scrdy = windy + dy;
48402                :    
48403                :        /*
48404                :         * intersect at old bit position to discover the
48405                :         * bits on the screen which can be put into the
48406                :         * new backing store
48407                :         */
48408                :        REGION_TRANSLATE( pScreen, oldClip, windx - oldx, windy - oldy);
48409                :        doomed = REGION_CREATE( pScreen, NullBox, 1);
48410                :        REGION_INTERSECT( pScreen, doomed, oldClip, newSaved);
48411                :        REGION_TRANSLATE( pScreen, oldClip, oldx - windx, oldy - windy);
48412                :
48413                :        /*
48414                :         * Translate the old saved region to the position in the
48415                :         * window where it will appear to be
48416                :         */
48417                :        REGION_TRANSLATE( pScreen, pSavedRegion, windx, windy);
48418                :
48419                :        /*
48420                :         * Add the old saved region to the new saved region, so
48421                :         * that calls to RestoreAreas will be able to fetch those
48422                :         * bits back
48423                :         */
48424                :        REGION_UNION( pScreen, newSaved, newSaved, pSavedRegion);
48425                :
48426                :        /*
48427                :         * Swap the new saved region into the window
48428                :         */
48429                :        {
48430                :            RegionRec   tmp;
48431                :
48432                :            tmp = *pSavedRegion;
48433                :            *pSavedRegion = *newSaved;
48434                :            *newSaved = tmp;
48435                :        }
48436                :        miResizeBackingStore (pWin, windx, windy, TRUE);
48437                :
48438                :        /*
48439                :         * Compute the newly enabled region
48440                :         * of backing store.  This region will be
48441                :         * set to background in the backing pixmap and
48442                :         * sent as exposure events to the client.
48443                :         */
48444                :        REGION_SUBTRACT( pScreen, newSaved, pSavedRegion, newSaved);
48445                :
48446                :        /*
48447                :         * Fetch bits which will be obscured from
48448                :         * the screen
48449                :         */
48450                :        if (REGION_NOTEMPTY( pScreen, doomed))
48451                :        {
48452                :            /*
48453                :             * Don't clear regions which have bits on the
48454                :             * screen
48455                :             */
48456                :            REGION_SUBTRACT( pScreen, newSaved, newSaved, doomed);
48457                :
48458                :            /*
48459                :             * Make the region to SaveDoomedAreas absolute, instead
48460                :             * of window relative.
48461                :             */
48462                :            REGION_TRANSLATE( pScreen, doomed,
48463                :                                          pWin->drawable.x, pWin->drawable.y);
48464                :            (* pScreen->SaveDoomedAreas) (pWin, doomed, scrdx, scrdy);
48465                :        }
48466                :        
48467                :        REGION_DESTROY(pScreen, doomed);
48468                :
48469                :        /*
48470                :         * and clear whatever there is that's new
48471                :         */
48472                :        if (REGION_NOTEMPTY( pScreen, newSaved))
48473                :        {
48474                :            miBSClearBackingRegion (pWin, newSaved);
48475                :            /*
48476                :             * Make the exposed region absolute
48477                :             */
48478                :            REGION_TRANSLATE(pScreen, newSaved,
48479                :                                         pWin->drawable.x,
48480                :                                         pWin->drawable.y);
48481                :        }
48482                :        else
48483                :        {
48484                :            REGION_DESTROY(pScreen, newSaved);
48485                :            newSaved = NullRegion;
48486                :        }
48487                :    }
48488                :    else
48489                :    {
48490                :        /*
48491                :         * ForgetGravity: just reset backing store and
48492                :         * expose the whole mess
48493                :         */
48494                :        REGION_COPY( pScreen, pSavedRegion, newSaved);
48495                :        REGION_TRANSLATE( pScreen, newSaved,
48496                :                                      pWin->drawable.x, pWin->drawable.y);
48497                :
48498                :        miResizeBackingStore (pWin, 0, 0, FALSE);
48499                :        (void) miBSClearBackingStore (pWin, 0, 0, 0, 0, FALSE);
48500                :    }
48501                :
48502                :    return newSaved;
48503                :}
48504                :
48505                :/*
48506                : * Inform the backing store layer that you are about to validate
48507                : * a gc with a window, and that subsequent output to the window
48508                : * is (or is not) guaranteed to be already clipped to the visible
48509                : * regions of the window.
48510                : */
48511                :
48512                :static void
48513                :miBSDrawGuarantee (pWin, pGC, guarantee)
48514                :    WindowPtr   pWin;
48515                :    GCPtr       pGC;
48516                :    int         guarantee;
48517                :{
48518                :    miBSGCPtr   pPriv;
48519                :
48520                :    if (pWin->backStorage)
48521                :    {
48522                :        pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
48523                :        if (!pPriv)
48524                :            (void) miBSCreateGCPrivate (pGC);
48525                :        pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
48526                :        if (pPriv)
48527                :        {
48528                :            /*
48529                :             * XXX KLUDGE ALERT
48530                :             *
48531                :             * when the GC is Cheap pPriv will point
48532                :             * at some device's gc func structure.  guarantee
48533                :             * will point at the ChangeGC entry of that struct
48534                :             * and will never match a valid guarantee value.
48535                :             */
48536                :            switch (pPriv->guarantee)
48537                :            {
48538                :            case GuaranteeNothing:
48539                :            case GuaranteeVisBack:
48540                :                pPriv->guarantee = guarantee;
48541                :                break;
48542                :            }
48543                :        }
48544                :    }
48545                :}
48546                :
48547                :#define noBackingCopy (GCGraphicsExposures|GCClipXOrigin|GCClipYOrigin| \
48548                :                       GCClipMask|GCSubwindowMode| \
48549                :                       GCTileStipXOrigin|GCTileStipYOrigin)
48550                :
48551                :/*-
48552                : *-----------------------------------------------------------------------
48553                : * miBSValidateGC --
48554                : *      Wrapper around output-library's ValidateGC routine
48555                : *
48556                : * Results:
48557                : *      None.
48558                : *
48559                : * Side Effects:
48560                : *
48561                : * Notes:
48562                : *      The idea here is to perform several functions:
48563                : *          - All the output calls must be intercepted and routed to
48564                : *            backing-store as necessary.
48565                : *          - pGC in the window's devBackingStore must be set up with the
48566                : *            clip list appropriate for writing to pBackingPixmap (i.e.
48567                : *            the inverse of the window's clipList intersected with the
48568                : *            clientClip of the GC). Since the destination for this GC is
48569                : *            a pixmap, it is sufficient to set the clip list as its
48570                : *            clientClip.
48571                : *-----------------------------------------------------------------------
48572                : */
48573                :
48574                :static void
48575                :miBSValidateGC (pGC, stateChanges, pDrawable)
48576                :    GCPtr         pGC;
48577                :    unsigned long stateChanges;
48578                :    DrawablePtr   pDrawable;
48579                :{
48580                :    GCPtr               pBackingGC;
48581                :    miBSWindowPtr       pWindowPriv = NULL;
48582                :    miBSGCPtr           pPriv;
48583                :    WindowPtr           pWin;
48584                :    int                 lift_functions;
48585                :    RegionPtr           backingCompositeClip = NULL;
48586                :
48587                :    if (pDrawable->type != DRAWABLE_PIXMAP)
48588                :    {
48589                :        pWin = (WindowPtr) pDrawable;
48590                :        pWindowPriv = (miBSWindowPtr) pWin->backStorage;
48591                :        lift_functions = (pWindowPriv == (miBSWindowPtr) NULL);
48592                :    }
48593                :    else
48594                :    {
48595                :        pWin = (WindowPtr) NULL;
48596                :        lift_functions = TRUE;
48597                :    }
48598                :
48599                :    pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
48600                :
48601                :    FUNC_PROLOGUE (pGC, pPriv);
48602                :
48603                :    (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
48604                :
48605                :    /*
48606                :     * rewrap funcs and ops as Validate may have changed them
48607                :     */
48608                :
48609                :    pPriv->wrapFuncs = pGC->funcs;
48610                :    pPriv->wrapOps = pGC->ops;
48611                :
48612                :    if (!lift_functions && ((pPriv->guarantee == GuaranteeVisBack) ||
48613                :                            (pWindowPriv->status == StatusNoPixmap) ||
48614                :                            (pWindowPriv->status == StatusBadAlloc)))
48615                :        lift_functions = TRUE;
48616                :
48617                :    /*
48618                :     * check to see if a new backingCompositeClip region must
48619                :     * be generated
48620                :     */
48621                :
48622                :    if (!lift_functions && 
48623                :        ((pDrawable->serialNumber != pPriv->serialNumber) ||
48624                :         (stateChanges&(GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode))))
48625                :    {
48626                :        if (REGION_NOTEMPTY(pGC->pScreen, &pWindowPriv->SavedRegion))
48627                :        {
48628                :            backingCompositeClip = REGION_CREATE(pGC->pScreen, NULL, 1);
48629                :            if ((pGC->clientClipType == CT_NONE) || 
48630                :                (pGC->clientClipType == CT_PIXMAP))
48631                :            {
48632                :                REGION_COPY(pGC->pScreen, backingCompositeClip,
48633                :                                             &pWindowPriv->SavedRegion); 
48634                :            }
48635                :            else
48636                :            {
48637                :                /*
48638                :                 * Make a new copy of the client clip, translated to
48639                :                 * its proper origin.
48640                :                 */
48641                :
48642                :                REGION_COPY(pGC->pScreen, backingCompositeClip,
48643                :                                pGC->clientClip);
48644                :                REGION_TRANSLATE(pGC->pScreen, backingCompositeClip,
48645                :                                                  pGC->clipOrg.x,
48646                :                                                  pGC->clipOrg.y);
48647                :                REGION_INTERSECT(pGC->pScreen, backingCompositeClip,
48648                :                                        backingCompositeClip,
48649                :                                        &pWindowPriv->SavedRegion);
48650                :            }
48651                :            if (pGC->subWindowMode == IncludeInferiors)
48652                :            {
48653                :                RegionPtr translatedClip;
48654                :
48655                :                /* XXX
48656                :                 * any output in IncludeInferiors mode will not
48657                :                 * be redirected to Inferiors backing store.  This
48658                :                 * can be fixed only at great cost to the shadow routines.
48659                :                 */
48660                :                translatedClip = NotClippedByChildren (pWin);
48661                :                REGION_TRANSLATE(pGC->pScreen, translatedClip,
48662                :                                                  -pDrawable->x,
48663                :                                                  -pDrawable->y);
48664                :                REGION_SUBTRACT(pGC->pScreen, backingCompositeClip,
48665                :                                backingCompositeClip, translatedClip);
48666                :                REGION_DESTROY(pGC->pScreen, translatedClip);
48667                :            }
48668                :            if (!REGION_NOTEMPTY(pGC->pScreen, backingCompositeClip))
48669                :                lift_functions = TRUE;
48670                :        }
48671                :        else
48672                :        {
48673                :            lift_functions = TRUE;
48674                :        }
48675                :
48676                :        /* Reset the status when drawing to an unoccluded window so that
48677                :         * future SaveAreas will actually copy bits from the screen.  Note that
48678                :         * output to root window in IncludeInferiors mode will not cause this
48679                :         * to change.  This causes all transient graphics by the window
48680                :         * manager to the root window to not enable backing store.
48681                :         */
48682                :        if (lift_functions && (pWindowPriv->status == StatusVirtual) &&
48683                :            (pWin->parent || pGC->subWindowMode != IncludeInferiors))
48684                :            pWindowPriv->status = StatusVDirty;
48685                :    }
48686                :
48687                :    /*
48688                :     * if no backing store has been allocated, and it's needed,
48689                :     * create it now.
48690                :     */
48691                :
48692                :    if (!lift_functions && !pWindowPriv->pBackingPixmap)
48693                :    {
48694                :        miCreateBSPixmap (pWin, NullBox);
48695                :        if (!pWindowPriv->pBackingPixmap)
48696                :            lift_functions = TRUE;
48697                :    }
48698                :    
48699                :    /*
48700                :     * create the backing GC if needed, lift functions
48701                :     * if the creation fails
48702                :     */
48703                :
48704                :    if (!lift_functions && !pPriv->pBackingGC)
48705                :    {
48706                :        int status;
48707                :        XID noexpose = xFalse;
48708                :
48709                :        /* We never want ops with the backingGC to generate GraphicsExpose */
48710                :        pBackingGC = CreateGC ((DrawablePtr)pWindowPriv->pBackingPixmap,
48711                :                               GCGraphicsExposures, &noexpose, &status);
48712                :        if (status != Success)
48713                :            lift_functions = TRUE;
48714                :        else
48715                :            pPriv->pBackingGC = pBackingGC;
48716                :    }
48717                :
48718                :    pBackingGC = pPriv->pBackingGC;
48719                :
48720                :    pPriv->stateChanges |= stateChanges;
48721                :
48722                :    if (lift_functions)
48723                :    {
48724                :        if (backingCompositeClip)
48725                :            REGION_DESTROY( pGC->pScreen, backingCompositeClip);
48726                :
48727                :        /* unwrap the GC again */
48728                :        miBSDestroyGCPrivate (pGC);
48729                :
48730                :        return;
48731                :    }
48732                :
48733                :    /*
48734                :     * the rest of this function gets the pBackingGC
48735                :     * into shape for possible draws
48736                :     */
48737                :
48738                :    pPriv->stateChanges &= ~noBackingCopy;
48739                :    if (pPriv->stateChanges)
48740                :        CopyGC(pGC, pBackingGC, pPriv->stateChanges);
48741                :    if ((pGC->patOrg.x - pWindowPriv->x) != pBackingGC->patOrg.x ||
48742                :        (pGC->patOrg.y - pWindowPriv->y) != pBackingGC->patOrg.y)
48743                :    {
48744                :        XID vals[2];
48745                :        vals[0] = pGC->patOrg.x - pWindowPriv->x;
48746                :        vals[1] = pGC->patOrg.y - pWindowPriv->y;
48747                :        DoChangeGC(pBackingGC, GCTileStipXOrigin|GCTileStipYOrigin, vals, 0);
48748                :    }
48749                :    pPriv->stateChanges = 0;
48750                :
48751                :    if (backingCompositeClip)
48752                :    {
48753                :        XID vals[2];
48754                :
48755                :        if (pGC->clientClipType == CT_PIXMAP)
48756                :        {
48757                :            (*pBackingGC->funcs->CopyClip)(pBackingGC, pGC);
48758                :            REGION_TRANSLATE(pGC->pScreen, backingCompositeClip,
48759                :                                        -pGC->clipOrg.x, -pGC->clipOrg.y);
48760                :            vals[0] = pGC->clipOrg.x - pWindowPriv->x;
48761                :            vals[1] = pGC->clipOrg.y - pWindowPriv->y;
48762                :            DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
48763                :            (* pGC->pScreen->BackingStoreFuncs.SetClipmaskRgn)
48764                :                (pBackingGC, backingCompositeClip);
48765                :            REGION_DESTROY( pGC->pScreen, backingCompositeClip);
48766                :        }
48767                :        else
48768                :        {
48769                :            vals[0] = -pWindowPriv->x;
48770                :            vals[1] = -pWindowPriv->y;
48771                :            DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
48772                :            (*pBackingGC->funcs->ChangeClip) (pBackingGC, CT_REGION, backingCompositeClip, 0);
48773                :        }
48774                :        pPriv->serialNumber = pDrawable->serialNumber;
48775                :    }
48776                :    
48777                :    if (pWindowPriv->pBackingPixmap->drawable.serialNumber
48778                :        != pBackingGC->serialNumber)
48779                :    {
48780                :        ValidateGC((DrawablePtr)pWindowPriv->pBackingPixmap, pBackingGC);
48781                :    }
48782                :
48783                :    if (pBackingGC->clientClip == 0)
48784                :        ErrorF ("backing store clip list nil");
48785                :
48786                :    FUNC_EPILOGUE (pGC, pPriv);
48787                :}
48788                :
48789                :static void
48790                :miBSChangeGC (pGC, mask)
48791                :    GCPtr   pGC;
48792                :    unsigned long   mask;
48793                :{
48794                :    miBSGCPtr   pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
48795                :
48796                :    FUNC_PROLOGUE (pGC, pPriv);
48797                :
48798                :    (*pGC->funcs->ChangeGC) (pGC, mask);
48799                :
48800                :    FUNC_EPILOGUE (pGC, pPriv);
48801                :}
48802                :
48803                :static void
48804                :miBSCopyGC (pGCSrc, mask, pGCDst)
48805                :    GCPtr   pGCSrc, pGCDst;
48806                :    unsigned long   mask;
48807                :{
48808                :    miBSGCPtr   pPriv = (miBSGCPtr) (pGCDst)->devPrivates[miBSGCIndex].ptr;
48809                :
48810                :    FUNC_PROLOGUE (pGCDst, pPriv);
48811                :
48812                :    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
48813                :
48814                :    FUNC_EPILOGUE (pGCDst, pPriv);
48815                :}
48816                :
48817                :static void
48818                :miBSDestroyGC (pGC)
48819                :    GCPtr   pGC;
48820                :{
48821                :    miBSGCPtr   pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
48822                :
48823                :    FUNC_PROLOGUE (pGC, pPriv);
48824                :
48825                :    if (pPriv->pBackingGC)
48826                :        FreeGC(pPriv->pBackingGC, (GContext)0);
48827                :
48828                :    (*pGC->funcs->DestroyGC) (pGC);
48829                :
48830                :    FUNC_EPILOGUE (pGC, pPriv);
48831                :
48832                :    xfree(pPriv);
48833                :}
48834                :
48835                :static void
48836                :miBSChangeClip(pGC, type, pvalue, nrects)
48837                :    GCPtr       pGC;
48838                :    int         type;
48839                :    pointer     pvalue;
48840                :    int         nrects;
48841                :{
48842                :    miBSGCPtr   pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
48843                :
48844                :    FUNC_PROLOGUE (pGC, pPriv);
48845                :
48846                :    (* pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
48847                :
48848                :    FUNC_EPILOGUE (pGC, pPriv);
48849                :}
48850                :
48851                :static void
48852                :miBSCopyClip(pgcDst, pgcSrc)
48853                :    GCPtr pgcDst, pgcSrc;
48854                :{
48855                :    miBSGCPtr   pPriv = (miBSGCPtr) (pgcDst)->devPrivates[miBSGCIndex].ptr;
48856                :
48857                :    FUNC_PROLOGUE (pgcDst, pPriv);
48858                :
48859                :    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
48860                :
48861                :    FUNC_EPILOGUE (pgcDst, pPriv);
48862                :}
48863                :
48864                :static void
48865                :miBSDestroyClip(pGC)
48866                :    GCPtr       pGC;
48867                :{
48868                :    miBSGCPtr   pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
48869                :
48870                :    FUNC_PROLOGUE (pGC, pPriv);
48871                :
48872                :    (* pGC->funcs->DestroyClip)(pGC);
48873                :
48874                :    FUNC_EPILOGUE (pGC, pPriv);
48875                :}
48876                :
48877                :static void
48878                :miDestroyBSPixmap (pWin)
48879                :    WindowPtr   pWin;
48880                :{
48881                :    miBSWindowPtr       pBackingStore;
48882                :    ScreenPtr           pScreen;
48883                :    
48884                :    pScreen = pWin->drawable.pScreen;
48885                :    pBackingStore = (miBSWindowPtr) pWin->backStorage;
48886                :    if (pBackingStore->pBackingPixmap)
48887                :        (* pScreen->DestroyPixmap)(pBackingStore->pBackingPixmap);
48888                :    pBackingStore->pBackingPixmap = NullPixmap;
48889                :    pBackingStore->x = 0;
48890                :    pBackingStore->y = 0;
48891                :    if (pBackingStore->backgroundState == BackgroundPixmap)
48892                :        (* pScreen->DestroyPixmap)(pBackingStore->background.pixmap);
48893                :    pBackingStore->backgroundState = None;
48894                :    pBackingStore->status = StatusNoPixmap;
48895                :    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
48896                :}
48897                :
48898                :static void
48899                :miTileVirtualBS (pWin)
48900                :    WindowPtr   pWin;
48901                :{
48902                :    miBSWindowPtr       pBackingStore;
48903                :
48904                :    pBackingStore = (miBSWindowPtr) pWin->backStorage;
48905                :    if (pBackingStore->backgroundState == BackgroundPixmap)
48906                :        (* pWin->drawable.pScreen->DestroyPixmap)
48907                :            (pBackingStore->background.pixmap);
48908                :    pBackingStore->backgroundState = pWin->backgroundState;
48909                :    pBackingStore->background = pWin->background;
48910                :    if (pBackingStore->backgroundState == BackgroundPixmap)
48911                :        pBackingStore->background.pixmap->refcnt++;
48912                :
48913                :    if (pBackingStore->status != StatusVDirty)
48914                :        pBackingStore->status = StatusVirtual;
48915                :
48916                :    /*
48917                :     * punt parent relative tiles and do it now
48918                :     */
48919                :    if (pBackingStore->backgroundState == ParentRelative)
48920                :        miCreateBSPixmap (pWin, NullBox);
48921                :}
48922                :
48923                :#ifdef DEBUG
48924                :static int BSAllocationsFailed = 0;
48925                :#define FAILEDSIZE      32
48926                :static struct { int w, h; } failedRecord[FAILEDSIZE];
48927                :static int failedIndex;
48928                :#endif
48929                :
48930                :static void
48931                :miCreateBSPixmap (pWin, pExtents)
48932                :    WindowPtr   pWin;
48933                :    BoxPtr      pExtents;
48934                :{
48935                :    miBSWindowPtr       pBackingStore;
48936                :    ScreenPtr           pScreen;
48937                :    PixUnion            background;
48938                :    char                backgroundState = 0;
48939                :    BoxPtr              extents;
48940                :    Bool                backSet;
48941                :
48942                :    pScreen = pWin->drawable.pScreen;
48943                :    pBackingStore = (miBSWindowPtr) pWin->backStorage;
48944                :    if (pBackingStore->status == StatusBadAlloc)
48945                :        return;
48946                :    backSet = ((pBackingStore->status == StatusVirtual) ||
48947                :               (pBackingStore->status == StatusVDirty));
48948                :
48949                :    extents = REGION_EXTENTS( pScreen, &pBackingStore->SavedRegion);
48950                :
48951                :    if (!pBackingStore->pBackingPixmap &&
48952                :        extents->x2 != extents->x1 &&
48953                :        extents->y2 != extents->y1)
48954                :    {
48955                :        /* the policy here could be more sophisticated */
48956                :        pBackingStore->x = extents->x1;
48957                :        pBackingStore->y = extents->y1;
48958                :        pBackingStore->pBackingPixmap =
48959                :            (PixmapPtr)(* pScreen->CreatePixmap)
48960                :                           (pScreen,
48961                :                            extents->x2 - extents->x1,
48962                :                            extents->y2 - extents->y1,
48963                :                            pWin->drawable.depth);
48964                :    }
48965                :    if (!pBackingStore->pBackingPixmap)
48966                :    {
48967                :#ifdef DEBUG
48968                :        BSAllocationsFailed++;
48969                :        /*
48970                :         * record failed allocations
48971                :         */
48972                :        failedRecord[failedIndex].w = pWin->drawable.width;
48973                :        failedRecord[failedIndex].h = pWin->drawable.height;
48974                :        failedIndex++;
48975                :        if (failedIndex == FAILEDSIZE)
48976                :                failedIndex = 0;
48977                :#endif
48978                :#ifdef BSEAGER
48979                :        pBackingStore->status = StatusNoPixmap;
48980                :#else
48981                :        pBackingStore->status = StatusBadAlloc;
48982                :#endif
48983                :        return;
48984                :    }
48985                :
48986                :    pBackingStore->status = StatusContents;
48987                :
48988                :    if (backSet)
48989                :    {
48990                :        backgroundState = pWin->backgroundState;
48991                :        background = pWin->background;
48992                :    
48993                :        pWin->backgroundState = pBackingStore->backgroundState;
48994                :        pWin->background = pBackingStore->background;
48995                :        if (pWin->backgroundState == BackgroundPixmap)
48996                :            pWin->background.pixmap->refcnt++;
48997                :    }
48998                :
48999                :    if (!pExtents)
49000                :        pExtents = extents;
49001                :
49002                :    if (pExtents->y1 != pExtents->y2)
49003                :    {
49004                :        RegionPtr exposed;
49005                :
49006                :        exposed = miBSClearBackingStore(pWin,
49007                :                              pExtents->x1, pExtents->y1,
49008                :                              pExtents->x2 - pExtents->x1,
49009                :                              pExtents->y2 - pExtents->y1,
49010                :                              !backSet);
49011                :        if (exposed)
49012                :        {
49013                :            miSendExposures(pWin, exposed, pWin->drawable.x, pWin->drawable.y);
49014                :            REGION_DESTROY( pScreen, exposed);
49015                :        }
49016                :    }
49017                :
49018                :    if (backSet)
49019                :    {
49020                :        if (pWin->backgroundState == BackgroundPixmap)
49021                :            (* pScreen->DestroyPixmap) (pWin->background.pixmap);
49022                :        pWin->backgroundState = backgroundState;
49023                :        pWin->background = background;
49024                :        if (pBackingStore->backgroundState == BackgroundPixmap)
49025                :            (* pScreen->DestroyPixmap) (pBackingStore->background.pixmap);
49026                :        pBackingStore->backgroundState = None;
49027                :    }
49028                :}
49029                :
49030                :/*-
49031                : *-----------------------------------------------------------------------
49032                : * miBSExposeCopy --
49033                : *      Handle the restoration of areas exposed by graphics operations.
49034                : *
49035                : * Results:
49036                : *      None.
49037                : *
49038                : * Side Effects:
49039                : *      prgnExposed has the areas exposed from backing-store removed
49040                : *      from it.
49041                : *
49042                : *-----------------------------------------------------------------------
49043                : */
49044                :static void
49045                :miBSExposeCopy (pSrc, pDst, pGC, prgnExposed, srcx, srcy, dstx, dsty, plane)
49046                :    WindowPtr           pSrc;
49047                :    DrawablePtr         pDst;
49048                :    GCPtr               pGC;
49049                :    RegionPtr           prgnExposed;
49050                :    int                 srcx, srcy;
49051                :    int                 dstx, dsty;
49052                :    unsigned long       plane;
49053                :{
49054                :    RegionRec           tempRgn;
49055                :    miBSWindowPtr       pBackingStore;
49056                :    CopyPlaneProcPtr    copyProc;
49057                :    GCPtr               pScratchGC;
49058                :    BoxPtr              pBox;
49059                :    int                 i;
49060                :    int                 dx, dy;
49061                :    BITS32              gcMask;
49062                :
49063                :    if (!REGION_NOTEMPTY(pGC->pScreen, prgnExposed))
49064                :        return;
49065                :    pBackingStore = (miBSWindowPtr)pSrc->backStorage;
49066                :    
49067                :    if ((pBackingStore->status == StatusNoPixmap) ||
49068                :        (pBackingStore->status == StatusBadAlloc))
49069                :        return;
49070                :
49071                :    REGION_NULL( pGC->pScreen, &tempRgn);
49072                :    REGION_INTERSECT( pGC->pScreen, &tempRgn, prgnExposed,
49073                :                                 &pBackingStore->SavedRegion);
49074                :    REGION_SUBTRACT( pGC->pScreen, prgnExposed, prgnExposed, &tempRgn);
49075                :
49076                :    if (plane != 0) {
49077                :        copyProc = pGC->ops->CopyPlane;
49078                :    } else {
49079                :        copyProc = (CopyPlaneProcPtr)pGC->ops->CopyArea;
49080                :    }
49081                :    
49082                :    dx = dstx - srcx;
49083                :    dy = dsty - srcy;
49084                :    
49085                :    switch (pBackingStore->status) {
49086                :    case StatusVirtual:
49087                :    case StatusVDirty:
49088                :        pScratchGC = GetScratchGC (pDst->depth, pDst->pScreen);
49089                :        if (pScratchGC)
49090                :        {
49091                :            gcMask = 0;
49092                :            if (pGC->alu != pScratchGC->alu)
49093                :                gcMask = GCFunction;
49094                :            if (pGC->planemask != pScratchGC->planemask)
49095                :                gcMask |= GCPlaneMask;
49096                :            if (gcMask)
49097                :                CopyGC (pGC, pScratchGC, gcMask);
49098                :            miBSFillVirtualBits (pDst, pScratchGC, &tempRgn, dx, dy,
49099                :                                 (int) pBackingStore->backgroundState,
49100                :                                 pBackingStore->background,
49101                :                                 ~0L);
49102                :            FreeScratchGC (pScratchGC);
49103                :        }
49104                :        break;
49105                :    case StatusContents:
49106                :        for (i = REGION_NUM_RECTS(&tempRgn), pBox = REGION_RECTS(&tempRgn);
49107                :             --i >= 0;
49108                :             pBox++)
49109                :        {
49110                :            (* copyProc) (&(pBackingStore->pBackingPixmap->drawable), pDst, pGC,
49111                :                          pBox->x1 - pBackingStore->x,
49112                :                          pBox->y1 - pBackingStore->y,
49113                :                          pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
49114                :                          pBox->x1 + dx, pBox->y1 + dy, plane);
49115                :        }
49116                :        break;
49117                :    }
49118                :    REGION_UNINIT( pGC->pScreen, &tempRgn);
49119                :}
49120 /* 
49121  * Total samples for file : "/home/cworth/src/xorg/xserver/dix/devices.c"
49122  * 
49123  *      9  0.0098
49124  */
49125
49126
49127                :/************************************************************
49128                :
49129                :Copyright 1987, 1998  The Open Group
49130                :
49131                :Permission to use, copy, modify, distribute, and sell this software and its
49132                :documentation for any purpose is hereby granted without fee, provided that
49133                :the above copyright notice appear in all copies and that both that
49134                :copyright notice and this permission notice appear in supporting
49135                :documentation.
49136                :
49137                :The above copyright notice and this permission notice shall be included in
49138                :all copies or substantial portions of the Software.
49139                :
49140                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
49141                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49142                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
49143                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
49144                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
49145                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49146                :
49147                :Except as contained in this notice, the name of The Open Group shall not be
49148                :used in advertising or otherwise to promote the sale, use or other dealings
49149                :in this Software without prior written authorization from The Open Group.
49150                :
49151                :
49152                :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
49153                :
49154                :                        All Rights Reserved
49155                :
49156                :Permission to use, copy, modify, and distribute this software and its 
49157                :documentation for any purpose and without fee is hereby granted, 
49158                :provided that the above copyright notice appear in all copies and that
49159                :both that copyright notice and this permission notice appear in 
49160                :supporting documentation, and that the name of Digital not be
49161                :used in advertising or publicity pertaining to distribution of the
49162                :software without specific, written prior permission.  
49163                :
49164                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
49165                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49166                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
49167                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
49168                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
49169                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49170                :SOFTWARE.
49171                :
49172                :********************************************************/
49173                :
49174                :
49175                :
49176                :#ifdef HAVE_DIX_CONFIG_H
49177                :#include <dix-config.h>
49178                :#endif
49179                :
49180                :#include <X11/X.h>
49181                :#include "misc.h"
49182                :#include "resource.h"
49183                :#define NEED_EVENTS
49184                :#define NEED_REPLIES
49185                :#include <X11/Xproto.h>
49186                :#include "windowstr.h"
49187                :#include "inputstr.h"
49188                :#include "scrnintstr.h"
49189                :#include "cursorstr.h"
49190                :#include "dixstruct.h"
49191                :#include "site.h"
49192                :#ifndef XKB_IN_SERVER
49193                :#define XKB_IN_SERVER
49194                :#endif
49195                :#ifdef XKB
49196                :#include <xkbsrv.h>
49197                :#endif
49198                :#include "xace.h"
49199                :
49200                :#include "dispatch.h"
49201                :#include "swaprep.h"
49202                :#include "dixevents.h"
49203                :
49204                :#include <X11/extensions/XI.h>
49205                :#include <X11/extensions/XIproto.h>
49206                :#include "exglobals.h"
49207                :#include "exevents.h"
49208                :
49209                :/** @file
49210                : * This file handles input device-related stuff.
49211                : */
49212                :
49213                :int CoreDevicePrivatesIndex = 0;
49214                :static int CoreDevicePrivatesGeneration = -1;
49215                :
49216                :/**
49217                : * Create a new input device and init it to sane values. The device is added
49218                : * to the server's off_devices list.
49219                : *
49220                : * @param deviceProc Callback for device control function (switch dev on/off).
49221                : * @return The newly created device.
49222                : */
49223                :DeviceIntPtr
49224                :AddInputDevice(DeviceProc deviceProc, Bool autoStart)
49225                :{
49226                :    DeviceIntPtr dev, *prev; /* not a typo */
49227                :    DeviceIntPtr devtmp;
49228                :    int devid;
49229                :    char devind[MAX_DEVICES];
49230                :
49231                :    /* Find next available id */
49232                :    memset(devind, 0, sizeof(char)*MAX_DEVICES);
49233                :    for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next)
49234                :        devind[devtmp->id]++;
49235                :    for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next)
49236                :        devind[devtmp->id]++;
49237                :    for (devid = 0; devid < MAX_DEVICES && devind[devid]; devid++)
49238                :        ;
49239                :
49240                :    if (devid >= MAX_DEVICES)
49241                :        return (DeviceIntPtr)NULL;
49242                :    dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec), 1);
49243                :    if (!dev)
49244                :        return (DeviceIntPtr)NULL;
49245                :    dev->name = (char *)NULL;
49246                :    dev->type = 0;
49247                :    dev->id = devid;
49248                :    inputInfo.numDevices++;
49249                :    dev->public.on = FALSE;
49250                :    dev->public.processInputProc = (ProcessInputProc)NoopDDA;
49251                :    dev->public.realInputProc = (ProcessInputProc)NoopDDA;
49252                :    dev->public.enqueueInputProc = EnqueueEvent;
49253                :    dev->deviceProc = deviceProc;
49254                :    dev->startup = autoStart;
49255                :    dev->sync.frozen = FALSE;
49256                :    dev->sync.other = NullGrab;
49257                :    dev->sync.state = NOT_GRABBED;
49258                :    dev->sync.event = (xEvent *) NULL;
49259                :    dev->sync.evcount = 0;
49260                :    dev->grab = NullGrab;
49261                :    dev->grabTime = currentTime;
49262                :    dev->fromPassiveGrab = FALSE;
49263                :    dev->key = (KeyClassPtr)NULL;
49264                :    dev->valuator = (ValuatorClassPtr)NULL;
49265                :    dev->button = (ButtonClassPtr)NULL;
49266                :    dev->focus = (FocusClassPtr)NULL;
49267                :    dev->proximity = (ProximityClassPtr)NULL;
49268                :    dev->absolute = (AbsoluteClassPtr)NULL;
49269                :    dev->kbdfeed = (KbdFeedbackPtr)NULL;
49270                :    dev->ptrfeed = (PtrFeedbackPtr)NULL;
49271                :    dev->intfeed = (IntegerFeedbackPtr)NULL;
49272                :    dev->stringfeed = (StringFeedbackPtr)NULL;
49273                :    dev->bell = (BellFeedbackPtr)NULL;
49274                :    dev->leds = (LedFeedbackPtr)NULL;
49275                :#ifdef XKB
49276                :    dev->xkb_interest = NULL;
49277                :#endif
49278                :    dev->nPrivates = 0;
49279                :    dev->devPrivates = NULL;
49280                :    dev->unwrapProc = NULL;
49281                :    dev->coreEvents = TRUE;
49282                :    dev->inited = FALSE;
49283                :    dev->enabled = FALSE;
49284                :
49285                :    for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next)
49286                :        ;
49287                :    *prev = dev;
49288                :    dev->next = NULL;
49289                :
49290                :    return dev;
49291                :}
49292                :
49293                :/**
49294                : * Switch device ON through the driver and push it onto the global device
49295                : * list. All clients are notified about the device being enabled.
49296                : *
49297                : * A device will send events once enabled.
49298                : *
49299                : * @param The device to be enabled.
49300                : * @return TRUE on success or FALSE otherwise.
49301                : */
49302                :Bool
49303                :EnableDevice(DeviceIntPtr dev)
49304                :{
49305                :    DeviceIntPtr *prev;
49306                :    int ret;
49307                :    DeviceIntRec dummyDev;
49308                :    devicePresenceNotify ev;
49309                :
49310                :    for (prev = &inputInfo.off_devices;
49311                :         *prev && (*prev != dev);
49312                :         prev = &(*prev)->next)
49313                :        ;
49314                :    if ((*prev != dev) || !dev->inited ||
49315                :        ((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
49316                :        ErrorF("couldn't enable device %d\n", dev->id);
49317                :        return FALSE;
49318                :    }
49319                :    dev->enabled = TRUE;
49320                :    *prev = dev->next;
49321                :
49322                :    for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next)
49323                :        ;
49324                :    *prev = dev;
49325                :    dev->next = NULL;
49326                :
49327                :    ev.type = DevicePresenceNotify;
49328                :    ev.time = currentTime.milliseconds;
49329                :    ev.devchange = DeviceEnabled;
49330                :    ev.deviceid = dev->id;
49331                :    dummyDev.id = 0;
49332                :    SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
49333                :                          (xEvent *) &ev, 1);
49334                :
49335                :    return TRUE;
49336                :}
49337                :
49338                :/**
49339                : * Switch a device off through the driver and push it onto the off_devices
49340                : * list. A device will not send events while disabled. All clients are
49341                : * notified about the device being disabled.
49342                : *
49343                : * @return TRUE on success or FALSE otherwise.
49344                : */
49345                :Bool
49346                :DisableDevice(DeviceIntPtr dev)
49347                :{
49348                :    DeviceIntPtr *prev;
49349                :    DeviceIntRec dummyDev;
49350                :    devicePresenceNotify ev;
49351                :
49352                :    for (prev = &inputInfo.devices;
49353                :         *prev && (*prev != dev);
49354                :         prev = &(*prev)->next)
49355                :        ;
49356                :    if (*prev != dev)
49357                :        return FALSE;
49358                :    (void)(*dev->deviceProc)(dev, DEVICE_OFF);
49359                :    dev->enabled = FALSE;
49360                :    *prev = dev->next;
49361                :    dev->next = inputInfo.off_devices;
49362                :    inputInfo.off_devices = dev;
49363                :
49364                :    ev.type = DevicePresenceNotify;
49365                :    ev.time = currentTime.milliseconds;
49366                :    ev.devchange = DeviceDisabled;
49367                :    ev.deviceid = dev->id;
49368                :    dummyDev.id = 0;
49369                :    SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
49370                :                          (xEvent *) &ev, 1);
49371                :
49372                :    return TRUE;
49373                :}
49374                :
49375                :/**
49376                : * Initialise a new device through the driver and tell all clients about the
49377                : * new device.
49378                : * 
49379                : * The device will NOT send events until it is enabled!
49380                : *
49381                : * @return Success or an error code on failure.
49382                : */
49383                :int
49384                :ActivateDevice(DeviceIntPtr dev)
49385                :{
49386                :    int ret = Success;
49387                :    devicePresenceNotify ev;
49388                :    DeviceIntRec dummyDev;
49389                :
49390                :    if (!dev || !dev->deviceProc)
49391                :        return BadImplementation;
49392                :
49393                :    ret = (*dev->deviceProc) (dev, DEVICE_INIT);
49394                :    dev->inited = (ret == Success);
49395                :    
49396                :    ev.type = DevicePresenceNotify;
49397                :    ev.time = currentTime.milliseconds;
49398                :    ev.devchange = DeviceAdded;
49399                :    ev.deviceid = dev->id;
49400                :    dummyDev.id = 0;
49401                :    SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
49402                :                          (xEvent *) &ev, 1);
49403                :
49404                :    return ret;
49405                :}
49406                :
49407                :/**
49408                : * Ring the bell.
49409                : * The actual task of ringing the bell is the job of the DDX.
49410                : */
49411                :static void
49412                :CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
49413                :{
49414                :    KeybdCtrl *ctrl = arg;
49415                :
49416                :    DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration);
49417                :}
49418                :
49419                :static void
49420                :CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
49421                :{
49422                :    return;
49423                :}
49424                :
49425                :/**
49426                : * Device control function for the Virtual Core Keyboard. 
49427                : */
49428                :static int
49429                :CoreKeyboardProc(DeviceIntPtr pDev, int what)
49430                :{
49431                :    CARD8 *modMap;
49432                :    KeySymsRec keySyms;
49433                :#ifdef XKB
49434                :    XkbComponentNamesRec names;
49435                :#endif
49436                :
49437                :    switch (what) {
49438                :    case DEVICE_INIT:
49439                :        keySyms.minKeyCode = 8;
49440                :        keySyms.maxKeyCode = 255;
49441                :        keySyms.mapWidth = 4;
49442                :        keySyms.map = (KeySym *)xcalloc(sizeof(KeySym),
49443                :                                        (keySyms.maxKeyCode -
49444                :                                         keySyms.minKeyCode + 1) *
49445                :                                        keySyms.mapWidth);
49446                :        if (!keySyms.map) {
49447                :            ErrorF("Couldn't allocate core keymap\n");
49448                :            return BadAlloc;
49449                :        }
49450                :
49451                :        modMap = (CARD8 *)xalloc(MAP_LENGTH);
49452                :        if (!modMap) {
49453                :            ErrorF("Couldn't allocate core modifier map\n");
49454                :            return BadAlloc;
49455                :        }
49456                :        bzero((char *)modMap, MAP_LENGTH);
49457                :
49458                :#ifdef XKB
49459                :        if (!noXkbExtension) {
49460                :            bzero(&names, sizeof(names));
49461                :            XkbSetRulesDflts("base", "pc105", "us", NULL, NULL);
49462                :            XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, modMap,
49463                :                                        CoreKeyboardBell, CoreKeyboardCtl);
49464                :        }
49465                :        else
49466                :#endif
49467                :        {
49468                :            /* FIXME Our keymap here isn't exactly useful. */
49469                :            InitKeyboardDeviceStruct((DevicePtr)pDev, &keySyms, modMap,
49470                :                                     CoreKeyboardBell, CoreKeyboardCtl);
49471                :        }
49472                :
49473                :        xfree(keySyms.map);
49474                :        xfree(modMap);
49475                :
49476                :        break;
49477                :
49478                :    case DEVICE_CLOSE:
49479                :        pDev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
49480                :        break;
49481                :
49482                :    default:
49483                :        break;
49484                :    }
49485                :    return Success;
49486                :}
49487                :
49488                :/**
49489                : * Device control function for the Virtual Core Pointer.
49490                : */
49491                :static int
49492                :CorePointerProc(DeviceIntPtr pDev, int what)
49493                :{
49494                :    BYTE map[33];
49495                :    int i = 0;
49496                :
49497                :    switch (what) {
49498                :    case DEVICE_INIT:
49499                :        for (i = 1; i <= 32; i++)
49500                :            map[i] = i;
49501                :        InitPointerDeviceStruct((DevicePtr)pDev, map, 32,
49502                :                                GetMotionHistory, (PtrCtrlProcPtr)NoopDDA,
49503                :                                GetMotionHistorySize(), 2);
49504                :        pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
49505                :        pDev->valuator->lastx = pDev->valuator->axisVal[0];
49506                :        pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
49507                :        pDev->valuator->lasty = pDev->valuator->axisVal[1];
49508                :        break;
49509                :
49510                :    case DEVICE_CLOSE:
49511                :        pDev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
49512                :        break;
49513                :
49514                :    default:
49515                :        break;
49516                :    }
49517                :
49518                :    return Success;
49519                :}
49520                :
49521                :/**
49522                : * Initialise the two core devices, VCP and VCK (see events.c).
49523                : * The devices are activated but not enabled.
49524                : * Note that the server MUST have two core devices at all times, even if there
49525                : * is no physical device connected.
49526                : */
49527                :void
49528                :InitCoreDevices(void)
49529                :{
49530                :    DeviceIntPtr dev;
49531                :
49532                :    if (CoreDevicePrivatesGeneration != serverGeneration) {
49533                :        CoreDevicePrivatesIndex = AllocateDevicePrivateIndex();
49534                :        CoreDevicePrivatesGeneration = serverGeneration;
49535                :    }
49536                :
49537                :    if (!inputInfo.keyboard) {
49538                :        dev = AddInputDevice(CoreKeyboardProc, TRUE);
49539                :        if (!dev)
49540                :            FatalError("Failed to allocate core keyboard");
49541                :        dev->name = strdup("Virtual core keyboard");
49542                :#ifdef XKB
49543                :        dev->public.processInputProc = CoreProcessKeyboardEvent;
49544                :        dev->public.realInputProc = CoreProcessKeyboardEvent;
49545                :        if (!noXkbExtension)
49546                :           XkbSetExtension(dev, ProcessKeyboardEvent);
49547                :#else
49548                :        dev->public.processInputProc = ProcessKeyboardEvent;
49549                :        dev->public.realInputProc = ProcessKeyboardEvent;
49550                :#endif
49551                :        dev->ActivateGrab = ActivateKeyboardGrab;
49552                :        dev->DeactivateGrab = DeactivateKeyboardGrab;
49553                :        dev->coreEvents = FALSE;
49554                :        if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
49555                :            FatalError("Couldn't allocate keyboard devPrivates\n");
49556                :        dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
49557                :        (void)ActivateDevice(dev);
49558                :        inputInfo.keyboard = dev;
49559                :    }
49560                :
49561                :    if (!inputInfo.pointer) {
49562                :        dev = AddInputDevice(CorePointerProc, TRUE);
49563                :        if (!dev)
49564                :            FatalError("Failed to allocate core pointer");
49565                :        dev->name = strdup("Virtual core pointer");
49566                :#ifdef XKB
49567                :        dev->public.processInputProc = CoreProcessPointerEvent;
49568                :        dev->public.realInputProc = CoreProcessPointerEvent;
49569                :        if (!noXkbExtension)
49570                :           XkbSetExtension(dev, ProcessPointerEvent);
49571                :#else
49572                :        dev->public.processInputProc = ProcessPointerEvent;
49573                :        dev->public.realInputProc = ProcessPointerEvent;
49574                :#endif
49575                :        dev->ActivateGrab = ActivatePointerGrab;
49576                :        dev->DeactivateGrab = DeactivatePointerGrab;
49577                :        dev->coreEvents = FALSE;
49578                :        if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
49579                :            FatalError("Couldn't allocate pointer devPrivates\n");
49580                :        dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
49581                :        (void)ActivateDevice(dev);
49582                :        inputInfo.pointer = dev;
49583                :    }
49584                :}
49585                :
49586                :/**
49587                : * Activate all switched-off devices and then enable all those devices.
49588                : * 
49589                : * Will return an error if no core keyboard or core pointer is present.
49590                : * In theory this should never happen if you call InitCoreDevices() first.
49591                : * 
49592                : * @return Success or error code on failure.
49593                : */
49594                :int
49595                :InitAndStartDevices(void)
49596                :{
49597                :    DeviceIntPtr dev, next;
49598                :
49599                :    for (dev = inputInfo.off_devices; dev; dev = dev->next) {
49600                :        DebugF("(dix) initialising device %d\n", dev->id);
49601                :        ActivateDevice(dev);
49602                :    }
49603                :    for (dev = inputInfo.off_devices; dev; dev = next)
49604                :    {
49605                :        DebugF("(dix) enabling device %d\n", dev->id);
49606                :        next = dev->next;
49607                :        if (dev->inited && dev->startup)
49608                :            (void)EnableDevice(dev);
49609                :    }
49610                :    for (dev = inputInfo.devices;
49611                :         dev && (dev != inputInfo.keyboard);
49612                :         dev = dev->next)
49613                :        ;
49614                :    if (!dev || (dev != inputInfo.keyboard)) {
49615                :        ErrorF("No core keyboard\n");
49616                :        return BadImplementation;
49617                :    }
49618                :    for (dev = inputInfo.devices;
49619                :         dev && (dev != inputInfo.pointer);
49620                :         dev = dev->next)
49621                :        ;
49622                :    if (!dev || (dev != inputInfo.pointer)) {
49623                :        ErrorF("No core pointer\n");
49624                :        return BadImplementation;
49625                :    }
49626                :    return Success;
49627                :}
49628                :
49629                :/**
49630                : * Close down a device and free all resources. 
49631                : * Once closed down, the driver will probably not expect you that you'll ever
49632                : * enable it again and free associated structs. If you want the device to just
49633                : * be disabled, DisableDevice().
49634                : * Don't call this function directly, use RemoveDevice() instead.
49635                : */
49636                :static void
49637                :CloseDevice(DeviceIntPtr dev)
49638                :{
49639                :    KbdFeedbackPtr k, knext;
49640                :    PtrFeedbackPtr p, pnext;
49641                :    IntegerFeedbackPtr i, inext;
49642                :    StringFeedbackPtr s, snext;
49643                :    BellFeedbackPtr b, bnext;
49644                :    LedFeedbackPtr l, lnext;
49645                :
49646                :    if (dev->inited)
49647                :        (void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
49648                :
49649                :    xfree(dev->name);
49650                :
49651                :    if (dev->key) {
49652                :#ifdef XKB
49653                :        if (dev->key->xkbInfo)
49654                :            XkbFreeInfo(dev->key->xkbInfo);
49655                :#endif
49656                :        xfree(dev->key->curKeySyms.map);
49657                :        xfree(dev->key->modifierKeyMap);
49658                :        xfree(dev->key);
49659                :    }
49660                :
49661                :    if (dev->valuator) {
49662                :        /* Counterpart to 'biggest hack ever' in init. */
49663                :        if (dev->valuator->motion &&
49664                :            dev->valuator->GetMotionProc == GetMotionHistory)
49665                :            xfree(dev->valuator->motion);
49666                :        xfree(dev->valuator);
49667                :    }
49668                :
49669                :    if (dev->button) {
49670                :#ifdef XKB
49671                :        if (dev->button->xkb_acts)
49672                :            xfree(dev->button->xkb_acts);
49673                :#endif
49674                :        xfree(dev->button);
49675                :    }
49676                :
49677                :    if (dev->focus) {
49678                :        xfree(dev->focus->trace);
49679                :        xfree(dev->focus);
49680                :    }
49681                :
49682                :    if (dev->proximity)
49683                :        xfree(dev->proximity);
49684                :
49685                :    for (k = dev->kbdfeed; k; k = knext) {
49686                :        knext = k->next;
49687                :#ifdef XKB
49688                :        if (k->xkb_sli)
49689                :            XkbFreeSrvLedInfo(k->xkb_sli);
49690                :#endif
49691                :        xfree(k);
49692                :    }
49693                :
49694                :    for (p = dev->ptrfeed; p; p = pnext) {
49695                :        pnext = p->next;
49696                :        xfree(p);
49697                :    }
49698                :    
49699                :    for (i = dev->intfeed; i; i = inext) {
49700                :        inext = i->next;
49701                :        xfree(i);
49702                :    }
49703                :
49704                :    for (s = dev->stringfeed; s; s = snext) {
49705                :        snext = s->next;
49706                :        xfree(s->ctrl.symbols_supported);
49707                :        xfree(s->ctrl.symbols_displayed);
49708                :        xfree(s);
49709                :    }
49710                :
49711                :    for (b = dev->bell; b; b = bnext) {
49712                :        bnext = b->next;
49713                :        xfree(b);
49714                :    }
49715                :
49716                :    for (l = dev->leds; l; l = lnext) {
49717                :        lnext = l->next;
49718                :#ifdef XKB
49719                :        if (l->xkb_sli)
49720                :            XkbFreeSrvLedInfo(l->xkb_sli);
49721                :#endif
49722                :        xfree(l);
49723                :    }
49724                :
49725                :#ifdef XKB
49726                :    while (dev->xkb_interest)
49727                :        XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
49728                :#endif
49729                :
49730                :    if (dev->devPrivates)
49731                :        xfree(dev->devPrivates);
49732                :
49733                :    xfree(dev->sync.event);
49734                :    xfree(dev);
49735                :}
49736                :
49737                :/**
49738                : * Shut down all devices, free all resources, etc. 
49739                : * Only useful if you're shutting down the server!
49740                : */
49741                :void
49742                :CloseDownDevices(void)
49743                :{
49744                :    DeviceIntPtr dev, next;
49745                :
49746                :    for (dev = inputInfo.devices; dev; dev = next)
49747                :    {
49748                :        next = dev->next;
49749                :        CloseDevice(dev);
49750                :    }
49751                :    for (dev = inputInfo.off_devices; dev; dev = next)
49752                :    {
49753                :        next = dev->next;
49754                :        CloseDevice(dev);
49755                :    }
49756                :    inputInfo.devices = NULL;
49757                :    inputInfo.off_devices = NULL;
49758                :    inputInfo.keyboard = NULL;
49759                :    inputInfo.pointer = NULL;
49760                :}
49761                :
49762                :/**
49763                : * Remove a device from the device list, closes it and thus frees all
49764                : * resources. 
49765                : * Removes both enabled and disabled devices and notifies all devices about
49766                : * the removal of the device.
49767                : */
49768                :int
49769                :RemoveDevice(DeviceIntPtr dev)
49770                :{
49771                :    DeviceIntPtr prev,tmp,next;
49772                :    int ret = BadMatch;
49773                :    devicePresenceNotify ev;
49774                :    DeviceIntRec dummyDev;
49775                :    int deviceid;
49776                :
49777                :    DebugF("(dix) removing device %d\n", dev->id);
49778                :
49779                :    if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
49780                :        return BadImplementation;
49781                :
49782                :    deviceid = dev->id;
49783                :    DisableDevice(dev);
49784                :
49785                :    prev = NULL;
49786                :    for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
49787                :        next = tmp->next;
49788                :        if (tmp == dev) {
49789                :            CloseDevice(tmp);
49790                :
49791                :            if (prev==NULL)
49792                :                inputInfo.devices = next;
49793                :            else
49794                :                prev->next = next;
49795                :
49796                :            ret = Success;
49797                :        }
49798                :    }
49799                :
49800                :    prev = NULL;
49801                :    for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) {
49802                :        next = tmp->next;
49803                :        if (tmp == dev) {
49804                :            CloseDevice(tmp);
49805                :
49806                :            if (prev == NULL)
49807                :                inputInfo.off_devices = next;
49808                :            else
49809                :                prev->next = next;
49810                :
49811                :            ret = Success;
49812                :        }
49813                :    }
49814                :    
49815                :    if (ret == Success) {
49816                :        inputInfo.numDevices--;
49817                :        ev.type = DevicePresenceNotify;
49818                :        ev.time = currentTime.milliseconds;
49819                :        ev.devchange = DeviceRemoved;
49820                :        ev.deviceid = deviceid;
49821                :        dummyDev.id = 0;
49822                :        SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
49823                :                              (xEvent *) &ev, 1);
49824                :    }
49825                :
49826                :    return ret;
49827                :}
49828                :
49829                :int
49830                :NumMotionEvents(void)
49831                :{
49832                :    return inputInfo.pointer->valuator->numMotionEvents;
49833                :}
49834                :
49835                :void
49836                :RegisterPointerDevice(DeviceIntPtr device)
49837                :{
49838                :    RegisterOtherDevice(device);
49839                :}
49840                :
49841                :void
49842                :RegisterKeyboardDevice(DeviceIntPtr device)
49843                :{
49844                :    RegisterOtherDevice(device);
49845                :}
49846                :
49847                :_X_EXPORT DevicePtr
49848                :LookupKeyboardDevice(void)
49849                :{
49850                :    return inputInfo.keyboard ? &inputInfo.keyboard->public : NULL;
49851                :}
49852                :
49853                :_X_EXPORT DevicePtr
49854                :LookupPointerDevice(void)
49855                :{
49856                :    return inputInfo.pointer ? &inputInfo.pointer->public : NULL;
49857                :}
49858                :
49859                :DevicePtr
49860                :LookupDevice(int id)
49861                :{
49862                :    DeviceIntPtr dev;
49863                :
49864                :    for (dev=inputInfo.devices; dev; dev=dev->next) {
49865                :        if (dev->id == (CARD8)id)
49866                :            return (DevicePtr)dev;
49867                :    }
49868                :    for (dev=inputInfo.off_devices; dev; dev=dev->next) {
49869                :        if (dev->id == (CARD8)id)
49870                :            return (DevicePtr)dev;
49871                :    }
49872                :    return NULL;
49873                :}
49874                :
49875                :void
49876                :QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode)
49877                :{
49878                :    if (inputInfo.keyboard) {
49879                :        *minCode = inputInfo.keyboard->key->curKeySyms.minKeyCode;
49880                :        *maxCode = inputInfo.keyboard->key->curKeySyms.maxKeyCode;
49881                :    }
49882                :}
49883                :
49884                :Bool
49885                :SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
49886                :{
49887                :    int i, j;
49888                :    int rowDif = src->minKeyCode - dst->minKeyCode;
49889                :
49890                :    /* if keysym map size changes, grow map first */
49891                :    if (src->mapWidth < dst->mapWidth)
49892                :    {
49893                :        for (i = src->minKeyCode; i <= src->maxKeyCode; i++)
49894                :        {
49895                :#define SI(r, c) (((r-src->minKeyCode)*src->mapWidth) + (c))
49896                :#define DI(r, c) (((r - dst->minKeyCode)*dst->mapWidth) + (c))
49897                :            for (j = 0; j < src->mapWidth; j++)
49898                :                dst->map[DI(i, j)] = src->map[SI(i, j)];
49899                :            for (j = src->mapWidth; j < dst->mapWidth; j++)
49900                :                dst->map[DI(i, j)] = NoSymbol;
49901                :#undef SI
49902                :#undef DI
49903                :        }
49904                :        return TRUE;
49905                :    }
49906                :    else if (src->mapWidth > dst->mapWidth)
49907                :    {
49908                :        KeySym *map;
49909                :        int bytes = sizeof(KeySym) * src->mapWidth *
49910                :                    (dst->maxKeyCode - dst->minKeyCode + 1);
49911                :        map = (KeySym *)xalloc(bytes);
49912                :        if (!map)
49913                :            return FALSE;
49914                :        bzero((char *)map, bytes);
49915                :        if (dst->map)
49916                :        {
49917                :            for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++)
49918                :                memmove((char *)&map[i*src->mapWidth],
49919                :                        (char *)&dst->map[i*dst->mapWidth],
49920                :                      dst->mapWidth * sizeof(KeySym));
49921                :            xfree(dst->map);
49922                :        }
49923                :        dst->mapWidth = src->mapWidth;
49924                :        dst->map = map;
49925                :    }
49926                :    memmove((char *)&dst->map[rowDif * dst->mapWidth],
49927                :            (char *)src->map,
49928                :          (int)(src->maxKeyCode - src->minKeyCode + 1) *
49929                :          dst->mapWidth * sizeof(KeySym));
49930                :    return TRUE;
49931                :}
49932                :
49933                :static Bool
49934                :InitModMap(KeyClassPtr keyc)
49935                :{
49936                :    int i, j;
49937                :    CARD8 keysPerModifier[8];
49938                :    CARD8 mask;
49939                :
49940                :    keyc->maxKeysPerModifier = 0;
49941                :    for (i = 0; i < 8; i++)
49942                :        keysPerModifier[i] = 0;
49943                :    for (i = 8; i < MAP_LENGTH; i++)
49944                :    {
49945                :        for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
49946                :        {
49947                :            if (mask & keyc->modifierMap[i])
49948                :            {
49949                :                if (++keysPerModifier[j] > keyc->maxKeysPerModifier)
49950                :                    keyc->maxKeysPerModifier = keysPerModifier[j];
49951                :            }
49952                :        }
49953                :    }
49954                :    keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier);
49955                :    if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier)
49956                :        return (FALSE);
49957                :    bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier);
49958                :    for (i = 0; i < 8; i++)
49959                :        keysPerModifier[i] = 0;
49960                :    for (i = 8; i < MAP_LENGTH; i++)
49961                :    {
49962                :        for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
49963                :        {
49964                :            if (mask & keyc->modifierMap[i])
49965                :            {
49966                :                keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) +
49967                :                                     keysPerModifier[j]] = i;
49968                :                keysPerModifier[j]++;
49969                :            }
49970                :        }
49971                :    }
49972                :    return TRUE;
49973                :}
49974                :
49975                :_X_EXPORT Bool
49976                :InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers[])
49977                :{
49978                :    int i;
49979                :    KeyClassPtr keyc;
49980                :    
49981                :    keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec));
49982                :    if (!keyc)
49983                :        return FALSE;
49984                :    keyc->curKeySyms.map = (KeySym *)NULL;
49985                :    keyc->curKeySyms.mapWidth = 0;
49986                :    keyc->curKeySyms.minKeyCode = pKeySyms->minKeyCode;
49987                :    keyc->curKeySyms.maxKeyCode = pKeySyms->maxKeyCode;
49988                :    keyc->modifierKeyMap = (KeyCode *)NULL;
49989                :    keyc->state = 0;
49990                :    keyc->prev_state = 0;
49991                :    if (pModifiers)
49992                :        memmove((char *)keyc->modifierMap, (char *)pModifiers, MAP_LENGTH);
49993                :    else
49994                :        bzero((char *)keyc->modifierMap, MAP_LENGTH);
49995                :    bzero((char *)keyc->down, DOWN_LENGTH);
49996                :    for (i = 0; i < 8; i++)
49997                :        keyc->modifierKeyCount[i] = 0;
49998                :    if (!SetKeySymsMap(&keyc->curKeySyms, pKeySyms) || !InitModMap(keyc))
49999                :    {
50000                :        xfree(keyc->curKeySyms.map);
50001                :        xfree(keyc->modifierKeyMap);
50002                :        xfree(keyc);
50003                :        return FALSE;
50004                :    }
50005                :    dev->key = keyc;
50006                :#ifdef XKB
50007                :    dev->key->xkbInfo= NULL;
50008                :    if (!noXkbExtension) XkbInitDevice(dev);
50009                :#endif
50010                :    return TRUE;
50011                :}
50012                :
50013                :_X_EXPORT Bool
50014                :InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, 
50015                :                            CARD8 *map)
50016                :{
50017                :    ButtonClassPtr butc;
50018                :    int i;
50019                :
50020                :    butc = (ButtonClassPtr)xalloc(sizeof(ButtonClassRec));
50021                :    if (!butc)
50022                :        return FALSE;
50023                :    butc->numButtons = numButtons;
50024                :    for (i = 1; i <= numButtons; i++)
50025                :        butc->map[i] = map[i];
50026                :    butc->buttonsDown = 0;
50027                :    butc->state = 0;
50028                :    butc->motionMask = 0;
50029                :    bzero((char *)butc->down, DOWN_LENGTH);
50030                :#ifdef XKB
50031                :    butc->xkb_acts=     NULL;
50032                :#endif
50033                :    dev->button = butc;
50034                :    return TRUE;
50035                :}
50036                :
50037                :_X_EXPORT Bool
50038                :InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, 
50039                :                              ValuatorMotionProcPtr motionProc, 
50040                :                              int numMotionEvents, int mode)
50041                :{
50042                :    int i;
50043                :    ValuatorClassPtr valc;
50044                :
50045                :    if (!dev)
50046                :        return FALSE;
50047                :
50048                :    valc = (ValuatorClassPtr)xalloc(sizeof(ValuatorClassRec) +
50049                :                                    numAxes * sizeof(AxisInfo) +
50050                :                                    numAxes * sizeof(unsigned int));
50051                :    if (!valc)
50052                :        return FALSE;
50053                :
50054                :    valc->motion = NULL;
50055                :    valc->first_motion = 0;
50056                :    valc->last_motion = 0;
50057                :    valc->GetMotionProc = motionProc;
50058                :
50059                :    valc->numMotionEvents = numMotionEvents;
50060                :    valc->motionHintWindow = NullWindow;
50061                :    valc->numAxes = numAxes;
50062                :    valc->mode = mode;
50063                :    valc->axes = (AxisInfoPtr)(valc + 1);
50064                :    valc->axisVal = (int *)(valc->axes + numAxes);
50065                :    valc->lastx = 0;
50066                :    valc->lasty = 0;
50067                :    valc->dxremaind = 0;
50068                :    valc->dyremaind = 0;
50069                :    dev->valuator = valc;
50070                :
50071                :    /* biggest hack ever. */
50072                :    if (motionProc == GetMotionHistory)
50073                :        AllocateMotionHistory(dev);
50074                :
50075                :    for (i=0; i<numAxes; i++) {
50076                :        InitValuatorAxisStruct(dev, i, 0, -1, 0, 0, 0);
50077                :        valc->axisVal[i]=0;
50078                :    }
50079                :    return TRUE;
50080                :}
50081                :
50082                :_X_EXPORT Bool
50083                :InitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
50084                :{
50085                :    AbsoluteClassPtr abs;
50086                :
50087                :    abs = (AbsoluteClassPtr)xalloc(sizeof(AbsoluteClassRec));
50088                :    if (!abs)
50089                :        return FALSE;
50090                :
50091                :    /* we don't do anything sensible with these, but should */
50092                :    abs->min_x = -1;
50093                :    abs->min_y = -1;
50094                :    abs->max_x = -1;
50095                :    abs->max_y = -1;
50096                :    abs->flip_x = 0;
50097                :    abs->flip_y = 0;
50098                :    abs->rotation = 0;
50099                :    abs->button_threshold = 0;
50100                :
50101                :    abs->offset_x = 0;
50102                :    abs->offset_y = 0;
50103                :    abs->width = -1;
50104                :    abs->height = -1;
50105                :    abs->following = 0;
50106                :    abs->screen = 0;
50107                :
50108                :    dev->absolute = abs;
50109                :
50110                :    return TRUE;
50111                :}
50112                :
50113                :_X_EXPORT Bool
50114                :InitFocusClassDeviceStruct(DeviceIntPtr dev)
50115                :{
50116                :    FocusClassPtr focc;
50117                :
50118                :    focc = (FocusClassPtr)xalloc(sizeof(FocusClassRec));
50119                :    if (!focc)
50120                :        return FALSE;
50121                :    focc->win = PointerRootWin;
50122                :    focc->revert = None;
50123                :    focc->time = currentTime;
50124                :    focc->trace = (WindowPtr *)NULL;
50125                :    focc->traceSize = 0;
50126                :    focc->traceGood = 0;
50127                :    dev->focus = focc;
50128                :    return TRUE;
50129                :}
50130                :
50131                :_X_EXPORT Bool
50132                :InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, 
50133                :                                 KbdCtrlProcPtr controlProc)
50134                :{
50135                :    KbdFeedbackPtr feedc;
50136                :
50137                :    feedc = (KbdFeedbackPtr)xalloc(sizeof(KbdFeedbackClassRec));
50138                :    if (!feedc)
50139                :        return FALSE;
50140                :    feedc->BellProc = bellProc;
50141                :    feedc->CtrlProc = controlProc;
50142                :#ifdef XKB
50143                :    defaultKeyboardControl.autoRepeat = TRUE;
50144                :#endif
50145                :    feedc->ctrl = defaultKeyboardControl;
50146                :    feedc->ctrl.id = 0;
50147                :    if ((feedc->next = dev->kbdfeed) != 0)
50148                :        feedc->ctrl.id = dev->kbdfeed->ctrl.id + 1;
50149                :    dev->kbdfeed = feedc;
50150                :#ifdef XKB
50151                :    feedc->xkb_sli= NULL;
50152                :    if (!noXkbExtension)
50153                :        XkbFinishDeviceInit(dev);
50154                :#endif
50155                :    (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl);
50156                :    return TRUE;
50157                :}
50158                :
50159                :_X_EXPORT Bool
50160                :InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc)
50161                :{
50162                :    PtrFeedbackPtr feedc;
50163                :
50164                :    feedc = (PtrFeedbackPtr)xalloc(sizeof(PtrFeedbackClassRec));
50165                :    if (!feedc)
50166                :        return FALSE;
50167                :    feedc->CtrlProc = controlProc;
50168                :    feedc->ctrl = defaultPointerControl;
50169                :    feedc->ctrl.id = 0;
50170                :    if ( (feedc->next = dev->ptrfeed) )
50171                :        feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1;
50172                :    dev->ptrfeed = feedc;
50173                :    (*controlProc)(dev, &feedc->ctrl);
50174                :    return TRUE;
50175                :}
50176                :
50177                :
50178                :static LedCtrl defaultLedControl = {
50179                :        DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0};
50180                :
50181                :static BellCtrl defaultBellControl = {
50182                :        DEFAULT_BELL,
50183                :        DEFAULT_BELL_PITCH,
50184                :        DEFAULT_BELL_DURATION,
50185                :        0};
50186                :
50187                :static IntegerCtrl defaultIntegerControl = {
50188                :        DEFAULT_INT_RESOLUTION,
50189                :        DEFAULT_INT_MIN_VALUE,
50190                :        DEFAULT_INT_MAX_VALUE,
50191                :        DEFAULT_INT_DISPLAYED,
50192                :        0};
50193                :
50194                :_X_EXPORT Bool
50195                :InitStringFeedbackClassDeviceStruct (
50196                :      DeviceIntPtr dev, StringCtrlProcPtr controlProc, 
50197                :      int max_symbols, int num_symbols_supported, KeySym *symbols)
50198                :{
50199                :    int i;
50200                :    StringFeedbackPtr feedc;
50201                :
50202                :    feedc = (StringFeedbackPtr)xalloc(sizeof(StringFeedbackClassRec));
50203                :    if (!feedc)
50204                :        return FALSE;
50205                :    feedc->CtrlProc = controlProc;
50206                :    feedc->ctrl.num_symbols_supported = num_symbols_supported;
50207                :    feedc->ctrl.num_symbols_displayed = 0;
50208                :    feedc->ctrl.max_symbols = max_symbols;
50209                :    feedc->ctrl.symbols_supported = (KeySym *) 
50210                :        xalloc (sizeof (KeySym) * num_symbols_supported);
50211                :    feedc->ctrl.symbols_displayed = (KeySym *) 
50212                :        xalloc (sizeof (KeySym) * max_symbols);
50213                :    if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed)
50214                :    {
50215                :        if (feedc->ctrl.symbols_supported)
50216                :            xfree(feedc->ctrl.symbols_supported);
50217                :        if (feedc->ctrl.symbols_displayed)
50218                :            xfree(feedc->ctrl.symbols_displayed);
50219                :        xfree(feedc);
50220                :        return FALSE;
50221                :    }
50222                :    for (i=0; i<num_symbols_supported; i++)
50223                :        *(feedc->ctrl.symbols_supported+i) = *symbols++;
50224                :    for (i=0; i<max_symbols; i++)
50225                :        *(feedc->ctrl.symbols_displayed+i) = (KeySym) NULL;
50226                :    feedc->ctrl.id = 0;
50227                :    if ( (feedc->next = dev->stringfeed) )
50228                :        feedc->ctrl.id = dev->stringfeed->ctrl.id + 1;
50229                :    dev->stringfeed = feedc;
50230                :    (*controlProc)(dev, &feedc->ctrl);
50231                :    return TRUE;
50232                :}
50233                :
50234                :_X_EXPORT Bool
50235                :InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, 
50236                :                                   BellCtrlProcPtr controlProc)
50237                :{
50238                :    BellFeedbackPtr feedc;
50239                :
50240                :    feedc = (BellFeedbackPtr)xalloc(sizeof(BellFeedbackClassRec));
50241                :    if (!feedc)
50242                :        return FALSE;
50243                :    feedc->CtrlProc = controlProc;
50244                :    feedc->BellProc = bellProc;
50245                :    feedc->ctrl = defaultBellControl;
50246                :    feedc->ctrl.id = 0;
50247                :    if ( (feedc->next = dev->bell) )
50248                :        feedc->ctrl.id = dev->bell->ctrl.id + 1;
50249                :    dev->bell = feedc;
50250                :    (*controlProc)(dev, &feedc->ctrl);
50251                :    return TRUE;
50252                :}
50253                :
50254                :_X_EXPORT Bool
50255                :InitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc)
50256                :{
50257                :    LedFeedbackPtr feedc;
50258                :
50259                :    feedc = (LedFeedbackPtr)xalloc(sizeof(LedFeedbackClassRec));
50260                :    if (!feedc)
50261                :        return FALSE;
50262                :    feedc->CtrlProc = controlProc;
50263                :    feedc->ctrl = defaultLedControl;
50264                :    feedc->ctrl.id = 0;
50265                :    if ( (feedc->next = dev->leds) )
50266                :        feedc->ctrl.id = dev->leds->ctrl.id + 1;
50267                :#ifdef XKB
50268                :    feedc->xkb_sli= NULL;
50269                :#endif
50270                :    dev->leds = feedc;
50271                :    (*controlProc)(dev, &feedc->ctrl);
50272                :    return TRUE;
50273                :}
50274                :
50275                :_X_EXPORT Bool
50276                :InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc)
50277                :{
50278                :    IntegerFeedbackPtr feedc;
50279                :
50280                :    feedc = (IntegerFeedbackPtr)xalloc(sizeof(IntegerFeedbackClassRec));
50281                :    if (!feedc)
50282                :        return FALSE;
50283                :    feedc->CtrlProc = controlProc;
50284                :    feedc->ctrl = defaultIntegerControl;
50285                :    feedc->ctrl.id = 0;
50286                :    if ( (feedc->next = dev->intfeed) )
50287                :        feedc->ctrl.id = dev->intfeed->ctrl.id + 1;
50288                :    dev->intfeed = feedc;
50289                :    (*controlProc)(dev, &feedc->ctrl);
50290                :    return TRUE;
50291                :}
50292                :
50293                :_X_EXPORT Bool
50294                :InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, 
50295                :                        ValuatorMotionProcPtr motionProc, 
50296                :                        PtrCtrlProcPtr controlProc, int numMotionEvents,
50297                :                        int numAxes)
50298                :{
50299                :    DeviceIntPtr dev = (DeviceIntPtr)device;
50300                :
50301                :    return(InitButtonClassDeviceStruct(dev, numButtons, map) &&
50302                :           InitValuatorClassDeviceStruct(dev, numAxes, motionProc,
50303                :                                         numMotionEvents, 0) &&
50304                :           InitPtrFeedbackClassDeviceStruct(dev, controlProc));
50305                :}
50306                :
50307                :_X_EXPORT Bool
50308                :InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, 
50309                :                         CARD8 pModifiers[], BellProcPtr bellProc, 
50310                :                         KbdCtrlProcPtr controlProc) 
50311                :{
50312                :    DeviceIntPtr dev = (DeviceIntPtr)device;
50313                :
50314                :    return(InitKeyClassDeviceStruct(dev, pKeySyms, pModifiers) &&
50315                :           InitFocusClassDeviceStruct(dev) &&
50316                :           InitKbdFeedbackClassDeviceStruct(dev, bellProc, controlProc));
50317                :}
50318                :
50319                :_X_EXPORT void
50320                :SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, 
50321                :                  ClientPtr client)
50322                :{
50323                :    int i;
50324                :    xEvent event;
50325                :
50326                :    event.u.u.type = MappingNotify;
50327                :    event.u.mappingNotify.request = request;
50328                :    if (request == MappingKeyboard)
50329                :    {
50330                :        event.u.mappingNotify.firstKeyCode = firstKeyCode;
50331                :        event.u.mappingNotify.count = count;
50332                :    }
50333                :#ifdef XKB
50334                :    if (!noXkbExtension &&
50335                :        ((request == MappingKeyboard) || (request == MappingModifier))) {
50336                :        XkbApplyMappingChange(inputInfo.keyboard,request,firstKeyCode,count,
50337                :                                                                        client);
50338                :    }
50339                :#endif
50340                :
50341                :   /* 0 is the server client */
50342                :    for (i=1; i<currentMaxClients; i++)
50343                :    {
50344                :        if (clients[i] && clients[i]->clientState == ClientStateRunning)
50345                :        {
50346                :#ifdef XKB
50347                :            if (!noXkbExtension &&
50348                :                (request == MappingKeyboard) &&
50349                :                (clients[i]->xkbClientFlags != 0) &&
50350                :                (clients[i]->mapNotifyMask&XkbKeySymsMask))
50351                :                continue;
50352                :#endif
50353                :            event.u.u.sequenceNumber = clients[i]->sequence;
50354                :            WriteEventsToClient(clients[i], 1, &event);
50355                :        }
50356                :    }
50357                :}
50358                :
50359                :/*
50360                : * n-squared algorithm. n < 255 and don't want to copy the whole thing and
50361                : * sort it to do the checking. How often is it called? Just being lazy?
50362                : */
50363                :Bool
50364                :BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval)
50365                :{
50366                :    int i, j;
50367                :
50368                :    for (i = 0; i < length; i++)
50369                :        if (buff[i])                   /* only check non-zero elements */
50370                :        {
50371                :            if ((low > buff[i]) || (high < buff[i]))
50372                :            {
50373                :                *errval = buff[i];
50374                :                return TRUE;
50375                :            }
50376                :            for (j = i + 1; j < length; j++)
50377                :                if (buff[i] == buff[j])
50378                :                {
50379                :                    *errval = buff[i];
50380                :                    return TRUE;
50381                :                }
50382                :        }
50383                :    return FALSE;
50384                :}
50385                :
50386                :Bool
50387                :AllModifierKeysAreUp(dev, map1, per1, map2, per2)
50388                :    DeviceIntPtr dev;
50389                :    CARD8 *map1, *map2;
50390                :    int per1, per2;
50391                :{
50392                :    int i, j, k;
50393                :    CARD8 *down = dev->key->down;
50394                :
50395                :    for (i = 8; --i >= 0; map2 += per2)
50396                :    {
50397                :        for (j = per1; --j >= 0; map1++)
50398                :        {
50399                :            if (*map1 && BitIsOn(down, *map1))
50400                :            {
50401                :                for (k = per2; (--k >= 0) && (*map1 != map2[k]);)
50402                :                  ;
50403                :                if (k < 0)
50404                :                    return FALSE;
50405                :            }
50406                :        }
50407                :    }
50408                :    return TRUE;
50409                :}
50410                :
50411                :static int
50412                :DoSetModifierMapping(ClientPtr client, KeyCode *inputMap,
50413                :                     int numKeyPerModifier)
50414                :{
50415                :    DeviceIntPtr pDev = NULL;
50416                :    int i = 0, inputMapLen = numKeyPerModifier * 8;
50417                :
50418                :    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
50419                :        if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
50420                :            for (i = 0; i < inputMapLen; i++) {
50421                :                /* Check that all the new modifiers fall within the advertised
50422                :                 * keycode range, and are okay with the DDX. */
50423                :                if (inputMap[i] && ((inputMap[i] < pDev->key->curKeySyms.minKeyCode ||
50424                :                                    inputMap[i] > pDev->key->curKeySyms.maxKeyCode) ||
50425                :                                    !LegalModifier(inputMap[i], pDev))) {
50426                :                    client->errorValue = inputMap[i];
50427                :                    return BadValue;
50428                :                }
50429                :            }
50430                :
50431                :            if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE))
50432                :                return BadAccess;
50433                :
50434                :            /* None of the modifiers (old or new) may be down while we change
50435                :             * the map. */
50436                :            if (!AllModifierKeysAreUp(pDev, pDev->key->modifierKeyMap,
50437                :                                      pDev->key->maxKeysPerModifier,
50438                :                                      inputMap, numKeyPerModifier) ||
50439                :                !AllModifierKeysAreUp(pDev, inputMap, numKeyPerModifier,
50440                :                                      pDev->key->modifierKeyMap,
50441                :                                      pDev->key->maxKeysPerModifier)) {
50442                :                return MappingBusy;
50443                :            }
50444                :        }
50445                :    }
50446                :
50447                :    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
50448                :
50449                :        if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
50450                :            bzero(pDev->key->modifierMap, MAP_LENGTH);
50451                :
50452                :            /* Annoyingly, we lack a modifierKeyMap size, so we have to just free
50453                :             * and re-alloc it every time. */
50454                :            if (pDev->key->modifierKeyMap)
50455                :                xfree(pDev->key->modifierKeyMap);
50456                :
50457                :            if (inputMapLen) {
50458                :                pDev->key->modifierKeyMap = (KeyCode *) xalloc(inputMapLen);
50459                :                if (!pDev->key->modifierKeyMap)
50460                :                    return BadAlloc;
50461                :
50462                :                memcpy(pDev->key->modifierKeyMap, inputMap, inputMapLen);
50463                :                pDev->key->maxKeysPerModifier = numKeyPerModifier;
50464                :
50465                :                for (i = 0; i < inputMapLen; i++) {
50466                :                    if (inputMap[i]) {
50467                :                        pDev->key->modifierMap[inputMap[i]] |=
50468                :                            (1 << (((unsigned int)i) / numKeyPerModifier));
50469                :                    }
50470                :                }
50471                :            }
50472                :            else {
50473                :                pDev->key->modifierKeyMap = NULL;
50474                :                pDev->key->maxKeysPerModifier = 0;
50475                :            }
50476                :        }
50477                :    }
50478                :
50479                :    return Success;
50480                :}
50481                :
50482                :int 
50483                :ProcSetModifierMapping(ClientPtr client)
50484                :{
50485                :    xSetModifierMappingReply rep;
50486                :    REQUEST(xSetModifierMappingReq);
50487                :    
50488                :    REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq);
50489                :
50490                :    if (client->req_len != ((stuff->numKeyPerModifier << 1) +
50491                :                            (sizeof (xSetModifierMappingReq) >> 2)))
50492                :        return BadLength;
50493                :
50494                :    rep.type = X_Reply;
50495                :    rep.length = 0;
50496                :    rep.sequenceNumber = client->sequence;
50497                :
50498                :    rep.success = DoSetModifierMapping(client, (KeyCode *)&stuff[1],
50499                :                                       stuff->numKeyPerModifier);
50500                :
50501                :    /* FIXME: Send mapping notifies for all the extended devices as well. */
50502                :    SendMappingNotify(MappingModifier, 0, 0, client);
50503                :    WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
50504                :    return client->noClientException;
50505                :}
50506                :
50507                :int
50508                :ProcGetModifierMapping(ClientPtr client)
50509                :{
50510                :    xGetModifierMappingReply rep;
50511                :    KeyClassPtr keyc = inputInfo.keyboard->key;
50512                :
50513                :    REQUEST_SIZE_MATCH(xReq);
50514                :    rep.type = X_Reply;
50515                :    rep.numKeyPerModifier = keyc->maxKeysPerModifier;
50516                :    rep.sequenceNumber = client->sequence;
50517                :    /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */
50518                :    rep.length = keyc->maxKeysPerModifier << 1;
50519                :
50520                :    WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep);
50521                :
50522                :    /* Use the (modified by DDX) map that SetModifierMapping passed in */
50523                :    (void)WriteToClient(client, (int)(keyc->maxKeysPerModifier << 3),
50524                :                        (char *)keyc->modifierKeyMap);
50525                :    return client->noClientException;
50526                :}
50527                :
50528                :int
50529                :ProcChangeKeyboardMapping(ClientPtr client)
50530                :{
50531                :    REQUEST(xChangeKeyboardMappingReq);
50532                :    unsigned len;
50533                :    KeySymsRec keysyms;
50534                :    KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
50535                :    DeviceIntPtr pDev = NULL;
50536                :    REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
50537                :
50538                :    len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2);  
50539                :    if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
50540                :            return BadLength;
50541                :
50542                :    if ((stuff->firstKeyCode < curKeySyms->minKeyCode) ||
50543                :        (stuff->firstKeyCode > curKeySyms->maxKeyCode)) {
50544                :            client->errorValue = stuff->firstKeyCode;
50545                :            return BadValue;
50546                :
50547                :    }
50548                :    if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) >
50549                :        curKeySyms->maxKeyCode) || (stuff->keySymsPerKeyCode == 0)) {
50550                :            client->errorValue = stuff->keySymsPerKeyCode;
50551                :            return BadValue;
50552                :    }
50553                :
50554                :    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
50555                :        if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
50556                :            if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE))
50557                :                return BadAccess;
50558                :        }
50559                :    }
50560                :
50561                :    keysyms.minKeyCode = stuff->firstKeyCode;
50562                :    keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1;
50563                :    keysyms.mapWidth = stuff->keySymsPerKeyCode;
50564                :    keysyms.map = (KeySym *)&stuff[1];
50565                :    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
50566                :        if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
50567                :            if (!SetKeySymsMap(&pDev->key->curKeySyms, &keysyms))
50568                :                return BadAlloc;
50569                :        }
50570                :    }
50571                :
50572                :    /* FIXME: Send mapping notifies for all the extended devices as well. */
50573                :    SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes,
50574                :                      client);
50575                :    return client->noClientException;
50576                :}
50577                :
50578                :static int
50579                :DoSetPointerMapping(DeviceIntPtr device, BYTE *map, int n)
50580                :{
50581                :    int i = 0;
50582                :    DeviceIntPtr dev = NULL;
50583                :
50584                :    if (!device || !device->button)
50585                :        return BadDevice;
50586                :
50587                :    for (dev = inputInfo.devices; dev; dev = dev->next) {
50588                :        if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) {
50589                :            for (i = 0; i < n; i++) {
50590                :                if ((device->button->map[i + 1] != map[i]) &&
50591                :                    BitIsOn(device->button->down, i + 1)) {
50592                :                    return MappingBusy;
50593                :                }
50594                :            }
50595                :        }
50596                :    }
50597                :
50598                :    for (dev = inputInfo.devices; dev; dev = dev->next) {
50599                :        if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) {
50600                :            for (i = 0; i < n; i++)
50601                :                dev->button->map[i + 1] = map[i];
50602                :        }
50603                :    }
50604                :
50605                :    return Success;
50606                :}
50607                :
50608                :int
50609                :ProcSetPointerMapping(ClientPtr client)
50610                :{
50611                :    REQUEST(xSetPointerMappingReq);
50612                :    BYTE *map;
50613                :    int ret;
50614                :    xSetPointerMappingReply rep;
50615                :
50616                :    REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
50617                :    if (client->req_len != (sizeof(xSetPointerMappingReq)+stuff->nElts+3) >> 2)
50618                :        return BadLength;
50619                :    rep.type = X_Reply;
50620                :    rep.length = 0;
50621                :    rep.sequenceNumber = client->sequence;
50622                :    rep.success = MappingSuccess;
50623                :    map = (BYTE *)&stuff[1];
50624                :    
50625                :    /* So we're bounded here by the number of core buttons.  This check
50626                :     * probably wants disabling through XFixes. */
50627                :    if (stuff->nElts != inputInfo.pointer->button->numButtons) {
50628                :        client->errorValue = stuff->nElts;
50629                :        return BadValue;
50630                :    }
50631                :    if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue))
50632                :        return BadValue;
50633                :
50634                :    ret = DoSetPointerMapping(inputInfo.pointer, map, stuff->nElts);
50635                :    if (ret != Success) {
50636                :        rep.success = ret;
50637                :        WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
50638                :        return Success;
50639                :    }
50640                :
50641                :    /* FIXME: Send mapping notifies for all the extended devices as well. */
50642                :    SendMappingNotify(MappingPointer, 0, 0, client);
50643                :    WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
50644                :    return Success;
50645                :}
50646                :
50647                :int
50648                :ProcGetKeyboardMapping(ClientPtr client)
50649                :{
50650                :    xGetKeyboardMappingReply rep;
50651                :    REQUEST(xGetKeyboardMappingReq);
50652                :    KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
50653                :
50654                :    REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
50655                :
50656                :    if ((stuff->firstKeyCode < curKeySyms->minKeyCode) ||
50657                :        (stuff->firstKeyCode > curKeySyms->maxKeyCode)) {
50658                :        client->errorValue = stuff->firstKeyCode;
50659                :        return BadValue;
50660                :    }
50661                :    if (stuff->firstKeyCode + stuff->count >
50662                :        (unsigned)(curKeySyms->maxKeyCode + 1)) {
50663                :        client->errorValue = stuff->count;
50664                :        return BadValue;
50665                :    }
50666                :
50667                :    rep.type = X_Reply;
50668                :    rep.sequenceNumber = client->sequence;
50669                :    rep.keySymsPerKeyCode = curKeySyms->mapWidth;
50670                :    /* length is a count of 4 byte quantities and KeySyms are 4 bytes */
50671                :    rep.length = (curKeySyms->mapWidth * stuff->count);
50672                :    WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep);
50673                :    client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
50674                :    WriteSwappedDataToClient(
50675                :        client,
50676                :        curKeySyms->mapWidth * stuff->count * sizeof(KeySym),
50677                :        &curKeySyms->map[(stuff->firstKeyCode - curKeySyms->minKeyCode) *
50678                :                         curKeySyms->mapWidth]);
50679                :
50680                :    return client->noClientException;
50681                :}
50682                :
50683                :int
50684                :ProcGetPointerMapping(ClientPtr client)
50685                :{
50686                :    xGetPointerMappingReply rep;
50687                :    ButtonClassPtr butc = inputInfo.pointer->button;
50688                :
50689                :    REQUEST_SIZE_MATCH(xReq);
50690                :    rep.type = X_Reply;
50691                :    rep.sequenceNumber = client->sequence;
50692                :    rep.nElts = butc->numButtons;
50693                :    rep.length = ((unsigned)rep.nElts + (4-1))/4;
50694                :    WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep);
50695                :    (void)WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]);
50696                :    return Success;    
50697                :}
50698                :
50699                :void
50700                :NoteLedState(DeviceIntPtr keybd, int led, Bool on)
50701                :{
50702                :    KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl;
50703                :    if (on)
50704                :        ctrl->leds |= ((Leds)1 << (led - 1));
50705                :    else
50706                :        ctrl->leds &= ~((Leds)1 << (led - 1));
50707                :}
50708                :
50709                :_X_EXPORT int
50710                :Ones(unsigned long mask)             /* HACKMEM 169 */
50711      3  0.0033 :{ /* Ones total:      9  0.0098 */
50712                :    unsigned long y;
50713                :
50714                :    y = (mask >> 1) &033333333333;
50715      4  0.0044 :    y = mask - y - ((y >>1) & 033333333333);
50716                :    return (((y + (y >> 3)) & 030707070707) % 077);
50717      2  0.0022 :}
50718                :
50719                :static int
50720                :DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
50721                :                         BITS32 vmask)
50722                :{
50723                :#define DO_ALL    (-1)
50724                :    KeybdCtrl ctrl;
50725                :    int t;
50726                :    int led = DO_ALL;
50727                :    int key = DO_ALL;
50728                :    BITS32 index2;
50729                :    int mask = vmask, i;
50730                :
50731                :    ctrl = keybd->kbdfeed->ctrl;
50732                :    while (vmask) {
50733                :        index2 = (BITS32) lowbit (vmask);
50734                :        vmask &= ~index2;
50735                :        switch (index2) {
50736                :        case KBKeyClickPercent: 
50737                :            t = (INT8)*vlist;
50738                :            vlist++;
50739                :            if (t == -1) {
50740                :                t = defaultKeyboardControl.click;
50741                :            }
50742                :            else if (t < 0 || t > 100) {
50743                :                client->errorValue = t;
50744                :                return BadValue;
50745                :            }
50746                :            ctrl.click = t;
50747                :            break;
50748                :        case KBBellPercent:
50749                :            t = (INT8)*vlist;
50750                :            vlist++;
50751                :            if (t == -1) {
50752                :                t = defaultKeyboardControl.bell;
50753                :            }
50754                :            else if (t < 0 || t > 100) {
50755                :                client->errorValue = t;
50756                :                return BadValue;
50757                :            }
50758                :            ctrl.bell = t;
50759                :            break;
50760                :        case KBBellPitch:
50761                :            t = (INT16)*vlist;
50762                :            vlist++;
50763                :            if (t == -1) {
50764                :                t = defaultKeyboardControl.bell_pitch;
50765                :            }
50766                :            else if (t < 0) {
50767                :                client->errorValue = t;
50768                :                return BadValue;
50769                :            }
50770                :            ctrl.bell_pitch = t;
50771                :            break;
50772                :        case KBBellDuration:
50773                :            t = (INT16)*vlist;
50774                :            vlist++;
50775                :            if (t == -1)
50776                :                t = defaultKeyboardControl.bell_duration;
50777                :            else if (t < 0) {
50778                :                client->errorValue = t;
50779                :                return BadValue;
50780                :            }
50781                :            ctrl.bell_duration = t;
50782                :            break;
50783                :        case KBLed:
50784                :            led = (CARD8)*vlist;
50785                :            vlist++;
50786                :            if (led < 1 || led > 32) {
50787                :                client->errorValue = led;
50788                :                return BadValue;
50789                :            }
50790                :            if (!(mask & KBLedMode))
50791                :                return BadMatch;
50792                :            break;
50793                :        case KBLedMode:
50794                :            t = (CARD8)*vlist;
50795                :            vlist++;
50796                :            if (t == LedModeOff) {
50797                :                if (led == DO_ALL)
50798                :                    ctrl.leds = 0x0;
50799                :                else
50800                :                    ctrl.leds &= ~(((Leds)(1)) << (led - 1));
50801                :            }
50802                :            else if (t == LedModeOn) {
50803                :                if (led == DO_ALL)
50804                :                    ctrl.leds = ~0L;
50805                :                else
50806                :                    ctrl.leds |= (((Leds)(1)) << (led - 1));
50807                :            }
50808                :            else {
50809                :                client->errorValue = t;
50810                :                return BadValue;
50811                :            }
50812                :#ifdef XKB
50813                :            if (!noXkbExtension) {
50814                :                XkbEventCauseRec cause;
50815                :                XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client);
50816                :                XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))),
50817                :                                                        ctrl.leds, &cause);
50818                :                ctrl.leds = keybd->kbdfeed->ctrl.leds;
50819                :            }
50820                :#endif
50821                :            break;
50822                :        case KBKey:
50823                :            key = (KeyCode)*vlist;
50824                :            vlist++;
50825                :            if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode ||
50826                :                (KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) {
50827                :                client->errorValue = key;
50828                :                return BadValue;
50829                :            }
50830                :            if (!(mask & KBAutoRepeatMode))
50831                :                return BadMatch;
50832                :            break;
50833                :        case KBAutoRepeatMode:
50834                :            i = (key >> 3);
50835                :            mask = (1 << (key & 7));
50836                :            t = (CARD8)*vlist;
50837                :            vlist++;
50838                :#ifdef XKB
50839                :            if (!noXkbExtension && key != DO_ALL)
50840                :                XkbDisableComputedAutoRepeats(keybd,key);
50841                :#endif
50842                :            if (t == AutoRepeatModeOff) {
50843                :                if (key == DO_ALL)
50844                :                    ctrl.autoRepeat = FALSE;
50845                :                else
50846                :                    ctrl.autoRepeats[i] &= ~mask;
50847                :            }
50848                :            else if (t == AutoRepeatModeOn) {
50849                :                if (key == DO_ALL)
50850                :                    ctrl.autoRepeat = TRUE;
50851                :                else
50852                :                    ctrl.autoRepeats[i] |= mask;
50853                :            }
50854                :            else if (t == AutoRepeatModeDefault) {
50855                :                if (key == DO_ALL)
50856                :                    ctrl.autoRepeat = defaultKeyboardControl.autoRepeat;
50857                :                else
50858                :                    ctrl.autoRepeats[i] =
50859                :                            (ctrl.autoRepeats[i] & ~mask) |
50860                :                            (defaultKeyboardControl.autoRepeats[i] & mask);
50861                :            }
50862                :            else {
50863                :                client->errorValue = t;
50864                :                return BadValue;
50865                :            }
50866                :            break;
50867                :        default:
50868                :            client->errorValue = mask;
50869                :            return BadValue;
50870                :        }
50871                :    }
50872                :    keybd->kbdfeed->ctrl = ctrl;
50873                :
50874                :#ifdef XKB
50875                :    /* The XKB RepeatKeys control and core protocol global autorepeat */
50876                :    /* value are linked */
50877                :    if (!noXkbExtension)
50878                :        XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat);
50879                :    else
50880                :#endif
50881                :        (*keybd->kbdfeed->CtrlProc)(keybd, &keybd->kbdfeed->ctrl);
50882                :
50883                :    return Success;
50884                :
50885                :#undef DO_ALL
50886                :} 
50887                :
50888                :int
50889                :ProcChangeKeyboardControl (ClientPtr client)
50890                :{
50891                :    XID *vlist;
50892                :    BITS32 vmask;
50893                :    int ret = Success, error = Success;
50894                :    DeviceIntPtr pDev = NULL;
50895                :    REQUEST(xChangeKeyboardControlReq);
50896                :
50897                :    REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq);
50898                :
50899                :    vmask = stuff->mask;
50900                :    vlist = (XID *)&stuff[1];
50901                :
50902                :    if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask))
50903                :        return BadLength;
50904                :
50905                :    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
50906                :        if ((pDev->coreEvents || pDev == inputInfo.keyboard) &&
50907                :            pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
50908                :            if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE))
50909                :                return BadAccess;
50910                :        }
50911                :    }
50912                :
50913                :    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
50914                :        if ((pDev->coreEvents || pDev == inputInfo.keyboard) &&
50915                :            pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
50916                :            ret = DoChangeKeyboardControl(client, pDev, vlist, vmask);
50917                :            if (ret != Success)
50918                :                error = ret;
50919                :        }
50920                :    }
50921                :
50922                :    return error;
50923                :}
50924                :
50925                :int
50926                :ProcGetKeyboardControl (ClientPtr client)
50927                :{
50928                :    int i;
50929                :    KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl;
50930                :    xGetKeyboardControlReply rep;
50931                :
50932                :    REQUEST_SIZE_MATCH(xReq);
50933                :    rep.type = X_Reply;
50934                :    rep.length = 5;
50935                :    rep.sequenceNumber = client->sequence;
50936                :    rep.globalAutoRepeat = ctrl->autoRepeat;
50937                :    rep.keyClickPercent = ctrl->click;
50938                :    rep.bellPercent = ctrl->bell;
50939                :    rep.bellPitch = ctrl->bell_pitch;
50940                :    rep.bellDuration = ctrl->bell_duration;
50941                :    rep.ledMask = ctrl->leds;
50942                :    for (i = 0; i < 32; i++)
50943                :        rep.map[i] = ctrl->autoRepeats[i];
50944                :    WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep);
50945                :    return Success;
50946                :} 
50947                :
50948                :int
50949                :ProcBell(ClientPtr client)
50950                :{
50951                :    DeviceIntPtr keybd = inputInfo.keyboard;
50952                :    int base = keybd->kbdfeed->ctrl.bell;
50953                :    int newpercent;
50954                :    REQUEST(xBellReq);
50955                :    REQUEST_SIZE_MATCH(xBellReq);
50956                :
50957                :    if (!keybd->kbdfeed->BellProc)
50958                :        return BadDevice;
50959                :    
50960                :    if (stuff->percent < -100 || stuff->percent > 100) {
50961                :        client->errorValue = stuff->percent;
50962                :        return BadValue;
50963                :    }
50964                :
50965                :    newpercent = (base * stuff->percent) / 100;
50966                :    if (stuff->percent < 0)
50967                :        newpercent = base + newpercent;
50968                :    else
50969                :        newpercent = base - newpercent + stuff->percent;
50970                :
50971                :    for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
50972                :        if ((keybd->coreEvents || keybd == inputInfo.keyboard) &&
50973                :            keybd->kbdfeed && keybd->kbdfeed->BellProc) {
50974                :#ifdef XKB
50975                :            if (!noXkbExtension)
50976                :                XkbHandleBell(FALSE, FALSE, keybd, newpercent,
50977                :                              &keybd->kbdfeed->ctrl, 0, None, NULL, client);
50978                :            else
50979                :#endif
50980                :                (*keybd->kbdfeed->BellProc)(newpercent, keybd,
50981                :                                            &keybd->kbdfeed->ctrl, 0);
50982                :        }
50983                :    }
50984                :
50985                :    return Success;
50986                :} 
50987                :
50988                :int
50989                :ProcChangePointerControl(ClientPtr client)
50990                :{
50991                :    DeviceIntPtr mouse = inputInfo.pointer;
50992                :    PtrCtrl ctrl;               /* might get BadValue part way through */
50993                :    REQUEST(xChangePointerControlReq);
50994                :
50995                :    REQUEST_SIZE_MATCH(xChangePointerControlReq);
50996                :    
50997                :    if (!mouse->ptrfeed->CtrlProc)
50998                :        return BadDevice;
50999                :    
51000                :    ctrl = mouse->ptrfeed->ctrl;
51001                :    if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
51002                :        client->errorValue = stuff->doAccel;
51003                :        return(BadValue);
51004                :    }
51005                :    if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) {
51006                :        client->errorValue = stuff->doThresh;
51007                :        return(BadValue);
51008                :    }
51009                :    if (stuff->doAccel) {
51010                :        if (stuff->accelNum == -1) {
51011                :            ctrl.num = defaultPointerControl.num;
51012                :        }
51013                :        else if (stuff->accelNum < 0) {
51014                :            client->errorValue = stuff->accelNum;
51015                :            return BadValue;
51016                :        }
51017                :        else {
51018                :            ctrl.num = stuff->accelNum;
51019                :        }
51020                :
51021                :        if (stuff->accelDenum == -1) {
51022                :            ctrl.den = defaultPointerControl.den;
51023                :        }
51024                :        else if (stuff->accelDenum <= 0) {
51025                :            client->errorValue = stuff->accelDenum;
51026                :            return BadValue;
51027                :        }
51028                :        else {
51029                :            ctrl.den = stuff->accelDenum;
51030                :        }
51031                :    }
51032                :    if (stuff->doThresh) {
51033                :        if (stuff->threshold == -1) {
51034                :            ctrl.threshold = defaultPointerControl.threshold;
51035                :        }
51036                :        else if (stuff->threshold < 0) {
51037                :            client->errorValue = stuff->threshold;
51038                :            return BadValue;
51039                :        }
51040                :        else {
51041                :            ctrl.threshold = stuff->threshold;
51042                :        }
51043                :    }
51044                :
51045                :
51046                :    for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
51047                :        if ((mouse->coreEvents || mouse == inputInfo.pointer) &&
51048                :            mouse->ptrfeed && mouse->ptrfeed->CtrlProc) {
51049                :            mouse->ptrfeed->ctrl = ctrl;
51050                :            (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl);
51051                :        }
51052                :    }
51053                :
51054                :    return Success;
51055                :} 
51056                :
51057                :int
51058                :ProcGetPointerControl(ClientPtr client)
51059                :{
51060                :    PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl;
51061                :    xGetPointerControlReply rep;
51062                :
51063                :    REQUEST_SIZE_MATCH(xReq);
51064                :    rep.type = X_Reply;
51065                :    rep.length = 0;
51066                :    rep.sequenceNumber = client->sequence;
51067                :    rep.threshold = ctrl->threshold;
51068                :    rep.accelNumerator = ctrl->num;
51069                :    rep.accelDenominator = ctrl->den;
51070                :    WriteReplyToClient(client, sizeof(xGenericReply), &rep);
51071                :    return Success;
51072                :}
51073                :
51074                :void
51075                :MaybeStopHint(DeviceIntPtr dev, ClientPtr client)
51076                :{
51077                :    GrabPtr grab = dev->grab;
51078                :
51079                :    if ((grab && SameClient(grab, client) &&
51080                :         ((grab->eventMask & PointerMotionHintMask) ||
51081                :          (grab->ownerEvents &&
51082                :           (EventMaskForClient(dev->valuator->motionHintWindow, client) &
51083                :            PointerMotionHintMask)))) ||
51084                :        (!grab &&
51085                :         (EventMaskForClient(dev->valuator->motionHintWindow, client) &
51086                :          PointerMotionHintMask)))
51087                :        dev->valuator->motionHintWindow = NullWindow;
51088                :}
51089                :
51090                :int
51091                :ProcGetMotionEvents(ClientPtr client)
51092                :{
51093                :    WindowPtr pWin;
51094                :    xTimecoord * coords = (xTimecoord *) NULL;
51095                :    xGetMotionEventsReply rep;
51096                :    int i, count, xmin, xmax, ymin, ymax, rc;
51097                :    unsigned long nEvents;
51098                :    DeviceIntPtr mouse = inputInfo.pointer;
51099                :    TimeStamp start, stop;
51100                :    REQUEST(xGetMotionEventsReq);
51101                :
51102                :    REQUEST_SIZE_MATCH(xGetMotionEventsReq);
51103                :    rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
51104                :    if (rc != Success)
51105                :        return rc;
51106                :    if (mouse->valuator->motionHintWindow)
51107                :        MaybeStopHint(mouse, client);
51108                :    rep.type = X_Reply;
51109                :    rep.sequenceNumber = client->sequence;
51110                :    nEvents = 0;
51111                :    start = ClientTimeToServerTime(stuff->start);
51112                :    stop = ClientTimeToServerTime(stuff->stop);
51113                :    if ((CompareTimeStamps(start, stop) != LATER) &&
51114                :        (CompareTimeStamps(start, currentTime) != LATER) &&
51115                :        mouse->valuator->numMotionEvents)
51116                :    {
51117                :        if (CompareTimeStamps(stop, currentTime) == LATER)
51118                :            stop = currentTime;
51119                :        coords = (xTimecoord *)ALLOCATE_LOCAL(mouse->valuator->numMotionEvents
51120                :                                              * sizeof(xTimecoord));
51121                :        if (!coords)
51122                :            return BadAlloc;
51123                :        count = (*mouse->valuator->GetMotionProc) (mouse, coords,
51124                :                                                   start.milliseconds,
51125                :                                                   stop.milliseconds,
51126                :                                                   pWin->drawable.pScreen);
51127                :        xmin = pWin->drawable.x - wBorderWidth (pWin);
51128                :        xmax = pWin->drawable.x + (int)pWin->drawable.width +
51129                :                wBorderWidth (pWin);
51130                :        ymin = pWin->drawable.y - wBorderWidth (pWin);
51131                :        ymax = pWin->drawable.y + (int)pWin->drawable.height +
51132                :                wBorderWidth (pWin);
51133                :        for (i = 0; i < count; i++)
51134                :            if ((xmin <= coords[i].x) && (coords[i].x < xmax) &&
51135                :                    (ymin <= coords[i].y) && (coords[i].y < ymax))
51136                :            {
51137                :                coords[nEvents].time = coords[i].time;
51138                :                coords[nEvents].x = coords[i].x - pWin->drawable.x;
51139                :                coords[nEvents].y = coords[i].y - pWin->drawable.y;
51140                :                nEvents++;
51141                :            }
51142                :    }
51143                :    rep.length = nEvents * (sizeof(xTimecoord) >> 2);
51144                :    rep.nEvents = nEvents;
51145                :    WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep);
51146                :    if (nEvents)
51147                :    {
51148                :        client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite;
51149                :        WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord),
51150                :                                 (char *)coords);
51151                :    }
51152                :    if (coords)
51153                :        DEALLOCATE_LOCAL(coords);
51154                :    return Success;
51155                :}
51156                :
51157                :int
51158                :ProcQueryKeymap(ClientPtr client)
51159                :{
51160                :    xQueryKeymapReply rep;
51161                :    int i;
51162                :    CARD8 *down = inputInfo.keyboard->key->down;
51163                :
51164                :    REQUEST_SIZE_MATCH(xReq);
51165                :    rep.type = X_Reply;
51166                :    rep.sequenceNumber = client->sequence;
51167                :    rep.length = 2;
51168                :
51169                :    if (XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
51170                :        for (i = 0; i<32; i++)
51171                :            rep.map[i] = down[i];
51172                :    else
51173                :        bzero((char *)&rep.map[0], 32);
51174                :
51175                :    WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
51176                :    return Success;
51177                :}
51178 /* 
51179  * Total samples for file : "xf86dri.c"
51180  * 
51181  *      8  0.0087
51182  */
51183
51184 <credited to line zero>      8  0.0087 :
51185  /* __i686.get_pc_thunk.cx total:      8  0.0087 */
51186 /* 
51187  * Total samples for file : "/home/cworth/src/xorg/xserver/dix/extension.c"
51188  * 
51189  *      5  0.0054
51190  */
51191
51192
51193                :/***********************************************************
51194                :
51195                :Copyright 1987, 1998  The Open Group
51196                :
51197                :Permission to use, copy, modify, distribute, and sell this software and its
51198                :documentation for any purpose is hereby granted without fee, provided that
51199                :the above copyright notice appear in all copies and that both that
51200                :copyright notice and this permission notice appear in supporting
51201                :documentation.
51202                :
51203                :The above copyright notice and this permission notice shall be included in
51204                :all copies or substantial portions of the Software.
51205                :
51206                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51207                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51208                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
51209                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
51210                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
51211                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
51212                :
51213                :Except as contained in this notice, the name of The Open Group shall not be
51214                :used in advertising or otherwise to promote the sale, use or other dealings
51215                :in this Software without prior written authorization from The Open Group.
51216                :
51217                :
51218                :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
51219                :
51220                :                        All Rights Reserved
51221                :
51222                :Permission to use, copy, modify, and distribute this software and its 
51223                :documentation for any purpose and without fee is hereby granted, 
51224                :provided that the above copyright notice appear in all copies and that
51225                :both that copyright notice and this permission notice appear in 
51226                :supporting documentation, and that the name of Digital not be
51227                :used in advertising or publicity pertaining to distribution of the
51228                :software without specific, written prior permission.  
51229                :
51230                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
51231                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
51232                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
51233                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51234                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
51235                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51236                :SOFTWARE.
51237                :
51238                :******************************************************************/
51239                :
51240                :#ifdef HAVE_DIX_CONFIG_H
51241                :#include <dix-config.h>
51242                :#endif
51243                :
51244                :#include <X11/X.h>
51245                :#define NEED_EVENTS
51246                :#define NEED_REPLIES
51247                :#include <X11/Xproto.h>
51248                :#include "misc.h"
51249                :#include "dixstruct.h"
51250                :#include "extnsionst.h"
51251                :#include "gcstruct.h"
51252                :#include "scrnintstr.h"
51253                :#include "dispatch.h"
51254                :#include "xace.h"
51255                :
51256                :#define EXTENSION_BASE  128
51257                :#define EXTENSION_EVENT_BASE  64
51258                :#define LAST_EVENT  128
51259                :#define LAST_ERROR 255
51260                :
51261                :static ExtensionEntry **extensions = (ExtensionEntry **)NULL;
51262                :
51263                :int lastEvent = EXTENSION_EVENT_BASE;
51264                :static int lastError = FirstExtensionError;
51265                :static unsigned int NumExtensions = 0;
51266                :
51267                :extern int extensionPrivateLen;
51268                :extern unsigned *extensionPrivateSizes;
51269                :extern unsigned totalExtensionSize;
51270                :
51271                :static void
51272                :InitExtensionPrivates(ExtensionEntry *ext)
51273                :{
51274                :    char *ptr;
51275                :    DevUnion *ppriv;
51276                :    unsigned *sizes;
51277                :    unsigned size;
51278                :    int i;
51279                :
51280                :    if (totalExtensionSize == sizeof(ExtensionEntry))
51281                :        ppriv = (DevUnion *)NULL;
51282                :    else
51283                :        ppriv = (DevUnion *)(ext + 1);
51284                :
51285                :    ext->devPrivates = ppriv;
51286                :    sizes = extensionPrivateSizes;
51287                :    ptr = (char *)(ppriv + extensionPrivateLen);
51288                :    for (i = extensionPrivateLen; --i >= 0; ppriv++, sizes++)
51289                :    {
51290                :        if ( (size = *sizes) )
51291                :        {
51292                :            ppriv->ptr = (pointer)ptr;
51293                :            ptr += size;
51294                :        }
51295                :        else
51296                :            ppriv->ptr = (pointer)NULL;
51297                :    }
51298                :}
51299                :
51300                :_X_EXPORT ExtensionEntry *
51301                :AddExtension(char *name, int NumEvents, int NumErrors, 
51302                :             int (*MainProc)(ClientPtr c1), 
51303                :             int (*SwappedMainProc)(ClientPtr c2), 
51304                :             void (*CloseDownProc)(ExtensionEntry *e), 
51305                :             unsigned short (*MinorOpcodeProc)(ClientPtr c3))
51306                :{
51307                :    int i;
51308                :    ExtensionEntry *ext, **newexts;
51309                :
51310                :    if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc)
51311                :        return((ExtensionEntry *) NULL);
51312                :    if ((lastEvent + NumEvents > LAST_EVENT) || 
51313                :                (unsigned)(lastError + NumErrors > LAST_ERROR))
51314                :        return((ExtensionEntry *) NULL);
51315                :
51316                :    ext = (ExtensionEntry *) xalloc(totalExtensionSize);
51317                :    if (!ext)
51318                :        return((ExtensionEntry *) NULL);
51319                :    bzero(ext, totalExtensionSize);
51320                :    InitExtensionPrivates(ext);
51321                :    ext->name = (char *)xalloc(strlen(name) + 1);
51322                :    ext->num_aliases = 0;
51323                :    ext->aliases = (char **)NULL;
51324                :    if (!ext->name)
51325                :    {
51326                :        xfree(ext);
51327                :        return((ExtensionEntry *) NULL);
51328                :    }
51329                :    strcpy(ext->name,  name);
51330                :    i = NumExtensions;
51331                :    newexts = (ExtensionEntry **) xrealloc(extensions,
51332                :                                           (i + 1) * sizeof(ExtensionEntry *));
51333                :    if (!newexts)
51334                :    {
51335                :        xfree(ext->name);
51336                :        xfree(ext);
51337                :        return((ExtensionEntry *) NULL);
51338                :    }
51339                :    NumExtensions++;
51340                :    extensions = newexts;
51341                :    extensions[i] = ext;
51342                :    ext->index = i;
51343                :    ext->base = i + EXTENSION_BASE;
51344                :    ext->CloseDown = CloseDownProc;
51345                :    ext->MinorOpcode = MinorOpcodeProc;
51346                :    ProcVector[i + EXTENSION_BASE] = MainProc;
51347                :    SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc;
51348                :    if (NumEvents)
51349                :    {
51350                :        ext->eventBase = lastEvent;
51351                :        ext->eventLast = lastEvent + NumEvents;
51352                :        lastEvent += NumEvents;
51353                :    }
51354                :    else
51355                :    {
51356                :        ext->eventBase = 0;
51357                :        ext->eventLast = 0;
51358                :    }
51359                :    if (NumErrors)
51360                :    {
51361                :        ext->errorBase = lastError;
51362                :        ext->errorLast = lastError + NumErrors;
51363                :        lastError += NumErrors;
51364                :    }
51365                :    else
51366                :    {
51367                :        ext->errorBase = 0;
51368                :        ext->errorLast = 0;
51369                :    }
51370                :
51371                :    return(ext);
51372                :}
51373                :
51374                :_X_EXPORT Bool AddExtensionAlias(char *alias, ExtensionEntry *ext)
51375                :{
51376                :    char *name;
51377                :    char **aliases;
51378                :
51379                :    aliases = (char **)xrealloc(ext->aliases,
51380                :                                (ext->num_aliases + 1) * sizeof(char *));
51381                :    if (!aliases)
51382                :        return FALSE;
51383                :    ext->aliases = aliases;
51384                :    name = (char *)xalloc(strlen(alias) + 1);
51385                :    if (!name)
51386                :        return FALSE;
51387                :    strcpy(name,  alias);
51388                :    ext->aliases[ext->num_aliases] = name;
51389                :    ext->num_aliases++;
51390                :    return TRUE;
51391                :}
51392                :
51393                :static int
51394                :FindExtension(char *extname, int len)
51395                :{
51396                :    int i, j;
51397                :
51398                :    for (i=0; i<NumExtensions; i++)
51399                :    {
51400                :        if ((strlen(extensions[i]->name) == len) &&
51401                :            !strncmp(extname, extensions[i]->name, len))
51402                :            break;
51403                :        for (j = extensions[i]->num_aliases; --j >= 0;)
51404                :        {
51405                :            if ((strlen(extensions[i]->aliases[j]) == len) &&
51406                :                !strncmp(extname, extensions[i]->aliases[j], len))
51407                :                break;
51408                :        }
51409                :        if (j >= 0) break;
51410                :    }
51411                :    return ((i == NumExtensions) ? -1 : i);
51412                :}
51413                :
51414                :/*
51415                : * CheckExtension returns the extensions[] entry for the requested
51416                : * extension name.  Maybe this could just return a Bool instead?
51417                : */
51418                :_X_EXPORT ExtensionEntry *
51419                :CheckExtension(const char *extname)
51420                :{
51421                :    int n;
51422                :
51423                :    n = FindExtension((char*)extname, strlen(extname));
51424                :    if (n != -1)
51425                :        return extensions[n];
51426                :    else
51427                :        return NULL;
51428                :}
51429                :
51430                :/*
51431                : * Added as part of Xace.
51432                : */
51433                :ExtensionEntry *
51434                :GetExtensionEntry(int major)
51435      5  0.0054 :{     /* GetExtensionEntry total:      5  0.0054 */
51436                :    if (major < EXTENSION_BASE)
51437                :        return NULL;
51438                :    major -= EXTENSION_BASE;
51439                :    if (major >= NumExtensions)
51440                :        return NULL;
51441                :    return extensions[major];
51442                :}
51443                :
51444                :_X_EXPORT void
51445                :DeclareExtensionSecurity(char *extname, Bool secure)
51446                :{
51447                :    int i = FindExtension(extname, strlen(extname));
51448                :    if (i >= 0)
51449                :        XaceHook(XACE_DECLARE_EXT_SECURE, extensions[i], secure);
51450                :}
51451                :
51452                :_X_EXPORT unsigned short
51453                :StandardMinorOpcode(ClientPtr client)
51454                :{
51455                :    return ((xReq *)client->requestBuffer)->data;
51456                :}
51457                :
51458                :_X_EXPORT unsigned short
51459                :MinorOpcodeOfRequest(ClientPtr client)
51460                :{
51461                :    unsigned char major;
51462                :
51463                :    major = ((xReq *)client->requestBuffer)->reqType;
51464                :    if (major < EXTENSION_BASE)
51465                :        return 0;
51466                :    major -= EXTENSION_BASE;
51467                :    if (major >= NumExtensions)
51468                :        return 0;
51469                :    return (*extensions[major]->MinorOpcode)(client);
51470                :}
51471                :
51472                :void
51473                :CloseDownExtensions(void)
51474                :{
51475                :    int i,j;
51476                :
51477                :    for (i = NumExtensions - 1; i >= 0; i--)
51478                :    {
51479                :        (* extensions[i]->CloseDown)(extensions[i]);
51480                :        NumExtensions = i;
51481                :        xfree(extensions[i]->name);
51482                :        for (j = extensions[i]->num_aliases; --j >= 0;)
51483                :            xfree(extensions[i]->aliases[j]);
51484                :        xfree(extensions[i]->aliases);
51485                :        xfree(extensions[i]);
51486                :    }
51487                :    xfree(extensions);
51488                :    extensions = (ExtensionEntry **)NULL;
51489                :    lastEvent = EXTENSION_EVENT_BASE;
51490                :    lastError = FirstExtensionError;
51491                :}
51492                :
51493                :int
51494                :ProcQueryExtension(ClientPtr client)
51495                :{
51496                :    xQueryExtensionReply reply;
51497                :    int i;
51498                :    REQUEST(xQueryExtensionReq);
51499                :
51500                :    REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes);
51501                :    
51502                :    reply.type = X_Reply;
51503                :    reply.length = 0;
51504                :    reply.major_opcode = 0;
51505                :    reply.sequenceNumber = client->sequence;
51506                :
51507                :    if ( ! NumExtensions )
51508                :        reply.present = xFalse;
51509                :    else
51510                :    {
51511                :        i = FindExtension((char *)&stuff[1], stuff->nbytes);
51512                :        if (i < 0 || !XaceHook(XACE_EXT_ACCESS, client, extensions[i]))
51513                :            reply.present = xFalse;
51514                :        else
51515                :        {            
51516                :            reply.present = xTrue;
51517                :            reply.major_opcode = extensions[i]->base;
51518                :            reply.first_event = extensions[i]->eventBase;
51519                :            reply.first_error = extensions[i]->errorBase;
51520                :        }
51521                :    }
51522                :    WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply);
51523                :    return(client->noClientException);
51524                :}
51525                :
51526                :int
51527                :ProcListExtensions(ClientPtr client)
51528                :{
51529                :    xListExtensionsReply reply;
51530                :    char *bufptr, *buffer;
51531                :    int total_length = 0;
51532                :
51533                :    REQUEST_SIZE_MATCH(xReq);
51534                :
51535                :    reply.type = X_Reply;
51536                :    reply.nExtensions = 0;
51537                :    reply.length = 0;
51538                :    reply.sequenceNumber = client->sequence;
51539                :    buffer = NULL;
51540                :
51541                :    if ( NumExtensions )
51542                :    {
51543                :        int i, j;
51544                :
51545                :        for (i=0;  i<NumExtensions; i++)
51546                :        {
51547                :            /* call callbacks to find out whether to show extension */
51548                :            if (!XaceHook(XACE_EXT_ACCESS, client, extensions[i]))
51549                :                continue;
51550                :
51551                :            total_length += strlen(extensions[i]->name) + 1;
51552                :            reply.nExtensions += 1 + extensions[i]->num_aliases;
51553                :            for (j = extensions[i]->num_aliases; --j >= 0;)
51554                :                total_length += strlen(extensions[i]->aliases[j]) + 1;
51555                :        }
51556                :        reply.length = (total_length + 3) >> 2;
51557                :        buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length);
51558                :        if (!buffer)
51559                :            return(BadAlloc);
51560                :        for (i=0;  i<NumExtensions; i++)
51561                :        {
51562                :            int len;
51563                :            if (!XaceHook(XACE_EXT_ACCESS, client, extensions[i]))
51564                :                continue;
51565                :
51566                :            *bufptr++ = len = strlen(extensions[i]->name);
51567                :            memmove(bufptr, extensions[i]->name,  len);
51568                :            bufptr += len;
51569                :            for (j = extensions[i]->num_aliases; --j >= 0;)
51570                :            {
51571                :                *bufptr++ = len = strlen(extensions[i]->aliases[j]);
51572                :                memmove(bufptr, extensions[i]->aliases[j],  len);
51573                :                bufptr += len;
51574                :            }
51575                :        }
51576                :    }
51577                :    WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply);
51578                :    if (reply.length)
51579                :    {
51580                :        WriteToClient(client, total_length, buffer);
51581                :        DEALLOCATE_LOCAL(buffer);
51582                :    }
51583                :    return(client->noClientException);
51584                :}
51585                :
51586                :#ifdef XSERVER_DTRACE
51587                :void LoadExtensionNames(char **RequestNames) {
51588                :    int i;
51589                :
51590                :    for (i=0; i<NumExtensions; i++) {
51591                :        int r = extensions[i]->base;
51592                :
51593                :        if (RequestNames[r] == NULL) {
51594                :            RequestNames[r] = strdup(extensions[i]->name);
51595                :        }
51596                :    }
51597                :}
51598                :#endif
51599 /* 
51600  * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-trap.c"
51601  * 
51602  *      5  0.0054
51603  */
51604
51605
51606                :/*
51607                : * $Id$
51608                : *
51609                : * Copyright Â© 2004 Keith Packard
51610                : *
51611                : * Permission to use, copy, modify, distribute, and sell this software and its
51612                : * documentation for any purpose is hereby granted without fee, provided that
51613                : * the above copyright notice appear in all copies and that both that
51614                : * copyright notice and this permission notice appear in supporting
51615                : * documentation, and that the name of Keith Packard not be used in
51616                : * advertising or publicity pertaining to distribution of the software without
51617                : * specific, written prior permission.  Keith Packard makes no
51618                : * representations about the suitability of this software for any purpose.  It
51619                : * is provided "as is" without express or implied warranty.
51620                : *
51621                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
51622                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
51623                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
51624                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
51625                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
51626                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
51627                : * PERFORMANCE OF THIS SOFTWARE.
51628                : */
51629                :
51630                :#include <config.h>
51631                :#include <stdio.h>
51632                :#include "pixman-private.h"
51633                :
51634                :typedef uint32_t FbBits;
51635                :
51636                :void
51637                :pixman_add_traps (pixman_image_t *      image,
51638                :                  int16_t       x_off,
51639                :                  int16_t       y_off,
51640                :                  int           ntrap,
51641                :                  pixman_trap_t *traps)
51642                :{
51643                :    int         bpp;
51644                :    int         width;
51645                :    int         height;
51646                :
51647                :    pixman_fixed_t      x_off_fixed;
51648                :    pixman_fixed_t      y_off_fixed;
51649                :    pixman_edge_t  l, r;
51650                :    pixman_fixed_t      t, b;
51651                :
51652                :    width = image->bits.width;
51653                :    height = image->bits.height;
51654                :    bpp = PIXMAN_FORMAT_BPP (image->bits.format);
51655                :    
51656                :    x_off_fixed = pixman_int_to_fixed(y_off);
51657                :    y_off_fixed = pixman_int_to_fixed(y_off);
51658                :
51659                :    while (ntrap--)
51660                :    {
51661                :        t = traps->top.y + y_off_fixed;
51662                :        if (t < 0)
51663                :            t = 0;
51664                :        t = pixman_sample_ceil_y (t, bpp);
51665                :    
51666                :        b = traps->bot.y + y_off_fixed;
51667                :        if (pixman_fixed_to_int (b) >= height)
51668                :            b = pixman_int_to_fixed (height) - 1;
51669                :        b = pixman_sample_floor_y (b, bpp);
51670                :        
51671                :        if (b >= t)
51672                :        {
51673                :            /* initialize edge walkers */
51674                :            pixman_edge_init (&l, bpp, t,
51675                :                              traps->top.l + x_off_fixed,
51676                :                              traps->top.y + y_off_fixed,
51677                :                              traps->bot.l + x_off_fixed,
51678                :                              traps->bot.y + y_off_fixed);
51679                :        
51680                :            pixman_edge_init (&r, bpp, t,
51681                :                              traps->top.r + x_off_fixed,
51682                :                              traps->top.y + y_off_fixed,
51683                :                              traps->bot.r + x_off_fixed,
51684                :                              traps->bot.y + y_off_fixed);
51685                :            
51686                :            pixman_rasterize_edges (image, &l, &r, t, b);
51687                :        }
51688                :        traps++;
51689                :    }
51690                :
51691                :    fbFinishAccess (pPicture->pDrawable);
51692                :}
51693                :
51694                :static void
51695                :dump_image (pixman_image_t *image,
51696                :            const char *title)
51697                :{
51698                :    int i, j;
51699                :    
51700                :    if (!image->type == BITS)
51701                :    {
51702                :        printf ("%s is not a regular image\n", title);
51703                :    }
51704                :
51705                :    if (!image->bits.format == PIXMAN_a8)
51706                :    {
51707                :        printf ("%s is not an alpha mask\n", title);
51708                :    }
51709                :
51710                :    printf ("\n\n\n%s: \n", title);
51711                :    
51712                :    for (i = 0; i < image->bits.height; ++i)
51713                :    {
51714                :        uint8_t *line =
51715                :            (uint8_t *)&(image->bits.bits[i * image->bits.rowstride]);
51716                :            
51717                :        for (j = 0; j < image->bits.width; ++j)
51718                :            printf ("%c", line[j]? '#' : ' ');
51719                :
51720                :        printf ("\n");
51721                :    }
51722                :}
51723                :
51724                :void
51725                :pixman_add_trapezoids       (pixman_image_t      *image,
51726                :                             int16_t              x_off,
51727                :                             int                      y_off,
51728                :                             int                      ntraps,
51729                :                             const pixman_trapezoid_t *traps)
51730                :{
51731                :    int i;
51732                :
51733                :#if 0
51734                :    dump_image (image, "before");
51735                :#endif
51736                :    
51737                :    for (i = 0; i < ntraps; ++i)
51738                :    {
51739                :        const pixman_trapezoid_t *trap = &(traps[i]);
51740                :        
51741                :        if (!pixman_trapezoid_valid (trap))
51742                :            continue;
51743                :        
51744                :        pixman_rasterize_trapezoid (image, trap, x_off, y_off);
51745                :    }
51746                :
51747                :#if 0
51748                :    dump_image (image, "after");
51749                :#endif
51750                :}
51751                :
51752                :void
51753                :pixman_rasterize_trapezoid (pixman_image_t *    image,
51754                :                            const pixman_trapezoid_t *trap,
51755                :                            int                 x_off,
51756                :                            int                 y_off)
51757                :{ /* pixman_rasterize_trapezoid total:      5  0.0054 */
51758                :    int         bpp;
51759                :    int         width;
51760                :    int         height;
51761                :
51762                :    pixman_fixed_t      x_off_fixed;
51763                :    pixman_fixed_t      y_off_fixed;
51764                :    pixman_edge_t       l, r;
51765                :    pixman_fixed_t      t, b;
51766                :
51767                :    return_if_fail (image->type == BITS);
51768                :    
51769      2  0.0022 :    if (!pixman_trapezoid_valid (trap))
51770                :        return;
51771                :
51772                :    width = image->bits.width;
51773                :    height = image->bits.height;
51774                :    bpp = PIXMAN_FORMAT_BPP (image->bits.format);
51775                :    
51776                :    x_off_fixed = pixman_int_to_fixed(x_off);
51777                :    y_off_fixed = pixman_int_to_fixed(y_off);
51778                :    t = trap->top + y_off_fixed;
51779                :    if (t < 0)
51780                :        t = 0;
51781                :    t = pixman_sample_ceil_y (t, bpp);
51782                :
51783                :    b = trap->bottom + y_off_fixed;
51784                :    if (pixman_fixed_to_int (b) >= height)
51785                :        b = pixman_int_to_fixed (height) - 1;
51786                :    b = pixman_sample_floor_y (b, bpp);
51787                :    
51788                :    if (b >= t)
51789                :    {
51790                :        /* initialize edge walkers */
51791                :        pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
51792      3  0.0033 :        pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);
51793                :
51794                :        pixman_rasterize_edges (image, &l, &r, t, b);
51795                :    }
51796                :}
51797                :
51798                :#if 0
51799                :static int
51800                :_GreaterY (pixman_point_fixed_t *a, pixman_point_fixed_t *b)
51801                :{
51802                :    if (a->y == b->y)
51803                :        return a->x > b->x;
51804                :    return a->y > b->y;
51805                :}
51806                :
51807                :/*
51808                : * Note that the definition of this function is a bit odd because
51809                : * of the X coordinate space (y increasing downwards).
51810                : */
51811                :static int
51812                :_Clockwise (pixman_point_fixed_t *ref, pixman_point_fixed_t *a, pixman_point_fixed_t *b)
51813                :{
51814                :    pixman_point_fixed_t        ad, bd;
51815                :
51816                :    ad.x = a->x - ref->x;
51817                :    ad.y = a->y - ref->y;
51818                :    bd.x = b->x - ref->x;
51819                :    bd.y = b->y - ref->y;
51820                :
51821                :    return ((pixman_fixed_32_32_t) bd.y * ad.x - (pixman_fixed_32_32_t) ad.y * bd.x) < 0;
51822                :}
51823                :
51824                :/* FIXME -- this could be made more efficient */
51825                :void
51826                :fbAddTriangles (pixman_image_t *  pPicture,
51827                :                int16_t     x_off,
51828                :                int16_t     y_off,
51829                :                int         ntri,
51830                :                xTriangle *tris)
51831                :{
51832                :    pixman_point_fixed_t          *top, *left, *right, *tmp;
51833                :    xTrapezoid      trap;
51834                :
51835                :    for (; ntri; ntri--, tris++)
51836                :    {
51837                :        top = &tris->p1;
51838                :        left = &tris->p2;
51839                :        right = &tris->p3;
51840                :        if (_GreaterY (top, left)) {
51841                :            tmp = left; left = top; top = tmp;
51842                :        }
51843                :        if (_GreaterY (top, right)) {
51844                :            tmp = right; right = top; top = tmp;
51845                :        }
51846                :        if (_Clockwise (top, right, left)) {
51847                :            tmp = right; right = left; left = tmp;
51848                :        }
51849                :        
51850                :        /*
51851                :         * Two cases:
51852                :         *
51853                :         *              +               +
51854                :         *             / \             / \
51855                :         *            /   \           /   \
51856                :         *           /     +         +     \
51857                :         *      /    --           --    \
51858                :         *     /   --               --   \
51859                :         *    / ---                   --- \
51860                :         *       +--                         --+
51861                :         */
51862                :        
51863                :        trap.top = top->y;
51864                :        trap.left.p1 = *top;
51865                :        trap.left.p2 = *left;
51866                :        trap.right.p1 = *top;
51867                :        trap.right.p2 = *right;
51868                :        if (right->y < left->y)
51869                :            trap.bottom = right->y;
51870                :        else
51871                :            trap.bottom = left->y;
51872                :        fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
51873                :        if (right->y < left->y)
51874                :        {
51875                :            trap.top = right->y;
51876                :            trap.bottom = left->y;
51877                :            trap.right.p1 = *right;
51878                :            trap.right.p2 = *left;
51879                :        }
51880                :        else
51881                :        {
51882                :            trap.top = left->y;
51883                :            trap.bottom = right->y;
51884                :            trap.left.p1 = *left;
51885                :            trap.left.p2 = *right;
51886                :        }
51887                :        fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
51888                :    }
51889                :}
51890                :#endif
51891 /* 
51892  * Total samples for file : "memcpy.c"
51893  * 
51894  *      4  0.0044
51895  */
51896
51897 <credited to line zero>      4  0.0044 :
51898  /* _dl_load_cache_lookup total:      1  0.0011 */
51899  /* _dl_lookup_symbol_x total:      1  0.0011 */
51900  /* _dl_relocate_object total:      1  0.0011 */
51901  /* strcmp total:      2  0.0022 */
51902 /* 
51903  * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbpict.c"
51904  * 
51905  *      3  0.0033
51906  */
51907
51908
51909                :/*
51910                : *
51911                : * Copyright Â© 2000 SuSE, Inc.
51912                : * Copyright Â© 2007 Red Hat, Inc.
51913                : *
51914                : * Permission to use, copy, modify, distribute, and sell this software and its
51915                : * documentation for any purpose is hereby granted without fee, provided that
51916                : * the above copyright notice appear in all copies and that both that
51917                : * copyright notice and this permission notice appear in supporting
51918                : * documentation, and that the name of SuSE not be used in advertising or
51919                : * publicity pertaining to distribution of the software without specific,
51920                : * written prior permission.  SuSE makes no representations about the
51921                : * suitability of this software for any purpose.  It is provided "as is"
51922                : * without express or implied warranty.
51923                : *
51924                : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
51925                : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
51926                : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
51927                : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
51928                : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
51929                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51930                : *
51931                : * Author:  Keith Packard, SuSE, Inc.
51932                : */
51933                :
51934                :#ifdef HAVE_DIX_CONFIG_H
51935                :#include <dix-config.h>
51936                :#endif
51937                :
51938                :#include <string.h>
51939                :
51940                :#include "fb.h"
51941                :
51942                :#ifdef RENDER
51943                :
51944                :#include "picturestr.h"
51945                :#include "mipict.h"
51946                :#include "fbpict.h"
51947                :
51948                :#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
51949                :
51950                :void
51951                :fbWalkCompositeRegion (CARD8 op,
51952                :                       PicturePtr pSrc,
51953                :                       PicturePtr pMask,
51954                :                       PicturePtr pDst,
51955                :                       INT16 xSrc,
51956                :                       INT16 ySrc,
51957                :                       INT16 xMask,
51958                :                       INT16 yMask,
51959                :                       INT16 xDst,
51960                :                       INT16 yDst,
51961                :                       CARD16 width,
51962                :                       CARD16 height,
51963                :                       Bool srcRepeat,
51964                :                       Bool maskRepeat,
51965                :                       CompositeFunc compositeRect)
51966                :{
51967                :    RegionRec       region;
51968                :    int             n;
51969                :    BoxPtr          pbox;
51970                :    int             w, h, w_this, h_this;
51971                :    int             x_msk, y_msk, x_src, y_src, x_dst, y_dst;
51972                :    
51973                :    xDst += pDst->pDrawable->x;
51974                :    yDst += pDst->pDrawable->y;
51975                :    if (pSrc->pDrawable)
51976                :    {
51977                :        xSrc += pSrc->pDrawable->x;
51978                :        ySrc += pSrc->pDrawable->y;
51979                :    }
51980                :    if (pMask && pMask->pDrawable)
51981                :    {
51982                :        xMask += pMask->pDrawable->x;
51983                :        yMask += pMask->pDrawable->y;
51984                :    }
51985                :
51986                :    if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst, xSrc, ySrc,
51987                :                                   xMask, yMask, xDst, yDst, width, height))
51988                :        return;
51989                :    
51990                :    n = REGION_NUM_RECTS (&region);
51991                :    pbox = REGION_RECTS (&region);
51992                :    while (n--)
51993                :    {
51994                :        h = pbox->y2 - pbox->y1;
51995                :        y_src = pbox->y1 - yDst + ySrc;
51996                :        y_msk = pbox->y1 - yDst + yMask;
51997                :        y_dst = pbox->y1;
51998                :        while (h)
51999                :        {
52000                :            h_this = h;
52001                :            w = pbox->x2 - pbox->x1;
52002                :            x_src = pbox->x1 - xDst + xSrc;
52003                :            x_msk = pbox->x1 - xDst + xMask;
52004                :            x_dst = pbox->x1;
52005                :            if (maskRepeat)
52006                :            {
52007                :                y_msk = mod (y_msk - pMask->pDrawable->y, pMask->pDrawable->height);
52008                :                if (h_this > pMask->pDrawable->height - y_msk)
52009                :                    h_this = pMask->pDrawable->height - y_msk;
52010                :                y_msk += pMask->pDrawable->y;
52011                :            }
52012                :            if (srcRepeat)
52013                :            {
52014                :                y_src = mod (y_src - pSrc->pDrawable->y, pSrc->pDrawable->height);
52015                :                if (h_this > pSrc->pDrawable->height - y_src)
52016                :                    h_this = pSrc->pDrawable->height - y_src;
52017                :                y_src += pSrc->pDrawable->y;
52018                :            }
52019                :            while (w)
52020                :            {
52021                :                w_this = w;
52022                :                if (maskRepeat)
52023                :                {
52024                :                    x_msk = mod (x_msk - pMask->pDrawable->x, pMask->pDrawable->width);
52025                :                    if (w_this > pMask->pDrawable->width - x_msk)
52026                :                        w_this = pMask->pDrawable->width - x_msk;
52027                :                    x_msk += pMask->pDrawable->x;
52028                :                }
52029                :                if (srcRepeat)
52030                :                {
52031                :                    x_src = mod (x_src - pSrc->pDrawable->x, pSrc->pDrawable->width);
52032                :                    if (w_this > pSrc->pDrawable->width - x_src)
52033                :                        w_this = pSrc->pDrawable->width - x_src;
52034                :                    x_src += pSrc->pDrawable->x;
52035                :                }
52036                :                (*compositeRect) (op, pSrc, pMask, pDst,
52037                :                                  x_src, y_src, x_msk, y_msk, x_dst, y_dst,
52038                :                                  w_this, h_this);
52039                :                w -= w_this;
52040                :                x_src += w_this;
52041                :                x_msk += w_this;
52042                :                x_dst += w_this;
52043                :            }
52044                :            h -= h_this;
52045                :            y_src += h_this;
52046                :            y_msk += h_this;
52047                :            y_dst += h_this;
52048                :        }
52049                :        pbox++;
52050                :    }
52051                :    REGION_UNINIT (pDst->pDrawable->pScreen, &region);
52052                :}
52053                :
52054                :void
52055                :fbComposite (CARD8      op,
52056                :             PicturePtr pSrc,
52057                :             PicturePtr pMask,
52058                :             PicturePtr pDst,
52059                :             INT16      xSrc,
52060                :             INT16      ySrc,
52061                :             INT16      xMask,
52062                :             INT16      yMask,
52063                :             INT16      xDst,
52064                :             INT16      yDst,
52065                :             CARD16     width,
52066                :             CARD16     height)
52067                :{
52068                :    pixman_image_t *src, *mask, *dest;
52069                :    
52070                :    xDst += pDst->pDrawable->x;
52071                :    yDst += pDst->pDrawable->y;
52072                :    if (pSrc->pDrawable)
52073                :    {
52074                :        xSrc += pSrc->pDrawable->x;
52075                :        ySrc += pSrc->pDrawable->y;
52076                :    }
52077                :    if (pMask && pMask->pDrawable)
52078                :    {
52079                :        xMask += pMask->pDrawable->x;
52080                :        yMask += pMask->pDrawable->y;
52081                :    }
52082                :
52083                :    miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height);
52084                :    if (pMask)
52085                :        miCompositeSourceValidate (pMask, xMask, yMask, width, height);
52086                :    
52087                :    src = image_from_pict (pSrc, TRUE);
52088                :    mask = image_from_pict (pMask, TRUE);
52089                :    dest = image_from_pict (pDst, TRUE);
52090                :
52091                :    if (src && dest && !(pMask && !mask))
52092                :    {
52093                :        pixman_image_composite (op, src, mask, dest,
52094                :                                xSrc, ySrc, xMask, yMask, xDst, yDst,
52095                :                                width, height);
52096                :            
52097                :    }
52098                :    
52099                :    if (src)
52100                :        pixman_image_unref (src);
52101                :    if (mask)
52102                :        pixman_image_unref (mask);
52103                :    if (dest)
52104                :        pixman_image_unref (dest);
52105                :}
52106                :
52107                :void
52108                :fbCompositeGeneral (CARD8       op,
52109                :                    PicturePtr  pSrc,
52110                :                    PicturePtr  pMask,
52111                :                    PicturePtr  pDst,
52112                :                    INT16       xSrc,
52113                :                    INT16       ySrc,
52114                :                    INT16       xMask,
52115                :                    INT16       yMask,
52116                :                    INT16       xDst,
52117                :                    INT16       yDst,
52118                :                    CARD16      width,
52119                :                    CARD16      height)
52120                :{
52121                :    return fbComposite (op, pSrc, pMask, pDst,
52122                :                        xSrc, ySrc, xMask, yMask, xDst, yDst,
52123                :                        width, height);
52124                :}
52125                :
52126                :#endif /* RENDER */
52127                :
52128                :static pixman_image_t *
52129                :create_solid_fill_image (PicturePtr pict)
52130                :{
52131                :    PictSolidFill *solid = &pict->pSourcePict->solidFill;
52132                :    pixman_color_t color;
52133                :    CARD32 a, r, g, b;
52134                :    
52135                :    a = (solid->color & 0xff000000) >> 24;
52136                :    r = (solid->color & 0x00ff0000) >> 16;
52137                :    g = (solid->color & 0x0000ff00) >>  8;
52138                :    b = (solid->color & 0x000000ff) >>  0;
52139                :    
52140                :    color.alpha = (a << 8) | a;
52141                :    color.red =   (r << 8) | r;
52142                :    color.green = (g << 8) | g;
52143                :    color.blue =  (b << 8) | b;
52144                :    
52145                :    return pixman_image_create_solid_fill (&color);
52146                :}
52147                :
52148                :static pixman_image_t *
52149                :create_linear_gradient_image (PictGradient *gradient)
52150                :{
52151                :    PictLinearGradient *linear = (PictLinearGradient *)gradient;
52152                :    pixman_point_fixed_t p1;
52153                :    pixman_point_fixed_t p2;
52154                :    
52155                :    p1.x = linear->p1.x;
52156                :    p1.y = linear->p1.y;
52157                :    p2.x = linear->p2.x;
52158                :    p2.y = linear->p2.y;
52159                :    
52160                :    return pixman_image_create_linear_gradient (
52161                :        &p1, &p2, (pixman_gradient_stop_t *)gradient->stops, gradient->nstops);
52162                :}
52163                :
52164                :static pixman_image_t *
52165                :create_radial_gradient_image (PictGradient *gradient)
52166                :{
52167                :    PictRadialGradient *radial = (PictRadialGradient *)gradient;
52168                :    pixman_point_fixed_t c1;
52169                :    pixman_point_fixed_t c2;
52170                :    
52171                :    c1.x = radial->c1.x;
52172                :    c1.y = radial->c1.y;
52173                :    c2.x = radial->c2.x;
52174                :    c2.y = radial->c2.y;
52175                :    
52176                :    return pixman_image_create_radial_gradient (
52177                :        &c1, &c2, radial->c1.radius,
52178                :        radial->c2.radius,
52179                :        (pixman_gradient_stop_t *)gradient->stops, gradient->nstops);
52180                :}
52181                :
52182                :static pixman_image_t *
52183                :create_conical_gradient_image (PictGradient *gradient)
52184                :{
52185                :    PictConicalGradient *conical = (PictConicalGradient *)gradient;
52186                :    pixman_point_fixed_t center;
52187                :    
52188                :    center.x = conical->center.x;
52189                :    center.y = conical->center.y;
52190                :    
52191                :    return pixman_image_create_conical_gradient (
52192                :        &center, conical->angle, (pixman_gradient_stop_t *)gradient->stops,
52193                :        gradient->nstops);
52194                :}
52195                :
52196                :static pixman_image_t *
52197                :create_bits_picture (PicturePtr pict,
52198                :                     Bool       has_clip)
52199                :{
52200                :    FbBits *bits;
52201                :    FbStride stride;
52202                :    int bpp, xoff, yoff;
52203                :    pixman_image_t *image;
52204                :    
52205                :    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
52206                :    
52207                :    bits += yoff * stride + xoff;
52208                :    
52209                :    image = pixman_image_create_bits (
52210                :        pict->format,
52211                :        pict->pDrawable->width, pict->pDrawable->height,
52212                :        (uint32_t *)bits, stride * sizeof (FbStride));
52213                :    
52214                :    
52215                :#ifdef FB_ACCESS_WRAPPER
52216                :#if FB_SHIFT==5
52217                :    
52218                :    pixman_image_set_accessors (image,
52219                :                                (pixman_read_memory_func_t)wfbReadMemory,
52220                :                                (pixman_write_memory_func_t)wfbWriteMemory);
52221                :    
52222                :#else
52223                :    
52224                :#error The pixman library only works when FbBits is 32 bits wide
52225                :    
52226                :#endif
52227                :#endif
52228                :    
52229                :    /* pCompositeClip is undefined for source pictures, so
52230                :     * only set the clip region for pictures with drawables
52231                :     */
52232                :    if (has_clip)
52233                :    {
52234                :        if (pict->clientClipType != CT_NONE)
52235                :            pixman_image_set_has_client_clip (image, TRUE);
52236                :        
52237                :        pixman_image_set_clip_region (image, pict->pCompositeClip);
52238                :    }
52239                :    
52240                :    /* Indexed table */
52241                :    if (pict->pFormat->index.devPrivate)
52242                :        pixman_image_set_indexed (image, pict->pFormat->index.devPrivate);
52243                :    
52244                :    fbFinishAccess (pict->pDrawable);
52245                :
52246                :    return image;
52247                :}
52248                :
52249                :static void
52250                :set_image_properties (pixman_image_t *image, PicturePtr pict)
52251                :{
52252                :    pixman_repeat_t repeat;
52253                :    pixman_filter_t filter;
52254                :    
52255                :    if (pict->transform)
52256                :    {
52257                :        pixman_image_set_transform (
52258                :            image, (pixman_transform_t *)pict->transform);
52259                :    }
52260                :    
52261                :    switch (pict->repeatType)
52262                :    {
52263                :    default:
52264                :    case RepeatNone:
52265                :        repeat = PIXMAN_REPEAT_NONE;
52266                :        break;
52267                :        
52268                :    case RepeatPad:
52269                :        repeat = PIXMAN_REPEAT_PAD;
52270                :        break;
52271                :        
52272                :    case RepeatNormal:
52273                :        repeat = PIXMAN_REPEAT_NORMAL;
52274                :        break;
52275                :        
52276                :    case RepeatReflect:
52277                :        repeat = PIXMAN_REPEAT_REFLECT;
52278                :        break;
52279                :    }
52280                :    
52281                :    pixman_image_set_repeat (image, repeat);
52282                :    
52283                :    if (pict->alphaMap)
52284                :    {
52285                :        pixman_image_t *alpha_map = image_from_pict (pict->alphaMap, TRUE);
52286                :        
52287                :        pixman_image_set_alpha_map (
52288                :            image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y);
52289                :        
52290                :        pixman_image_unref (alpha_map);
52291                :    }
52292                :    
52293                :    pixman_image_set_component_alpha (image, pict->componentAlpha);
52294                :
52295                :    switch (pict->filter)
52296                :    {
52297                :    default:
52298                :    case PictFilterNearest:
52299                :    case PictFilterFast:
52300                :        filter = PIXMAN_FILTER_NEAREST;
52301                :        break;
52302                :        
52303                :    case PictFilterBilinear:
52304                :    case PictFilterGood:
52305                :        filter = PIXMAN_FILTER_BILINEAR;
52306                :        break;
52307                :        
52308                :    case PictFilterConvolution:
52309                :        filter = PIXMAN_FILTER_CONVOLUTION;
52310                :        break;
52311                :    }
52312                :    
52313                :    pixman_image_set_filter (image, filter, (pixman_fixed_t *)pict->filter_params, pict->filter_nparams);
52314                :}
52315                :
52316                :pixman_image_t *
52317                :image_from_pict (PicturePtr pict,
52318                :                 Bool has_clip)
52319      3  0.0033 :{ /* image_from_pict total:      4  0.0044 */
52320                :    pixman_image_t *image = NULL;
52321                :
52322                :    if (!pict)
52323                :        return NULL;
52324                :
52325                :    if (pict->pDrawable)
52326                :    {
52327                :        image = create_bits_picture (pict, has_clip);
52328                :    }
52329                :    else if (pict->pSourcePict)
52330                :    {
52331                :        SourcePict *sp = pict->pSourcePict;
52332                :        
52333                :        if (sp->type == SourcePictTypeSolidFill)
52334                :        {
52335                :            image = create_solid_fill_image (pict);
52336                :        }
52337                :        else
52338                :        {
52339                :            PictGradient *gradient = &pict->pSourcePict->gradient;
52340                :            
52341                :            if (sp->type == SourcePictTypeLinear)
52342                :                image = create_linear_gradient_image (gradient);
52343                :            else if (sp->type == SourcePictTypeRadial)
52344                :                image = create_radial_gradient_image (gradient);
52345                :            else if (sp->type == SourcePictTypeConical)
52346                :                image = create_conical_gradient_image (gradient);
52347                :        }
52348                :    }
52349                :    
52350                :    if (image)
52351                :        set_image_properties (image, pict);
52352                :    
52353                :    return image;
52354                :}
52355                :
52356                :Bool
52357                :fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
52358                :{
52359                :
52360                :#ifdef RENDER
52361                :
52362                :    PictureScreenPtr    ps;
52363                :
52364                :    if (!miPictureInit (pScreen, formats, nformats))
52365                :        return FALSE;
52366                :    ps = GetPictureScreen(pScreen);
52367                :    ps->Composite = fbComposite;
52368                :    ps->Glyphs = miGlyphs;
52369                :    ps->CompositeRects = miCompositeRects;
52370                :    ps->RasterizeTrapezoid = fbRasterizeTrapezoid;
52371                :    ps->AddTraps = fbAddTraps;
52372                :    ps->AddTriangles = fbAddTriangles;
52373                :
52374                :#endif /* RENDER */
52375                :
52376                :    return TRUE;
52377                :}
52378 /* 
52379  * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i830_render.c"
52380  * 
52381  *      3  0.0033
52382  */
52383
52384
52385                :/*
52386                : * Copyright Â© 2006 Intel Corporation
52387                : *
52388                : * Permission is hereby granted, free of charge, to any person obtaining a
52389                : * copy of this software and associated documentation files (the "Software"),
52390                : * to deal in the Software without restriction, including without limitation
52391                : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
52392                : * and/or sell copies of the Software, and to permit persons to whom the
52393                : * Software is furnished to do so, subject to the following conditions:
52394                : *
52395                : * The above copyright notice and this permission notice (including the next
52396                : * paragraph) shall be included in all copies or substantial portions of the
52397                : * Software.
52398                : *
52399                : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52400                : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52401                : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
52402                : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
52403                : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52404                : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52405                : * SOFTWARE.
52406                : *
52407                : * Authors:
52408                : *    Wang Zhenyu <zhenyu.z.wang@intel.com>
52409                : *    Eric Anholt <eric@anholt.net>
52410                : *
52411                : */
52412                :
52413                :#ifdef HAVE_CONFIG_H
52414                :#include "config.h"
52415                :#endif
52416                :
52417                :#include "xf86.h"
52418                :#include "i830.h"
52419                :#include "i830_reg.h"
52420                :
52421                :#ifdef I830DEBUG
52422                :#define DEBUG_I830FALLBACK 1
52423                :#endif
52424                :
52425                :#ifdef DEBUG_I830FALLBACK
52426                :#define I830FALLBACK(s, arg...)                         \
52427                :do {                                                    \
52428                :        DPRINTF(PFX, "EXA fallback: " s "\n", ##arg);   \
52429                :        return FALSE;                                   \
52430                :} while(0)
52431                :#else
52432                :#define I830FALLBACK(s, arg...)                         \
52433                :do {                                                    \
52434                :        return FALSE;                                   \
52435                :} while(0)
52436                :#endif
52437                :
52438                :struct blendinfo {
52439                :    Bool dst_alpha;
52440                :    Bool src_alpha;
52441                :    CARD32 src_blend;
52442                :    CARD32 dst_blend;
52443                :};
52444                :
52445                :struct formatinfo {
52446                :    int fmt;
52447                :    CARD32 card_fmt;
52448                :};
52449                :
52450                :#define TB0C_LAST_STAGE (1 << 31)
52451                :#define TB0C_RESULT_SCALE_1X            (0 << 29)
52452                :#define TB0C_RESULT_SCALE_2X            (1 << 29)
52453                :#define TB0C_RESULT_SCALE_4X            (2 << 29)
52454                :#define TB0C_OP_MODULE                  (3 << 25)
52455                :#define TB0C_OUTPUT_WRITE_CURRENT       (0 << 24)
52456                :#define TB0C_OUTPUT_WRITE_ACCUM         (1 << 24)
52457                :#define TB0C_ARG3_REPLICATE_ALPHA       (1<<23)
52458                :#define TB0C_ARG3_INVERT                (1<<22)
52459                :#define TB0C_ARG3_SEL_XXX
52460                :#define TB0C_ARG2_REPLICATE_ALPHA       (1<<17)
52461                :#define TB0C_ARG2_INVERT                (1<<16)
52462                :#define TB0C_ARG2_SEL_ONE               (0 << 12)
52463                :#define TB0C_ARG2_SEL_FACTOR            (1 << 12)
52464                :#define TB0C_ARG2_SEL_TEXEL0            (6 << 12)
52465                :#define TB0C_ARG2_SEL_TEXEL1            (7 << 12)
52466                :#define TB0C_ARG2_SEL_TEXEL2            (8 << 12)
52467                :#define TB0C_ARG2_SEL_TEXEL3            (9 << 12)
52468                :#define TB0C_ARG1_REPLICATE_ALPHA       (1<<11)
52469                :#define TB0C_ARG1_INVERT                (1<<10)
52470                :#define TB0C_ARG1_SEL_ONE               (0 << 6)
52471                :#define TB0C_ARG1_SEL_TEXEL0            (6 << 6)
52472                :#define TB0C_ARG1_SEL_TEXEL1            (7 << 6)
52473                :#define TB0C_ARG1_SEL_TEXEL2            (8 << 6)
52474                :#define TB0C_ARG1_SEL_TEXEL3            (9 << 6)
52475                :#define TB0C_ARG0_REPLICATE_ALPHA       (1<<5)
52476                :#define TB0C_ARG0_SEL_XXX
52477                :
52478                :#define TB0A_CTR_STAGE_ENABLE           (1<<31)
52479                :#define TB0A_RESULT_SCALE_1X            (0 << 29)
52480                :#define TB0A_RESULT_SCALE_2X            (1 << 29)
52481                :#define TB0A_RESULT_SCALE_4X            (2 << 29)
52482                :#define TB0A_OP_MODULE                  (3 << 25)
52483                :#define TB0A_OUTPUT_WRITE_CURRENT       (0<<24)
52484                :#define TB0A_OUTPUT_WRITE_ACCUM         (1<<24)
52485                :#define TB0A_CTR_STAGE_SEL_BITS_XXX
52486                :#define TB0A_ARG3_SEL_XXX
52487                :#define TB0A_ARG3_INVERT                (1<<17)
52488                :#define TB0A_ARG2_INVERT                (1<<16)
52489                :#define TB0A_ARG2_SEL_ONE               (0 << 12)
52490                :#define TB0A_ARG2_SEL_TEXEL0            (6 << 12)
52491                :#define TB0A_ARG2_SEL_TEXEL1            (7 << 12)
52492                :#define TB0A_ARG2_SEL_TEXEL2            (8 << 12)
52493                :#define TB0A_ARG2_SEL_TEXEL3            (9 << 12)
52494                :#define TB0A_ARG1_INVERT                (1<<10)
52495                :#define TB0A_ARG1_SEL_ONE               (0 << 6)
52496                :#define TB0A_ARG1_SEL_TEXEL0            (6 << 6)
52497                :#define TB0A_ARG1_SEL_TEXEL1            (7 << 6)
52498                :#define TB0A_ARG1_SEL_TEXEL2            (8 << 6)
52499                :#define TB0A_ARG1_SEL_TEXEL3            (9 << 6)
52500                :
52501                :static struct blendinfo i830_blend_op[] = {
52502                :    /* Clear */
52503                :    {0, 0, BLENDFACTOR_ZERO,            BLENDFACTOR_ZERO},
52504                :    /* Src */
52505                :    {0, 0, BLENDFACTOR_ONE,             BLENDFACTOR_ZERO},
52506                :    /* Dst */
52507                :    {0, 0, BLENDFACTOR_ZERO,            BLENDFACTOR_ONE},
52508                :    /* Over */
52509                :    {0, 1, BLENDFACTOR_ONE,             BLENDFACTOR_INV_SRC_ALPHA},
52510                :    /* OverReverse */
52511                :    {1, 0, BLENDFACTOR_INV_DST_ALPHA,   BLENDFACTOR_ONE},
52512                :    /* In */
52513                :    {1, 0, BLENDFACTOR_DST_ALPHA,       BLENDFACTOR_ZERO},
52514                :    /* InReverse */
52515                :    {0, 1, BLENDFACTOR_ZERO,            BLENDFACTOR_SRC_ALPHA},
52516                :    /* Out */
52517                :    {1, 0, BLENDFACTOR_INV_DST_ALPHA,   BLENDFACTOR_ZERO},
52518                :    /* OutReverse */
52519                :    {0, 1, BLENDFACTOR_ZERO,            BLENDFACTOR_INV_SRC_ALPHA},
52520                :    /* Atop */
52521                :    {1, 1, BLENDFACTOR_DST_ALPHA,       BLENDFACTOR_INV_SRC_ALPHA},
52522                :    /* AtopReverse */
52523                :    {1, 1, BLENDFACTOR_INV_DST_ALPHA,   BLENDFACTOR_SRC_ALPHA},
52524                :    /* Xor */
52525                :    {1, 1, BLENDFACTOR_INV_DST_ALPHA,   BLENDFACTOR_INV_SRC_ALPHA},
52526                :    /* Add */
52527                :    {0, 0, BLENDFACTOR_ONE,             BLENDFACTOR_ONE},
52528                :};
52529                :
52530                :static struct formatinfo i830_tex_formats[] = {
52531                :    {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
52532                :    {PICT_x8r8g8b8, MT_32BIT_XRGB8888 },
52533                :    {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
52534                :    {PICT_x8b8g8r8, MT_32BIT_XBGR8888 },
52535                :    {PICT_r5g6b5,   MT_16BIT_RGB565   },
52536                :    {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
52537                :    {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
52538                :    {PICT_a8,       MT_8BIT_A8        },
52539                :};
52540                :
52541                :static Bool i830_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
52542                :{
52543                :    switch (pDstPicture->format) {
52544                :    case PICT_a8r8g8b8:
52545                :    case PICT_x8r8g8b8:
52546                :        *dst_format = COLR_BUF_ARGB8888;
52547                :        break;
52548                :    case PICT_r5g6b5:
52549                :        *dst_format = COLR_BUF_RGB565;
52550                :        break;
52551                :    case PICT_a1r5g5b5:
52552                :    case PICT_x1r5g5b5:
52553                :        *dst_format = COLR_BUF_ARGB1555;
52554                :        break;
52555                :        /*
52556                :    case PICT_a8:
52557                :        *dst_format = COLR_BUF_8BIT;
52558                :        break;
52559                :        */
52560                :    case PICT_a4r4g4b4:
52561                :    case PICT_x4r4g4b4:
52562                :        *dst_format = COLR_BUF_ARGB4444;
52563                :        break;
52564                :    default:
52565                :        I830FALLBACK("Unsupported dest format 0x%x\n",
52566                :                     (int)pDstPicture->format);
52567                :    }
52568                :
52569                :    return TRUE;
52570                :}
52571                :
52572                :
52573                :static CARD32 i830_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format)
52574                :{
52575                :    CARD32 sblend, dblend;
52576                :
52577                :    sblend = i830_blend_op[op].src_blend;
52578                :    dblend = i830_blend_op[op].dst_blend;
52579                :
52580                :    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
52581                :     * it as always 1.
52582                :     */
52583                :    if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) {
52584                :        if (sblend == BLENDFACTOR_DST_ALPHA)
52585                :            sblend = BLENDFACTOR_ONE;
52586                :        else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
52587                :            sblend = BLENDFACTOR_ZERO;
52588                :    }
52589                :
52590                :    /* If the source alpha is being used, then we should only be in a case
52591                :     * where the source blend factor is 0, and the source blend value is the
52592                :     * mask channels multiplied by the source picture's alpha.
52593                :     */
52594                :    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) 
52595                :            && i830_blend_op[op].src_alpha) {
52596                :        if (dblend == BLENDFACTOR_SRC_ALPHA) {
52597                :            dblend = BLENDFACTOR_SRC_COLR;
52598                :        } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
52599                :            dblend = BLENDFACTOR_INV_SRC_COLR;
52600                :        }
52601                :    }
52602                :
52603                :    return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) |
52604                :        (dblend << S8_DST_BLEND_FACTOR_SHIFT);
52605                :}
52606                :
52607                :static Bool i830_check_composite_texture(PicturePtr pPict, int unit)
52608                :{
52609                :    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
52610                :    I830Ptr pI830 = I830PTR(pScrn);
52611                :    int w = pPict->pDrawable->width;
52612                :    int h = pPict->pDrawable->height;
52613                :    int i;
52614                :
52615                :    if ((w > 0x7ff) || (h > 0x7ff))
52616                :        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
52617                :
52618                :    for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
52619                :         i++)
52620                :    {
52621                :        if (i830_tex_formats[i].fmt == pPict->format)
52622                :            break;
52623                :    }
52624                :    if (i == sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]))
52625                :        I830FALLBACK("Unsupported picture format 0x%x\n",
52626                :                     (int)pPict->format);
52627                :
52628                :    if (IS_I830(pI830) || IS_845G(pI830)) {
52629                :        if (pPict->format == PICT_x8r8g8b8 || 
52630                :                pPict->format == PICT_x8b8g8r8 || 
52631                :                pPict->format == PICT_a8)
52632                :            I830FALLBACK("830/845G don't support a8, x8r8g8b8, x8b8g8r8\n");
52633                :    }
52634                :
52635                :    if (pPict->repeat && pPict->repeatType != RepeatNormal)
52636                :        I830FALLBACK("unsupport repeat type\n");
52637                :
52638                :    if (pPict->filter != PictFilterNearest &&
52639                :        pPict->filter != PictFilterBilinear)
52640                :    {
52641                :        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
52642                :    }
52643                :
52644                :    return TRUE;
52645                :}
52646                :
52647                :static CARD32
52648                :i8xx_get_card_format(PicturePtr pPict)
52649                :{
52650                :    int i;
52651                :    for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
52652                :            i++)
52653                :    {
52654                :        if (i830_tex_formats[i].fmt == pPict->format)
52655                :            break;
52656                :    }
52657                :    return i830_tex_formats[i].card_fmt;
52658                :}
52659                :
52660                :static Bool
52661                :i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
52662                :{
52663                :
52664                :    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
52665                :    I830Ptr pI830 = I830PTR(pScrn);
52666                :    CARD32 format, offset, pitch, filter;
52667                :    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
52668                :
52669                :    offset = intel_get_pixmap_offset(pPix);
52670                :    pitch = intel_get_pixmap_pitch(pPix);
52671                :    pI830->scale_units[unit][0] = pPix->drawable.width;
52672                :    pI830->scale_units[unit][1] = pPix->drawable.height;
52673                :    pI830->transform[unit] = pPict->transform;
52674                :
52675                :    format = i8xx_get_card_format(pPict);
52676                :
52677                :    if (pPict->repeat)
52678                :        wrap_mode = TEXCOORDMODE_WRAP;
52679                :
52680                :    switch (pPict->filter) {
52681                :    case PictFilterNearest:
52682                :        filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) |
52683                :                  (FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
52684                :        break;
52685                :    case PictFilterBilinear:
52686                :        filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) |
52687                :                  (FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
52688                :        break;
52689                :    default:
52690                :        filter = 0;
52691                :        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
52692                :    }
52693                :    filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 
52694                :
52695                :    {
52696                :        if (pPix->drawable.bitsPerPixel == 8)
52697                :            format |= MAPSURF_8BIT;
52698                :        else if (pPix->drawable.bitsPerPixel == 16)
52699                :            format |= MAPSURF_16BIT;
52700                :        else
52701                :            format |= MAPSURF_32BIT;
52702                :
52703                :        BEGIN_LP_RING(10);
52704                :        OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
52705                :        OUT_RING((offset & TM0S0_ADDRESS_MASK) | TM0S0_USE_FENCE); 
52706                :        OUT_RING(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
52707                :                ((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
52708                :        OUT_RING((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
52709                :        OUT_RING(filter);
52710                :        OUT_RING(0); /* default color */
52711                :        OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
52712                :                 ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
52713                :                 TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL |
52714                :                 TEXCOORD_ADDR_V_MODE(wrap_mode) |
52715                :                 ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
52716                :        /* map texel stream */
52717                :        OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD);
52718                :        if (unit == 0)
52719                :            OUT_RING(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
52720                :                    TEXBIND_SET1(TEXCOORDSRC_KEEP) |
52721                :                    TEXBIND_SET2(TEXCOORDSRC_KEEP) |
52722                :                    TEXBIND_SET3(TEXCOORDSRC_KEEP));
52723                :        else
52724                :            OUT_RING(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
52725                :                    TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
52726                :                    TEXBIND_SET2(TEXCOORDSRC_KEEP) |
52727                :                    TEXBIND_SET3(TEXCOORDSRC_KEEP));
52728                :        OUT_RING(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) |
52729                :                DISABLE_TEX_STREAM_BUMP | 
52730                :                ENABLE_TEX_STREAM_COORD_SET |
52731                :                TEX_STREAM_COORD_SET(unit) |
52732                :                ENABLE_TEX_STREAM_MAP_IDX |
52733                :                TEX_STREAM_MAP_IDX(unit));
52734                :        ADVANCE_LP_RING();
52735                :     }
52736                :
52737                :#ifdef I830DEBUG
52738                :    ErrorF("try to sync to show any errors...");
52739                :    I830Sync(pScrn);
52740                :#endif
52741                :
52742                :    return TRUE;
52743                :}
52744                :
52745                :Bool
52746                :i830_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
52747                :                     PicturePtr pDstPicture)
52748                :{
52749                :    CARD32 tmp1;
52750                :
52751                :    /* Check for unsupported compositing operations. */
52752                :    if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0]))
52753                :        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
52754                :
52755                :    if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
52756                :            PICT_FORMAT_RGB(pMaskPicture->format)) {
52757                :        /* Check if it's component alpha that relies on a source alpha and on
52758                :         * the source value.  We can only get one of those into the single
52759                :         * source value that we get to blend with.
52760                :         */
52761                :        if (i830_blend_op[op].src_alpha &&
52762                :            (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO))
52763                :                I830FALLBACK("Component alpha not supported with source "
52764                :                             "alpha and source value blending.\n");
52765                :    }
52766                :
52767                :    if (!i830_check_composite_texture(pSrcPicture, 0))
52768                :        I830FALLBACK("Check Src picture texture\n");
52769                :    if (pMaskPicture != NULL && !i830_check_composite_texture(pMaskPicture, 1))
52770                :        I830FALLBACK("Check Mask picture texture\n");
52771                :
52772                :    if (!i830_get_dest_format(pDstPicture, &tmp1))
52773                :        I830FALLBACK("Get Color buffer format\n");
52774                :
52775                :    return TRUE;
52776                :}
52777                :
52778                :Bool
52779                :i830_prepare_composite(int op, PicturePtr pSrcPicture,
52780                :                       PicturePtr pMaskPicture, PicturePtr pDstPicture,
52781                :                       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
52782                :{
52783                :    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
52784                :    I830Ptr pI830 = I830PTR(pScrn);
52785                :    CARD32 dst_format, dst_offset, dst_pitch;
52786                :
52787                :    IntelEmitInvarientState(pScrn);
52788                :    *pI830->last_3d = LAST_3D_RENDER;
52789                :
52790                :    i830_get_dest_format(pDstPicture, &dst_format);
52791                :    dst_offset = intel_get_pixmap_offset(pDst);
52792                :    dst_pitch = intel_get_pixmap_pitch(pDst);
52793                :
52794                :    if (!i830_texture_setup(pSrcPicture, pSrc, 0))
52795                :        I830FALLBACK("fail to setup src texture\n");
52796                :    if (pMask != NULL) {
52797                :        if (!i830_texture_setup(pMaskPicture, pMask, 1))
52798                :            I830FALLBACK("fail to setup mask texture\n");
52799                :    } else {
52800                :        pI830->transform[1] = NULL;
52801                :        pI830->scale_units[1][0] = -1;
52802                :        pI830->scale_units[1][1] = -1;
52803                :    }
52804                :
52805                :    {
52806                :        CARD32 cblend, ablend, blendctl, vf2;
52807                :
52808                :        BEGIN_LP_RING(30);
52809                :
52810                :        /* color buffer */
52811                :        OUT_RING(_3DSTATE_BUF_INFO_CMD);
52812                :        OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
52813                :        OUT_RING(BUF_3D_ADDR(dst_offset));
52814                :        OUT_RING(MI_NOOP);
52815                :
52816                :        OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
52817                :        OUT_RING(dst_format);
52818                :
52819                :        /* defaults */
52820                :        OUT_RING(_3DSTATE_DFLT_Z_CMD);
52821                :        OUT_RING(0);
52822                :
52823                :        OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
52824                :        OUT_RING(0);
52825                :
52826                :        OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
52827                :        OUT_RING(0);
52828                :
52829                :        OUT_RING(_3DSTATE_DRAW_RECT_CMD);
52830                :        OUT_RING(0);
52831                :        OUT_RING(0); /* ymin, xmin */
52832                :        OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
52833                :                DRAW_XMAX(pDst->drawable.width - 1));
52834                :        OUT_RING(0); /* yorig, xorig */
52835                :
52836                :        OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 
52837                :                I1_LOAD_S(3) | 1);
52838                :        if (pMask)
52839                :            vf2 = 2 << 12; /* 2 texture coord sets */
52840                :        else
52841                :            vf2 = 1 << 12;
52842                :        OUT_RING(vf2); /* TEXCOORDFMT_2D */
52843                :        OUT_RING(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
52844                :
52845                :        /* We use two pipes for color and alpha, and do (src In mask)
52846                :           in one stage. Arg1 is from src pict, and arg2 is from mask pict.
52847                :           Be sure to force 1.0 when src or mask pict has no alpha channel.
52848                :         */
52849                :        cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
52850                :                 TB0C_OUTPUT_WRITE_CURRENT;
52851                :        ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE |
52852                :                 TB0A_OUTPUT_WRITE_CURRENT;
52853                :
52854                :        if (PICT_FORMAT_A(pSrcPicture->format) != 0) {
52855                :            ablend |= TB0A_ARG1_SEL_TEXEL0;
52856                :            cblend |= TB0C_ARG1_SEL_TEXEL0;
52857                :        } else {
52858                :            ablend |= TB0A_ARG1_SEL_ONE;
52859                :            if (pMask && pMaskPicture->componentAlpha 
52860                :                    && PICT_FORMAT_RGB(pMaskPicture->format)
52861                :                    && i830_blend_op[op].src_alpha)
52862                :                cblend |= TB0C_ARG1_SEL_ONE;
52863                :            else
52864                :                cblend |= TB0C_ARG1_SEL_TEXEL0;
52865                :        }
52866                :
52867                :        if (pMask) {
52868                :            if (pMaskPicture->componentAlpha && 
52869                :                    PICT_FORMAT_RGB(pMaskPicture->format)) {
52870                :                if (i830_blend_op[op].src_alpha)
52871                :                    cblend |= (TB0C_ARG2_SEL_TEXEL1 | 
52872                :                            TB0C_ARG1_REPLICATE_ALPHA);
52873                :                else 
52874                :                    cblend |= TB0C_ARG2_SEL_TEXEL1;
52875                :            } else {
52876                :                if (PICT_FORMAT_A(pMaskPicture->format) != 0)
52877                :                    cblend |= (TB0C_ARG2_SEL_TEXEL1 | 
52878                :                            TB0C_ARG2_REPLICATE_ALPHA);
52879                :                else
52880                :                    cblend |= TB0C_ARG2_SEL_ONE;
52881                :            }
52882                :            if (PICT_FORMAT_A(pMaskPicture->format) != 0)
52883                :                ablend |= TB0A_ARG2_SEL_TEXEL1;
52884                :            else
52885                :                ablend |= TB0A_ARG2_SEL_ONE;
52886                :        } else {
52887                :            cblend |= TB0C_ARG2_SEL_ONE;
52888                :            ablend |= TB0A_ARG2_SEL_ONE;
52889                :        }
52890                :
52891                :        OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
52892                :                 LOAD_TEXTURE_BLEND_STAGE(0)|1);
52893                :        OUT_RING(cblend);
52894                :        OUT_RING(ablend);
52895                :        OUT_RING(0);
52896                :
52897                :        blendctl = i830_get_blend_cntl(op, pMaskPicture, pDstPicture->format);
52898                :        OUT_RING(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND);
52899                :        OUT_RING(MI_NOOP);
52900                :        OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
52901                :        OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | blendctl | 
52902                :                 S8_ENABLE_COLOR_BUFFER_WRITE);
52903                :
52904                :        OUT_RING(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP | 
52905                :                DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS | 
52906                :                DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST | 
52907                :                ENABLE_COLOR_BLEND | DISABLE_DEPTH_TEST);
52908                :        /* We have to explicitly say we don't want write disabled */
52909                :        OUT_RING(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK |
52910                :                DISABLE_STENCIL_WRITE | ENABLE_TEX_CACHE |
52911                :                DISABLE_DITHER | ENABLE_COLOR_WRITE |
52912                :                DISABLE_DEPTH_WRITE);
52913                :        ADVANCE_LP_RING();
52914                :    }
52915                :
52916                :#ifdef I830DEBUG
52917                :    Error("try to sync to show any errors...");
52918                :    I830Sync(pScrn);
52919                :#endif
52920                :
52921                :    return TRUE;
52922                :}
52923                :
52924                :
52925                :/**
52926                : * Do a single rectangle composite operation.
52927                : *
52928                : * This function is shared between i830 and i915 generation code.
52929                : */
52930                :void
52931                :i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
52932                :               int dstX, int dstY, int w, int h)
52933                :{
52934                :    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
52935                :    I830Ptr pI830 = I830PTR(pScrn);
52936                :    Bool has_mask;
52937                :    float src_x[3], src_y[3], mask_x[3], mask_y[3];
52938                :
52939                :    i830_get_transformed_coordinates(srcX, srcY,
52940                :                                     pI830->transform[0],
52941                :                                     &src_x[0], &src_y[0]);
52942                :    i830_get_transformed_coordinates(srcX, srcY + h,
52943                :                                     pI830->transform[0],
52944                :                                     &src_x[1], &src_y[1]);
52945                :    i830_get_transformed_coordinates(srcX + w, srcY + h,
52946                :                                     pI830->transform[0],
52947                :                                     &src_x[2], &src_y[2]);
52948                :
52949                :    if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
52950                :        has_mask = FALSE;
52951                :    } else {
52952                :        has_mask = TRUE;
52953                :        i830_get_transformed_coordinates(maskX, maskY,
52954                :                                         pI830->transform[1],
52955                :                                         &mask_x[0], &mask_y[0]);
52956                :        i830_get_transformed_coordinates(maskX, maskY + h,
52957                :                                         pI830->transform[1],
52958                :                                         &mask_x[1], &mask_y[1]);
52959                :        i830_get_transformed_coordinates(maskX + w, maskY + h,
52960                :                                         pI830->transform[1],
52961                :                                         &mask_x[2], &mask_y[2]);
52962                :    }
52963                :
52964                :    {
52965                :        int vertex_count;
52966                :
52967                :        if (has_mask)
52968                :                vertex_count = 3*6;
52969                :        else
52970                :                vertex_count = 3*4;
52971                :
52972                :        BEGIN_LP_RING(6+vertex_count);
52973                :
52974                :        OUT_RING(MI_NOOP);
52975                :        OUT_RING(MI_NOOP);
52976                :        OUT_RING(MI_NOOP);
52977                :        OUT_RING(MI_NOOP);
52978                :        OUT_RING(MI_NOOP);
52979                :
52980                :        OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (vertex_count-1));
52981                :
52982                :        OUT_RING_F(-0.125 + dstX + w);
52983                :        OUT_RING_F(-0.125 + dstY + h);
52984                :        OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
52985                :        OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
52986                :        if (has_mask) {
52987                :            OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
52988                :            OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
52989                :        }
52990                :
52991                :        OUT_RING_F(-0.125 + dstX);
52992                :        OUT_RING_F(-0.125 + dstY + h);
52993                :        OUT_RING_F(src_x[1] / pI830->scale_units[0][0]);
52994                :        OUT_RING_F(src_y[1] / pI830->scale_units[0][1]);
52995                :        if (has_mask) {
52996                :            OUT_RING_F(mask_x[1] / pI830->scale_units[1][0]);
52997                :            OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
52998                :        }
52999                :
53000                :        OUT_RING_F(-0.125 + dstX);
53001                :        OUT_RING_F(-0.125 + dstY);
53002                :        OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
53003                :        OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
53004                :        if (has_mask) {
53005                :            OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
53006                :            OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
53007                :        }
53008                :        ADVANCE_LP_RING();
53009                :    }
53010                :}
53011                :
53012                :/**
53013                : * Do any cleanup from the Composite operation.
53014                : *
53015                : * This is shared between i830 through i965.
53016                : */
53017                :void
53018                :i830_done_composite(PixmapPtr pDst)
53019      2  0.0022 :{ /* i830_done_composite total:      3  0.0033 */
53020                :    /* NO-OP */
53021      1  0.0011 :}
53022 /* 
53023  * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-edge.c"
53024  * 
53025  *      3  0.0033
53026  */
53027
53028
53029                :/*
53030                : * $Id$
53031                : *
53032                : * Copyright Â© 2004 Keith Packard
53033                : *
53034                : * Permission to use, copy, modify, distribute, and sell this software and its
53035                : * documentation for any purpose is hereby granted without fee, provided that
53036                : * the above copyright notice appear in all copies and that both that
53037                : * copyright notice and this permission notice appear in supporting
53038                : * documentation, and that the name of Keith Packard not be used in
53039                : * advertising or publicity pertaining to distribution of the software without
53040                : * specific, written prior permission.  Keith Packard makes no
53041                : * representations about the suitability of this software for any purpose.  It
53042                : * is provided "as is" without express or implied warranty.
53043                : *
53044                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
53045                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
53046                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
53047                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
53048                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
53049                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
53050                : * PERFORMANCE OF THIS SOFTWARE.
53051                : */
53052                :#include <config.h>
53053                :#include <string.h>
53054                :#include "pixman.h"
53055                :#include "pixman-private.h"
53056                :
53057                :#ifdef PIXMAN_FB_ACCESSORS
53058                :#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
53059                :#else
53060                :#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
53061                :#endif
53062                :
53063                :/*
53064                : * 4 bit alpha
53065                : */
53066                :
53067                :#define N_BITS  4
53068                :#define rasterizeEdges  fbRasterizeEdges4
53069                :
53070                :#if BITMAP_BIT_ORDER == LSBFirst
53071                :#define Shift4(o)       ((o) << 2)
53072                :#else
53073                :#define Shift4(o)       ((1-(o)) << 2)
53074                :#endif
53075                :
53076                :#define Get4(x,o)       (((x) >> Shift4(o)) & 0xf)
53077                :#define Put4(x,o,v)     (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o)))
53078                :
53079                :#define DefineAlpha(line,x)                          \
53080                :    uint8_t   *__ap = (uint8_t *) line + ((x) >> 1); \
53081                :    int     __ao = (x) & 1
53082                :
53083                :#define StepAlpha       ((__ap += __ao), (__ao ^= 1))
53084                :
53085                :#define AddAlpha(a) {                                           \
53086                :        uint8_t   __o = READ(__ap);                             \
53087                :        uint8_t   __a = (a) + Get4(__o, __ao);                  \
53088                :        WRITE(__ap, Put4 (__o, __ao, __a | (0 - ((__a) >> 4))));        \
53089                :    }
53090                :
53091                :#include "pixman-edge-imp.h"
53092                :
53093                :#undef AddAlpha
53094                :#undef StepAlpha
53095                :#undef DefineAlpha
53096                :#undef rasterizeEdges
53097                :#undef N_BITS
53098                :
53099                :
53100                :/*
53101                : * 1 bit alpha
53102                : */
53103                :
53104                :#define N_BITS 1
53105                :#define rasterizeEdges  fbRasterizeEdges1
53106                :
53107                :#include "pixman-edge-imp.h"
53108                :
53109                :#undef rasterizeEdges
53110                :#undef N_BITS
53111                :
53112                :/*
53113                : * 8 bit alpha
53114                : */
53115                :
53116                :static inline uint8_t
53117                :clip255 (int x)
53118                :{
53119                :    if (x > 255) return 255;
53120                :    return x;
53121                :}
53122                :
53123                :#define add_saturate_8(buf,val,length)                          \
53124                :    do {                                                        \
53125                :        int i__ = (length);                                     \
53126                :        uint8_t *buf__ = (buf);                                 \
53127                :        int val__ = (val);                                      \
53128                :                                                                \
53129                :        while (i__--)                                           \
53130                :        {                                                       \
53131                :            WRITE((buf__), clip255 (READ((buf__)) + (val__)));  \
53132                :            (buf__)++;                                          \
53133                :        }                                                       \
53134                :    } while (0)
53135                :
53136                :/*
53137                : * We want to detect the case where we add the same value to a long
53138                : * span of pixels.  The triangles on the end are filled in while we
53139                : * count how many sub-pixel scanlines contribute to the middle section.
53140                : *
53141                : *                 +--------------------------+
53142                : *  fill_height =|   \                      /
53143                : *                     +------------------+
53144                : *                      |================|
53145                : *                   fill_start       fill_end
53146                : */
53147                :static void
53148                :fbRasterizeEdges8 (pixman_image_t       *image,
53149                :                   pixman_edge_t        *l,
53150                :                   pixman_edge_t        *r,
53151                :                   pixman_fixed_t       t,
53152                :                   pixman_fixed_t       b)
53153                :{
53154                :    pixman_fixed_t  y = t;
53155                :    uint32_t  *line;
53156                :    int fill_start = -1, fill_end = -1;
53157                :    int fill_size = 0;
53158                :    uint32_t *buf = (image)->bits.bits;         
53159                :    uint32_t stride = (image)->bits.rowstride;  
53160                :    uint32_t width = (image)->bits.width;
53161                :    
53162                :    line = buf + pixman_fixed_to_int (y) * stride;
53163                :    
53164                :    for (;;)
53165                :    {
53166                :        uint8_t *ap = (uint8_t *) line;
53167                :        pixman_fixed_t  lx, rx;
53168                :        int     lxi, rxi;
53169                :        
53170                :        /* clip X */
53171                :        lx = l->x;
53172                :        if (lx < 0)
53173                :            lx = 0;
53174                :        rx = r->x;
53175                :        if (pixman_fixed_to_int (rx) >= width)
53176                :            rx = pixman_int_to_fixed (width);
53177                :        
53178                :        /* Skip empty (or backwards) sections */
53179                :        if (rx > lx)
53180                :        {
53181                :            int lxs, rxs;
53182                :            
53183                :            /* Find pixel bounds for span. */
53184                :            lxi = pixman_fixed_to_int (lx);
53185                :            rxi = pixman_fixed_to_int (rx);
53186                :            
53187                :            /* Sample coverage for edge pixels */
53188                :            lxs = RenderSamplesX (lx, 8);
53189                :            rxs = RenderSamplesX (rx, 8);
53190                :            
53191                :            /* Add coverage across row */
53192                :            if (lxi == rxi)
53193                :            {
53194                :                WRITE(ap +lxi, clip255 (READ(ap + lxi) + rxs - lxs));
53195                :            }
53196                :            else
53197                :            {
53198                :                WRITE(ap + lxi, clip255 (READ(ap + lxi) + N_X_FRAC(8) - lxs));
53199                :                
53200                :                /* Move forward so that lxi/rxi is the pixel span */
53201                :                lxi++;
53202                :                
53203                :                /* Don't bother trying to optimize the fill unless
53204                :                 * the span is longer than 4 pixels. */
53205                :                if (rxi - lxi > 4)
53206                :                {
53207                :                    if (fill_start < 0)
53208                :                    {
53209                :                        fill_start = lxi;
53210                :                        fill_end = rxi;
53211                :                        fill_size++;
53212                :                    }
53213                :                    else
53214                :                    {
53215                :                        if (lxi >= fill_end || rxi < fill_start)
53216                :                        {
53217                :                            /* We're beyond what we saved, just fill it */
53218                :                            add_saturate_8 (ap + fill_start,
53219                :                                            fill_size * N_X_FRAC(8),
53220                :                                            fill_end - fill_start);
53221                :                            fill_start = lxi;
53222                :                            fill_end = rxi;
53223                :                            fill_size = 1;
53224                :                        }
53225                :                        else
53226                :                        {
53227                :                            /* Update fill_start */
53228                :                            if (lxi > fill_start)
53229                :                            {
53230                :                                add_saturate_8 (ap + fill_start,
53231                :                                                fill_size * N_X_FRAC(8),
53232                :                                                lxi - fill_start);
53233                :                                fill_start = lxi;
53234                :                            }
53235                :                            else if (lxi < fill_start)
53236                :                            {
53237                :                                add_saturate_8 (ap + lxi, N_X_FRAC(8),
53238                :                                                fill_start - lxi);
53239                :                            }
53240                :                            
53241                :                            /* Update fill_end */
53242                :                            if (rxi < fill_end)
53243                :                            {
53244                :                                add_saturate_8 (ap + rxi,
53245                :                                                fill_size * N_X_FRAC(8),
53246                :                                                fill_end - rxi);
53247                :                                fill_end = rxi;
53248                :                            }
53249                :                            else if (fill_end < rxi)
53250                :                            {
53251                :                                add_saturate_8 (ap + fill_end,
53252                :                                                N_X_FRAC(8),
53253                :                                                rxi - fill_end);
53254                :                            }
53255                :                            fill_size++;
53256                :                        }
53257                :                    }
53258                :                }
53259                :                else
53260                :                {
53261                :                    add_saturate_8 (ap + lxi, N_X_FRAC(8), rxi - lxi);
53262                :                }
53263                :                
53264                :                /* Do not add in a 0 alpha here. This check is
53265                :                 * necessary to avoid a buffer overrun, (when rx
53266                :                 * is exactly on a pixel boundary). */
53267                :                if (rxs)
53268                :                    WRITE(ap + rxi, clip255 (READ(ap + rxi) + rxs));
53269                :            }
53270                :        }
53271                :        
53272                :        if (y == b) {
53273                :            /* We're done, make sure we clean up any remaining fill. */
53274                :            if (fill_start != fill_end) {
53275                :                if (fill_size == N_Y_FRAC(8))
53276                :                {
53277                :                    MEMSET_WRAPPED (ap + fill_start, 0xff, fill_end - fill_start);
53278                :                }
53279                :                else
53280                :                {
53281                :                    add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8),
53282                :                                    fill_end - fill_start);
53283                :                }
53284                :            }
53285                :            break;
53286                :        }
53287                :        
53288                :        if (pixman_fixed_frac (y) != Y_FRAC_LAST(8))
53289                :        {
53290                :            RenderEdgeStepSmall (l);
53291                :            RenderEdgeStepSmall (r);
53292                :            y += STEP_Y_SMALL(8);
53293                :        }
53294                :        else
53295                :        {
53296                :            RenderEdgeStepBig (l);
53297                :            RenderEdgeStepBig (r);
53298                :            y += STEP_Y_BIG(8);
53299                :            if (fill_start != fill_end)
53300                :            {
53301                :                if (fill_size == N_Y_FRAC(8))
53302                :                {
53303                :                    MEMSET_WRAPPED (ap + fill_start, 0xff, fill_end - fill_start);
53304                :                }
53305                :                else
53306                :                {
53307                :                    add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8),
53308                :                                    fill_end - fill_start);
53309                :                }
53310                :                fill_start = fill_end = -1;
53311                :                fill_size = 0;
53312                :            }
53313                :            line += stride;
53314                :        }
53315                :    }
53316                :}
53317                :
53318                :#ifndef PIXMAN_FB_ACCESSORS
53319                :static
53320                :#endif
53321                :void
53322                :PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
53323                :                        pixman_edge_t   *l,
53324                :                        pixman_edge_t   *r,
53325                :                        pixman_fixed_t  t,
53326                :                        pixman_fixed_t  b)
53327                :{
53328                :    switch (PIXMAN_FORMAT_BPP (image->bits.format))
53329                :    {
53330                :    case 1:
53331                :        fbRasterizeEdges1 (image, l, r, t, b);
53332                :        break;
53333                :    case 4:
53334                :        fbRasterizeEdges4 (image, l, r, t, b);
53335                :        break;
53336                :    case 8:
53337                :        fbRasterizeEdges8 (image, l, r, t, b);
53338                :        break;
53339                :    }
53340                :}
53341                :
53342                :#ifndef PIXMAN_FB_ACCESSORS
53343                :
53344                :void
53345                :pixman_rasterize_edges (pixman_image_t *image,
53346                :                        pixman_edge_t   *l,
53347                :                        pixman_edge_t   *r,
53348                :                        pixman_fixed_t  t,
53349                :                        pixman_fixed_t  b)
53350                :{ /* pixman_rasterize_edges total:   5402  5.8849 */
53351      2  0.0022 :    if (image->common.read_func || image->common.write_func)
53352                :    {
53353                :        return pixman_rasterize_edges_accessors (image, l, r, t, b);
53354                :    }
53355                :    else
53356                :    {
53357                :        return pixman_rasterize_edges_no_accessors (image, l, r, t, b);
53358                :    }
53359      1  0.0011 :}
53360                :
53361                :#endif
53362 /* 
53363  * Total samples for file : "/home/cworth/src/xorg/xserver/os/WaitFor.c"
53364  * 
53365  *      2  0.0022
53366  */
53367
53368
53369                :/***********************************************************
53370                :
53371                :Copyright 1987, 1998  The Open Group
53372                :
53373                :Permission to use, copy, modify, distribute, and sell this software and its
53374                :documentation for any purpose is hereby granted without fee, provided that
53375                :the above copyright notice appear in all copies and that both that
53376                :copyright notice and this permission notice appear in supporting
53377                :documentation.
53378                :
53379                :The above copyright notice and this permission notice shall be included in
53380                :all copies or substantial portions of the Software.
53381                :
53382                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53383                :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53384                :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
53385                :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
53386                :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
53387                :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
53388                :
53389                :Except as contained in this notice, the name of The Open Group shall not be
53390                :used in advertising or otherwise to promote the sale, use or other dealings
53391                :in this Software without prior written authorization from The Open Group.
53392                :
53393                :
53394                :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
53395                :
53396                :                        All Rights Reserved
53397                :
53398                :Permission to use, copy, modify, and distribute this software and its 
53399                :documentation for any purpose and without fee is hereby granted, 
53400                :provided that the above copyright notice appear in all copies and that
53401                :both that copyright notice and this permission notice appear in 
53402                :supporting documentation, and that the name of Digital not be
53403                :used in advertising or publicity pertaining to distribution of the
53404                :software without specific, written prior permission.  
53405                :
53406                :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
53407                :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
53408                :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
53409                :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
53410                :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
53411                :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53412                :SOFTWARE.
53413                :
53414                :******************************************************************/
53415                :
53416                :
53417                :/*****************************************************************
53418                : * OS Dependent input routines:
53419                : *
53420                : *  WaitForSomething
53421                : *  TimerForce, TimerSet, TimerCheck, TimerFree
53422                : *
53423                : *****************************************************************/
53424                :
53425                :#ifdef HAVE_DIX_CONFIG_H
53426                :#include <dix-config.h>
53427                :#endif
53428                :
53429                :#ifdef WIN32
53430                :#include <X11/Xwinsock.h>
53431                :#endif
53432                :#include <X11/Xos.h>                    /* for strings, fcntl, time */
53433                :#include <errno.h>
53434                :#include <stdio.h>
53435                :#include <X11/X.h>
53436                :#include "misc.h"
53437                :
53438                :#include "osdep.h"
53439                :#include <X11/Xpoll.h>
53440                :#include "dixstruct.h"
53441                :#include "opaque.h"
53442                :#ifdef DPMSExtension
53443                :#include "dpmsproc.h"
53444                :#endif
53445                :
53446                :#ifdef WIN32
53447                :/* Error codes from windows sockets differ from fileio error codes  */
53448                :#undef EINTR
53449                :#define EINTR WSAEINTR
53450                :#undef EINVAL
53451                :#define EINVAL WSAEINVAL
53452                :#undef EBADF
53453                :#define EBADF WSAENOTSOCK
53454                :/* Windows select does not set errno. Use GetErrno as wrapper for 
53455                :   WSAGetLastError */
53456                :#define GetErrno WSAGetLastError
53457                :#else
53458                :/* This is just a fallback to errno to hide the differences between unix and
53459                :   Windows in the code */
53460                :#define GetErrno() errno
53461                :#endif
53462                :
53463                :/* modifications by raphael */
53464                :int
53465                :mffs(fd_mask mask)
53466                :{
53467                :    int i;
53468                :
53469                :    if (!mask) return 0;
53470                :    i = 1;
53471                :    while (!(mask & 1))
53472                :    {
53473                :        i++;
53474                :        mask >>= 1;
53475                :    }
53476                :    return i;
53477                :}
53478                :
53479                :#ifdef DPMSExtension
53480                :#define DPMS_SERVER
53481                :#include <X11/extensions/dpms.h>
53482                :#endif
53483                :
53484                :struct _OsTimerRec {
53485                :    OsTimerPtr          next;
53486                :    CARD32              expires;
53487                :    CARD32              delta;
53488                :    OsTimerCallback     callback;
53489                :    pointer             arg;
53490                :};
53491                :
53492                :static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
53493                :static void CheckAllTimers(void);
53494                :static OsTimerPtr timers = NULL;
53495                :
53496                :/*****************
53497                : * WaitForSomething:
53498                : *     Make the server suspend until there is
53499                : *      1. data from clients or
53500                : *      2. input events available or
53501                : *      3. ddx notices something of interest (graphics
53502                : *         queue ready, etc.) or
53503                : *      4. clients that have buffered replies/events are ready
53504                : *
53505                : *     If the time between INPUT events is
53506                : *     greater than ScreenSaverTime, the display is turned off (or
53507                : *     saved, depending on the hardware).  So, WaitForSomething()
53508                : *     has to handle this also (that's why the select() has a timeout.
53509                : *     For more info on ClientsWithInput, see ReadRequestFromClient().
53510                : *     pClientsReady is an array to store ready client->index values into.
53511                : *****************/
53512                :
53513                :int
53514                :WaitForSomething(int *pClientsReady)
53515                :{ /* WaitForSomething total:      2  0.0022 */
53516                :    int i;
53517                :    struct timeval waittime, *wt;
53518                :    INT32 timeout = 0;
53519                :    fd_set clientsReadable;
53520                :    fd_set clientsWritable;
53521                :    int curclient;
53522                :    int selecterr;
53523                :    int nready;
53524                :    fd_set devicesReadable;
53525                :    CARD32 now = 0;
53526                :#ifdef SMART_SCHEDULE
53527                :    Bool    someReady = FALSE;
53528                :#endif
53529                :
53530                :    FD_ZERO(&clientsReadable);
53531                :
53532                :    /* We need a while loop here to handle 
53533                :       crashed connections and the screen saver timeout */
53534                :    while (1)
53535                :    {
53536                :        /* deal with any blocked jobs */
53537                :        if (workQueue)
53538                :            ProcessWorkQueue();
53539                :        if (XFD_ANYSET (&ClientsWithInput))
53540                :        {
53541                :#ifdef SMART_SCHEDULE
53542                :            if (!SmartScheduleDisable)
53543                :            {
53544                :                someReady = TRUE;
53545                :                waittime.tv_sec = 0;
53546                :                waittime.tv_usec = 0;
53547                :                wt = &waittime;
53548                :            }
53549                :            else
53550                :#endif
53551                :            {
53552                :                XFD_COPYSET (&ClientsWithInput, &clientsReadable);
53553                :                break;
53554                :            }
53555                :        }
53556                :#ifdef SMART_SCHEDULE
53557                :        if (someReady)
53558                :        {
53559                :            XFD_COPYSET(&AllSockets, &LastSelectMask);
53560                :            XFD_UNSET(&LastSelectMask, &ClientsWithInput);
53561                :        }
53562                :        else
53563                :        {
53564                :#endif
53565                :        wt = NULL;
53566                :        if (timers)
53567                :        {
53568                :            now = GetTimeInMillis();
53569                :            timeout = timers->expires - now;
53570                :            if (timeout > 0 && timeout > timers->delta + 250) {
53571                :                /* time has rewound.  reset the timers. */
53572                :                CheckAllTimers();
53573                :            }
53574                :
53575                :            if (timers) {
53576                :                timeout = timers->expires - now;
53577                :                if (timeout < 0)
53578                :                    timeout = 0;
53579                :                waittime.tv_sec = timeout / MILLI_PER_SECOND;
53580                :                waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
53581                :                                   (1000000 / MILLI_PER_SECOND);
53582                :                wt = &waittime;
53583                :            }
53584                :        }
53585                :        XFD_COPYSET(&AllSockets, &LastSelectMask);
53586                :#ifdef SMART_SCHEDULE
53587                :        }
53588                :        SmartScheduleIdle = TRUE;
53589                :#endif
53590                :        BlockHandler((pointer)&wt, (pointer)&LastSelectMask);
53591                :        if (NewOutputPending)
53592                :            FlushAllOutput();
53593                :        /* keep this check close to select() call to minimize race */
53594                :        if (dispatchException)
53595                :            i = -1;
53596                :        else if (AnyClientsWriteBlocked)
53597                :        {
53598                :            XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
53599                :            i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
53600                :        }
53601                :        else 
53602                :        {
53603      1  0.0011 :            i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
53604                :        }
53605                :        selecterr = GetErrno();
53606                :        WakeupHandler(i, (pointer)&LastSelectMask);
53607                :#ifdef SMART_SCHEDULE
53608                :        if (i >= 0)
53609                :        {
53610                :            SmartScheduleIdle = FALSE;
53611                :            SmartScheduleIdleCount = 0;
53612                :            if (SmartScheduleTimerStopped)
53613                :                (void) SmartScheduleStartTimer ();
53614                :        }
53615                :#endif
53616                :        if (i <= 0) /* An error or timeout occurred */
53617                :        {
53618                :            if (dispatchException)
53619                :                return 0;
53620                :            if (i < 0) 
53621                :            {
53622                :                if (selecterr == EBADF)    /* Some client disconnected */
53623                :                {
53624                :                    CheckConnections ();
53625                :                    if (! XFD_ANYSET (&AllClients))
53626                :                        return 0;
53627                :                }
53628                :                else if (selecterr == EINVAL)
53629                :                {
53630                :                    FatalError("WaitForSomething(): select: errno=%d\n",
53631                :                        selecterr);
53632                :            }
53633                :                else if (selecterr != EINTR)
53634                :                {
53635                :                    ErrorF("WaitForSomething(): select: errno=%d\n",
53636                :                        selecterr);
53637                :                }
53638                :            }
53639                :#ifdef SMART_SCHEDULE
53640                :            else if (someReady)
53641                :            {
53642                :                /*
53643                :                 * If no-one else is home, bail quickly
53644                :                 */
53645                :                XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
53646                :                XFD_COPYSET(&ClientsWithInput, &clientsReadable);
53647                :                break;
53648                :            }
53649                :#endif
53650                :            if (*checkForInput[0] != *checkForInput[1])
53651                :                return 0;
53652                :
53653                :            if (timers)
53654                :            {
53655                :                int expired = 0;
53656                :                now = GetTimeInMillis();
53657                :                if ((int) (timers->expires - now) <= 0)
53658                :                    expired = 1;
53659                :
53660                :                while (timers && (int) (timers->expires - now) <= 0)
53661                :                    DoTimer(timers, now, &timers);
53662                :
53663                :                if (expired)
53664                :                    return 0;
53665                :            }
53666                :        }
53667                :        else
53668                :        {
53669                :            fd_set tmp_set;
53670                :
53671                :            if (*checkForInput[0] == *checkForInput[1]) {
53672                :                if (timers)
53673                :                {
53674                :                    int expired = 0;
53675                :                    now = GetTimeInMillis();
53676                :                    if ((int) (timers->expires - now) <= 0)
53677                :                        expired = 1;
53678                :
53679                :                    while (timers && (int) (timers->expires - now) <= 0)
53680                :                        DoTimer(timers, now, &timers);
53681                :
53682                :                    if (expired)
53683                :                        return 0;
53684                :                }
53685                :            }
53686                :#ifdef SMART_SCHEDULE
53687                :            if (someReady)
53688                :                XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
53689                :#endif      
53690                :            if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable))
53691                :            {
53692                :                NewOutputPending = TRUE;
53693                :                XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
53694                :                XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
53695                :                if (! XFD_ANYSET(&ClientsWriteBlocked))
53696                :                    AnyClientsWriteBlocked = FALSE;
53697                :            }
53698                :
53699                :            XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices);
53700                :            XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); 
53701                :            XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections);
53702                :            if (XFD_ANYSET(&tmp_set))
53703                :                QueueWorkProc(EstablishNewConnections, NULL,
53704                :                              (pointer)&LastSelectMask);
53705                :
53706                :            if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable))
53707                :                break;
53708                :#ifdef WIN32
53709                :            /* Windows keyboard and mouse events are added to the input queue
53710                :               in Block- and WakupHandlers. There is no device to check if  
53711                :               data is ready. So check here if new input is available */
53712                :            if (*checkForInput[0] != *checkForInput[1])
53713                :                return 0;
53714                :#endif
53715                :        }
53716                :    }
53717                :
53718                :    nready = 0;
53719                :    if (XFD_ANYSET (&clientsReadable))
53720                :    {
53721                :#ifndef WIN32
53722                :        for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
53723                :        {
53724                :            int highest_priority = 0;
53725                :
53726                :            while (clientsReadable.fds_bits[i])
53727                :            {
53728                :                int client_priority, client_index;
53729                :
53730                :                curclient = ffs (clientsReadable.fds_bits[i]) - 1;
53731      1  0.0011 :                client_index = /* raphael: modified */
53732                :                        ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))];
53733                :#else
53734                :        int highest_priority = 0;
53735                :        fd_set savedClientsReadable;
53736                :        XFD_COPYSET(&clientsReadable, &savedClientsReadable);
53737                :        for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++)
53738                :        {
53739                :            int client_priority, client_index;
53740                :
53741                :            curclient = XFD_FD(&savedClientsReadable, i);
53742                :            client_index = GetConnectionTranslation(curclient);
53743                :#endif
53744                :#ifdef XSYNC
53745                :                /*  We implement "strict" priorities.
53746                :                 *  Only the highest priority client is returned to
53747                :                 *  dix.  If multiple clients at the same priority are
53748                :                 *  ready, they are all returned.  This means that an
53749                :                 *  aggressive client could take over the server.
53750                :                 *  This was not considered a big problem because
53751                :                 *  aggressive clients can hose the server in so many 
53752                :                 *  other ways :)
53753                :                 */
53754                :                client_priority = clients[client_index]->priority;
53755                :                if (nready == 0 || client_priority > highest_priority)
53756                :                {
53757                :                    /*  Either we found the first client, or we found
53758                :                     *  a client whose priority is greater than all others
53759                :                     *  that have been found so far.  Either way, we want 
53760                :                     *  to initialize the list of clients to contain just
53761                :                     *  this client.
53762                :                     */
53763                :                    pClientsReady[0] = client_index;
53764                :                    highest_priority = client_priority;
53765                :                    nready = 1;
53766                :                }
53767                :                /*  the following if makes sure that multiple same-priority 
53768                :                 *  clients get batched together
53769                :                 */
53770                :                else if (client_priority == highest_priority)
53771                :#endif
53772                :                {
53773                :                    pClientsReady[nready++] = client_index;
53774                :                }
53775                :#ifndef WIN32
53776                :                clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient);
53777                :            }
53778                :#else
53779                :            FD_CLR(curclient, &clientsReadable);
53780                :#endif
53781                :        }
53782                :    }
53783                :    return nready;
53784                :}
53785                :
53786                :#if 0
53787                :/*
53788                : * This is not always a macro.
53789                : */
53790                :ANYSET(FdMask *src)
53791                :{
53792                :    int i;
53793                :
53794                :    for (i=0; i<mskcnt; i++)
53795                :        if (src[ i ])
53796                :            return (TRUE);
53797                :    return (FALSE);
53798                :}
53799                :#endif
53800                :
53801                :/* If time has rewound, re-run every affected timer.
53802                : * Timers might drop out of the list, so we have to restart every time. */
53803                :static void
53804                :CheckAllTimers(void)
53805                :{
53806                :    OsTimerPtr timer;
53807                :    CARD32 now;
53808                :
53809                :start:
53810                :    now = GetTimeInMillis();
53811                :
53812                :    for (timer = timers; timer; timer = timer->next) {
53813                :        if (timer->expires - now > timer->delta + 250) {
53814                :            TimerForce(timer);
53815                :            goto start;
53816                :        }
53817                :    }
53818                :}
53819                :
53820                :static void
53821                :DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
53822                :{
53823                :    CARD32 newTime;
53824                :
53825                :    *prev = timer->next;
53826                :    timer->next = NULL;
53827                :    newTime = (*timer->callback)(timer, now, timer->arg);
53828                :    if (newTime)
53829                :        TimerSet(timer, 0, newTime, timer->callback, timer->arg);
53830                :}
53831                :
53832                :_X_EXPORT OsTimerPtr
53833                :TimerSet(OsTimerPtr timer, int flags, CARD32 millis, 
53834                :    OsTimerCallback func, pointer arg)
53835                :{
53836                :    register OsTimerPtr *prev;
53837                :    CARD32 now = GetTimeInMillis();
53838                :
53839                :    if (!timer)
53840                :    {
53841                :        timer = (OsTimerPtr)xalloc(sizeof(struct _OsTimerRec));
53842                :        if (!timer)
53843                :            return NULL;
53844                :    }
53845                :    else
53846                :    {
53847                :        for (prev = &timers; *prev; prev = &(*prev)->next)
53848                :        {
53849                :            if (*prev == timer)
53850                :            {
53851                :                *prev = timer->next;
53852                :                if (flags & TimerForceOld)
53853                :                    (void)(*timer->callback)(timer, now, timer->arg);
53854                :                break;
53855                :            }
53856                :        }
53857                :    }
53858                :    if (!millis)
53859                :        return timer;
53860                :    if (flags & TimerAbsolute) {
53861                :        timer->delta = millis - now;
53862                :    }
53863                :    else {
53864                :        timer->delta = millis;
53865                :        millis += now;
53866                :    }
53867                :    timer->expires = millis;
53868                :    timer->callback = func;
53869                :    timer->arg = arg;
53870                :    if ((int) (millis - now) <= 0)
53871                :    {
53872                :        timer->next = NULL;
53873                :        millis = (*timer->callback)(timer, now, timer->arg);
53874                :        if (!millis)
53875                :            return timer;
53876                :    }
53877                :    for (prev = &timers;
53878                :         *prev && (int) ((*prev)->expires - millis) <= 0;
53879                :         prev = &(*prev)->next)
53880                :        ;
53881                :    timer->next = *prev;
53882                :    *prev = timer;
53883                :    return timer;
53884                :}
53885                :
53886                :Bool
53887                :TimerForce(OsTimerPtr timer)
53888                :{
53889                :    OsTimerPtr *prev;
53890                :
53891                :    for (prev = &timers; *prev; prev = &(*prev)->next)
53892                :    {
53893                :        if (*prev == timer)
53894                :        {
53895                :            DoTimer(timer, GetTimeInMillis(), prev);
53896                :            return TRUE;
53897                :        }
53898                :    }
53899                :    return FALSE;
53900                :}
53901                :
53902                :
53903                :_X_EXPORT void
53904                :TimerCancel(OsTimerPtr timer)
53905                :{
53906                :    OsTimerPtr *prev;
53907                :
53908                :    if (!timer)
53909                :        return;
53910                :    for (prev = &timers; *prev; prev = &(*prev)->next)
53911                :    {
53912                :        if (*prev == timer)
53913                :        {
53914                :            *prev = timer->next;
53915                :            break;
53916                :        }
53917                :    }
53918                :}
53919                :
53920                :_X_EXPORT void
53921                :TimerFree(OsTimerPtr timer)
53922                :{
53923                :    if (!timer)
53924                :        return;
53925                :    TimerCancel(timer);
53926                :    xfree(timer);
53927                :}
53928                :
53929                :void
53930                :TimerCheck(void)
53931                :{
53932                :    CARD32 now = GetTimeInMillis();
53933                :
53934                :    while (timers && (int) (timers->expires - now) <= 0)
53935                :        DoTimer(timers, now, &timers);
53936                :}
53937                :
53938                :void
53939                :TimerInit(void)
53940                :{
53941                :    OsTimerPtr timer;
53942                :
53943                :    while ((timer = timers))
53944                :    {
53945                :        timers = timer->next;
53946                :        xfree(timer);
53947                :    }
53948                :}
53949                :
53950                :#ifdef DPMSExtension
53951                :
53952                :#define DPMS_CHECK_MODE(mode,time)\
53953                :    if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
53954                :        DPMSSet(mode);
53955                :
53956                :#define DPMS_CHECK_TIMEOUT(time)\
53957                :    if (time > 0 && (time - timeout) > 0)\
53958                :        return time - timeout;
53959                :
53960                :static CARD32
53961                :NextDPMSTimeout(INT32 timeout)
53962                :{
53963                :    /*
53964                :     * Return the amount of time remaining until we should set
53965                :     * the next power level. Fallthroughs are intentional.
53966                :     */
53967                :    switch (DPMSPowerLevel)
53968                :    {
53969                :        case DPMSModeOn:
53970                :            DPMS_CHECK_TIMEOUT(DPMSStandbyTime)
53971                :
53972                :        case DPMSModeStandby:
53973                :            DPMS_CHECK_TIMEOUT(DPMSSuspendTime)
53974                :
53975                :        case DPMSModeSuspend:
53976                :            DPMS_CHECK_TIMEOUT(DPMSOffTime)
53977                :
53978                :        default: /* DPMSModeOff */
53979                :            return 0;
53980                :    }
53981                :}
53982                :#endif /* DPMSExtension */
53983                :
53984                :static CARD32
53985                :ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg)
53986                :{
53987                :    INT32 timeout      = now - lastDeviceEventTime.milliseconds;
53988                :    CARD32 nextTimeout = 0;
53989                :
53990                :#ifdef DPMSExtension
53991                :    /*
53992                :     * Check each mode lowest to highest, since a lower mode can
53993                :     * have the same timeout as a higher one.
53994                :     */
53995                :    if (DPMSEnabled)
53996                :    {
53997                :        DPMS_CHECK_MODE(DPMSModeOff,     DPMSOffTime)
53998                :        DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime)
53999                :        DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime)
54000                :
54001                :        nextTimeout = NextDPMSTimeout(timeout);
54002                :    }
54003                :
54004                :    /*
54005                :     * Only do the screensaver checks if we're not in a DPMS
54006                :     * power saving mode
54007                :     */
54008                :    if (DPMSPowerLevel != DPMSModeOn)
54009                :        return nextTimeout;
54010                :#endif /* DPMSExtension */
54011                :
54012                :    if (!ScreenSaverTime)
54013                :        return nextTimeout;
54014                :
54015                :    if (timeout < ScreenSaverTime)
54016                :    {
54017                :        return nextTimeout > 0 ? 
54018                :                min(ScreenSaverTime - timeout, nextTimeout) :
54019                :                ScreenSaverTime - timeout;
54020                :    }
54021                :
54022                :    ResetOsBuffers(); /* not ideal, but better than nothing */
54023                :    SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive);
54024                :
54025                :    if (ScreenSaverInterval > 0)
54026                :    {
54027                :        nextTimeout = nextTimeout > 0 ? 
54028                :                min(ScreenSaverInterval, nextTimeout) :
54029                :                ScreenSaverInterval;
54030                :    }
54031                :
54032                :    return nextTimeout;
54033                :}
54034                :
54035                :static OsTimerPtr ScreenSaverTimer = NULL;
54036                :
54037                :void
54038                :FreeScreenSaverTimer(void)
54039                :{
54040                :    if (ScreenSaverTimer) {
54041                :        TimerFree(ScreenSaverTimer);
54042                :        ScreenSaverTimer = NULL;
54043                :    }
54044                :}
54045                :
54046                :void
54047                :SetScreenSaverTimer(void)
54048                :{
54049                :    CARD32 timeout = 0;
54050                :
54051                :#ifdef DPMSExtension
54052                :    if (DPMSEnabled)
54053                :    {
54054                :        /*
54055                :         * A higher DPMS level has a timeout that's either less
54056                :         * than or equal to that of a lower DPMS level.
54057                :         */
54058                :        if (DPMSStandbyTime > 0)
54059                :            timeout = DPMSStandbyTime;
54060                :
54061                :        else if (DPMSSuspendTime > 0)
54062                :            timeout = DPMSSuspendTime;
54063                :
54064                :        else if (DPMSOffTime > 0)
54065                :            timeout = DPMSOffTime;
54066                :    }
54067                :#endif
54068                :
54069                :    if (ScreenSaverTime > 0)
54070                :    {
54071                :        timeout = timeout > 0 ?
54072                :                min(ScreenSaverTime, timeout) :
54073                :                ScreenSaverTime;
54074                :    }
54075                :
54076                :#ifdef SCREENSAVER
54077                :    if (timeout && !screenSaverSuspended) {
54078                :#else
54079                :    if (timeout) {
54080                :#endif
54081                :        ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout,
54082                :                                    ScreenSaverTimeoutExpire, NULL);
54083                :    }
54084                :    else if (ScreenSaverTimer) {
54085                :        FreeScreenSaverTimer();
54086                :    }
54087                :}
54088                :
54089 /* 
54090  * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fballpriv.c"
54091  * 
54092  *      2  0.0022
54093  */
54094
54095
54096                :/*
54097                : * Copyright Â© 1998 Keith Packard
54098                : *
54099                : * Permission to use, copy, modify, distribute, and sell this software and its
54100                : * documentation for any purpose is hereby granted without fee, provided that
54101                : * the above copyright notice appear in all copies and that both that
54102                : * copyright notice and this permission notice appear in supporting
54103                : * documentation, and that the name of Keith Packard not be used in
54104                : * advertising or publicity pertaining to distribution of the software without
54105                : * specific, written prior permission.  Keith Packard makes no
54106                : * representations about the suitability of this software for any purpose.  It
54107                : * is provided "as is" without express or implied warranty.
54108                : *
54109                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
54110                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
54111                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
54112                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
54113                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
54114                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
54115                : * PERFORMANCE OF THIS SOFTWARE.
54116                : */
54117                :
54118                :#ifdef HAVE_DIX_CONFIG_H
54119                :#include <dix-config.h>
54120                :#endif
54121                :
54122                :#include "fb.h"
54123                :
54124                :#ifdef FB_SCREEN_PRIVATE
54125                :int fbScreenPrivateIndex;
54126                :int fbGetScreenPrivateIndex(void)
54127                :{
54128                :    return fbScreenPrivateIndex;
54129                :}
54130                :#endif
54131                :int fbGCPrivateIndex;
54132                :int fbGetGCPrivateIndex(void)
54133      2  0.0022 :{ /* fbGetGCPrivateIndex total:      2  0.0022 */
54134                :    return fbGCPrivateIndex;
54135                :}
54136                :#ifndef FB_NO_WINDOW_PIXMAPS
54137                :int fbWinPrivateIndex;
54138                :int fbGetWinPrivateIndex(void)
54139                :{
54140                :    return fbWinPrivateIndex;
54141                :}
54142                :#endif
54143                :int fbGeneration;
54144                :
54145                :#ifdef FB_OLD_SCREEN
54146                :#define miAllocateGCPrivateIndex()  AllocateGCPrivateIndex()
54147                :#endif
54148                :
54149                :Bool
54150                :fbAllocatePrivates(ScreenPtr pScreen, int *pGCIndex)
54151                :{
54152                :    if (fbGeneration != serverGeneration)
54153                :    {
54154                :        fbGCPrivateIndex = miAllocateGCPrivateIndex ();
54155                :#ifndef FB_NO_WINDOW_PIXMAPS
54156                :        fbWinPrivateIndex = AllocateWindowPrivateIndex();
54157                :#endif
54158                :#ifdef FB_SCREEN_PRIVATE
54159                :        fbScreenPrivateIndex = AllocateScreenPrivateIndex ();
54160                :        if (fbScreenPrivateIndex == -1)
54161                :            return FALSE;
54162                :#endif
54163                :        
54164                :        fbGeneration = serverGeneration;
54165                :    }
54166                :    if (pGCIndex)
54167                :        *pGCIndex = fbGCPrivateIndex;
54168                :    if (!AllocateGCPrivate(pScreen, fbGCPrivateIndex, sizeof(FbGCPrivRec)))
54169                :        return FALSE;
54170                :#ifndef FB_NO_WINDOW_PIXMAPS
54171                :    if (!AllocateWindowPrivate(pScreen, fbWinPrivateIndex, 0))
54172                :        return FALSE;
54173                :#endif
54174                :#ifdef FB_SCREEN_PRIVATE
54175                :    {
54176                :        FbScreenPrivPtr pScreenPriv;
54177                :
54178                :        pScreenPriv = (FbScreenPrivPtr) xalloc (sizeof (FbScreenPrivRec));
54179                :        if (!pScreenPriv)
54180                :            return FALSE;
54181                :        pScreen->devPrivates[fbScreenPrivateIndex].ptr = (pointer) pScreenPriv;
54182                :    }
54183                :#endif
54184                :    return TRUE;
54185                :}
54186                :
54187                :#ifdef FB_ACCESS_WRAPPER
54188                :ReadMemoryProcPtr wfbReadMemory;
54189                :WriteMemoryProcPtr wfbWriteMemory;
54190                :#endif
54191 /* 
54192  * Total samples for file : "/home/cworth/opt/xorg//include/X11/Xtrans/Xtranssock.c"
54193  * 
54194  *      2  0.0022
54195  */
54196
54197
54198                :/* $XdotOrg: lib/xtrans/Xtranssock.c,v 1.11 2005/11/08 06:33:26 jkj Exp $ */
54199                :/* $Xorg: Xtranssock.c,v 1.11 2001/02/09 02:04:06 xorgcvs Exp $ */
54200                :/*
54201                :
54202                :Copyright 1993, 1994, 1998  The Open Group
54203                :Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
54204                :
54205                :Permission to use, copy, modify, distribute, and sell this software and its
54206                :documentation for any purpose is hereby granted without fee, provided that
54207                :the above copyright notice appear in all copies and that both that
54208                :copyright notice and this permission notice appear in supporting
54209                :documentation.
54210                :
54211                :The above copyright notice and this permission notice shall be included
54212                :in all copies or substantial portions of the Software.
54213                :
54214                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
54215                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54216                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
54217                :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
54218                :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
54219                :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
54220                :OTHER DEALINGS IN THE SOFTWARE.
54221                :
54222                :Except as contained in this notice, the name of the copyright holders shall
54223                :not be used in advertising or otherwise to promote the sale, use or
54224                :other dealings in this Software without prior written authorization
54225                :from the copyright holders.
54226                :
54227                :*/
54228                :/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.68 2004/01/07 04:28:02 dawes Exp $ */
54229                :
54230                :/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
54231                : *
54232                : * All Rights Reserved
54233                : *
54234                : * Permission to use, copy, modify, and distribute this software and its
54235                : * documentation for any purpose and without fee is hereby granted, provided
54236                : * that the above copyright notice appear in all copies and that both that
54237                : * copyright notice and this permission notice appear in supporting
54238                : * documentation, and that the name NCR not be used in advertising
54239                : * or publicity pertaining to distribution of the software without specific,
54240                : * written prior permission.  NCR makes no representations about the
54241                : * suitability of this software for any purpose.  It is provided "as is"
54242                : * without express or implied warranty.
54243                : *
54244                : * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
54245                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
54246                : * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
54247                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
54248                : * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
54249                : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
54250                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
54251                : */
54252                :
54253                :#include <ctype.h>
54254                :#ifdef XTHREADS
54255                :#include <X11/Xthreads.h>
54256                :#endif
54257                :
54258                :#ifndef WIN32
54259                :
54260                :#if defined(TCPCONN) || defined(UNIXCONN)
54261                :#include <sys/socket.h>
54262                :#include <netinet/in.h>
54263                :#include <arpa/inet.h>
54264                :#endif
54265                :
54266                :#if defined(TCPCONN) || defined(UNIXCONN)
54267                :#define X_INCLUDE_NETDB_H
54268                :#define XOS_USE_NO_LOCKING
54269                :#include <X11/Xos_r.h>
54270                :#endif
54271                :
54272                :#ifdef UNIXCONN
54273                :#ifndef X_NO_SYS_UN
54274                :#ifndef Lynx
54275                :#include <sys/un.h>
54276                :#else
54277                :#include <un.h>
54278                :#endif
54279                :#endif
54280                :#include <sys/stat.h>
54281                :#endif
54282                :
54283                :#if defined(hpux) || (defined(MOTOROLA) && defined(SYSV))
54284                :#define NO_TCP_H
54285                :#endif 
54286                :
54287                :#ifndef NO_TCP_H
54288                :#if defined(__osf__) || defined(linux) || defined(__GLIBC__) || defined(AIXV5)
54289                :#include <sys/param.h>
54290                :#endif /* osf */
54291                :#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
54292                :#include <sys/param.h>
54293                :#include <machine/endian.h>
54294                :#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
54295                :#include <netinet/tcp.h>
54296                :#endif /* !NO_TCP_H */
54297                :
54298                :#include <sys/ioctl.h>
54299                :#if defined(SVR4) && !defined(DGUX) && !defined(_SEQUENT_)
54300                :#include <sys/filio.h>
54301                :#endif
54302                :
54303                :#if (defined(i386) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
54304                :#include <net/errno.h>
54305                :#endif 
54306                :
54307                :#if (defined(i386) && defined(SYSV)) && (!defined(ISC) || !defined(I_NREAD) || defined(SCO325)) || defined(_SEQUENT_)
54308                :#include <sys/stropts.h>
54309                :#endif 
54310                :
54311                :#else /* !WIN32 */
54312                :
54313                :#include <X11/Xwinsock.h>
54314                :#include <X11/Xwindows.h>
54315                :#include <X11/Xw32defs.h>
54316                :#undef close
54317                :#define close closesocket
54318                :#define ECONNREFUSED WSAECONNREFUSED
54319                :#define EADDRINUSE WSAEADDRINUSE
54320                :#define EPROTOTYPE WSAEPROTOTYPE
54321                :#undef EWOULDBLOCK
54322                :#define EWOULDBLOCK WSAEWOULDBLOCK
54323                :#define EINPROGRESS WSAEINPROGRESS
54324                :#undef EINTR
54325                :#define EINTR WSAEINTR
54326                :#define X_INCLUDE_NETDB_H
54327                :#define XOS_USE_MTSAFE_NETDBAPI
54328                :#include <X11/Xos_r.h>
54329                :#endif /* WIN32 */
54330                :
54331                :#if defined(SO_DONTLINGER) && defined(SO_LINGER)
54332                :#undef SO_DONTLINGER
54333                :#endif
54334                :
54335                :#if defined(__UNIXOS2__)
54336                :#if defined(NOT_EMX09A)
54337                :static int IBMsockInit = 0;
54338                :#define SocketInitOnce()\
54339                :    if (!IBMsockInit) {\
54340                :        sock_init();\
54341                :        IBMsockInit = 1;\
54342                :    }
54343                :#undef EINTR
54344                :#define EINTR SOCEINTR
54345                :#undef EINVAL
54346                :#define EINVAL SOCEINVAL
54347                :#undef errno
54348                :#define errno sock_errno()
54349                :#undef close
54350                :#define close soclose
54351                :#undef ioctl
54352                :#define ioctl sockioctl
54353                :#else
54354                :#define SocketInitOnce() /**/
54355                :#endif
54356                :/* this is still not there */
54357                :#define SOCKET int
54358                :#else
54359                :/* others don't need this */
54360                :#define SocketInitOnce() /**/
54361                :#endif
54362                :
54363                :#define MIN_BACKLOG 128
54364                :#ifdef SOMAXCONN
54365                :#if SOMAXCONN > MIN_BACKLOG
54366                :#define BACKLOG SOMAXCONN
54367                :#endif
54368                :#endif
54369                :#ifndef BACKLOG
54370                :#define BACKLOG MIN_BACKLOG
54371                :#endif
54372                :/*
54373                : * This is the Socket implementation of the X Transport service layer
54374                : *
54375                : * This file contains the implementation for both the UNIX and INET domains,
54376                : * and can be built for either one, or both.
54377                : *
54378                : */
54379                :
54380                :typedef struct _Sockettrans2dev {      
54381                :    char        *transname;
54382                :    int         family;
54383                :    int         devcotsname;
54384                :    int         devcltsname;
54385                :    int         protocol;
54386                :} Sockettrans2dev;
54387                :
54388                :static Sockettrans2dev Sockettrans2devtab[] = {
54389                :#ifdef TCPCONN
54390                :    {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
54391                :#if !defined(IPv6) || !defined(AF_INET6)
54392                :    {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
54393                :#else /* IPv6 */
54394                :    {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
54395                :    {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
54396                :    {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
54397                :#endif
54398                :#endif /* TCPCONN */
54399                :#ifdef UNIXCONN
54400                :    {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
54401                :#if !defined(LOCALCONN)
54402                :    {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
54403                :#endif /* !LOCALCONN */
54404                :#endif /* UNIXCONN */
54405                :};
54406                :
54407                :#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
54408                :
54409                :#ifdef TCPCONN
54410                :static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
54411                :#endif
54412                :
54413                :#ifdef UNIXCONN
54414                :
54415                :#ifdef hpux
54416                :
54417                :#if defined(X11_t)
54418                :#define UNIX_PATH "/usr/spool/sockets/X11/"
54419                :#define UNIX_DIR "/usr/spool/sockets/X11"
54420                :#define OLD_UNIX_PATH "/tmp/.X11-unix/X"
54421                :#endif /* X11_t */
54422                :#if defined(XIM_t)
54423                :#define UNIX_PATH "/usr/spool/sockets/XIM/"
54424                :#define UNIX_DIR "/usr/spool/sockets/XIM"
54425                :#define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM"
54426                :#endif /* XIM_t */
54427                :#if defined(FS_t) || defined(FONT_t)
54428                :#define UNIX_PATH "/usr/spool/sockets/fontserv/"
54429                :#define UNIX_DIR "/usr/spool/sockets/fontserv"
54430                :#endif /* FS_t || FONT_t */
54431                :#if defined(ICE_t)
54432                :#define UNIX_PATH "/usr/spool/sockets/ICE/"
54433                :#define UNIX_DIR "/usr/spool/sockets/ICE"
54434                :#endif /* ICE_t */
54435                :#if defined(TEST_t)
54436                :#define UNIX_PATH "/usr/spool/sockets/xtrans_test/"
54437                :#define UNIX_DIR "/usr/spool/sockets/xtrans_test"
54438                :#endif
54439                :#if defined(LBXPROXY_t)
54440                :#define UNIX_PATH "/usr/spool/sockets/X11/"
54441                :#define UNIX_DIR  "/usr/spool/sockets/X11"
54442                :#endif
54443                :
54444                :#else /* !hpux */
54445                :
54446                :#if defined(X11_t)
54447                :#define UNIX_PATH "/tmp/.X11-unix/X"
54448                :#define UNIX_DIR "/tmp/.X11-unix"
54449                :#endif /* X11_t */
54450                :#if defined(XIM_t)
54451                :#define UNIX_PATH "/tmp/.XIM-unix/XIM"
54452                :#define UNIX_DIR "/tmp/.XIM-unix"
54453                :#endif /* XIM_t */
54454                :#if defined(FS_t) || defined(FONT_t)
54455                :#define UNIX_PATH "/tmp/.font-unix/fs"
54456                :#define UNIX_DIR "/tmp/.font-unix"
54457                :#endif /* FS_t || FONT_t */
54458                :#if defined(ICE_t)
54459                :#define UNIX_PATH "/tmp/.ICE-unix/"
54460                :#define UNIX_DIR "/tmp/.ICE-unix"
54461                :#endif /* ICE_t */
54462                :#if defined(TEST_t)
54463                :#define UNIX_PATH "/tmp/.Test-unix/test"
54464                :#define UNIX_DIR "/tmp/.Test-unix"
54465                :#endif
54466                :#if defined(LBXPROXY_t)
54467                :#define UNIX_PATH "/tmp/.X11-unix/X"
54468                :#define UNIX_DIR  "/tmp/.X11-unix"
54469                :#endif
54470                :
54471                :#endif /* hpux */
54472                :
54473                :#endif /* UNIXCONN */
54474                :
54475                :#define PORTBUFSIZE     32
54476                :
54477                :#ifndef MAXHOSTNAMELEN
54478                :#define MAXHOSTNAMELEN 255
54479                :#endif
54480                :
54481                :/*
54482                : * This provides compatibility for apps linked against system libraries
54483                : * that don't have IPv6 support.
54484                : */
54485                :#if defined(IPv6) && defined(AF_INET6)
54486                :static const struct in6_addr local_in6addr_any = IN6ADDR_ANY_INIT;
54487                :#pragma weak in6addr_any = local_in6addr_any
54488                :#ifndef __USLC__
54489                :#pragma weak getaddrinfo
54490                :#endif
54491                :static int haveIPv6 = 1;
54492                :#endif
54493                :
54494                :/*
54495                : * These are some utility function used by the real interface function below.
54496                : */
54497                :
54498                :static int
54499                :TRANS(SocketSelectFamily) (int first, char *family)
54500                :
54501                :{
54502                :    int     i;
54503                :
54504                :    PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
54505                :
54506                :    for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
54507                :    {
54508                :        if (!strcmp (family, Sockettrans2devtab[i].transname))
54509                :            return i;
54510                :    }
54511                :
54512                :    return (first == -1 ? -2 : -1);
54513                :}
54514                :
54515                :
54516                :/*
54517                : * This function gets the local address of the socket and stores it in the
54518                : * XtransConnInfo structure for the connection.
54519                : */
54520                :
54521                :static int
54522                :TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
54523                :
54524                :{
54525                :#if defined(IPv6) && defined(AF_INET6)
54526                :    struct sockaddr_storage socknamev6;
54527                :#endif
54528                :    struct sockaddr_in socknamev4;
54529                :    void *socknamePtr;
54530                :#if defined(SVR4) || defined(__SCO__)
54531                :    size_t namelen;
54532                :#else
54533                :    int namelen;
54534                :#endif
54535                :
54536                :    PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0);
54537                :
54538                :#if defined(IPv6) && defined(AF_INET6)
54539                :    if (haveIPv6)
54540                :    {
54541                :        namelen = sizeof(socknamev6);
54542                :        socknamePtr = &socknamev6;
54543                :    }
54544                :    else
54545                :#endif
54546                :    {
54547                :        namelen = sizeof(socknamev4);
54548                :        socknamePtr = &socknamev4;
54549                :    }
54550                :
54551                :    bzero(socknamePtr, namelen);
54552                :    
54553                :    if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
54554                :                     (void *)&namelen) < 0)
54555                :    {
54556                :#ifdef WIN32
54557                :        errno = WSAGetLastError();
54558                :#endif
54559                :        PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
54560                :            EGET(),0, 0);
54561                :        return -1;
54562                :    }
54563                :
54564                :    /*
54565                :     * Everything looks good: fill in the XtransConnInfo structure.
54566                :     */
54567                :
54568                :    if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
54569                :    {
54570                :        PRMSG (1,
54571                :            "SocketINETGetAddr: Can't allocate space for the addr\n",
54572                :            0, 0, 0);
54573                :        return -1;
54574                :    }
54575                :
54576                :#if defined(IPv6) && defined(AF_INET6)
54577                :    if (haveIPv6)
54578                :    {
54579                :        ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
54580                :    }
54581                :    else
54582                :#endif
54583                :    {
54584                :        ciptr->family = socknamev4.sin_family;
54585                :    }
54586                :    ciptr->addrlen = namelen;
54587                :    memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
54588                :
54589                :    return 0;
54590                :}
54591                :
54592                :
54593                :/*
54594                : * This function gets the remote address of the socket and stores it in the
54595                : * XtransConnInfo structure for the connection.
54596                : */
54597                :
54598                :static int
54599                :TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
54600                :
54601                :{
54602                :#if defined(IPv6) && defined(AF_INET6)
54603                :    struct sockaddr_storage socknamev6;
54604                :#endif
54605                :    struct sockaddr_in  socknamev4;
54606                :    void *socknamePtr;
54607                :#if defined(SVR4) || defined(__SCO__)
54608                :    size_t namelen;
54609                :#else
54610                :    int namelen;
54611                :#endif
54612                :
54613                :#if defined(IPv6) && defined(AF_INET6)
54614                :    if (haveIPv6 && ciptr->family == AF_INET6)
54615                :    {
54616                :        namelen = sizeof(socknamev6);
54617                :        socknamePtr = &socknamev6;
54618                :    }
54619                :    else
54620                :#endif
54621                :    {
54622                :        namelen = sizeof(socknamev4);
54623                :        socknamePtr = &socknamev4;
54624                :    }
54625                :
54626                :    bzero(socknamePtr, namelen);
54627                :    
54628                :    PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0);
54629                :
54630                :    if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
54631                :                     (void *)&namelen) < 0)
54632                :    {
54633                :#ifdef WIN32
54634                :        errno = WSAGetLastError();
54635                :#endif
54636                :        PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
54637                :            EGET(), 0, 0);
54638                :        return -1;
54639                :    }
54640                :
54641                :    /*
54642                :     * Everything looks good: fill in the XtransConnInfo structure.
54643                :     */
54644                :
54645                :    if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
54646                :    {
54647                :        PRMSG (1,
54648                :           "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
54649                :           0, 0, 0);
54650                :        return -1;
54651                :    }
54652                :
54653                :    ciptr->peeraddrlen = namelen;
54654                :    memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
54655                :
54656                :    return 0;
54657                :}
54658                :
54659                :
54660                :static XtransConnInfo
54661                :TRANS(SocketOpen) (int i, int type)
54662                :
54663                :{
54664                :    XtransConnInfo      ciptr;
54665                :
54666                :    PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
54667                :
54668                :#if defined(IPv6) && defined(AF_INET6)
54669                :    if (getaddrinfo == NULL)
54670                :        haveIPv6 = 0;
54671                :
54672                :    if (!haveIPv6 && Sockettrans2devtab[i].family == AF_INET6)
54673                :        return NULL;
54674                :#endif
54675                :
54676                :    if ((ciptr = (XtransConnInfo) xcalloc (
54677                :        1, sizeof(struct _XtransConnInfo))) == NULL)
54678                :    {
54679                :        PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
54680                :        return NULL;
54681                :    }
54682                :
54683                :    if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
54684                :        Sockettrans2devtab[i].protocol)) < 0
54685                :#ifndef WIN32
54686                :#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
54687                :       || ciptr->fd >= TRANS_OPEN_MAX
54688                :#endif
54689                :#endif
54690                :      ) {
54691                :#ifdef WIN32
54692                :        errno = WSAGetLastError();
54693                :#endif
54694                :        PRMSG (2, "SocketOpen: socket() failed for %s\n",
54695                :            Sockettrans2devtab[i].transname, 0, 0);
54696                :
54697                :        xfree ((char *) ciptr);
54698                :        return NULL;
54699                :    }
54700                :
54701                :#ifdef TCP_NODELAY
54702                :    if (Sockettrans2devtab[i].family == AF_INET
54703                :#if defined(IPv6) && defined(AF_INET6)
54704                :      || Sockettrans2devtab[i].family == AF_INET6
54705                :#endif
54706                :    )
54707                :    {
54708                :        /*
54709                :         * turn off TCP coalescence for INET sockets
54710                :         */
54711                :
54712                :        int tmp = 1;
54713                :        setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
54714                :            (char *) &tmp, sizeof (int));
54715                :    }
54716                :#endif
54717                :
54718                :    return ciptr;
54719                :}
54720                :
54721                :
54722                :#ifdef TRANS_REOPEN
54723                :
54724                :static XtransConnInfo
54725                :TRANS(SocketReopen) (int i, int type, int fd, char *port)
54726                :
54727                :{
54728                :    XtransConnInfo      ciptr;
54729                :
54730                :    PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
54731                :
54732                :    if ((ciptr = (XtransConnInfo) xcalloc (
54733                :        1, sizeof(struct _XtransConnInfo))) == NULL)
54734                :    {
54735                :        PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0);
54736                :        return NULL;
54737                :    }
54738                :
54739                :    ciptr->fd = fd;
54740                :
54741                :    return ciptr;
54742                :}
54743                :
54744                :#endif /* TRANS_REOPEN */
54745                :
54746                :
54747                :/*
54748                : * These functions are the interface supplied in the Xtransport structure
54749                : */
54750                :
54751                :#ifdef TRANS_CLIENT
54752                :
54753                :static XtransConnInfo
54754                :TRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
54755                :                                char *host, char *port, int previndex)
54756                :{
54757                :    XtransConnInfo      ciptr;
54758                :    int                 i = previndex;
54759                :
54760                :    PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
54761                :        protocol, host, port);
54762                :
54763                :    SocketInitOnce();
54764                :
54765                :    while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
54766                :        if ((ciptr = TRANS(SocketOpen) (
54767                :                 i, Sockettrans2devtab[i].devcotsname)) != NULL)
54768                :            break;
54769                :    }
54770                :    if (i < 0) {
54771                :        if (i == -1)
54772                :            PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
54773                :                   transname, 0, 0);
54774                :        else
54775                :            PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
54776                :                   transname, 0, 0);
54777                :        return NULL;
54778                :    }
54779                :
54780                :    /* Save the index for later use */
54781                :
54782                :    ciptr->index = i;
54783                :
54784                :    return ciptr;
54785                :}
54786                :
54787                :static XtransConnInfo
54788                :TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol, 
54789                :                             char *host, char *port)
54790                :{
54791                :    return TRANS(SocketOpenCOTSClientBase)(
54792                :                        thistrans->TransName, protocol, host, port, -1);
54793                :}
54794                :
54795                :
54796                :#endif /* TRANS_CLIENT */
54797                :
54798                :
54799                :#ifdef TRANS_SERVER
54800                :
54801                :static XtransConnInfo
54802                :TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol, 
54803                :                             char *host, char *port)
54804                :
54805                :{
54806                :    XtransConnInfo      ciptr;
54807                :    int i = -1;
54808                :
54809                :    PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
54810                :
54811                :    SocketInitOnce();
54812                :
54813                :    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
54814                :        if ((ciptr = TRANS(SocketOpen) (
54815                :                 i, Sockettrans2devtab[i].devcotsname)) != NULL)
54816                :            break;
54817                :    }
54818                :    if (i < 0) {
54819                :        if (i == -1)
54820                :            PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
54821                :                   thistrans->TransName, 0, 0);
54822                :        else
54823                :            PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
54824                :                   thistrans->TransName, 0, 0);
54825                :        return NULL;
54826                :    }
54827                :
54828                :    /*
54829                :     * Using this prevents the bind() check for an existing server listening
54830                :     * on the same port, but it is required for other reasons.
54831                :     */
54832                :#ifdef SO_REUSEADDR
54833                :
54834                :    /*
54835                :     * SO_REUSEADDR only applied to AF_INET && AF_INET6
54836                :     */
54837                :
54838                :    if (Sockettrans2devtab[i].family == AF_INET
54839                :#if defined(IPv6) && defined(AF_INET6)
54840                :      || Sockettrans2devtab[i].family == AF_INET6
54841                :#endif
54842                :    )
54843                :    {
54844                :        int one = 1;
54845                :        setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
54846                :                    (char *) &one, sizeof (int));
54847                :    }
54848                :#endif
54849                :#ifdef IPV6_V6ONLY
54850                :    if (Sockettrans2devtab[i].family == AF_INET6)
54851                :    {
54852                :        int one = 1;
54853                :        setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
54854                :    }
54855                :#endif
54856                :    /* Save the index for later use */
54857                :
54858                :    ciptr->index = i;
54859                :
54860                :    return ciptr;
54861                :}
54862                :
54863                :#endif /* TRANS_SERVER */
54864                :
54865                :
54866                :#ifdef TRANS_CLIENT
54867                :
54868                :static XtransConnInfo
54869                :TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol, 
54870                :                             char *host, char *port)
54871                :
54872                :{
54873                :    XtransConnInfo      ciptr;
54874                :    int                 i = -1;
54875                :
54876                :    PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
54877                :
54878                :    SocketInitOnce();
54879                :
54880                :    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
54881                :        if ((ciptr = TRANS(SocketOpen) (
54882                :                 i, Sockettrans2devtab[i].devcotsname)) != NULL)
54883                :            break;
54884                :    }
54885                :    if (i < 0) {
54886                :        if (i == -1)
54887                :            PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
54888                :                   thistrans->TransName, 0, 0);
54889                :        else
54890                :            PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
54891                :                   thistrans->TransName, 0, 0);
54892                :        return NULL;
54893                :    }
54894                :
54895                :    /* Save the index for later use */
54896                :
54897                :    ciptr->index = i;
54898                :
54899                :    return ciptr;
54900                :}
54901                :
54902                :#endif /* TRANS_CLIENT */
54903                :
54904                :
54905                :#ifdef TRANS_SERVER
54906                :
54907                :static XtransConnInfo
54908                :TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol, 
54909                :                             char *host, char *port)
54910                :
54911                :{
54912                :    XtransConnInfo      ciptr;
54913                :    int i = -1;
54914                :
54915                :    PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
54916                :
54917                :    SocketInitOnce();
54918                :
54919                :    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
54920                :        if ((ciptr = TRANS(SocketOpen) (
54921                :                 i, Sockettrans2devtab[i].devcotsname)) != NULL)
54922                :            break;
54923                :    }
54924                :    if (i < 0) {
54925                :        if (i == -1)
54926                :            PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
54927                :                   thistrans->TransName, 0, 0);
54928                :        else
54929                :            PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
54930                :                   thistrans->TransName, 0, 0);
54931                :        return NULL;
54932                :    }
54933                :
54934                :#ifdef IPV6_V6ONLY
54935                :    if (Sockettrans2devtab[i].family == AF_INET6)
54936                :    {
54937                :        int one = 1;
54938                :        setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
54939                :    }
54940                :#endif
54941                :    /* Save the index for later use */
54942                :
54943                :    ciptr->index = i;
54944                :
54945                :    return ciptr;
54946                :}
54947                :
54948                :#endif /* TRANS_SERVER */
54949                :
54950                :
54951                :#ifdef TRANS_REOPEN
54952                :
54953                :static XtransConnInfo
54954                :TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
54955                :
54956                :{
54957                :    XtransConnInfo      ciptr;
54958                :    int                 i = -1;
54959                :
54960                :    PRMSG (2,
54961                :        "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
54962                :
54963                :    SocketInitOnce();
54964                :
54965                :    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
54966                :        if ((ciptr = TRANS(SocketReopen) (
54967                :                 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
54968                :            break;
54969                :    }
54970                :    if (i < 0) {
54971                :        if (i == -1)
54972                :            PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
54973                :                   thistrans->TransName, 0, 0);
54974                :        else
54975                :            PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
54976                :                   thistrans->TransName, 0, 0);
54977                :        return NULL;
54978                :    }
54979                :
54980                :    /* Save the index for later use */
54981                :
54982                :    ciptr->index = i;
54983                :
54984                :    return ciptr;
54985                :}
54986                :
54987                :static XtransConnInfo
54988                :TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
54989                :
54990                :{
54991                :    XtransConnInfo      ciptr;
54992                :    int                 i = -1;
54993                :
54994                :    PRMSG (2,
54995                :        "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
54996                :
54997                :    SocketInitOnce();
54998                :
54999                :    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
55000                :        if ((ciptr = TRANS(SocketReopen) (
55001                :                 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
55002                :            break;
55003                :    }
55004                :    if (i < 0) {
55005                :        if (i == -1)
55006                :            PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
55007                :                   thistrans->TransName, 0, 0);
55008                :        else
55009                :            PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
55010                :                   thistrans->TransName, 0, 0);
55011                :        return NULL;
55012                :    }
55013                :
55014                :    /* Save the index for later use */
55015                :
55016                :    ciptr->index = i;
55017                :
55018                :    return ciptr;
55019                :}
55020                :
55021                :#endif /* TRANS_REOPEN */
55022                :
55023                :
55024                :static int
55025                :TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
55026                :
55027                :{
55028                :    PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
55029                :
55030                :    return -1;
55031                :}
55032                :
55033                :#ifdef UNIXCONN
55034                :static int
55035                :set_sun_path(const char *port, const char *upath, char *path)
55036                :{
55037                :    struct sockaddr_un s;
55038                :    int maxlen = sizeof(s.sun_path) - 1;
55039                :
55040                :    if (!port || !*port || !path)
55041                :        return -1;
55042                :
55043                :    if (*port == '/') { /* a full pathname */
55044                :        if (strlen(port) > maxlen)
55045                :            return -1;
55046                :        sprintf(path, "%s", port);
55047                :    } else {
55048                :        if (strlen(port) + strlen(upath) > maxlen)
55049                :            return -1;
55050                :        sprintf(path, "%s%s", upath, port);
55051                :    }
55052                :    return 0;
55053                :}
55054                :#endif
55055                :
55056                :#ifdef TRANS_SERVER
55057                :
55058                :static int
55059                :TRANS(SocketCreateListener) (XtransConnInfo ciptr, 
55060                :                             struct sockaddr *sockname,
55061                :                             int socknamelen, unsigned int flags)
55062                :
55063                :{
55064                :    int namelen = socknamelen;
55065                :    int fd = ciptr->fd;
55066                :    int retry;
55067                :
55068                :    PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0);
55069                :
55070                :    if (Sockettrans2devtab[ciptr->index].family == AF_INET
55071                :#if defined(IPv6) && defined(AF_INET6)
55072                :      || Sockettrans2devtab[ciptr->index].family == AF_INET6
55073                :#endif
55074                :        )
55075                :        retry = 20;
55076                :    else
55077                :        retry = 0;
55078                :
55079                :    while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
55080                :    {
55081                :        if (errno == EADDRINUSE) {
55082                :            if (flags & ADDR_IN_USE_ALLOWED)
55083                :                break;
55084                :            else
55085                :                return TRANS_ADDR_IN_USE;
55086                :        }
55087                :        
55088                :        if (retry-- == 0) {
55089                :            PRMSG (1, "SocketCreateListener: failed to bind listener\n",
55090                :                0, 0, 0);
55091                :            close (fd);
55092                :            return TRANS_CREATE_LISTENER_FAILED;
55093                :        }
55094                :#ifdef SO_REUSEADDR
55095                :        sleep (1);
55096                :#else
55097                :        sleep (10);
55098                :#endif /* SO_REUSEDADDR */
55099                :    }
55100                :
55101                :    if (Sockettrans2devtab[ciptr->index].family == AF_INET
55102                :#if defined(IPv6) && defined(AF_INET6)
55103                :      || Sockettrans2devtab[ciptr->index].family == AF_INET6
55104                :#endif
55105                :        ) {
55106                :#ifdef SO_DONTLINGER
55107                :        setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
55108                :#else
55109                :#ifdef SO_LINGER
55110                :    {
55111                :        static int linger[2] = { 0, 0 };
55112                :        setsockopt (fd, SOL_SOCKET, SO_LINGER,
55113                :                (char *) linger, sizeof (linger));
55114                :    }
55115                :#endif
55116                :#endif
55117                :}
55118                :
55119                :    if (listen (fd, BACKLOG) < 0)
55120                :    {
55121                :        PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
55122                :        close (fd);
55123                :        return TRANS_CREATE_LISTENER_FAILED;
55124                :    }
55125                :        
55126                :    /* Set a flag to indicate that this connection is a listener */
55127                :
55128                :    ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
55129                :
55130                :    return 0;
55131                :}
55132                :
55133                :#ifdef TCPCONN
55134                :static int
55135                :TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
55136                :
55137                :{
55138                :#if defined(IPv6) && defined(AF_INET6)
55139                :    struct sockaddr_storage sockname;
55140                :#else
55141                :    struct sockaddr_in      sockname;
55142                :#endif
55143                :    unsigned short          sport;
55144                :    int         namelen = sizeof(sockname);
55145                :    int         status;
55146                :    long        tmpport;
55147                :#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
55148                :    _Xgetservbynameparams sparams;
55149                :#endif
55150                :    struct servent *servp;
55151                :
55152                :#ifdef X11_t
55153                :    char        portbuf[PORTBUFSIZE];
55154                :#endif
55155                :    
55156                :    PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
55157                :
55158                :#ifdef X11_t
55159                :    /*
55160                :     * X has a well known port, that is transport dependent. It is easier
55161                :     * to handle it here, than try and come up with a transport independent
55162                :     * representation that can be passed in and resolved the usual way.
55163                :     *
55164                :     * The port that is passed here is really a string containing the idisplay
55165                :     * from ConnectDisplay().
55166                :     */
55167                :
55168                :    if (is_numeric (port))
55169                :    {
55170                :        /* fixup the server port address */
55171                :        tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
55172                :        sprintf (portbuf,"%lu", tmpport);
55173                :        port = portbuf;
55174                :    }
55175                :#endif
55176                :
55177                :    if (port && *port)
55178                :    {
55179                :        /* Check to see if the port string is just a number (handles X11) */
55180                :
55181                :        if (!is_numeric (port))
55182                :        {
55183                :            if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
55184                :            {
55185                :                PRMSG (1,
55186                :             "SocketINETCreateListener: Unable to get service for %s\n",
55187                :                      port, 0, 0);
55188                :                return TRANS_CREATE_LISTENER_FAILED;
55189                :            }
55190                :            /* we trust getservbyname to return a valid number */
55191                :            sport = servp->s_port;
55192                :        }
55193                :        else
55194                :        {
55195                :            tmpport = strtol (port, (char**)NULL, 10);
55196                :            /* 
55197                :             * check that somehow the port address isn't negative or in
55198                :             * the range of reserved port addresses. This can happen and
55199                :             * be very bad if the server is suid-root and the user does 
55200                :             * something (dumb) like `X :60049`. 
55201                :             */
55202                :            if (tmpport < 1024 || tmpport > USHRT_MAX)
55203                :                return TRANS_CREATE_LISTENER_FAILED;
55204                :
55205                :            sport = (unsigned short) tmpport;
55206                :        }
55207                :    }
55208                :    else
55209                :        sport = 0;
55210                :
55211                :    bzero(&sockname, sizeof(sockname));
55212                :#if defined(IPv6) && defined(AF_INET6)
55213                :    if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
55214                :        namelen = sizeof (struct sockaddr_in);
55215                :#ifdef BSD44SOCKETS
55216                :        ((struct sockaddr_in *)&sockname)->sin_len = namelen;
55217                :#endif
55218                :        ((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
55219                :        ((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
55220                :        ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
55221                :    } else {
55222                :        namelen = sizeof (struct sockaddr_in6);
55223                :#ifdef SIN6_LEN
55224                :        ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
55225                :#endif
55226                :        ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
55227                :        ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
55228                :        ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
55229                :    }
55230                :#else
55231                :#ifdef BSD44SOCKETS
55232                :    sockname.sin_len = sizeof (sockname);
55233                :#endif
55234                :    sockname.sin_family = AF_INET;
55235                :    sockname.sin_port = htons (sport);
55236                :    sockname.sin_addr.s_addr = htonl (INADDR_ANY);
55237                :#endif
55238                :
55239                :    if ((status = TRANS(SocketCreateListener) (ciptr,
55240                :        (struct sockaddr *) &sockname, namelen, flags)) < 0)
55241                :    {
55242                :        PRMSG (1,
55243                :    "SocketINETCreateListener: ...SocketCreateListener() failed\n",
55244                :            0, 0, 0);
55245                :        return status;
55246                :    }
55247                :
55248                :    if (TRANS(SocketINETGetAddr) (ciptr) < 0)
55249                :    {
55250                :        PRMSG (1,
55251                :       "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
55252                :            0, 0, 0);
55253                :        return TRANS_CREATE_LISTENER_FAILED;
55254                :    }
55255                :
55256                :    return 0;
55257                :}
55258                :
55259                :#endif /* TCPCONN */
55260                :
55261                :
55262                :#ifdef UNIXCONN
55263                :
55264                :static int
55265                :TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
55266                :                                 unsigned int flags)
55267                :
55268                :{
55269                :    struct sockaddr_un  sockname;
55270                :    int                 namelen;
55271                :    int                 oldUmask;
55272                :    int                 status;
55273                :    unsigned int        mode;
55274                :
55275                :    PRMSG (2, "SocketUNIXCreateListener(%s)\n",
55276                :        port ? port : "NULL", 0, 0);
55277                :
55278                :    /* Make sure the directory is created */
55279                :
55280                :    oldUmask = umask (0);
55281                :
55282                :#ifdef UNIX_DIR
55283                :#ifdef HAS_STICKY_DIR_BIT
55284                :    mode = 01777;
55285                :#else
55286                :    mode = 0777;
55287                :#endif
55288                :    if (trans_mkdir(UNIX_DIR, mode) == -1) {
55289                :        PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
55290                :               UNIX_DIR, errno, 0);
55291                :        (void) umask (oldUmask);
55292                :        return TRANS_CREATE_LISTENER_FAILED;
55293                :    }
55294                :#endif
55295                :
55296                :    sockname.sun_family = AF_UNIX;
55297                :
55298                :    if (port && *port) {
55299                :        if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
55300                :            PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
55301                :            return TRANS_CREATE_LISTENER_FAILED;
55302                :        }
55303                :    } else {
55304                :        snprintf (sockname.sun_path, sizeof(sockname.sun_path),
55305                :                  "%s%ld", UNIX_PATH, (long)getpid());
55306                :    }
55307                :
55308                :#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
55309                :    sockname.sun_len = strlen(sockname.sun_path);
55310                :#endif
55311                :
55312                :#if defined(BSD44SOCKETS) || defined(SUN_LEN)
55313                :    namelen = SUN_LEN(&sockname);
55314                :#else
55315                :    namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
55316                :#endif
55317                :
55318                :    unlink (sockname.sun_path);
55319                :
55320                :    if ((status = TRANS(SocketCreateListener) (ciptr,
55321                :        (struct sockaddr *) &sockname, namelen, flags)) < 0)
55322                :    {
55323                :        PRMSG (1,
55324                :    "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
55325                :            0, 0, 0);
55326                :        (void) umask (oldUmask);
55327                :        return status;
55328                :    }
55329                :
55330                :    /*
55331                :     * Now that the listener is esablished, create the addr info for
55332                :     * this connection. getpeername() doesn't work for UNIX Domain Sockets
55333                :     * on some systems (hpux at least), so we will just do it manually, instead
55334                :     * of calling something like TRANS(SocketUNIXGetAddr).
55335                :     */
55336                :
55337                :    namelen = sizeof (sockname); /* this will always make it the same size */
55338                :
55339                :    if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
55340                :    {
55341                :        PRMSG (1,
55342                :        "SocketUNIXCreateListener: Can't allocate space for the addr\n",
55343                :            0, 0, 0);
55344                :        (void) umask (oldUmask);
55345                :        return TRANS_CREATE_LISTENER_FAILED;
55346                :    }
55347                :
55348                :    ciptr->family = sockname.sun_family;
55349                :    ciptr->addrlen = namelen;
55350                :    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
55351                :
55352                :    (void) umask (oldUmask);
55353                :
55354                :    return 0;
55355                :}
55356                :
55357                :
55358                :static int
55359                :TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
55360                :
55361                :{
55362                :    /*
55363                :     * See if the unix domain socket has disappeared.  If it has, recreate it.
55364                :     */
55365                :
55366                :    struct sockaddr_un  *unsock = (struct sockaddr_un *) ciptr->addr;
55367                :    struct stat         statb;
55368                :    int                 status = TRANS_RESET_NOOP;
55369                :    unsigned int        mode;
55370                :
55371                :    PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0);
55372                :
55373                :    if (stat (unsock->sun_path, &statb) == -1 ||
55374                :        ((statb.st_mode & S_IFMT) !=
55375                :#if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
55376                :                        S_IFIFO))
55377                :#else
55378                :                        S_IFSOCK))
55379                :#endif
55380                :    {
55381                :        int oldUmask = umask (0);
55382                :
55383                :#ifdef UNIX_DIR
55384                :#ifdef HAS_STICKY_DIR_BIT
55385                :        mode = 01777;
55386                :#else
55387                :        mode = 0777;
55388                :#endif
55389                :        if (trans_mkdir(UNIX_DIR, mode) == -1) {
55390                :            PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
55391                :            UNIX_DIR, errno, 0);
55392                :            (void) umask (oldUmask);
55393                :            return TRANS_RESET_FAILURE;
55394                :        }
55395                :#endif
55396                :
55397                :        close (ciptr->fd);
55398                :        unlink (unsock->sun_path);
55399                :
55400                :        if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
55401                :        {
55402                :            TRANS(FreeConnInfo) (ciptr);
55403                :            (void) umask (oldUmask);
55404                :            return TRANS_RESET_FAILURE;
55405                :        }
55406                :
55407                :        if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
55408                :        {
55409                :            close (ciptr->fd);
55410                :            TRANS(FreeConnInfo) (ciptr);
55411                :            return TRANS_RESET_FAILURE;
55412                :        }
55413                :
55414                :        if (listen (ciptr->fd, BACKLOG) < 0)
55415                :        {
55416                :            close (ciptr->fd);
55417                :            TRANS(FreeConnInfo) (ciptr);
55418                :            (void) umask (oldUmask);
55419                :            return TRANS_RESET_FAILURE;
55420                :        }
55421                :
55422                :        umask (oldUmask);
55423                :
55424                :        status = TRANS_RESET_NEW_FD;
55425                :    }
55426                :
55427                :    return status;
55428                :}
55429                :
55430                :#endif /* UNIXCONN */
55431                :
55432                :
55433                :#ifdef TCPCONN
55434                :
55435                :static XtransConnInfo
55436                :TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
55437                :
55438                :{
55439                :    XtransConnInfo      newciptr;
55440                :    struct sockaddr_in  sockname;
55441                :    int                 namelen = sizeof(sockname);
55442                :
55443                :    PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
55444                :
55445                :    if ((newciptr = (XtransConnInfo) xcalloc (
55446                :        1, sizeof(struct _XtransConnInfo))) == NULL)
55447                :    {
55448                :        PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
55449                :        *status = TRANS_ACCEPT_BAD_MALLOC;
55450                :        return NULL;
55451                :    }
55452                :
55453                :    if ((newciptr->fd = accept (ciptr->fd,
55454                :        (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
55455                :    {
55456                :#ifdef WIN32
55457                :        errno = WSAGetLastError();
55458                :#endif
55459                :        PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
55460                :        xfree (newciptr);
55461                :        *status = TRANS_ACCEPT_FAILED;
55462                :        return NULL;
55463                :    }
55464                :
55465                :#ifdef TCP_NODELAY
55466                :    {
55467                :        /*
55468                :         * turn off TCP coalescence for INET sockets
55469                :         */
55470                :
55471                :        int tmp = 1;
55472                :        setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
55473                :            (char *) &tmp, sizeof (int));
55474                :    }
55475                :#endif
55476                :
55477                :    /*
55478                :     * Get this address again because the transport may give a more 
55479                :     * specific address now that a connection is established.
55480                :     */
55481                :
55482                :    if (TRANS(SocketINETGetAddr) (newciptr) < 0)
55483                :    {
55484                :        PRMSG (1,
55485                :            "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
55486                :            0, 0, 0);
55487                :        close (newciptr->fd);
55488                :        xfree (newciptr);
55489                :        *status = TRANS_ACCEPT_MISC_ERROR;
55490                :        return NULL;
55491                :    }
55492                :
55493                :    if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
55494                :    {
55495                :        PRMSG (1,
55496                :          "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
55497                :                0, 0, 0);
55498                :        close (newciptr->fd);
55499                :        if (newciptr->addr) xfree (newciptr->addr);
55500                :        xfree (newciptr);
55501                :        *status = TRANS_ACCEPT_MISC_ERROR;
55502                :        return NULL;
55503                :    }
55504                :
55505                :    *status = 0;
55506                :
55507                :    return newciptr;
55508                :}
55509                :
55510                :#endif /* TCPCONN */
55511                :
55512                :
55513                :#ifdef UNIXCONN
55514                :static XtransConnInfo
55515                :TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
55516                :
55517                :{
55518                :    XtransConnInfo      newciptr;
55519                :    struct sockaddr_un  sockname;
55520                :#if defined(SVR4) || defined(__SCO__)
55521                :    size_t namelen = sizeof sockname;
55522                :#else
55523                :    int namelen = sizeof sockname;
55524                :#endif
55525                :
55526                :    PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
55527                :
55528                :    if ((newciptr = (XtransConnInfo) xcalloc (
55529                :        1, sizeof(struct _XtransConnInfo))) == NULL)
55530                :    {
55531                :        PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
55532                :        *status = TRANS_ACCEPT_BAD_MALLOC;
55533                :        return NULL;
55534                :    }
55535                :
55536                :    if ((newciptr->fd = accept (ciptr->fd,
55537                :        (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
55538                :    {
55539                :        PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
55540                :        xfree (newciptr);
55541                :        *status = TRANS_ACCEPT_FAILED;
55542                :        return NULL;
55543                :    }
55544                :
55545                :    /*
55546                :     * Get the socket name and the peer name from the listener socket,
55547                :     * since this is unix domain.
55548                :     */
55549                :
55550                :    if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
55551                :    {
55552                :        PRMSG (1,
55553                :        "SocketUNIXAccept: Can't allocate space for the addr\n",
55554                :              0, 0, 0);
55555                :        close (newciptr->fd);
55556                :        xfree (newciptr);
55557                :        *status = TRANS_ACCEPT_BAD_MALLOC;
55558                :        return NULL;
55559                :    }
55560                :
55561                :
55562                :    newciptr->addrlen = ciptr->addrlen;
55563                :    memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
55564                :
55565                :    if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
55566                :    {
55567                :        PRMSG (1,
55568                :              "SocketUNIXAccept: Can't allocate space for the addr\n",
55569                :              0, 0, 0);
55570                :        close (newciptr->fd);
55571                :        if (newciptr->addr) xfree (newciptr->addr);
55572                :        xfree (newciptr);
55573                :        *status = TRANS_ACCEPT_BAD_MALLOC;
55574                :        return NULL;
55575                :    }
55576                :    
55577                :    newciptr->peeraddrlen = ciptr->addrlen;
55578                :    memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
55579                :
55580                :    newciptr->family = AF_UNIX;
55581                :
55582                :    *status = 0;
55583                :
55584                :    return newciptr;
55585                :}
55586                :
55587                :#endif /* UNIXCONN */
55588                :
55589                :#endif /* TRANS_SERVER */
55590                :
55591                :
55592                :#ifdef TRANS_CLIENT
55593                :
55594                :#ifdef TCPCONN
55595                :
55596                :#if defined(IPv6) && defined(AF_INET6)
55597                :struct addrlist {
55598                :    struct addrinfo *   addr;
55599                :    struct addrinfo *   firstaddr; 
55600                :    char                port[PORTBUFSIZE];
55601                :    char                host[MAXHOSTNAMELEN];
55602                :};
55603                :static struct addrlist  *addrlist = NULL;
55604                :#endif
55605                :
55606                :
55607                :static int
55608                :TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
55609                :
55610                :{
55611                :    struct sockaddr *   socketaddr = NULL;
55612                :    int                 socketaddrlen = 0;
55613                :    int                 res;
55614                :#if defined(IPv6) && defined(AF_INET6)
55615                :    struct addrinfo     hints;
55616                :    char                ntopbuf[INET6_ADDRSTRLEN];
55617                :    int                 resetonce = 0;
55618                :#endif
55619                :    struct sockaddr_in  sockname;
55620                :#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
55621                :    _Xgethostbynameparams hparams;
55622                :    _Xgetservbynameparams sparams;
55623                :#endif
55624                :    struct hostent      *hostp;
55625                :    struct servent      *servp;
55626                :    unsigned long       tmpaddr;
55627                :#ifdef X11_t
55628                :    char        portbuf[PORTBUFSIZE];
55629                :#endif
55630                :
55631                :    long                tmpport;
55632                :    char                hostnamebuf[256];               /* tmp space */
55633                :
55634                :    PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
55635                :
55636                :    if (!host)
55637                :    {
55638                :        hostnamebuf[0] = '\0';
55639                :        (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
55640                :        host = hostnamebuf;
55641                :    }
55642                :
55643                :#ifdef X11_t
55644                :    /*
55645                :     * X has a well known port, that is transport dependent. It is easier
55646                :     * to handle it here, than try and come up with a transport independent
55647                :     * representation that can be passed in and resolved the usual way.
55648                :     *
55649                :     * The port that is passed here is really a string containing the idisplay
55650                :     * from ConnectDisplay().
55651                :     */
55652                :
55653                :    if (is_numeric (port))
55654                :    {
55655                :        tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
55656                :        sprintf (portbuf, "%lu", tmpport);
55657                :        port = portbuf;
55658                :    }
55659                :#endif
55660                :
55661                :#if defined(IPv6) && defined(AF_INET6)
55662                :    if (haveIPv6) {
55663                :        if (addrlist != NULL) {
55664                :            if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
55665                :                if (addrlist->firstaddr)
55666                :                    freeaddrinfo(addrlist->firstaddr);
55667                :                addrlist->firstaddr = NULL;
55668                :            }
55669                :        } else {
55670                :            addrlist = malloc(sizeof(struct addrlist));
55671                :            addrlist->firstaddr = NULL;
55672                :        }
55673                :
55674                :        if (addrlist->firstaddr == NULL) {
55675                :            strncpy(addrlist->port, port, sizeof(addrlist->port));
55676                :            addrlist->port[sizeof(addrlist->port) - 1] = '\0';
55677                :            strncpy(addrlist->host, host, sizeof(addrlist->host));
55678                :            addrlist->host[sizeof(addrlist->host) - 1] = '\0';
55679                :
55680                :            bzero(&hints,sizeof(hints));
55681                :            hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
55682                :
55683                :            res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
55684                :            if (res != 0) {
55685                :                PRMSG (1, "SocketINETConnect() can't get address "
55686                :                        "for %s:%s: %s\n", host, port, gai_strerror(res));
55687                :                ESET(EINVAL);
55688                :                return TRANS_CONNECT_FAILED;
55689                :            }
55690                :            for (res = 0, addrlist->addr = addrlist->firstaddr;
55691                :                 addrlist->addr ; res++) {
55692                :                addrlist->addr = addrlist->addr->ai_next;
55693                :            }
55694                :            PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0);
55695                :            res = 0;
55696                :            addrlist->addr = NULL;
55697                :        }
55698                :
55699                :        while (socketaddr == NULL) {
55700                :            if (addrlist->addr == NULL) {
55701                :                if (resetonce) { 
55702                :                    /* Already checked entire list - no usable addresses */
55703                :                    PRMSG (1, "SocketINETConnect() no usable address "
55704                :                           "for %s:%s\n", host, port, 0);
55705                :                    return TRANS_CONNECT_FAILED;
55706                :                } else {
55707                :                    /* Go back to beginning of list */
55708                :                    resetonce = 1;
55709                :                    addrlist->addr = addrlist->firstaddr;
55710                :                }
55711                :            } 
55712                :
55713                :            socketaddr = addrlist->addr->ai_addr;
55714                :            socketaddrlen = addrlist->addr->ai_addrlen;
55715                :
55716                :            if (addrlist->addr->ai_family == AF_INET) {
55717                :                struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
55718                :
55719                :                PRMSG (4,"SocketINETConnect() sockname.sin_addr = %s\n",
55720                :                        inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
55721                :                        ntopbuf,sizeof(ntopbuf)), 0, 0); 
55722                :
55723                :                PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n",
55724                :                        ntohs(sin->sin_port), 0, 0); 
55725                :
55726                :                if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
55727                :                    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
55728                :                                "tcp") == 0) {
55729                :                        XtransConnInfo newciptr;
55730                :
55731                :                        /*
55732                :                         * Our socket is an IPv6 socket, but the address is
55733                :                         * IPv4.  Close it and get an IPv4 socket.  This is
55734                :                         * needed for IPv4 connections to work on platforms
55735                :                         * that don't allow IPv4 over IPv6 sockets.
55736                :                         */
55737                :                        TRANS(SocketINETClose)(ciptr);
55738                :                        newciptr = TRANS(SocketOpenCOTSClientBase)(
55739                :                                        "tcp", "tcp", host, port, ciptr->index);
55740                :                        if (newciptr)
55741                :                            ciptr->fd = newciptr->fd;
55742                :                        if (!newciptr ||
55743                :                            Sockettrans2devtab[newciptr->index].family !=
55744                :                                AF_INET) {
55745                :                            socketaddr = NULL;
55746                :                            PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
55747                :                                        " socketfor IPv4 address\n", 0,0,0);
55748                :                        }
55749                :                        if (newciptr)
55750                :                            xfree(newciptr);
55751                :                    } else {
55752                :                        socketaddr = NULL;
55753                :                        PRMSG (4,"SocketINETConnect Skipping IPv4 address\n",
55754                :                                0,0,0);
55755                :                    }
55756                :                }
55757                :            } else if (addrlist->addr->ai_family == AF_INET6) {
55758                :                struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
55759                :        
55760                :                PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
55761                :                        inet_ntop(addrlist->addr->ai_family,
55762                :                                  &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
55763                :                        0, 0); 
55764                :                PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n",
55765                :                        ntohs(sin6->sin6_port), 0, 0); 
55766                :
55767                :                if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
55768                :                    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
55769                :                                "tcp") == 0) {
55770                :                        XtransConnInfo newciptr;
55771                :
55772                :                        /*
55773                :                         * Close the IPv4 socket and try to open an IPv6 socket.
55774                :                         */
55775                :                        TRANS(SocketINETClose)(ciptr);
55776                :                        newciptr = TRANS(SocketOpenCOTSClientBase)(
55777                :                                        "tcp", "tcp", host, port, -1);
55778                :                        if (newciptr)
55779                :                            ciptr->fd = newciptr->fd;
55780                :                        if (!newciptr ||
55781                :                            Sockettrans2devtab[newciptr->index].family !=
55782                :                                        AF_INET6) {
55783                :                            socketaddr = NULL;
55784                :                            PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
55785                :                                   "socket for IPv6 address\n", 0,0,0);
55786                :                        }
55787                :                        if (newciptr)
55788                :                            xfree(newciptr);
55789                :                    }
55790                :                    else
55791                :                    {
55792                :                        socketaddr = NULL;
55793                :                        PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n",
55794                :                                0,0,0);
55795                :                    }
55796                :                }
55797                :            } else {
55798                :                socketaddr = NULL; /* Unsupported address type */
55799                :            }
55800                :            if (socketaddr == NULL) {
55801                :                addrlist->addr = addrlist->addr->ai_next;
55802                :            }
55803                :        } 
55804                :    } else
55805                :#endif
55806                :    {
55807                :        /*
55808                :         * Build the socket name.
55809                :         */
55810                :
55811                :#ifdef BSD44SOCKETS
55812                :        sockname.sin_len = sizeof (struct sockaddr_in);
55813                :#endif
55814                :        sockname.sin_family = AF_INET;
55815                :
55816                :        /*
55817                :         * fill in sin_addr
55818                :         */
55819                :
55820                :#ifndef INADDR_NONE
55821                :#define INADDR_NONE ((in_addr_t) 0xffffffff)
55822                :#endif
55823                :
55824                :        /* check for ww.xx.yy.zz host string */
55825                :
55826                :        if (isascii (host[0]) && isdigit (host[0])) {
55827                :            tmpaddr = inet_addr (host); /* returns network byte order */
55828                :        } else {
55829                :            tmpaddr = INADDR_NONE;
55830                :        }
55831                :
55832                :        PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0);
55833                :
55834                :        if (tmpaddr == INADDR_NONE) {
55835                :            if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
55836                :                PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
55837                :                        host, 0, 0);
55838                :                ESET(EINVAL);
55839                :                return TRANS_CONNECT_FAILED;
55840                :            }
55841                :            if (hostp->h_addrtype != AF_INET) {  /* is IP host? */
55842                :                PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0);
55843                :                ESET(EPROTOTYPE);
55844                :                return TRANS_CONNECT_FAILED;
55845                :            }
55846                :        
55847                :#if defined(CRAY) && defined(OLDTCP)
55848                :            /* Only Cray UNICOS3 and UNICOS4 will define this */
55849                :            {
55850                :                long t;
55851                :                memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t));
55852                :                sockname.sin_addr = t;
55853                :            }
55854                :#else
55855                :            memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
55856                :                    sizeof (sockname.sin_addr));
55857                :#endif /* CRAY and OLDTCP */
55858                :
55859                :        } else {
55860                :#if defined(CRAY) && defined(OLDTCP)
55861                :            /* Only Cray UNICOS3 and UNICOS4 will define this */
55862                :            sockname.sin_addr = tmpaddr;
55863                :#else
55864                :            sockname.sin_addr.s_addr = tmpaddr;
55865                :#endif /* CRAY and OLDTCP */
55866                :        }
55867                :
55868                :        /*
55869                :         * fill in sin_port
55870                :         */
55871                :
55872                :        /* Check for number in the port string */
55873                :
55874                :        if (!is_numeric (port)) {
55875                :            if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
55876                :                PRMSG (1,"SocketINETConnect: can't get service for %s\n",
55877                :                        port, 0, 0);
55878                :                return TRANS_CONNECT_FAILED;
55879                :            }
55880                :            sockname.sin_port = htons (servp->s_port);
55881                :        } else {
55882                :            tmpport = strtol (port, (char**)NULL, 10);
55883                :            if (tmpport < 1024 || tmpport > USHRT_MAX)
55884                :                return TRANS_CONNECT_FAILED;
55885                :            sockname.sin_port = htons (((unsigned short) tmpport));
55886                :        }
55887                :
55888                :        PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
55889                :                ntohs(sockname.sin_port), 0, 0);
55890                :        socketaddr = (struct sockaddr *) &sockname;
55891                :        socketaddrlen = sizeof(sockname);
55892                :    }
55893                :
55894                :    /*
55895                :     * Turn on socket keepalive so the client process will eventually
55896                :     * be notified with a SIGPIPE signal if the display server fails
55897                :     * to respond to a periodic transmission of messages
55898                :     * on the connected socket.
55899                :     * This is useful to avoid hung application processes when the
55900                :     * processes are not spawned from the xdm session and
55901                :     * the display server terminates abnormally.
55902                :     * (Someone turned off the power switch.)
55903                :     */
55904                :
55905                :    {
55906                :        int tmp = 1;
55907                :        setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
55908                :                (char *) &tmp, sizeof (int));
55909                :    }
55910                :
55911                :    /*
55912                :     * Do the connect()
55913                :     */
55914                :
55915                :    if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
55916                :    {
55917                :#ifdef WIN32
55918                :        int olderrno = WSAGetLastError();
55919                :#else
55920                :        int olderrno = errno;
55921                :#endif
55922                :
55923                :        /*
55924                :         * If the error was ECONNREFUSED, the server may be overloaded
55925                :         * and we should try again.
55926                :         *
55927                :         * If the error was EWOULDBLOCK or EINPROGRESS then the socket
55928                :         * was non-blocking and we should poll using select
55929                :         *
55930                :         * If the error was EINTR, the connect was interrupted and we
55931                :         * should try again.
55932                :         *
55933                :         * If multiple addresses are found for a host then we should
55934                :         * try to connect again with a different address for a larger
55935                :         * number of errors that made us quit before, since those
55936                :         * could be caused by trying to use an IPv6 address to contact
55937                :         * a machine with an IPv4-only server or other reasons that
55938                :         * only affect one of a set of addresses.  
55939                :         */
55940                :
55941                :        if (olderrno == ECONNREFUSED || olderrno == EINTR
55942                :#if defined(IPv6) && defined(AF_INET6)
55943                :          || (haveIPv6 && ((addrlist->addr->ai_next != NULL) || 
55944                :                (addrlist->addr != addrlist->firstaddr)) &&
55945                :               (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
55946                :                 olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
55947                :#if defined(EHOSTDOWN)
55948                :                   || olderrno == EHOSTDOWN
55949                :#endif
55950                :               ))
55951                :#endif
55952                :            )
55953                :            res = TRANS_TRY_CONNECT_AGAIN;
55954                :        else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
55955                :            res = TRANS_IN_PROGRESS;
55956                :        else
55957                :        {
55958                :            PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
55959                :                   olderrno,0, 0);
55960                :
55961                :            res = TRANS_CONNECT_FAILED; 
55962                :        }
55963                :    } else {
55964                :        res = 0;
55965                :    
55966                :
55967                :        /*
55968                :         * Sync up the address fields of ciptr.
55969                :         */
55970                :    
55971                :        if (TRANS(SocketINETGetAddr) (ciptr) < 0)
55972                :        {
55973                :            PRMSG (1,
55974                :             "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
55975                :              0, 0, 0);
55976                :            res = TRANS_CONNECT_FAILED;
55977                :        }
55978                :
55979                :        else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
55980                :        {
55981                :            PRMSG (1,
55982                :              "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
55983                :              0, 0, 0);
55984                :            res = TRANS_CONNECT_FAILED;
55985                :        }
55986                :    }
55987                :
55988                :#if defined(IPv6) && defined(AF_INET6)
55989                :   if (haveIPv6 && res != 0) { 
55990                :        addrlist->addr = addrlist->addr->ai_next;
55991                :   }
55992                :#endif
55993                :
55994                :    return res;
55995                :}
55996                :
55997                :#endif /* TCPCONN */
55998                :
55999                :
56000                :\f
56001                :#ifdef UNIXCONN
56002                :
56003                :/*
56004                : * Make sure 'host' is really local.
56005                : */
56006                :
56007                :static int
56008                :UnixHostReallyLocal (char *host)
56009                :
56010                :{
56011                :    char hostnamebuf[256];
56012                :
56013                :#if defined(IPv6) && defined(AF_INET6)
56014                :    if (getaddrinfo == NULL)
56015                :        haveIPv6 = 0;
56016                :#endif
56017                :
56018                :    TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
56019                :
56020                :    if (strcmp (hostnamebuf, host) == 0)
56021                :    {
56022                :        return (1);
56023                :    }
56024                :#if defined(IPv6) && defined(AF_INET6)
56025                :    else if (haveIPv6)
56026                :    {
56027                :        struct addrinfo *localhostaddr;
56028                :        struct addrinfo *otherhostaddr;
56029                :        struct addrinfo *i, *j;
56030                :        int equiv = 0;
56031                :
56032                :        if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
56033                :            return 0;
56034                :        if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
56035                :            freeaddrinfo(localhostaddr);
56036                :            return 0;
56037                :        }
56038                :
56039                :        for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
56040                :            for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
56041                :                if (i->ai_family == j->ai_family) {
56042                :                    if (i->ai_family == AF_INET) {
56043                :                        struct sockaddr_in *sinA 
56044                :                          = (struct sockaddr_in *) i->ai_addr;
56045                :                        struct sockaddr_in *sinB
56046                :                          = (struct sockaddr_in *) j->ai_addr;
56047                :                        struct in_addr *A = &sinA->sin_addr;
56048                :                        struct in_addr *B = &sinB->sin_addr;
56049                :
56050                :                        if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
56051                :                            equiv = 1;
56052                :                        }
56053                :                    } else if (i->ai_family == AF_INET6) {
56054                :                        struct sockaddr_in6 *sinA 
56055                :                          = (struct sockaddr_in6 *) i->ai_addr;
56056                :                        struct sockaddr_in6 *sinB 
56057                :                          = (struct sockaddr_in6 *) j->ai_addr;
56058                :                        struct in6_addr *A = &sinA->sin6_addr;
56059                :                        struct in6_addr *B = &sinB->sin6_addr;
56060                :
56061                :                        if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
56062                :                            equiv = 1;
56063                :                        }
56064                :                    }
56065                :                }
56066                :            }
56067                :        }
56068                :        
56069                :        freeaddrinfo(localhostaddr);
56070                :        freeaddrinfo(otherhostaddr);
56071                :        return equiv;
56072                :    }
56073                :#endif
56074                :    else
56075                :    {
56076                :        /*
56077                :         * A host may have more than one network address.  If any of the
56078                :         * network addresses of 'host' (specified to the connect call)
56079                :         * match any of the network addresses of 'hostname' (determined
56080                :         * by TRANS(GetHostname)), then the two hostnames are equivalent,
56081                :         * and we know that 'host' is really a local host.
56082                :         */
56083                :        char specified_local_addr_list[10][4];
56084                :        int scount, equiv, i, j;
56085                :#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
56086                :        _Xgethostbynameparams hparams;
56087                :#endif
56088                :        struct hostent *hostp;
56089                :
56090                :        if ((hostp = _XGethostbyname (host,hparams)) == NULL)
56091                :            return (0);
56092                :
56093                :        scount = 0;
56094                :        while (hostp->h_addr_list[scount] && scount <= 8)
56095                :        {
56096                :            /*
56097                :             * The 2nd call to gethostname() overrides the data
56098                :             * from the 1st call, so we must save the address list.
56099                :             */
56100                :
56101                :            specified_local_addr_list[scount][0] = 
56102                :                                hostp->h_addr_list[scount][0];
56103                :            specified_local_addr_list[scount][1] = 
56104                :                                hostp->h_addr_list[scount][1];
56105                :            specified_local_addr_list[scount][2] = 
56106                :                                hostp->h_addr_list[scount][2];
56107                :            specified_local_addr_list[scount][3] = 
56108                :                                hostp->h_addr_list[scount][3];
56109                :            scount++;
56110                :        }
56111                :        if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
56112                :            return (0);
56113                :
56114                :        equiv = 0;
56115                :        i = 0;
56116                :
56117                :        while (i < scount && !equiv)
56118                :        {
56119                :            j = 0;
56120                :
56121                :            while (hostp->h_addr_list[j])
56122                :            {
56123                :                if ((specified_local_addr_list[i][0] == 
56124                :                                        hostp->h_addr_list[j][0]) &&
56125                :                    (specified_local_addr_list[i][1] == 
56126                :                                        hostp->h_addr_list[j][1]) &&
56127                :                    (specified_local_addr_list[i][2] == 
56128                :                                        hostp->h_addr_list[j][2]) &&
56129                :                    (specified_local_addr_list[i][3] == 
56130                :                                        hostp->h_addr_list[j][3]))
56131                :                {
56132                :                    /* They're equal, so we're done */
56133                :                    
56134                :                    equiv = 1;
56135                :                    break;
56136                :                }
56137                :
56138                :                j++;
56139                :            }
56140                :
56141                :            i++;
56142                :        }
56143                :        return (equiv);
56144                :    }
56145                :}
56146                :
56147                :static int
56148                :TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
56149                :
56150                :{
56151                :    struct sockaddr_un  sockname;
56152                :    int                 namelen;
56153                :
56154                :#if defined(hpux) && defined(X11_t)
56155                :    struct sockaddr_un  old_sockname;
56156                :    int                 old_namelen;
56157                :#endif
56158                :
56159                :
56160                :    PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
56161                :    
56162                :    /*
56163                :     * Make sure 'host' is really local.  If not, we return failure.
56164                :     * The reason we make this check is because a process may advertise
56165                :     * a "local" network ID for which it can accept connections, but if
56166                :     * a process on a remote machine tries to connect to this network ID,
56167                :     * we know for sure it will fail.
56168                :     */
56169                :
56170                :    if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
56171                :    {
56172                :        PRMSG (1,
56173                :           "SocketUNIXConnect: Cannot connect to non-local host %s\n",
56174                :               host, 0, 0);
56175                :        return TRANS_CONNECT_FAILED;
56176                :    }
56177                :
56178                :
56179                :    /*
56180                :     * Check the port.
56181                :     */
56182                :
56183                :    if (!port || !*port)
56184                :    {
56185                :        PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
56186                :              0, 0, 0);
56187                :        return TRANS_CONNECT_FAILED;
56188                :    }
56189                :
56190                :    /*
56191                :     * Build the socket name.
56192                :     */
56193                :    
56194                :    sockname.sun_family = AF_UNIX;
56195                :
56196                :    if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
56197                :        PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
56198                :        return TRANS_CONNECT_FAILED;
56199                :    }
56200                :
56201                :#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
56202                :    sockname.sun_len = strlen (sockname.sun_path);
56203                :#endif
56204                :
56205                :#if defined(BSD44SOCKETS) || defined(SUN_LEN)
56206                :    namelen = SUN_LEN (&sockname);
56207                :#else
56208                :    namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
56209                :#endif
56210                :
56211                :
56212                :#if defined(hpux) && defined(X11_t)
56213                :    /*
56214                :     * This is gross, but it was in Xlib
56215                :     */
56216                :    old_sockname.sun_family = AF_UNIX;
56217                :    if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) {
56218                :        PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
56219                :        return TRANS_CONNECT_FAILED;
56220                :    }
56221                :    old_namelen = strlen (old_sockname.sun_path) +
56222                :        offsetof(struct sockaddr_un, sun_path);
56223                :#endif
56224                :
56225                :
56226                :    /*
56227                :     * Do the connect()
56228                :     */
56229                :
56230                :    if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
56231                :    {
56232                :        int olderrno = errno;
56233                :        int connected = 0;
56234                :        
56235                :#if defined(hpux) && defined(X11_t)
56236                :        if (olderrno == ENOENT)
56237                :        {
56238                :            if (connect (ciptr->fd,
56239                :                (struct sockaddr *) &old_sockname, old_namelen) >= 0)
56240                :            {
56241                :                connected = 1;
56242                :            }
56243                :            else
56244                :                olderrno = errno;
56245                :        }
56246                :#endif
56247                :        if (!connected)
56248                :        {
56249                :            errno = olderrno;
56250                :            
56251                :            /*
56252                :             * If the error was ENOENT, the server may be starting up
56253                :             * and we should try again.
56254                :             *
56255                :             * If the error was EWOULDBLOCK or EINPROGRESS then the socket
56256                :             * was non-blocking and we should poll using select
56257                :             *
56258                :             * If the error was EINTR, the connect was interrupted and we
56259                :             * should try again.
56260                :             */
56261                :
56262                :            if (olderrno == ENOENT || olderrno == EINTR)
56263                :                return TRANS_TRY_CONNECT_AGAIN;
56264                :            else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
56265                :                return TRANS_IN_PROGRESS;
56266                :            else
56267                :            {
56268                :                PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
56269                :                       EGET(),0, 0);
56270                :
56271                :                return TRANS_CONNECT_FAILED;
56272                :            }
56273                :        }
56274                :    }
56275                :
56276                :    /*
56277                :     * Get the socket name and the peer name from the connect socket,
56278                :     * since this is unix domain.
56279                :     */
56280                :
56281                :    if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
56282                :       (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
56283                :    {
56284                :        PRMSG (1,
56285                :        "SocketUNIXCreateListener: Can't allocate space for the addr\n",
56286                :              0, 0, 0);
56287                :        return TRANS_CONNECT_FAILED;
56288                :    }
56289                :
56290                :    ciptr->family = AF_UNIX;
56291                :    ciptr->addrlen = namelen;
56292                :    ciptr->peeraddrlen = namelen;
56293                :    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
56294                :    memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
56295                :    
56296                :    return 0;
56297                :}
56298                :
56299                :#endif /* UNIXCONN */
56300                :
56301                :#endif /* TRANS_CLIENT */
56302                :
56303                :
56304                :static int
56305                :TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
56306                :
56307                :{
56308                :    PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
56309                :        ciptr, ciptr->fd, pend);
56310                :#if defined(QNX4)
56311                :    *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */
56312                :#endif
56313                :#ifdef WIN32
56314                :    {
56315                :        int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
56316                :        errno = WSAGetLastError();
56317                :        return ret;
56318                :    }
56319                :#else
56320                :#if (defined(i386) && defined(SYSV) && !defined(SCO325)) || (defined(_SEQUENT_) && _SOCKET_VERSION == 1)
56321                :    return ioctl (ciptr->fd, I_NREAD, (char *) pend);
56322                :#else
56323                :#if defined(__UNIXOS2__)
56324                :    return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int));
56325                :#else
56326                :    return ioctl (ciptr->fd, FIONREAD, (char *) pend);
56327                :#endif /* __UNIXOS2__ */
56328                :#endif /* i386 && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
56329                :#endif /* WIN32 */
56330                :}
56331                :
56332                :
56333                :static int
56334                :TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
56335                :
56336      1  0.0011 :{ /* _XSERVTransSocketRead total:      2  0.0022 */
56337                :    PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
56338                :
56339                :#if defined(WIN32) || defined(__UNIXOS2__)
56340                :    {
56341                :        int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
56342                :#ifdef WIN32
56343                :        errno = WSAGetLastError();
56344                :#endif
56345                :        return ret;
56346                :    }
56347                :#else
56348      1  0.0011 :    return read (ciptr->fd, buf, size);
56349                :#endif /* WIN32 */
56350                :}
56351                :
56352                :
56353                :static int
56354                :TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
56355                :
56356                :{
56357                :    PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
56358                :
56359                :#if defined(WIN32) || defined(__UNIXOS2__)
56360                :    {
56361                :        int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
56362                :#ifdef WIN32
56363                :        errno = WSAGetLastError();
56364                :#endif
56365                :        return ret;
56366                :    }
56367                :#else
56368                :    return write (ciptr->fd, buf, size);
56369                :#endif /* WIN32 */
56370                :}
56371                :
56372                :
56373                :static int
56374                :TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
56375                :
56376                :{
56377                :    PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
56378                :
56379                :    return READV (ciptr, buf, size);
56380                :}
56381                :
56382                :
56383                :static int
56384                :TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
56385                :
56386                :{
56387                :    PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
56388                :
56389                :    return WRITEV (ciptr, buf, size);
56390                :}
56391                :
56392                :
56393                :static int
56394                :TRANS(SocketDisconnect) (XtransConnInfo ciptr)
56395                :
56396                :{
56397                :    PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0);
56398                :
56399                :#ifdef WIN32
56400                :    { 
56401                :        int ret = shutdown (ciptr->fd, 2);
56402                :        errno = WSAGetLastError();
56403                :        return ret;
56404                :    }
56405                :#else
56406                :    return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
56407                :#endif
56408                :}
56409                :
56410                :
56411                :#ifdef TCPCONN
56412                :static int
56413                :TRANS(SocketINETClose) (XtransConnInfo ciptr)
56414                :
56415                :{
56416                :    PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0);
56417                :
56418                :#ifdef WIN32
56419                :    {
56420                :        int ret = close (ciptr->fd);
56421                :        errno = WSAGetLastError();
56422                :        return ret;
56423                :    }
56424                :#else
56425                :    return close (ciptr->fd);
56426                :#endif
56427                :}
56428                :
56429                :#endif /* TCPCONN */
56430                :
56431                :
56432                :#ifdef UNIXCONN
56433                :static int
56434                :TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
56435                :
56436                :{
56437                :    /*
56438                :     * If this is the server side, then once the socket is closed,
56439                :     * it must be unlinked to completely close it
56440                :     */
56441                :
56442                :    struct sockaddr_un  *sockname = (struct sockaddr_un *) ciptr->addr;
56443                :    int ret;
56444                :
56445                :    PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0);
56446                :
56447                :    ret = close(ciptr->fd);
56448                :
56449                :    if (ciptr->flags
56450                :       && sockname
56451                :       && sockname->sun_family == AF_UNIX
56452                :       && sockname->sun_path[0])
56453                :    {
56454                :        if (!(ciptr->flags & TRANS_NOUNLINK))
56455                :                unlink (sockname->sun_path);
56456                :    }
56457                :
56458                :    return ret;
56459                :}
56460                :
56461                :static int
56462                :TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
56463                :
56464                :{
56465                :    /*
56466                :     * Don't unlink path.
56467                :     */
56468                :
56469                :    int ret;
56470                :
56471                :    PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
56472                :        ciptr, ciptr->fd, 0);
56473                :
56474                :    ret = close(ciptr->fd);
56475                :
56476                :    return ret;
56477                :}
56478                :
56479                :#endif /* UNIXCONN */
56480                :
56481                :
56482                :#ifdef TCPCONN
56483                :# ifdef TRANS_SERVER
56484                :static char* tcp_nolisten[] = {
56485                :        "inet",
56486                :#if defined(IPv6) && defined(AF_INET6)
56487                :        "inet6",
56488                :#endif
56489                :        NULL
56490                :};
56491                :# endif
56492                :
56493                :Xtransport      TRANS(SocketTCPFuncs) = {
56494                :        /* Socket Interface */
56495                :        "tcp",
56496                :        TRANS_ALIAS,
56497                :#ifdef TRANS_CLIENT
56498                :        TRANS(SocketOpenCOTSClient),
56499                :#endif /* TRANS_CLIENT */
56500                :#ifdef TRANS_SERVER
56501                :        tcp_nolisten,
56502                :        TRANS(SocketOpenCOTSServer),
56503                :#endif /* TRANS_SERVER */
56504                :#ifdef TRANS_CLIENT
56505                :        TRANS(SocketOpenCLTSClient),
56506                :#endif /* TRANS_CLIENT */
56507                :#ifdef TRANS_SERVER
56508                :        TRANS(SocketOpenCLTSServer),
56509                :#endif /* TRANS_SERVER */
56510                :#ifdef TRANS_REOPEN
56511                :        TRANS(SocketReopenCOTSServer),
56512                :        TRANS(SocketReopenCLTSServer),
56513                :#endif
56514                :        TRANS(SocketSetOption),
56515                :#ifdef TRANS_SERVER
56516                :        TRANS(SocketINETCreateListener),
56517                :        NULL,                                   /* ResetListener */
56518                :        TRANS(SocketINETAccept),
56519                :#endif /* TRANS_SERVER */
56520                :#ifdef TRANS_CLIENT
56521                :        TRANS(SocketINETConnect),
56522                :#endif /* TRANS_CLIENT */
56523                :        TRANS(SocketBytesReadable),
56524                :        TRANS(SocketRead),
56525                :        TRANS(SocketWrite),
56526                :        TRANS(SocketReadv),
56527                :        TRANS(SocketWritev),
56528                :        TRANS(SocketDisconnect),
56529                :        TRANS(SocketINETClose),
56530                :        TRANS(SocketINETClose),
56531                :        };
56532                :
56533                :Xtransport      TRANS(SocketINETFuncs) = {
56534                :        /* Socket Interface */
56535                :        "inet",
56536                :        0,
56537                :#ifdef TRANS_CLIENT
56538                :        TRANS(SocketOpenCOTSClient),
56539                :#endif /* TRANS_CLIENT */
56540                :#ifdef TRANS_SERVER
56541                :        NULL,
56542                :        TRANS(SocketOpenCOTSServer),
56543                :#endif /* TRANS_SERVER */
56544                :#ifdef TRANS_CLIENT
56545                :        TRANS(SocketOpenCLTSClient),
56546                :#endif /* TRANS_CLIENT */
56547                :#ifdef TRANS_SERVER
56548                :        TRANS(SocketOpenCLTSServer),
56549                :#endif /* TRANS_SERVER */
56550                :#ifdef TRANS_REOPEN
56551                :        TRANS(SocketReopenCOTSServer),
56552                :        TRANS(SocketReopenCLTSServer),
56553                :#endif
56554                :        TRANS(SocketSetOption),
56555                :#ifdef TRANS_SERVER
56556                :        TRANS(SocketINETCreateListener),
56557                :        NULL,                                   /* ResetListener */
56558                :        TRANS(SocketINETAccept),
56559                :#endif /* TRANS_SERVER */
56560                :#ifdef TRANS_CLIENT
56561                :        TRANS(SocketINETConnect),
56562                :#endif /* TRANS_CLIENT */
56563                :        TRANS(SocketBytesReadable),
56564                :        TRANS(SocketRead),
56565                :        TRANS(SocketWrite),
56566                :        TRANS(SocketReadv),
56567                :        TRANS(SocketWritev),
56568                :        TRANS(SocketDisconnect),
56569                :        TRANS(SocketINETClose),
56570                :        TRANS(SocketINETClose),
56571                :        };
56572                :
56573                :#if defined(IPv6) && defined(AF_INET6)
56574                :Xtransport     TRANS(SocketINET6Funcs) = {
56575                :        /* Socket Interface */
56576                :        "inet6",
56577                :        0,
56578                :#ifdef TRANS_CLIENT
56579                :        TRANS(SocketOpenCOTSClient),
56580                :#endif /* TRANS_CLIENT */
56581                :#ifdef TRANS_SERVER
56582                :        NULL,
56583                :        TRANS(SocketOpenCOTSServer),
56584                :#endif /* TRANS_SERVER */
56585                :#ifdef TRANS_CLIENT
56586                :        TRANS(SocketOpenCLTSClient),
56587                :#endif /* TRANS_CLIENT */
56588                :#ifdef TRANS_SERVER
56589                :        TRANS(SocketOpenCLTSServer),
56590                :#endif /* TRANS_SERVER */
56591                :#ifdef TRANS_REOPEN
56592                :        TRANS(SocketReopenCOTSServer),
56593                :        TRANS(SocketReopenCLTSServer),
56594                :#endif
56595                :        TRANS(SocketSetOption),
56596                :#ifdef TRANS_SERVER
56597                :        TRANS(SocketINETCreateListener),
56598                :        NULL,                                   /* ResetListener */
56599                :        TRANS(SocketINETAccept),
56600                :#endif /* TRANS_SERVER */
56601                :#ifdef TRANS_CLIENT
56602                :        TRANS(SocketINETConnect),
56603                :#endif /* TRANS_CLIENT */
56604                :        TRANS(SocketBytesReadable),
56605                :        TRANS(SocketRead),
56606                :        TRANS(SocketWrite),
56607                :        TRANS(SocketReadv),
56608                :        TRANS(SocketWritev),
56609                :        TRANS(SocketDisconnect),
56610                :        TRANS(SocketINETClose),
56611                :        TRANS(SocketINETClose),
56612                :        };
56613                :#endif /* IPv6 */
56614                :#endif /* TCPCONN */
56615                :
56616                :#ifdef UNIXCONN
56617                :#if !defined(LOCALCONN)
56618                :Xtransport      TRANS(SocketLocalFuncs) = {
56619                :        /* Socket Interface */
56620                :        "local",
56621                :        0,
56622                :#ifdef TRANS_CLIENT
56623                :        TRANS(SocketOpenCOTSClient),
56624                :#endif /* TRANS_CLIENT */
56625                :#ifdef TRANS_SERVER
56626                :        NULL,
56627                :        TRANS(SocketOpenCOTSServer),
56628                :#endif /* TRANS_SERVER */
56629                :#ifdef TRANS_CLIENT
56630                :        TRANS(SocketOpenCLTSClient),
56631                :#endif /* TRANS_CLIENT */
56632                :#ifdef TRANS_SERVER
56633                :        TRANS(SocketOpenCLTSServer),
56634                :#endif /* TRANS_SERVER */
56635                :#ifdef TRANS_REOPEN
56636                :        TRANS(SocketReopenCOTSServer),
56637                :        TRANS(SocketReopenCLTSServer),
56638                :#endif
56639                :        TRANS(SocketSetOption),
56640                :#ifdef TRANS_SERVER
56641                :        TRANS(SocketUNIXCreateListener),
56642                :        TRANS(SocketUNIXResetListener),
56643                :        TRANS(SocketUNIXAccept),
56644                :#endif /* TRANS_SERVER */
56645                :#ifdef TRANS_CLIENT
56646                :        TRANS(SocketUNIXConnect),
56647                :#endif /* TRANS_CLIENT */
56648                :        TRANS(SocketBytesReadable),
56649                :        TRANS(SocketRead),
56650                :        TRANS(SocketWrite),
56651                :        TRANS(SocketReadv),
56652                :        TRANS(SocketWritev),
56653                :        TRANS(SocketDisconnect),
56654                :        TRANS(SocketUNIXClose),
56655                :        TRANS(SocketUNIXCloseForCloning),
56656                :        };
56657                :#endif /* !LOCALCONN */
56658                :# ifdef TRANS_SERVER
56659                :#  if !defined(LOCALCONN)
56660                :static char* unix_nolisten[] = { "local" , NULL };
56661                :#  endif
56662                :# endif
56663                :            
56664                :Xtransport      TRANS(SocketUNIXFuncs) = {
56665                :        /* Socket Interface */
56666                :        "unix",
56667                :#if !defined(LOCALCONN)
56668                :        TRANS_ALIAS,
56669                :#else
56670                :        0,
56671                :#endif
56672                :#ifdef TRANS_CLIENT
56673                :        TRANS(SocketOpenCOTSClient),
56674                :#endif /* TRANS_CLIENT */
56675                :#ifdef TRANS_SERVER
56676                :#if !defined(LOCALCONN)
56677                :        unix_nolisten,
56678                :#else
56679                :        NULL,
56680                :#endif
56681                :        TRANS(SocketOpenCOTSServer),
56682                :#endif /* TRANS_SERVER */
56683                :#ifdef TRANS_CLIENT
56684                :        TRANS(SocketOpenCLTSClient),
56685                :#endif /* TRANS_CLIENT */
56686                :#ifdef TRANS_SERVER
56687                :        TRANS(SocketOpenCLTSServer),
56688                :#endif /* TRANS_SERVER */
56689                :#ifdef TRANS_REOPEN
56690                :        TRANS(SocketReopenCOTSServer),
56691                :        TRANS(SocketReopenCLTSServer),
56692                :#endif
56693                :        TRANS(SocketSetOption),
56694                :#ifdef TRANS_SERVER
56695                :        TRANS(SocketUNIXCreateListener),
56696                :        TRANS(SocketUNIXResetListener),
56697                :        TRANS(SocketUNIXAccept),
56698                :#endif /* TRANS_SERVER */
56699                :#ifdef TRANS_CLIENT
56700                :        TRANS(SocketUNIXConnect),
56701                :#endif /* TRANS_CLIENT */
56702                :        TRANS(SocketBytesReadable),
56703                :        TRANS(SocketRead),
56704                :        TRANS(SocketWrite),
56705                :        TRANS(SocketReadv),
56706                :        TRANS(SocketWritev),
56707                :        TRANS(SocketDisconnect),
56708                :        TRANS(SocketUNIXClose),
56709                :        TRANS(SocketUNIXCloseForCloning),
56710                :        };
56711                :
56712                :#endif /* UNIXCONN */
56713 /* 
56714  * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbtrap.c"
56715  * 
56716  *      1  0.0011
56717  */
56718
56719
56720                :/*
56721                : * Copyright Â© 2004 Keith Packard
56722                : *
56723                : * Permission to use, copy, modify, distribute, and sell this software and its
56724                : * documentation for any purpose is hereby granted without fee, provided that
56725                : * the above copyright notice appear in all copies and that both that
56726                : * copyright notice and this permission notice appear in supporting
56727                : * documentation, and that the name of Keith Packard not be used in
56728                : * advertising or publicity pertaining to distribution of the software without
56729                : * specific, written prior permission.  Keith Packard makes no
56730                : * representations about the suitability of this software for any purpose.  It
56731                : * is provided "as is" without express or implied warranty.
56732                : *
56733                : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
56734                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
56735                : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
56736                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
56737                : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
56738                : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
56739                : * PERFORMANCE OF THIS SOFTWARE.
56740                : */
56741                :
56742                :#ifdef HAVE_DIX_CONFIG_H
56743                :#include <dix-config.h>
56744                :#endif
56745                :
56746                :#include "fb.h"
56747                :
56748                :#ifdef RENDER
56749                :
56750                :#include "picturestr.h"
56751                :#include "mipict.h"
56752                :#include "renderedge.h"
56753                :#include "fbpict.h"
56754                :
56755                :void
56756                :fbAddTraps (PicturePtr  pPicture,
56757                :            INT16       x_off,
56758                :            INT16       y_off,
56759                :            int         ntrap,
56760                :            xTrap       *traps)
56761                :{
56762                :    pixman_image_t *image = image_from_pict (pPicture, FALSE);
56763                :
56764                :    if (!image)
56765                :        return;
56766                :    
56767                :    pixman_add_traps (image, x_off, y_off, ntrap, (pixman_trap_t *)traps);
56768                :
56769                :    fbFinishAccess (pPicture->pDrawable);
56770                :
56771                :    pixman_image_unref (image);
56772                :}
56773                :
56774                :void
56775                :fbRasterizeTrapezoid (PicturePtr    pPicture,
56776                :                      xTrapezoid  *trap,
56777                :                      int           x_off,
56778                :                      int           y_off)
56779                :{ /* fbRasterizeTrapezoid total:      1  0.0011 */
56780                :    pixman_image_t *image = image_from_pict (pPicture, FALSE);
56781                :
56782                :    if (!image)
56783                :        return;
56784                :
56785                :    pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *)trap, x_off, y_off);
56786                :
56787                :    fbFinishAccess (pPicture->pDrawable);
56788                :
56789      1  0.0011 :    pixman_image_unref (image);
56790                :}
56791                :
56792                :static int
56793                :_GreaterY (xPointFixed *a, xPointFixed *b)
56794                :{
56795                :    if (a->y == b->y)
56796                :        return a->x > b->x;
56797                :    return a->y > b->y;
56798                :}
56799                :
56800                :/*
56801                : * Note that the definition of this function is a bit odd because
56802                : * of the X coordinate space (y increasing downwards).
56803                : */
56804                :static int
56805                :_Clockwise (xPointFixed *ref, xPointFixed *a, xPointFixed *b)
56806                :{
56807                :    xPointFixed ad, bd;
56808                :
56809                :    ad.x = a->x - ref->x;
56810                :    ad.y = a->y - ref->y;
56811                :    bd.x = b->x - ref->x;
56812                :    bd.y = b->y - ref->y;
56813                :
56814                :    return ((xFixed_32_32) bd.y * ad.x - (xFixed_32_32) ad.y * bd.x) < 0;
56815                :}
56816                :
56817                :/* FIXME -- this could be made more efficient */
56818                :void
56819                :fbAddTriangles (PicturePtr  pPicture,
56820                :                INT16       x_off,
56821                :                INT16       y_off,
56822                :                int         ntri,
56823                :                xTriangle *tris)
56824                :{
56825                :    xPointFixed   *top, *left, *right, *tmp;
56826                :    xTrapezoid      trap;
56827                :
56828                :    for (; ntri; ntri--, tris++)
56829                :    {
56830                :        top = &tris->p1;
56831                :        left = &tris->p2;
56832                :        right = &tris->p3;
56833                :        if (_GreaterY (top, left)) {
56834                :            tmp = left; left = top; top = tmp;
56835                :        }
56836                :        if (_GreaterY (top, right)) {
56837                :            tmp = right; right = top; top = tmp;
56838                :        }
56839                :        if (_Clockwise (top, right, left)) {
56840                :            tmp = right; right = left; left = tmp;
56841                :        }
56842                :        
56843                :        /*
56844                :         * Two cases:
56845                :         *
56846                :         *              +               +
56847                :         *             / \             / \
56848                :         *            /   \           /   \
56849                :         *           /     +         +     \
56850                :         *      /    --           --    \
56851                :         *     /   --               --   \
56852                :         *    / ---                   --- \
56853                :         *       +--                         --+
56854                :         */
56855                :        
56856                :        trap.top = top->y;
56857                :        trap.left.p1 = *top;
56858                :        trap.left.p2 = *left;
56859                :        trap.right.p1 = *top;
56860                :        trap.right.p2 = *right;
56861                :        if (right->y < left->y)
56862                :            trap.bottom = right->y;
56863                :        else
56864                :            trap.bottom = left->y;
56865                :        fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
56866                :        if (right->y < left->y)
56867                :        {
56868                :            trap.top = right->y;
56869                :            trap.bottom = left->y;
56870                :            trap.right.p1 = *right;
56871                :            trap.right.p2 = *left;
56872                :        }
56873                :        else
56874                :        {
56875                :            trap.top = left->y;
56876                :            trap.bottom = right->y;
56877                :            trap.left.p1 = *left;
56878                :            trap.left.p2 = *right;
56879                :        }
56880                :        fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
56881                :    }
56882                :}
56883                :
56884                :#endif /* RENDER */
56885 /* 
56886  * Total samples for file : "/home/cworth/opt/xorg//include/X11/Xtrans/Xtrans.c"
56887  * 
56888  *      1  0.0011
56889  */
56890
56891
56892                :/* $XdotOrg: xc/lib/xtrans/Xtrans.c,v 1.4 2004/11/15 15:06:56 ago Exp $ */
56893                :/* $Xorg: Xtrans.c,v 1.4 2001/02/09 02:04:06 xorgcvs Exp $ */
56894                :/*
56895                :
56896                :Copyright 1993, 1994, 1998  The Open Group
56897                :
56898                :Permission to use, copy, modify, distribute, and sell this software and its
56899                :documentation for any purpose is hereby granted without fee, provided that
56900                :the above copyright notice appear in all copies and that both that
56901                :copyright notice and this permission notice appear in supporting
56902                :documentation.
56903                :
56904                :The above copyright notice and this permission notice shall be included
56905                :in all copies or substantial portions of the Software.
56906                :
56907                :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
56908                :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56909                :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56910                :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
56911                :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
56912                :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
56913                :OTHER DEALINGS IN THE SOFTWARE.
56914                :
56915                :Except as contained in this notice, the name of The Open Group shall
56916                :not be used in advertising or otherwise to promote the sale, use or
56917                :other dealings in this Software without prior written authorization
56918                :from The Open Group.
56919                :
56920                :*/
56921                :/* $XFree86: xc/lib/xtrans/Xtrans.c,v 3.33 2003/08/11 17:41:29 eich Exp $ */
56922                :
56923                :/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
56924                : *
56925                : * All Rights Reserved
56926                : *
56927                : * Permission to use, copy, modify, and distribute this software and its
56928                : * documentation for any purpose and without fee is hereby granted, provided
56929                : * that the above copyright notice appear in all copies and that both that
56930                : * copyright notice and this permission notice appear in supporting
56931                : * documentation, and that the name NCR not be used in advertising
56932                : * or publicity pertaining to distribution of the software without specific,
56933                : * written prior permission.  NCR makes no representations about the
56934                : * suitability of this software for any purpose.  It is provided "as is"
56935                : * without express or implied warranty.
56936                : *
56937                : * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
56938                : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
56939                : * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
56940                : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
56941                : * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
56942                : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
56943                : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
56944                : */
56945                :
56946                :#include <ctype.h>
56947                :
56948                :/*
56949                : * The transport table contains a definition for every transport (protocol)
56950                : * family. All operations that can be made on the transport go through this
56951                : * table.
56952                : *
56953                : * Each transport is assigned a unique transport id.
56954                : *
56955                : * New transports can be added by adding an entry in this table.
56956                : * For compatiblity, the transport ids should never be renumbered.
56957                : * Always add to the end of the list.
56958                : */
56959                :
56960                :#define TRANS_TLI_INET_INDEX            1
56961                :#define TRANS_TLI_TCP_INDEX             2
56962                :#define TRANS_TLI_TLI_INDEX             3
56963                :#define TRANS_SOCKET_UNIX_INDEX         4
56964                :#define TRANS_SOCKET_LOCAL_INDEX        5
56965                :#define TRANS_SOCKET_INET_INDEX         6
56966                :#define TRANS_SOCKET_TCP_INDEX          7
56967                :#define TRANS_DNET_INDEX                8
56968                :#define TRANS_LOCAL_LOCAL_INDEX         9
56969                :#define TRANS_LOCAL_PTS_INDEX           10
56970                :#define TRANS_LOCAL_NAMED_INDEX         11
56971                :#define TRANS_LOCAL_ISC_INDEX           12
56972                :#define TRANS_LOCAL_SCO_INDEX           13
56973                :#define TRANS_SOCKET_INET6_INDEX        14
56974                :#define TRANS_LOCAL_PIPE_INDEX          15
56975                :
56976                :
56977                :static
56978                :Xtransport_table Xtransports[] = {
56979                :#if defined(STREAMSCONN)
56980                :    { &TRANS(TLITCPFuncs),      TRANS_TLI_TCP_INDEX },
56981                :    { &TRANS(TLIINETFuncs),     TRANS_TLI_INET_INDEX },
56982                :    { &TRANS(TLITLIFuncs),      TRANS_TLI_TLI_INDEX },
56983                :#endif /* STREAMSCONN */
56984                :#if defined(TCPCONN)
56985                :    { &TRANS(SocketTCPFuncs),   TRANS_SOCKET_TCP_INDEX },
56986                :#if defined(IPv6) && defined(AF_INET6)
56987                :    { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX },
56988                :#endif /* IPv6 */
56989                :    { &TRANS(SocketINETFuncs),  TRANS_SOCKET_INET_INDEX },
56990                :#endif /* TCPCONN */
56991                :#if defined(DNETCONN)
56992                :    { &TRANS(DNETFuncs),        TRANS_DNET_INDEX },
56993                :#endif /* DNETCONN */
56994                :#if defined(UNIXCONN)
56995                :#if !defined(LOCALCONN)
56996                :    { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX },
56997                :#endif /* !LOCALCONN */
56998                :    { &TRANS(SocketUNIXFuncs),  TRANS_SOCKET_UNIX_INDEX },
56999                :#endif /* UNIXCONN */
57000                :#if defined(OS2PIPECONN)
57001                :    { &TRANS(OS2LocalFuncs),    TRANS_LOCAL_LOCAL_INDEX },
57002                :#endif /* OS2PIPECONN */
57003                :#if defined(LOCALCONN)
57004                :    { &TRANS(LocalFuncs),       TRANS_LOCAL_LOCAL_INDEX },
57005                :#ifndef sun
57006                :    { &TRANS(PTSFuncs),         TRANS_LOCAL_PTS_INDEX },
57007                :#endif /* sun */
57008                :#ifdef SVR4
57009                :    { &TRANS(NAMEDFuncs),       TRANS_LOCAL_NAMED_INDEX },
57010                :#endif
57011                :#ifdef sun
57012                :    { &TRANS(PIPEFuncs),        TRANS_LOCAL_PIPE_INDEX },
57013                :#else /* !sun */
57014                :#if !defined(__SCO__) && !defined(__UNIXWARE__)
57015                :    { &TRANS(ISCFuncs),         TRANS_LOCAL_ISC_INDEX },
57016                :#endif
57017                :    { &TRANS(SCOFuncs),         TRANS_LOCAL_SCO_INDEX },
57018                :#endif /* sun */
57019                :#endif /* LOCALCONN */
57020                :};
57021                :
57022                :#define NUMTRANS        (sizeof(Xtransports)/sizeof(Xtransport_table))
57023                :
57024                :
57025                :#ifdef WIN32
57026                :#define ioctl ioctlsocket
57027                :#endif
57028                :
57029                :
57030                :\f
57031                :/*
57032                : * These are a few utility function used by the public interface functions.
57033                : */
57034                :
57035                :void
57036                :TRANS(FreeConnInfo) (XtransConnInfo ciptr)
57037                :
57038                :{
57039                :    PRMSG (3,"FreeConnInfo(%p)\n", ciptr, 0, 0);
57040                :
57041                :    if (ciptr->addr)
57042                :        xfree (ciptr->addr);
57043                :
57044                :    if (ciptr->peeraddr)
57045                :        xfree (ciptr->peeraddr);
57046                :
57047                :    if (ciptr->port)
57048                :        xfree (ciptr->port);
57049                :
57050                :    xfree ((char *) ciptr);
57051                :}
57052                :
57053                :
57054                :#define PROTOBUFSIZE    20
57055                :
57056                :static Xtransport *
57057                :TRANS(SelectTransport) (char *protocol)
57058                :
57059                :{
57060                :    char        protobuf[PROTOBUFSIZE];
57061                :    int         i;
57062                :
57063                :    PRMSG (3,"SelectTransport(%s)\n", protocol, 0, 0);
57064                :
57065                :    /*
57066                :     * Force Protocol to be lowercase as a way of doing
57067                :     * a case insensitive match.
57068                :     */
57069                :
57070                :    strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
57071                :    protobuf[PROTOBUFSIZE-1] = '\0';
57072                :
57073                :    for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
57074                :        if (isupper (protobuf[i]))
57075                :            protobuf[i] = tolower (protobuf[i]);
57076                :
57077                :    /* Look at all of the configured protocols */
57078                :
57079                :    for (i = 0; i < NUMTRANS; i++)
57080                :    {
57081                :        if (!strcmp (protobuf, Xtransports[i].transport->TransName))
57082                :            return Xtransports[i].transport;
57083                :    }
57084                :
57085                :    return NULL;
57086                :}
57087                :
57088                :#ifndef TEST_t
57089                :static
57090                :#endif /* TEST_t */
57091                :int
57092                :TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port)
57093                :
57094                :{
57095                :    /*
57096                :     * For the font library, the address is a string formatted
57097                :     * as "protocol/host:port[/catalogue]".  Note that the catologue
57098                :     * is optional.  At this time, the catologue info is ignored, but
57099                :     * we have to parse it anyways.
57100                :     *
57101                :     * Other than fontlib, the address is a string formatted
57102                :     * as "protocol/host:port".
57103                :     *
57104                :     * If the protocol part is missing, then assume TCP.
57105                :     * If the protocol part and host part are missing, then assume local.
57106                :     * If a "::" is found then assume DNET.
57107                :     */
57108                :
57109                :    char        *mybuf, *tmpptr;
57110                :    char        *_protocol, *_host, *_port;
57111                :    char        hostnamebuf[256];
57112                :    int         _host_len;
57113                :
57114                :    PRMSG (3,"ParseAddress(%s)\n", address, 0, 0);
57115                :
57116                :    /* Copy the string so it can be changed */
57117                :
57118                :    tmpptr = mybuf = (char *) xalloc (strlen (address) + 1);
57119                :    strcpy (mybuf, address);
57120                :
57121                :    /* Parse the string to get each component */
57122                :    
57123                :    /* Get the protocol part */
57124                :
57125                :    _protocol = mybuf;
57126                :
57127                :
57128                :   if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
57129                :      ((mybuf = strrchr (tmpptr,':')) == NULL) )
57130                :   {
57131                :        /* address is in a bad format */
57132                :        *protocol = NULL;
57133                :        *host = NULL;
57134                :        *port = NULL;
57135                :        xfree (tmpptr);
57136                :        return 0;
57137                :    }
57138                :
57139                :    if (*mybuf == ':')
57140                :    {
57141                :        /*
57142                :         * If there is a hostname, then assume tcp, otherwise
57143                :         * it must be local.
57144                :         */
57145                :        if (mybuf == tmpptr)
57146                :        {
57147                :            /* There is neither a protocol or host specified */
57148                :            _protocol = "local";
57149                :        }
57150                :        else
57151                :        {
57152                :            /* There is a hostname specified */
57153                :            _protocol = "tcp";
57154                :            mybuf = tmpptr;     /* reset to the begining of the host ptr */
57155                :        }
57156                :    }
57157                :    else
57158                :    {
57159                :        /* *mybuf == '/' */
57160                :
57161                :        *mybuf ++= '\0'; /* put a null at the end of the protocol */
57162                :
57163                :        if (strlen(_protocol) == 0)
57164                :        {
57165                :            /*
57166                :             * If there is a hostname, then assume tcp, otherwise
57167                :             * it must be local.
57168                :             */
57169                :            if (*mybuf != ':')
57170                :                _protocol = "tcp";
57171                :            else
57172                :                _protocol = "local";
57173                :        }
57174                :    }
57175                :
57176                :    /* Get the host part */
57177                :
57178                :    _host = mybuf;
57179                :
57180                :    if ((mybuf = strrchr (mybuf,':')) == NULL)
57181                :    {
57182                :        *protocol = NULL;
57183                :        *host = NULL;
57184                :        *port = NULL;
57185                :        xfree (tmpptr);
57186                :        return 0;
57187                :    }
57188                :
57189                :    /* Check for DECnet */
57190                :
57191                :    if ((mybuf != _host) && (*(mybuf - 1) == ':')
57192                :#if defined(IPv6) && defined(AF_INET6)
57193                :      /* An IPv6 address can end in :: so three : in a row is assumed to be
57194                :         an IPv6 host and not a DECnet node with a : in it's name, unless
57195                :         DECnet is specifically requested */
57196                :      && ( ((mybuf - 1) == _host) || (*(mybuf - 2) != ':') ||
57197                :        ((_protocol != NULL) && (strcmp(_protocol, "dnet") == 0)) )
57198                :#endif
57199                :        )
57200                :    {
57201                :        _protocol = "dnet";
57202                :        *(mybuf - 1) = '\0';
57203                :    }
57204                :
57205                :    *mybuf ++= '\0';
57206                :
57207                :    _host_len = strlen(_host);
57208                :    if (_host_len == 0)
57209                :    {
57210                :        TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
57211                :        _host = hostnamebuf;
57212                :    }
57213                :#if defined(IPv6) && defined(AF_INET6)
57214                :    /* hostname in IPv6 [numeric_addr]:0 form? */
57215                :    else if ( (_host_len > 3) && 
57216                :      ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
57217                :      && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) { 
57218                :        struct sockaddr_in6 sin6;
57219                :
57220                :        *(_host + _host_len - 1) = '\0';
57221                :
57222                :        /* Verify address is valid IPv6 numeric form */
57223                :        if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
57224                :            /* It is. Use it as such. */
57225                :            _host++;
57226                :            _protocol = "inet6";
57227                :        } else {
57228                :            /* It's not, restore it just in case some other code can use it. */
57229                :            *(_host + _host_len - 1) = ']';
57230                :        }
57231                :    }
57232                :#endif
57233                :
57234                :
57235                :    /* Get the port */
57236                :
57237                :    _port = mybuf;
57238                :
57239                :#if defined(FONT_t) || defined(FS_t)
57240                :    /*
57241                :     * Is there an optional catalogue list?
57242                :     */
57243                :
57244                :    if ((mybuf = strchr (mybuf,'/')) != NULL)
57245                :        *mybuf ++= '\0';
57246                :
57247                :    /*
57248                :     * The rest, if any, is the (currently unused) catalogue list.
57249                :     *
57250                :     * _catalogue = mybuf;
57251                :     */
57252                :#endif
57253                :
57254                :    /*
57255                :     * Now that we have all of the components, allocate new
57256                :     * string space for them.
57257                :     */
57258                :
57259                :    if ((*protocol = (char *) xalloc(strlen (_protocol) + 1)) == NULL)
57260                :    {
57261                :        /* Malloc failed */
57262                :        *port = NULL;
57263                :        *host = NULL;
57264                :        *protocol = NULL;
57265                :        xfree (tmpptr);
57266                :        return 0;
57267                :    }
57268                :    else
57269                :        strcpy (*protocol, _protocol);
57270                :
57271                :    if ((*host = (char *) xalloc (strlen (_host) + 1)) == NULL)
57272                :    {
57273                :        /* Malloc failed */
57274                :        *port = NULL;
57275                :        *host = NULL;
57276                :        xfree (*protocol);
57277                :        *protocol = NULL;
57278                :        xfree (tmpptr);
57279                :        return 0;
57280                :        }
57281                :    else
57282                :        strcpy (*host, _host);
57283                :
57284                :    if ((*port = (char *) xalloc (strlen (_port) + 1)) == NULL)
57285                :    {
57286                :        /* Malloc failed */
57287                :        *port = NULL;
57288                :        xfree (*host);
57289                :        *host = NULL;
57290                :        xfree (*protocol);
57291                :        *protocol = NULL;
57292                :        xfree (tmpptr);
57293                :        return 0;
57294                :    }
57295                :    else
57296                :        strcpy (*port, _port);
57297                :
57298                :    xfree (tmpptr);
57299                :
57300                :    return 1;
57301                :}
57302                :
57303                :
57304                :/*
57305                : * TRANS(Open) does all of the real work opening a connection. The only
57306                : * funny part about this is the type parameter which is used to decide which
57307                : * type of open to perform.
57308                : */
57309                :
57310                :static XtransConnInfo
57311                :TRANS(Open) (int type, char *address)
57312                :
57313                :{
57314                :    char                *protocol = NULL, *host = NULL, *port = NULL;
57315                :    XtransConnInfo      ciptr = NULL;
57316                :    Xtransport          *thistrans;
57317                :
57318                :    PRMSG (2,"Open(%d,%s)\n", type, address, 0);
57319                :
57320                :#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN))
57321                :    if (TRANS(WSAStartup)())
57322                :    {
57323                :        PRMSG (1,"Open: WSAStartup failed\n", 0, 0, 0);
57324                :        return NULL;
57325                :    }
57326                :#endif
57327                :
57328                :    /* Parse the Address */
57329                :
57330                :    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
57331                :    {
57332                :        PRMSG (1,"Open: Unable to Parse address %s\n", address, 0, 0);
57333                :        return NULL;
57334                :    }
57335                :
57336                :    /* Determine the transport type */
57337                :
57338                :    if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
57339                :    {
57340                :        PRMSG (1,"Open: Unable to find transport for %s\n",
57341                :               protocol, 0, 0);
57342                :
57343                :        xfree (protocol);
57344                :        xfree (host);
57345                :        xfree (port);
57346                :        return NULL;
57347                :    }
57348                :
57349                :    /* Open the transport */
57350                :
57351                :    switch (type)
57352                :    {
57353                :    case XTRANS_OPEN_COTS_CLIENT:
57354                :#ifdef TRANS_CLIENT
57355                :        ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
57356                :#endif /* TRANS_CLIENT */
57357                :        break;
57358                :    case XTRANS_OPEN_COTS_SERVER:
57359                :#ifdef TRANS_SERVER
57360                :        ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
57361                :#endif /* TRANS_SERVER */
57362                :        break;
57363                :    case XTRANS_OPEN_CLTS_CLIENT:
57364                :#ifdef TRANS_CLIENT
57365                :        ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
57366                :#endif /* TRANS_CLIENT */
57367                :        break;
57368                :    case XTRANS_OPEN_CLTS_SERVER:
57369                :#ifdef TRANS_SERVER
57370                :        ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
57371                :#endif /* TRANS_SERVER */
57372                :        break;
57373                :    default:
57374                :        PRMSG (1,"Open: Unknown Open type %d\n", type, 0, 0);
57375                :    }
57376                :
57377                :    if (ciptr == NULL)
57378                :    {
57379                :        if (!(thistrans->flags & TRANS_DISABLED)) 
57380                :        {
57381                :            PRMSG (1,"Open: transport open failed for %s/%s:%s\n",
57382                :                   protocol, host, port);
57383                :        }
57384                :        xfree (protocol);
57385                :        xfree (host);
57386                :        xfree (port);
57387                :        return NULL;
57388                :    }
57389                :
57390                :    ciptr->transptr = thistrans;
57391                :    ciptr->port = port;                 /* We need this for TRANS(Reopen) */
57392                :
57393                :    xfree (protocol);
57394                :    xfree (host);
57395                :
57396                :    return ciptr;
57397                :}
57398                :
57399                :
57400                :#ifdef TRANS_REOPEN
57401                :
57402                :/*
57403                : * We might want to create an XtransConnInfo object based on a previously
57404                : * opened connection.  For example, the font server may clone itself and
57405                : * pass file descriptors to the parent.
57406                : */
57407                :
57408                :static XtransConnInfo
57409                :TRANS(Reopen) (int type, int trans_id, int fd, char *port)
57410                :
57411                :{
57412                :    XtransConnInfo      ciptr = NULL;
57413                :    Xtransport          *thistrans = NULL;
57414                :    char                *save_port;
57415                :    int                 i;
57416                :
57417                :    PRMSG (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port);
57418                :
57419                :    /* Determine the transport type */
57420                :
57421                :    for (i = 0; i < NUMTRANS; i++)
57422                :        if (Xtransports[i].transport_id == trans_id)
57423                :        {
57424                :            thistrans = Xtransports[i].transport;
57425                :            break;
57426                :        }
57427                :
57428                :    if (thistrans == NULL)
57429                :    {
57430                :        PRMSG (1,"Reopen: Unable to find transport id %d\n",
57431                :               trans_id, 0, 0);
57432                :
57433                :        return NULL;
57434                :    }
57435                :
57436                :    if ((save_port = (char *) xalloc (strlen (port) + 1)) == NULL)
57437                :    {
57438                :        PRMSG (1,"Reopen: Unable to malloc port string\n", 0, 0, 0);
57439                :
57440                :        return NULL;
57441                :    }
57442                :
57443                :    strcpy (save_port, port);
57444                :
57445                :    /* Get a new XtransConnInfo object */
57446                :
57447                :    switch (type)
57448                :    {
57449                :    case XTRANS_OPEN_COTS_SERVER:
57450                :        ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
57451                :        break;
57452                :    case XTRANS_OPEN_CLTS_SERVER:
57453                :        ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
57454                :        break;
57455                :    default:
57456                :        PRMSG (1,"Reopen: Bad Open type %d\n", type, 0, 0);
57457                :    }
57458                :
57459                :    if (ciptr == NULL)
57460                :    {
57461                :        PRMSG (1,"Reopen: transport open failed\n", 0, 0, 0);
57462                :        return NULL;
57463                :    }
57464                :
57465                :    ciptr->transptr = thistrans;
57466                :    ciptr->port = save_port;
57467                :
57468                :    return ciptr;
57469                :}
57470                :
57471                :#endif /* TRANS_REOPEN */
57472                :
57473                :
57474                :\f
57475                :/*
57476                : * These are the public interfaces to this Transport interface.
57477                : * These are the only functions that should have knowledge of the transport
57478                : * table.
57479                : */
57480                :
57481                :#ifdef TRANS_CLIENT
57482                :
57483                :XtransConnInfo
57484                :TRANS(OpenCOTSClient) (char *address)
57485                :
57486                :{
57487                :    PRMSG (2,"OpenCOTSClient(%s)\n", address, 0, 0);
57488                :    return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
57489                :}
57490                :
57491                :#endif /* TRANS_CLIENT */
57492                :
57493                :
57494                :#ifdef TRANS_SERVER
57495                :
57496                :XtransConnInfo
57497                :TRANS(OpenCOTSServer) (char *address)
57498                :
57499                :{
57500                :    PRMSG (2,"OpenCOTSServer(%s)\n", address, 0, 0);
57501                :    return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
57502                :}
57503                :
57504                :#endif /* TRANS_SERVER */
57505                :
57506                :
57507                :#ifdef TRANS_CLIENT
57508                :
57509                :XtransConnInfo
57510                :TRANS(OpenCLTSClient) (char *address)
57511                :
57512                :{
57513                :    PRMSG (2,"OpenCLTSClient(%s)\n", address, 0, 0);
57514                :    return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
57515                :}
57516                :
57517                :#endif /* TRANS_CLIENT */
57518                :
57519                :
57520                :#ifdef TRANS_SERVER
57521                :
57522                :XtransConnInfo
57523                :TRANS(OpenCLTSServer) (char *address)
57524                :
57525                :{
57526                :    PRMSG (2,"OpenCLTSServer(%s)\n", address, 0, 0);
57527                :    return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
57528                :}
57529                :
57530                :#endif /* TRANS_SERVER */
57531                :
57532                :
57533                :#ifdef TRANS_REOPEN
57534                :
57535                :XtransConnInfo
57536                :TRANS(ReopenCOTSServer) (int trans_id, int fd, char *port)
57537                :
57538                :{
57539                :    PRMSG (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
57540                :    return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
57541                :}
57542                :
57543                :XtransConnInfo
57544                :TRANS(ReopenCLTSServer) (int trans_id, int fd, char *port)
57545                :
57546                :{
57547                :    PRMSG (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port);
57548                :    return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
57549                :}
57550                :
57551                :
57552                :int
57553                :TRANS(GetReopenInfo) (XtransConnInfo ciptr, 
57554                :                      int *trans_id, int *fd, char **port)
57555                :
57556                :{
57557                :    int i;
57558                :
57559                :    for (i = 0; i < NUMTRANS; i++)
57560                :        if (Xtransports[i].transport == ciptr->transptr)
57561                :        {
57562                :            *trans_id = Xtransports[i].transport_id;
57563                :            *fd = ciptr->fd;
57564                :
57565                :            if ((*port = (char *) xalloc (strlen (ciptr->port) + 1)) == NULL)
57566                :                return 0;
57567                :            else
57568                :            {
57569                :                strcpy (*port, ciptr->port);
57570                :                return 1;
57571                :            }
57572                :        }
57573                :
57574                :    return 0;
57575                :}
57576                :
57577                :#endif /* TRANS_REOPEN */
57578                :
57579                :
57580                :int
57581                :TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
57582                :
57583                :{
57584                :    int fd = ciptr->fd;
57585                :    int ret = 0;
57586                :
57587                :    PRMSG (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
57588                :
57589                :    /*
57590                :     * For now, all transport type use the same stuff for setting options.
57591                :     * As long as this is true, we can put the common code here. Once a more
57592                :     * complicated transport such as shared memory or an OSI implementation
57593                :     * that uses the session and application libraries is implemented, this
57594                :     * code may have to move to a transport dependent function.
57595                :     *
57596                :     * ret = ciptr->transptr->SetOption (ciptr, option, arg);
57597                :     */
57598                :
57599                :    switch (option)
57600                :    {
57601                :    case TRANS_NONBLOCKING:
57602                :        switch (arg)
57603                :        {
57604                :        case 0:
57605                :            /* Set to blocking mode */
57606                :            break;
57607                :        case 1: /* Set to non-blocking mode */
57608                :
57609                :#if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux) && !defined(AIXV3) && !defined(uniosu) && !defined(__UNIXOS2__) && !defined(SCO325)) && !defined(__QNX__)
57610                :            ret = fcntl (fd, F_GETFL, 0);
57611                :            if (ret != -1)
57612                :                ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
57613                :#else
57614                :#ifdef FIOSNBIO
57615                :        {
57616                :            int arg;
57617                :            arg = 1;
57618                :            ret = ioctl (fd, FIOSNBIO, &arg);
57619                :        }
57620                :#else
57621                :#if (defined(AIXV3) || defined(uniosu) || defined(WIN32) || defined(__UNIXOS2__) || defined(__QNX__)) && defined(FIONBIO)
57622                :        {
57623                :#ifdef WIN32
57624                :            u_long arg;
57625                :#else
57626                :            int arg;
57627                :#endif
57628                :            arg = 1;
57629                :/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
57630                : * eventually with EWOULDBLOCK */
57631                :#ifndef __UNIXOS2__
57632                :            ret = ioctl (fd, FIONBIO, &arg);
57633                :#else
57634                :/*          ret = ioctl(fd, FIONBIO, &arg, sizeof(int));*/
57635                :#endif
57636                :        }
57637                :#else
57638                :            ret = fcntl (fd, F_GETFL, 0);
57639                :#ifdef FNDELAY
57640                :            ret = fcntl (fd, F_SETFL, ret | FNDELAY);
57641                :#else
57642                :            ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
57643                :#endif
57644                :#endif /* AIXV3  || uniosu */
57645                :#endif /* FIOSNBIO */
57646                :#endif /* O_NONBLOCK */
57647                :            break;
57648                :        default:
57649                :            /* Unknown option */
57650                :            break;
57651                :        }
57652                :        break;
57653                :    case TRANS_CLOSEONEXEC:
57654                :#ifdef F_SETFD
57655                :#ifdef FD_CLOEXEC
57656                :        ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
57657                :#else
57658                :        ret = fcntl (fd, F_SETFD, 1);
57659                :#endif /* FD_CLOEXEC */
57660                :#endif /* F_SETFD */
57661                :        break;
57662                :    }
57663                :    
57664                :    return ret;
57665                :}
57666                :
57667                :#ifdef TRANS_SERVER
57668                :
57669                :int
57670                :TRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
57671                :
57672                :{
57673                :    return ciptr->transptr->CreateListener (ciptr, port, flags);
57674                :}
57675                :
57676                :int
57677                :TRANS(NoListen) (char * protocol)
57678                :        
57679                :{
57680                :   Xtransport *trans;
57681                :   int i = 0, ret = 0;
57682                :   
57683                :   if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 
57684                :   {
57685                :        PRMSG (1,"TransNoListen: unable to find transport: %s\n", 
57686                :               protocol, 0, 0);
57687                :
57688                :        return -1;
57689                :   }
57690                :   if (trans->flags & TRANS_ALIAS) {
57691                :       if (trans->nolisten)
57692                :           while (trans->nolisten[i]) {
57693                :               ret |= TRANS(NoListen)(trans->nolisten[i]);
57694                :               i++;
57695                :       }
57696                :   }
57697                :
57698                :   trans->flags |= TRANS_NOLISTEN;
57699                :   return ret;
57700                :}
57701                :
57702                :int
57703                :TRANS(ResetListener) (XtransConnInfo ciptr)
57704                :
57705                :{
57706                :    if (ciptr->transptr->ResetListener)
57707                :        return ciptr->transptr->ResetListener (ciptr);
57708                :    else
57709                :        return TRANS_RESET_NOOP;
57710                :}
57711                :
57712                :
57713                :XtransConnInfo
57714                :TRANS(Accept) (XtransConnInfo ciptr, int *status)
57715                :
57716                :{
57717                :    XtransConnInfo      newciptr;
57718                :
57719                :    PRMSG (2,"Accept(%d)\n", ciptr->fd, 0, 0);
57720                :
57721                :    newciptr = ciptr->transptr->Accept (ciptr, status);
57722                :
57723                :    if (newciptr)
57724                :        newciptr->transptr = ciptr->transptr;
57725                :
57726                :    return newciptr;
57727                :}
57728                :
57729                :#endif /* TRANS_SERVER */
57730                :
57731                :
57732                :#ifdef TRANS_CLIENT
57733                :
57734                :int
57735                :TRANS(Connect) (XtransConnInfo ciptr, char *address)
57736                :
57737                :{
57738                :    char        *protocol;
57739                :    char        *host;
57740                :    char        *port;
57741                :    int         ret;
57742                :
57743                :    PRMSG (2,"Connect(%d,%s)\n", ciptr->fd, address, 0);
57744                :
57745                :    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
57746                :    {
57747                :        PRMSG (1,"Connect: Unable to Parse address %s\n",
57748                :               address, 0, 0);
57749                :        return -1;
57750                :    }
57751                :
57752                :    if (!port || !*port)
57753                :    {
57754                :        PRMSG (1,"Connect: Missing port specification in %s\n",
57755                :              address, 0, 0);
57756                :        if (protocol) xfree (protocol);
57757                :        if (host) xfree (host);
57758                :        return -1;
57759                :    }
57760                :
57761                :    ret = ciptr->transptr->Connect (ciptr, host, port);
57762                :
57763                :    if (protocol) xfree (protocol);
57764                :    if (host) xfree (host);
57765                :    if (port) xfree (port);
57766                :    
57767                :    return ret;
57768                :}
57769                :
57770                :#endif /* TRANS_CLIENT */
57771                :
57772                :
57773                :int
57774                :TRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
57775                :
57776                :{
57777                :    return ciptr->transptr->BytesReadable (ciptr, pend);
57778                :}
57779                :
57780                :int
57781                :TRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
57782                :
57783                :{ /* _XSERVTransRead total:      1  0.0011 */
57784      1  0.0011 :    return ciptr->transptr->Read (ciptr, buf, size);
57785                :}
57786                :
57787                :int
57788                :TRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
57789                :
57790                :{
57791                :    return ciptr->transptr->Write (ciptr, buf, size);
57792                :}
57793                :
57794                :int
57795                :TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
57796                :
57797                :{
57798                :    return ciptr->transptr->Readv (ciptr, buf, size);
57799                :}
57800                :
57801                :int
57802                :TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
57803                :
57804                :{
57805                :    return ciptr->transptr->Writev (ciptr, buf, size);
57806                :}
57807                :
57808                :int
57809                :TRANS(Disconnect) (XtransConnInfo ciptr)
57810                :
57811                :{
57812                :    return ciptr->transptr->Disconnect (ciptr);
57813                :}
57814                :
57815                :int
57816                :TRANS(Close) (XtransConnInfo ciptr)
57817                :
57818                :{
57819                :    int ret;
57820                :
57821                :    PRMSG (2,"Close(%d)\n", ciptr->fd, 0, 0);
57822                :
57823                :    ret = ciptr->transptr->Close (ciptr);
57824                :
57825                :    TRANS(FreeConnInfo) (ciptr);
57826                :
57827                :    return ret;
57828                :}
57829                :
57830                :int
57831                :TRANS(CloseForCloning) (XtransConnInfo ciptr)
57832                :
57833                :{
57834                :    int ret;
57835                :
57836                :    PRMSG (2,"CloseForCloning(%d)\n", ciptr->fd, 0, 0);
57837                :
57838                :    ret = ciptr->transptr->CloseForCloning (ciptr);
57839                :
57840                :    TRANS(FreeConnInfo) (ciptr);
57841                :
57842                :    return ret;
57843                :}
57844                :
57845                :int
57846                :TRANS(IsLocal) (XtransConnInfo ciptr)
57847                :
57848                :{
57849                :    return (ciptr->family == AF_UNIX);
57850                :}
57851                :
57852                :
57853                :int
57854                :TRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 
57855                :                  Xtransaddr **addrp)
57856                :
57857                :{
57858                :    PRMSG (2,"GetMyAddr(%d)\n", ciptr->fd, 0, 0);
57859                :
57860                :    *familyp = ciptr->family;
57861                :    *addrlenp = ciptr->addrlen;
57862                :
57863                :    if ((*addrp = (Xtransaddr *) xalloc (ciptr->addrlen)) == NULL)
57864                :    {
57865                :        PRMSG (1,"GetMyAddr: malloc failed\n", 0, 0, 0);
57866                :        return -1;
57867                :    }
57868                :    memcpy(*addrp, ciptr->addr, ciptr->addrlen);
57869                :
57870                :    return 0;
57871                :}
57872                :
57873                :int
57874                :TRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 
57875                :                    Xtransaddr **addrp)
57876                :
57877                :{
57878                :    PRMSG (2,"GetPeerAddr(%d)\n", ciptr->fd, 0, 0);
57879                :
57880                :    *familyp = ciptr->family;
57881                :    *addrlenp = ciptr->peeraddrlen;
57882                :
57883                :    if ((*addrp = (Xtransaddr *) xalloc (ciptr->peeraddrlen)) == NULL)
57884                :    {
57885                :        PRMSG (1,"GetPeerAddr: malloc failed\n", 0, 0, 0);
57886                :        return -1;
57887                :    }
57888                :    memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
57889                :
57890                :    return 0;
57891                :}
57892                :
57893                :
57894                :int
57895                :TRANS(GetConnectionNumber) (XtransConnInfo ciptr)
57896                :
57897                :{
57898                :    return ciptr->fd;
57899                :}
57900                :
57901                :\f
57902                :/*
57903                : * These functions are really utility functions, but they require knowledge
57904                : * of the internal data structures, so they have to be part of the Transport
57905                : * Independant API.
57906                : */
57907                :
57908                :#ifdef TRANS_SERVER
57909                :
57910                :static int
57911                :complete_network_count (void)
57912                :
57913                :{
57914                :    int count = 0;
57915                :    int found_local = 0;
57916                :    int i;
57917                :
57918                :    /*
57919                :     * For a complete network, we only need one LOCALCONN transport to work
57920                :     */
57921                :
57922                :    for (i = 0; i < NUMTRANS; i++)
57923                :    {
57924                :        if (Xtransports[i].transport->flags & TRANS_ALIAS
57925                :         || Xtransports[i].transport->flags & TRANS_NOLISTEN)
57926                :            continue;
57927                :
57928                :        if (Xtransports[i].transport->flags & TRANS_LOCAL)
57929                :            found_local = 1;
57930                :        else
57931                :            count++;
57932                :    }
57933                :
57934                :    return (count + found_local);
57935                :}
57936                :
57937                :
57938                :
57939                :int
57940                :TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, 
57941                :                                   XtransConnInfo **ciptrs_ret)
57942                :
57943                :{
57944                :    char                buffer[256]; /* ??? What size ?? */
57945                :    XtransConnInfo      ciptr, temp_ciptrs[NUMTRANS];
57946                :    int                 status, i, j;
57947                :#if defined(IPv6) && defined(AF_INET6)
57948                :    int         ipv6_succ = 0;
57949                :#endif
57950                :
57951                :    PRMSG (2,"MakeAllCOTSServerListeners(%s,%p)\n",
57952                :           port ? port : "NULL", ciptrs_ret, 0);
57953                :
57954                :    *count_ret = 0;
57955                :
57956                :    for (i = 0; i < NUMTRANS; i++)
57957                :    {
57958                :        Xtransport *trans = Xtransports[i].transport;
57959                :        unsigned int flags = 0;
57960                :
57961                :        if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
57962                :            continue;
57963                :
57964                :        snprintf(buffer, sizeof(buffer), "%s/:%s",
57965                :                 trans->TransName, port ? port : "");
57966                :
57967                :        PRMSG (5,"MakeAllCOTSServerListeners: opening %s\n",
57968                :               buffer, 0, 0);
57969                :
57970                :        if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
57971                :        {
57972                :            if (trans->flags & TRANS_DISABLED)
57973                :                continue;
57974                :
57975                :            PRMSG (1,
57976                :          "MakeAllCOTSServerListeners: failed to open listener for %s\n",
57977                :                  trans->TransName, 0, 0);
57978                :            continue;
57979                :        }
57980                :#if defined(IPv6) && defined(AF_INET6)
57981                :                if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
57982                :                     && ipv6_succ))
57983                :                    flags |= ADDR_IN_USE_ALLOWED;
57984                :#endif
57985                :
57986                :        if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
57987                :        {
57988                :            if (status == TRANS_ADDR_IN_USE)
57989                :            {
57990                :                /*
57991                :                 * We failed to bind to the specified address because the
57992                :                 * address is in use.  It must be that a server is already
57993                :                 * running at this address, and this function should fail.
57994                :                 */
57995                :
57996                :                PRMSG (1,
57997                :                "MakeAllCOTSServerListeners: server already running\n",
57998                :                  0, 0, 0);
57999                :
58000                :                for (j = 0; j < *count_ret; j++)
58001                :                    TRANS(Close) (temp_ciptrs[j]);
58002                :
58003                :                *count_ret = 0;
58004                :                *ciptrs_ret = NULL;
58005                :                *partial = 0;
58006                :                return -1;
58007                :            }
58008                :            else
58009                :            {
58010                :                PRMSG (1,
58011                :        "MakeAllCOTSServerListeners: failed to create listener for %s\n",
58012                :                  trans->TransName, 0, 0);
58013                :
58014                :                continue;
58015                :            }
58016                :        }
58017                :
58018                :#if defined(IPv6) && defined(AF_INET6)
58019                :        if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
58020                :            ipv6_succ = 1;
58021                :#endif
58022                :        
58023                :        PRMSG (5,
58024                :              "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
58025                :              trans->TransName, ciptr->fd, 0);
58026                :
58027                :        temp_ciptrs[*count_ret] = ciptr;
58028                :        (*count_ret)++;
58029                :    }
58030                :
58031                :    *partial = (*count_ret < complete_network_count());
58032                :
58033                :    PRMSG (5,
58034                :     "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n",
58035                :        *partial, *count_ret, complete_network_count());
58036                :
58037                :    if (*count_ret > 0)
58038                :    {
58039                :        if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
58040                :            *count_ret * sizeof (XtransConnInfo))) == NULL)
58041                :        {
58042                :            return -1;
58043                :        }
58044                :
58045                :        for (i = 0; i < *count_ret; i++)
58046                :        {
58047                :            (*ciptrs_ret)[i] = temp_ciptrs[i];
58048                :        }
58049                :    }
58050                :    else
58051                :        *ciptrs_ret = NULL;
58052                : 
58053                :    return 0;
58054                :}
58055                :
58056                :int
58057                :TRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret, 
58058                :                                   XtransConnInfo **ciptrs_ret)
58059                :
58060                :{
58061                :    char                buffer[256]; /* ??? What size ?? */
58062                :    XtransConnInfo      ciptr, temp_ciptrs[NUMTRANS];
58063                :    int                 status, i, j;
58064                :
58065                :    PRMSG (2,"MakeAllCLTSServerListeners(%s,%p)\n",
58066                :        port ? port : "NULL", ciptrs_ret, 0);
58067                :
58068                :    *count_ret = 0;
58069                :
58070                :    for (i = 0; i < NUMTRANS; i++)
58071                :    {
58072                :        Xtransport *trans = Xtransports[i].transport;
58073                :
58074                :        if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
58075                :            continue;
58076                :
58077                :        snprintf(buffer, sizeof(buffer), "%s/:%s",
58078                :                 trans->TransName, port ? port : "");
58079                :
58080                :        PRMSG (5,"MakeAllCLTSServerListeners: opening %s\n",
58081                :            buffer, 0, 0);
58082                :
58083                :        if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
58084                :        {
58085                :            PRMSG (1,
58086                :        "MakeAllCLTSServerListeners: failed to open listener for %s\n",
58087                :                  trans->TransName, 0, 0);
58088                :            continue;
58089                :        }
58090                :
58091                :        if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0)
58092                :        {
58093                :            if (status == TRANS_ADDR_IN_USE)
58094                :            {
58095                :                /*
58096                :                 * We failed to bind to the specified address because the
58097                :                 * address is in use.  It must be that a server is already
58098                :                 * running at this address, and this function should fail.
58099                :                 */
58100                :
58101                :                PRMSG (1,
58102                :                "MakeAllCLTSServerListeners: server already running\n",
58103                :                  0, 0, 0);
58104                :
58105                :                for (j = 0; j < *count_ret; j++)
58106                :                    TRANS(Close) (temp_ciptrs[j]);
58107                :
58108                :                *count_ret = 0;
58109                :                *ciptrs_ret = NULL;
58110                :                *partial = 0;
58111                :                return -1;
58112                :            }
58113                :            else
58114                :            {
58115                :                PRMSG (1,
58116                :        "MakeAllCLTSServerListeners: failed to create listener for %s\n",
58117                :                  trans->TransName, 0, 0);
58118                :
58119                :                continue;
58120                :            }
58121                :        }
58122                :
58123                :        PRMSG (5,
58124                :        "MakeAllCLTSServerListeners: opened listener for %s, %d\n",
58125                :              trans->TransName, ciptr->fd, 0);
58126                :        temp_ciptrs[*count_ret] = ciptr;
58127                :        (*count_ret)++;
58128                :    }
58129                :
58130                :    *partial = (*count_ret < complete_network_count());
58131                :
58132                :    PRMSG (5,
58133                :     "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n",
58134                :        *partial, *count_ret, complete_network_count());
58135                :
58136                :    if (*count_ret > 0)
58137                :    {
58138                :        if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
58139                :            *count_ret * sizeof (XtransConnInfo))) == NULL)
58140                :        {
58141                :            return -1;
58142                :        }
58143                :
58144                :        for (i = 0; i < *count_ret; i++)
58145                :        {
58146                :            (*ciptrs_ret)[i] = temp_ciptrs[i];
58147                :        }
58148                :    }
58149                :    else
58150                :        *ciptrs_ret = NULL;
58151                :    
58152                :    return 0;
58153                :}
58154                :
58155                :#endif /* TRANS_SERVER */
58156                :
58157                :
58158                :\f
58159                :/*
58160                : * These routines are not part of the X Transport Interface, but they
58161                : * may be used by it.
58162                : */
58163                :
58164                :#ifdef CRAY
58165                :
58166                :/*
58167                : * Cray UniCOS does not have readv and writev so we emulate
58168                : */
58169                :
58170                :static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
58171                :
58172                :{
58173                :    struct msghdr hdr;
58174                :
58175                :    hdr.msg_iov = iov;
58176                :    hdr.msg_iovlen = iovcnt;
58177                :    hdr.msg_accrights = 0;
58178                :    hdr.msg_accrightslen = 0;
58179                :    hdr.msg_name = 0;
58180                :    hdr.msg_namelen = 0;
58181                :
58182                :    return (recvmsg (ciptr->fd, &hdr, 0));
58183                :}
58184                :
58185                :static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
58186                :
58187                :{
58188                :    struct msghdr hdr;
58189                :
58190                :    hdr.msg_iov = iov;
58191                :    hdr.msg_iovlen = iovcnt;
58192                :    hdr.msg_accrights = 0;
58193                :    hdr.msg_accrightslen = 0;
58194                :    hdr.msg_name = 0;
58195                :    hdr.msg_namelen = 0;
58196                :
58197                :    return (sendmsg (ciptr->fd, &hdr, 0));
58198                :}
58199                :
58200                :#endif /* CRAY */
58201                :
58202                :#if (defined(SYSV) && defined(i386) && !defined(__SCO__) && !defined(sun)) || defined(WIN32) || defined(__sxg__) || defined(__UNIXOS2__)
58203                :
58204                :/*
58205                : * emulate readv
58206                : */
58207                :
58208                :static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
58209                :
58210                :{
58211                :    int i, len, total;
58212                :    char *base;
58213                :
58214                :    ESET(0);
58215                :    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
58216                :        len = iov->iov_len;
58217                :        base = iov->iov_base;
58218                :        while (len > 0) {
58219                :            register int nbytes;
58220                :            nbytes = TRANS(Read) (ciptr, base, len);
58221                :            if (nbytes < 0 && total == 0)  return -1;
58222                :            if (nbytes <= 0)  return total;
58223                :            ESET(0);
58224                :            len   -= nbytes;
58225                :            total += nbytes;
58226                :            base  += nbytes;
58227                :        }
58228                :    }
58229                :    return total;
58230                :}
58231                :
58232                :#endif /* SYSV && i386 || WIN32 || __sxg__ */
58233                :
58234                :#if (defined(SYSV) && defined(i386) && !defined(__SCO__) && !defined(sun)) || defined(WIN32) || defined(__sxg__) || defined(__UNIXOS2__)
58235                :
58236                :/*
58237                : * emulate writev
58238                : */
58239                :
58240                :static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
58241                :
58242                :{
58243                :    int i, len, total;
58244                :    char *base;
58245                :
58246                :    ESET(0);
58247                :    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
58248                :        len = iov->iov_len;
58249                :        base = iov->iov_base;
58250                :        while (len > 0) {
58251                :            register int nbytes;
58252                :            nbytes = TRANS(Write) (ciptr, base, len);
58253                :            if (nbytes < 0 && total == 0)  return -1;
58254                :            if (nbytes <= 0)  return total;
58255                :            ESET(0);
58256                :            len   -= nbytes;
58257                :            total += nbytes;
58258                :            base  += nbytes;
58259                :        }
58260                :    }
58261                :    return total;
58262                :}
58263                :
58264                :#endif /* SYSV && i386 || WIN32 || __sxg__ */
58265                :
58266                :
58267                :#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) || defined(__SCO__)
58268                :#ifndef NEED_UTSNAME
58269                :#define NEED_UTSNAME
58270                :#endif
58271                :#include <sys/utsname.h>
58272                :#endif
58273                :
58274                :/*
58275                : * TRANS(GetHostname) - similar to gethostname but allows special processing.
58276                : */
58277                :
58278                :int TRANS(GetHostname) (char *buf, int maxlen)
58279                :
58280                :{
58281                :    int len;
58282                :
58283                :#ifdef NEED_UTSNAME
58284                :    struct utsname name;
58285                :
58286                :    uname (&name);
58287                :    len = strlen (name.nodename);
58288                :    if (len >= maxlen) len = maxlen - 1;
58289                :    strncpy (buf, name.nodename, len);
58290                :    buf[len] = '\0';
58291                :#else
58292                :    buf[0] = '\0';
58293                :    (void) gethostname (buf, maxlen);
58294                :    buf [maxlen - 1] = '\0';
58295                :    len = strlen(buf);
58296                :#endif /* NEED_UTSNAME */
58297                :    return len;
58298                :}