/* * Command line: opannotate --source * * Interpretation of command line: * Output annotated source file with samples * Output all files * * CPU: Core 2, speed 2133.49 MHz (estimated) * Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000 */ /* * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i830_accel.c" * * 31562 34.3831 */ :/* : * XXX So far, for GXxor this is about 40% of the speed of SW, but CPU : * utilisation falls from 95% to < 5%. : */ : :#ifdef HAVE_CONFIG_H :#include "config.h" :#endif : :/************************************************************************** : :Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. :All Rights Reserved. : :Permission is hereby granted, free of charge, to any person obtaining a :copy of this software and associated documentation files (the :"Software"), to deal in the Software without restriction, including :without limitation the rights to use, copy, modify, merge, publish, :distribute, sub license, and/or sell copies of the Software, and to :permit persons to whom the Software is furnished to do so, subject to :the following conditions: : :The above copyright notice and this permission notice (including the :next paragraph) shall be included in all copies or substantial portions :of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. :IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR :ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, :TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE :SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :**************************************************************************/ :/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_accel.c,v 1.8 2003/04/24 18:00:24 eich Exp $ */ : :/* : * Reformatted with GNU indent (2.2.8), using the following options: : * : * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78 : * -lp -npcs -psl -sob -ss -br -ce -sc -hnl : * : * This provides a good match with the original i810 code and preferred : * XFree86 formatting conventions. : * : * When editing this driver, please follow the existing formatting, and edit : * with characters expanded at 8-column intervals. : */ : :/* : * Authors: : * Keith Whitwell : * : */ : :#include "xf86.h" :#include "xaarop.h" :#include "i830.h" :#include "i810_reg.h" :#include "i830_debug.h" : :unsigned long :intel_get_pixmap_offset(PixmapPtr pPix) 15 0.0163 :{ /* intel_get_pixmap_offset total: 77 0.0839 */ : ScreenPtr pScreen = pPix->drawable.pScreen; : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 27 0.0294 : I830Ptr pI830 = I830PTR(pScrn); : :#ifdef I830_USE_EXA 24 0.0261 : if (pI830->useEXA) 4 0.0044 : return exaGetPixmapOffset(pPix); :#endif : return (unsigned long)pPix->devPrivate.ptr - (unsigned long)pI830->FbBase; 7 0.0076 :} : :unsigned long :intel_get_pixmap_pitch(PixmapPtr pPix) 12 0.0131 :{ /* intel_get_pixmap_pitch total: 83 0.0904 */ : ScreenPtr pScreen = pPix->drawable.pScreen; : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : :#ifdef I830_USE_EXA 57 0.0621 : if (pI830->useEXA) 4 0.0044 : return exaGetPixmapPitch(pPix); :#endif :#ifdef I830_USE_XAA : return (unsigned long)pPix->devKind; :#endif 10 0.0109 :} : :int :I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) 10 0.0109 :{ /* I830WaitLpRing total: 31130 33.9125 */ 2 0.0022 : I830Ptr pI830 = I830PTR(pScrn); 1 0.0011 : I830RingBuffer *ring = pI830->LpRing; : int iters = 0; : unsigned int start = 0; : unsigned int now = 0; : int last_head = 0; : unsigned int first = 0; : : /* If your system hasn't moved the head pointer in 2 seconds, I'm going to : * call it crashed. : */ : if (timeout_millis == 0) : timeout_millis = 2000; : : if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) { : ErrorF("I830WaitLpRing %d\n", n); : first = GetTimeInMillis(); : } : 383 0.4172 : while (ring->space < n) { 217 0.2364 : ring->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; 30204 32.9038 : ring->space = ring->head - (ring->tail + 8); : : if (ring->space < 0) 145 0.1580 : ring->space += ring->mem->size; : 93 0.1013 : iters++; : if ((iters & 0xfff) == 0) { : now = GetTimeInMillis(); : if (start == 0 || now < start || ring->head != last_head) { : if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) : if (now > start) : ErrorF("space: %d wanted %d\n", ring->space, n); : start = now; : last_head = ring->head; : } else if (now - start > timeout_millis) { : ErrorF("Error in I830WaitLpRing(), timeout for %d seconds\n", : timeout_millis/1000); : if (IS_I965G(pI830)) : i965_dump_error_state(pScrn); : else : i830_dump_error_state(pScrn); : ErrorF("space: %d wanted %d\n", ring->space, n); :#ifdef XF86DRI : if (pI830->directRenderingEnabled) { : DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); : DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]); : } :#endif :#ifdef I830_USE_XAA : pI830->AccelInfoRec = NULL; /* Stops recursive behavior */ :#endif :#ifdef I830_USE_EXA : pI830->EXADriverPtr = NULL; :#endif 1 0.0011 : FatalError("lockup\n"); : } : } : DELAY(10); : } : : if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) { : now = GetTimeInMillis(); : if (now - first) { : ErrorF("Elapsed %u ms\n", now - first); : ErrorF("space: %d wanted %d\n", ring->space, n); : } : } : : return iters; 74 0.0806 :} : :void :I830Sync(ScrnInfoPtr pScrn) 6 0.0065 :{ /* I830Sync total: 272 0.2963 */ 2 0.0022 : I830Ptr pI830 = I830PTR(pScrn); : int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE; : : if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC)) : ErrorF("I830Sync\n"); : :#ifdef XF86DRI : /* VT switching tries to do this. : */ : if (!pI830->LockHeld && pI830->directRenderingEnabled) { : return; : } :#endif : 1 0.0011 : if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) return; : 6 0.0065 : if (IS_I965G(pI830)) : flags = 0; : : /* Send a flush instruction and then wait till the ring is empty. : * This is stronger than waiting for the blitter to finish as it also : * flushes the internal graphics caches. : */ : : { 3 0.0033 : BEGIN_LP_RING(2); 11 0.0120 : OUT_RING(MI_FLUSH | flags); 11 0.0120 : OUT_RING(MI_NOOP); /* pad to quadword */ 17 0.0185 : ADVANCE_LP_RING(); : } : 168 0.1830 : I830WaitLpRing(pScrn, pI830->LpRing->mem->size - 8, 0); : 37 0.0403 : pI830->LpRing->space = pI830->LpRing->mem->size - 8; 1 0.0011 : pI830->nextColorExpandBuf = 0; 9 0.0098 :} : :void :I830EmitFlush(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE; : : if (IS_I965G(pI830)) : flags = 0; : : { : BEGIN_LP_RING(2); : OUT_RING(MI_FLUSH | flags); : OUT_RING(MI_NOOP); /* pad to quadword */ : ADVANCE_LP_RING(); : } :} : :void :I830SelectBuffer(ScrnInfoPtr pScrn, int buffer) :{ : I830Ptr pI830 = I830PTR(pScrn); : : switch (buffer) { :#ifdef XF86DRI : case I830_SELECT_BACK: : pI830->bufferOffset = pI830->back_buffer->offset; : break; : case I830_SELECT_THIRD: : pI830->bufferOffset = pI830->third_buffer->offset; : break; : case I830_SELECT_DEPTH: : pI830->bufferOffset = pI830->depth_buffer->offset; : break; :#endif : default: : case I830_SELECT_FRONT: : pI830->bufferOffset = pScrn->fbOffset; : break; : } : : if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) : ErrorF("I830SelectBuffer %d --> offset %x\n", : buffer, pI830->bufferOffset); :} : :void :I830RefreshRing(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : : pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; : pI830->LpRing->tail = INREG(LP_RING + RING_TAIL); : pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8); : if (pI830->LpRing->space < 0) : pI830->LpRing->space += pI830->LpRing->mem->size; : i830MarkSync(pScrn); :} : :/* The following function sets up the supported acceleration. Call it : * from the FbInit() function in the SVGA driver, or before ScreenInit : * in a monolithic server. : */ :Bool :I830AccelInit(ScreenPtr pScreen) :{ :#ifdef I830_USE_EXA : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : : if (pI830->useEXA) : return I830EXAInit(pScreen); :#endif :#ifdef I830_USE_XAA : return I830XAAInit(pScreen); :#endif : return FALSE; :} /* * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i965_render.c" * * 12731 13.8689 */ :/* : * Copyright © 2006 Intel Corporation : * : * Permission is hereby granted, free of charge, to any person obtaining a : * copy of this software and associated documentation files (the "Software"), : * to deal in the Software without restriction, including without limitation : * the rights to use, copy, modify, merge, publish, distribute, sublicense, : * and/or sell copies of the Software, and to permit persons to whom the : * Software is furnished to do so, subject to the following conditions: : * : * The above copyright notice and this permission notice (including the next : * paragraph) shall be included in all copies or substantial portions of the : * Software. : * : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE : * SOFTWARE. : * : * Authors: : * Wang Zhenyu : * Eric Anholt : * : */ : :#ifdef HAVE_CONFIG_H :#include "config.h" :#endif : :#include :#include "xf86.h" :#include "i830.h" :#include "i915_reg.h" : :/* bring in brw structs */ :#include "brw_defines.h" :#include "brw_structs.h" : :#ifdef I830DEBUG :#define DEBUG_I830FALLBACK 1 :#endif : :#ifdef DEBUG_I830FALLBACK :#define I830FALLBACK(s, arg...) \ :do { \ : DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \ : return FALSE; \ :} while(0) :#else :#define I830FALLBACK(s, arg...) \ :do { \ : return FALSE; \ :} while(0) :#endif : :struct blendinfo { : Bool dst_alpha; : Bool src_alpha; : CARD32 src_blend; : CARD32 dst_blend; :}; : :struct formatinfo { : int fmt; : CARD32 card_fmt; :}; : :// refer vol2, 3d rasterization 3.8.1 : :/* defined in brw_defines.h */ :static struct blendinfo i965_blend_op[] = { : /* Clear */ : {0, 0, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_ZERO}, : /* Src */ : {0, 0, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_ZERO}, : /* Dst */ : {0, 0, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_ONE}, : /* Over */ : {0, 1, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_INV_SRC_ALPHA}, : /* OverReverse */ : {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ONE}, : /* In */ : {1, 0, BRW_BLENDFACTOR_DST_ALPHA, BRW_BLENDFACTOR_ZERO}, : /* InReverse */ : {0, 1, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_SRC_ALPHA}, : /* Out */ : {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ZERO}, : /* OutReverse */ : {0, 1, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_INV_SRC_ALPHA}, : /* Atop */ : {1, 1, BRW_BLENDFACTOR_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA}, : /* AtopReverse */ : {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_SRC_ALPHA}, : /* Xor */ : {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA}, : /* Add */ : {0, 0, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_ONE}, :}; : :/* FIXME: surface format defined in brw_defines.h, shared Sampling engine : * 1.7.2 : */ :static struct formatinfo i965_tex_formats[] = { : {PICT_a8r8g8b8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM }, : {PICT_x8r8g8b8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM }, : {PICT_a8b8g8r8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM }, : {PICT_x8b8g8r8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM }, : {PICT_r5g6b5, BRW_SURFACEFORMAT_B5G6R5_UNORM }, : {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM }, : {PICT_a8, BRW_SURFACEFORMAT_A8_UNORM }, :}; : :static void i965_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format, : CARD32 *sblend, CARD32 *dblend) :{ : : *sblend = i965_blend_op[op].src_blend; : *dblend = i965_blend_op[op].dst_blend; : : /* If there's no dst alpha channel, adjust the blend op so that we'll treat : * it as always 1. : */ : if (PICT_FORMAT_A(dst_format) == 0 && i965_blend_op[op].dst_alpha) { : if (*sblend == BRW_BLENDFACTOR_DST_ALPHA) : *sblend = BRW_BLENDFACTOR_ONE; : else if (*sblend == BRW_BLENDFACTOR_INV_DST_ALPHA) : *sblend = BRW_BLENDFACTOR_ZERO; : } : : /* If the source alpha is being used, then we should only be in a case where : * the source blend factor is 0, and the source blend value is the mask : * channels multiplied by the source picture's alpha. : */ : if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) : && i965_blend_op[op].src_alpha) { : if (*dblend == BRW_BLENDFACTOR_SRC_ALPHA) { : *dblend = BRW_BLENDFACTOR_SRC_COLOR; : } else if (*dblend == BRW_BLENDFACTOR_INV_SRC_ALPHA) { : *dblend = BRW_BLENDFACTOR_INV_SRC_COLOR; : } : } : :} : :static Bool i965_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format) 8 0.0087 :{ /* i965_get_dest_format total: 28 0.0305 */ 10 0.0109 : switch (pDstPicture->format) { : case PICT_a8r8g8b8: : case PICT_x8r8g8b8: 1 0.0011 : *dst_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; : break; : case PICT_r5g6b5: : *dst_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; : break; : case PICT_a1r5g5b5: : *dst_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM; : break; : case PICT_x1r5g5b5: : *dst_format = BRW_SURFACEFORMAT_B5G5R5X1_UNORM; : break; : /* COLR_BUF_8BIT is special for YUV surfaces. While we may end up being : * able to use it depending on how the hardware implements it, disable it : * for now while we don't know what exactly it does (what channel does it : * read from? : */ : /* : case PICT_a8: : *dst_format = COLR_BUF_8BIT; : break; : */ : case PICT_a4r4g4b4: : case PICT_x4r4g4b4: : *dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; : break; : default: : I830FALLBACK("Unsupported dest format 0x%x\n", : (int)pDstPicture->format); : } : : return TRUE; 9 0.0098 :} : :static Bool i965_check_composite_texture(PicturePtr pPict, int unit) 28 0.0305 :{ /* i965_check_composite_texture total: 73 0.0795 */ 3 0.0033 : int w = pPict->pDrawable->width; : int h = pPict->pDrawable->height; : int i; : 15 0.0163 : if ((w > 0x7ff) || (h > 0x7ff)) : I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h); : : for (i = 0; i < sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]); : i++) : { 9 0.0098 : if (i965_tex_formats[i].fmt == pPict->format) : break; : } 7 0.0076 : if (i == sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0])) : I830FALLBACK("Unsupported picture format 0x%x\n", : (int)pPict->format); : 4 0.0044 : if (pPict->repeat && pPict->repeatType != RepeatNormal) : I830FALLBACK("extended repeat (%d) not supported\n", : pPict->repeatType); : : if (pPict->filter != PictFilterNearest && : pPict->filter != PictFilterBilinear) : { : I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter); : } : : return TRUE; 7 0.0076 :} : :Bool :i965_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, : PicturePtr pDstPicture) 9 0.0098 :{ /* i965_check_composite total: 54 0.0588 */ : CARD32 tmp1; : : /* Check for unsupported compositing operations. */ : if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0])) : I830FALLBACK("Unsupported Composite op 0x%x\n", op); : 4 0.0044 : if (pMaskPicture && pMaskPicture->componentAlpha && : PICT_FORMAT_RGB(pMaskPicture->format)) { : /* Check if it's component alpha that relies on a source alpha and on : * the source value. We can only get one of those into the single : * source value that we get to blend with. : */ 11 0.0120 : if (i965_blend_op[op].src_alpha && : (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO)) : { : I830FALLBACK("Component alpha not supported with source " : "alpha and source value blending.\n"); : } : } : 9 0.0098 : if (!i965_check_composite_texture(pSrcPicture, 0)) : I830FALLBACK("Check Src picture texture\n"); 2 0.0022 : if (pMaskPicture != NULL && !i965_check_composite_texture(pMaskPicture, 1)) : I830FALLBACK("Check Mask picture texture\n"); : 9 0.0098 : if (!i965_get_dest_format(pDstPicture, &tmp1)) : I830FALLBACK("Get Color buffer format\n"); : : return TRUE; : 10 0.0109 :} : :#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) :#define MIN(a,b) ((a) < (b) ? (a) : (b)) :#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1) : :static int urb_vs_start, urb_vs_size; :static int urb_gs_start, urb_gs_size; :static int urb_clip_start, urb_clip_size; :static int urb_sf_start, urb_sf_size; :static int urb_cs_start, urb_cs_size; : :static struct brw_surface_state *dest_surf_state, dest_surf_state_local; :static struct brw_surface_state *src_surf_state, src_surf_state_local; :static struct brw_surface_state *mask_surf_state, mask_surf_state_local; :static struct brw_sampler_state *src_sampler_state, src_sampler_state_local; :static struct brw_sampler_state *mask_sampler_state, mask_sampler_state_local; :static struct brw_sampler_default_color *default_color_state; : :static struct brw_vs_unit_state *vs_state, vs_state_local; :static struct brw_sf_unit_state *sf_state, sf_state_local; :static struct brw_wm_unit_state *wm_state, wm_state_local; :static struct brw_cc_unit_state *cc_state, cc_state_local; :static struct brw_cc_viewport *cc_viewport; : :static struct brw_instruction *sf_kernel; :static struct brw_instruction *ps_kernel; :static struct brw_instruction *sip_kernel; : :static CARD32 *binding_table; :static int binding_table_entries; : :static int dest_surf_offset, src_surf_offset, mask_surf_offset; :static int src_sampler_offset, mask_sampler_offset,vs_offset; :static int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset; :static int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset; :static int wm_scratch_offset; :static int binding_table_offset; :static int default_color_offset; :static int next_offset, total_state_size; :static char *state_base; :static int state_base_offset; :static float *vb; :static int vb_size = (4 * 4) * 4 ; /* 4 DWORDS per vertex*/ : :static CARD32 src_blend, dst_blend; : :static const CARD32 sip_kernel_static[][4] = { :/* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */ : { 0x00000030, 0x20000108, 0x00001220, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :/* nop (4) g0<1>UD { align1 + } */ : { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, :}; : :/* : * this program computes dA/dx and dA/dy for the texture coordinates along : * with the base texture coordinate. It was extracted from the Mesa driver : */ : :#define SF_KERNEL_NUM_GRF 16 :#define SF_MAX_THREADS 1 : :static const CARD32 sf_kernel_static[][4] = { :#include "exa_sf_prog.h" :}; : :static const CARD32 sf_kernel_static_mask[][4] = { :#include "exa_sf_mask_prog.h" :}; : :static const CARD32 sf_kernel_static_rotation[][4] = { :#include "exa_sf_rotation_prog.h" :}; : :/* ps kernels */ :#define PS_KERNEL_NUM_GRF 32 :#define PS_MAX_THREADS 32 : :static const CARD32 ps_kernel_static_nomask [][4] = { :#include "exa_wm_nomask_prog.h" :}; : :static const CARD32 ps_kernel_static_maskca [][4] = { :#include "exa_wm_maskca_prog.h" :}; : :static const CARD32 ps_kernel_static_maskca_srcalpha [][4] = { :#include "exa_wm_maskca_srcalpha_prog.h" :}; : :static const CARD32 ps_kernel_static_masknoca [][4] = { :#include "exa_wm_masknoca_prog.h" :}; : :static const CARD32 ps_kernel_static_rotation [][4] = { :#include "exa_wm_rotation_prog.h" :}; : :static CARD32 :i965_get_card_format(PicturePtr pPict) 27 0.0294 :{ /* i965_get_card_format total: 32 0.0349 */ : int i; : 4 0.0044 : for (i = 0; i < sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]); : i++) : { 1 0.0011 : if (i965_tex_formats[i].fmt == pPict->format) : break; : } : return i965_tex_formats[i].card_fmt; :} : :static Bool :i965_check_rotation_transform(PictTransformPtr t) :{ : /* XXX this is arbitrary */ : int a, b; : a = xFixedToInt(t->matrix[0][1]); : b = xFixedToInt(t->matrix[1][0]); : if (a == -1 && b == 1) : return TRUE; : else if (a == 1 && b == -1) : return TRUE; : else : return FALSE; :} : :Bool :i965_prepare_composite(int op, PicturePtr pSrcPicture, : PicturePtr pMaskPicture, PicturePtr pDstPicture, : PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) 3 0.0033 :{ /* i965_prepare_composite total: 9782 10.6564 */ 29 0.0316 : ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum]; 7 0.0076 : I830Ptr pI830 = I830PTR(pScrn); : CARD32 src_offset, src_pitch; : CARD32 mask_offset = 0, mask_pitch = 0; : CARD32 dst_format, dst_offset, dst_pitch; : Bool rotation_program = FALSE; : : IntelEmitInvarientState(pScrn); 6 0.0065 : *pI830->last_3d = LAST_3D_RENDER; : 6 0.0065 : src_offset = intel_get_pixmap_offset(pSrc); : src_pitch = intel_get_pixmap_pitch(pSrc); 2 0.0022 : dst_offset = intel_get_pixmap_offset(pDst); 3 0.0033 : dst_pitch = intel_get_pixmap_pitch(pDst); : if (pMask) { 2 0.0022 : mask_offset = intel_get_pixmap_offset(pMask); 6 0.0065 : mask_pitch = intel_get_pixmap_pitch(pMask); : } 8 0.0087 : pI830->scale_units[0][0] = pSrc->drawable.width; 24 0.0261 : pI830->scale_units[0][1] = pSrc->drawable.height; : 1 0.0011 : pI830->transform[0] = pSrcPicture->transform; : : if (!pMask) { : pI830->transform[1] = NULL; : pI830->scale_units[1][0] = -1; : pI830->scale_units[1][1] = -1; : if (pI830->transform[0] && : i965_check_rotation_transform(pI830->transform[0])) : rotation_program = TRUE; : } else { : pI830->transform[1] = pMaskPicture->transform; : if (pI830->transform[1]) : I830FALLBACK("i965 mask transform not implemented!\n"); 3 0.0033 : pI830->scale_units[1][0] = pMask->drawable.width; 3 0.0033 : pI830->scale_units[1][1] = pMask->drawable.height; : } : : /* setup 3d pipeline state */ : 1 0.0011 : binding_table_entries = 2; /* default no mask */ : : /* Set up our layout of state in framebuffer. First the general state: */ : next_offset = 0; 1 0.0011 : vs_offset = ALIGN(next_offset, 64); : next_offset = vs_offset + sizeof(*vs_state); : : sf_offset = ALIGN(next_offset, 32); : next_offset = sf_offset + sizeof(*sf_state); : : wm_offset = ALIGN(next_offset, 32); : next_offset = wm_offset + sizeof(*wm_state); : : wm_scratch_offset = ALIGN(next_offset, 1024); : next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS; : : cc_offset = ALIGN(next_offset, 32); : next_offset = cc_offset + sizeof(*cc_state); : : /* keep current sf_kernel, which will send one setup urb entry to : * PS kernel : */ 1 0.0011 : sf_kernel_offset = ALIGN(next_offset, 64); : if (pMask) : next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask); : else if (rotation_program) : next_offset = sf_kernel_offset + sizeof (sf_kernel_static_rotation); : else : next_offset = sf_kernel_offset + sizeof (sf_kernel_static); : : ps_kernel_offset = ALIGN(next_offset, 64); : if (pMask) { : if (pMaskPicture->componentAlpha && : PICT_FORMAT_RGB(pMaskPicture->format)) { : if (i965_blend_op[op].src_alpha) { : next_offset = ps_kernel_offset + : sizeof(ps_kernel_static_maskca_srcalpha); : } else { : next_offset = ps_kernel_offset + : sizeof(ps_kernel_static_maskca); : } : } else 1 0.0011 : next_offset = ps_kernel_offset + : sizeof(ps_kernel_static_masknoca); : } else if (rotation_program) { : next_offset = ps_kernel_offset + sizeof (ps_kernel_static_rotation); : } else { 1 0.0011 : next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask); : } : 13 0.0142 : sip_kernel_offset = ALIGN(next_offset, 64); : next_offset = sip_kernel_offset + sizeof (sip_kernel_static); : : /* needed? */ 3 0.0033 : cc_viewport_offset = ALIGN(next_offset, 32); : next_offset = cc_viewport_offset + sizeof(*cc_viewport); : : /* for texture sampler */ 3 0.0033 : src_sampler_offset = ALIGN(next_offset, 32); 2 0.0022 : next_offset = src_sampler_offset + sizeof(*src_sampler_state); : 3 0.0033 : if (pMask) { : mask_sampler_offset = ALIGN(next_offset, 32); 1 0.0011 : next_offset = mask_sampler_offset + sizeof(*mask_sampler_state); : } : /* Align VB to native size of elements, for safety */ 10 0.0109 : vb_offset = ALIGN(next_offset, 8); : next_offset = vb_offset + vb_size; : : /* And then the general state: */ 2 0.0022 : dest_surf_offset = ALIGN(next_offset, 32); : next_offset = dest_surf_offset + sizeof(*dest_surf_state); : 2 0.0022 : src_surf_offset = ALIGN(next_offset, 32); 1 0.0011 : next_offset = src_surf_offset + sizeof(*src_surf_state); : 1 0.0011 : if (pMask) { 1 0.0011 : mask_surf_offset = ALIGN(next_offset, 32); : next_offset = mask_surf_offset + sizeof(*mask_surf_state); 3 0.0033 : binding_table_entries = 3; : } : 3 0.0033 : binding_table_offset = ALIGN(next_offset, 32); : next_offset = binding_table_offset + (binding_table_entries * 4); : 4 0.0044 : default_color_offset = ALIGN(next_offset, 32); 2 0.0022 : next_offset = default_color_offset + sizeof(*default_color_state); : 3 0.0033 : total_state_size = next_offset; : assert(total_state_size < pI830->exa_965_state->size); : 3 0.0033 : state_base_offset = pI830->exa_965_state->offset; 9 0.0098 : state_base_offset = ALIGN(state_base_offset, 64); : state_base = (char *)(pI830->FbBase + state_base_offset); : : sf_kernel = (void *)(state_base + sf_kernel_offset); 1 0.0011 : ps_kernel = (void *)(state_base + ps_kernel_offset); : sip_kernel = (void *)(state_base + sip_kernel_offset); : 1 0.0011 : cc_viewport = (void *)(state_base + cc_viewport_offset); : 1 0.0011 : binding_table = (void *)(state_base + binding_table_offset); : 2 0.0022 : vb = (void *)(state_base + vb_offset); : 5 0.0054 : default_color_state = (void*)(state_base + default_color_offset); : : /* Set up a default static partitioning of the URB, which is supposed to : * allow anything we would want to do, at potentially lower performance. : */ :#define URB_CS_ENTRY_SIZE 0 :#define URB_CS_ENTRIES 0 : :#define URB_VS_ENTRY_SIZE 1 // each 512-bit row :#define URB_VS_ENTRIES 8 // we needs at least 8 entries : :#define URB_GS_ENTRY_SIZE 0 :#define URB_GS_ENTRIES 0 : :#define URB_CLIP_ENTRY_SIZE 0 :#define URB_CLIP_ENTRIES 0 : :#define URB_SF_ENTRY_SIZE 2 :#define URB_SF_ENTRIES 1 : : urb_vs_start = 0; 1 0.0011 : urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; : urb_gs_start = urb_vs_start + urb_vs_size; : urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; : urb_clip_start = urb_gs_start + urb_gs_size; : urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; 1 0.0011 : urb_sf_start = urb_clip_start + urb_clip_size; : urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; 2 0.0022 : urb_cs_start = urb_sf_start + urb_sf_size; 1 0.0011 : urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; : : /* Because we only have a single static buffer for our state currently, : * we have to sync before updating it every time. : */ 3 0.0033 : i830WaitSync(pScrn); : 17 0.0185 : memset (cc_viewport, 0, sizeof (*cc_viewport)); 17 0.0185 : cc_viewport->min_depth = -1.e35; 19 0.0207 : cc_viewport->max_depth = 1.e35; : : /* Color calculator state */ 7 0.0076 : cc_state = &cc_state_local; 32 0.0349 : memset(cc_state, 0, sizeof(*cc_state)); 34 0.0370 : cc_state->cc0.stencil_enable = 0; /* disable stencil */ : cc_state->cc2.depth_test = 0; /* disable depth test */ : cc_state->cc2.logicop_enable = 0; /* disable logic op */ : cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */ : cc_state->cc3.blend_enable = 1; /* enable color blend */ 6 0.0065 : cc_state->cc3.alpha_test = 0; /* disable alpha test */ 12 0.0131 : cc_state->cc4.cc_viewport_state_offset = (state_base_offset + : cc_viewport_offset) >> 5; : cc_state->cc5.dither_enable = 0; /* disable dither */ 2 0.0022 : cc_state->cc5.logicop_func = 0xc; /* COPY */ : cc_state->cc5.statistics_enable = 1; 1 0.0011 : cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; 38 0.0414 : i965_get_blend_cntl(op, pMaskPicture, pDstPicture->format, : &src_blend, &dst_blend); : /* XXX: alpha blend factor should be same as color, but check : * for CA case in future : */ 24 0.0261 : cc_state->cc5.ia_src_blend_factor = src_blend; 9 0.0098 : cc_state->cc5.ia_dest_blend_factor = dst_blend; : cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD; 6 0.0065 : cc_state->cc6.src_blend_factor = src_blend; 10 0.0109 : cc_state->cc6.dest_blend_factor = dst_blend; : cc_state->cc6.clamp_post_alpha_blend = 1; 4 0.0044 : cc_state->cc6.clamp_pre_alpha_blend = 1; 1 0.0011 : cc_state->cc6.clamp_range = 0; /* clamp range [0,1] */ : 1 0.0011 : cc_state = (void *)(state_base + cc_offset); 51 0.0556 : memcpy (cc_state, &cc_state_local, sizeof (cc_state_local)); : : /* Upload system kernel */ 10 0.0109 : memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static)); : : /* Set up the state buffer for the destination surface */ 8 0.0087 : dest_surf_state = &dest_surf_state_local; 42 0.0458 : memset(dest_surf_state, 0, sizeof(*dest_surf_state)); 1 0.0011 : dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; 8 0.0087 : dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; 4 0.0044 : i965_get_dest_format(pDstPicture, &dst_format); 34 0.0370 : dest_surf_state->ss0.surface_format = dst_format; : : dest_surf_state->ss0.writedisable_alpha = 0; : dest_surf_state->ss0.writedisable_red = 0; : dest_surf_state->ss0.writedisable_green = 0; : dest_surf_state->ss0.writedisable_blue = 0; 27 0.0294 : dest_surf_state->ss0.color_blend = 1; : dest_surf_state->ss0.vert_line_stride = 0; : dest_surf_state->ss0.vert_line_stride_ofs = 0; : dest_surf_state->ss0.mipmap_layout_mode = 0; : dest_surf_state->ss0.render_cache_read_mode = 0; : : dest_surf_state->ss1.base_addr = dst_offset; 4 0.0044 : dest_surf_state->ss2.height = pDst->drawable.height - 1; 40 0.0436 : dest_surf_state->ss2.width = pDst->drawable.width - 1; : dest_surf_state->ss2.mip_count = 0; : dest_surf_state->ss2.render_target_rotation = 0; 23 0.0251 : dest_surf_state->ss3.pitch = dst_pitch - 1; : 1 0.0011 : dest_surf_state = (void *)(state_base + dest_surf_offset); 31 0.0338 : memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local)); : : /* Set up the source surface state buffer */ : src_surf_state = &src_surf_state_local; 48 0.0523 : memset(src_surf_state, 0, sizeof(*src_surf_state)); 5 0.0054 : src_surf_state->ss0.surface_type = BRW_SURFACE_2D; 20 0.0218 : src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture); : : src_surf_state->ss0.writedisable_alpha = 0; 3 0.0033 : src_surf_state->ss0.writedisable_red = 0; : src_surf_state->ss0.writedisable_green = 0; : src_surf_state->ss0.writedisable_blue = 0; 31 0.0338 : src_surf_state->ss0.color_blend = 1; : src_surf_state->ss0.vert_line_stride = 0; : src_surf_state->ss0.vert_line_stride_ofs = 0; : src_surf_state->ss0.mipmap_layout_mode = 0; : src_surf_state->ss0.render_cache_read_mode = 0; : 3 0.0033 : src_surf_state->ss1.base_addr = src_offset; 7 0.0076 : src_surf_state->ss2.width = pSrc->drawable.width - 1; 6 0.0065 : src_surf_state->ss2.height = pSrc->drawable.height - 1; : src_surf_state->ss2.mip_count = 0; 30 0.0327 : src_surf_state->ss2.render_target_rotation = 0; 15 0.0163 : src_surf_state->ss3.pitch = src_pitch - 1; : : src_surf_state = (void *)(state_base + src_surf_offset); 28 0.0305 : memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local)); : : /* setup mask surface */ 1 0.0011 : if (pMask) { : mask_surf_state = &mask_surf_state_local; 35 0.0381 : memset(mask_surf_state, 0, sizeof(*mask_surf_state)); 6 0.0065 : mask_surf_state->ss0.surface_type = BRW_SURFACE_2D; 18 0.0196 : mask_surf_state->ss0.surface_format = : i965_get_card_format(pMaskPicture); : : mask_surf_state->ss0.writedisable_alpha = 0; 8 0.0087 : mask_surf_state->ss0.writedisable_red = 0; : mask_surf_state->ss0.writedisable_green = 0; : mask_surf_state->ss0.writedisable_blue = 0; 20 0.0218 : mask_surf_state->ss0.color_blend = 1; : mask_surf_state->ss0.vert_line_stride = 0; : mask_surf_state->ss0.vert_line_stride_ofs = 0; : mask_surf_state->ss0.mipmap_layout_mode = 0; : mask_surf_state->ss0.render_cache_read_mode = 0; : : mask_surf_state->ss1.base_addr = mask_offset; 11 0.0120 : mask_surf_state->ss2.width = pMask->drawable.width - 1; 4 0.0044 : mask_surf_state->ss2.height = pMask->drawable.height - 1; : mask_surf_state->ss2.mip_count = 0; 31 0.0338 : mask_surf_state->ss2.render_target_rotation = 0; 8 0.0087 : mask_surf_state->ss3.pitch = mask_pitch - 1; : : mask_surf_state = (void *)(state_base + mask_surf_offset); 38 0.0414 : memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local)); : } : : /* Set up a binding table for our surfaces. Only the PS will use it */ 8 0.0087 : binding_table[0] = state_base_offset + dest_surf_offset; 1 0.0011 : binding_table[1] = state_base_offset + src_surf_offset; : if (pMask) 3 0.0033 : binding_table[2] = state_base_offset + mask_surf_offset; : : /* PS kernel use this sampler */ : src_sampler_state = &src_sampler_state_local; 3 0.0033 : memset(src_sampler_state, 0, sizeof(*src_sampler_state)); : src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */ 58 0.0632 : switch(pSrcPicture->filter) { : case PictFilterNearest: 4 0.0044 : src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 38 0.0414 : src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST; : break; : case PictFilterBilinear: : src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; : src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; : break; : default: : I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter); : } : 40 0.0436 : memset(default_color_state, 0, sizeof(*default_color_state)); 1 0.0011 : default_color_state->color[0] = 0.0; /* R */ 4 0.0044 : default_color_state->color[1] = 0.0; /* G */ : default_color_state->color[2] = 0.0; /* B */ : default_color_state->color[3] = 0.0; /* A */ : 3 0.0033 : src_sampler_state->ss0.default_color_mode = 0; /* GL mode */ : 3 0.0033 : if (!pSrcPicture->repeat) { : src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; 1 0.0011 : src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; : src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER; : src_sampler_state->ss2.default_color_pointer = : (state_base_offset + default_color_offset) >> 5; : } else { 8 0.0087 : src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; : src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP; 85 0.0926 : src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP; : } 3 0.0033 : src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */ : 6 0.0065 : src_sampler_state = (void *)(state_base + src_sampler_offset); 32 0.0349 : memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local)); : 3 0.0033 : if (pMask) { : mask_sampler_state = &mask_sampler_state_local; : memset(mask_sampler_state, 0, sizeof(*mask_sampler_state)); 3 0.0033 : mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */ 45 0.0490 : switch(pMaskPicture->filter) { : case PictFilterNearest: 5 0.0054 : mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST; 41 0.0447 : mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST; : break; : case PictFilterBilinear: : mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; : mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; : break; : default: : I830FALLBACK("Bad filter 0x%x\n", pMaskPicture->filter); : } : 34 0.0370 : if (!pMaskPicture->repeat) { 3 0.0033 : mask_sampler_state->ss1.r_wrap_mode = : BRW_TEXCOORDMODE_CLAMP_BORDER; 40 0.0436 : mask_sampler_state->ss1.s_wrap_mode = : BRW_TEXCOORDMODE_CLAMP_BORDER; 22 0.0240 : mask_sampler_state->ss1.t_wrap_mode = : BRW_TEXCOORDMODE_CLAMP_BORDER; 7 0.0076 : mask_sampler_state->ss2.default_color_pointer = : (state_base_offset + default_color_offset)>>5; : } else { : mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP; : mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP; : mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP; : } : mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */ : 5 0.0054 : mask_sampler_state = (void *)(state_base + mask_sampler_offset); 27 0.0294 : memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local)); : } : : /* Set up the vertex shader to be disabled (passthrough) */ 4 0.0044 : vs_state = &vs_state_local; 8 0.0087 : memset(vs_state, 0, sizeof(*vs_state)); 1 0.0011 : vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES; 1 0.0011 : vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; 46 0.0501 : vs_state->vs6.vs_enable = 0; : vs_state->vs6.vert_cache_disable = 1; : 6 0.0065 : vs_state = (void *)(state_base + vs_offset); 22 0.0240 : memcpy (vs_state, &vs_state_local, sizeof (vs_state_local)); : : /* Set up the SF kernel to do coord interp: for each attribute, : * calculate dA/dx and dA/dy. Hand these interpolation coefficients : * back to SF which then hands pixels off to WM. : */ 4 0.0044 : if (pMask) 5 0.0054 : memcpy(sf_kernel, sf_kernel_static_mask, sizeof (sf_kernel_static)); : else if (rotation_program) : memcpy(sf_kernel, sf_kernel_static_rotation, : sizeof (sf_kernel_static_rotation)); : else : memcpy(sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); : 3 0.0033 : sf_state = &sf_state_local; 45 0.0490 : memset(sf_state, 0, sizeof(*sf_state)); 102 0.1111 : sf_state->thread0.kernel_start_pointer = : (state_base_offset + sf_kernel_offset) >> 6; 1 0.0011 : sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); 50 0.0545 : sf_state->sf1.single_program_flow = 1; : sf_state->sf1.binding_table_entry_count = 0; : sf_state->sf1.thread_priority = 0; : sf_state->sf1.floating_point_mode = 0; /* Mesa does this */ : sf_state->sf1.illegal_op_exception_enable = 1; 7 0.0076 : sf_state->sf1.mask_stack_exception_enable = 1; : sf_state->sf1.sw_exception_enable = 1; 45 0.0490 : sf_state->thread2.per_thread_scratch_space = 0; : /* scratch space is not used in our kernel */ 4 0.0044 : sf_state->thread2.scratch_space_base_pointer = 0; 3 0.0033 : sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */ 8 0.0087 : sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */ 9 0.0098 : sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ : /* don't smash vertex header, read start from dw8 */ 4 0.0044 : sf_state->thread3.urb_entry_read_offset = 1; 3 0.0033 : sf_state->thread3.dispatch_grf_start_reg = 3; 10 0.0109 : sf_state->thread4.max_threads = SF_MAX_THREADS - 1; 1 0.0011 : sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; 6 0.0065 : sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES; : sf_state->thread4.stats_enable = 1; : sf_state->sf5.viewport_transform = FALSE; /* skip viewport */ 32 0.0349 : sf_state->sf6.cull_mode = BRW_CULLMODE_NONE; 40 0.0436 : sf_state->sf6.scissor = 0; 5 0.0054 : sf_state->sf7.trifan_pv = 2; 5 0.0054 : sf_state->sf6.dest_org_vbias = 0x8; 54 0.0588 : sf_state->sf6.dest_org_hbias = 0x8; : 3 0.0033 : sf_state = (void *)(state_base + sf_offset); 14 0.0153 : memcpy (sf_state, &sf_state_local, sizeof (sf_state_local)); : : /* Set up the PS kernel (dispatched by WM) */ : if (pMask) { 5 0.0054 : if (pMaskPicture->componentAlpha && : PICT_FORMAT_RGB(pMaskPicture->format)) { 3 0.0033 : if (i965_blend_op[op].src_alpha) 3 0.0033 : memcpy(ps_kernel, ps_kernel_static_maskca_srcalpha, : sizeof (ps_kernel_static_maskca_srcalpha)); : else 2 0.0022 : memcpy(ps_kernel, ps_kernel_static_maskca, : sizeof (ps_kernel_static_maskca)); : } else 8 0.0087 : memcpy(ps_kernel, ps_kernel_static_masknoca, : sizeof (ps_kernel_static_masknoca)); : } else if (rotation_program) { 1 0.0011 : memcpy(ps_kernel, ps_kernel_static_rotation, : sizeof (ps_kernel_static_rotation)); : } else { 1 0.0011 : memcpy(ps_kernel, ps_kernel_static_nomask, : sizeof (ps_kernel_static_nomask)); : } : 13 0.0142 : wm_state = &wm_state_local; 90 0.0980 : memset(wm_state, 0, sizeof (*wm_state)); 90 0.0980 : wm_state->thread0.kernel_start_pointer = : (state_base_offset + ps_kernel_offset) >> 6; 21 0.0229 : wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF); : wm_state->thread1.single_program_flow = 1; : if (!pMask) 1 0.0011 : wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */ : else 18 0.0196 : wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */ : 6 0.0065 : wm_state->thread2.scratch_space_base_pointer = (state_base_offset + : wm_scratch_offset)>>10; 33 0.0359 : wm_state->thread2.per_thread_scratch_space = 0; : wm_state->thread3.const_urb_entry_read_length = 0; 1 0.0011 : wm_state->thread3.const_urb_entry_read_offset = 0; : /* Each pair of attributes (src/mask coords) is one URB entry */ : if (pMask) 7 0.0076 : wm_state->thread3.urb_entry_read_length = 2; : else 2 0.0022 : wm_state->thread3.urb_entry_read_length = 1; 4 0.0044 : wm_state->thread3.urb_entry_read_offset = 0; : /* wm kernel use urb from 3, see wm_program in compiler module */ 19 0.0207 : wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */ : 10 0.0109 : wm_state->wm4.stats_enable = 1; /* statistic */ 7 0.0076 : wm_state->wm4.sampler_state_pointer = (state_base_offset + : src_sampler_offset) >> 5; 19 0.0207 : wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */ 6 0.0065 : wm_state->wm5.max_threads = PS_MAX_THREADS - 1; : wm_state->wm5.thread_dispatch_enable = 1; : /* just use 16-pixel dispatch (4 subspans), don't need to change kernel : * start point : */ 2 0.0022 : wm_state->wm5.enable_16_pix = 1; : wm_state->wm5.enable_8_pix = 0; 20 0.0218 : wm_state->wm5.early_depth_test = 1; : 3 0.0033 : wm_state = (void *)(state_base + wm_offset); 35 0.0381 : memcpy (wm_state, &wm_state_local, sizeof (wm_state_local)); : : /* Begin the long sequence of commands needed to set up the 3D : * rendering pipe : */ : { 2 0.0022 : BEGIN_LP_RING(2); 3 0.0033 : OUT_RING(MI_FLUSH | : MI_STATE_INSTRUCTION_CACHE_FLUSH | : BRW_MI_GLOBAL_SNAPSHOT_RESET); 4 0.0044 : OUT_RING(MI_NOOP); 37 0.0403 : ADVANCE_LP_RING(); : } : { 2751 2.9969 : BEGIN_LP_RING(12); : : /* Match Mesa driver setup */ 5 0.0054 : OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); : 10 0.0109 : OUT_RING(BRW_CS_URB_STATE | 0); 5 0.0054 : OUT_RING((0 << 4) | /* URB Entry Allocation Size */ : (0 << 0)); /* Number of URB Entries */ : : /* Zero out the two base address registers so all offsets are : * absolute. : */ 4 0.0044 : OUT_RING(BRW_STATE_BASE_ADDRESS | 4); 1 0.0011 : OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */ 2 0.0022 : OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */ 5 0.0054 : OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */ : /* general state max addr, disabled */ 4 0.0044 : OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); : /* media object state max addr, disabled */ 7 0.0076 : OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); : : /* Set system instruction pointer */ 4 0.0044 : OUT_RING(BRW_STATE_SIP | 0); 13 0.0142 : OUT_RING(state_base_offset + sip_kernel_offset); 8 0.0087 : OUT_RING(MI_NOOP); 106 0.1155 : ADVANCE_LP_RING(); : } : { 1204 1.3116 : BEGIN_LP_RING(26); : /* Pipe control */ 2 0.0022 : OUT_RING(BRW_PIPE_CONTROL | : BRW_PIPE_CONTROL_NOWRITE | : BRW_PIPE_CONTROL_IS_FLUSH | : 2); 15 0.0163 : OUT_RING(0); /* Destination address */ 6 0.0065 : OUT_RING(0); /* Immediate data low DW */ 3 0.0033 : OUT_RING(0); /* Immediate data high DW */ : : /* Binding table pointers */ 3 0.0033 : OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); 6 0.0065 : OUT_RING(0); /* vs */ 5 0.0054 : OUT_RING(0); /* gs */ 5 0.0054 : OUT_RING(0); /* clip */ 10 0.0109 : OUT_RING(0); /* sf */ : /* Only the PS uses the binding table */ 16 0.0174 : OUT_RING(state_base_offset + binding_table_offset); /* ps */ : : /* The drawing rectangle clipping is always on. Set it to values that : * shouldn't do any clipping. : */ 22 0.0240 : OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */ 12 0.0131 : OUT_RING(0x00000000); /* ymin, xmin */ 61 0.0665 : OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) | : DRAW_XMAX(pDst->drawable.width - 1)); /* ymax, xmax */ 41 0.0447 : OUT_RING(0x00000000); /* yorigin, xorigin */ : : /* skip the depth buffer */ : /* skip the polygon stipple */ : /* skip the polygon stipple offset */ : /* skip the line stipple */ : : /* Set the pointers to the 3d pipeline state */ : OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5); 29 0.0316 : OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */ 11 0.0120 : OUT_RING(BRW_GS_DISABLE); /* disable GS, resulting in passthrough */ 102 0.1111 : OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */ 383 0.4172 : OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */ 26 0.0283 : OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */ 17 0.0185 : OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */ : : /* URB fence */ : OUT_RING(BRW_URB_FENCE | : UF0_CS_REALLOC | : UF0_SF_REALLOC | : UF0_CLIP_REALLOC | : UF0_GS_REALLOC | : UF0_VS_REALLOC | : 1); 39 0.0425 : OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | : ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | : ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); 28 0.0305 : OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | : ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); : : /* Constant buffer state */ 11 0.0120 : OUT_RING(BRW_CS_URB_STATE | 0); 3 0.0033 : OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | : (URB_CS_ENTRIES << 0)); 62 0.0675 : ADVANCE_LP_RING(); : } : { 702 0.7647 : int nelem = pMask ? 3: 2; 12 0.0131 : BEGIN_LP_RING(pMask?12:10); : /* Set up the pointer to our vertex buffer */ 4 0.0044 : OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3); 2 0.0022 : OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) | : VB0_VERTEXDATA | : ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT)); 10 0.0109 : OUT_RING(state_base_offset + vb_offset); 2 0.0022 : OUT_RING(3); 7 0.0076 : OUT_RING(0); // ignore for VERTEXDATA, but still there : : /* Set up our vertex elements, sourced from the single vertex buffer. : */ 9 0.0098 : OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1)); : /* vertex coordinates */ 5 0.0054 : OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | : VE0_VALID | : (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | : (0 << VE0_OFFSET_SHIFT)); 2 0.0022 : OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | : (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | : (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | : (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | : (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); : /* u0, v0 */ 2 0.0022 : OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | : VE0_VALID | : (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | : (8 << VE0_OFFSET_SHIFT)); /* offset vb in bytes */ 14 0.0153 : OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | : (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | : (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) | : (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) | : (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */ : /* u1, v1 */ 1 0.0011 : if (pMask) { 4 0.0044 : OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | : VE0_VALID | : (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | : (16 << VE0_OFFSET_SHIFT)); 1 0.0011 : OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | : (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | : (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) | : (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) | : (10 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); : } : 66 0.0719 : ADVANCE_LP_RING(); : } : :#ifdef I830DEBUG : ErrorF("try to sync to show any errors..."); : I830Sync(pScrn); :#endif : return TRUE; 1196 1.3029 :} : :void :i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, : int dstX, int dstY, int w, int h) 707 0.7702 :{ /* i965_composite total: 2800 3.0503 */ 38 0.0414 : ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 3 0.0033 : I830Ptr pI830 = I830PTR(pScrn); : Bool has_mask; : float src_x[3], src_y[3], mask_x[3], mask_y[3]; : int i; : 22 0.0240 : i830_get_transformed_coordinates(srcX, srcY, : pI830->transform[0], : &src_x[0], &src_y[0]); 5 0.0054 : i830_get_transformed_coordinates(srcX, srcY + h, : pI830->transform[0], : &src_x[1], &src_y[1]); 15 0.0163 : i830_get_transformed_coordinates(srcX + w, srcY + h, : pI830->transform[0], : &src_x[2], &src_y[2]); : 18 0.0196 : if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) { : has_mask = FALSE; : } else { : has_mask = TRUE; 1 0.0011 : i830_get_transformed_coordinates(maskX, maskY, : pI830->transform[1], : &mask_x[0], &mask_y[0]); 8 0.0087 : i830_get_transformed_coordinates(maskX, maskY + h, : pI830->transform[1], : &mask_x[1], &mask_y[1]); 33 0.0359 : i830_get_transformed_coordinates(maskX + w, maskY + h, : pI830->transform[1], : &mask_x[2], &mask_y[2]); : } : : /* Wait for any existing composite rectangles to land before we overwrite : * the VB with the next one. : */ 7 0.0076 : i830WaitSync(pScrn); : : i = 0; : /* rect (x2,y2) */ 6 0.0065 : vb[i++] = (float)(dstX + w); 7 0.0076 : vb[i++] = (float)(dstY + h); 4 0.0044 : vb[i++] = src_x[2] / pI830->scale_units[0][0]; 8 0.0087 : vb[i++] = src_y[2] / pI830->scale_units[0][1]; : if (has_mask) { 77 0.0839 : vb[i++] = mask_x[2] / pI830->scale_units[1][0]; 88 0.0959 : vb[i++] = mask_y[2] / pI830->scale_units[1][1]; : } : : /* rect (x1,y2) */ 2 0.0022 : vb[i++] = (float)dstX; 1 0.0011 : vb[i++] = (float)(dstY + h); 3 0.0033 : vb[i++] = src_x[1] / pI830->scale_units[0][0]; 14 0.0153 : vb[i++] = src_y[1] / pI830->scale_units[0][1]; 2 0.0022 : if (has_mask) { 7 0.0076 : vb[i++] = mask_x[1] / pI830->scale_units[1][0]; 72 0.0784 : vb[i++] = mask_y[1] / pI830->scale_units[1][1]; : } : : /* rect (x1,y1) */ 2 0.0022 : vb[i++] = (float)dstX; 3 0.0033 : vb[i++] = (float)dstY; 3 0.0033 : vb[i++] = src_x[0] / pI830->scale_units[0][0]; 5 0.0054 : vb[i++] = src_y[0] / pI830->scale_units[0][1]; : if (has_mask) { 7 0.0076 : vb[i++] = mask_x[0] / pI830->scale_units[1][0]; 11 0.0120 : vb[i++] = mask_y[0] / pI830->scale_units[1][1]; : } : : { 2 0.0022 : BEGIN_LP_RING(6); 3 0.0033 : OUT_RING(BRW_3DPRIMITIVE | : BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | : (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | : (0 << 9) | /* CTG - indirect vertex count */ : 4); 4 0.0044 : OUT_RING(3); /* vertex count per instance */ : OUT_RING(0); /* start vertex offset */ 3 0.0033 : OUT_RING(1); /* single instance */ 4 0.0044 : OUT_RING(0); /* start instance location */ 3 0.0033 : OUT_RING(0); /* index buffer offset, ignored */ 4 0.0044 : ADVANCE_LP_RING(); : } :#ifdef I830DEBUG : ErrorF("sync after 3dprimitive"); : I830Sync(pScrn); :#endif : /* we must be sure that the pipeline is flushed before next exa draw, : because that will be new state, binding state and instructions*/ : { 804 0.8759 : BEGIN_LP_RING(4); : OUT_RING(BRW_PIPE_CONTROL | : BRW_PIPE_CONTROL_NOWRITE | : BRW_PIPE_CONTROL_WC_FLUSH | : BRW_PIPE_CONTROL_IS_FLUSH | : (1 << 10) | /* XXX texture cache flush for BLC/CTG */ : 2); 2 0.0022 : OUT_RING(0); /* Destination address */ 5 0.0054 : OUT_RING(0); /* Immediate data low DW */ 5 0.0054 : OUT_RING(0); /* Immediate data high DW */ 7 0.0076 : ADVANCE_LP_RING(); : } : : /* Mark sync so we can wait for it before setting up the VB on the next : * rectangle. : */ 773 0.8421 : i830MarkSync(pScrn); 2 0.0022 :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa.c" * * 854 0.9303 */ :/* : * Copyright © 2001 Keith Packard : * : * Partly based on code that is Copyright © The XFree86 Project Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :/** @file : * This file covers the initialization and teardown of EXA, and has various : * functions not responsible for performing rendering, pixmap migration, or : * memory management. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#ifdef MITSHM :#include "shmint.h" :#endif : :#include : :#include "exa_priv.h" :#include :#include "dixfontstr.h" :#include "exa.h" :#include "cw.h" : :static int exaGeneration; :int exaScreenPrivateIndex; :int exaPixmapPrivateIndex; : :/** : * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of : * the beginning of the given pixmap. : * : * Note that drivers are free to, and often do, munge this offset as necessary : * for handing to the hardware -- for example, translating it into a different : * aperture. This function may need to be extended in the future if we grow : * support for having multiple card-accessible offscreen, such as an AGP memory : * pool alongside the framebuffer pool. : */ :unsigned long :exaGetPixmapOffset(PixmapPtr pPix) 11 0.0120 :{ /* exaGetPixmapOffset total: 35 0.0381 */ 3 0.0033 : ExaScreenPriv (pPix->drawable.pScreen); 6 0.0065 : ExaPixmapPriv (pPix); : void *ptr; : : /* Return the offscreen pointer if we've hidden the data. */ 5 0.0054 : if (pPix->devPrivate.ptr == NULL) : ptr = pExaPixmap->fb_ptr; : else : ptr = pPix->devPrivate.ptr; : : return ((unsigned long)ptr - (unsigned long)pExaScr->info->memoryBase); 10 0.0109 :} : :/** : * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. : * : * This is a helper to make driver code more obvious, due to the rather obscure : * naming of the pitch field in the pixmap. : */ :unsigned long :exaGetPixmapPitch(PixmapPtr pPix) 2 0.0022 :{ /* exaGetPixmapPitch total: 7 0.0076 */ : return pPix->devKind; 5 0.0054 :} : :/** : * exaGetPixmapSize() returns the size in bytes of the given pixmap in video : * memory. Only valid when the pixmap is currently in framebuffer. : */ :unsigned long :exaGetPixmapSize(PixmapPtr pPix) :{ : ExaPixmapPrivPtr pExaPixmap; : : pExaPixmap = ExaGetPixmapPriv(pPix); : if (pExaPixmap != NULL) : return pExaPixmap->fb_size; : return 0; :} : :/** : * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. : * : * @param pDrawable the drawable being requested. : * : * This function returns the backing pixmap for a drawable, whether it is a : * redirected window, unredirected window, or already a pixmap. Note that : * coordinate translation is needed when drawing to the backing pixmap of a : * redirected window, and the translation coordinates are provided by calling : * exaGetOffscreenPixmap() on the drawable. : */ :PixmapPtr :exaGetDrawablePixmap(DrawablePtr pDrawable) 53 0.0577 :{ /* exaGetDrawablePixmap total: 111 0.1209 */ 5 0.0054 : if (pDrawable->type == DRAWABLE_WINDOW) : return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable); : else 30 0.0327 : return (PixmapPtr) pDrawable; 23 0.0251 :} : :/** : * Sets the offsets to add to coordinates to make them address the same bits in : * the backing drawable. These coordinates are nonzero only for redirected : * windows. : */ :void :exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, : int *xp, int *yp) 8 0.0087 :{ /* exaGetDrawableDeltas total: 52 0.0566 */ :#ifdef COMPOSITE 21 0.0229 : if (pDrawable->type == DRAWABLE_WINDOW) { : *xp = -pPixmap->screen_x; : *yp = -pPixmap->screen_y; : return; : } :#endif : 4 0.0044 : *xp = 0; 1 0.0011 : *yp = 0; 18 0.0196 :} : :/** : * exaPixmapDirty() marks a pixmap as dirty, allowing for : * optimizations in pixmap migration when no changes have occurred. : */ :void :exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) 20 0.0218 :{ /* exaPixmapDirty total: 90 0.0980 */ 6 0.0065 : ExaPixmapPriv(pPix); : BoxRec box; : RegionPtr pDamageReg; : RegionRec region; : 11 0.0120 : if (!pExaPixmap) : return; : 3 0.0033 : box.x1 = max(x1, 0); : box.y1 = max(y1, 0); 6 0.0065 : box.x2 = min(x2, pPix->drawable.width); 13 0.0142 : box.y2 = min(y2, pPix->drawable.height); : 4 0.0044 : if (box.x1 >= box.x2 || box.y1 >= box.y2) : return; : 4 0.0044 : pDamageReg = DamageRegion(pExaPixmap->pDamage); : 5 0.0054 : REGION_INIT(pScreen, ®ion, &box, 1); 6 0.0065 : REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); 4 0.0044 : REGION_UNINIT(pScreen, ®ion); 8 0.0087 :} : :static Bool :exaDestroyPixmap (PixmapPtr pPixmap) 3 0.0033 :{ /* exaDestroyPixmap total: 4 0.0044 */ : if (pPixmap->refcnt == 1) : { : ExaPixmapPriv (pPixmap); : if (pExaPixmap->area) : { : DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", : (void*)pPixmap->drawable.id, : ExaGetPixmapPriv(pPixmap)->area->offset, : pPixmap->drawable.width, : pPixmap->drawable.height)); : /* Free the offscreen area */ : exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area); 1 0.0011 : pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; : pPixmap->devKind = pExaPixmap->sys_pitch; : } : REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validReg); : } : return fbDestroyPixmap (pPixmap); :} : :static int :exaLog2(int val) :{ : int bits; : : if (val <= 0) : return 0; : for (bits = 0; val != 0; bits++) : val >>= 1; : return bits - 1; :} : :/** : * exaCreatePixmap() creates a new pixmap. : * : * If width and height are 0, this won't be a full-fledged pixmap and it will : * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because : * ModifyPixmapHeader() would break migration. These types of pixmaps are used : * for scratch pixmaps, or to represent the visible screen. : */ :static PixmapPtr :exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth) 4 0.0044 :{ /* exaCreatePixmap total: 19 0.0207 */ : PixmapPtr pPixmap; : ExaPixmapPrivPtr pExaPixmap; : int bpp; 1 0.0011 : ExaScreenPriv(pScreen); : : if (w > 32767 || h > 32767) : return NullPixmap; : 3 0.0033 : pPixmap = fbCreatePixmap (pScreen, w, h, depth); : if (!pPixmap) : return NULL; 1 0.0011 : pExaPixmap = ExaGetPixmapPriv(pPixmap); : : bpp = pPixmap->drawable.bitsPerPixel; : : /* Glyphs have w/h equal to zero, and may not be migrated. See exaGlyphs. */ 1 0.0011 : if (!w || !h) : pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; : else 2 0.0022 : pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; : : pExaPixmap->area = NULL; : : pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; : pExaPixmap->sys_pitch = pPixmap->devKind; : : pExaPixmap->fb_ptr = NULL; 1 0.0011 : if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) : pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8; : else 1 0.0011 : pExaPixmap->fb_pitch = w * bpp / 8; 4 0.0044 : pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, : pExaScr->info->pixmapPitchAlign); : pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; : : if (pExaPixmap->fb_pitch > 32767) { : fbDestroyPixmap(pPixmap); : return NULL; : } : : /* Set up damage tracking */ : pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE, : pScreen, pPixmap); : : if (pExaPixmap->pDamage == NULL) { : fbDestroyPixmap (pPixmap); : return NULL; : } : : DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); : DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); : : /* None of the pixmap bits are valid initially */ 1 0.0011 : REGION_NULL(pScreen, &pExaPixmap->validReg); : : return pPixmap; :} : :/** : * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen : * memory, meaning that acceleration could probably be done to it, and that it : * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it : * with the CPU. : * : * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly : * deal with moving pixmaps in and out of system memory), EXA will give drivers : * pixmaps as arguments for which exaPixmapIsOffscreen() is TRUE. : * : * @return TRUE if the given drawable is in framebuffer memory. : */ :Bool :exaPixmapIsOffscreen(PixmapPtr p) 44 0.0479 :{ /* exaPixmapIsOffscreen total: 267 0.2909 */ : ScreenPtr pScreen = p->drawable.pScreen; 53 0.0577 : ExaScreenPriv(pScreen); : : /* If the devPrivate.ptr is NULL, it's offscreen but we've hidden the data. : */ 36 0.0392 : if (p->devPrivate.ptr == NULL) : return TRUE; : 80 0.0872 : if (pExaScr->info->PixmapIsOffscreen) : return pExaScr->info->PixmapIsOffscreen(p); : 27 0.0294 : return ((unsigned long) ((CARD8 *) p->devPrivate.ptr - : (CARD8 *) pExaScr->info->memoryBase) < : pExaScr->info->memorySize); 27 0.0294 :} : :/** : * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapIsOffscreen(). : */ :Bool :exaDrawableIsOffscreen (DrawablePtr pDrawable) :{ : return exaPixmapIsOffscreen (exaGetDrawablePixmap (pDrawable)); :} : :/** : * Returns the pixmap which backs a drawable, and the offsets to add to : * coordinates to make them address the same bits in the backing drawable. : */ :PixmapPtr :exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) 17 0.0185 :{ /* exaGetOffscreenPixmap total: 69 0.0752 */ 6 0.0065 : PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); : 16 0.0174 : exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp); : 15 0.0163 : if (exaPixmapIsOffscreen (pPixmap)) : return pPixmap; : else : return NULL; 15 0.0163 :} : :/** : * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. : * : * It deals with waiting for synchronization with the card, determining if : * PrepareAccess() is necessary, and working around PrepareAccess() failure. : */ :void :exaPrepareAccess(DrawablePtr pDrawable, int index) :{ /* exaPrepareAccess total: 1 0.0011 */ : ScreenPtr pScreen = pDrawable->pScreen; : ExaScreenPriv (pScreen); : PixmapPtr pPixmap; : : pPixmap = exaGetDrawablePixmap (pDrawable); : : if (exaPixmapIsOffscreen (pPixmap)) : exaWaitSync (pDrawable->pScreen); : else : return; : : /* Unhide pixmap pointer */ : if (pPixmap->devPrivate.ptr == NULL) { : ExaPixmapPriv (pPixmap); : : pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; : } : 1 0.0011 : if (pExaScr->info->PrepareAccess == NULL) : return; : : if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { : ExaPixmapPriv (pPixmap); : if (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED) : FatalError("Driver failed PrepareAccess on a pinned pixmap\n"); : exaMoveOutPixmap (pPixmap); : } :} : :/** : * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. : * : * It deals with calling the driver's FinishAccess() only if necessary. : */ :void :exaFinishAccess(DrawablePtr pDrawable, int index) :{ /* exaFinishAccess total: 1 0.0011 */ : ScreenPtr pScreen = pDrawable->pScreen; 1 0.0011 : ExaScreenPriv (pScreen); : PixmapPtr pPixmap; : ExaPixmapPrivPtr pExaPixmap; : : pPixmap = exaGetDrawablePixmap (pDrawable); : : pExaPixmap = ExaGetPixmapPriv(pPixmap); : : /* Rehide pixmap pointer if we're doing that. */ : if (pExaPixmap != NULL && pExaScr->hideOffscreenPixmapData && : pExaPixmap->fb_ptr == pPixmap->devPrivate.ptr) : { : pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; : } : : if (pExaScr->info->FinishAccess == NULL) : return; : : if (!exaPixmapIsOffscreen (pPixmap)) : return; : : (*pExaScr->info->FinishAccess) (pPixmap, index); :} : :/** : * exaValidateGC() sets the ops to EXA's implementations, which may be : * accelerated or may sync the card and fall back to fb. : */ :static void :exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 2 0.0022 :{ /* exaValidateGC total: 8 0.0087 */ : /* fbValidateGC will do direct access to pixmaps if the tiling has changed. : * Preempt fbValidateGC by doing its work and masking the change out, so : * that we can do the Prepare/FinishAccess. : */ :#ifdef FB_24_32BIT 1 0.0011 : if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { : (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); : fbGetRotatedPixmap(pGC) = 0; : } : : if (pGC->fillStyle == FillTiled) { : PixmapPtr pOldTile, pNewTile; : : pOldTile = pGC->tile.pixmap; : if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) : { : pNewTile = fbGetRotatedPixmap(pGC); : if (!pNewTile || : pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) : { : if (pNewTile) : (*pGC->pScreen->DestroyPixmap) (pNewTile); : /* fb24_32ReformatTile will do direct access of a newly- : * allocated pixmap. This isn't a problem yet, since we don't : * put pixmaps in FB until at least one accelerated EXA op. : */ : exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC); : pNewTile = fb24_32ReformatTile (pOldTile, : pDrawable->bitsPerPixel); : exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); : exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); : } : if (pNewTile) : { : fbGetRotatedPixmap(pGC) = pOldTile; : pGC->tile.pixmap = pNewTile; : changes |= GCTile; : } : } : } :#endif : if (changes & GCTile) { : if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width * : pDrawable->bitsPerPixel)) : { : /* XXX This fixes corruption with tiled pixmaps, but may just be a : * workaround for broken drivers : */ : exaMoveOutPixmap(pGC->tile.pixmap); : fbPadPixmap (pGC->tile.pixmap); : exaPixmapDirty(pGC->tile.pixmap, 0, 0, : pGC->tile.pixmap->drawable.width, : pGC->tile.pixmap->drawable.height); : } : /* Mask out the GCTile change notification, now that we've done FB's : * job for it. : */ : changes &= ~GCTile; : } : 1 0.0011 : fbValidateGC (pGC, changes, pDrawable); : 1 0.0011 : pGC->ops = (GCOps *) &exaOps; 3 0.0033 :} : :static GCFuncs exaGCFuncs = { : exaValidateGC, : miChangeGC, : miCopyGC, : miDestroyGC, : miChangeClip, : miDestroyClip, : miCopyClip :}; : :/** : * exaCreateGC makes a new GC and hooks up its funcs handler, so that : * exaValidateGC() will get called. : */ :static int :exaCreateGC (GCPtr pGC) :{ : if (!fbCreateGC (pGC)) : return FALSE; : : pGC->funcs = &exaGCFuncs; : : return TRUE; :} : :/** : * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's : * screen private, before calling down to the next CloseSccreen. : */ :static Bool :exaCloseScreen(int i, ScreenPtr pScreen) :{ : ExaScreenPriv(pScreen); :#ifdef RENDER : PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); :#endif : : pScreen->CreateGC = pExaScr->SavedCreateGC; : pScreen->CloseScreen = pExaScr->SavedCloseScreen; : pScreen->GetImage = pExaScr->SavedGetImage; : pScreen->GetSpans = pExaScr->SavedGetSpans; : pScreen->PaintWindowBackground = pExaScr->SavedPaintWindowBackground; : pScreen->PaintWindowBorder = pExaScr->SavedPaintWindowBorder; : pScreen->CreatePixmap = pExaScr->SavedCreatePixmap; : pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap; : pScreen->CopyWindow = pExaScr->SavedCopyWindow; :#ifdef RENDER : if (ps) { : ps->Composite = pExaScr->SavedComposite; : ps->Glyphs = pExaScr->SavedGlyphs; : } :#endif : : xfree (pExaScr); : : return (*pScreen->CloseScreen) (i, pScreen); :} : :/** : * This function allocates a driver structure for EXA drivers to fill in. By : * having EXA allocate the structure, the driver structure can be extended : * without breaking ABI between EXA and the drivers. The driver's : * responsibility is to check beforehand that the EXA module has a matching : * major number and sufficient minor. Drivers are responsible for freeing the : * driver structure using xfree(). : * : * @return a newly allocated, zero-filled driver structure : */ :ExaDriverPtr :exaDriverAlloc(void) :{ : return xcalloc(1, sizeof(ExaDriverRec)); :} : :/** : * @param pScreen screen being initialized : * @param pScreenInfo EXA driver record : * : * exaDriverInit sets up EXA given a driver record filled in by the driver. : * pScreenInfo should have been allocated by exaDriverAlloc(). See the : * comments in _ExaDriver for what must be filled in and what is optional. : * : * @return TRUE if EXA was successfully initialized. : */ :Bool :exaDriverInit (ScreenPtr pScreen, : ExaDriverPtr pScreenInfo) :{ : ExaScreenPrivPtr pExaScr; :#ifdef RENDER : PictureScreenPtr ps; :#endif : : if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || : pScreenInfo->exa_minor > EXA_VERSION_MINOR) : { : LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " : "(%d.%d) are incompatible with EXA version (%d.%d)\n", : pScreen->myNum, : pScreenInfo->exa_major, pScreenInfo->exa_minor, : EXA_VERSION_MAJOR, EXA_VERSION_MINOR); : return FALSE; : } : :#ifdef RENDER : ps = GetPictureScreenIfSet(pScreen); :#endif : if (exaGeneration != serverGeneration) : { : exaScreenPrivateIndex = AllocateScreenPrivateIndex(); : exaPixmapPrivateIndex = AllocatePixmapPrivateIndex(); : exaGeneration = serverGeneration; : } : : pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1); : : if (!pExaScr) { : LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", : pScreen->myNum); : return FALSE; : } : : pExaScr->info = pScreenInfo; : : pScreen->devPrivates[exaScreenPrivateIndex].ptr = (pointer) pExaScr; : : pExaScr->migration = ExaMigrationAlways; : : exaDDXDriverInit(pScreen); : : /* : * Replace various fb screen functions : */ : pExaScr->SavedCloseScreen = pScreen->CloseScreen; : pScreen->CloseScreen = exaCloseScreen; : : pExaScr->SavedCreateGC = pScreen->CreateGC; : pScreen->CreateGC = exaCreateGC; : : pExaScr->SavedGetImage = pScreen->GetImage; : pScreen->GetImage = exaGetImage; : : pExaScr->SavedGetSpans = pScreen->GetSpans; : pScreen->GetSpans = exaGetSpans; : : pExaScr->SavedCopyWindow = pScreen->CopyWindow; : pScreen->CopyWindow = exaCopyWindow; : : pExaScr->SavedPaintWindowBackground = pScreen->PaintWindowBackground; : pScreen->PaintWindowBackground = exaPaintWindow; : : pExaScr->SavedPaintWindowBorder = pScreen->PaintWindowBorder; : pScreen->PaintWindowBorder = exaPaintWindow; : : pScreen->BackingStoreFuncs.SaveAreas = ExaCheckSaveAreas; : pScreen->BackingStoreFuncs.RestoreAreas = ExaCheckRestoreAreas; :#ifdef RENDER : if (ps) { : pExaScr->SavedComposite = ps->Composite; : ps->Composite = exaComposite; : : pExaScr->SavedRasterizeTrapezoid = ps->RasterizeTrapezoid; : ps->RasterizeTrapezoid = exaRasterizeTrapezoid; : : pExaScr->SavedAddTriangles = ps->AddTriangles; : ps->AddTriangles = exaAddTriangles; : : pExaScr->SavedGlyphs = ps->Glyphs; : ps->Glyphs = exaGlyphs; : } :#endif : :#ifdef MITSHM : /* Re-register with the MI funcs, which don't allow shared pixmaps. : * Shared pixmaps are almost always a performance loss for us, but this : * still allows for SHM PutImage. : */ : ShmRegisterFuncs(pScreen, NULL); :#endif : /* : * Hookup offscreen pixmaps : */ : if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && : pExaScr->info->offScreenBase < pExaScr->info->memorySize) : { : if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex, : sizeof (ExaPixmapPrivRec))) { : LogMessage(X_WARNING, : "EXA(%d): Failed to allocate pixmap private\n", : pScreen->myNum); : return FALSE; : } : pExaScr->SavedCreatePixmap = pScreen->CreatePixmap; : pScreen->CreatePixmap = exaCreatePixmap; : : pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap; : pScreen->DestroyPixmap = exaDestroyPixmap; : : LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %d bytes\n", : pScreen->myNum, : pExaScr->info->memorySize - pExaScr->info->offScreenBase); : } : else : { : LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); : if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex, 0)) : return FALSE; : } : : DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, : pExaScr->info->memorySize)); : if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { : if (!exaOffscreenInit (pScreen)) { : LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n", : pScreen->myNum); : return FALSE; : } : } : : LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" : " operations:\n", pScreen->myNum); : assert(pScreenInfo->PrepareSolid != NULL); : LogMessage(X_INFO, " Solid\n"); : assert(pScreenInfo->PrepareCopy != NULL); : LogMessage(X_INFO, " Copy\n"); : if (pScreenInfo->PrepareComposite != NULL) { : LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); : } : if (pScreenInfo->UploadToScreen != NULL) { : LogMessage(X_INFO, " UploadToScreen\n"); : } : if (pScreenInfo->DownloadFromScreen != NULL) { : LogMessage(X_INFO, " DownloadFromScreen\n"); : } : : return TRUE; :} : :/** : * exaDriverFini tears down EXA on a given screen. : * : * @param pScreen screen being torn down. : */ :void :exaDriverFini (ScreenPtr pScreen) :{ : /*right now does nothing*/ :} : :/** : * exaMarkSync() should be called after any asynchronous drawing by the hardware. : * : * @param pScreen screen which drawing occurred on : * : * exaMarkSync() sets a flag to indicate that some asynchronous drawing has : * happened and a WaitSync() will be necessary before relying on the contents of : * offscreen memory from the CPU's perspective. It also calls an optional : * driver MarkSync() callback, the return value of which may be used to do partial : * synchronization with the hardware in the future. : */ :void exaMarkSync(ScreenPtr pScreen) 22 0.0240 :{ /* exaMarkSync total: 88 0.0959 */ 10 0.0109 : ExaScreenPriv(pScreen); : 13 0.0142 : pExaScr->info->needsSync = TRUE; 34 0.0370 : if (pExaScr->info->MarkSync != NULL) { : pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen); : } 9 0.0098 :} : :/** : * exaWaitSync() ensures that all drawing has been completed. : * : * @param pScreen screen being synchronized. : * : * Calls down into the driver to ensure that all previous drawing has completed. : * It should always be called before relying on the framebuffer contents : * reflecting previous drawing, from a CPU perspective. : */ :void exaWaitSync(ScreenPtr pScreen) 9 0.0098 :{ /* exaWaitSync total: 102 0.1111 */ 5 0.0054 : ExaScreenPriv(pScreen); : 45 0.0490 : if (pExaScr->info->needsSync && !pExaScr->swappedOut) { 4 0.0044 : (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker); 22 0.0240 : pExaScr->info->needsSync = FALSE; : } 17 0.0185 :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa_render.c" * * 785 0.8552 */ :/* : * Copyright © 2001 Keith Packard : * : * Partly based on code that is Copyright © The XFree86 Project Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include : :#include "exa_priv.h" : :#ifdef RENDER :#include "mipict.h" : :#if DEBUG_TRACE_FALL :static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n) :{ : char format[20]; : char size[20]; : char loc; : int temp; : : if (!pict) { : snprintf(string, n, "None"); : return; : } : : switch (pict->format) : { : case PICT_a8r8g8b8: : snprintf(format, 20, "ARGB8888"); : break; : case PICT_r5g6b5: : snprintf(format, 20, "RGB565 "); : break; : case PICT_x1r5g5b5: : snprintf(format, 20, "RGB555 "); : break; : case PICT_a8: : snprintf(format, 20, "A8 "); : break; : case PICT_a1: : snprintf(format, 20, "A1 "); : break; : default: : snprintf(format, 20, "0x%x", (int)pict->format); : break; : } : : loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm'; : : snprintf(size, 20, "%dx%d%s", pict->pDrawable->width, : pict->pDrawable->height, pict->repeat ? : " R" : ""); : : snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, size); :} : :static void :exaPrintCompositeFallback(CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst) :{ : char sop[20]; : char srcdesc[40], maskdesc[40], dstdesc[40]; : : switch(op) : { : case PictOpSrc: : sprintf(sop, "Src"); : break; : case PictOpOver: : sprintf(sop, "Over"); : break; : default: : sprintf(sop, "0x%x", (int)op); : break; : } : : exaCompositeFallbackPictDesc(pSrc, srcdesc, 40); : exaCompositeFallbackPictDesc(pMask, maskdesc, 40); : exaCompositeFallbackPictDesc(pDst, dstdesc, 40); : : ErrorF("Composite fallback: op %s, \n" : " src %s, \n" : " mask %s, \n" : " dst %s, \n", : sop, srcdesc, maskdesc, dstdesc); :} :#endif /* DEBUG_TRACE_FALL */ : :static Bool :exaOpReadsDestination (CARD8 op) 1 0.0011 :{ /* exaOpReadsDestination total: 4 0.0044 */ : /* FALSE (does not read destination) is the list of ops in the protocol : * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. : * That's just Clear and Src. ReduceCompositeOp() will already have : * converted con/disjoint clear/src to Clear or Src. : */ 3 0.0033 : switch (op) { : case PictOpClear: : case PictOpSrc: : return FALSE; : default: : return TRUE; : } :} : : :static Bool :exaGetPixelFromRGBA(CARD32 *pixel, : CARD16 red, : CARD16 green, : CARD16 blue, : CARD16 alpha, : CARD32 format) :{ : int rbits, bbits, gbits, abits; : int rshift, bshift, gshift, ashift; : : *pixel = 0; : : if (!PICT_FORMAT_COLOR(format)) : return FALSE; : : rbits = PICT_FORMAT_R(format); : gbits = PICT_FORMAT_G(format); : bbits = PICT_FORMAT_B(format); : abits = PICT_FORMAT_A(format); : : if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { : bshift = 0; : gshift = bbits; : rshift = gshift + gbits; : ashift = rshift + rbits; : } else { /* PICT_TYPE_ABGR */ : rshift = 0; : gshift = rbits; : bshift = gshift + gbits; : ashift = bshift + bbits; : } : : *pixel |= ( blue >> (16 - bbits)) << bshift; : *pixel |= ( red >> (16 - rbits)) << rshift; : *pixel |= (green >> (16 - gbits)) << gshift; : *pixel |= (alpha >> (16 - abits)) << ashift; : : return TRUE; :} : :static Bool :exaGetRGBAFromPixel(CARD32 pixel, : CARD16 *red, : CARD16 *green, : CARD16 *blue, : CARD16 *alpha, : CARD32 format) :{ : int rbits, bbits, gbits, abits; : int rshift, bshift, gshift, ashift; : : if (!PICT_FORMAT_COLOR(format)) : return FALSE; : : rbits = PICT_FORMAT_R(format); : gbits = PICT_FORMAT_G(format); : bbits = PICT_FORMAT_B(format); : abits = PICT_FORMAT_A(format); : : if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { : bshift = 0; : gshift = bbits; : rshift = gshift + gbits; : ashift = rshift + rbits; : } else { /* PICT_TYPE_ABGR */ : rshift = 0; : gshift = rbits; : bshift = gshift + gbits; : ashift = bshift + bbits; : } : : *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits); : while (rbits < 16) { : *red |= *red >> rbits; : rbits <<= 1; : } : : *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits); : while (gbits < 16) { : *green |= *green >> gbits; : gbits <<= 1; : } : : *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits); : while (bbits < 16) { : *blue |= *blue >> bbits; : bbits <<= 1; : } : : if (abits) { : *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits); : while (abits < 16) { : *alpha |= *alpha >> abits; : abits <<= 1; : } : } else : *alpha = 0xffff; : : return TRUE; :} : :static int :exaTryDriverSolidFill(PicturePtr pSrc, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) :{ : ExaScreenPriv (pDst->pDrawable->pScreen); : RegionRec region; : BoxPtr pbox; : int nbox; : int dst_off_x, dst_off_y; : PixmapPtr pSrcPix, pDstPix; : CARD32 pixel; : CARD16 red, green, blue, alpha; : ExaMigrationRec pixmaps[1]; : : xDst += pDst->pDrawable->x; : yDst += pDst->pDrawable->y; : xSrc += pSrc->pDrawable->x; : ySrc += pSrc->pDrawable->y; : : if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, : xSrc, ySrc, 0, 0, xDst, yDst, : width, height)) : return 1; : : pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); : pixel = exaGetPixmapFirstPixel (pSrcPix); : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = FALSE; : pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); : exaDoMigration(pixmaps, 1, TRUE); : : pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y); : if (!pDstPix) { : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return 0; : } : : if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha, : pSrc->format)) : { : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return -1; : } : : if (!exaGetPixelFromRGBA(&pixel, red, green, blue, alpha, : pDst->format)) : { : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return -1; : } : : if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel)) : { : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return -1; : } : : nbox = REGION_NUM_RECTS(®ion); : pbox = REGION_RECTS(®ion); : : while (nbox--) : { : (*pExaScr->info->Solid) (pDstPix, : pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, : pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); : pbox++; : } : : (*pExaScr->info->DoneSolid) (pDstPix); : exaMarkSync(pDst->pDrawable->pScreen); : : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return 1; :} : :static int :exaTryDriverComposite(CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) 49 0.0534 :{ /* exaTryDriverComposite total: 348 0.3791 */ 23 0.0251 : ExaScreenPriv (pDst->pDrawable->pScreen); : RegionRec region; : BoxPtr pbox; : int nbox; : int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; : PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; : struct _Pixmap scratch; : ExaMigrationRec pixmaps[3]; : 10 0.0109 : pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); 5 0.0054 : pDstPix = exaGetDrawablePixmap(pDst->pDrawable); 2 0.0022 : if (pMask) 2 0.0022 : pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); : : /* Bail if we might exceed coord limits by rendering from/to these. We : * should really be making some scratch pixmaps with offsets and coords : * adjusted to deal with this, but it hasn't been done yet. : */ 24 0.0261 : if (pSrcPix->drawable.width > pExaScr->info->maxX || : pSrcPix->drawable.height > pExaScr->info->maxY || : pDstPix->drawable.width > pExaScr->info->maxX || : pDstPix->drawable.height > pExaScr->info->maxY || : (pMask && (pMaskPix->drawable.width > pExaScr->info->maxX || : pMaskPix->drawable.height > pExaScr->info->maxY))) : { : return -1; : } : 14 0.0153 : xDst += pDst->pDrawable->x; 2 0.0022 : yDst += pDst->pDrawable->y; : : if (pMask) { 7 0.0076 : xMask += pMask->pDrawable->x; 10 0.0109 : yMask += pMask->pDrawable->y; : } : 9 0.0098 : xSrc += pSrc->pDrawable->x; 2 0.0022 : ySrc += pSrc->pDrawable->y; : 23 0.0251 : if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, : xSrc, ySrc, xMask, yMask, xDst, yDst, : width, height)) : return 1; : 38 0.0414 : if (pExaScr->info->CheckComposite && : !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) : { : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return -1; : } : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = exaOpReadsDestination(op); 1 0.0011 : pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); : pixmaps[1].as_dst = FALSE; : pixmaps[1].as_src = TRUE; 3 0.0033 : pixmaps[1].pPix = exaGetDrawablePixmap (pSrc->pDrawable); : if (pMask) { : pixmaps[2].as_dst = FALSE; : pixmaps[2].as_src = TRUE; 6 0.0065 : pixmaps[2].pPix = exaGetDrawablePixmap (pMask->pDrawable); 2 0.0022 : exaDoMigration(pixmaps, 3, TRUE); : } else { 2 0.0022 : exaDoMigration(pixmaps, 2, TRUE); : } : 4 0.0044 : pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); : if (pMask) 3 0.0033 : pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, : &mask_off_y); 2 0.0022 : pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y); : : if (!pDstPix) { : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return 0; : } : 1 0.0011 : if (!pSrcPix && (!pMask || pMaskPix) && pExaScr->info->UploadToScratch) { : pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); : if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch)) : pSrcPix = &scratch; : } else if (pSrcPix && pMask && !pMaskPix && pExaScr->info->UploadToScratch) { : pMaskPix = exaGetDrawablePixmap (pMask->pDrawable); : if ((*pExaScr->info->UploadToScratch) (pMaskPix, &scratch)) : pMaskPix = &scratch; : } : 2 0.0022 : if (!pSrcPix || (pMask && !pMaskPix)) { : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return 0; : } : 9 0.0098 : if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix, : pMaskPix, pDstPix)) : { 5 0.0054 : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return -1; : } : 1 0.0011 : nbox = REGION_NUM_RECTS(®ion); : pbox = REGION_RECTS(®ion); : : xMask -= xDst; 16 0.0174 : yMask -= yDst; : : xSrc -= xDst; : ySrc -= yDst; : 5 0.0054 : while (nbox--) : { 26 0.0283 : (*pExaScr->info->Composite) (pDstPix, : pbox->x1 + xSrc + src_off_x, : pbox->y1 + ySrc + src_off_y, : pbox->x1 + xMask + mask_off_x, : pbox->y1 + yMask + mask_off_y, : pbox->x1 + dst_off_x, : pbox->y1 + dst_off_y, : pbox->x2 - pbox->x1, : pbox->y2 - pbox->y1); : pbox++; : } 3 0.0033 : (*pExaScr->info->DoneComposite) (pDstPix); 12 0.0131 : exaMarkSync(pDst->pDrawable->pScreen); : 7 0.0076 : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : return 1; 18 0.0196 :} : :/** : * exaTryMagicTwoPassCompositeHelper implements PictOpOver using two passes of : * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component : * alpha and limited 1-tmu cards. : * : * From http://anholt.livejournal.com/32058.html: : * : * The trouble is that component-alpha rendering requires two different sources : * for blending: one for the source value to the blender, which is the : * per-channel multiplication of source and mask, and one for the source alpha : * for multiplying with the destination channels, which is the multiplication : * of the source channels by the mask alpha. So the equation for Over is: : * : * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A : * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R : * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G : * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B : * : * But we can do some simpler operations, right? How about PictOpOutReverse, : * which has a source factor of 0 and dest factor of (1 - source alpha). We : * can get the source alpha value (srca.X = src.A * mask.X) out of the texture : * blenders pretty easily. So we can do a component-alpha OutReverse, which : * gets us: : * : * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A : * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R : * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G : * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B : * : * OK. And if an op doesn't use the source alpha value for the destination : * factor, then we can do the channel multiplication in the texture blenders : * to get the source value, and ignore the source alpha that we wouldn't use. : * We've supported this in the Radeon driver for a long time. An example would : * be PictOpAdd, which does: : * : * dst.A = src.A * mask.A + dst.A : * dst.R = src.R * mask.R + dst.R : * dst.G = src.G * mask.G + dst.G : * dst.B = src.B * mask.B + dst.B : * : * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right : * after it, we get: : * : * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A) : * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R) : * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G) : * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B) : */ : :static int :exaTryMagicTwoPassCompositeHelper(CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) :{ : ExaScreenPriv (pDst->pDrawable->pScreen); : DrawablePtr pDstDraw = pDst->pDrawable; : PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDstDraw); : int xoff, yoff; : : assert(op == PictOpOver); : : if (pExaScr->info->CheckComposite && : (!(*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask, : pDst) || : !(*pExaScr->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst))) : { : return -1; : } : : /* Now, we think we should be able to accelerate this operation. First, : * composite the destination to be the destination times the source alpha : * factors. : */ : exaComposite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, : xDst, yDst, width, height); : : exaGetDrawableDeltas(pDstDraw, pDstPixmap, &xoff, &yoff); : xoff += pDstDraw->x; : yoff += pDstDraw->y; : exaPixmapDirty(pDstPixmap, xDst + xoff, yDst + yoff, xDst + xoff + width, : yDst + yoff + height); : : /* Then, add in the source value times the destination alpha factors (1.0). : */ : exaComposite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, : xDst, yDst, width, height); : : return 1; :} : :void :exaComposite(CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) 48 0.0523 :{ /* exaComposite total: 354 0.3856 */ 39 0.0425 : ExaScreenPriv (pDst->pDrawable->pScreen); : int ret = -1; 5 0.0054 : Bool saveSrcRepeat = pSrc->repeat; 3 0.0033 : Bool saveMaskRepeat = pMask ? pMask->repeat : 0; : ExaMigrationRec pixmaps[3]; : int npixmaps = 1; : PixmapPtr pSrcPixmap = NULL; : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = exaOpReadsDestination(op); 2 0.0022 : pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); : 4 0.0044 : if (pSrc->pDrawable) { 3 0.0033 : pSrcPixmap = exaGetDrawablePixmap (pSrc->pDrawable); : pixmaps[npixmaps].as_dst = FALSE; : pixmaps[npixmaps].as_src = TRUE; : pixmaps[npixmaps].pPix = pSrcPixmap; : npixmaps++; : } : 1 0.0011 : if (pMask && pMask->pDrawable) { : pixmaps[npixmaps].as_dst = FALSE; : pixmaps[npixmaps].as_src = TRUE; : pixmaps[npixmaps].pPix = exaGetDrawablePixmap (pMask->pDrawable); : npixmaps++; : } : : /* We currently don't support acceleration of gradients, or other pictures : * with a NULL pDrawable. : */ 14 0.0153 : if (pExaScr->swappedOut || : pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL)) : { : goto fallback; : } : : /* Remove repeat in source if useless */ 18 0.0196 : if (pSrc->repeat && !pSrc->transform && xSrc >= 0 && : (xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 && : (ySrc + height) <= pSrc->pDrawable->height) : pSrc->repeat = 0; : 3 0.0033 : if (!pMask) : { 3 0.0033 : if ((op == PictOpSrc && : ((pSrc->format == pDst->format) || : (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) || : (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) || : (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap && : pSrc->format == pDst->format && : (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8))) : { : if (pSrc->pDrawable->width == 1 && : pSrc->pDrawable->height == 1 && : pSrc->repeat) : { : ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst, : width, height); : if (ret == 1) : goto done; : } : else if (pSrcPixmap && !pSrc->repeat && !pSrc->transform) : { : RegionRec region; : : xDst += pDst->pDrawable->x; : yDst += pDst->pDrawable->y; : xSrc += pSrc->pDrawable->x; : ySrc += pSrc->pDrawable->y; : : if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, : xSrc, ySrc, xMask, yMask, xDst, : yDst, width, height)) : goto done; : : : exaCopyNtoN (pSrc->pDrawable, pDst->pDrawable, NULL, : REGION_RECTS(®ion), REGION_NUM_RECTS(®ion), : xSrc - xDst, ySrc - yDst, : FALSE, FALSE, 0, NULL); : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : goto done; : } : else if (pSrcPixmap && !pSrc->transform && : pSrc->repeatType == RepeatNormal) : { : RegionRec region; : DDXPointRec srcOrg; : : /* Let's see if the driver can do the repeat in one go */ : if (pExaScr->info->PrepareComposite && !pSrc->alphaMap && : !pDst->alphaMap) : { : ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, : ySrc, xMask, yMask, xDst, yDst, : width, height); : if (ret == 1) : goto done; : } : : /* Now see if we can use exaFillRegionTiled() */ : xDst += pDst->pDrawable->x; : yDst += pDst->pDrawable->y; : xSrc += pSrc->pDrawable->x; : ySrc += pSrc->pDrawable->y; : : if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, : ySrc, xMask, yMask, xDst, yDst, : width, height)) : goto done; : : srcOrg.x = (xSrc - xDst) % pSrcPixmap->drawable.width; : srcOrg.y = (ySrc - yDst) % pSrcPixmap->drawable.height; : : ret = exaFillRegionTiled(pDst->pDrawable, ®ion, pSrcPixmap, : &srcOrg, FB_ALLONES, GXcopy); : : REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); : : if (ret) : goto done; : } : } : } : : /* Remove repeat in mask if useless */ 12 0.0131 : if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 && : (xMask + width) <= pMask->pDrawable->width && yMask >= 0 && : (yMask + height) <= pMask->pDrawable->height) : pMask->repeat = 0; : 37 0.0403 : if (pExaScr->info->PrepareComposite && : (!pSrc->repeat || pSrc->repeatType == RepeatNormal) && : (!pMask || !pMask->repeat || pMask->repeatType == RepeatNormal) && : !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap) : { : Bool isSrcSolid; : 59 0.0643 : ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, : yMask, xDst, yDst, width, height); 3 0.0033 : if (ret == 1) : goto done; : : /* For generic masks and solid src pictures, mach64 can do Over in two : * passes, similar to the component-alpha case. : */ 8 0.0087 : isSrcSolid = pSrc->pDrawable->width == 1 && : pSrc->pDrawable->height == 1 && : pSrc->repeat; : : /* If we couldn't do the Composite in a single pass, and it was a : * component-alpha Over, see if we can do it in two passes with : * an OutReverse and then an Add. : */ 2 0.0022 : if (ret == -1 && op == PictOpOver && pMask && : (pMask->componentAlpha || isSrcSolid)) { : ret = exaTryMagicTwoPassCompositeHelper(op, pSrc, pMask, pDst, : xSrc, ySrc, : xMask, yMask, xDst, yDst, : width, height); : if (ret == 1) : goto done; : } : } : :fallback: : return; :#if DEBUG_TRACE_FALL : exaPrintCompositeFallback (op, pSrc, pMask, pDst); :#endif : : exaDoMigration(pixmaps, npixmaps, FALSE); : ExaCheckComposite (op, pSrc, pMask, pDst, xSrc, ySrc, : xMask, yMask, xDst, yDst, width, height); : :done: 15 0.0163 : pSrc->repeat = saveSrcRepeat; 3 0.0033 : if (pMask) 18 0.0196 : pMask->repeat = saveMaskRepeat; 6 0.0065 :} :#endif : :#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) : :/** : * exaRasterizeTrapezoid is just a wrapper around the software implementation. : * : * The trapezoid specification is basically too hard to be done in hardware (at : * the very least, without programmability), so we just do the appropriate : * Prepare/FinishAccess for it before using fbtrap.c. : */ :void :exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, : int x_off, int y_off) :{ /* exaRasterizeTrapezoid total: 2 0.0022 */ : DrawablePtr pDraw = pPicture->pDrawable; : ExaMigrationRec pixmaps[1]; : int xoff, yoff; : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = TRUE; 1 0.0011 : pixmaps[0].pPix = exaGetDrawablePixmap (pDraw); 1 0.0011 : exaDoMigration(pixmaps, 1, FALSE); : : exaPrepareAccess(pDraw, EXA_PREPARE_DEST); : fbRasterizeTrapezoid(pPicture, trap, x_off, y_off); : exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff); : exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff, : pDraw->x + xoff + pDraw->width, : pDraw->y + yoff + pDraw->height); : exaFinishAccess(pDraw, EXA_PREPARE_DEST); :} : :/** : * exaAddTriangles does migration and syncing before dumping down to the : * software implementation. : */ :void :exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, : xTriangle *tris) :{ : DrawablePtr pDraw = pPicture->pDrawable; : ExaMigrationRec pixmaps[1]; : int xoff, yoff; : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = TRUE; : pixmaps[0].pPix = exaGetDrawablePixmap (pDraw); : exaDoMigration(pixmaps, 1, FALSE); : : exaPrepareAccess(pDraw, EXA_PREPARE_DEST); : fbAddTriangles(pPicture, x_off, y_off, ntri, tris); : exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff); : exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff, : pDraw->x + xoff + pDraw->width, : pDraw->y + yoff + pDraw->height); : exaFinishAccess(pDraw, EXA_PREPARE_DEST); :} : :/** : * Returns TRUE if the glyphs in the lists intersect. Only checks based on : * bounding box, which appears to be good enough to catch most cases at least. : */ :static Bool :exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs) :{ : int x1, x2, y1, y2; : int n; : GlyphPtr glyph; : int x, y; : BoxRec extents; : Bool first = TRUE; : : x = 0; : y = 0; : while (nlist--) { : x += list->xOff; : y += list->yOff; : n = list->len; : list++; : while (n--) { : glyph = *glyphs++; : : if (glyph->info.width == 0 || glyph->info.height == 0) { : x += glyph->info.xOff; : y += glyph->info.yOff; : continue; : } : : x1 = x - glyph->info.x; : if (x1 < MINSHORT) : x1 = MINSHORT; : y1 = y - glyph->info.y; : if (y1 < MINSHORT) : y1 = MINSHORT; : x2 = x1 + glyph->info.width; : if (x2 > MAXSHORT) : x2 = MAXSHORT; : y2 = y1 + glyph->info.height; : if (y2 > MAXSHORT) : y2 = MAXSHORT; : : if (first) { : extents.x1 = x1; : extents.y1 = y1; : extents.x2 = x2; : extents.y2 = y2; : first = FALSE; : } else { : if (x1 < extents.x2 && x2 > extents.x1 && : y1 < extents.y2 && y2 > extents.y1) : { : return TRUE; : } : : if (x1 < extents.x1) : extents.x1 = x1; : if (x2 > extents.x2) : extents.x2 = x2; : if (y1 < extents.y1) : extents.y1 = y1; : if (y2 > extents.y2) : extents.y2 = y2; : } : x += glyph->info.xOff; : y += glyph->info.yOff; : } : } : : return FALSE; :} : :/* exaGlyphs is a slight variation on miGlyphs, to support acceleration. The : * issue is that miGlyphs' use of ModifyPixmapHeader makes it impossible to : * migrate these pixmaps. So, instead we create a pixmap at the beginning of : * the loop and upload each glyph into the pixmap before compositing. : */ :void :exaGlyphs (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int nlist, : GlyphListPtr list, : GlyphPtr *glyphs) 1 0.0011 :{ /* exaGlyphs total: 185 0.2015 */ : ExaScreenPriv (pDst->pDrawable->pScreen); : PixmapPtr pPixmap = NULL; : PicturePtr pPicture; : PixmapPtr pMaskPixmap = NULL; 1 0.0011 : PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDst->pDrawable); : PicturePtr pMask; : ScreenPtr pScreen = pDst->pDrawable->pScreen; : int width = 0, height = 0; : int x, y, x1, y1, xoff, yoff; 1 0.0011 : int xDst = list->xOff, yDst = list->yOff; : int n; : int error; : BoxRec extents; : CARD32 component_alpha; : : /* If we have a mask format but it's the same as all the glyphs and : * the glyphs don't intersect, we can avoid accumulating the glyphs in the : * temporary picture. : */ : if (maskFormat != NULL) { : Bool sameFormat = TRUE; : int i; : 1 0.0011 : for (i = 0; i < nlist; i++) { : if (maskFormat->format != list[i].format->format) { : sameFormat = FALSE; : break; : } : } : if (sameFormat) { : if (!exaGlyphsIntersect(nlist, list, glyphs)) { : maskFormat = NULL; : } : } : } : : /* If the driver doesn't support accelerated composite, there's no point in : * going to this extra work. Assume that any driver that supports Composite : * will be able to support component alpha using the two-pass helper. : */ : if (!pExaScr->info->PrepareComposite) : { : miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); : return; : } : : if (maskFormat) : { : GCPtr pGC; : xRectangle rect; : 1 0.0011 : miGlyphExtents (nlist, list, glyphs, &extents); : : extents.x1 = max(extents.x1, 0); : extents.y1 = max(extents.y1, 0); : extents.x2 = min(extents.x2, pDst->pDrawable->width); 1 0.0011 : extents.y2 = min(extents.y2, pDst->pDrawable->height); : : if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) : return; : width = extents.x2 - extents.x1; : height = extents.y2 - extents.y1; : pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, : maskFormat->depth); : if (!pMaskPixmap) : return; : component_alpha = NeedsComponent(maskFormat->format); 1 0.0011 : pMask = CreatePicture (0, &pMaskPixmap->drawable, : maskFormat, CPComponentAlpha, &component_alpha, : serverClient, &error); : if (!pMask) : { : (*pScreen->DestroyPixmap) (pMaskPixmap); : return; : } : ValidatePicture(pMask); : pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); : ValidateGC (&pMaskPixmap->drawable, pGC); : rect.x = 0; : rect.y = 0; : rect.width = width; : rect.height = height; 1 0.0011 : (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); : exaPixmapDirty(pMaskPixmap, 0, 0, width, height); : FreeScratchGC (pGC); : x = -extents.x1; : y = -extents.y1; : } : else : { : pMask = pDst; : x = 0; : y = 0; : } : : exaGetDrawableDeltas(pDst->pDrawable, pDstPixmap, &xoff, &yoff); : : while (nlist--) : { : GCPtr pGC = NULL; : int maxwidth = 0, maxheight = 0, i; : ExaMigrationRec pixmaps[1]; : PixmapPtr pScratchPixmap = NULL; : : x += list->xOff; : y += list->yOff; : n = list->len; : for (i = 0; i < n; i++) { 14 0.0153 : if (glyphs[i]->info.width > maxwidth) : maxwidth = glyphs[i]->info.width; : if (glyphs[i]->info.height > maxheight) : maxheight = glyphs[i]->info.height; : } 1 0.0011 : if (maxwidth == 0 || maxheight == 0) { : while (n--) : { : GlyphPtr glyph; : : glyph = *glyphs++; : x += glyph->info.xOff; : y += glyph->info.yOff; : } : list++; : continue; : } : : /* Create the (real) temporary pixmap to store the current glyph in */ 1 0.0011 : pPixmap = (*pScreen->CreatePixmap) (pScreen, maxwidth, maxheight, : list->format->depth); : if (!pPixmap) : return; : : /* Create a temporary picture to wrap the temporary pixmap, so it can be : * used as a source for Composite. : */ : component_alpha = NeedsComponent(list->format->format); : pPicture = CreatePicture (0, &pPixmap->drawable, list->format, : CPComponentAlpha, &component_alpha, : serverClient, &error); : if (!pPicture) { : (*pScreen->DestroyPixmap) (pPixmap); : return; : } : ValidatePicture(pPicture); : : /* Give the temporary pixmap an initial kick towards the screen, so : * it'll stick there. : */ : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = TRUE; : pixmaps[0].pPix = pPixmap; : exaDoMigration (pixmaps, 1, pExaScr->info->PrepareComposite != NULL); : 1 0.0011 : while (n--) : { 1 0.0011 : GlyphPtr glyph = *glyphs++; : pointer glyphdata = (pointer) (glyph + 1); 5 0.0054 : DrawablePtr pCmpDrw = (maskFormat ? pMask : pDst)->pDrawable; : : x1 = x - glyph->info.x; 8 0.0087 : y1 = y - glyph->info.y; : 7 0.0076 : if (x1 >= pCmpDrw->width || y1 >= pCmpDrw->height || : (x1 + glyph->info.width) <= 0 || (y1 + glyph->info.height) <= 0) : goto nextglyph; : 2 0.0022 : (*pScreen->ModifyPixmapHeader) (pScratchPixmap, : glyph->info.width, : glyph->info.height, : 0, 0, -1, glyphdata); : : /* Copy the glyph data into the proper pixmap instead of a fake. : * First we try to use UploadToScreen, if we can, then we fall back : * to a plain exaCopyArea in case of failure. : */ 5 0.0054 : if (pExaScr->info->UploadToScreen && : exaPixmapIsOffscreen(pPixmap) && : (*pExaScr->info->UploadToScreen) (pPixmap, 0, 0, : glyph->info.width, : glyph->info.height, : glyphdata, : PixmapBytePad(glyph->info.width, : list->format->depth))) : { : exaMarkSync (pScreen); : } else { : /* Set up the scratch pixmap/GC for doing a CopyArea. */ : if (pScratchPixmap == NULL) { : /* Get a scratch pixmap to wrap the original glyph data */ 2 0.0022 : pScratchPixmap = GetScratchPixmapHeader (pScreen, : glyph->info.width, : glyph->info.height, : list->format->depth, : list->format->depth, : -1, glyphdata); : if (!pScratchPixmap) { : FreePicture(pPicture, 0); : (*pScreen->DestroyPixmap) (pPixmap); : return; : } : : /* Get a scratch GC with which to copy the glyph data from : * scratch to temporary : */ : pGC = GetScratchGC (list->format->depth, pScreen); 1 0.0011 : ValidateGC (&pPixmap->drawable, pGC); : } else { 2 0.0022 : (*pScreen->ModifyPixmapHeader) (pScratchPixmap, : glyph->info.width, : glyph->info.height, : 0, 0, -1, glyphdata); 5 0.0054 : pScratchPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; : } : 7 0.0076 : exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC, : 0, 0, glyph->info.width, glyph->info.height, 0, 0); : } : 5 0.0054 : exaPixmapDirty (pPixmap, 0, 0, : glyph->info.width, glyph->info.height); : 5 0.0054 : if (maskFormat) : { 4 0.0044 : exaComposite (PictOpAdd, pPicture, NULL, pMask, 0, 0, 0, 0, : x1, y1, glyph->info.width, glyph->info.height); 2 0.0022 : exaPixmapDirty(pMaskPixmap, x1, y1, x1 + glyph->info.width, : y1 + glyph->info.height); : } : else : { 13 0.0142 : exaComposite (op, pSrc, pPicture, pDst, : xSrc + x1 - xDst, ySrc + y1 - yDst, : 0, 0, x1, y1, glyph->info.width, : glyph->info.height); 11 0.0120 : x1 += pDst->pDrawable->x + xoff; 5 0.0054 : y1 += pDst->pDrawable->y + yoff; 3 0.0033 : exaPixmapDirty(pDstPixmap, x1, y1, x1 + glyph->info.width, : y1 + glyph->info.height); : } :nextglyph: 3 0.0033 : x += glyph->info.xOff; 2 0.0022 : y += glyph->info.yOff; : } : list++; : if (pGC != NULL) : FreeScratchGC (pGC); 1 0.0011 : FreePicture ((pointer) pPicture, 0); : (*pScreen->DestroyPixmap) (pPixmap); : if (pScratchPixmap != NULL) : FreeScratchPixmapHeader (pScratchPixmap); : } : if (maskFormat) : { : x = extents.x1; : y = extents.y1; 1 0.0011 : exaComposite (op, pSrc, pMask, pDst, xSrc + x - xDst, ySrc + y - yDst, : 0, 0, x, y, width, height); : FreePicture ((pointer) pMask, (XID) 0); : (*pScreen->DestroyPixmap) (pMaskPixmap); : } :} /* * Total samples for file : "interp.c" * * 753 0.8203 */ 753 0.8203 : /* __i686.get_pc_thunk.cx total: 1 0.0011 */ /* __i686.get_pc_thunk.bx total: 44 0.0479 */ /* _nl_load_locale_from_archive total: 1 0.0011 */ /* _itoa_word total: 1 0.0011 */ /* __find_specmb total: 2 0.0022 */ /* _IO_old_init total: 1 0.0011 */ /* _IO_str_init_static_internal total: 1 0.0011 */ /* _int_free total: 227 0.2473 */ /* _int_malloc total: 460 0.5011 */ /* _int_realloc total: 10 0.0109 */ /* __close_nocancel total: 1 0.0011 */ /* __read_nocancel total: 3 0.0033 */ /* __xstat32_conv total: 1 0.0011 */ /* * Total samples for file : "exa_unaccel.c" * * 590 0.6427 */ 590 0.6427 : /* __i686.get_pc_thunk.cx total: 14 0.0153 */ /* __i686.get_pc_thunk.bx total: 576 0.6275 */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa_offscreen.c" * * 534 0.5817 */ :/* : * Copyright © 2003 Anders Carlsson : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Anders Carlsson not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Anders Carlsson makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :/** @file : * This allocator allocates blocks of memory by maintaining a list of areas : * and a score for each area. As an area is marked used, its score is : * incremented, and periodically all of the areas have their scores decayed by : * a fraction. When allocating, the contiguous block of areas with the minimum : * score is found and evicted in order to make room for the new allocation. : */ : :#include "exa_priv.h" : :#include :#include :#include : :#if DEBUG_OFFSCREEN :#define DBG_OFFSCREEN(a) ErrorF a :#else :#define DBG_OFFSCREEN(a) :#endif : :#if DEBUG_OFFSCREEN :static void :ExaOffscreenValidate (ScreenPtr pScreen) :{ : ExaScreenPriv (pScreen); : ExaOffscreenArea *prev = 0, *area; : : assert (pExaScr->info->offScreenAreas->base_offset == : pExaScr->info->offScreenBase); : for (area = pExaScr->info->offScreenAreas; area; area = area->next) : { : assert (area->offset >= area->base_offset && : area->offset < (area->base_offset + area->size)); : if (prev) : assert (prev->base_offset + prev->size == area->base_offset); : prev = area; : } : assert (prev->base_offset + prev->size == pExaScr->info->memorySize); :} :#else :#define ExaOffscreenValidate(s) :#endif : :static ExaOffscreenArea * :ExaOffscreenKickOut (ScreenPtr pScreen, ExaOffscreenArea *area) :{ : if (area->save) : (*area->save) (pScreen, area); : return exaOffscreenFree (pScreen, area); :} : :/** : * exaOffscreenAlloc allocates offscreen memory : * : * @param pScreen current screen : * @param size size in bytes of the allocation : * @param align byte alignment requirement for the offset of the allocated area : * @param locked whether the allocated area is locked and can't be kicked out : * @param save callback for when the area is evicted from memory : * @param privdata private data for the save callback. : * : * Allocates offscreen memory from the device associated with pScreen. size : * and align deteremine where and how large the allocated area is, and locked : * will mark whether it should be held in card memory. privdata may be any : * pointer for the save callback when the area is removed. : * : * Note that locked areas do get evicted on VT switch unless the driver : * requested version 2.1 or newer behavior. In that case, the save callback is : * still called. : */ :ExaOffscreenArea * :exaOffscreenAlloc (ScreenPtr pScreen, int size, int align, : Bool locked, : ExaOffscreenSaveProc save, : pointer privData) 2 0.0022 :{ /* exaOffscreenAlloc total: 68 0.0741 */ : ExaOffscreenArea *area, *begin, *best; 1 0.0011 : ExaScreenPriv (pScreen); : int tmp, real_size = 0, best_score; :#if DEBUG_OFFSCREEN : static int number = 0; : ErrorF("================= ============ allocating a new pixmap %d\n", ++number); :#endif : : ExaOffscreenValidate (pScreen); 1 0.0011 : if (!align) : align = 1; : : if (!size) : { : DBG_OFFSCREEN (("Alloc 0x%x -> EMPTY\n", size)); : return NULL; : } : : /* throw out requests that cannot fit */ 2 0.0022 : if (size > (pExaScr->info->memorySize - pExaScr->info->offScreenBase)) : { : DBG_OFFSCREEN (("Alloc 0x%x vs (0x%lx) -> TOBIG\n", size, : pExaScr->info->memorySize - : pExaScr->info->offScreenBase)); : return NULL; : } : : /* Try to find a free space that'll fit. */ 11 0.0120 : for (area = pExaScr->info->offScreenAreas; area; area = area->next) : { : /* skip allocated areas */ 11 0.0120 : if (area->state != ExaOffscreenAvail) : continue; : : /* adjust size to match alignment requirement */ : real_size = size; 2 0.0022 : tmp = area->base_offset % align; 31 0.0338 : if (tmp) : real_size += (align - tmp); : : /* does it fit? */ : if (real_size <= area->size) : break; : } : : if (!area) : { : /* : * Kick out existing users to make space. : * : * First, locate a region which can hold the desired object. : */ : : /* prev points at the first object to boot */ : best = NULL; : best_score = INT_MAX; : for (begin = pExaScr->info->offScreenAreas; begin != NULL; : begin = begin->next) : { : int avail, score; : ExaOffscreenArea *scan; : : if (begin->state == ExaOffscreenLocked) : continue; : : /* adjust size needed to account for alignment loss for this area */ : real_size = size; : tmp = begin->base_offset % align; : if (tmp) : real_size += (align - tmp); : : avail = 0; : score = 0; : /* now see if we can make room here, and how "costly" it'll be. */ : for (scan = begin; scan != NULL; scan = scan->next) : { : if (scan->state == ExaOffscreenLocked) { : /* Can't make room here, start after this locked area. */ : begin = scan; : break; : } : /* Score should only be non-zero for ExaOffscreenRemovable */ : score += scan->score; : avail += scan->size; : if (avail >= real_size) : break; : } : /* Is it the best option we've found so far? */ : if (avail >= real_size && score < best_score) { : best = begin; : best_score = score; : } : } : area = best; : if (!area) : { : DBG_OFFSCREEN (("Alloc 0x%x -> NOSPACE\n", size)); : /* Could not allocate memory */ : ExaOffscreenValidate (pScreen); : return NULL; : } : : /* adjust size needed to account for alignment loss for this area */ : real_size = size; : tmp = area->base_offset % align; : if (tmp) : real_size += (align - tmp); : : /* : * Kick out first area if in use : */ : if (area->state != ExaOffscreenAvail) : area = ExaOffscreenKickOut (pScreen, area); : /* : * Now get the system to merge the other needed areas together : */ : while (area->size < real_size) : { : assert (area->next && area->next->state == ExaOffscreenRemovable); : (void) ExaOffscreenKickOut (pScreen, area->next); : } : } : : /* save extra space in new area */ 1 0.0011 : if (real_size < area->size) : { : ExaOffscreenArea *new_area = xalloc (sizeof (ExaOffscreenArea)); : if (!new_area) : return NULL; : new_area->base_offset = area->base_offset + real_size; : new_area->offset = new_area->base_offset; : new_area->size = area->size - real_size; : new_area->state = ExaOffscreenAvail; : new_area->save = NULL; : new_area->score = 0; : new_area->next = area->next; 1 0.0011 : area->next = new_area; : area->size = real_size; : } : /* : * Mark this area as in use : */ : if (locked) : area->state = ExaOffscreenLocked; : else : area->state = ExaOffscreenRemovable; : area->privData = privData; : area->save = save; : area->score = 0; : area->offset = (area->base_offset + align - 1); 5 0.0054 : area->offset -= area->offset % align; : : ExaOffscreenValidate (pScreen); : : DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x (0x%x)\n", size, : area->base_offset, area->offset)); : return area; :} : :/** : * Ejects all offscreen areas, and uninitializes the offscreen memory manager. : */ :void :ExaOffscreenSwapOut (ScreenPtr pScreen) :{ : ExaScreenPriv (pScreen); : : ExaOffscreenValidate (pScreen); : /* loop until a single free area spans the space */ : for (;;) : { : ExaOffscreenArea *area = pExaScr->info->offScreenAreas; : : if (!area) : break; : if (area->state == ExaOffscreenAvail) : { : area = area->next; : if (!area) : break; : } : assert (area->state != ExaOffscreenAvail); : (void) ExaOffscreenKickOut (pScreen, area); : ExaOffscreenValidate (pScreen); : } : ExaOffscreenValidate (pScreen); : ExaOffscreenFini (pScreen); :} : :/** Ejects all pixmaps managed by EXA. */ :static void :ExaOffscreenEjectPixmaps (ScreenPtr pScreen) :{ : ExaScreenPriv (pScreen); : : ExaOffscreenValidate (pScreen); : /* loop until a single free area spans the space */ : for (;;) : { : ExaOffscreenArea *area; : : for (area = pExaScr->info->offScreenAreas; area != NULL; : area = area->next) : { : if (area->state == ExaOffscreenRemovable && : area->save == exaPixmapSave) : { : (void) ExaOffscreenKickOut (pScreen, area); : ExaOffscreenValidate (pScreen); : break; : } : } : if (area == NULL) : break; : } : ExaOffscreenValidate (pScreen); :} : :void :ExaOffscreenSwapIn (ScreenPtr pScreen) :{ : exaOffscreenInit (pScreen); :} : :/** : * Prepares EXA for disabling of FB access, or restoring it. : * : * In version 2.1, the disabling results in pixmaps being ejected, while other : * allocations remain. With this plus the prevention of migration while : * swappedOut is set, EXA by itself should not cause any access of the : * framebuffer to occur while swapped out. Any remaining issues are the : * responsibility of the driver. : * : * Prior to version 2.1, all allocations, including locked ones, are ejected : * when access is disabled, and the allocator is torn down while swappedOut : * is set. This is more drastic, and caused implementation difficulties for : * many drivers that could otherwise handle the lack of FB access while : * swapped out. : */ :void :exaEnableDisableFBAccess (int index, Bool enable) :{ : ScreenPtr pScreen = screenInfo.screens[index]; : ExaScreenPriv (pScreen); : : if (!enable && pExaScr->disableFbCount++ == 0) { : if (pExaScr->info->exa_minor < 1) : ExaOffscreenSwapOut (pScreen); : else : ExaOffscreenEjectPixmaps (pScreen); : pExaScr->swappedOut = TRUE; : } : : if (enable && --pExaScr->disableFbCount == 0) { : if (pExaScr->info->exa_minor < 1) : ExaOffscreenSwapIn (pScreen); : pExaScr->swappedOut = FALSE; : } :} : :/* merge the next free area into this one */ :static void :ExaOffscreenMerge (ExaOffscreenArea *area) 1 0.0011 :{ /* ExaOffscreenMerge total: 3 0.0033 */ : ExaOffscreenArea *next = area->next; : : /* account for space */ : area->size += next->size; : /* frob pointer */ 1 0.0011 : area->next = next->next; : xfree (next); 1 0.0011 :} : :/** : * exaOffscreenFree frees an allocation. : * : * @param pScreen current screen : * @param area offscreen area to free : * : * exaOffscreenFree frees an allocation created by exaOffscreenAlloc. Note that : * the save callback of the area is not called, and it is up to the driver to : * do any cleanup necessary as a result. : * : * @return pointer to the newly freed area. This behavior should not be relied : * on. : */ :ExaOffscreenArea * :exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area) :{ /* exaOffscreenFree total: 11 0.0120 */ : ExaScreenPriv(pScreen); : ExaOffscreenArea *next = area->next; : ExaOffscreenArea *prev; : : DBG_OFFSCREEN (("Free 0x%x -> 0x%x (0x%x)\n", area->size, : area->base_offset, area->offset)); : ExaOffscreenValidate (pScreen); : : area->state = ExaOffscreenAvail; : area->save = NULL; : area->score = 0; : /* : * Find previous area : */ : if (area == pExaScr->info->offScreenAreas) : prev = NULL; : else 2 0.0022 : for (prev = pExaScr->info->offScreenAreas; prev; prev = prev->next) 8 0.0087 : if (prev->next == area) : break; : : /* link with next area if free */ : if (next && next->state == ExaOffscreenAvail) 1 0.0011 : ExaOffscreenMerge (area); : : /* link with prev area if free */ : if (prev && prev->state == ExaOffscreenAvail) : { : area = prev; : ExaOffscreenMerge (area); : } : : ExaOffscreenValidate (pScreen); : DBG_OFFSCREEN(("\tdone freeing\n")); : return area; :} : :void :ExaOffscreenMarkUsed (PixmapPtr pPixmap) 11 0.0120 :{ /* ExaOffscreenMarkUsed total: 452 0.4924 */ 4 0.0044 : ExaPixmapPriv (pPixmap); 17 0.0185 : ExaScreenPriv (pPixmap->drawable.pScreen); : static int iter = 0; : 9 0.0098 : if (!pExaPixmap || !pExaPixmap->area) : return; : : /* The numbers here are arbitrary. We may want to tune these. */ : pExaPixmap->area->score += 100; 19 0.0207 : if (++iter == 10) { : ExaOffscreenArea *area; 79 0.0861 : for (area = pExaScr->info->offScreenAreas; area != NULL; 27 0.0294 : area = area->next) : { 77 0.0839 : if (area->state == ExaOffscreenRemovable) 198 0.2157 : area->score = (area->score * 7) / 8; : } : iter = 0; : } 11 0.0120 :} : :/** : * exaOffscreenInit initializes the offscreen memory manager. : * : * @param pScreen current screen : * : * exaOffscreenInit is called by exaDriverInit to set up the memory manager for : * the screen, if any offscreen memory is available. : */ :Bool :exaOffscreenInit (ScreenPtr pScreen) :{ : ExaScreenPriv (pScreen); : ExaOffscreenArea *area; : : /* Allocate a big free area */ : area = xalloc (sizeof (ExaOffscreenArea)); : : if (!area) : return FALSE; : : area->state = ExaOffscreenAvail; : area->base_offset = pExaScr->info->offScreenBase; : area->offset = area->base_offset; : area->size = pExaScr->info->memorySize - area->base_offset; : area->save = NULL; : area->next = NULL; : area->score = 0; : : /* Add it to the free areas */ : pExaScr->info->offScreenAreas = area; : : ExaOffscreenValidate (pScreen); : : return TRUE; :} : :void :ExaOffscreenFini (ScreenPtr pScreen) :{ : ExaScreenPriv (pScreen); : ExaOffscreenArea *area; : : /* just free all of the area records */ : while ((area = pExaScr->info->offScreenAreas)) : { : pExaScr->info->offScreenAreas = area->next; : xfree (area); : } :} /* * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-region.c" * * 480 0.5229 */ :/*********************************************************** : :Copyright 1987, 1988, 1989, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : :Copyright 1987, 1988, 1989 by :Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :******************************************************************/ : :#include :#include :#include :#include :#include : :#include "pixman-private.h" :#include "pixman.h" : :typedef struct pixman_region16_point { : int x, y; :} pixman_region16_point_t; : :#define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects) :/* not a region */ :#define PIXREGION_NAR(reg) ((reg)->data == pixman_brokendata) :#define PIXREGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1) :#define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0) :#define PIXREGION_RECTS(reg) ((reg)->data ? (pixman_box16_t *)((reg)->data + 1) \ : : &(reg)->extents) :#define PIXREGION_BOXPTR(reg) ((pixman_box16_t *)((reg)->data + 1)) :#define PIXREGION_BOX(reg,i) (&PIXREGION_BOXPTR(reg)[i]) :#define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects) :#define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1) :#define PIXREGION_SZOF(n) (sizeof(pixman_region16_data_t) + ((n) * sizeof(pixman_box16_t))) : : :#undef assert :#ifdef DEBUG_PIXREGION :#define assert(expr) {if (!(expr)) \ : FatalError("Assertion failed file %s, line %d: expr\n", \ : __FILE__, __LINE__); } :#else :#define assert(expr) :#endif : :#define good(reg) assert(pixman_region_selfcheck(reg)) : :#undef MIN :#define MIN(a,b) ((a) < (b) ? (a) : (b)) :#undef MAX :#define MAX(a,b) ((a) > (b) ? (a) : (b)) : :static const pixman_box16_t _pixman_region_emptyBox = {0, 0, 0, 0}; :static const pixman_region16_data_t _pixman_region_emptyData = {0, 0}; :static const pixman_region16_data_t _pixman_brokendata = {0, 0}; : :static pixman_box16_t *pixman_region_emptyBox = (pixman_box16_t *)&_pixman_region_emptyBox; :static pixman_region16_data_t *pixman_region_emptyData = (pixman_region16_data_t *)&_pixman_region_emptyData; :static pixman_region16_data_t *pixman_brokendata = (pixman_region16_data_t *)&_pixman_brokendata; : :/* This function exists only to make it possible to preserve the X ABI - it should : * go away at first opportunity. : * : * The problem is that the X ABI exports the three structs and has used : * them through macros. So the X server calls this function with : * the addresses of those structs which makes the existing code continue to : * work. : */ :void :pixman_region_set_static_pointers (pixman_box16_t *empty_box, : pixman_region16_data_t *empty_data, : pixman_region16_data_t *broken_data) :{ : pixman_region_emptyBox = empty_box; : pixman_region_emptyData = empty_data; : pixman_brokendata = broken_data; :} : :static pixman_bool_t :pixman_break (pixman_region16_t *pReg); : :/* : * The functions in this file implement the Region abstraction used extensively : * throughout the X11 sample server. A Region is simply a set of disjoint : * (non-overlapping) rectangles, plus an "extent" rectangle which is the : * smallest single rectangle that contains all the non-overlapping rectangles. : * : * A Region is implemented as a "y-x-banded" array of rectangles. This array : * imposes two degrees of order. First, all rectangles are sorted by top side : * y coordinate first (y1), and then by left side x coordinate (x1). : * : * Furthermore, the rectangles are grouped into "bands". Each rectangle in a : * band has the same top y coordinate (y1), and each has the same bottom y : * coordinate (y2). Thus all rectangles in a band differ only in their left : * and right side (x1 and x2). Bands are implicit in the array of rectangles: : * there is no separate list of band start pointers. : * : * The y-x band representation does not minimize rectangles. In particular, : * if a rectangle vertically crosses a band (the rectangle has scanlines in : * the y1 to y2 area spanned by the band), then the rectangle may be broken : * down into two or more smaller rectangles stacked one atop the other. : * : * ----------- ----------- : * | | | | band 0 : * | | -------- ----------- -------- : * | | | | in y-x banded | | | | band 1 : * | | | | form is | | | | : * ----------- | | ----------- -------- : * | | | | band 2 : * -------- -------- : * : * An added constraint on the rectangles is that they must cover as much : * horizontal area as possible: no two rectangles within a band are allowed : * to touch. : * : * Whenever possible, bands will be merged together to cover a greater vertical : * distance (and thus reduce the number of rectangles). Two bands can be merged : * only if the bottom of one touches the top of the other and they have : * rectangles in the same places (of the same width, of course). : * : * Adam de Boor wrote most of the original region code. Joel McCormack : * substantially modified or rewrote most of the core arithmetic routines, and : * added pixman_region_validate in order to support several speed improvements to : * pixman_region_validateTree. Bob Scheifler changed the representation to be more : * compact when empty or a single rectangle, and did a bunch of gratuitous : * reformatting. Carl Worth did further gratuitous reformatting while re-merging : * the server and client region code into libpixregion. : */ : :/* true iff two Boxes overlap */ :#define EXTENTCHECK(r1,r2) \ : (!( ((r1)->x2 <= (r2)->x1) || \ : ((r1)->x1 >= (r2)->x2) || \ : ((r1)->y2 <= (r2)->y1) || \ : ((r1)->y1 >= (r2)->y2) ) ) : :/* true iff (x,y) is in Box */ :#define INBOX(r,x,y) \ : ( ((r)->x2 > x) && \ : ((r)->x1 <= x) && \ : ((r)->y2 > y) && \ : ((r)->y1 <= y) ) : :/* true iff Box r1 contains Box r2 */ :#define SUBSUMES(r1,r2) \ : ( ((r1)->x1 <= (r2)->x1) && \ : ((r1)->x2 >= (r2)->x2) && \ : ((r1)->y1 <= (r2)->y1) && \ : ((r1)->y2 >= (r2)->y2) ) : :#define allocData(n) malloc(PIXREGION_SZOF(n)) :#define freeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data) : :#define RECTALLOC_BAIL(pReg,n,bail) \ :if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ : if (!pixman_rect_alloc(pReg, n)) { goto bail; } : :#define RECTALLOC(pReg,n) \ :if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ : if (!pixman_rect_alloc(pReg, n)) { return FALSE; } : :#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \ :{ \ : pNextRect->x1 = nx1; \ : pNextRect->y1 = ny1; \ : pNextRect->x2 = nx2; \ : pNextRect->y2 = ny2; \ : pNextRect++; \ :} : :#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \ :{ \ : if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\ : { \ : if (!pixman_rect_alloc(pReg, 1)) \ : return FALSE; \ : pNextRect = PIXREGION_TOP(pReg); \ : } \ : ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \ : pReg->data->numRects++; \ : assert(pReg->data->numRects<=pReg->data->size); \ :} : :#define DOWNSIZE(reg,numRects) \ :if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ :{ \ : pixman_region16_data_t * NewData; \ : NewData = (pixman_region16_data_t *)realloc((reg)->data, PIXREGION_SZOF(numRects)); \ : if (NewData) \ : { \ : NewData->size = (numRects); \ : (reg)->data = NewData; \ : } \ :} : :pixman_bool_t :pixman_region_equal(reg1, reg2) : pixman_region16_t * reg1; : pixman_region16_t * reg2; :{ : int i; : pixman_box16_t *rects1; : pixman_box16_t *rects2; : : if (reg1->extents.x1 != reg2->extents.x1) return FALSE; : if (reg1->extents.x2 != reg2->extents.x2) return FALSE; : if (reg1->extents.y1 != reg2->extents.y1) return FALSE; : if (reg1->extents.y2 != reg2->extents.y2) return FALSE; : if (PIXREGION_NUM_RECTS(reg1) != PIXREGION_NUM_RECTS(reg2)) return FALSE; : : rects1 = PIXREGION_RECTS(reg1); : rects2 = PIXREGION_RECTS(reg2); : for (i = 0; i != PIXREGION_NUM_RECTS(reg1); i++) { : if (rects1[i].x1 != rects2[i].x1) return FALSE; : if (rects1[i].x2 != rects2[i].x2) return FALSE; : if (rects1[i].y1 != rects2[i].y1) return FALSE; : if (rects1[i].y2 != rects2[i].y2) return FALSE; : } : return TRUE; :} : :int :pixman_region16_print(rgn) : pixman_region16_t * rgn; :{ : int num, size; : int i; : pixman_box16_t * rects; : : num = PIXREGION_NUM_RECTS(rgn); : size = PIXREGION_SIZE(rgn); : rects = PIXREGION_RECTS(rgn); : fprintf(stderr, "num: %d size: %d\n", num, size); : fprintf(stderr, "extents: %d %d %d %d\n", : rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2); : for (i = 0; i < num; i++) : fprintf(stderr, "%d %d %d %d \n", : rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); : fprintf(stderr, "\n"); : return(num); :} : : :void :pixman_region_init (pixman_region16_t *region) 8 0.0087 :{ /* pixman_region_init total: 13 0.0142 */ 3 0.0033 : region->extents = *pixman_region_emptyBox; : region->data = pixman_region_emptyData; 2 0.0022 :} : :void :pixman_region_init_rect (pixman_region16_t *region, : int x, int y, unsigned int width, unsigned int height) 2 0.0022 :{ /* pixman_region_init_rect total: 3 0.0033 */ : region->extents.x1 = x; : region->extents.y1 = y; : region->extents.x2 = x + width; 1 0.0011 : region->extents.y2 = y + height; : region->data = NULL; :} : :void :pixman_region_init_with_extents (pixman_region16_t *region, pixman_box16_t *extents) 1 0.0011 :{ /* pixman_region_init_with_extents total: 2 0.0022 */ 1 0.0011 : region->extents = *extents; : region->data = NULL; :} : :void :pixman_region_fini (pixman_region16_t *region) 41 0.0447 :{ /* pixman_region_fini total: 44 0.0479 */ : good (region); 1 0.0011 : freeData (region); 2 0.0022 :} : :int :pixman_region_n_rects (pixman_region16_t *region) 14 0.0153 :{ /* pixman_region_n_rects total: 38 0.0414 */ 16 0.0174 : return PIXREGION_NUM_RECTS (region); 8 0.0087 :} : :pixman_box16_t * :pixman_region_rects (pixman_region16_t *region) :{ : return PIXREGION_RECTS (region); :} : :pixman_box16_t * :pixman_region_rectangles (pixman_region16_t *region, : int *n_rects) 41 0.0447 :{ /* pixman_region_rectangles total: 82 0.0893 */ : if (n_rects) : *n_rects = PIXREGION_NUM_RECTS (region); : 17 0.0185 : return PIXREGION_RECTS (region); 24 0.0261 :} : :static pixman_bool_t :pixman_break (pixman_region16_t *region) :{ : freeData (region); : region->extents = *pixman_region_emptyBox; : region->data = pixman_brokendata; : return FALSE; :} : :static pixman_bool_t :pixman_rect_alloc (pixman_region16_t * region, int n) 7 0.0076 :{ /* pixman_rect_alloc total: 16 0.0174 */ : pixman_region16_data_t *data; : : if (!region->data) : { : n++; : region->data = allocData(n); : if (!region->data) : return pixman_break (region); : region->data->numRects = 1; : *PIXREGION_BOXPTR(region) = region->extents; : } 1 0.0011 : else if (!region->data->size) : { 4 0.0044 : region->data = allocData(n); 1 0.0011 : if (!region->data) : return pixman_break (region); 1 0.0011 : region->data->numRects = 0; : } : else : { : if (n == 1) : { : n = region->data->numRects; : if (n > 500) /* XXX pick numbers out of a hat */ : n = 250; : } : n += region->data->numRects; : data = (pixman_region16_data_t *)realloc(region->data, PIXREGION_SZOF(n)); : if (!data) : return pixman_break (region); : region->data = data; : } : region->data->size = n; : return TRUE; 2 0.0022 :} : :pixman_bool_t :pixman_region_copy (pixman_region16_t *dst, pixman_region16_t *src) 4 0.0044 :{ /* pixman_region_copy total: 15 0.0163 */ : good(dst); : good(src); : if (dst == src) : return TRUE; 2 0.0022 : dst->extents = src->extents; 1 0.0011 : if (!src->data || !src->data->size) : { 6 0.0065 : freeData(dst); 1 0.0011 : dst->data = src->data; : return TRUE; : } : if (!dst->data || (dst->data->size < src->data->numRects)) : { : freeData(dst); : dst->data = allocData(src->data->numRects); : if (!dst->data) : return pixman_break (dst); : dst->data->size = src->data->numRects; : } : dst->data->numRects = src->data->numRects; : memmove((char *)PIXREGION_BOXPTR(dst),(char *)PIXREGION_BOXPTR(src), : dst->data->numRects * sizeof(pixman_box16_t)); : return TRUE; 1 0.0011 :} : :/*====================================================================== : * Generic Region Operator : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * pixman_coalesce -- : * Attempt to merge the boxes in the current band with those in the : * previous one. We are guaranteed that the current band extends to : * the end of the rects array. Used only by pixman_op. : * : * Results: : * The new index for the previous band. : * : * Side Effects: : * If coalescing takes place: : * - rectangles in the previous band will have their y2 fields : * altered. : * - region->data->numRects will be decreased. : * : *----------------------------------------------------------------------- : */ :static inline int :pixman_coalesce ( : pixman_region16_t * region, /* Region to coalesce */ : int prevStart, /* Index of start of previous band */ : int curStart) /* Index of start of current band */ :{ : pixman_box16_t * pPrevBox; /* Current box in previous band */ : pixman_box16_t * pCurBox; /* Current box in current band */ : int numRects; /* Number rectangles in both bands */ : int y2; /* Bottom of current band */ : /* : * Figure out how many rectangles are in the band. : */ : numRects = curStart - prevStart; : assert(numRects == region->data->numRects - curStart); : : if (!numRects) return curStart; : : /* : * The bands may only be coalesced if the bottom of the previous : * matches the top scanline of the current. : */ : pPrevBox = PIXREGION_BOX(region, prevStart); : pCurBox = PIXREGION_BOX(region, curStart); : if (pPrevBox->y2 != pCurBox->y1) return curStart; : : /* : * Make sure the bands have boxes in the same places. This : * assumes that boxes have been added in such a way that they : * cover the most area possible. I.e. two boxes in a band must : * have some horizontal space between them. : */ : y2 = pCurBox->y2; : : do { : if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) { : return (curStart); : } : pPrevBox++; : pCurBox++; : numRects--; : } while (numRects); : : /* : * The bands may be merged, so set the bottom y of each box : * in the previous band to the bottom y of the current band. : */ : numRects = curStart - prevStart; : region->data->numRects -= numRects; : do { : pPrevBox--; : pPrevBox->y2 = y2; : numRects--; : } while (numRects); : return prevStart; :} : :/* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */ : :#define Coalesce(newReg, prevBand, curBand) \ : if (curBand - prevBand == newReg->data->numRects - curBand) { \ : prevBand = pixman_coalesce(newReg, prevBand, curBand); \ : } else { \ : prevBand = curBand; \ : } : :/*- : *----------------------------------------------------------------------- : * pixman_region_appendNonO -- : * Handle a non-overlapping band for the union and subtract operations. : * Just adds the (top/bottom-clipped) rectangles into the region. : * Doesn't have to check for subsumption or anything. : * : * Results: : * None. : * : * Side Effects: : * region->data->numRects is incremented and the rectangles overwritten : * with the rectangles we're passed. : * : *----------------------------------------------------------------------- : */ : :static inline pixman_bool_t :pixman_region_appendNonO ( : pixman_region16_t * region, : pixman_box16_t * r, : pixman_box16_t * rEnd, : int y1, : int y2) :{ : pixman_box16_t * pNextRect; : int newRects; : : newRects = rEnd - r; : : assert(y1 < y2); : assert(newRects != 0); : : /* Make sure we have enough space for all rectangles to be added */ : RECTALLOC(region, newRects); : pNextRect = PIXREGION_TOP(region); : region->data->numRects += newRects; : do { : assert(r->x1 < r->x2); : ADDRECT(pNextRect, r->x1, y1, r->x2, y2); : r++; : } while (r != rEnd); : : return TRUE; :} : :#define FindBand(r, rBandEnd, rEnd, ry1) \ :{ \ : ry1 = r->y1; \ : rBandEnd = r+1; \ : while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \ : rBandEnd++; \ : } \ :} : :#define AppendRegions(newReg, r, rEnd) \ :{ \ : int newRects; \ : if ((newRects = rEnd - r)) { \ : RECTALLOC(newReg, newRects); \ : memmove((char *)PIXREGION_TOP(newReg),(char *)r, \ : newRects * sizeof(pixman_box16_t)); \ : newReg->data->numRects += newRects; \ : } \ :} : :/*- : *----------------------------------------------------------------------- : * pixman_op -- : * Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse, : * pixman_region_subtract, pixman_region_intersect.... Both regions MUST have at least one : * rectangle, and cannot be the same object. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * The new region is overwritten. : * pOverlap set to TRUE if overlapFunc ever returns TRUE. : * : * Notes: : * The idea behind this function is to view the two regions as sets. : * Together they cover a rectangle of area that this function divides : * into horizontal bands where points are covered only by one region : * or by both. For the first case, the nonOverlapFunc is called with : * each the band and the band's upper and lower extents. For the : * second, the overlapFunc is called to process the entire band. It : * is responsible for clipping the rectangles in the band, though : * this function provides the boundaries. : * At the end of each band, the new region is coalesced, if possible, : * to reduce the number of rectangles in the region. : * : *----------------------------------------------------------------------- : */ : :typedef pixman_bool_t (*OverlapProcPtr)( : pixman_region16_t *region, : pixman_box16_t *r1, : pixman_box16_t *r1End, : pixman_box16_t *r2, : pixman_box16_t *r2End, : short y1, : short y2, : int *pOverlap); : :static pixman_bool_t :pixman_op( : pixman_region16_t *newReg, /* Place to store result */ : pixman_region16_t * reg1, /* First region in operation */ : pixman_region16_t * reg2, /* 2d region in operation */ : OverlapProcPtr overlapFunc, /* Function to call for over- : * lapping bands */ : int appendNon1, /* Append non-overlapping bands */ : /* in region 1 ? */ : int appendNon2, /* Append non-overlapping bands */ : /* in region 2 ? */ : int *pOverlap) 7 0.0076 :{ /* pixman_op total: 146 0.1591 */ : pixman_box16_t * r1; /* Pointer into first region */ : pixman_box16_t * r2; /* Pointer into 2d region */ : pixman_box16_t * r1End; /* End of 1st region */ : pixman_box16_t * r2End; /* End of 2d region */ : short ybot; /* Bottom of intersection */ : short ytop; /* Top of intersection */ : pixman_region16_data_t * oldData; /* Old data for newReg */ : int prevBand; /* Index of start of : * previous band in newReg */ : int curBand; /* Index of start of current : * band in newReg */ : pixman_box16_t * r1BandEnd; /* End of current band in r1 */ : pixman_box16_t * r2BandEnd; /* End of current band in r2 */ : short top; /* Top of non-overlapping band */ : short bot; /* Bottom of non-overlapping band*/ : int r1y1; /* Temps for r1->y1 and r2->y1 */ : int r2y1; : int newSize; : int numRects; : : /* : * Break any region computed from a broken region : */ 3 0.0033 : if (PIXREGION_NAR (reg1) || PIXREGION_NAR(reg2)) : return pixman_break (newReg); : : /* : * Initialization: : * set r1, r2, r1End and r2End appropriately, save the rectangles : * of the destination region until the end in case it's one of : * the two source regions, then mark the "new" region empty, allocating : * another array of rectangles for it to use. : */ : 3 0.0033 : r1 = PIXREGION_RECTS(reg1); 2 0.0022 : newSize = PIXREGION_NUM_RECTS(reg1); : r1End = r1 + newSize; 4 0.0044 : numRects = PIXREGION_NUM_RECTS(reg2); 1 0.0011 : r2 = PIXREGION_RECTS(reg2); : r2End = r2 + numRects; : assert(r1 != r1End); : assert(r2 != r2End); : : oldData = (pixman_region16_data_t *)NULL; 1 0.0011 : if (((newReg == reg1) && (newSize > 1)) || : ((newReg == reg2) && (numRects > 1))) : { 1 0.0011 : oldData = newReg->data; 1 0.0011 : newReg->data = pixman_region_emptyData; : } : /* guess at new size */ : if (numRects > newSize) : newSize = numRects; : newSize <<= 1; 1 0.0011 : if (!newReg->data) 2 0.0022 : newReg->data = pixman_region_emptyData; : else if (newReg->data->size) : newReg->data->numRects = 0; : if (newSize > newReg->data->size) { : if (!pixman_rect_alloc(newReg, newSize)) { : if (oldData) : free (oldData); : return FALSE; : } : } : : /* : * Initialize ybot. : * In the upcoming loop, ybot and ytop serve different functions depending : * on whether the band being handled is an overlapping or non-overlapping : * band. : * In the case of a non-overlapping band (only one of the regions : * has points in the band), ybot is the bottom of the most recent : * intersection and thus clips the top of the rectangles in that band. : * ytop is the top of the next intersection between the two regions and : * serves to clip the bottom of the rectangles in the current band. : * For an overlapping band (where the two regions intersect), ytop clips : * the top of the rectangles of both regions and ybot clips the bottoms. : */ : 2 0.0022 : ybot = MIN(r1->y1, r2->y1); : : /* : * prevBand serves to mark the start of the previous band so rectangles : * can be coalesced into larger rectangles. qv. pixman_coalesce, above. : * In the beginning, there is no previous band, so prevBand == curBand : * (curBand is set later on, of course, but the first band will always : * start at index 0). prevBand and curBand must be indices because of : * the possible expansion, and resultant moving, of the new region's : * array of rectangles. : */ : prevBand = 0; : : do { : /* : * This algorithm proceeds one source-band (as opposed to a : * destination band, which is determined by where the two regions : * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the : * rectangle after the last one in the current band for their : * respective regions. : */ : assert(r1 != r1End); : assert(r2 != r2End); : 2 0.0022 : FindBand(r1, r1BandEnd, r1End, r1y1); 9 0.0098 : FindBand(r2, r2BandEnd, r2End, r2y1); : : /* : * First handle the band that doesn't intersect, if any. : * : * Note that attention is restricted to one band in the : * non-intersecting region at once, so if a region has n : * bands between the current position and the next place it overlaps : * the other, this entire loop will be passed through n times. : */ 3 0.0033 : if (r1y1 < r2y1) { : if (appendNon1) { : top = MAX(r1y1, ybot); : bot = MIN(r1->y2, r2y1); : if (top != bot) { : curBand = newReg->data->numRects; : pixman_region_appendNonO(newReg, r1, r1BandEnd, top, bot); : Coalesce(newReg, prevBand, curBand); : } : } : ytop = r2y1; : } else if (r2y1 < r1y1) { 1 0.0011 : if (appendNon2) { 1 0.0011 : top = MAX(r2y1, ybot); : bot = MIN(r2->y2, r1y1); : if (top != bot) { : curBand = newReg->data->numRects; : pixman_region_appendNonO(newReg, r2, r2BandEnd, top, bot); : Coalesce(newReg, prevBand, curBand); : } : } : ytop = r1y1; : } else { : ytop = r1y1; : } : : /* : * Now see if we've hit an intersecting band. The two bands only : * intersect if ybot > ytop : */ 2 0.0022 : ybot = MIN(r1->y2, r2->y2); 6 0.0065 : if (ybot > ytop) { 4 0.0044 : curBand = newReg->data->numRects; 4 0.0044 : (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot, : pOverlap); 9 0.0098 : Coalesce(newReg, prevBand, curBand); : } : : /* : * If we've finished with a band (y2 == ybot) we skip forward : * in the region to the next band. : */ 1 0.0011 : if (r1->y2 == ybot) r1 = r1BandEnd; 3 0.0033 : if (r2->y2 == ybot) r2 = r2BandEnd; : 5 0.0054 : } while (r1 != r1End && r2 != r2End); : : /* : * Deal with whichever region (if any) still has rectangles left. : * : * We only need to worry about banding and coalescing for the very first : * band left. After that, we can just group all remaining boxes, : * regardless of how many bands, into one final append to the list. : */ : : if ((r1 != r1End) && appendNon1) { : /* Do first nonOverlap1Func call, which may be able to coalesce */ 1 0.0011 : FindBand(r1, r1BandEnd, r1End, r1y1); : curBand = newReg->data->numRects; 2 0.0022 : pixman_region_appendNonO(newReg, r1, r1BandEnd, MAX(r1y1, ybot), r1->y2); 3 0.0033 : Coalesce(newReg, prevBand, curBand); : /* Just append the rest of the boxes */ 1 0.0011 : AppendRegions(newReg, r1BandEnd, r1End); : : } else if ((r2 != r2End) && appendNon2) { : /* Do first nonOverlap2Func call, which may be able to coalesce */ : FindBand(r2, r2BandEnd, r2End, r2y1); : curBand = newReg->data->numRects; : pixman_region_appendNonO(newReg, r2, r2BandEnd, MAX(r2y1, ybot), r2->y2); : Coalesce(newReg, prevBand, curBand); : /* Append rest of boxes */ 7 0.0076 : AppendRegions(newReg, r2BandEnd, r2End); : } : 2 0.0022 : if (oldData) : free(oldData); : 8 0.0087 : if (!(numRects = newReg->data->numRects)) : { : freeData(newReg); : newReg->data = pixman_region_emptyData; : } 1 0.0011 : else if (numRects == 1) : { : newReg->extents = *PIXREGION_BOXPTR(newReg); : freeData(newReg); : newReg->data = (pixman_region16_data_t *)NULL; : } : else : { 1 0.0011 : DOWNSIZE(newReg, numRects); : } : : return TRUE; :} : :/*- : *----------------------------------------------------------------------- : * pixman_set_extents -- : * Reset the extents of a region to what they should be. Called by : * pixman_region_subtract and pixman_region_intersect as they can't figure it out along the : * way or do so easily, as pixman_region_union can. : * : * Results: : * None. : * : * Side Effects: : * The region's 'extents' structure is overwritten. : * : *----------------------------------------------------------------------- : */ :static void :pixman_set_extents (pixman_region16_t *region) :{ : pixman_box16_t *box, *boxEnd; : : if (!region->data) : return; : if (!region->data->size) : { : region->extents.x2 = region->extents.x1; : region->extents.y2 = region->extents.y1; : return; : } : : box = PIXREGION_BOXPTR(region); : boxEnd = PIXREGION_END(region); : : /* : * Since box is the first rectangle in the region, it must have the : * smallest y1 and since boxEnd is the last rectangle in the region, : * it must have the largest y2, because of banding. Initialize x1 and : * x2 from box and boxEnd, resp., as good things to initialize them : * to... : */ : region->extents.x1 = box->x1; : region->extents.y1 = box->y1; : region->extents.x2 = boxEnd->x2; : region->extents.y2 = boxEnd->y2; : : assert(region->extents.y1 < region->extents.y2); : while (box <= boxEnd) { : if (box->x1 < region->extents.x1) : region->extents.x1 = box->x1; : if (box->x2 > region->extents.x2) : region->extents.x2 = box->x2; : box++; : }; : : assert(region->extents.x1 < region->extents.x2); :} : :/*====================================================================== : * Region Intersection : *====================================================================*/ :/*- : *----------------------------------------------------------------------- : * pixman_region_intersectO -- : * Handle an overlapping band for pixman_region_intersect. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * Rectangles may be added to the region. : * : *----------------------------------------------------------------------- : */ :/*ARGSUSED*/ :static pixman_bool_t :pixman_region_intersectO (pixman_region16_t *region, : pixman_box16_t *r1, : pixman_box16_t *r1End, : pixman_box16_t *r2, : pixman_box16_t *r2End, : short y1, : short y2, : int *pOverlap) :{ : int x1; : int x2; : pixman_box16_t * pNextRect; : : pNextRect = PIXREGION_TOP(region); : : assert(y1 < y2); : assert(r1 != r1End && r2 != r2End); : : do { : x1 = MAX(r1->x1, r2->x1); : x2 = MIN(r1->x2, r2->x2); : : /* : * If there's any overlap between the two rectangles, add that : * overlap to the new region. : */ : if (x1 < x2) : NEWRECT(region, pNextRect, x1, y1, x2, y2); : : /* : * Advance the pointer(s) with the leftmost right side, since the next : * rectangle on that list may still overlap the other region's : * current rectangle. : */ : if (r1->x2 == x2) { : r1++; : } : if (r2->x2 == x2) { : r2++; : } : } while ((r1 != r1End) && (r2 != r2End)); : : return TRUE; :} : :pixman_bool_t :pixman_region_intersect (pixman_region16_t * newReg, : pixman_region16_t * reg1, : pixman_region16_t * reg2) 4 0.0044 :{ /* pixman_region_intersect total: 13 0.0142 */ : good(reg1); : good(reg2); : good(newReg); : /* check for trivial reject */ 4 0.0044 : if (PIXREGION_NIL(reg1) || PIXREGION_NIL(reg2) || : !EXTENTCHECK(®1->extents, ®2->extents)) : { : /* Covers about 20% of all cases */ : freeData(newReg); : newReg->extents.x2 = newReg->extents.x1; : newReg->extents.y2 = newReg->extents.y1; : if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2)) : { : newReg->data = pixman_brokendata; : return FALSE; : } : else : newReg->data = pixman_region_emptyData; : } : else if (!reg1->data && !reg2->data) : { : /* Covers about 80% of cases that aren't trivially rejected */ 1 0.0011 : newReg->extents.x1 = MAX(reg1->extents.x1, reg2->extents.x1); 1 0.0011 : newReg->extents.y1 = MAX(reg1->extents.y1, reg2->extents.y1); 1 0.0011 : newReg->extents.x2 = MIN(reg1->extents.x2, reg2->extents.x2); : newReg->extents.y2 = MIN(reg1->extents.y2, reg2->extents.y2); : freeData(newReg); : newReg->data = (pixman_region16_data_t *)NULL; : } : else if (!reg2->data && SUBSUMES(®2->extents, ®1->extents)) : { : return pixman_region_copy(newReg, reg1); : } : else if (!reg1->data && SUBSUMES(®1->extents, ®2->extents)) : { : return pixman_region_copy(newReg, reg2); : } : else if (reg1 == reg2) : { : return pixman_region_copy(newReg, reg1); : } : else : { : /* General purpose intersection */ : int overlap; /* result ignored */ : if (!pixman_op(newReg, reg1, reg2, pixman_region_intersectO, FALSE, FALSE, : &overlap)) : return FALSE; : pixman_set_extents(newReg); : } : : good(newReg); : return(TRUE); 2 0.0022 :} : :#define MERGERECT(r) \ :{ \ : if (r->x1 <= x2) { \ : /* Merge with current rectangle */ \ : if (r->x1 < x2) *pOverlap = TRUE; \ : if (x2 < r->x2) x2 = r->x2; \ : } else { \ : /* Add current rectangle, start new one */ \ : NEWRECT(region, pNextRect, x1, y1, x2, y2); \ : x1 = r->x1; \ : x2 = r->x2; \ : } \ : r++; \ :} : :/*====================================================================== : * Region Union : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * pixman_region_unionO -- : * Handle an overlapping band for the union operation. Picks the : * left-most rectangle each time and merges it into the region. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * region is overwritten. : * pOverlap is set to TRUE if any boxes overlap. : * : *----------------------------------------------------------------------- : */ :static pixman_bool_t :pixman_region_unionO ( : pixman_region16_t *region, : pixman_box16_t *r1, : pixman_box16_t *r1End, : pixman_box16_t *r2, : pixman_box16_t *r2End, : short y1, : short y2, : int *pOverlap) 11 0.0120 :{ /* pixman_region_unionO total: 39 0.0425 */ : pixman_box16_t * pNextRect; : int x1; /* left and right side of current union */ : int x2; : : assert (y1 < y2); : assert(r1 != r1End && r2 != r2End); : 6 0.0065 : pNextRect = PIXREGION_TOP(region); : : /* Start off current rectangle */ : if (r1->x1 < r2->x1) : { : x1 = r1->x1; : x2 = r1->x2; : r1++; : } : else : { 1 0.0011 : x1 = r2->x1; 2 0.0022 : x2 = r2->x2; : r2++; : } 3 0.0033 : while (r1 != r1End && r2 != r2End) : { : if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2); : } : : /* Finish off whoever (if any) is left */ : if (r1 != r1End) : { : do : { 8 0.0087 : MERGERECT(r1); 2 0.0022 : } while (r1 != r1End); : } : else if (r2 != r2End) : { : do : { : MERGERECT(r2); : } while (r2 != r2End); : } : : /* Add current rectangle */ 4 0.0044 : NEWRECT(region, pNextRect, x1, y1, x2, y2); : : return TRUE; 2 0.0022 :} : :/* Convenience function for performing union of region with a : * single rectangle : */ :pixman_bool_t :pixman_region_union_rect (pixman_region16_t *dest, : pixman_region16_t *source, : int x, int y, : unsigned int width, unsigned int height) :{ : pixman_region16_t region; : : if (!width || !height) : return pixman_region_copy (dest, source); : region.data = NULL; : region.extents.x1 = x; : region.extents.y1 = y; : region.extents.x2 = x + width; : region.extents.y2 = y + height; : : return pixman_region_union (dest, source, ®ion); :} : :pixman_bool_t :pixman_region_union (pixman_region16_t *newReg, : pixman_region16_t *reg1, : pixman_region16_t *reg2) 17 0.0185 :{ /* pixman_region_union total: 87 0.0948 */ : int overlap; /* result ignored */ : : /* Return TRUE if some overlap : * between reg1, reg2 : */ : good(reg1); : good(reg2); : good(newReg); : /* checks all the simple cases */ : : /* : * Region 1 and 2 are the same : */ : if (reg1 == reg2) : { : return pixman_region_copy(newReg, reg1); : } : : /* : * Region 1 is empty : */ 7 0.0076 : if (PIXREGION_NIL(reg1)) : { : if (PIXREGION_NAR(reg1)) : return pixman_break (newReg); 1 0.0011 : if (newReg != reg2) 1 0.0011 : return pixman_region_copy(newReg, reg2); : return TRUE; : } : : /* : * Region 2 is empty : */ 9 0.0098 : if (PIXREGION_NIL(reg2)) : { : if (PIXREGION_NAR(reg2)) : return pixman_break (newReg); : if (newReg != reg1) : return pixman_region_copy(newReg, reg1); : return TRUE; : } : : /* : * Region 1 completely subsumes region 2 : */ 8 0.0087 : if (!reg1->data && SUBSUMES(®1->extents, ®2->extents)) : { 7 0.0076 : if (newReg != reg1) : return pixman_region_copy(newReg, reg1); : return TRUE; : } : : /* : * Region 2 completely subsumes region 1 : */ 2 0.0022 : if (!reg2->data && SUBSUMES(®2->extents, ®1->extents)) : { : if (newReg != reg2) 1 0.0011 : return pixman_region_copy(newReg, reg2); : return TRUE; : } : 3 0.0033 : if (!pixman_op(newReg, reg1, reg2, pixman_region_unionO, TRUE, TRUE, &overlap)) : return FALSE; : 1 0.0011 : newReg->extents.x1 = MIN(reg1->extents.x1, reg2->extents.x1); 3 0.0033 : newReg->extents.y1 = MIN(reg1->extents.y1, reg2->extents.y1); 7 0.0076 : newReg->extents.x2 = MAX(reg1->extents.x2, reg2->extents.x2); 8 0.0087 : newReg->extents.y2 = MAX(reg1->extents.y2, reg2->extents.y2); : good(newReg); 5 0.0054 : return TRUE; 7 0.0076 :} : :/*====================================================================== : * Batch Rectangle Union : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * pixman_region_append -- : * : * "Append" the rgn rectangles onto the end of dstrgn, maintaining : * knowledge of YX-banding when it's easy. Otherwise, dstrgn just : * becomes a non-y-x-banded random collection of rectangles, and not : * yet a true region. After a sequence of appends, the caller must : * call pixman_region_validate to ensure that a valid region is : * constructed. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * dstrgn is modified if rgn has rectangles. : * : */ :pixman_bool_t :pixman_region_append (pixman_region16_t * dstrgn, : pixman_region16_t * rgn) :{ : int numRects, dnumRects, size; : pixman_box16_t *new, *old; : int prepend; : : if (PIXREGION_NAR(rgn)) : return pixman_break (dstrgn); : : if (!rgn->data && (dstrgn->data == pixman_region_emptyData)) : { : dstrgn->extents = rgn->extents; : dstrgn->data = (pixman_region16_data_t *)NULL; : return TRUE; : } : : numRects = PIXREGION_NUM_RECTS(rgn); : if (!numRects) : return TRUE; : prepend = FALSE; : size = numRects; : dnumRects = PIXREGION_NUM_RECTS(dstrgn); : if (!dnumRects && (size < 200)) : size = 200; /* XXX pick numbers out of a hat */ : RECTALLOC(dstrgn, size); : old = PIXREGION_RECTS(rgn); : if (!dnumRects) : dstrgn->extents = rgn->extents; : else if (dstrgn->extents.x2 > dstrgn->extents.x1) : { : pixman_box16_t *first, *last; : : first = old; : last = PIXREGION_BOXPTR(dstrgn) + (dnumRects - 1); : if ((first->y1 > last->y2) || : ((first->y1 == last->y1) && (first->y2 == last->y2) && : (first->x1 > last->x2))) : { : if (rgn->extents.x1 < dstrgn->extents.x1) : dstrgn->extents.x1 = rgn->extents.x1; : if (rgn->extents.x2 > dstrgn->extents.x2) : dstrgn->extents.x2 = rgn->extents.x2; : dstrgn->extents.y2 = rgn->extents.y2; : } : else : { : first = PIXREGION_BOXPTR(dstrgn); : last = old + (numRects - 1); : if ((first->y1 > last->y2) || : ((first->y1 == last->y1) && (first->y2 == last->y2) && : (first->x1 > last->x2))) : { : prepend = TRUE; : if (rgn->extents.x1 < dstrgn->extents.x1) : dstrgn->extents.x1 = rgn->extents.x1; : if (rgn->extents.x2 > dstrgn->extents.x2) : dstrgn->extents.x2 = rgn->extents.x2; : dstrgn->extents.y1 = rgn->extents.y1; : } : else : dstrgn->extents.x2 = dstrgn->extents.x1; : } : } : if (prepend) : { : new = PIXREGION_BOX(dstrgn, numRects); : if (dnumRects == 1) : *new = *PIXREGION_BOXPTR(dstrgn); : else : memmove((char *)new,(char *)PIXREGION_BOXPTR(dstrgn), : dnumRects * sizeof(pixman_box16_t)); : new = PIXREGION_BOXPTR(dstrgn); : } : else : new = PIXREGION_BOXPTR(dstrgn) + dnumRects; : if (numRects == 1) : *new = *old; : else : memmove((char *)new, (char *)old, numRects * sizeof(pixman_box16_t)); : dstrgn->data->numRects += numRects; : return TRUE; :} : :#define ExchangeRects(a, b) \ :{ \ : pixman_box16_t t; \ : t = rects[a]; \ : rects[a] = rects[b]; \ : rects[b] = t; \ :} : :static void :QuickSortRects( : pixman_box16_t rects[], : int numRects) :{ : int y1; : int x1; : int i, j; : pixman_box16_t *r; : : /* Always called with numRects > 1 */ : : do : { : if (numRects == 2) : { : if (rects[0].y1 > rects[1].y1 || : (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1)) : ExchangeRects(0, 1); : return; : } : : /* Choose partition element, stick in location 0 */ : ExchangeRects(0, numRects >> 1); : y1 = rects[0].y1; : x1 = rects[0].x1; : : /* Partition array */ : i = 0; : j = numRects; : do : { : r = &(rects[i]); : do : { : r++; : i++; : } while (i != numRects && : (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1))); : r = &(rects[j]); : do : { : r--; : j--; : } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1)); : if (i < j) : ExchangeRects(i, j); : } while (i < j); : : /* Move partition element back to middle */ : ExchangeRects(0, j); : : /* Recurse */ : if (numRects-j-1 > 1) : QuickSortRects(&rects[j+1], numRects-j-1); : numRects = j; : } while (numRects > 1); :} : :/*- : *----------------------------------------------------------------------- : * pixman_region_validate -- : * : * Take a ``region'' which is a non-y-x-banded random collection of : * rectangles, and compute a nice region which is the union of all the : * rectangles. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * The passed-in ``region'' may be modified. : * pOverlap set to TRUE if any retangles overlapped, : * else FALSE; : * : * Strategy: : * Step 1. Sort the rectangles into ascending order with primary key y1 : * and secondary key x1. : * : * Step 2. Split the rectangles into the minimum number of proper y-x : * banded regions. This may require horizontally merging : * rectangles, and vertically coalescing bands. With any luck, : * this step in an identity transformation (ala the Box widget), : * or a coalescing into 1 box (ala Menus). : * : * Step 3. Merge the separate regions down to a single region by calling : * pixman_region_union. Maximize the work each pixman_region_union call does by using : * a binary merge. : * : *----------------------------------------------------------------------- : */ : :pixman_bool_t :pixman_region_validate(pixman_region16_t * badreg, : int *pOverlap) :{ : /* Descriptor for regions under construction in Step 2. */ : typedef struct { : pixman_region16_t reg; : int prevBand; : int curBand; : } RegionInfo; : : int numRects; /* Original numRects for badreg */ : RegionInfo *ri; /* Array of current regions */ : int numRI; /* Number of entries used in ri */ : int sizeRI; /* Number of entries available in ri */ : int i; /* Index into rects */ : int j; /* Index into ri */ : RegionInfo *rit; /* &ri[j] */ : pixman_region16_t * reg; /* ri[j].reg */ : pixman_box16_t * box; /* Current box in rects */ : pixman_box16_t * riBox; /* Last box in ri[j].reg */ : pixman_region16_t * hreg; /* ri[j_half].reg */ : pixman_bool_t ret = TRUE; : : *pOverlap = FALSE; : if (!badreg->data) : { : good(badreg); : return TRUE; : } : numRects = badreg->data->numRects; : if (!numRects) : { : if (PIXREGION_NAR(badreg)) : return FALSE; : good(badreg); : return TRUE; : } : if (badreg->extents.x1 < badreg->extents.x2) : { : if ((numRects) == 1) : { : freeData(badreg); : badreg->data = (pixman_region16_data_t *) NULL; : } : else : { : DOWNSIZE(badreg, numRects); : } : good(badreg); : return TRUE; : } : : /* Step 1: Sort the rects array into ascending (y1, x1) order */ : QuickSortRects(PIXREGION_BOXPTR(badreg), numRects); : : /* Step 2: Scatter the sorted array into the minimum number of regions */ : : /* Set up the first region to be the first rectangle in badreg */ : /* Note that step 2 code will never overflow the ri[0].reg rects array */ : ri = (RegionInfo *) malloc(4 * sizeof(RegionInfo)); : if (!ri) : return pixman_break (badreg); : sizeRI = 4; : numRI = 1; : ri[0].prevBand = 0; : ri[0].curBand = 0; : ri[0].reg = *badreg; : box = PIXREGION_BOXPTR(&ri[0].reg); : ri[0].reg.extents = *box; : ri[0].reg.data->numRects = 1; : : /* Now scatter rectangles into the minimum set of valid regions. If the : next rectangle to be added to a region would force an existing rectangle : in the region to be split up in order to maintain y-x banding, just : forget it. Try the next region. If it doesn't fit cleanly into any : region, make a new one. */ : : for (i = numRects; --i > 0;) : { : box++; : /* Look for a region to append box to */ : for (j = numRI, rit = ri; --j >= 0; rit++) : { : reg = &rit->reg; : riBox = PIXREGION_END(reg); : : if (box->y1 == riBox->y1 && box->y2 == riBox->y2) : { : /* box is in same band as riBox. Merge or append it */ : if (box->x1 <= riBox->x2) : { : /* Merge it with riBox */ : if (box->x1 < riBox->x2) *pOverlap = TRUE; : if (box->x2 > riBox->x2) riBox->x2 = box->x2; : } : else : { : RECTALLOC_BAIL(reg, 1, bail); : *PIXREGION_TOP(reg) = *box; : reg->data->numRects++; : } : goto NextRect; /* So sue me */ : } : else if (box->y1 >= riBox->y2) : { : /* Put box into new band */ : if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; : if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1; : Coalesce(reg, rit->prevBand, rit->curBand); : rit->curBand = reg->data->numRects; : RECTALLOC_BAIL(reg, 1, bail); : *PIXREGION_TOP(reg) = *box; : reg->data->numRects++; : goto NextRect; : } : /* Well, this region was inappropriate. Try the next one. */ : } /* for j */ : : /* Uh-oh. No regions were appropriate. Create a new one. */ : if (sizeRI == numRI) : { : /* Oops, allocate space for new region information */ : sizeRI <<= 1; : rit = (RegionInfo *) realloc(ri, sizeRI * sizeof(RegionInfo)); : if (!rit) : goto bail; : ri = rit; : rit = &ri[numRI]; : } : numRI++; : rit->prevBand = 0; : rit->curBand = 0; : rit->reg.extents = *box; : rit->reg.data = (pixman_region16_data_t *)NULL; : if (!pixman_rect_alloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */ : goto bail; :NextRect: ; : } /* for i */ : : /* Make a final pass over each region in order to Coalesce and set : extents.x2 and extents.y2 */ : : for (j = numRI, rit = ri; --j >= 0; rit++) : { : reg = &rit->reg; : riBox = PIXREGION_END(reg); : reg->extents.y2 = riBox->y2; : if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; : Coalesce(reg, rit->prevBand, rit->curBand); : if (reg->data->numRects == 1) /* keep unions happy below */ : { : freeData(reg); : reg->data = (pixman_region16_data_t *)NULL; : } : } : : /* Step 3: Union all regions into a single region */ : while (numRI > 1) : { : int half = numRI/2; : for (j = numRI & 1; j < (half + (numRI & 1)); j++) : { : reg = &ri[j].reg; : hreg = &ri[j+half].reg; : if (!pixman_op(reg, reg, hreg, pixman_region_unionO, TRUE, TRUE, pOverlap)) : ret = FALSE; : if (hreg->extents.x1 < reg->extents.x1) : reg->extents.x1 = hreg->extents.x1; : if (hreg->extents.y1 < reg->extents.y1) : reg->extents.y1 = hreg->extents.y1; : if (hreg->extents.x2 > reg->extents.x2) : reg->extents.x2 = hreg->extents.x2; : if (hreg->extents.y2 > reg->extents.y2) : reg->extents.y2 = hreg->extents.y2; : freeData(hreg); : } : numRI -= half; : } : *badreg = ri[0].reg; : free(ri); : good(badreg); : return ret; :bail: : for (i = 0; i < numRI; i++) : freeData(&ri[i].reg); : free (ri); : return pixman_break (badreg); :} : :/*====================================================================== : * Region Subtraction : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * pixman_region_subtractO -- : * Overlapping band subtraction. x1 is the left-most point not yet : * checked. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * region may have rectangles added to it. : * : *----------------------------------------------------------------------- : */ :/*ARGSUSED*/ :static pixman_bool_t :pixman_region_subtractO ( : pixman_region16_t * region, : pixman_box16_t * r1, : pixman_box16_t * r1End, : pixman_box16_t * r2, : pixman_box16_t * r2End, : short y1, : short y2, : int *pOverlap) :{ : pixman_box16_t * pNextRect; : int x1; : : x1 = r1->x1; : : assert(y1x2 <= x1) : { : /* : * Subtrahend entirely to left of minuend: go to next subtrahend. : */ : r2++; : } : else if (r2->x1 <= x1) : { : /* : * Subtrahend preceeds minuend: nuke left edge of minuend. : */ : x1 = r2->x2; : if (x1 >= r1->x2) : { : /* : * Minuend completely covered: advance to next minuend and : * reset left fence to edge of new minuend. : */ : r1++; : if (r1 != r1End) : x1 = r1->x1; : } : else : { : /* : * Subtrahend now used up since it doesn't extend beyond : * minuend : */ : r2++; : } : } : else if (r2->x1 < r1->x2) : { : /* : * Left part of subtrahend covers part of minuend: add uncovered : * part of minuend to region and skip to next subtrahend. : */ : assert(x1x1); : NEWRECT(region, pNextRect, x1, y1, r2->x1, y2); : : x1 = r2->x2; : if (x1 >= r1->x2) : { : /* : * Minuend used up: advance to new... : */ : r1++; : if (r1 != r1End) : x1 = r1->x1; : } : else : { : /* : * Subtrahend used up : */ : r2++; : } : } : else : { : /* : * Minuend used up: add any remaining piece before advancing. : */ : if (r1->x2 > x1) : NEWRECT(region, pNextRect, x1, y1, r1->x2, y2); : r1++; : if (r1 != r1End) : x1 = r1->x1; : } : } while ((r1 != r1End) && (r2 != r2End)); : : /* : * Add remaining minuend rectangles to region. : */ : while (r1 != r1End) : { : assert(x1x2); : NEWRECT(region, pNextRect, x1, y1, r1->x2, y2); : r1++; : if (r1 != r1End) : x1 = r1->x1; : } : return TRUE; :} : :/*- : *----------------------------------------------------------------------- : * pixman_region_subtract -- : * Subtract regS from regM and leave the result in regD. : * S stands for subtrahend, M for minuend and D for difference. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * regD is overwritten. : * : *----------------------------------------------------------------------- : */ :pixman_bool_t :pixman_region_subtract(pixman_region16_t * regD, : pixman_region16_t * regM, : pixman_region16_t * regS) :{ : int overlap; /* result ignored */ : : good(regM); : good(regS); : good(regD); : /* check for trivial rejects */ : if (PIXREGION_NIL(regM) || PIXREGION_NIL(regS) || : !EXTENTCHECK(®M->extents, ®S->extents)) : { : if (PIXREGION_NAR (regS)) : return pixman_break (regD); : return pixman_region_copy(regD, regM); : } : else if (regM == regS) : { : freeData(regD); : regD->extents.x2 = regD->extents.x1; : regD->extents.y2 = regD->extents.y1; : regD->data = pixman_region_emptyData; : return TRUE; : } : : /* Add those rectangles in region 1 that aren't in region 2, : do yucky substraction for overlaps, and : just throw away rectangles in region 2 that aren't in region 1 */ : if (!pixman_op(regD, regM, regS, pixman_region_subtractO, TRUE, FALSE, &overlap)) : return FALSE; : : /* : * Can't alter RegD's extents before we call pixman_op because : * it might be one of the source regions and pixman_op depends : * on the extents of those regions being unaltered. Besides, this : * way there's no checking against rectangles that will be nuked : * due to coalescing, so we have to examine fewer rectangles. : */ : pixman_set_extents(regD); : good(regD); : return TRUE; :} : :/*====================================================================== : * Region Inversion : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * pixman_region_inverse -- : * Take a region and a box and return a region that is everything : * in the box but not in the region. The careful reader will note : * that this is the same as subtracting the region from the box... : * : * Results: : * TRUE. : * : * Side Effects: : * newReg is overwritten. : * : *----------------------------------------------------------------------- : */ :pixman_bool_t :pixman_region_inverse(pixman_region16_t * newReg, /* Destination region */ : pixman_region16_t * reg1, /* Region to invert */ : pixman_box16_t * invRect) /* Bounding box for inversion */ :{ : pixman_region16_t invReg; /* Quick and dirty region made from the : * bounding box */ : int overlap; /* result ignored */ : : good(reg1); : good(newReg); : /* check for trivial rejects */ : if (PIXREGION_NIL(reg1) || !EXTENTCHECK(invRect, ®1->extents)) : { : if (PIXREGION_NAR(reg1)) : return pixman_break (newReg); : newReg->extents = *invRect; : freeData(newReg); : newReg->data = (pixman_region16_data_t *)NULL; : return TRUE; : } : : /* Add those rectangles in region 1 that aren't in region 2, : do yucky substraction for overlaps, and : just throw away rectangles in region 2 that aren't in region 1 */ : invReg.extents = *invRect; : invReg.data = (pixman_region16_data_t *)NULL; : if (!pixman_op(newReg, &invReg, reg1, pixman_region_subtractO, TRUE, FALSE, &overlap)) : return FALSE; : : /* : * Can't alter newReg's extents before we call pixman_op because : * it might be one of the source regions and pixman_op depends : * on the extents of those regions being unaltered. Besides, this : * way there's no checking against rectangles that will be nuked : * due to coalescing, so we have to examine fewer rectangles. : */ : pixman_set_extents(newReg); : good(newReg); : return TRUE; :} : :/* : * RectIn(region, rect) : * This routine takes a pointer to a region and a pointer to a box : * and determines if the box is outside/inside/partly inside the region. : * : * The idea is to travel through the list of rectangles trying to cover the : * passed box with them. Anytime a piece of the rectangle isn't covered : * by a band of rectangles, partOut is set TRUE. Any time a rectangle in : * the region covers part of the box, partIn is set TRUE. The process ends : * when either the box has been completely covered (we reached a band that : * doesn't overlap the box, partIn is TRUE and partOut is false), the : * box has been partially covered (partIn == partOut == TRUE -- because of : * the banding, the first time this is true we know the box is only : * partially in the region) or is outside the region (we reached a band : * that doesn't overlap the box at all and partIn is false) : */ : :pixman_region_overlap_t :pixman_region_contains_rectangle(pixman_region16_t * region, : pixman_box16_t * prect) :{ : int x; : int y; : pixman_box16_t * pbox; : pixman_box16_t * pboxEnd; : int partIn, partOut; : int numRects; : : good(region); : numRects = PIXREGION_NUM_RECTS(region); : /* useful optimization */ : if (!numRects || !EXTENTCHECK(®ion->extents, prect)) : return(PIXMAN_REGION_OUT); : : if (numRects == 1) : { : /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */ : if (SUBSUMES(®ion->extents, prect)) : return(PIXMAN_REGION_IN); : else : return(PIXMAN_REGION_PART); : } : : partOut = FALSE; : partIn = FALSE; : : /* (x,y) starts at upper left of rect, moving to the right and down */ : x = prect->x1; : y = prect->y1; : : /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */ : for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects; : pbox != pboxEnd; : pbox++) : { : : if (pbox->y2 <= y) : continue; /* getting up to speed or skipping remainder of band */ : : if (pbox->y1 > y) : { : partOut = TRUE; /* missed part of rectangle above */ : if (partIn || (pbox->y1 >= prect->y2)) : break; : y = pbox->y1; /* x guaranteed to be == prect->x1 */ : } : : if (pbox->x2 <= x) : continue; /* not far enough over yet */ : : if (pbox->x1 > x) : { : partOut = TRUE; /* missed part of rectangle to left */ : if (partIn) : break; : } : : if (pbox->x1 < prect->x2) : { : partIn = TRUE; /* definitely overlap */ : if (partOut) : break; : } : : if (pbox->x2 >= prect->x2) : { : y = pbox->y2; /* finished with this band */ : if (y >= prect->y2) : break; : x = prect->x1; /* reset x out to left again */ : } : else : { : /* : * Because boxes in a band are maximal width, if the first box : * to overlap the rectangle doesn't completely cover it in that : * band, the rectangle must be partially out, since some of it : * will be uncovered in that band. partIn will have been set true : * by now... : */ : partOut = TRUE; : break; : } : } : : if (partIn) : { : if (y < prect->y2) : return PIXMAN_REGION_PART; : else : return PIXMAN_REGION_IN; : } : else : { : return PIXMAN_REGION_OUT; : } :} : :/* pixman_region_translate (region, x, y) : translates in place :*/ : :void :pixman_region_translate (pixman_region16_t * region, int x, int y) 1 0.0011 :{ /* pixman_region_translate total: 7 0.0076 */ : int x1, x2, y1, y2; : int nbox; : pixman_box16_t * pbox; : : good(region); : region->extents.x1 = x1 = region->extents.x1 + x; 1 0.0011 : region->extents.y1 = y1 = region->extents.y1 + y; : region->extents.x2 = x2 = region->extents.x2 + x; 1 0.0011 : region->extents.y2 = y2 = region->extents.y2 + y; 1 0.0011 : if (((x1 - SHRT_MIN)|(y1 - SHRT_MIN)|(SHRT_MAX - x2)|(SHRT_MAX - y2)) >= 0) : { 1 0.0011 : if (region->data && (nbox = region->data->numRects)) : { : for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++) : { : pbox->x1 += x; : pbox->y1 += y; : pbox->x2 += x; : pbox->y2 += y; : } : } : return; : } : if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|(SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0) : { : region->extents.x2 = region->extents.x1; : region->extents.y2 = region->extents.y1; : freeData(region); : region->data = pixman_region_emptyData; : return; : } : if (x1 < SHRT_MIN) : region->extents.x1 = SHRT_MIN; : else if (x2 > SHRT_MAX) : region->extents.x2 = SHRT_MAX; : if (y1 < SHRT_MIN) : region->extents.y1 = SHRT_MIN; : else if (y2 > SHRT_MAX) : region->extents.y2 = SHRT_MAX; : if (region->data && (nbox = region->data->numRects)) : { : pixman_box16_t * pboxout; : : for (pboxout = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++) : { : pboxout->x1 = x1 = pbox->x1 + x; : pboxout->y1 = y1 = pbox->y1 + y; : pboxout->x2 = x2 = pbox->x2 + x; : pboxout->y2 = y2 = pbox->y2 + y; : if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)| : (SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0) : { : region->data->numRects--; : continue; : } : if (x1 < SHRT_MIN) : pboxout->x1 = SHRT_MIN; : else if (x2 > SHRT_MAX) : pboxout->x2 = SHRT_MAX; : if (y1 < SHRT_MIN) : pboxout->y1 = SHRT_MIN; : else if (y2 > SHRT_MAX) : pboxout->y2 = SHRT_MAX; : pboxout++; : } : if (pboxout != pbox) : { : if (region->data->numRects == 1) : { : region->extents = *PIXREGION_BOXPTR(region); : freeData(region); : region->data = (pixman_region16_data_t *)NULL; : } : else : pixman_set_extents(region); : } : } 2 0.0022 :} : :/* XXX: Do we need this? :static pixman_bool_t :pixman_region16_data_copy(pixman_region16_t * dst, pixman_region16_t * src) :{ : good(dst); : good(src); : if (dst->data) : return TRUE; : if (dst == src) : return TRUE; : if (!src->data || !src->data->size) : { : freeData(dst); : dst->data = (pixman_region16_data_t *)NULL; : return TRUE; : } : if (!dst->data || (dst->data->size < src->data->numRects)) : { : freeData(dst); : dst->data = allocData(src->data->numRects); : if (!dst->data) : return pixman_break (dst); : } : dst->data->size = src->data->size; : dst->data->numRects = src->data->numRects; : return TRUE; :} :*/ : :void :pixman_region_reset(pixman_region16_t *region, pixman_box16_t *box) :{ : good(region); : assert(box->x1<=box->x2); : assert(box->y1<=box->y2); : region->extents = *box; : freeData(region); : region->data = (pixman_region16_data_t *)NULL; :} : :/* box is "return" value */ :int :pixman_region_contains_point(pixman_region16_t * region, : int x, int y, : pixman_box16_t * box) :{ : pixman_box16_t *pbox, *pboxEnd; : int numRects; : : good(region); : numRects = PIXREGION_NUM_RECTS(region); : if (!numRects || !INBOX(®ion->extents, x, y)) : return(FALSE); : if (numRects == 1) : { : *box = region->extents; : return(TRUE); : } : for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects; : pbox != pboxEnd; : pbox++) : { : if (y >= pbox->y2) : continue; /* not there yet */ : if ((y < pbox->y1) || (x < pbox->x1)) : break; /* missed it */ : if (x >= pbox->x2) : continue; /* not there yet */ : *box = *pbox; : return(TRUE); : } : return(FALSE); :} : :int :pixman_region_not_empty(pixman_region16_t * region) 9 0.0098 :{ /* pixman_region_not_empty total: 17 0.0185 */ : good(region); 5 0.0054 : return(!PIXREGION_NIL(region)); 3 0.0033 :} : :/* XXX: Do we need this? :static int :pixman_region16_broken(pixman_region16_t * region) :{ : good(region); : return (PIXREGION_NAR(region)); :} :*/ : :void :pixman_region_empty(pixman_region16_t * region) :{ : good(region); : freeData(region); : region->extents.x2 = region->extents.x1; : region->extents.y2 = region->extents.y1; : region->data = pixman_region_emptyData; :} : :pixman_box16_t * :pixman_region_extents(pixman_region16_t * region) :{ : good(region); : return(®ion->extents); :} : :#define ExchangeSpans(a, b) \ :{ \ : pixman_region16_point_t tpt; \ : int tw; \ : \ : tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \ : tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ :} : :/* ||| I should apply the merge sort code to rectangle sorting above, and see : if mapping time can be improved. But right now I've been at work 12 hours, : so forget it. :*/ : :static void QuickSortSpans( : pixman_region16_point_t spans[], : int widths[], : int numSpans) :{ : int y; : int i, j, m; : pixman_region16_point_t *r; : : /* Always called with numSpans > 1 */ : /* Sorts only by y, doesn't bother to sort by x */ : : do : { : if (numSpans < 9) : { : /* Do insertion sort */ : int yprev; : : yprev = spans[0].y; : i = 1; : do : { /* while i != numSpans */ : y = spans[i].y; : if (yprev > y) : { : /* spans[i] is out of order. Move into proper location. */ : pixman_region16_point_t tpt; : int tw, k; : : for (j = 0; y >= spans[j].y; j++) {} : tpt = spans[i]; : tw = widths[i]; : for (k = i; k != j; k--) : { : spans[k] = spans[k-1]; : widths[k] = widths[k-1]; : } : spans[j] = tpt; : widths[j] = tw; : y = spans[i].y; : } /* if out of order */ : yprev = y; : i++; : } while (i != numSpans); : return; : } : : /* Choose partition element, stick in location 0 */ : m = numSpans / 2; : if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); : if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1); : if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); : y = spans[0].y; : : /* Partition array */ : i = 0; : j = numSpans; : do : { : r = &(spans[i]); : do : { : r++; : i++; : } while (i != numSpans && r->y < y); : r = &(spans[j]); : do : { : r--; : j--; : } while (y < r->y); : if (i < j) : ExchangeSpans(i, j); : } while (i < j); : : /* Move partition element back to middle */ : ExchangeSpans(0, j); : : /* Recurse */ : if (numSpans-j-1 > 1) : QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1); : numSpans = j; : } while (numSpans > 1); :} : :#define NextBand() \ :{ \ : clipy1 = pboxBandStart->y1; \ : clipy2 = pboxBandStart->y2; \ : pboxBandEnd = pboxBandStart + 1; \ : while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \ : pboxBandEnd++; \ : } \ : for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \ :} : :/* : Clip a list of scanlines to a region. The caller has allocated the : space. FSorted is non-zero if the scanline origins are in ascending : order. : returns the number of new, clipped scanlines. :*/ : :#ifdef XXX_DO_WE_NEED_THIS :static int :pixman_region16_clip_spans( : pixman_region16_t *prgnDst, : pixman_region16_point_t *ppt, : int *pwidth, : int nspans, : pixman_region16_point_t *pptNew, : int *pwidthNew, : int fSorted) :{ : pixman_region16_point_t *pptLast; : int *pwidthNewStart; /* the vengeance of Xerox! */ : int y, x1, x2; : int numRects; : : good(prgnDst); : pptLast = ppt + nspans; : pwidthNewStart = pwidthNew; : : if (!prgnDst->data) : { : /* Do special fast code with clip boundaries in registers(?) */ : /* It doesn't pay much to make use of fSorted in this case, : so we lump everything together. */ : : int clipx1, clipx2, clipy1, clipy2; : : clipx1 = prgnDst->extents.x1; : clipy1 = prgnDst->extents.y1; : clipx2 = prgnDst->extents.x2; : clipy2 = prgnDst->extents.y2; : : for (; ppt != pptLast; ppt++, pwidth++) : { : y = ppt->y; : x1 = ppt->x; : if (clipy1 <= y && y < clipy2) : { : x2 = x1 + *pwidth; : if (x1 < clipx1) x1 = clipx1; : if (x2 > clipx2) x2 = clipx2; : if (x1 < x2) : { : /* part of span in clip rectangle */ : pptNew->x = x1; : pptNew->y = y; : *pwidthNew = x2 - x1; : pptNew++; : pwidthNew++; : } : } : } /* end for */ : : } : else if ((numRects = prgnDst->data->numRects)) : { : /* Have to clip against many boxes */ : pixman_box16_t *pboxBandStart, *pboxBandEnd; : pixman_box16_t *pbox; : pixman_box16_t *pboxLast; : int clipy1, clipy2; : : /* In this case, taking advantage of sorted spans gains more than : the sorting costs. */ : if ((! fSorted) && (nspans > 1)) : QuickSortSpans(ppt, pwidth, nspans); : : pboxBandStart = PIXREGION_BOXPTR(prgnDst); : pboxLast = pboxBandStart + numRects; : : NextBand(); : : for (; ppt != pptLast; ) : { : y = ppt->y; : if (y < clipy2) : { : /* span is in the current band */ : pbox = pboxBandStart; : x1 = ppt->x; : x2 = x1 + *pwidth; : do : { /* For each box in band */ : int newx1, newx2; : : newx1 = x1; : newx2 = x2; : if (newx1 < pbox->x1) newx1 = pbox->x1; : if (newx2 > pbox->x2) newx2 = pbox->x2; : if (newx1 < newx2) : { : /* Part of span in clip rectangle */ : pptNew->x = newx1; : pptNew->y = y; : *pwidthNew = newx2 - newx1; : pptNew++; : pwidthNew++; : } : pbox++; : } while (pbox != pboxBandEnd); : ppt++; : pwidth++; : } : else : { : /* Move to next band, adjust ppt as needed */ : pboxBandStart = pboxBandEnd; : if (pboxBandStart == pboxLast) : break; /* We're completely done */ : NextBand(); : } : } : } : return (pwidthNew - pwidthNewStart); :} : :/* find the band in a region with the most rectangles */ :static int :pixman_region16_find_max_band(pixman_region16_t * prgn) :{ : int nbox; : pixman_box16_t * pbox; : int nThisBand; : int nMaxBand = 0; : short yThisBand; : : good(prgn); : nbox = PIXREGION_NUM_RECTS(prgn); : pbox = PIXREGION_RECTS(prgn); : : while(nbox > 0) : { : yThisBand = pbox->y1; : nThisBand = 0; : while((nbox > 0) && (pbox->y1 == yThisBand)) : { : nbox--; : pbox++; : nThisBand++; : } : if (nThisBand > nMaxBand) : nMaxBand = nThisBand; : } : return (nMaxBand); :} :#endif /* XXX_DO_WE_NEED_THIS */ : : :pixman_bool_t :pixman_region_selfcheck (reg) : pixman_region16_t * reg; :{ : int i, numRects; : : if ((reg->extents.x1 > reg->extents.x2) || : (reg->extents.y1 > reg->extents.y2)) : return FALSE; : numRects = PIXREGION_NUM_RECTS(reg); : if (!numRects) : return ((reg->extents.x1 == reg->extents.x2) && : (reg->extents.y1 == reg->extents.y2) && : (reg->data->size || (reg->data == pixman_region_emptyData))); : else if (numRects == 1) : return (!reg->data); : else : { : pixman_box16_t * pboxP, * pboxN; : pixman_box16_t box; : : pboxP = PIXREGION_RECTS(reg); : box = *pboxP; : box.y2 = pboxP[numRects-1].y2; : pboxN = pboxP + 1; : for (i = numRects; --i > 0; pboxP++, pboxN++) : { : if ((pboxN->x1 >= pboxN->x2) || : (pboxN->y1 >= pboxN->y2)) : return FALSE; : if (pboxN->x1 < box.x1) : box.x1 = pboxN->x1; : if (pboxN->x2 > box.x2) : box.x2 = pboxN->x2; : if ((pboxN->y1 < pboxP->y1) || : ((pboxN->y1 == pboxP->y1) && : ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2)))) : return FALSE; : } : return ((box.x1 == reg->extents.x1) && : (box.x2 == reg->extents.x2) && : (box.y1 == reg->extents.y1) && : (box.y2 == reg->extents.y2)); : } :} : :pixman_bool_t :pixman_region_init_rects (pixman_region16_t *region, : pixman_box16_t *boxes, int count) :{ : int overlap; : : if (count == 1) { : pixman_region_init_rect(region, : boxes[0].x1, : boxes[0].y1, : boxes[0].x2 - boxes[0].x1, : boxes[0].y2 - boxes[0].y1); : return TRUE; : } : : pixman_region_init(region); : if (!pixman_rect_alloc(region, count)) : return FALSE; : : /* Copy in the rects */ : memcpy (PIXREGION_RECTS(region), boxes, sizeof(pixman_box16_t) * count); : region->data->numRects = count; : : /* Validate */ : region->extents.x1 = region->extents.x2 = 0; : return pixman_region_validate (region, &overlap); :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa_migration.c" * * 335 0.3649 */ :/* : * Copyright © 2006 Intel Corporation : * : * Permission is hereby granted, free of charge, to any person obtaining a : * copy of this software and associated documentation files (the "Software"), : * to deal in the Software without restriction, including without limitation : * the rights to use, copy, modify, merge, publish, distribute, sublicense, : * and/or sell copies of the Software, and to permit persons to whom the : * Software is furnished to do so, subject to the following conditions: : * : * The above copyright notice and this permission notice (including the next : * paragraph) shall be included in all copies or substantial portions of the : * Software. : * : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE : * SOFTWARE. : * : * Authors: : * Eric Anholt : * Michel Dänzer : * : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include : :#include "exa_priv.h" :#include :#include "dixfontstr.h" :#include "exa.h" :#include "cw.h" : :#if DEBUG_MIGRATE :#define DBG_MIGRATE(a) ErrorF a :#else :#define DBG_MIGRATE(a) :#endif : :/** : * Returns TRUE if the pixmap is not movable. This is the case where it's a : * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch : * pixmap created by some other X Server internals (the score says it's : * pinned). : */ :static Bool :exaPixmapIsPinned (PixmapPtr pPix) 11 0.0120 :{ /* exaPixmapIsPinned total: 45 0.0490 */ 7 0.0076 : ExaPixmapPriv (pPix); : 25 0.0272 : return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED; 2 0.0022 :} : :/** : * The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys : * and exaCopyDirtyToFb both needed to do this loop. : */ :static void :exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch, : CARD8 *dst, int dst_pitch) : { : int i, cpp = pPixmap->drawable.bitsPerPixel / 8; : int bytes = (pbox->x2 - pbox->x1) * cpp; : : src += pbox->y1 * src_pitch + pbox->x1 * cpp; : dst += pbox->y1 * dst_pitch + pbox->x1 * cpp; : : for (i = pbox->y2 - pbox->y1; i; i--) { : memcpy (dst, src, bytes); : src += src_pitch; : dst += dst_pitch; : } :} : :/** : * Returns TRUE if the pixmap is dirty (has been modified in its current : * location compared to the other), or lacks a private for tracking : * dirtiness. : */ :static Bool :exaPixmapIsDirty (PixmapPtr pPix) :{ : ExaPixmapPriv (pPix); : : return pExaPixmap == NULL || : REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage)); :} : :/** : * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score : * to be considered "should be in framebuffer". That's just anything that has : * had more acceleration than fallbacks, or has no score yet. : * : * Only valid if using a migration scheme that tracks score. : */ :static Bool :exaPixmapShouldBeInFB (PixmapPtr pPix) :{ : ExaPixmapPriv (pPix); : : if (exaPixmapIsPinned (pPix)) : return TRUE; : : return pExaPixmap->score >= 0; :} : :/** : * If the pixmap is currently dirty, this copies at least the dirty area from : * the framebuffer memory copy to the system memory copy. Both areas must be : * allocated. : */ :static void :exaCopyDirtyToSys (PixmapPtr pPixmap) :{ : ExaScreenPriv (pPixmap->drawable.pScreen); : ExaPixmapPriv (pPixmap); : RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage); : CARD8 *save_ptr; : int save_pitch; : BoxPtr pBox = REGION_RECTS(pRegion); : int nbox = REGION_NUM_RECTS(pRegion); : Bool do_sync = FALSE; : : save_ptr = pPixmap->devPrivate.ptr; : save_pitch = pPixmap->devKind; : pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; : pPixmap->devKind = pExaPixmap->fb_pitch; : : while (nbox--) { : pBox->x1 = max(pBox->x1, 0); : pBox->y1 = max(pBox->y1, 0); : pBox->x2 = min(pBox->x2, pPixmap->drawable.width); : pBox->y2 = min(pBox->y2, pPixmap->drawable.height); : : if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) : continue; : : if (pExaScr->info->DownloadFromScreen == NULL || : !pExaScr->info->DownloadFromScreen (pPixmap, : pBox->x1, pBox->y1, : pBox->x2 - pBox->x1, : pBox->y2 - pBox->y1, : pExaPixmap->sys_ptr : + pBox->y1 * pExaPixmap->sys_pitch : + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8, : pExaPixmap->sys_pitch)) : { : exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); : exaMemcpyBox (pPixmap, pBox, : pExaPixmap->fb_ptr, pExaPixmap->fb_pitch, : pExaPixmap->sys_ptr, pExaPixmap->sys_pitch); : exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); : } : else : do_sync = TRUE; : : pBox++; : } : : /* Make sure the bits have actually landed, since we don't necessarily sync : * when accessing pixmaps in system memory. : */ : if (do_sync) : exaWaitSync (pPixmap->drawable.pScreen); : : pPixmap->devPrivate.ptr = save_ptr; : pPixmap->devKind = save_pitch; : : /* The previously damaged bits are now no longer damaged but valid */ : REGION_UNION(pPixmap->drawable.pScreen, : &pExaPixmap->validReg, &pExaPixmap->validReg, pRegion); : DamageEmpty (pExaPixmap->pDamage); :} : :/** : * If the pixmap is currently dirty, this copies at least the dirty area from : * the system memory copy to the framebuffer memory copy. Both areas must be : * allocated. : */ :static void :exaCopyDirtyToFb (PixmapPtr pPixmap) :{ : ExaScreenPriv (pPixmap->drawable.pScreen); : ExaPixmapPriv (pPixmap); : RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage); : CARD8 *save_ptr; : int save_pitch; : BoxPtr pBox = REGION_RECTS(pRegion); : int nbox = REGION_NUM_RECTS(pRegion); : Bool do_sync = FALSE; : : save_ptr = pPixmap->devPrivate.ptr; : save_pitch = pPixmap->devKind; : pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; : pPixmap->devKind = pExaPixmap->fb_pitch; : : while (nbox--) { : pBox->x1 = max(pBox->x1, 0); : pBox->y1 = max(pBox->y1, 0); : pBox->x2 = min(pBox->x2, pPixmap->drawable.width); : pBox->y2 = min(pBox->y2, pPixmap->drawable.height); : : if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) : continue; : : if (pExaScr->info->UploadToScreen == NULL || : !pExaScr->info->UploadToScreen (pPixmap, : pBox->x1, pBox->y1, : pBox->x2 - pBox->x1, : pBox->y2 - pBox->y1, : pExaPixmap->sys_ptr : + pBox->y1 * pExaPixmap->sys_pitch : + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8, : pExaPixmap->sys_pitch)) : { : exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST); : exaMemcpyBox (pPixmap, pBox, : pExaPixmap->sys_ptr, pExaPixmap->sys_pitch, : pExaPixmap->fb_ptr, pExaPixmap->fb_pitch); : exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST); : } : else : do_sync = TRUE; : : pBox++; : } : : if (do_sync) : exaMarkSync (pPixmap->drawable.pScreen); : : pPixmap->devPrivate.ptr = save_ptr; : pPixmap->devKind = save_pitch; : : /* The previously damaged bits are now no longer damaged but valid */ : REGION_UNION(pPixmap->drawable.pScreen, : &pExaPixmap->validReg, &pExaPixmap->validReg, pRegion); : DamageEmpty (pExaPixmap->pDamage); :} : :/** : * Copies out important pixmap data and removes references to framebuffer area. : * Called when the memory manager decides it's time to kick the pixmap out of : * framebuffer entirely. : */ :void :exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area) :{ : PixmapPtr pPixmap = area->privData; : ExaPixmapPriv(pPixmap); : RegionPtr pDamageReg = DamageRegion(pExaPixmap->pDamage); : : DBG_MIGRATE (("Save %p (%p) (%dx%d) (%c)\n", pPixmap, : (void*)(ExaGetPixmapPriv(pPixmap)->area ? : ExaGetPixmapPriv(pPixmap)->area->offset : 0), : pPixmap->drawable.width, : pPixmap->drawable.height, : exaPixmapIsDirty(pPixmap) ? 'd' : 'c')); : : if (exaPixmapIsOffscreen(pPixmap)) { : exaCopyDirtyToSys (pPixmap); : pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; : pPixmap->devKind = pExaPixmap->sys_pitch; : pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; : } : : pExaPixmap->fb_ptr = NULL; : pExaPixmap->area = NULL; : : /* Mark all valid bits as damaged, so they'll get copied to FB next time */ : REGION_UNION(pPixmap->drawable.pScreen, pDamageReg, pDamageReg, : &pExaPixmap->validReg); :} : :/** : * Allocates a framebuffer copy of the pixmap if necessary, and then copies : * any necessary pixmap data into the framebuffer copy and points the pixmap at : * it. : * : * Note that when first allocated, a pixmap will have FALSE dirty flag. : * This is intentional because pixmap data starts out undefined. So if we move : * it in due to the first operation against it being accelerated, it will have : * undefined framebuffer contents that we didn't have to upload. If we do : * moveouts (and moveins) after the first movein, then we will only have to copy : * back and forth if the pixmap was written to after the last synchronization of : * the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away) : * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move : * all the data, since it's almost surely all valid now. : */ :void :exaMoveInPixmap (PixmapPtr pPixmap) 30 0.0327 :{ /* exaMoveInPixmap total: 133 0.1449 */ 4 0.0044 : ScreenPtr pScreen = pPixmap->drawable.pScreen; 23 0.0251 : ExaScreenPriv (pScreen); 23 0.0251 : ExaPixmapPriv (pPixmap); : : /* If we're VT-switched away, no touching card memory allowed. */ 16 0.0174 : if (pExaScr->swappedOut) : return; : : /* If we're already in FB, our work is done. */ 12 0.0131 : if (exaPixmapIsOffscreen(pPixmap)) : return; : : /* If we're not allowed to move, then fail. */ : if (exaPixmapIsPinned(pPixmap)) : return; : : /* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of : * fragility in EXA, and <8bpp is probably not used enough any more to care : * (at least, not in acceleratd paths). : */ 1 0.0011 : if (pPixmap->drawable.bitsPerPixel < 8) : return; : : if (pExaPixmap->area == NULL) { 2 0.0022 : pExaPixmap->area = : exaOffscreenAlloc (pScreen, pExaPixmap->fb_size, : pExaScr->info->pixmapOffsetAlign, FALSE, : exaPixmapSave, (pointer) pPixmap); : if (pExaPixmap->area == NULL) : return; : : pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase + : pExaPixmap->area->offset; : } : : DBG_MIGRATE (("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap, : (ExaGetPixmapPriv(pPixmap)->area ? : ExaGetPixmapPriv(pPixmap)->area->offset : 0), : pPixmap->drawable.width, : pPixmap->drawable.height, : exaPixmapIsDirty(pPixmap) ? 'd' : 'c')); : : exaCopyDirtyToFb (pPixmap); : : if (pExaScr->hideOffscreenPixmapData) : pPixmap->devPrivate.ptr = NULL; : else 1 0.0011 : pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 1 0.0011 : pPixmap->devKind = pExaPixmap->fb_pitch; 2 0.0022 : pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 9 0.0098 :} : :/** : * Switches the current active location of the pixmap to system memory, copying : * updated data out if necessary. : */ :void :exaMoveOutPixmap (PixmapPtr pPixmap) :{ : ExaPixmapPriv (pPixmap); : : if (exaPixmapIsPinned(pPixmap)) : return; : : if (exaPixmapIsOffscreen(pPixmap)) { : : DBG_MIGRATE (("<- %p (%p) (%dx%d) (%c)\n", pPixmap, : (void*)(ExaGetPixmapPriv(pPixmap)->area ? : ExaGetPixmapPriv(pPixmap)->area->offset : 0), : pPixmap->drawable.width, : pPixmap->drawable.height, : exaPixmapIsDirty(pPixmap) ? 'd' : 'c')); : : exaCopyDirtyToSys (pPixmap); : : pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; : pPixmap->devKind = pExaPixmap->sys_pitch; : pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; : } :} : :/** : * For the "greedy" migration scheme, pushes the pixmap toward being located in : * framebuffer memory. : */ :static void :exaMigrateTowardFb (PixmapPtr pPixmap) :{ : ExaPixmapPriv (pPixmap); : : if (pExaPixmap == NULL) { : DBG_MIGRATE(("UseScreen: ignoring exa-uncontrolled pixmap %p (%s)\n", : (pointer)pPixmap, : exaPixmapIsOffscreen(pPixmap) ? "s" : "m")); : return; : } : : if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) { : DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n", : (pointer)pPixmap)); : return; : } : : DBG_MIGRATE(("UseScreen %p score %d\n", : (pointer)pPixmap, pExaPixmap->score)); : : if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) { : exaMoveInPixmap(pPixmap); : pExaPixmap->score = 0; : } : : if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX) : pExaPixmap->score++; : : if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN && : !exaPixmapIsOffscreen(pPixmap)) : { : exaMoveInPixmap (pPixmap); : } : : ExaOffscreenMarkUsed (pPixmap); :} : :/** : * For the "greedy" migration scheme, pushes the pixmap toward being located in : * system memory. : */ :static void :exaMigrateTowardSys (PixmapPtr pPixmap) :{ : ExaPixmapPriv (pPixmap); : : if (pExaPixmap == NULL) { : DBG_MIGRATE(("UseMem: ignoring exa-uncontrolled pixmap %p (%s)\n", : (pointer)pPixmap, : exaPixmapIsOffscreen(pPixmap) ? "s" : "m")); : return; : } : : DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)pPixmap, pExaPixmap->score)); : : if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) : return; : : if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) : pExaPixmap->score = 0; : : if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN) : pExaPixmap->score--; : : if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area) : exaMoveOutPixmap (pPixmap); :} : :/** : * If the pixmap has both a framebuffer and system memory copy, this function : * asserts that both of them are the same. : */ :static Bool :exaAssertNotDirty (PixmapPtr pPixmap) :{ : ExaPixmapPriv (pPixmap); : CARD8 *dst, *src; : RegionPtr pValidReg = &pExaPixmap->validReg; : int dst_pitch, src_pitch, cpp, y, nbox = REGION_NUM_RECTS(pValidReg); : BoxPtr pBox = REGION_RECTS(pValidReg); : Bool ret = TRUE; : : if (!nbox || exaPixmapIsPinned(pPixmap) || pExaPixmap->fb_ptr == NULL) : return ret; : : dst_pitch = pExaPixmap->sys_pitch; : src_pitch = pExaPixmap->fb_pitch; : cpp = pPixmap->drawable.bitsPerPixel / 8; : : exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); : while (nbox--) { : int rowbytes; : : pBox->x1 = max(pBox->x1, 0); : pBox->y1 = max(pBox->y1, 0); : pBox->x2 = min(pBox->x2, pPixmap->drawable.width); : pBox->y2 = min(pBox->y2, pPixmap->drawable.height); : : if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) : continue; : : rowbytes = (pBox->x2 - pBox->x1) * cpp; : src = pExaPixmap->fb_ptr + pBox->y1 * src_pitch + pBox->x1 * cpp; : dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp; : : for (y = pBox->y1; y < pBox->y2; : y++, src += src_pitch, dst += dst_pitch) { : if (memcmp(dst, src, rowbytes) != 0) { : ret = FALSE; : exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, : pBox->y2); : break; : } : } : } : exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); : : return ret; :} : :/** : * Performs migration of the pixmaps according to the operation information : * provided in pixmaps and can_accel and the migration scheme chosen in the : * config file. : */ :void :exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) 12 0.0131 :{ /* exaDoMigration total: 166 0.1808 */ : ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen; 17 0.0185 : ExaScreenPriv(pScreen); : int i, j; : 3 0.0033 : if (! can_accel) : return; : : /* If this debugging flag is set, check each pixmap for whether it is marked : * as clean, and if so, actually check if that's the case. This should help : * catch issues with failing to mark a drawable as dirty. While it will : * catch them late (after the operation happened), it at least explains what : * went wrong, and instrumenting the code to find what operation happened : * to the pixmap last shouldn't be hard. : */ 9 0.0098 : if (pExaScr->checkDirtyCorrectness) { 1 0.0011 : for (i = 0; i < npixmaps; i++) { : if (!exaPixmapIsDirty (pixmaps[i].pPix) && : !exaAssertNotDirty (pixmaps[i].pPix)) : ErrorF("%s: Pixmap %d dirty but not marked as such!\n", __func__, i); : } : } : /* If anything is pinned in system memory, we won't be able to : * accelerate. : */ 16 0.0174 : for (i = 0; i < npixmaps; i++) { 22 0.0240 : if (exaPixmapIsPinned (pixmaps[i].pPix) && : !exaPixmapIsOffscreen (pixmaps[i].pPix)) : { : return; : EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix, : pixmaps[i].pPix->drawable.width, : pixmaps[i].pPix->drawable.height)); : can_accel = FALSE; : break; : } : } : 2 0.0022 : if (pExaScr->migration == ExaMigrationSmart) { : /* If we've got something as a destination that we shouldn't cause to : * become newly dirtied, take the unaccelerated route. : */ : for (i = 0; i < npixmaps; i++) { : if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB (pixmaps[i].pPix) && : !exaPixmapIsDirty (pixmaps[i].pPix)) : { : for (i = 0; i < npixmaps; i++) { : if (!exaPixmapIsDirty (pixmaps[i].pPix)) : exaMoveOutPixmap (pixmaps[i].pPix); : } : return; : } : } : : /* If we aren't going to accelerate, then we migrate everybody toward : * system memory, and kick out if it's free. : */ : if (!can_accel) { : for (i = 0; i < npixmaps; i++) { : exaMigrateTowardSys (pixmaps[i].pPix); : if (!exaPixmapIsDirty (pixmaps[i].pPix)) : exaMoveOutPixmap (pixmaps[i].pPix); : } : return; : } : : /* Finally, the acceleration path. Move them all in. */ : for (i = 0; i < npixmaps; i++) { : exaMigrateTowardFb(pixmaps[i].pPix); : exaMoveInPixmap(pixmaps[i].pPix); : } : } else if (pExaScr->migration == ExaMigrationGreedy) { : /* If we can't accelerate, either because the driver can't or because one of : * the pixmaps is pinned in system memory, then we migrate everybody toward : * system memory. : * : * We also migrate toward system if all pixmaps involved are currently in : * system memory -- this can mitigate thrashing when there are significantly : * more pixmaps active than would fit in memory. : * : * If not, then we migrate toward FB so that hopefully acceleration can : * happen. : */ : if (!can_accel) { : for (i = 0; i < npixmaps; i++) : exaMigrateTowardSys (pixmaps[i].pPix); : return; : } : : for (i = 0; i < npixmaps; i++) { : if (exaPixmapIsOffscreen(pixmaps[i].pPix)) { : /* Found one in FB, so move all to FB. */ : for (j = 0; j < npixmaps; j++) : exaMigrateTowardFb(pixmaps[j].pPix); : return; : } : } : : /* Nobody's in FB, so move all away from FB. */ : for (i = 0; i < npixmaps; i++) : exaMigrateTowardSys(pixmaps[i].pPix); 3 0.0033 : } else if (pExaScr->migration == ExaMigrationAlways) { : /* Always move the pixmaps out if we can't accelerate. If we can : * accelerate, try to move them all in. If that fails, then move them : * back out. : */ : if (!can_accel) { : for (i = 0; i < npixmaps; i++) : exaMoveOutPixmap(pixmaps[i].pPix); : return; : } : : /* Now, try to move them all into FB */ 21 0.0229 : for (i = 0; i < npixmaps; i++) { 18 0.0196 : exaMoveInPixmap(pixmaps[i].pPix); 11 0.0120 : ExaOffscreenMarkUsed (pixmaps[i].pPix); : } : : /* If we couldn't fit everything in, then kick back out */ 6 0.0065 : for (i = 0; i < npixmaps; i++) { 17 0.0185 : if (!exaPixmapIsOffscreen(pixmaps[i].pPix)) { : return; : EXA_FALLBACK(("Pixmap %p (%dx%d) not in fb\n", pixmaps[i].pPix, : pixmaps[i].pPix->drawable.width, : pixmaps[i].pPix->drawable.height)); : for (j = 0; j < npixmaps; j++) : exaMoveOutPixmap(pixmaps[j].pPix); : break; : } : } : } 8 0.0087 :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/render/mipict.c" * * 267 0.2909 */ :/* : * : * Copyright © 1999 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "scrnintstr.h" :#include "gcstruct.h" :#include "pixmapstr.h" :#include "windowstr.h" :#include "mi.h" :#include "picturestr.h" :#include "mipict.h" : :#ifndef __GNUC__ :#define __inline :#endif : :int :miCreatePicture (PicturePtr pPicture) 1 0.0011 :{ /* miCreatePicture total: 2 0.0022 */ : return Success; 1 0.0011 :} : :void :miDestroyPicture (PicturePtr pPicture) 3 0.0033 :{ /* miDestroyPicture total: 4 0.0044 */ : if (pPicture->freeCompClip) 1 0.0011 : REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->pCompositeClip); :} : :void :miDestroyPictureClip (PicturePtr pPicture) :{ : switch (pPicture->clientClipType) { : case CT_NONE: : return; : case CT_PIXMAP: : (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip)); : break; : default: : /* : * we know we'll never have a list of rectangles, since ChangeClip : * immediately turns them into a region : */ : REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->clientClip); : break; : } : pPicture->clientClip = NULL; : pPicture->clientClipType = CT_NONE; :} : :int :miChangePictureClip (PicturePtr pPicture, : int type, : pointer value, : int n) :{ /* miChangePictureClip total: 1 0.0011 */ : ScreenPtr pScreen = pPicture->pDrawable->pScreen; 1 0.0011 : PictureScreenPtr ps = GetPictureScreen(pScreen); : pointer clientClip; : int clientClipType; : : switch (type) { : case CT_PIXMAP: : /* convert the pixmap to a region */ : clientClip = (pointer) BITMAP_TO_REGION(pScreen, (PixmapPtr) value); : if (!clientClip) : return BadAlloc; : clientClipType = CT_REGION; : (*pScreen->DestroyPixmap) ((PixmapPtr) value); : break; : case CT_REGION: : clientClip = value; : clientClipType = CT_REGION; : break; : case CT_NONE: : clientClip = 0; : clientClipType = CT_NONE; : break; : default: : clientClip = (pointer) RECTS_TO_REGION(pScreen, n, : (xRectangle *) value, : type); : if (!clientClip) : return BadAlloc; : clientClipType = CT_REGION; : xfree(value); : break; : } : (*ps->DestroyPictureClip) (pPicture); : pPicture->clientClip = clientClip; : pPicture->clientClipType = clientClipType; : pPicture->stateChanges |= CPClipMask; : return Success; :} : :void :miChangePicture (PicturePtr pPicture, : Mask mask) :{ /* miChangePicture total: 1 0.0011 */ : return; 1 0.0011 :} : :void :miValidatePicture (PicturePtr pPicture, : Mask mask) 3 0.0033 :{ /* miValidatePicture total: 9 0.0098 */ : DrawablePtr pDrawable = pPicture->pDrawable; : : if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) || : (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) : { 1 0.0011 : if (pDrawable->type == DRAWABLE_WINDOW) : { : WindowPtr pWin = (WindowPtr) pDrawable; : RegionPtr pregWin; : Bool freeTmpClip, freeCompClip; : : if (pPicture->subWindowMode == IncludeInferiors) : { : pregWin = NotClippedByChildren(pWin); : freeTmpClip = TRUE; : } : else : { : pregWin = &pWin->clipList; : freeTmpClip = FALSE; : } : freeCompClip = pPicture->freeCompClip; : : /* : * if there is no client clip, we can get by with just keeping the : * pointer we got, and remembering whether or not should destroy : * (or maybe re-use) it later. this way, we avoid unnecessary : * copying of regions. (this wins especially if many clients clip : * by children and have no client clip.) : */ : if (pPicture->clientClipType == CT_NONE) : { : if (freeCompClip) : REGION_DESTROY(pScreen, pPicture->pCompositeClip); : pPicture->pCompositeClip = pregWin; : pPicture->freeCompClip = freeTmpClip; : } : else : { : /* : * we need one 'real' region to put into the composite clip. if : * pregWin the current composite clip are real, we can get rid of : * one. if pregWin is real and the current composite clip isn't, : * use pregWin for the composite clip. if the current composite : * clip is real and pregWin isn't, use the current composite : * clip. if neither is real, create a new region. : */ : : REGION_TRANSLATE(pScreen, pPicture->clientClip, : pDrawable->x + pPicture->clipOrigin.x, : pDrawable->y + pPicture->clipOrigin.y); : : if (freeCompClip) : { : REGION_INTERSECT(pScreen, pPicture->pCompositeClip, : pregWin, pPicture->clientClip); : if (freeTmpClip) : REGION_DESTROY(pScreen, pregWin); : } : else if (freeTmpClip) : { : REGION_INTERSECT(pScreen, pregWin, pregWin, pPicture->clientClip); : pPicture->pCompositeClip = pregWin; : } : else : { : pPicture->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0); : REGION_INTERSECT(pScreen, pPicture->pCompositeClip, : pregWin, pPicture->clientClip); : } : pPicture->freeCompClip = TRUE; : REGION_TRANSLATE(pScreen, pPicture->clientClip, : -(pDrawable->x + pPicture->clipOrigin.x), : -(pDrawable->y + pPicture->clipOrigin.y)); : } : } /* end of composite clip for a window */ : else : { : BoxRec pixbounds; : : /* XXX should we translate by drawable.x/y here ? */ : /* If you want pixmaps in offscreen memory, yes */ 1 0.0011 : pixbounds.x1 = pDrawable->x; : pixbounds.y1 = pDrawable->y; : pixbounds.x2 = pDrawable->x + pDrawable->width; : pixbounds.y2 = pDrawable->y + pDrawable->height; : : if (pPicture->freeCompClip) : { : REGION_RESET(pScreen, pPicture->pCompositeClip, &pixbounds); : } : else : { : pPicture->freeCompClip = TRUE; 3 0.0033 : pPicture->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1); : } : : if (pPicture->clientClipType == CT_REGION) : { : if(pDrawable->x || pDrawable->y) { : REGION_TRANSLATE(pScreen, pPicture->clientClip, : pDrawable->x + pPicture->clipOrigin.x, : pDrawable->y + pPicture->clipOrigin.y); : REGION_INTERSECT(pScreen, pPicture->pCompositeClip, : pPicture->pCompositeClip, pPicture->clientClip); : REGION_TRANSLATE(pScreen, pPicture->clientClip, : -(pDrawable->x + pPicture->clipOrigin.x), : -(pDrawable->y + pPicture->clipOrigin.y)); : } else { : REGION_TRANSLATE(pScreen, pPicture->pCompositeClip, : -pPicture->clipOrigin.x, -pPicture->clipOrigin.y); : REGION_INTERSECT(pScreen, pPicture->pCompositeClip, : pPicture->pCompositeClip, pPicture->clientClip); : REGION_TRANSLATE(pScreen, pPicture->pCompositeClip, : pPicture->clipOrigin.x, pPicture->clipOrigin.y); : } : } : } /* end of composite clip for pixmap */ : } 1 0.0011 :} : :int :miChangePictureTransform (PicturePtr pPicture, : PictTransform *transform) 1 0.0011 :{ /* miChangePictureTransform total: 1 0.0011 */ : return Success; :} : :int :miChangePictureFilter (PicturePtr pPicture, : int filter, : xFixed *params, : int nparams) 1 0.0011 :{ /* miChangePictureFilter total: 1 0.0011 */ : return Success; :} : :#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v)) : :static inline pixman_bool_t :miClipPictureReg (pixman_region16_t * pRegion, : pixman_region16_t * pClip, : int dx, : int dy) :{ : if (pixman_region_n_rects(pRegion) == 1 && : pixman_region_n_rects(pClip) == 1) : { : pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL); : pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL); : int v; : : if (pRbox->x1 < (v = pCbox->x1 + dx)) : pRbox->x1 = BOUND(v); : if (pRbox->x2 > (v = pCbox->x2 + dx)) : pRbox->x2 = BOUND(v); : if (pRbox->y1 < (v = pCbox->y1 + dy)) : pRbox->y1 = BOUND(v); : if (pRbox->y2 > (v = pCbox->y2 + dy)) : pRbox->y2 = BOUND(v); : if (pRbox->x1 >= pRbox->x2 || : pRbox->y1 >= pRbox->y2) : { : pixman_region_init (pRegion); : } : } : else if (!pixman_region_not_empty (pClip)) : return FALSE; : else : { : if (dx || dy) : pixman_region_translate (pRegion, -dx, -dy); : if (!pixman_region_intersect (pRegion, pRegion, pClip)) : return FALSE; : if (dx || dy) : pixman_region_translate(pRegion, dx, dy); : } : return pixman_region_not_empty(pRegion); :} : :static __inline Bool :miClipPictureSrc (RegionPtr pRegion, : PicturePtr pPicture, : int dx, : int dy) :{ : /* XXX what to do with clipping from transformed pictures? */ : if (pPicture->transform || !pPicture->pDrawable) : return TRUE; : if (pPicture->repeat) : { : if (pPicture->clientClipType != CT_NONE) : { : pixman_region_translate ( pRegion, : dx - pPicture->clipOrigin.x, : dy - pPicture->clipOrigin.y); : if (!REGION_INTERSECT (pScreen, pRegion, pRegion, : (RegionPtr) pPicture->pCompositeClip)) // clientClip)) : return FALSE; : pixman_region_translate ( pRegion, : - (dx - pPicture->clipOrigin.x), : - (dy - pPicture->clipOrigin.y)); : } : return TRUE; : } : else : { : return miClipPictureReg (pRegion, : pPicture->pCompositeClip, : dx, : dy); : } :} : :void :miCompositeSourceValidate (PicturePtr pPicture, : INT16 x, : INT16 y, : CARD16 width, : CARD16 height) 31 0.0338 :{ /* miCompositeSourceValidate total: 106 0.1155 */ 8 0.0087 : DrawablePtr pDrawable = pPicture->pDrawable; : ScreenPtr pScreen; : 4 0.0044 : if (!pDrawable) : return; : 11 0.0120 : pScreen = pDrawable->pScreen; : 18 0.0196 : if (pScreen->SourceValidate) : { : x -= pPicture->pDrawable->x; 12 0.0131 : y -= pPicture->pDrawable->y; 3 0.0033 : if (pPicture->transform) : { : xPoint points[4]; : int i; : int xmin, ymin, xmax, ymax; : :#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; } : VectorSet (0, x, y); : VectorSet (1, x + width, y); : VectorSet (2, x, y + height); : VectorSet (3, x + width, y + height); : xmin = ymin = 32767; : xmax = ymax = -32737; : for (i = 0; i < 4; i++) : { : PictVector t; : t.vector[0] = IntToxFixed (points[i].x); : t.vector[1] = IntToxFixed (points[i].y); : t.vector[2] = xFixed1; : if (PictureTransformPoint (pPicture->transform, &t)) : { : int tx = xFixedToInt (t.vector[0]); : int ty = xFixedToInt (t.vector[1]); : if (tx < xmin) xmin = tx; : if (tx > xmax) xmax = tx; : if (ty < ymin) ymin = ty; : if (ty > ymax) ymax = ty; : } : } : x = xmin; : y = ymin; : width = xmax - xmin; : height = ymax - ymin; : } 10 0.0109 : (*pScreen->SourceValidate) (pDrawable, x, y, width, height); : } 9 0.0098 :} : :/* : * returns FALSE if the final region is empty. Indistinguishable from : * an allocation failure, but rendering ignores those anyways. : */ : :_X_EXPORT Bool :miComputeCompositeRegion (RegionPtr pRegion, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) 28 0.0305 :{ /* miComputeCompositeRegion total: 296 0.3225 */ : : int v; : 2 0.0022 : pRegion->extents.x1 = xDst; 9 0.0098 : v = xDst + width; 10 0.0109 : pRegion->extents.x2 = BOUND(v); : pRegion->extents.y1 = yDst; 4 0.0044 : v = yDst + height; 9 0.0098 : pRegion->extents.y2 = BOUND(v); 2 0.0022 : pRegion->data = 0; : /* Check for empty operation */ 8 0.0087 : if (pRegion->extents.x1 >= pRegion->extents.x2 || : pRegion->extents.y1 >= pRegion->extents.y2) : { 1 0.0011 : pixman_region_init (pRegion); : return FALSE; : } : /* clip against dst */ 8 0.0087 : if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0)) : { : pixman_region_fini (pRegion); : return FALSE; : } : if (pDst->alphaMap) : { : if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip, : -pDst->alphaOrigin.x, : -pDst->alphaOrigin.y)) : { : pixman_region_fini (pRegion); : return FALSE; : } : } : /* clip against src */ 10 0.0109 : if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc)) : { : pixman_region_fini (pRegion); : return FALSE; : } 5 0.0054 : if (pSrc->alphaMap) : { : if (!miClipPictureSrc (pRegion, pSrc->alphaMap, : xDst - (xSrc + pSrc->alphaOrigin.x), : yDst - (ySrc + pSrc->alphaOrigin.y))) : { : pixman_region_fini (pRegion); : return FALSE; : } : } : /* clip against mask */ 5 0.0054 : if (pMask) : { 2 0.0022 : if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask)) : { : pixman_region_fini (pRegion); : return FALSE; : } 3 0.0033 : if (pMask->alphaMap) : { : if (!miClipPictureSrc (pRegion, pMask->alphaMap, : xDst - (xMask + pMask->alphaOrigin.x), : yDst - (yMask + pMask->alphaOrigin.y))) : { : pixman_region_fini (pRegion); : return FALSE; : } : } : } : : 23 0.0251 : miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height); : if (pMask) 7 0.0076 : miCompositeSourceValidate (pMask, xMask, yMask, width, height); : : return TRUE; 1 0.0011 :} : :void :miRenderColorToPixel (PictFormatPtr format, : xRenderColor *color, : CARD32 *pixel) :{ /* miRenderColorToPixel total: 5 0.0054 */ : CARD32 r, g, b, a; : miIndexedPtr pIndexed; : 1 0.0011 : switch (format->type) { : case PictTypeDirect: 1 0.0011 : r = color->red >> (16 - Ones (format->direct.redMask)); 1 0.0011 : g = color->green >> (16 - Ones (format->direct.greenMask)); : b = color->blue >> (16 - Ones (format->direct.blueMask)); : a = color->alpha >> (16 - Ones (format->direct.alphaMask)); : r = r << format->direct.red; : g = g << format->direct.green; : b = b << format->direct.blue; : a = a << format->direct.alpha; 2 0.0022 : *pixel = r|g|b|a; : break; : case PictTypeIndexed: : pIndexed = (miIndexedPtr) (format->index.devPrivate); : if (pIndexed->color) : { : r = color->red >> 11; : g = color->green >> 11; : b = color->blue >> 11; : *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b); : } : else : { : r = color->red >> 8; : g = color->green >> 8; : b = color->blue >> 8; : *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b); : } : break; : } :} : :static CARD16 :miFillColor (CARD32 pixel, int bits) :{ : while (bits < 16) : { : pixel |= pixel << bits; : bits <<= 1; : } : return (CARD16) pixel; :} : :Bool :miIsSolidAlpha (PicturePtr pSrc) :{ : ScreenPtr pScreen; : char line[1]; : : if (!pSrc->pDrawable) : return FALSE; : : pScreen = pSrc->pDrawable->pScreen; : : /* Alpha-only */ : if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A) : return FALSE; : /* repeat */ : if (!pSrc->repeat) : return FALSE; : /* 1x1 */ : if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) : return FALSE; : line[0] = 1; : (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line); : switch (pSrc->pDrawable->bitsPerPixel) { : case 1: : return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80; : case 4: : return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0; : case 8: : return (CARD8) line[0] == 0xff; : default: : return FALSE; : } :} : :void :miRenderPixelToColor (PictFormatPtr format, : CARD32 pixel, : xRenderColor *color) :{ : CARD32 r, g, b, a; : miIndexedPtr pIndexed; : : switch (format->type) { : case PictTypeDirect: : r = (pixel >> format->direct.red) & format->direct.redMask; : g = (pixel >> format->direct.green) & format->direct.greenMask; : b = (pixel >> format->direct.blue) & format->direct.blueMask; : a = (pixel >> format->direct.alpha) & format->direct.alphaMask; : color->red = miFillColor (r, Ones (format->direct.redMask)); : color->green = miFillColor (g, Ones (format->direct.greenMask)); : color->blue = miFillColor (b, Ones (format->direct.blueMask)); : color->alpha = miFillColor (a, Ones (format->direct.alphaMask)); : break; : case PictTypeIndexed: : pIndexed = (miIndexedPtr) (format->index.devPrivate); : pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)]; : r = (pixel >> 16) & 0xff; : g = (pixel >> 8) & 0xff; : b = (pixel ) & 0xff; : color->red = miFillColor (r, 8); : color->green = miFillColor (g, 8); : color->blue = miFillColor (b, 8); : color->alpha = 0xffff; : break; : } :} : :_X_EXPORT Bool :miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) :{ : PictureScreenPtr ps; : : if (!PictureInit (pScreen, formats, nformats)) : return FALSE; : ps = GetPictureScreen(pScreen); : ps->CreatePicture = miCreatePicture; : ps->DestroyPicture = miDestroyPicture; : ps->ChangePictureClip = miChangePictureClip; : ps->DestroyPictureClip = miDestroyPictureClip; : ps->ChangePicture = miChangePicture; : ps->ValidatePicture = miValidatePicture; : ps->InitIndexed = miInitIndexed; : ps->CloseIndexed = miCloseIndexed; : ps->UpdateIndexed = miUpdateIndexed; : ps->ChangePictureTransform = miChangePictureTransform; : ps->ChangePictureFilter = miChangePictureFilter; : ps->RealizeGlyph = miRealizeGlyph; : ps->UnrealizeGlyph = miUnrealizeGlyph; : : /* MI rendering routines */ : ps->Composite = 0; /* requires DDX support */ : ps->Glyphs = miGlyphs; : ps->CompositeRects = miCompositeRects; : ps->Trapezoids = miTrapezoids; : ps->Triangles = miTriangles; : ps->TriStrip = miTriStrip; : ps->TriFan = miTriFan; : : ps->RasterizeTrapezoid = 0; /* requires DDX support */ : ps->AddTraps = 0; /* requires DDX support */ : ps->AddTriangles = 0; /* requires DDX support */ : : return TRUE; :} /* * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i830_exa.c" * * 254 0.2767 */ :/************************************************************************** : :Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. :All Rights Reserved. :Copyright (c) 2005 Jesse Barnes : Based on code from i830_xaa.c. : :Permission is hereby granted, free of charge, to any person obtaining a :copy of this software and associated documentation files (the :"Software"), to deal in the Software without restriction, including :without limitation the rights to use, copy, modify, merge, publish, :distribute, sub license, and/or sell copies of the Software, and to :permit persons to whom the Software is furnished to do so, subject to :the following conditions: : :The above copyright notice and this permission notice (including the :next paragraph) shall be included in all copies or substantial portions :of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. :IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR :ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, :TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE :SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :**************************************************************************/ : :#ifdef HAVE_CONFIG_H :#include "config.h" :#endif : :#include "xf86.h" :#include "xaarop.h" :#include "i830.h" :#include "i810_reg.h" :#include "i830_reg.h" :#include : :#ifdef I830DEBUG :#define DEBUG_I830FALLBACK 1 :#endif : :#define ALWAYS_SYNC 0 : :#ifdef DEBUG_I830FALLBACK :#define I830FALLBACK(s, arg...) \ :do { \ : DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \ : return FALSE; \ :} while(0) :#else :#define I830FALLBACK(s, arg...) \ :do { \ : return FALSE; \ :} while(0) :#endif : :const int I830CopyROP[16] = :{ : ROP_0, /* GXclear */ : ROP_DSa, /* GXand */ : ROP_SDna, /* GXandReverse */ : ROP_S, /* GXcopy */ : ROP_DSna, /* GXandInverted */ : ROP_D, /* GXnoop */ : ROP_DSx, /* GXxor */ : ROP_DSo, /* GXor */ : ROP_DSon, /* GXnor */ : ROP_DSxn, /* GXequiv */ : ROP_Dn, /* GXinvert*/ : ROP_SDno, /* GXorReverse */ : ROP_Sn, /* GXcopyInverted */ : ROP_DSno, /* GXorInverted */ : ROP_DSan, /* GXnand */ : ROP_1 /* GXset */ :}; : :const int I830PatternROP[16] = :{ : ROP_0, : ROP_DPa, : ROP_PDna, : ROP_P, : ROP_DPna, : ROP_D, : ROP_DPx, : ROP_DPo, : ROP_DPon, : ROP_PDxn, : ROP_Dn, : ROP_PDno, : ROP_Pn, : ROP_DPno, : ROP_DPan, : ROP_1 :}; : :/** : * I830EXASync - wait for a command to finish : * @pScreen: current screen : * @marker: marker command to wait for : * : * Wait for the command specified by @marker to finish, then return. We don't : * actually do marker waits, though we might in the future. For now, just : * wait for a full idle. : */ :static void :I830EXASync(ScreenPtr pScreen, int marker) 4 0.0044 :{ /* I830EXASync total: 19 0.0207 */ : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : 3 0.0033 : I830Sync(pScrn); 12 0.0131 :} : :/** : * I830EXAPrepareSolid - prepare for a Solid operation, if possible : */ :static Bool :I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) :{ /* I830EXAPrepareSolid total: 10 0.0109 */ : ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 2 0.0022 : I830Ptr pI830 = I830PTR(pScrn); : unsigned long offset, pitch; : 1 0.0011 : if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask)) : I830FALLBACK("planemask is not solid"); : : if (pPixmap->drawable.bitsPerPixel == 24) : I830FALLBACK("solid 24bpp unsupported!\n"); : : offset = exaGetPixmapOffset(pPixmap); : pitch = exaGetPixmapPitch(pPixmap); : 4 0.0044 : if ( offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0) : I830FALLBACK("pixmap offset not aligned"); 1 0.0011 : if ( pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0) : I830FALLBACK("pixmap pitch not aligned"); : 1 0.0011 : pI830->BR[13] = (pitch & 0xffff); : switch (pPixmap->drawable.bitsPerPixel) { : case 8: : break; : case 16: : /* RGB565 */ : pI830->BR[13] |= (1 << 24); : break; : case 32: : /* RGB8888 */ 1 0.0011 : pI830->BR[13] |= ((1 << 24) | (1 << 25)); : break; : } : pI830->BR[13] |= (I830PatternROP[alu] & 0xff) << 16 ; : pI830->BR[16] = fg; : return TRUE; :} : :static void :I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 2 0.0022 :{ /* I830EXASolid total: 38 0.0414 */ : ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : unsigned long offset; : 1 0.0011 : offset = exaGetPixmapOffset(pPixmap); : : { 1 0.0011 : BEGIN_LP_RING(6); : if (pPixmap->drawable.bitsPerPixel == 32) 4 0.0044 : OUT_RING(XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA : | XY_COLOR_BLT_WRITE_RGB); : else : OUT_RING(XY_COLOR_BLT_CMD); : 1 0.0011 : OUT_RING(pI830->BR[13]); 3 0.0033 : OUT_RING((y1 << 16) | (x1 & 0xffff)); : OUT_RING((y2 << 16) | (x2 & 0xffff)); : OUT_RING(offset); : OUT_RING(pI830->BR[16]); 3 0.0033 : ADVANCE_LP_RING(); : } 23 0.0251 :} : :static void :I830EXADoneSolid(PixmapPtr pPixmap) :{ :#if ALWAYS_SYNC : ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; : : I830Sync(pScrn); :#endif :} : :/** : * TODO: : * - support planemask using FULL_BLT_CMD? : */ :static Bool :I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, : int ydir, int alu, Pixel planemask) :{ : ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : : if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask)) : I830FALLBACK("planemask is not solid"); : : pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap); : pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap); : : pI830->BR[13] = exaGetPixmapPitch(pDstPixmap); : pI830->BR[13] |= I830CopyROP[alu] << 16; : : switch (pSrcPixmap->drawable.bitsPerPixel) { : case 8: : break; : case 16: : pI830->BR[13] |= (1 << 24); : break; : case 32: : pI830->BR[13] |= ((1 << 25) | (1 << 24)); : break; : } : return TRUE; :} : :static void :I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1, : int dst_y1, int w, int h) :{ : ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : int dst_x2, dst_y2; : unsigned int dst_off; : : dst_x2 = dst_x1 + w; : dst_y2 = dst_y1 + h; : : dst_off = exaGetPixmapOffset(pDstPixmap); : : { : BEGIN_LP_RING(8); : : if (pDstPixmap->drawable.bitsPerPixel == 32) : OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | : XY_SRC_COPY_BLT_WRITE_RGB); : else : OUT_RING(XY_SRC_COPY_BLT_CMD); : : OUT_RING(pI830->BR[13]); : OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff)); : OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff)); : OUT_RING(dst_off); : OUT_RING((src_y1 << 16) | (src_x1 & 0xffff)); : OUT_RING(pI830->copy_src_pitch); : OUT_RING(pI830->copy_src_off); : : ADVANCE_LP_RING(); : } :} : :static void :I830EXADoneCopy(PixmapPtr pDstPixmap) :{ :#if ALWAYS_SYNC : ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; : : I830Sync(pScrn); :#endif :} : :#define xFixedToFloat(val) \ : ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)) : :/** : * Returns the floating-point coordinates transformed by the given transform. : * : * transform may be null. : */ :void :i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform, : float *x_out, float *y_out) 68 0.0741 :{ /* i830_get_transformed_coordinates total: 187 0.2037 */ 13 0.0142 : if (transform == NULL) { 39 0.0425 : *x_out = x; 35 0.0381 : *y_out = y; : } else { : PictVector v; : : v.vector[0] = IntToxFixed(x); : v.vector[1] = IntToxFixed(y); : v.vector[2] = xFixed1; : PictureTransformPoint(transform, &v); : *x_out = xFixedToFloat(v.vector[0]); : *y_out = xFixedToFloat(v.vector[1]); : } 32 0.0349 :} : :/** : * Uploads data from system memory to the framebuffer using a series of : * 8x8 pattern blits. : */ :static Bool :i830_upload_to_screen(PixmapPtr pDst, int x, int y, int w, int h, char *src, : int src_pitch) :{ : ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : const int uts_width_max = 16, uts_height_max = 16; : int cpp = pDst->drawable.bitsPerPixel / 8; : int sub_x, sub_y; : CARD32 br13; : CARD32 offset; : : if (w > uts_width_max || h > uts_height_max) : I830FALLBACK("too large for upload to screen (%d,%d)", w, h); : : offset = exaGetPixmapOffset(pDst); : : br13 = exaGetPixmapPitch(pDst); : br13 |= ((I830PatternROP[GXcopy] & 0xff) << 16); : switch (pDst->drawable.bitsPerPixel) { : case 16: : br13 |= 1 << 24; : break; : case 32: : br13 |= 3 << 24; : break; : } : : for (sub_y = 0; sub_y < uts_height_max && sub_y < h; sub_y += 8) { : int sub_height; : : if (sub_y + 8 > h) : sub_height = h - sub_y; : else : sub_height = 8; : : for (sub_x = 0; sub_x < uts_width_max && sub_x < w; sub_x += 8) { : int sub_width, line; : char *src_line = src + sub_y * src_pitch + sub_x * cpp; : : if (sub_x + 8 > w) : sub_width = w - sub_x; : else : sub_width = 8; : : BEGIN_LP_RING(6 + (cpp * 8 * 8 / 4)); : : /* XXX We may need a pattern offset here for {x,y} % 8 != 0*/ : OUT_RING(XY_PAT_BLT_IMMEDIATE | : XY_SRC_COPY_BLT_WRITE_ALPHA | : XY_SRC_COPY_BLT_WRITE_RGB | : (3 + cpp * 8 * 8 / 4)); : OUT_RING(br13); : OUT_RING(((y + sub_y) << 16) | (x + sub_x)); : OUT_RING(((y + sub_y + sub_height) << 16) | : (x + sub_x + sub_width)); : OUT_RING(offset); : : /* Write out the lines with valid data, followed by any needed : * padding : */ : for (line = 0; line < sub_height; line++) { : OUT_RING_COPY(sub_width * cpp, src_line); : src_line += src_pitch; : if (sub_width != 8) : OUT_RING_PAD((8 - sub_width) * cpp); : } : /* Write out any full padding lines to follow */ : if (sub_height != 8) : OUT_RING_PAD(8 * cpp * (8 - sub_height)); : : OUT_RING(MI_NOOP); : ADVANCE_LP_RING(); : } : } : : exaMarkSync(pDst->drawable.pScreen); : /* exaWaitSync(pDst->drawable.pScreen); */ : : return TRUE; :} : : :/* : * TODO: : * - Dual head? : */ :Bool :I830EXAInit(ScreenPtr pScreen) :{ : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : : pI830->EXADriverPtr = exaDriverAlloc(); : if (pI830->EXADriverPtr == NULL) { : pI830->noAccel = TRUE; : return FALSE; : } : memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr)); : : pI830->bufferOffset = 0; : pI830->EXADriverPtr->exa_major = 2; : pI830->EXADriverPtr->exa_minor = 1; : pI830->EXADriverPtr->memoryBase = pI830->FbBase; : pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset; : pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset + : pI830->exa_offscreen->size; : pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS; : : DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n", : pI830->EXADriverPtr->memoryBase, : pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize, : pI830->EXADriverPtr->offScreenBase, : pI830->EXADriverPtr->memorySize); : : : /* Limits are described in the BLT engine chapter under Graphics Data Size : * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO, : * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO. : * : * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768. : * : * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled. : * i965 limits 3D surface to 4kB-aligned offset if tiled. : * i965 limits 3D surfaces to w,h of ?,8192. : * i965 limits 3D surface to pitch of 1B - 128kB. : * i965 limits 3D surface pitch alignment to 1 or 2 times the element size. : * i965 limits 3D surface pitch alignment to 512B if tiled. : * i965 limits 3D destination drawing rect to w,h of 8192,8192. : * : * i915 limits 3D textures to 4B-aligned offset if un-tiled. : * i915 limits 3D textures to ~4kB-aligned offset if tiled. : * i915 limits 3D textures to width,height of 2048,2048. : * i915 limits 3D textures to pitch of 16B - 8kB, in dwords. : * i915 limits 3D destination to ~4kB-aligned offset if tiled. : * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled. : * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled. : * i915 limits 3D destination to POT aligned pitch if tiled. : * i915 limits 3D destination drawing rect to w,h of 2048,2048. : * : * i845 limits 3D textures to 4B-aligned offset if un-tiled. : * i845 limits 3D textures to ~4kB-aligned offset if tiled. : * i845 limits 3D textures to width,height of 2048,2048. : * i845 limits 3D textures to pitch of 4B - 8kB, in dwords. : * i845 limits 3D destination to 4B-aligned offset if un-tiled. : * i845 limits 3D destination to ~4kB-aligned offset if tiled. : * i845 limits 3D destination to pitch of 8B - 8kB, in dwords. : * i845 limits 3D destination drawing rect to w,h of 2048,2048. : * : * For the tiled issues, the only tiled buffer we draw to should be : * the front, which will have an appropriate pitch/offset already set up, : * so EXA doesn't need to worry. : */ : if (IS_I965G(pI830)) { : pI830->EXADriverPtr->pixmapOffsetAlign = 4 * 2; : pI830->EXADriverPtr->pixmapPitchAlign = 16; : pI830->EXADriverPtr->maxX = 8192; : pI830->EXADriverPtr->maxY = 8192; : } else { : pI830->EXADriverPtr->pixmapOffsetAlign = 4; : pI830->EXADriverPtr->pixmapPitchAlign = 16; : pI830->EXADriverPtr->maxX = 2048; : pI830->EXADriverPtr->maxY = 2048; : } : : /* Sync */ : pI830->EXADriverPtr->WaitMarker = I830EXASync; : : /* Solid fill */ : pI830->EXADriverPtr->PrepareSolid = I830EXAPrepareSolid; : pI830->EXADriverPtr->Solid = I830EXASolid; : pI830->EXADriverPtr->DoneSolid = I830EXADoneSolid; : : /* Copy */ : pI830->EXADriverPtr->PrepareCopy = I830EXAPrepareCopy; : pI830->EXADriverPtr->Copy = I830EXACopy; : pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy; : : /* Composite */ : if (!IS_I9XX(pI830)) { : pI830->EXADriverPtr->CheckComposite = i830_check_composite; : pI830->EXADriverPtr->PrepareComposite = i830_prepare_composite; : pI830->EXADriverPtr->Composite = i830_composite; : pI830->EXADriverPtr->DoneComposite = i830_done_composite; : } else if (IS_I915G(pI830) || IS_I915GM(pI830) || : IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) : { : pI830->EXADriverPtr->CheckComposite = i915_check_composite; : pI830->EXADriverPtr->PrepareComposite = i915_prepare_composite; : pI830->EXADriverPtr->Composite = i830_composite; : pI830->EXADriverPtr->DoneComposite = i830_done_composite; : } else { : pI830->EXADriverPtr->CheckComposite = i965_check_composite; : pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite; : pI830->EXADriverPtr->Composite = i965_composite; : pI830->EXADriverPtr->DoneComposite = i830_done_composite; : } : : /* UploadToScreen/DownloadFromScreen */ : if (0) : pI830->EXADriverPtr->UploadToScreen = i830_upload_to_screen; : : if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) { : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "EXA initialization failed; trying older version\n"); : pI830->EXADriverPtr->exa_minor = 0; : if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) { : xfree(pI830->EXADriverPtr); : pI830->noAccel = TRUE; : return FALSE; : } : } : : I830SelectBuffer(pScrn, I830_SELECT_FRONT); : : return TRUE; :} : :#ifdef XF86DRI : :#ifndef ExaOffscreenMarkUsed :extern void ExaOffscreenMarkUsed(PixmapPtr); :#endif : :unsigned long long :I830TexOffsetStart(PixmapPtr pPix) :{ : exaMoveInPixmap(pPix); : ExaOffscreenMarkUsed(pPix); : : return exaGetPixmapOffset(pPix); :} :#endif /* * Total samples for file : "/home/cworth/src/xorg/xserver/miext/damage/damage.c" * * 191 0.2081 */ :/* : * Copyright © 2003 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include : :#include :#include "scrnintstr.h" :#include "windowstr.h" :#include :#include "dixfontstr.h" :#include :#include "mi.h" :#include "regionstr.h" :#include "globals.h" :#include "gcstruct.h" :#include "damage.h" :#include "damagestr.h" :#ifdef COMPOSITE :#include "cw.h" :#endif : :#define wrap(priv, real, mem, func) {\ : priv->mem = real->mem; \ : real->mem = func; \ :} : :#define unwrap(priv, real, mem) {\ : real->mem = priv->mem; \ :} : :#define BOX_SAME(a,b) \ : ((a)->x1 == (b)->x1 && \ : (a)->y1 == (b)->y1 && \ : (a)->x2 == (b)->x2 && \ : (a)->y2 == (b)->y2) : :#define DAMAGE_VALIDATE_ENABLE 0 :#define DAMAGE_DEBUG_ENABLE 0 :#if DAMAGE_DEBUG_ENABLE :#define DAMAGE_DEBUG(x) ErrorF x :#else :#define DAMAGE_DEBUG(x) :#endif : :#define getPixmapDamageRef(pPixmap) \ : ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr)) : :#define pixmapDamage(pPixmap) damagePixPriv(pPixmap) : :static int damageScrPrivateIndex; :static int damagePixPrivateIndex; :static int damageGCPrivateIndex; :static int damageWinPrivateIndex; :static int damageGeneration; : :static DamagePtr * :getDrawableDamageRef (DrawablePtr pDrawable) 2 0.0022 :{ /* getDrawableDamageRef total: 6 0.0065 */ : PixmapPtr pPixmap; : : if (pDrawable->type == DRAWABLE_WINDOW) : { : ScreenPtr pScreen = pDrawable->pScreen; : : pPixmap = 0; : if (pScreen->GetWindowPixmap :#ifdef ROOTLESS_WORKAROUND : && ((WindowPtr)pDrawable)->viewable :#endif : ) : pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable); : : if (!pPixmap) : { : damageScrPriv(pScreen); : : return &pScrPriv->pScreenDamage; : } : } : else : pPixmap = (PixmapPtr) pDrawable; : return getPixmapDamageRef (pPixmap); 4 0.0044 :} : :#define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable)) :#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable) : :#define drawableDamage(pDrawable) \ : DamagePtr pDamage = getDrawableDamage(pDrawable) : :#define windowDamage(pWin) drawableDamage(&(pWin)->drawable) : :#define winDamageRef(pWindow) \ : DamagePtr *pPrev = (DamagePtr *) \ : &(pWindow->devPrivates[damageWinPrivateIndex].ptr) : :static void :DamageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion) 1 0.0011 :{ /* DamageReportDamage total: 4 0.0044 */ : BoxRec tmpBox; : RegionRec tmpRegion; : Bool was_empty; : : switch (pDamage->damageLevel) { : case DamageReportRawRegion: : (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); : break; : case DamageReportDeltaRegion: : REGION_NULL (pScreen, &tmpRegion); : REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage); : if (REGION_NOTEMPTY (pScreen, &tmpRegion)) { : REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, : pDamageRegion); : (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); : } : REGION_UNINIT(pScreen, &tmpRegion); : break; : case DamageReportBoundingBox: : tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage); : REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, : pDamageRegion); : if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) { : (*pDamage->damageReport) (pDamage, &pDamage->damage, : pDamage->closure); : } : break; : case DamageReportNonEmpty: : was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage); 1 0.0011 : REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, : pDamageRegion); : if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) { : (*pDamage->damageReport) (pDamage, &pDamage->damage, : pDamage->closure); : } : break; : case DamageReportNone: : REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, : pDamageRegion); : break; : } 2 0.0022 :} : :#if DAMAGE_DEBUG_ENABLE :static void :_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) :#define damageDamageRegion(d,r,c,m) _damageDamageRegion(d,r,c,m,__FUNCTION__) :#else :static void :damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, : int subWindowMode) :#endif 1 0.0011 :{ /* damageDamageRegion total: 21 0.0229 */ : ScreenPtr pScreen = pDrawable->pScreen; : damageScrPriv(pScreen); : drawableDamage(pDrawable); : DamagePtr pNext; : RegionRec clippedRec; : RegionPtr pDamageRegion; : RegionRec pixClip; : int draw_x, draw_y; :#ifdef COMPOSITE : int screen_x = 0, screen_y = 0; :#endif : : /* short circuit for empty regions */ 1 0.0011 : if (!REGION_NOTEMPTY(pScreen, pRegion)) : return; : :#ifdef COMPOSITE : /* : * When drawing to a pixmap which is storing window contents, : * the region presented is in pixmap relative coordinates which : * need to be converted to screen relative coordinates : */ : if (pDrawable->type != DRAWABLE_WINDOW) : { : screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x; 2 0.0022 : screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y; : } 2 0.0022 : if (screen_x || screen_y) : REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y); :#endif : : if (pDrawable->type == DRAWABLE_WINDOW && : ((WindowPtr)(pDrawable))->backingStore == NotUseful) : { : if (subWindowMode == ClipByChildren) : { : REGION_INTERSECT(pScreen, pRegion, pRegion, : &((WindowPtr)(pDrawable))->clipList); : } : else if (subWindowMode == IncludeInferiors) : { : RegionPtr pTempRegion = : NotClippedByChildren((WindowPtr)(pDrawable)); : REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion); : REGION_DESTROY(pScreen, pTempRegion); : } : /* If subWindowMode is set to an invalid value, don't perform : * any drawable-based clipping. */ : } : : 2 0.0022 : REGION_NULL (pScreen, &clippedRec); 1 0.0011 : for (; pDamage; pDamage = pNext) : { 1 0.0011 : pNext = pDamage->pNext; : /* : * Check for internal damage and don't send events : */ 1 0.0011 : if (pScrPriv->internalLevel > 0 && !pDamage->isInternal) : { : DAMAGE_DEBUG (("non internal damage, skipping at %d\n", : pScrPriv->internalLevel)); : continue; : } : /* : * Check for unrealized windows : */ 1 0.0011 : if (pDamage->pDrawable->type == DRAWABLE_WINDOW && : !((WindowPtr) (pDamage->pDrawable))->realized) : { :#if 0 : DAMAGE_DEBUG (("damage while window unrealized\n")); :#endif : continue; : } : 1 0.0011 : draw_x = pDamage->pDrawable->x; : draw_y = pDamage->pDrawable->y; :#ifdef COMPOSITE : /* : * Need to move everyone to screen coordinates : * XXX what about off-screen pixmaps with non-zero x/y? : */ : if (pDamage->pDrawable->type != DRAWABLE_WINDOW) : { : draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x; : draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y; : } :#endif : : /* : * Clip against border or pixmap bounds : */ : : pDamageRegion = pRegion; : if (clip || pDamage->pDrawable != pDrawable) : { : pDamageRegion = &clippedRec; : if (pDamage->pDrawable->type == DRAWABLE_WINDOW) { : REGION_INTERSECT (pScreen, pDamageRegion, pRegion, : &((WindowPtr)(pDamage->pDrawable))->borderClip); : } else { : BoxRec box; : box.x1 = draw_x; : box.y1 = draw_y; : box.x2 = draw_x + pDamage->pDrawable->width; : box.y2 = draw_y + pDamage->pDrawable->height; 1 0.0011 : REGION_INIT(pScreen, &pixClip, &box, 1); : REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip); 2 0.0022 : REGION_UNINIT(pScreen, &pixClip); : } : /* : * Short circuit empty results : */ : if (!REGION_NOTEMPTY(pScreen, pDamageRegion)) : continue; : } : : DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n", : where, : pDamageRegion->extents.x2 - pDamageRegion->extents.x1, : pDamageRegion->extents.y2 - pDamageRegion->extents.y1, : pDamageRegion->extents.x1, pDamageRegion->extents.y1, : pDrawable->id, pDamage->pDrawable->id)); : : /* : * Move region to target coordinate space : */ : if (draw_x || draw_y) : REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); : : /* If the damage rec has been flagged to report damage after the op has : * completed, then union it into the delayed damage region, which will : * be used for reporting after calling down, and skip the reporting : */ 1 0.0011 : if (!pDamage->reportAfter) { : DamageReportDamage (pDamage, pDamageRegion); : } else { 1 0.0011 : REGION_UNION(pScreen, &pDamage->pendingDamage, : &pDamage->pendingDamage, pDamageRegion); : } : : /* : * translate original region back : */ 1 0.0011 : if (pDamageRegion == pRegion && (draw_x || draw_y)) : REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y); : } :#ifdef COMPOSITE : if (screen_x || screen_y) : REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y); :#endif : : REGION_UNINIT (pScreen, &clippedRec); 2 0.0022 :} : :static void :damageReportPostOp (DrawablePtr pDrawable) :{ /* damageReportPostOp total: 3 0.0033 */ : drawableDamage(pDrawable); : : for (; pDamage != NULL; pDamage = pDamage->pNext) : { 2 0.0022 : if (pDamage->reportAfter) { : DamageReportDamage (pDamage, &pDamage->pendingDamage); 1 0.0011 : REGION_EMPTY (pScreen, &pDamage->pendingDamage); : } : } : :} : :#if DAMAGE_DEBUG_ENABLE :#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) :static void :_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where) :#else :static void :damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode) :#endif 2 0.0022 :{ /* damageDamageBox total: 3 0.0033 */ : RegionRec region; : : REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1); :#if DAMAGE_DEBUG_ENABLE : _damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode, where); :#else 1 0.0011 : damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode); :#endif : REGION_UNINIT (pDrawable->pScreen, ®ion); :} : :static void damageValidateGC(GCPtr, unsigned long, DrawablePtr); :static void damageChangeGC(GCPtr, unsigned long); :static void damageCopyGC(GCPtr, unsigned long, GCPtr); :static void damageDestroyGC(GCPtr); :static void damageChangeClip(GCPtr, int, pointer, int); :static void damageDestroyClip(GCPtr); :static void damageCopyClip(GCPtr, GCPtr); : :static GCFuncs damageGCFuncs = { : damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, : damageChangeClip, damageDestroyClip, damageCopyClip :}; : :static GCOps damageGCOps; : :static Bool :damageCreateGC(GCPtr pGC) :{ : ScreenPtr pScreen = pGC->pScreen; : damageScrPriv(pScreen); : damageGCPriv(pGC); : Bool ret; : : pGC->pCompositeClip = 0; : unwrap (pScrPriv, pScreen, CreateGC); : if((ret = (*pScreen->CreateGC) (pGC))) { : pGCPriv->ops = NULL; : pGCPriv->funcs = pGC->funcs; : pGC->funcs = &damageGCFuncs; : } : wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); : : return ret; :} : :#ifdef NOTUSED :static void :damageWrapGC (GCPtr pGC) :{ : damageGCPriv(pGC); : : pGCPriv->ops = NULL; : pGCPriv->funcs = pGC->funcs; : pGC->funcs = &damageGCFuncs; :} : :static void :damageUnwrapGC (GCPtr pGC) :{ : damageGCPriv(pGC); : : pGC->funcs = pGCPriv->funcs; : if (pGCPriv->ops) : pGC->ops = pGCPriv->ops; :} :#endif : :#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \ : damageGCPriv(pGC); \ : GCFuncs *oldFuncs = pGC->funcs; \ : unwrap(pGCPriv, pGC, funcs); \ : unwrap(pGCPriv, pGC, ops); \ : :#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \ : wrap(pGCPriv, pGC, funcs, oldFuncs); \ : wrap(pGCPriv, pGC, ops, &damageGCOps) : :#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \ : damageGCPriv(pGC); \ : unwrap(pGCPriv, pGC, funcs); \ : if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops) : :#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \ : wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \ : if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps) : :static void :damageValidateGC(GCPtr pGC, : unsigned long changes, : DrawablePtr pDrawable) 2 0.0022 :{ /* damageValidateGC total: 7 0.0076 */ 1 0.0011 : DAMAGE_GC_FUNC_PROLOGUE (pGC); 1 0.0011 : (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); : pGCPriv->ops = pGC->ops; /* just so it's not NULL */ 3 0.0033 : DAMAGE_GC_FUNC_EPILOGUE (pGC); :} : :static void :damageDestroyGC(GCPtr pGC) :{ : DAMAGE_GC_FUNC_PROLOGUE (pGC); : (*pGC->funcs->DestroyGC)(pGC); : DAMAGE_GC_FUNC_EPILOGUE (pGC); :} : :static void :damageChangeGC (GCPtr pGC, : unsigned long mask) 2 0.0022 :{ /* damageChangeGC total: 9 0.0098 */ 4 0.0044 : DAMAGE_GC_FUNC_PROLOGUE (pGC); 1 0.0011 : (*pGC->funcs->ChangeGC) (pGC, mask); 2 0.0022 : DAMAGE_GC_FUNC_EPILOGUE (pGC); :} : :static void :damageCopyGC (GCPtr pGCSrc, : unsigned long mask, : GCPtr pGCDst) :{ : DAMAGE_GC_FUNC_PROLOGUE (pGCDst); : (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); : DAMAGE_GC_FUNC_EPILOGUE (pGCDst); :} : :static void :damageChangeClip (GCPtr pGC, : int type, : pointer pvalue, : int nrects) 1 0.0011 :{ /* damageChangeClip total: 1 0.0011 */ : DAMAGE_GC_FUNC_PROLOGUE (pGC); : (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); : DAMAGE_GC_FUNC_EPILOGUE (pGC); :} : :static void :damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc) :{ : DAMAGE_GC_FUNC_PROLOGUE (pgcDst); : (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); : DAMAGE_GC_FUNC_EPILOGUE (pgcDst); :} : :static void :damageDestroyClip(GCPtr pGC) :{ : DAMAGE_GC_FUNC_PROLOGUE (pGC); : (* pGC->funcs->DestroyClip)(pGC); : DAMAGE_GC_FUNC_EPILOGUE (pGC); :} : :#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \ : BoxPtr extents = &pGC->pCompositeClip->extents;\ : if(box.x1 < extents->x1) box.x1 = extents->x1; \ : if(box.x2 > extents->x2) box.x2 = extents->x2; \ : if(box.y1 < extents->y1) box.y1 = extents->y1; \ : if(box.y2 > extents->y2) box.y2 = extents->y2; \ : } : :#define TRANSLATE_BOX(box, pDrawable) { \ : box.x1 += pDrawable->x; \ : box.x2 += pDrawable->x; \ : box.y1 += pDrawable->y; \ : box.y2 += pDrawable->y; \ : } : :#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \ : TRANSLATE_BOX(box, pDrawable); \ : TRIM_BOX(box, pGC); \ : } : :#define BOX_NOT_EMPTY(box) \ : (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) : :#define checkGCDamage(d,g) (getDrawableDamage(d) && \ : (!g->pCompositeClip ||\ : REGION_NOTEMPTY(d->pScreen, \ : g->pCompositeClip))) : :#ifdef RENDER : :#define TRIM_PICTURE_BOX(box, pDst) { \ : BoxPtr extents = &pDst->pCompositeClip->extents;\ : if(box.x1 < extents->x1) box.x1 = extents->x1; \ : if(box.x2 > extents->x2) box.x2 = extents->x2; \ : if(box.y1 < extents->y1) box.y1 = extents->y1; \ : if(box.y2 > extents->y2) box.y2 = extents->y2; \ : } : :#define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \ : REGION_NOTEMPTY(pScreen, p->pCompositeClip)) : :static void :damageComposite (CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) 1 0.0011 :{ /* damageComposite total: 6 0.0065 */ : ScreenPtr pScreen = pDst->pDrawable->pScreen; : PictureScreenPtr ps = GetPictureScreen(pScreen); : damageScrPriv(pScreen); : 1 0.0011 : if (checkPictureDamage (pDst)) : { : BoxRec box; : : box.x1 = xDst + pDst->pDrawable->x; : box.y1 = yDst + pDst->pDrawable->y; : box.x2 = box.x1 + width; : box.y2 = box.y1 + height; : TRIM_PICTURE_BOX(box, pDst); : if (BOX_NOT_EMPTY(box)) 1 0.0011 : damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); : } : unwrap (pScrPriv, ps, Composite); : (*ps->Composite) (op, : pSrc, : pMask, : pDst, : xSrc, : ySrc, : xMask, : yMask, : xDst, : yDst, : width, : height); 3 0.0033 : damageReportPostOp (pDst->pDrawable); : wrap (pScrPriv, ps, Composite, damageComposite); :} : :static void :damageGlyphs (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int nlist, : GlyphListPtr list, : GlyphPtr *glyphs) :{ /* damageGlyphs total: 61 0.0665 */ : ScreenPtr pScreen = pDst->pDrawable->pScreen; : PictureScreenPtr ps = GetPictureScreen(pScreen); : damageScrPriv(pScreen); : : if (checkPictureDamage (pDst)) : { : int nlistTmp = nlist; : GlyphListPtr listTmp = list; : GlyphPtr *glyphsTmp = glyphs; : int x, y; : int n; : GlyphPtr glyph; : BoxRec box; : int x1, y1, x2, y2; : : box.x1 = 32767; : box.y1 = 32767; : box.x2 = -32767; : box.y2 = -32767; : x = pDst->pDrawable->x; : y = pDst->pDrawable->y; 1 0.0011 : while (nlistTmp--) : { 1 0.0011 : x += listTmp->xOff; : y += listTmp->yOff; : n = listTmp->len; 1 0.0011 : while (n--) : { 2 0.0022 : glyph = *glyphsTmp++; 31 0.0338 : x1 = x - glyph->info.x; 3 0.0033 : y1 = y - glyph->info.y; 1 0.0011 : x2 = x1 + glyph->info.width; 1 0.0011 : y2 = y1 + glyph->info.height; : if (x1 < box.x1) : box.x1 = x1; 1 0.0011 : if (y1 < box.y1) : box.y1 = y1; 5 0.0054 : if (x2 > box.x2) 2 0.0022 : box.x2 = x2; 2 0.0022 : if (y2 > box.y2) 1 0.0011 : box.y2 = y2; 2 0.0022 : x += glyph->info.xOff; 2 0.0022 : y += glyph->info.yOff; : } : listTmp++; : } 1 0.0011 : TRIM_PICTURE_BOX (box, pDst); : if (BOX_NOT_EMPTY(box)) 1 0.0011 : damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); : } 1 0.0011 : unwrap (pScrPriv, ps, Glyphs); 1 0.0011 : (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); : damageReportPostOp (pDst->pDrawable); : wrap (pScrPriv, ps, Glyphs, damageGlyphs); 1 0.0011 :} :#endif : :/**********************************************************/ : : :static void :damageFillSpans(DrawablePtr pDrawable, : GC *pGC, : int npt, : DDXPointPtr ppt, : int *pwidth, : int fSorted) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (npt && checkGCDamage (pDrawable, pGC)) : { : int nptTmp = npt; : DDXPointPtr pptTmp = ppt; : int *pwidthTmp = pwidth; : BoxRec box; : : box.x1 = pptTmp->x; : box.x2 = box.x1 + *pwidthTmp; : box.y2 = box.y1 = pptTmp->y; : : while(--nptTmp) : { : pptTmp++; : pwidthTmp++; : if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; : if(box.x2 < (pptTmp->x + *pwidthTmp)) : box.x2 = pptTmp->x + *pwidthTmp; : if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; : else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; : } : : box.y2++; : : if(!pGC->miTranslate) { : TRANSLATE_BOX(box, pDrawable); : } : TRIM_BOX(box, pGC); : : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : : (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); : : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damageSetSpans(DrawablePtr pDrawable, : GCPtr pGC, : char *pcharsrc, : DDXPointPtr ppt, : int *pwidth, : int npt, : int fSorted) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (npt && checkGCDamage (pDrawable, pGC)) : { : DDXPointPtr pptTmp = ppt; : int *pwidthTmp = pwidth; : int nptTmp = npt; : BoxRec box; : : box.x1 = pptTmp->x; : box.x2 = box.x1 + *pwidthTmp; : box.y2 = box.y1 = pptTmp->y; : : while(--nptTmp) : { : pptTmp++; : pwidthTmp++; : if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; : if(box.x2 < (pptTmp->x + *pwidthTmp)) : box.x2 = pptTmp->x + *pwidthTmp; : if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; : else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; : } : : box.y2++; : : if(!pGC->miTranslate) { : TRANSLATE_BOX(box, pDrawable); : } : TRIM_BOX(box, pGC); : : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damagePutImage(DrawablePtr pDrawable, : GCPtr pGC, : int depth, : int x, : int y, : int w, : int h, : int leftPad, : int format, : char *pImage) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : if (checkGCDamage (pDrawable, pGC)) : { : BoxRec box; : : box.x1 = x + pDrawable->x; : box.x2 = box.x1 + w; : box.y1 = y + pDrawable->y; : box.y2 = box.y1 + h; : : TRIM_BOX(box, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, : leftPad, format, pImage); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static RegionPtr :damageCopyArea(DrawablePtr pSrc, : DrawablePtr pDst, : GC *pGC, : int srcx, : int srcy, : int width, : int height, : int dstx, : int dsty) :{ : RegionPtr ret; : DAMAGE_GC_OP_PROLOGUE(pGC, pDst); : : /* The driver will only call SourceValidate() when pSrc != pDst, : * but the software sprite (misprite.c) always need to know when a : * drawable is copied so it can remove the sprite. See #1030. */ : if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && : pSrc->type == DRAWABLE_WINDOW && : ((WindowPtr)pSrc)->viewable) : { : (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); : } : : if (checkGCDamage (pDst, pGC)) : { : BoxRec box; : : box.x1 = dstx + pDst->x; : box.x2 = box.x1 + width; : box.y1 = dsty + pDst->y; : box.y2 = box.y1 + height; : : TRIM_BOX(box, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDst, &box, pGC->subWindowMode); : } : : ret = (*pGC->ops->CopyArea)(pSrc, pDst, : pGC, srcx, srcy, width, height, dstx, dsty); : damageReportPostOp (pDst); : DAMAGE_GC_OP_EPILOGUE(pGC, pDst); : return ret; :} : :static RegionPtr :damageCopyPlane(DrawablePtr pSrc, : DrawablePtr pDst, : GCPtr pGC, : int srcx, : int srcy, : int width, : int height, : int dstx, : int dsty, : unsigned long bitPlane) :{ : RegionPtr ret; : DAMAGE_GC_OP_PROLOGUE(pGC, pDst); : : /* The driver will only call SourceValidate() when pSrc != pDst, : * but the software sprite (misprite.c) always need to know when a : * drawable is copied so it can remove the sprite. See #1030. */ : if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && : pSrc->type == DRAWABLE_WINDOW && : ((WindowPtr)pSrc)->viewable) : { : (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); : } : : if (checkGCDamage (pDst, pGC)) : { : BoxRec box; : : box.x1 = dstx + pDst->x; : box.x2 = box.x1 + width; : box.y1 = dsty + pDst->y; : box.y2 = box.y1 + height; : : TRIM_BOX(box, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDst, &box, pGC->subWindowMode); : } : : ret = (*pGC->ops->CopyPlane)(pSrc, pDst, : pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); : damageReportPostOp (pDst); : DAMAGE_GC_OP_EPILOGUE(pGC, pDst); : return ret; :} : :static void :damagePolyPoint(DrawablePtr pDrawable, : GCPtr pGC, : int mode, : int npt, : xPoint *ppt) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (npt && checkGCDamage (pDrawable, pGC)) : { : BoxRec box; : int nptTmp = npt; : xPoint *pptTmp = ppt; : : box.x2 = box.x1 = pptTmp->x; : box.y2 = box.y1 = pptTmp->y; : : /* this could be slow if the points were spread out */ : : while(--nptTmp) : { : pptTmp++; : if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; : else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; : if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; : else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; : } : : box.x2++; : box.y2++; : : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damagePolylines(DrawablePtr pDrawable, : GCPtr pGC, : int mode, : int npt, : DDXPointPtr ppt) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (npt && checkGCDamage (pDrawable, pGC)) : { : int nptTmp = npt; : DDXPointPtr pptTmp = ppt; : BoxRec box; : int extra = pGC->lineWidth >> 1; : : box.x2 = box.x1 = pptTmp->x; : box.y2 = box.y1 = pptTmp->y; : : if(nptTmp > 1) : { : if(pGC->joinStyle == JoinMiter) : extra = 6 * pGC->lineWidth; : else if(pGC->capStyle == CapProjecting) : extra = pGC->lineWidth; : } : : if(mode == CoordModePrevious) : { : int x = box.x1; : int y = box.y1; : while(--nptTmp) : { : pptTmp++; : x += pptTmp->x; : y += pptTmp->y; : if(box.x1 > x) box.x1 = x; : else if(box.x2 < x) box.x2 = x; : if(box.y1 > y) box.y1 = y; : else if(box.y2 < y) box.y2 = y; : } : } : else : { : while(--nptTmp) : { : pptTmp++; : if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; : else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; : if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; : else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; : } : } : : box.x2++; : box.y2++; : : if(extra) : { : box.x1 -= extra; : box.x2 += extra; : box.y1 -= extra; : box.y2 += extra; : } : : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damagePolySegment(DrawablePtr pDrawable, : GCPtr pGC, : int nSeg, : xSegment *pSeg) :{ /* damagePolySegment total: 1 0.0011 */ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (nSeg && checkGCDamage (pDrawable, pGC)) : { : BoxRec box; : int extra = pGC->lineWidth; : int nsegTmp = nSeg; : xSegment *pSegTmp = pSeg; : : if(pGC->capStyle != CapProjecting) : extra >>= 1; : : if(pSegTmp->x2 > pSegTmp->x1) { : box.x1 = pSegTmp->x1; : box.x2 = pSegTmp->x2; : } else { : box.x2 = pSegTmp->x1; : box.x1 = pSegTmp->x2; : } : : if(pSegTmp->y2 > pSegTmp->y1) { : box.y1 = pSegTmp->y1; : box.y2 = pSegTmp->y2; : } else { : box.y2 = pSegTmp->y1; : box.y1 = pSegTmp->y2; : } : : while(--nsegTmp) : { : pSegTmp++; : if(pSegTmp->x2 > pSegTmp->x1) : { : if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1; : if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2; : } : else : { : if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2; : if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1; : } : if(pSegTmp->y2 > pSegTmp->y1) : { : if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1; : if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2; : } : else : { : if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2; : if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1; : } : } : : box.x2++; : box.y2++; : : if(extra) : { : box.x1 -= extra; : box.x2 += extra; : box.y1 -= extra; : box.y2 += extra; : } : 1 0.0011 : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damagePolyRectangle(DrawablePtr pDrawable, : GCPtr pGC, : int nRects, : xRectangle *pRects) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (nRects && checkGCDamage (pDrawable, pGC)) : { : BoxRec box; : int offset1, offset2, offset3; : int nRectsTmp = nRects; : xRectangle *pRectsTmp = pRects; : : offset2 = pGC->lineWidth; : if(!offset2) offset2 = 1; : offset1 = offset2 >> 1; : offset3 = offset2 - offset1; : : while(nRectsTmp--) : { : box.x1 = pRectsTmp->x - offset1; : box.y1 = pRectsTmp->y - offset1; : box.x2 = box.x1 + pRectsTmp->width + offset2; : box.y2 = box.y1 + offset2; : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : : box.x1 = pRectsTmp->x - offset1; : box.y1 = pRectsTmp->y + offset3; : box.x2 = box.x1 + offset2; : box.y2 = box.y1 + pRectsTmp->height - offset2; : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : : box.x1 = pRectsTmp->x + pRectsTmp->width - offset1; : box.y1 = pRectsTmp->y + offset3; : box.x2 = box.x1 + offset2; : box.y2 = box.y1 + pRectsTmp->height - offset2; : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : : box.x1 = pRectsTmp->x - offset1; : box.y1 = pRectsTmp->y + pRectsTmp->height - offset1; : box.x2 = box.x1 + pRectsTmp->width + offset2; : box.y2 = box.y1 + offset2; : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : : pRectsTmp++; : } : } : (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damagePolyArc(DrawablePtr pDrawable, : GCPtr pGC, : int nArcs, : xArc *pArcs) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (nArcs && checkGCDamage (pDrawable, pGC)) : { : int extra = pGC->lineWidth >> 1; : BoxRec box; : int nArcsTmp = nArcs; : xArc *pArcsTmp = pArcs; : : box.x1 = pArcsTmp->x; : box.x2 = box.x1 + pArcsTmp->width; : box.y1 = pArcsTmp->y; : box.y2 = box.y1 + pArcsTmp->height; : : while(--nArcsTmp) : { : pArcsTmp++; : if(box.x1 > pArcsTmp->x) : box.x1 = pArcsTmp->x; : if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) : box.x2 = pArcsTmp->x + pArcsTmp->width; : if(box.y1 > pArcsTmp->y) : box.y1 = pArcsTmp->y; : if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) : box.y2 = pArcsTmp->y + pArcsTmp->height; : } : : if(extra) : { : box.x1 -= extra; : box.x2 += extra; : box.y1 -= extra; : box.y2 += extra; : } : : box.x2++; : box.y2++; : : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damageFillPolygon(DrawablePtr pDrawable, : GCPtr pGC, : int shape, : int mode, : int npt, : DDXPointPtr ppt) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (npt > 2 && checkGCDamage (pDrawable, pGC)) : { : DDXPointPtr pptTmp = ppt; : int nptTmp = npt; : BoxRec box; : : box.x2 = box.x1 = pptTmp->x; : box.y2 = box.y1 = pptTmp->y; : : if(mode != CoordModeOrigin) : { : int x = box.x1; : int y = box.y1; : while(--nptTmp) : { : pptTmp++; : x += pptTmp->x; : y += pptTmp->y; : if(box.x1 > x) box.x1 = x; : else if(box.x2 < x) box.x2 = x; : if(box.y1 > y) box.y1 = y; : else if(box.y2 < y) box.y2 = y; : } : } : else : { : while(--nptTmp) : { : pptTmp++; : if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; : else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; : if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; : else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; : } : } : : box.x2++; : box.y2++; : : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : : (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : : :static void :damagePolyFillRect(DrawablePtr pDrawable, : GCPtr pGC, : int nRects, : xRectangle *pRects) 2 0.0022 :{ /* damagePolyFillRect total: 17 0.0185 */ 2 0.0022 : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 2 0.0022 : if (nRects && checkGCDamage (pDrawable, pGC)) : { : BoxRec box; : xRectangle *pRectsTmp = pRects; : int nRectsTmp = nRects; : : box.x1 = pRectsTmp->x; : box.x2 = box.x1 + pRectsTmp->width; : box.y1 = pRectsTmp->y; : box.y2 = box.y1 + pRectsTmp->height; : 2 0.0022 : while(--nRectsTmp) : { : pRectsTmp++; : if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x; : if(box.x2 < (pRectsTmp->x + pRectsTmp->width)) : box.x2 = pRectsTmp->x + pRectsTmp->width; 1 0.0011 : if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y; : if(box.y2 < (pRectsTmp->y + pRectsTmp->height)) : box.y2 = pRectsTmp->y + pRectsTmp->height; : } : 4 0.0044 : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1 0.0011 : if(BOX_NOT_EMPTY(box)) 1 0.0011 : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } 1 0.0011 : (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); 1 0.0011 : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : : :static void :damagePolyFillArc(DrawablePtr pDrawable, : GCPtr pGC, : int nArcs, : xArc *pArcs) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (nArcs && checkGCDamage (pDrawable, pGC)) : { : BoxRec box; : int nArcsTmp = nArcs; : xArc *pArcsTmp = pArcs; : : box.x1 = pArcsTmp->x; : box.x2 = box.x1 + pArcsTmp->width; : box.y1 = pArcsTmp->y; : box.y2 = box.y1 + pArcsTmp->height; : : while(--nArcsTmp) : { : pArcsTmp++; : if(box.x1 > pArcsTmp->x) : box.x1 = pArcsTmp->x; : if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) : box.x2 = pArcsTmp->x + pArcsTmp->width; : if(box.y1 > pArcsTmp->y) : box.y1 = pArcsTmp->y; : if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) : box.y2 = pArcsTmp->y + pArcsTmp->height; : } : : TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :/* : * general Poly/Image text function. Extract glyph information, : * compute bounding box and remove cursor if it is overlapped. : */ : :static void :damageDamageChars (DrawablePtr pDrawable, : FontPtr font, : int x, : int y, : unsigned int n, : CharInfoPtr *charinfo, : Bool imageblt, : int subWindowMode) :{ : ExtentInfoRec extents; : BoxRec box; : : QueryGlyphExtents(font, charinfo, n, &extents); : if (imageblt) : { : if (extents.overallWidth > extents.overallRight) : extents.overallRight = extents.overallWidth; : if (extents.overallWidth < extents.overallLeft) : extents.overallLeft = extents.overallWidth; : if (extents.overallLeft > 0) : extents.overallLeft = 0; : if (extents.fontAscent > extents.overallAscent) : extents.overallAscent = extents.fontAscent; : if (extents.fontDescent > extents.overallDescent) : extents.overallDescent = extents.fontDescent; : } : box.x1 = x + extents.overallLeft; : box.y1 = y - extents.overallAscent; : box.x2 = x + extents.overallRight; : box.y2 = y + extents.overallDescent; : damageDamageBox (pDrawable, &box, subWindowMode); :} : :/* : * values for textType: : */ :#define TT_POLY8 0 :#define TT_IMAGE8 1 :#define TT_POLY16 2 :#define TT_IMAGE16 3 : :static int :damageText (DrawablePtr pDrawable, : GCPtr pGC, : int x, : int y, : unsigned long count, : char *chars, : FontEncoding fontEncoding, : Bool textType) :{ : CharInfoPtr *charinfo; : CharInfoPtr *info; : unsigned long i; : unsigned int n; : int w; : Bool imageblt; : : imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); : : charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); : if (!charinfo) : return x; : : GetGlyphs(pGC->font, count, (unsigned char *)chars, : fontEncoding, &i, charinfo); : n = (unsigned int)i; : w = 0; : if (!imageblt) : for (info = charinfo; i--; info++) : w += (*info)->metrics.characterWidth; : : if (n != 0) { : damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n, : charinfo, imageblt, pGC->subWindowMode); : if (imageblt) : (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, : FONTGLYPHS(pGC->font)); : else : (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, : FONTGLYPHS(pGC->font)); : } : DEALLOCATE_LOCAL(charinfo); : return x + w; :} : :static int :damagePolyText8(DrawablePtr pDrawable, : GCPtr pGC, : int x, : int y, : int count, : char *chars) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (checkGCDamage (pDrawable, pGC)) : x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, : Linear8Bit, TT_POLY8); : else : x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); : return x; :} : :static int :damagePolyText16(DrawablePtr pDrawable, : GCPtr pGC, : int x, : int y, : int count, : unsigned short *chars) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (checkGCDamage (pDrawable, pGC)) : x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, : FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, : TT_POLY16); : else : x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); : return x; :} : :static void :damageImageText8(DrawablePtr pDrawable, : GCPtr pGC, : int x, : int y, : int count, : char *chars) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (checkGCDamage (pDrawable, pGC)) : damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, : Linear8Bit, TT_IMAGE8); : else : (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damageImageText16(DrawablePtr pDrawable, : GCPtr pGC, : int x, : int y, : int count, : unsigned short *chars) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : : if (checkGCDamage (pDrawable, pGC)) : damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, : FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, : TT_IMAGE16); : else : (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : : :static void :damageImageGlyphBlt(DrawablePtr pDrawable, : GCPtr pGC, : int x, : int y, : unsigned int nglyph, : CharInfoPtr *ppci, : pointer pglyphBase) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, : nglyph, ppci, TRUE, pGC->subWindowMode); : (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, : ppci, pglyphBase); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damagePolyGlyphBlt(DrawablePtr pDrawable, : GCPtr pGC, : int x, : int y, : unsigned int nglyph, : CharInfoPtr *ppci, : pointer pglyphBase) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, : nglyph, ppci, FALSE, pGC->subWindowMode); : (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, : ppci, pglyphBase); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damagePushPixels(GCPtr pGC, : PixmapPtr pBitMap, : DrawablePtr pDrawable, : int dx, : int dy, : int xOrg, : int yOrg) :{ : DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); : if(checkGCDamage (pDrawable, pGC)) : { : BoxRec box; : : box.x1 = xOrg; : box.y1 = yOrg; : : if(!pGC->miTranslate) { : box.x1 += pDrawable->x; : box.y1 += pDrawable->y; : } : : box.x2 = box.x1 + dx; : box.y2 = box.y1 + dy; : : TRIM_BOX(box, pGC); : if(BOX_NOT_EMPTY(box)) : damageDamageBox (pDrawable, &box, pGC->subWindowMode); : } : (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); : damageReportPostOp (pDrawable); : DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); :} : :static void :damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage) 1 0.0011 :{ /* damageRemoveDamage total: 2 0.0022 */ : while (*pPrev) : { : if (*pPrev == pDamage) : { : *pPrev = pDamage->pNext; : return; : } : pPrev = &(*pPrev)->pNext; : } :#if DAMAGE_VALIDATE_ENABLE : ErrorF ("Damage not on list\n"); : abort (); :#endif 1 0.0011 :} : :static void :damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage) 1 0.0011 :{ /* damageInsertDamage total: 1 0.0011 */ :#if DAMAGE_VALIDATE_ENABLE : DamagePtr pOld; : : for (pOld = *pPrev; pOld; pOld = pOld->pNext) : if (pOld == pDamage) { : ErrorF ("Damage already on list\n"); : abort (); : } :#endif : pDamage->pNext = *pPrev; : *pPrev = pDamage; :} : :static Bool :damageDestroyPixmap (PixmapPtr pPixmap) 3 0.0033 :{ /* damageDestroyPixmap total: 15 0.0163 */ : ScreenPtr pScreen = pPixmap->drawable.pScreen; 2 0.0022 : damageScrPriv(pScreen); : : if (pPixmap->refcnt == 1) : { 1 0.0011 : DamagePtr *pPrev = getPixmapDamageRef (pPixmap); : DamagePtr pDamage; : : while ((pDamage = *pPrev)) : { : damageRemoveDamage (pPrev, pDamage); : if (!pDamage->isWindow) : DamageDestroy (pDamage); : } : } 3 0.0033 : unwrap (pScrPriv, pScreen, DestroyPixmap); 2 0.0022 : (*pScreen->DestroyPixmap) (pPixmap); 3 0.0033 : wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); : return TRUE; 1 0.0011 :} : :static void :damagePaintWindow(WindowPtr pWindow, : RegionPtr prgn, : int what) :{ : ScreenPtr pScreen = pWindow->drawable.pScreen; : damageScrPriv(pScreen); : : /* : * Painting background none doesn't actually *do* anything, so : * no damage is recorded : */ : if ((what != PW_BACKGROUND || pWindow->backgroundState != None) && : getWindowDamage (pWindow)) : damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1); : if(what == PW_BACKGROUND) { : unwrap (pScrPriv, pScreen, PaintWindowBackground); : (*pScreen->PaintWindowBackground) (pWindow, prgn, what); : damageReportPostOp (&pWindow->drawable); : wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); : } else { : unwrap (pScrPriv, pScreen, PaintWindowBorder); : (*pScreen->PaintWindowBorder) (pWindow, prgn, what); : damageReportPostOp (&pWindow->drawable); : wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); : } :} : : :static void :damageCopyWindow(WindowPtr pWindow, : DDXPointRec ptOldOrg, : RegionPtr prgnSrc) :{ : ScreenPtr pScreen = pWindow->drawable.pScreen; : damageScrPriv(pScreen); : : if (getWindowDamage (pWindow)) : { : int dx = pWindow->drawable.x - ptOldOrg.x; : int dy = pWindow->drawable.y - ptOldOrg.y; : : /* : * The region comes in source relative, but the damage occurs : * at the destination location. Translate back and forth. : */ : REGION_TRANSLATE (pScreen, prgnSrc, dx, dy); : damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE, -1); : REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); : } : unwrap (pScrPriv, pScreen, CopyWindow); : (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); : damageReportPostOp (&pWindow->drawable); : wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); :} : :static GCOps damageGCOps = { : damageFillSpans, damageSetSpans, : damagePutImage, damageCopyArea, : damageCopyPlane, damagePolyPoint, : damagePolylines, damagePolySegment, : damagePolyRectangle, damagePolyArc, : damageFillPolygon, damagePolyFillRect, : damagePolyFillArc, damagePolyText8, : damagePolyText16, damageImageText8, : damageImageText16, damageImageGlyphBlt, : damagePolyGlyphBlt, damagePushPixels, : {NULL} /* devPrivate */ :}; : :static void :damageRestoreAreas (PixmapPtr pPixmap, : RegionPtr prgn, : int xorg, : int yorg, : WindowPtr pWindow) :{ : ScreenPtr pScreen = pWindow->drawable.pScreen; : damageScrPriv(pScreen); : : damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1); : unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); : (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn, : xorg, yorg, pWindow); : damageReportPostOp (&pWindow->drawable); : wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, : damageRestoreAreas); :} : :static void :damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) :{ : DamagePtr pDamage; : ScreenPtr pScreen = pWindow->drawable.pScreen; : damageScrPriv(pScreen); : : if ((pDamage = damageGetWinPriv(pWindow))) : { : PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow); : DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap); : : while (pDamage) : { : damageRemoveDamage (pPrev, pDamage); : pDamage = pDamage->pNextWin; : } : } : unwrap (pScrPriv, pScreen, SetWindowPixmap); : (*pScreen->SetWindowPixmap) (pWindow, pPixmap); : wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); : if ((pDamage = damageGetWinPriv(pWindow))) : { : DamagePtr *pPrev = getPixmapDamageRef(pPixmap); : : while (pDamage) : { : damageInsertDamage (pPrev, pDamage); : pDamage = pDamage->pNextWin; : } : } :} : :static Bool :damageDestroyWindow (WindowPtr pWindow) :{ : DamagePtr pDamage; : ScreenPtr pScreen = pWindow->drawable.pScreen; : Bool ret; : damageScrPriv(pScreen); : : while ((pDamage = damageGetWinPriv(pWindow))) : { : DamageUnregister (&pWindow->drawable, pDamage); : DamageDestroy (pDamage); : } : unwrap (pScrPriv, pScreen, DestroyWindow); : ret = (*pScreen->DestroyWindow) (pWindow); : wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); : return ret; :} : :static Bool :damageCloseScreen (int i, ScreenPtr pScreen) :{ : damageScrPriv(pScreen); : : unwrap (pScrPriv, pScreen, DestroyPixmap); : unwrap (pScrPriv, pScreen, CreateGC); : unwrap (pScrPriv, pScreen, PaintWindowBackground); : unwrap (pScrPriv, pScreen, PaintWindowBorder); : unwrap (pScrPriv, pScreen, CopyWindow); : unwrap (pScrPriv, pScreen, CloseScreen); : unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); : xfree (pScrPriv); : return (*pScreen->CloseScreen) (i, pScreen); :} : :Bool :DamageSetup (ScreenPtr pScreen) :{ : DamageScrPrivPtr pScrPriv; :#ifdef RENDER : PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); :#endif : : if (damageGeneration != serverGeneration) : { : damageScrPrivateIndex = AllocateScreenPrivateIndex (); : if (damageScrPrivateIndex == -1) : return FALSE; : damageGCPrivateIndex = AllocateGCPrivateIndex (); : if (damageGCPrivateIndex == -1) : return FALSE; : damagePixPrivateIndex = AllocatePixmapPrivateIndex (); : if (damagePixPrivateIndex == -1) : return FALSE; : damageWinPrivateIndex = AllocateWindowPrivateIndex (); : if (damageWinPrivateIndex == -1) : return FALSE; : damageGeneration = serverGeneration; : } : if (pScreen->devPrivates[damageScrPrivateIndex].ptr) : return TRUE; : : if (!AllocateGCPrivate (pScreen, damageGCPrivateIndex, sizeof (DamageGCPrivRec))) : return FALSE; : if (!AllocatePixmapPrivate (pScreen, damagePixPrivateIndex, 0)) : return FALSE; : if (!AllocateWindowPrivate (pScreen, damageWinPrivateIndex, 0)) : return FALSE; : : pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec)); : if (!pScrPriv) : return FALSE; : : pScrPriv->internalLevel = 0; : pScrPriv->pScreenDamage = 0; : : wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); : wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); : wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); : wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); : wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); : wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); : wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); : wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); : wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, : damageRestoreAreas); :#ifdef RENDER : if (ps) { : wrap (pScrPriv, ps, Glyphs, damageGlyphs); : wrap (pScrPriv, ps, Composite, damageComposite); : } :#endif : : pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv; : return TRUE; :} : :DamagePtr :DamageCreate (DamageReportFunc damageReport, : DamageDestroyFunc damageDestroy, : DamageReportLevel damageLevel, : Bool isInternal, : ScreenPtr pScreen, : void *closure) 2 0.0022 :{ /* DamageCreate total: 12 0.0131 */ : DamagePtr pDamage; : 4 0.0044 : pDamage = xalloc (sizeof (DamageRec)); 1 0.0011 : if (!pDamage) : return 0; : pDamage->pNext = 0; : pDamage->pNextWin = 0; 3 0.0033 : REGION_NULL(pScreen, &pDamage->damage); : REGION_NULL(pScreen, &pDamage->pendingDamage); : : pDamage->damageLevel = damageLevel; 1 0.0011 : pDamage->isInternal = isInternal; : pDamage->closure = closure; : pDamage->isWindow = FALSE; : pDamage->pDrawable = 0; : pDamage->reportAfter = FALSE; : : pDamage->damageReport = damageReport; : pDamage->damageDestroy = damageDestroy; : return pDamage; 1 0.0011 :} : :void :DamageRegister (DrawablePtr pDrawable, : DamagePtr pDamage) 1 0.0011 :{ /* DamageRegister total: 1 0.0011 */ : if (pDrawable->type == DRAWABLE_WINDOW) : { : WindowPtr pWindow = (WindowPtr) pDrawable; : winDamageRef(pWindow); : :#if DAMAGE_VALIDATE_ENABLE : DamagePtr pOld; : : for (pOld = *pPrev; pOld; pOld = pOld->pNextWin) : if (pOld == pDamage) { : ErrorF ("Damage already on window list\n"); : abort (); : } :#endif : pDamage->pNextWin = *pPrev; : *pPrev = pDamage; : pDamage->isWindow = TRUE; : } : else : pDamage->isWindow = FALSE; : pDamage->pDrawable = pDrawable; : damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); :} : :void :DamageDrawInternal (ScreenPtr pScreen, Bool enable) :{ : damageScrPriv (pScreen); : : pScrPriv->internalLevel += enable ? 1 : -1; :} : :void :DamageUnregister (DrawablePtr pDrawable, : DamagePtr pDamage) :{ : if (pDrawable->type == DRAWABLE_WINDOW) : { : WindowPtr pWindow = (WindowPtr) pDrawable; : winDamageRef (pWindow); :#if DAMAGE_VALIDATE_ENABLE : int found = 0; :#endif : : while (*pPrev) : { : if (*pPrev == pDamage) : { : *pPrev = pDamage->pNextWin; :#if DAMAGE_VALIDATE_ENABLE : found = 1; :#endif : break; : } : pPrev = &(*pPrev)->pNextWin; : } :#if DAMAGE_VALIDATE_ENABLE : if (!found) { : ErrorF ("Damage not on window list\n"); : abort (); : } :#endif : } : pDamage->pDrawable = 0; : damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); :} : :void :DamageDestroy (DamagePtr pDamage) 1 0.0011 :{ /* DamageDestroy total: 3 0.0033 */ : if (pDamage->damageDestroy) : (*pDamage->damageDestroy) (pDamage, pDamage->closure); 2 0.0022 : REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage); : REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->pendingDamage); : xfree (pDamage); :} : :Bool :DamageSubtract (DamagePtr pDamage, : const RegionPtr pRegion) :{ : RegionPtr pClip; : RegionRec pixmapClip; : DrawablePtr pDrawable = pDamage->pDrawable; : : REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion); : if (pDrawable) : { : if (pDrawable->type == DRAWABLE_WINDOW) : pClip = &((WindowPtr) pDrawable)->borderClip; : else : { : BoxRec box; : : box.x1 = pDrawable->x; : box.y1 = pDrawable->y; : box.x2 = pDrawable->x + pDrawable->width; : box.y2 = pDrawable->y + pDrawable->height; : REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1); : pClip = &pixmapClip; : } : REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y); : REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip); : REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y); : if (pDrawable->type != DRAWABLE_WINDOW) : REGION_UNINIT(pDrawable->pScreen, &pixmapClip); : } : return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage); :} : :void :DamageEmpty (DamagePtr pDamage) 1 0.0011 :{ /* DamageEmpty total: 3 0.0033 */ 1 0.0011 : REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage); 1 0.0011 :} : :RegionPtr :DamageRegion (DamagePtr pDamage) 7 0.0076 :{ /* DamageRegion total: 10 0.0109 */ : return &pDamage->damage; 3 0.0033 :} : :_X_EXPORT void :DamageDamageRegion (DrawablePtr pDrawable, : RegionPtr pRegion) :{ : damageDamageRegion (pDrawable, pRegion, FALSE, -1); : : /* Go back and report this damage for DamagePtrs with reportAfter set, since : * this call isn't part of an in-progress drawing op in the call chain and : * the DDX probably just wants to know about it right away. : */ : damageReportPostOp (pDrawable); :} : :void :DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter) 4 0.0044 :{ /* DamageSetReportAfterOp total: 5 0.0054 */ : pDamage->reportAfter = reportAfter; 1 0.0011 :} /* * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i830_driver.c" * * 154 0.1678 */ :/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c,v 1.50 2004/02/20 00:06:00 alanh Exp $ */ :/************************************************************************** : :Copyright 2001 VA Linux Systems Inc., Fremont, California. :Copyright © 2002 by David Dawes : :All Rights Reserved. : :Permission is hereby granted, free of charge, to any person obtaining a :copy of this software and associated documentation files (the "Software"), :to deal in the Software without restriction, including without limitation :on the rights to use, copy, modify, merge, publish, distribute, sub :license, and/or sell copies of the Software, and to permit persons to whom :the Software is furnished to do so, subject to the following conditions: : :The above copyright notice and this permission notice (including the next :paragraph) shall be included in all copies or substantial portions of the :Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL :THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, :DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR :OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE :USE OR OTHER DEALINGS IN THE SOFTWARE. : :**************************************************************************/ : :/* : * Reformatted with GNU indent (2.2.8), using the following options: : * : * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78 : * -lp -npcs -psl -sob -ss -br -ce -sc -hnl : * : * This provides a good match with the original i810 code and preferred : * XFree86 formatting conventions. : * : * When editing this driver, please follow the existing formatting, and edit : * with characters expanded at 8-column intervals. : */ : :/* : * Authors: Jeff Hartmann : * Abraham van der Merwe : * David Dawes : * Alan Hourihane : */ : :/* : * Mode handling is based on the VESA driver written by: : * Paulo César Pereira de Andrade : */ : :/* : * Changes: : * : * 23/08/2001 Abraham van der Merwe : * - Fixed display timing bug (mode information for some : * modes were not initialized correctly) : * - Added workarounds for GTT corruptions (I don't adjust : * the pitches for 1280x and 1600x modes so we don't : * need extra memory) : * - The code will now default to 60Hz if LFP is connected : * - Added different refresh rate setting code to work : * around 0x4f02 BIOS bug : * - BIOS workaround for some mode sets (I use legacy BIOS : * calls for setting those) : * - Removed 0x4f04, 0x01 (save state) BIOS call which causes : * LFP to malfunction (do some house keeping and restore : * modes ourselves instead - not perfect, but at least the : * LFP is working now) : * - Several other smaller bug fixes : * : * 06/09/2001 Abraham van der Merwe : * - Preliminary local memory support (works without agpgart) : * - DGA fixes (the code were still using i810 mode sets, etc.) : * - agpgart fixes : * : * 18/09/2001 : * - Proper local memory support (should work correctly now : * with/without agpgart module) : * - more agpgart fixes : * - got rid of incorrect GTT adjustments : * : * 09/10/2001 : * - Changed the DPRINTF() variadic macro to an ANSI C compatible : * version : * : * 10/10/2001 : * - Fixed DPRINTF_stub(). I forgot the __...__ macros in there : * instead of the function arguments :P : * - Added a workaround for the 1600x1200 bug (Text mode corrupts : * when you exit from any 1600x1200 mode and 1280x1024@85Hz. I : * suspect this is a BIOS bug (hence the 1280x1024@85Hz case)). : * For now I'm switching to 800x600@60Hz then to 80x25 text mode : * and then restoring the registers - very ugly indeed. : * : * 15/10/2001 : * - Improved 1600x1200 mode set workaround. The previous workaround : * was causing mode set problems later on. : * : * 18/10/2001 : * - Fixed a bug in I830BIOSLeaveVT() which caused a bug when you : * switched VT's : */ :/* : * 07/2002 David Dawes : * - Add Intel(R) 855GM/852GM support. : */ :/* : * 07/2002 David Dawes : * - Cleanup code formatting. : * - Improve VESA mode selection, and fix refresh rate selection. : * - Don't duplicate functions provided in 4.2 vbe modules. : * - Don't duplicate functions provided in the vgahw module. : * - Rewrite memory allocation. : * - Rewrite initialisation and save/restore state handling. : * - Decouple the i810 support from i830 and later. : * - Remove various unnecessary hacks and workarounds. : * - Fix an 845G problem with the ring buffer not in pre-allocated : * memory. : * - Fix screen blanking. : * - Clear the screen at startup so you don't see the previous session. : * - Fix some HW cursor glitches, and turn HW cursor off at VT switch : * and exit. : * : * 08/2002 Keith Whitwell : * - Fix DRI initialisation. : * : * : * 08/2002 Alan Hourihane and David Dawes : * - Add XVideo support. : * : * : * 10/2002 David Dawes : * - Add Intel(R) 865G support. : * : * : * 01/2004 Alan Hourihane : * - Add Intel(R) 915G support. : * - Add Dual Head and Clone capabilities. : * - Add lid status checking : * - Fix Xvideo with high-res LFP's : * - Add ARGB HW cursor support : * : * 05/2005 Alan Hourihane : * - Add Intel(R) 945G support. : * : * 09/2005 Alan Hourihane : * - Add Intel(R) 945GM support. : * : * 10/2005 Alan Hourihane, Keith Whitwell, Brian Paul : * - Added Rotation support : * : * 12/2005 Alan Hourihane, Keith Whitwell : * - Add Intel(R) 965G support. : */ : :#ifdef HAVE_CONFIG_H :#include "config.h" :#endif : :#ifndef PRINT_MODE_INFO :#define PRINT_MODE_INFO 0 :#endif : :#include :#include :#include :#include :#include :#include : :#include "xf86.h" :#include "xf86_OSproc.h" :#include "xf86Resources.h" :#include "xf86RAC.h" :#include "xf86cmap.h" :#include "compiler.h" :#include "mibstore.h" :#include "vgaHW.h" :#include "mipointer.h" :#include "micmap.h" :#include "shadowfb.h" :#include :#include "fb.h" :#include "miscstruct.h" :#include "dixstruct.h" :#include "xf86xv.h" :#include :#include "vbe.h" :#include "shadow.h" :#include "i830.h" :#include "i830_display.h" :#include "i830_debug.h" :#include "i830_bios.h" : :#ifdef XF86DRI :#include "dri.h" :#include :#include :#endif : :#ifdef I830_USE_EXA :const char *I830exaSymbols[] = { : "exaGetVersion", : "exaDriverInit", : "exaDriverFini", : "exaOffscreenAlloc", : "exaOffscreenFree", : "exaWaitSync", : NULL :}; :#endif : :#define BIT(x) (1 << (x)) :#define MAX(a,b) ((a) > (b) ? (a) : (b)) :#define NB_OF(x) (sizeof (x) / sizeof (*x)) : :/* *INDENT-OFF* */ :static SymTabRec I830Chipsets[] = { : {PCI_CHIP_I830_M, "i830"}, : {PCI_CHIP_845_G, "845G"}, : {PCI_CHIP_I855_GM, "852GM/855GM"}, : {PCI_CHIP_I865_G, "865G"}, : {PCI_CHIP_I915_G, "915G"}, : {PCI_CHIP_E7221_G, "E7221 (i915)"}, : {PCI_CHIP_I915_GM, "915GM"}, : {PCI_CHIP_I945_G, "945G"}, : {PCI_CHIP_I945_GM, "945GM"}, : {PCI_CHIP_I945_GME, "945GME"}, : {PCI_CHIP_I965_G, "965G"}, : {PCI_CHIP_I965_G_1, "965G"}, : {PCI_CHIP_I965_Q, "965Q"}, : {PCI_CHIP_I946_GZ, "946GZ"}, : {PCI_CHIP_I965_GM, "965GM"}, : {PCI_CHIP_I965_GME, "965GME/GLE"}, : {PCI_CHIP_G33_G, "G33"}, : {PCI_CHIP_Q35_G, "Q35"}, : {PCI_CHIP_Q33_G, "Q33"}, : {-1, NULL} :}; : :static PciChipsets I830PciChipsets[] = { : {PCI_CHIP_I830_M, PCI_CHIP_I830_M, RES_SHARED_VGA}, : {PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA}, : {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA}, : {PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA}, : {PCI_CHIP_I915_G, PCI_CHIP_I915_G, RES_SHARED_VGA}, : {PCI_CHIP_E7221_G, PCI_CHIP_E7221_G, RES_SHARED_VGA}, : {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA}, : {PCI_CHIP_I945_G, PCI_CHIP_I945_G, RES_SHARED_VGA}, : {PCI_CHIP_I945_GM, PCI_CHIP_I945_GM, RES_SHARED_VGA}, : {PCI_CHIP_I945_GME, PCI_CHIP_I945_GME, RES_SHARED_VGA}, : {PCI_CHIP_I965_G, PCI_CHIP_I965_G, RES_SHARED_VGA}, : {PCI_CHIP_I965_G_1, PCI_CHIP_I965_G_1, RES_SHARED_VGA}, : {PCI_CHIP_I965_Q, PCI_CHIP_I965_Q, RES_SHARED_VGA}, : {PCI_CHIP_I946_GZ, PCI_CHIP_I946_GZ, RES_SHARED_VGA}, : {PCI_CHIP_I965_GM, PCI_CHIP_I965_GM, RES_SHARED_VGA}, : {PCI_CHIP_I965_GME, PCI_CHIP_I965_GME, RES_SHARED_VGA}, : {PCI_CHIP_G33_G, PCI_CHIP_G33_G, RES_SHARED_VGA}, : {PCI_CHIP_Q35_G, PCI_CHIP_Q35_G, RES_SHARED_VGA}, : {PCI_CHIP_Q33_G, PCI_CHIP_Q33_G, RES_SHARED_VGA}, : {-1, -1, RES_UNDEFINED} :}; : :/* : * Note: "ColorKey" is provided for compatibility with the i810 driver. : * However, the correct option name is "VideoKey". "ColorKey" usually : * refers to the tranparency key for 8+24 overlays, not for video overlays. : */ : :typedef enum { :#if defined(I830_USE_XAA) && defined(I830_USE_EXA) : OPTION_ACCELMETHOD, :#endif : OPTION_NOACCEL, : OPTION_SW_CURSOR, : OPTION_CACHE_LINES, : OPTION_DRI, : OPTION_PAGEFLIP, : OPTION_XVIDEO, : OPTION_VIDEO_KEY, : OPTION_COLOR_KEY, : OPTION_CHECKDEVICES, : OPTION_MODEDEBUG, :#ifdef XF86DRI_MM : OPTION_INTELTEXPOOL, : OPTION_INTELMMSIZE, :#endif : OPTION_TRIPLEBUFFER, :} I830Opts; : :static OptionInfoRec I830Options[] = { :#if defined(I830_USE_XAA) && defined(I830_USE_EXA) : {OPTION_ACCELMETHOD, "AccelMethod", OPTV_ANYSTR, {0}, FALSE}, :#endif : {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, : {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, : {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE}, : {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, TRUE}, : {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, : {OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, TRUE}, : {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, : {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, : {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN, {0}, FALSE}, : {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE}, :#ifdef XF86DRI_MM : {OPTION_INTELTEXPOOL,"Legacy3D", OPTV_BOOLEAN, {0}, FALSE}, : {OPTION_INTELMMSIZE, "AperTexSize", OPTV_INTEGER, {0}, FALSE}, :#endif : {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN, {0}, FALSE}, : {-1, NULL, OPTV_NONE, {0}, FALSE} :}; :/* *INDENT-ON* */ : :const char *i830_output_type_names[] = { : "Unused", : "Analog", : "DVO", : "SDVO", : "LVDS", : "TVOUT", :}; : :static void i830AdjustFrame(int scrnIndex, int x, int y, int flags); :static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen); :static Bool I830EnterVT(int scrnIndex, int flags); :static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg); :static Bool SaveHWState(ScrnInfoPtr pScrn); :static Bool RestoreHWState(ScrnInfoPtr pScrn); : :/* temporary */ :extern void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y); : :#ifdef I830DEBUG :void :I830DPRINTF_stub(const char *filename, int line, const char *function, : const char *fmt, ...) :{ : va_list ap; : : ErrorF("\n##############################################\n" : "*** In function %s, on line %d, in file %s ***\n", : function, line, filename); : va_start(ap, fmt); : VErrorF(fmt, ap); : va_end(ap); : ErrorF("##############################################\n\n"); :} :#else /* #ifdef I830DEBUG */ :void :I830DPRINTF_stub(const char *filename, int line, const char *function, : const char *fmt, ...) :{ : /* do nothing */ :} :#endif /* #ifdef I830DEBUG */ : :/* Export I830 options to i830 driver where necessary */ :const OptionInfoRec * :I830AvailableOptions(int chipid, int busid) :{ : int i; : : for (i = 0; I830PciChipsets[i].PCIid > 0; i++) { : if (chipid == I830PciChipsets[i].PCIid) : return I830Options; : } : return NULL; :} : :static Bool :I830GetRec(ScrnInfoPtr pScrn) :{ : I830Ptr pI830; : : if (pScrn->driverPrivate) : return TRUE; : pI830 = pScrn->driverPrivate = xnfcalloc(sizeof(I830Rec), 1); : return TRUE; :} : :static void :I830FreeRec(ScrnInfoPtr pScrn) :{ : I830Ptr pI830; : : if (!pScrn) : return; : if (!pScrn->driverPrivate) : return; : : pI830 = I830PTR(pScrn); : : xfree(pScrn->driverPrivate); : pScrn->driverPrivate = NULL; :} : :static void :I830ProbeDDC(ScrnInfoPtr pScrn, int index) :{ : vbeInfoPtr pVbe; : : /* The vbe module gets loaded in PreInit(), so no need to load it here. */ : : pVbe = VBEInit(NULL, index); : ConfiguredMonitor = vbeDoEDID(pVbe, NULL); :} : :static int :I830DetectMemory(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : PCITAG bridge; : CARD16 gmch_ctrl; : int memsize = 0, gtt_size; : int range; :#if 0 : VbeInfoBlock *vbeInfo; :#endif : : bridge = pciTag(0, 0, 0); /* This is always the host bridge */ : gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL); : : if (IS_I965G(pI830)) { : /* The 965 may have a GTT that is actually larger than is necessary : * to cover the aperture, so check the hardware's reporting of the : * GTT size. : */ : switch (INREG(PGETBL_CTL) & PGETBL_SIZE_MASK) { : case PGETBL_SIZE_512KB: : gtt_size = 512; : break; : case PGETBL_SIZE_256KB: : gtt_size = 256; : break; : case PGETBL_SIZE_128KB: : gtt_size = 128; : break; : default: : FatalError("Unknown GTT size value: %08x\n", (int)INREG(PGETBL_CTL)); : } : } else if (IS_G33CLASS(pI830)) { : /* G33's GTT size is detect in GMCH_CTRL */ : switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { : case G33_PGETBL_SIZE_1M: : gtt_size = 1024; : break; : case G33_PGETBL_SIZE_2M: : gtt_size = 2048; : break; : default: : FatalError("Unknown GTT size value: %08x\n", : (int)(gmch_ctrl & G33_PGETBL_SIZE_MASK)); : } : } else { : /* Older chipsets only had GTT appropriately sized for the aperture. */ : gtt_size = pI830->FbMapSize / (1024*1024); : } : : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "detected %d kB GTT.\n", gtt_size); : : /* The stolen memory has the GTT at the top, and the 4KB popup below that. : * Everything else can be freely used by the graphics driver. : */ : range = gtt_size + 4; : : if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) { : switch (gmch_ctrl & I830_GMCH_GMS_MASK) { : case I855_GMCH_GMS_STOLEN_1M: : memsize = MB(1) - KB(range); : break; : case I855_GMCH_GMS_STOLEN_4M: : memsize = MB(4) - KB(range); : break; : case I855_GMCH_GMS_STOLEN_8M: : memsize = MB(8) - KB(range); : break; : case I855_GMCH_GMS_STOLEN_16M: : memsize = MB(16) - KB(range); : break; : case I855_GMCH_GMS_STOLEN_32M: : memsize = MB(32) - KB(range); : break; : case I915G_GMCH_GMS_STOLEN_48M: : if (IS_I9XX(pI830)) : memsize = MB(48) - KB(range); : break; : case I915G_GMCH_GMS_STOLEN_64M: : if (IS_I9XX(pI830)) : memsize = MB(64) - KB(range); : break; : case G33_GMCH_GMS_STOLEN_128M: : if (IS_G33CLASS(pI830)) : memsize = MB(128) - KB(range); : break; : case G33_GMCH_GMS_STOLEN_256M: : if (IS_G33CLASS(pI830)) : memsize = MB(256) - KB(range); : break; : } : } else { : switch (gmch_ctrl & I830_GMCH_GMS_MASK) { : case I830_GMCH_GMS_STOLEN_512: : memsize = KB(512) - KB(range); : break; : case I830_GMCH_GMS_STOLEN_1024: : memsize = MB(1) - KB(range); : break; : case I830_GMCH_GMS_STOLEN_8192: : memsize = MB(8) - KB(range); : break; : case I830_GMCH_GMS_LOCAL: : memsize = 0; : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "Local memory found, but won't be used.\n"); : break; : } : } : :#if 0 : /* And 64KB page aligned */ : memsize &= ~0xFFFF; :#endif : : if (memsize > 0) { : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "detected %d kB stolen memory.\n", memsize / 1024); : } else { : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n"); : } : : return memsize; :} : :static Bool :I830MapMMIO(ScrnInfoPtr pScrn) :{ : int mmioFlags; : I830Ptr pI830 = I830PTR(pScrn); : :#if !defined(__alpha__) : mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; :#else : mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE; :#endif : : pI830->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, : pI830->PciTag, : pI830->MMIOAddr, I810_REG_SIZE); : if (!pI830->MMIOBase) : return FALSE; : : /* Set up the GTT mapping for the various places it has been moved over : * time. : */ : if (IS_I9XX(pI830)) { : if (IS_I965G(pI830)) { : pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, : pI830->PciTag, : pI830->MMIOAddr + (512 * 1024), : 512 * 1024); : if (pI830->GTTBase == NULL) : return FALSE; : } else { : CARD32 gttaddr = pI830->PciInfo->memBase[3] & 0xFFFFFF00; : : pI830->GTTBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, : pI830->PciTag, : gttaddr, : pI830->FbMapSize / 1024); : if (pI830->GTTBase == NULL) : return FALSE; : } : } else { : /* The GTT aperture on i830 is write-only. We could probably map the : * actual physical pages that back it, but leave it alone for now. : */ : pI830->GTTBase = NULL; : } : : return TRUE; :} : :static Bool :I830MapMem(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : long i; : : for (i = 2; i < pI830->FbMapSize; i <<= 1) ; : pI830->FbMapSize = i; : : if (!I830MapMMIO(pScrn)) : return FALSE; : : pI830->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, : pI830->PciTag, : pI830->LinearAddr, pI830->FbMapSize); : if (!pI830->FbBase) : return FALSE; : : if (I830IsPrimary(pScrn) && pI830->LpRing->mem != NULL) { : pI830->LpRing->virtual_start = : pI830->FbBase + pI830->LpRing->mem->offset; : } : : return TRUE; :} : :static void :I830UnmapMMIO(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : : xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase, : I810_REG_SIZE); : pI830->MMIOBase = NULL; : : if (IS_I9XX(pI830)) { : if (IS_I965G(pI830)) : xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase, 512 * 1024); : else { : xf86UnMapVidMem(pScrn->scrnIndex, pI830->GTTBase, : pI830->FbMapSize / 1024); : } : } :} : :static Bool :I830UnmapMem(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : : xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->FbBase, : pI830->FbMapSize); : pI830->FbBase = NULL; : I830UnmapMMIO(pScrn); : return TRUE; :} : :static void :I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, : LOCO * colors, VisualPtr pVisual) :{ : xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); : int i,j, index; : int p; : CARD16 lut_r[256], lut_g[256], lut_b[256]; : : DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); : : for(p = 0; p < xf86_config->num_crtc; p++) { : xf86CrtcPtr crtc = xf86_config->crtc[p]; : I830CrtcPrivatePtr intel_crtc = crtc->driver_private; : : /* Initialize to the old lookup table values. */ : for (i = 0; i < 256; i++) { : lut_r[i] = intel_crtc->lut_r[i] << 8; : lut_g[i] = intel_crtc->lut_g[i] << 8; : lut_b[i] = intel_crtc->lut_b[i] << 8; : } : : switch(pScrn->depth) { : case 15: : for (i = 0; i < numColors; i++) { : index = indices[i]; : for (j = 0; j < 8; j++) { : lut_r[index * 8 + j] = colors[index].red << 8; : lut_g[index * 8 + j] = colors[index].green << 8; : lut_b[index * 8 + j] = colors[index].blue << 8; : } : } : break; : case 16: : for (i = 0; i < numColors; i++) { : index = indices[i]; : : if (index <= 31) { : for (j = 0; j < 8; j++) { : lut_r[index * 8 + j] = colors[index].red << 8; : lut_b[index * 8 + j] = colors[index].blue << 8; : } : } : : for (j = 0; j < 4; j++) { : lut_g[index * 4 + j] = colors[index].green << 8; : } : } : break; : default: : for (i = 0; i < numColors; i++) { : index = indices[i]; : lut_r[index] = colors[index].red << 8; : lut_g[index] = colors[index].green << 8; : lut_b[index] = colors[index].blue << 8; : } : break; : } : : /* Make the change through RandR */ :#ifdef RANDR_12_INTERFACE : RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); :#else : crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); :#endif : } :} : :int :i830_output_clones (ScrnInfoPtr pScrn, int type_mask) :{ : xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); : int o; : int index_mask = 0; : : for (o = 0; o < config->num_output; o++) : { : xf86OutputPtr output = config->output[o]; : I830OutputPrivatePtr intel_output = output->driver_private; : if (type_mask & (1 << intel_output->type)) : index_mask |= (1 << o); : } : return index_mask; :} : :/** : * Set up the outputs according to what type of chip we are. : * : * Some outputs may not initialize, due to allocation failure or because a : * controller chip isn't found. : */ :static void :I830SetupOutputs(ScrnInfoPtr pScrn) :{ : xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); : I830Ptr pI830 = I830PTR(pScrn); : int o; : : /* everyone has at least a single analog output */ : i830_crt_init(pScrn); : : /* Set up integrated LVDS */ : if (IS_MOBILE(pI830) && !IS_I830(pI830)) : i830_lvds_init(pScrn); : : if (IS_I9XX(pI830)) { : i830_sdvo_init(pScrn, SDVOB); : i830_sdvo_init(pScrn, SDVOC); : } else { : i830_dvo_init(pScrn); : } : if (IS_I9XX(pI830) && !IS_I915G(pI830)) : i830_tv_init(pScrn); : : for (o = 0; o < config->num_output; o++) : { : xf86OutputPtr output = config->output[o]; : I830OutputPrivatePtr intel_output = output->driver_private; : int crtc_mask; : int c; : : crtc_mask = 0; : for (c = 0; c < config->num_crtc; c++) : { : xf86CrtcPtr crtc = config->crtc[c]; : I830CrtcPrivatePtr intel_crtc = crtc->driver_private; : : if (intel_output->pipe_mask & (1 << intel_crtc->pipe)) : crtc_mask |= (1 << c); : } : output->possible_crtcs = crtc_mask; : output->possible_clones = i830_output_clones (pScrn, intel_output->clone_mask); : } :} : :/** : * Setup the CRTCs : */ : : :static void :I830PreInitDDC(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : : if (!xf86LoadSubModule(pScrn, "ddc")) { : pI830->ddc2 = FALSE; : } else { : xf86LoaderReqSymLists(I810ddcSymbols, NULL); : pI830->ddc2 = TRUE; : } : : /* DDC can use I2C bus */ : /* Load I2C if we have the code to use it */ : if (pI830->ddc2) { : if (xf86LoadSubModule(pScrn, "i2c")) { : xf86LoaderReqSymLists(I810i2cSymbols, NULL); : : pI830->ddc2 = TRUE; : } else { : pI830->ddc2 = FALSE; : } : } :} : :static void :PreInitCleanup(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : : if (I830IsPrimary(pScrn)) { : if (pI830->entityPrivate) : pI830->entityPrivate->pScrn_1 = NULL; : } else { : if (pI830->entityPrivate) : pI830->entityPrivate->pScrn_2 = NULL; : } : if (pI830->swfSaved) { : OUTREG(SWF0, pI830->saveSWF0); : OUTREG(SWF4, pI830->saveSWF4); : } : if (pI830->MMIOBase) : I830UnmapMMIO(pScrn); : I830FreeRec(pScrn); :} : :Bool :I830IsPrimary(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : : if (xf86IsEntityShared(pScrn->entityList[0])) { : if (pI830->init == 0) return TRUE; : else return FALSE; : } : : return TRUE; :} : :static Bool :i830_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) :{ : scrn->virtualX = width; : scrn->virtualY = height; : return TRUE; :} : :static const xf86CrtcConfigFuncsRec i830_xf86crtc_config_funcs = { : i830_xf86crtc_resize :}; : :#define HOTKEY_BIOS_SWITCH 0 :#define HOTKEY_DRIVER_NOTIFY 1 : :/** : * Controls the BIOS's behavior on hotkey switch. : * : * If the mode is HOTKEY_BIOS_SWITCH, the BIOS will be set to do a mode switch : * on its own and update the state in the scratch register. : * If the mode is HOTKEY_DRIVER_NOTIFY, the BIOS won't do a mode switch and : * will just update the state to represent what it would have been switched to. : */ :static void :i830SetHotkeyControl(ScrnInfoPtr pScrn, int mode) :{ : I830Ptr pI830 = I830PTR(pScrn); : CARD8 gr18; : : gr18 = pI830->readControl(pI830, GRX, 0x18); : if (mode == HOTKEY_BIOS_SWITCH) : gr18 &= ~HOTKEY_VBIOS_SWITCH_BLOCK; : else : gr18 |= HOTKEY_VBIOS_SWITCH_BLOCK; : pI830->writeControl(pI830, GRX, 0x18, gr18); :} : :/** : * This is called per zaphod head (so usually just once) to do initialization : * before the Screen is created. : * : * This code generally covers probing, module loading, option handling : * card mapping, and RandR setup. : */ :static Bool :I830PreInit(ScrnInfoPtr pScrn, int flags) :{ : xf86CrtcConfigPtr xf86_config; : vgaHWPtr hwp; : I830Ptr pI830; : MessageType from = X_PROBED; : rgb defaultWeight = { 0, 0, 0 }; : EntityInfoPtr pEnt; : I830EntPtr pI830Ent = NULL; : int flags24; : int i; : char *s; : pointer pVBEModule = NULL; : const char *chipname; : int num_pipe; : int max_width, max_height; : : if (pScrn->numEntities != 1) : return FALSE; : : /* Load int10 module */ : if (!xf86LoadSubModule(pScrn, "int10")) : return FALSE; : xf86LoaderReqSymLists(I810int10Symbols, NULL); : : /* Load vbe module */ : if (!(pVBEModule = xf86LoadSubModule(pScrn, "vbe"))) : return FALSE; : xf86LoaderReqSymLists(I810vbeSymbols, NULL); : : pEnt = xf86GetEntityInfo(pScrn->entityList[0]); : : if (flags & PROBE_DETECT) { : I830ProbeDDC(pScrn, pEnt->index); : return TRUE; : } : : /* The vgahw module should be loaded here when needed */ : if (!xf86LoadSubModule(pScrn, "vgahw")) : return FALSE; : xf86LoaderReqSymLists(I810vgahwSymbols, NULL); : : /* Allocate a vgaHWRec */ : if (!vgaHWGetHWRec(pScrn)) : return FALSE; : : /* Allocate driverPrivate */ : if (!I830GetRec(pScrn)) : return FALSE; : : pI830 = I830PTR(pScrn); : pI830->SaveGeneration = -1; : pI830->pEnt = pEnt; : : pScrn->displayWidth = 640; /* default it */ : : if (pI830->pEnt->location.type != BUS_PCI) : return FALSE; : : pI830->PciInfo = xf86GetPciInfoForEntity(pI830->pEnt->index); : pI830->PciTag = pciTag(pI830->PciInfo->bus, pI830->PciInfo->device, : pI830->PciInfo->func); : : /* Allocate an entity private if necessary */ : if (xf86IsEntityShared(pScrn->entityList[0])) { : pI830Ent = xf86GetEntityPrivate(pScrn->entityList[0], : I830EntityIndex)->ptr; : pI830->entityPrivate = pI830Ent; : } else : pI830->entityPrivate = NULL; : : if (xf86RegisterResources(pI830->pEnt->index, NULL, ResNone)) { : PreInitCleanup(pScrn); : return FALSE; : } : : if (xf86IsEntityShared(pScrn->entityList[0])) { : if (xf86IsPrimInitDone(pScrn->entityList[0])) { : pI830->init = 1; : : if (!pI830Ent->pScrn_1) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Failed to setup second head due to primary head failure.\n"); : return FALSE; : } : } else { : xf86SetPrimInitDone(pScrn->entityList[0]); : pI830->init = 0; : } : } : : if (xf86IsEntityShared(pScrn->entityList[0])) { : if (!I830IsPrimary(pScrn)) { : pI830Ent->pScrn_2 = pScrn; : } else { : pI830Ent->pScrn_1 = pScrn; : pI830Ent->pScrn_2 = NULL; : } : } : : pScrn->racMemFlags = RAC_FB | RAC_COLORMAP; : pScrn->monitor = pScrn->confScreen->monitor; : pScrn->progClock = TRUE; : pScrn->rgbBits = 8; : : flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32; : : if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) : return FALSE; : : switch (pScrn->depth) { : case 8: : case 15: : case 16: : case 24: : break; : default: : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Given depth (%d) is not supported by I830 driver\n", : pScrn->depth); : return FALSE; : } : xf86PrintDepthBpp(pScrn); : : if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) : return FALSE; : if (!xf86SetDefaultVisual(pScrn, -1)) : return FALSE; : : hwp = VGAHWPTR(pScrn); : pI830->cpp = pScrn->bitsPerPixel / 8; : : pI830->preinit = TRUE; : : /* Process the options */ : xf86CollectOptions(pScrn, NULL); : if (!(pI830->Options = xalloc(sizeof(I830Options)))) : return FALSE; : memcpy(pI830->Options, I830Options, sizeof(I830Options)); : xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI830->Options); : : if (xf86ReturnOptValBool(pI830->Options, OPTION_MODEDEBUG, FALSE)) { : pI830->debug_modes = TRUE; : } else { : pI830->debug_modes = FALSE; : } : : /* We have to use PIO to probe, because we haven't mapped yet. */ : I830SetPIOAccess(pI830); : : switch (pI830->PciInfo->chipType) { : case PCI_CHIP_I830_M: : chipname = "830M"; : break; : case PCI_CHIP_845_G: : chipname = "845G"; : break; : case PCI_CHIP_I855_GM: : /* Check capid register to find the chipset variant */ : pI830->variant = (pciReadLong(pI830->PciTag, I85X_CAPID) : >> I85X_VARIANT_SHIFT) & I85X_VARIANT_MASK; : switch (pI830->variant) { : case I855_GM: : chipname = "855GM"; : break; : case I855_GME: : chipname = "855GME"; : break; : case I852_GM: : chipname = "852GM"; : break; : case I852_GME: : chipname = "852GME"; : break; : default: : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "Unknown 852GM/855GM variant: 0x%x)\n", pI830->variant); : chipname = "852GM/855GM (unknown variant)"; : break; : } : break; : case PCI_CHIP_I865_G: : chipname = "865G"; : break; : case PCI_CHIP_I915_G: : chipname = "915G"; : break; : case PCI_CHIP_E7221_G: : chipname = "E7221 (i915)"; : break; : case PCI_CHIP_I915_GM: : chipname = "915GM"; : break; : case PCI_CHIP_I945_G: : chipname = "945G"; : break; : case PCI_CHIP_I945_GM: : chipname = "945GM"; : break; : case PCI_CHIP_I945_GME: : chipname = "945GME"; : break; : case PCI_CHIP_I965_G: : case PCI_CHIP_I965_G_1: : chipname = "965G"; : break; : case PCI_CHIP_I965_Q: : chipname = "965Q"; : break; : case PCI_CHIP_I946_GZ: : chipname = "946GZ"; : break; : case PCI_CHIP_I965_GM: : chipname = "965GM"; : break; : case PCI_CHIP_I965_GME: : chipname = "965GME/GLE"; : break; : case PCI_CHIP_G33_G: : chipname = "G33"; : break; : case PCI_CHIP_Q35_G: : chipname = "Q35"; : break; : case PCI_CHIP_Q33_G: : chipname = "Q33"; : break; : default: : chipname = "unknown chipset"; : break; : } : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "Integrated Graphics Chipset: Intel(R) %s\n", chipname); : : /* Set the Chipset and ChipRev, allowing config file entries to override. */ : if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) { : pScrn->chipset = pI830->pEnt->device->chipset; : from = X_CONFIG; : } else if (pI830->pEnt->device->chipID >= 0) { : pScrn->chipset = (char *)xf86TokenToString(I830Chipsets, : pI830->pEnt->device->chipID); : from = X_CONFIG; : xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", : pI830->pEnt->device->chipID); : pI830->PciInfo->chipType = pI830->pEnt->device->chipID; : } else { : from = X_PROBED; : pScrn->chipset = (char *)xf86TokenToString(I830Chipsets, : pI830->PciInfo->chipType); : } : : if (pI830->pEnt->device->chipRev >= 0) { : xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", : pI830->pEnt->device->chipRev); : } : : xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", : (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i8xx"); : : if (pI830->pEnt->device->MemBase != 0) { : pI830->LinearAddr = pI830->pEnt->device->MemBase; : from = X_CONFIG; : } else { : if (IS_I9XX(pI830)) { : pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xFF000000; : from = X_PROBED; : } else if (pI830->PciInfo->memBase[1] != 0) { : /* XXX Check mask. */ : pI830->LinearAddr = pI830->PciInfo->memBase[0] & 0xFF000000; : from = X_PROBED; : } else { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "No valid FB address in PCI config space\n"); : PreInitCleanup(pScrn); : return FALSE; : } : } : : xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", : (unsigned long)pI830->LinearAddr); : : if (pI830->pEnt->device->IOBase != 0) { : pI830->MMIOAddr = pI830->pEnt->device->IOBase; : from = X_CONFIG; : } else { : if (IS_I9XX(pI830)) { : pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000; : from = X_PROBED; : } else if (pI830->PciInfo->memBase[1]) { : pI830->MMIOAddr = pI830->PciInfo->memBase[1] & 0xFFF80000; : from = X_PROBED; : } else { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "No valid MMIO address in PCI config space\n"); : PreInitCleanup(pScrn); : return FALSE; : } : } : : xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n", : (unsigned long)pI830->MMIOAddr); : : /* Allocate an xf86CrtcConfig */ : xf86CrtcConfigInit (pScrn, &i830_xf86crtc_config_funcs); : xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); : : /* See i830_exa.c comments for why we limit the framebuffer size like this. : */ : if (IS_I965G(pI830)) { : max_width = 8192; : max_height = 8192; : } else { : max_width = 2048; : max_height = 2048; : } : xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height); : : if (IS_I830(pI830) || IS_845G(pI830)) { : PCITAG bridge; : CARD16 gmch_ctrl; : : bridge = pciTag(0, 0, 0); /* This is always the host bridge */ : gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL); : if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { : pI830->FbMapSize = 0x8000000; : } else { : pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */ : } : } else { : if (IS_I9XX(pI830)) { : pI830->FbMapSize = 1UL << pciGetBaseSize(pI830->PciTag, 2, TRUE, : NULL); : } else { : /* 128MB aperture for later i8xx series. */ : pI830->FbMapSize = 0x8000000; : } : } : : /* Some of the probing needs MMIO access, so map it here. */ : I830MapMMIO(pScrn); : : if (pI830->debug_modes) { : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state on X startup:\n"); : i830DumpRegs (pScrn); : } : : i830TakeRegSnapshot(pScrn); : :#if 1 : pI830->saveSWF0 = INREG(SWF0); : pI830->saveSWF4 = INREG(SWF4); : pI830->swfSaved = TRUE; : : /* Set "extended desktop" */ : OUTREG(SWF0, pI830->saveSWF0 | (1 << 21)); : : /* Set "driver loaded", "OS unknown", "APM 1.2" */ : OUTREG(SWF4, (pI830->saveSWF4 & ~((3 << 19) | (7 << 16))) | : (1 << 23) | (2 << 16)); :#endif : : if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) : num_pipe = 1; : else : if (IS_MOBILE(pI830) || IS_I9XX(pI830)) : num_pipe = 2; : else : num_pipe = 1; : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n", : num_pipe, num_pipe > 1 ? "s" : ""); : : if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) { : pI830->noAccel = TRUE; : } : : /* : * The ugliness below: : * If either XAA or EXA (exclusive) is compiled in, default to it. : * : * If both are compiled in, and the user didn't specify noAccel, use the : * config option AccelMethod to determine which to use, defaulting to XAA : * if none is specified, or if the string was unrecognized. : * : * All this *could* go away if we removed XAA support from this driver, : * for example. :) : */ : if (!pI830->noAccel) { :#if (defined(I830_USE_EXA) && defined(I830_USE_XAA)) || !defined(I830_USE_EXA) : pI830->useEXA = FALSE; :#else : pI830->useEXA = TRUE; :#endif :#if defined(I830_USE_XAA) && defined(I830_USE_EXA) : int from = X_DEFAULT; : if ((s = (char *)xf86GetOptValString(pI830->Options, : OPTION_ACCELMETHOD))) { : if (!xf86NameCmp(s, "EXA")) { : from = X_CONFIG; : pI830->useEXA = TRUE; : } : else if (!xf86NameCmp(s, "XAA")) { : from = X_CONFIG; : pI830->useEXA = FALSE; : } : } :#endif : xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n", : pI830->useEXA ? "EXA" : "XAA"); : } : : if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) { : pI830->SWCursor = TRUE; : } : : pI830->directRenderingDisabled = : !xf86ReturnOptValBool(pI830->Options, OPTION_DRI, TRUE); : :#ifdef XF86DRI : if (!pI830->directRenderingDisabled) { : if (pI830->noAccel || pI830->SWCursor) { : xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it " : "needs HW cursor and 2D acceleration.\n"); : pI830->directRenderingDisabled = TRUE; : } else if (pScrn->depth != 16 && pScrn->depth != 24) { : xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it " : "runs only at depths 16 and 24.\n"); : pI830->directRenderingDisabled = TRUE; : } : : pI830->mmModeFlags = 0; : : if (!pI830->directRenderingDisabled) { : pI830->mmModeFlags = I830_KERNEL_TEX; :#ifdef XF86DRI_MM : Bool tmp = FALSE; : : if (!IS_I965G(pI830)) : pI830->mmModeFlags |= I830_KERNEL_MM; :#endif : : from = X_PROBED; : :#ifdef XF86DRI_MM : if (xf86GetOptValBool(pI830->Options, : OPTION_INTELTEXPOOL, &tmp)) { : from = X_CONFIG; : if (tmp) { : pI830->mmModeFlags |= I830_KERNEL_TEX; : pI830->mmModeFlags &= ~I830_KERNEL_MM; : } else { : pI830->mmModeFlags &= ~I830_KERNEL_TEX; : pI830->mmModeFlags |= I830_KERNEL_MM; : } : } :#endif : : xf86DrvMsg(pScrn->scrnIndex, from, : "Will %stry to allocate texture pool " : "for old Mesa 3D driver.\n", : (pI830->mmModeFlags & I830_KERNEL_TEX) ? : "" : "not "); : :#ifdef XF86DRI_MM : pI830->mmSize = I830_MM_MAXSIZE; : from = X_INFO; : if (xf86GetOptValInteger(pI830->Options, OPTION_INTELMMSIZE, : &(pI830->mmSize))) { : from = X_CONFIG; : } : xf86DrvMsg(pScrn->scrnIndex, from, : "Will try to reserve %d kiB of AGP aperture space\n" : "\tfor the DRM memory manager.\n", : pI830->mmSize); :#endif : } : } : :#endif : : I830PreInitDDC(pScrn); : for (i = 0; i < num_pipe; i++) { : i830_crtc_init(pScrn, i); : } : I830SetupOutputs(pScrn); : : SaveHWState(pScrn); : if (!xf86InitialConfiguration (pScrn, FALSE)) : { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); : RestoreHWState(pScrn); : PreInitCleanup(pScrn); : return FALSE; : } : RestoreHWState(pScrn); : : /* XXX This should go away, replaced by xf86Crtc.c support for it */ : pI830->rotation = RR_Rotate_0; : : /* : * Let's setup the mobile systems to check the lid status : */ : if (IS_MOBILE(pI830)) { : pI830->checkDevices = TRUE; : : if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKDEVICES, TRUE)) { : pI830->checkDevices = FALSE; : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n"); : } else : if (pI830->entityPrivate && !I830IsPrimary(pScrn) && : !I830PTR(pI830->entityPrivate->pScrn_1)->checkDevices) { : /* If checklid is off, on the primary head, then : * turn it off on the secondary*/ : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n"); : pI830->checkDevices = FALSE; : } else : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays enabled\n"); : } else : pI830->checkDevices = FALSE; : : pI830->stolen_size = I830DetectMemory(pScrn); : : pI830->XvDisabled = : !xf86ReturnOptValBool(pI830->Options, OPTION_XVIDEO, TRUE); : :#ifdef I830_XV : if (xf86GetOptValInteger(pI830->Options, OPTION_VIDEO_KEY, : &(pI830->colorKey))) { : from = X_CONFIG; : } else if (xf86GetOptValInteger(pI830->Options, OPTION_COLOR_KEY, : &(pI830->colorKey))) { : from = X_CONFIG; : } else { : pI830->colorKey = (1 << pScrn->offset.red) | : (1 << pScrn->offset.green) | : (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << : pScrn->offset.blue); : from = X_DEFAULT; : } : xf86DrvMsg(pScrn->scrnIndex, from, "video overlay key set to 0x%x\n", : pI830->colorKey); :#endif : :#ifdef XF86DRI : pI830->allowPageFlip = FALSE; : from = (!pI830->directRenderingDisabled && : xf86GetOptValBool(pI830->Options, OPTION_PAGEFLIP, : &pI830->allowPageFlip)) ? X_CONFIG : X_DEFAULT; : : xf86DrvMsg(pScrn->scrnIndex, from, "Will%s try to enable page flipping\n", : pI830->allowPageFlip ? "" : " not"); :#endif : :#ifdef XF86DRI : pI830->TripleBuffer = FALSE; : from = (!pI830->directRenderingDisabled && : xf86GetOptValBool(pI830->Options, OPTION_TRIPLEBUFFER, : &pI830->TripleBuffer)) ? X_CONFIG : X_DEFAULT; : : xf86DrvMsg(pScrn->scrnIndex, from, "Triple buffering %sabled\n", : pI830->TripleBuffer ? "en" : "dis"); :#endif : : /* : * If the driver can do gamma correction, it should call xf86SetGamma() here. : */ : : { : Gamma zeros = { 0.0, 0.0, 0.0 }; : : if (!xf86SetGamma(pScrn, zeros)) { : PreInitCleanup(pScrn); : return FALSE; : } : } : : /* Check if the HW cursor needs physical address. */ : if (IS_MOBILE(pI830) || IS_I9XX(pI830)) : pI830->CursorNeedsPhysical = TRUE; : else : pI830->CursorNeedsPhysical = FALSE; : : if (IS_I965G(pI830) || IS_G33CLASS(pI830)) : pI830->CursorNeedsPhysical = FALSE; : : /* : * XXX If we knew the pre-initialised GTT format for certain, we could : * probably figure out the physical address even in the StolenOnly case. : */ : if (!I830IsPrimary(pScrn)) { : I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); : if (!pI8301->SWCursor) { : xf86DrvMsg(pScrn->scrnIndex, X_PROBED, : "Using HW Cursor because it's enabled on primary head.\n"); : pI830->SWCursor = FALSE; : } : } else : if (pI830->StolenOnly && pI830->CursorNeedsPhysical && !pI830->SWCursor) { : xf86DrvMsg(pScrn->scrnIndex, X_PROBED, : "HW Cursor disabled because it needs agpgart memory.\n"); : pI830->SWCursor = TRUE; : } : : if (pScrn->modes == NULL) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); : PreInitCleanup(pScrn); : return FALSE; : } : pScrn->currentMode = pScrn->modes; : : if (!IS_I965G(pI830) && pScrn->virtualY > 2048) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n"); : pI830->noAccel = TRUE; : } : : /* Don't need MMIO access anymore. */ : if (pI830->swfSaved) { : OUTREG(SWF0, pI830->saveSWF0); : OUTREG(SWF4, pI830->saveSWF4); : } : : /* Set display resolution */ : xf86SetDpi(pScrn, 0, 0); : : /* Load the required sub modules */ : if (!xf86LoadSubModule(pScrn, "fb")) { : PreInitCleanup(pScrn); : return FALSE; : } : : xf86LoaderReqSymLists(I810fbSymbols, NULL); : :#ifdef I830_USE_XAA : if (!pI830->noAccel && !pI830->useEXA) { : if (!xf86LoadSubModule(pScrn, "xaa")) { : PreInitCleanup(pScrn); : return FALSE; : } : xf86LoaderReqSymLists(I810xaaSymbols, NULL); : } :#endif : :#ifdef I830_USE_EXA : if (!pI830->noAccel && pI830->useEXA) { : XF86ModReqInfo req; : int errmaj, errmin; : : memset(&req, 0, sizeof(req)); : req.majorversion = 2; : req.minorversion = 1; : if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, : &errmaj, &errmin)) { : LoaderErrorMsg(NULL, "exa", errmaj, errmin); : PreInitCleanup(pScrn); : return FALSE; : } : xf86LoaderReqSymLists(I830exaSymbols, NULL); : } :#endif : if (!pI830->SWCursor) { : if (!xf86LoadSubModule(pScrn, "ramdac")) { : PreInitCleanup(pScrn); : return FALSE; : } : xf86LoaderReqSymLists(I810ramdacSymbols, NULL); : } : : i830CompareRegsToSnapshot(pScrn, "After PreInit"); : : I830UnmapMMIO(pScrn); : : /* We won't be using the VGA access after the probe. */ : I830SetMMIOAccess(pI830); : xf86SetOperatingState(resVgaIo, pI830->pEnt->index, ResUnusedOpr); : xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr); : :#if 0 : if (I830IsPrimary(pScrn)) { : vbeFree(pI830->pVbe); : } : pI830->pVbe = NULL; :#endif : :#if defined(XF86DRI) : /* Load the dri module if requested. */ : if (xf86ReturnOptValBool(pI830->Options, OPTION_DRI, FALSE) && : !pI830->directRenderingDisabled) { : if (xf86LoadSubModule(pScrn, "dri")) { : xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL); : } : } :#endif : : pI830->preinit = FALSE; : : return TRUE; :} : :/* : * Reset registers that it doesn't make sense to save/restore to a sane state. : * This is basically the ring buffer and fence registers. Restoring these : * doesn't make sense without restoring GTT mappings. This is something that : * whoever gets control next should do. : */ :static void :ResetState(ScrnInfoPtr pScrn, Bool flush) :{ : I830Ptr pI830 = I830PTR(pScrn); : int i; : unsigned long temp; : : DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush)); : : if (!I830IsPrimary(pScrn)) return; : : if (pI830->entityPrivate) : pI830->entityPrivate->RingRunning = 0; : : /* Reset the fence registers to 0 */ : if (IS_I965G(pI830)) { : for (i = 0; i < FENCE_NEW_NR; i++) { : OUTREG(FENCE_NEW + i * 8, 0); : OUTREG(FENCE_NEW + 4 + i * 8, 0); : } : } else { : for (i = 0; i < FENCE_NR; i++) : OUTREG(FENCE + i * 4, 0); : } : /* Flush the ring buffer (if enabled), then disable it. */ : /* God this is ugly */ :#define flush_ring() do { \ : temp = INREG(LP_RING + RING_LEN); \ : if (temp & RING_VALID) { \ : I830RefreshRing(pScrn); \ : I830Sync(pScrn); \ : DO_RING_IDLE(); \ : } \ : } while(0) :#ifdef I830_USE_XAA : if (!pI830->useEXA && flush && pI830->AccelInfoRec) : flush_ring(); :#endif :#ifdef I830_USE_EXA : if (pI830->useEXA && flush && pI830->EXADriverPtr) : flush_ring(); :#endif : : OUTREG(LP_RING + RING_LEN, 0); : OUTREG(LP_RING + RING_HEAD, 0); : OUTREG(LP_RING + RING_TAIL, 0); : OUTREG(LP_RING + RING_START, 0); : : xf86_hide_cursors (pScrn); :} : :static void :SetFenceRegs(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : int i; : : DPRINTF(PFX, "SetFenceRegs\n"); : : if (!I830IsPrimary(pScrn)) return; : : if (IS_I965G(pI830)) { : for (i = 0; i < FENCE_NEW_NR; i++) { : OUTREG(FENCE_NEW + i * 8, pI830->fence[i]); : OUTREG(FENCE_NEW + 4 + i * 8, pI830->fence[i+FENCE_NEW_NR]); : if (I810_DEBUG & DEBUG_VERBOSE_VGA) { : ErrorF("Fence Start Register : %x\n", pI830->fence[i]); : ErrorF("Fence End Register : %x\n", pI830->fence[i+FENCE_NEW_NR]); : } : } : } else { : for (i = 0; i < FENCE_NR; i++) { : OUTREG(FENCE + i * 4, pI830->fence[i]); : if (I810_DEBUG & DEBUG_VERBOSE_VGA) : ErrorF("Fence Register : %x\n", pI830->fence[i]); : } : } :} : :static void :SetRingRegs(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : unsigned int itemp; : : DPRINTF(PFX, "SetRingRegs\n"); : : if (pI830->noAccel) : return; : : if (!I830IsPrimary(pScrn)) return; : : if (pI830->entityPrivate) : pI830->entityPrivate->RingRunning = 1; : : OUTREG(LP_RING + RING_LEN, 0); : OUTREG(LP_RING + RING_TAIL, 0); : OUTREG(LP_RING + RING_HEAD, 0); : : assert((pI830->LpRing->mem->offset & I830_RING_START_MASK) == : pI830->LpRing->mem->offset); : : /* Don't care about the old value. Reserved bits must be zero anyway. */ : itemp = pI830->LpRing->mem->offset; : OUTREG(LP_RING + RING_START, itemp); : : if (((pI830->LpRing->mem->size - 4096) & I830_RING_NR_PAGES) != : pI830->LpRing->mem->size - 4096) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its " : "mask (%x)\n", pI830->LpRing->mem->size - 4096, : I830_RING_NR_PAGES); : } : /* Don't care about the old value. Reserved bits must be zero anyway. */ : itemp = (pI830->LpRing->mem->size - 4096) & I830_RING_NR_PAGES; : itemp |= (RING_NO_REPORT | RING_VALID); : OUTREG(LP_RING + RING_LEN, itemp); : I830RefreshRing(pScrn); :} : :/* : * This should be called everytime the X server gains control of the screen, : * before any video modes are programmed (ScreenInit, EnterVT). : */ :static void :SetHWOperatingState(ScrnInfoPtr pScrn) :{ : I830Ptr pI830 = I830PTR(pScrn); : : DPRINTF(PFX, "SetHWOperatingState\n"); : : /* Disable clock gating reported to work incorrectly according to the specs. : */ : if (IS_I965GM(pI830)) { : OUTREG(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); : } else if (IS_I965G(pI830)) { : OUTREG(RENCLK_GATE_D1, : I965_RCC_CLOCK_GATE_DISABLE | I965_ISC_CLOCK_GATE_DISABLE); : } else if (IS_I855(pI830) || IS_I865G(pI830)) { : OUTREG(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); : } else if (IS_I830(pI830)) { : OUTREG(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); : } : : if (!pI830->noAccel) : SetRingRegs(pScrn); : SetFenceRegs(pScrn); : if (!pI830->SWCursor) : I830InitHWCursor(pScrn); :} : :static Bool :SaveHWState(ScrnInfoPtr pScrn) :{ : xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); : I830Ptr pI830 = I830PTR(pScrn); : vgaHWPtr hwp = VGAHWPTR(pScrn); : vgaRegPtr vgaReg = &hwp->SavedReg; : int i; : : /* Save video mode information for native mode-setting. */ : pI830->saveDSPACNTR = INREG(DSPACNTR); : pI830->savePIPEACONF = INREG(PIPEACONF); : pI830->savePIPEASRC = INREG(PIPEASRC); : pI830->saveFPA0 = INREG(FPA0); : pI830->saveFPA1 = INREG(FPA1); : pI830->saveDPLL_A = INREG(DPLL_A); : if (IS_I965G(pI830)) : pI830->saveDPLL_A_MD = INREG(DPLL_A_MD); : pI830->saveHTOTAL_A = INREG(HTOTAL_A); : pI830->saveHBLANK_A = INREG(HBLANK_A); : pI830->saveHSYNC_A = INREG(HSYNC_A); : pI830->saveVTOTAL_A = INREG(VTOTAL_A); : pI830->saveVBLANK_A = INREG(VBLANK_A); : pI830->saveVSYNC_A = INREG(VSYNC_A); : pI830->saveBCLRPAT_A = INREG(BCLRPAT_A); : pI830->saveDSPASTRIDE = INREG(DSPASTRIDE); : pI830->saveDSPASIZE = INREG(DSPASIZE); : pI830->saveDSPAPOS = INREG(DSPAPOS); : pI830->saveDSPABASE = INREG(DSPABASE); : : for(i= 0; i < 256; i++) { : pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2)); : } : : if(xf86_config->num_crtc == 2) { : pI830->savePIPEBCONF = INREG(PIPEBCONF); : pI830->savePIPEBSRC = INREG(PIPEBSRC); : pI830->saveDSPBCNTR = INREG(DSPBCNTR); : pI830->saveFPB0 = INREG(FPB0); : pI830->saveFPB1 = INREG(FPB1); : pI830->saveDPLL_B = INREG(DPLL_B); : if (IS_I965G(pI830)) : pI830->saveDPLL_B_MD = INREG(DPLL_B_MD); : pI830->saveHTOTAL_B = INREG(HTOTAL_B); : pI830->saveHBLANK_B = INREG(HBLANK_B); : pI830->saveHSYNC_B = INREG(HSYNC_B); : pI830->saveVTOTAL_B = INREG(VTOTAL_B); : pI830->saveVBLANK_B = INREG(VBLANK_B); : pI830->saveVSYNC_B = INREG(VSYNC_B); : pI830->saveBCLRPAT_B = INREG(BCLRPAT_B); : pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE); : pI830->saveDSPBSIZE = INREG(DSPBSIZE); : pI830->saveDSPBPOS = INREG(DSPBPOS); : pI830->saveDSPBBASE = INREG(DSPBBASE); : for(i= 0; i < 256; i++) { : pI830->savePaletteB[i] = INREG(PALETTE_B + (i << 2)); : } : } : : if (IS_I965G(pI830)) { : pI830->saveDSPASURF = INREG(DSPASURF); : pI830->saveDSPBSURF = INREG(DSPBSURF); : } : : pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0); : pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1); : pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV); : pI830->saveVGACNTRL = INREG(VGACNTRL); : : for(i = 0; i < 7; i++) { : pI830->saveSWF[i] = INREG(SWF0 + (i << 2)); : pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2)); : } : pI830->saveSWF[14] = INREG(SWF30); : pI830->saveSWF[15] = INREG(SWF31); : pI830->saveSWF[16] = INREG(SWF32); : : if (IS_MOBILE(pI830) && !IS_I830(pI830)) : pI830->saveLVDS = INREG(LVDS); : pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); : : for (i = 0; i < xf86_config->num_output; i++) { : xf86OutputPtr output = xf86_config->output[i]; : if (output->funcs->save) : (*output->funcs->save) (output); : } : : vgaHWUnlock(hwp); : vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS); : : return TRUE; :} : :static Bool :RestoreHWState(ScrnInfoPtr pScrn) :{ : xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); : I830Ptr pI830 = I830PTR(pScrn); : vgaHWPtr hwp = VGAHWPTR(pScrn); : vgaRegPtr vgaReg = &hwp->SavedReg; : int i; : : DPRINTF(PFX, "RestoreHWState\n"); : :#ifdef XF86DRI : I830DRISetVBlankInterrupt (pScrn, FALSE); :#endif : /* Disable outputs */ : for (i = 0; i < xf86_config->num_output; i++) { : xf86OutputPtr output = xf86_config->output[i]; : output->funcs->dpms(output, DPMSModeOff); : } : i830WaitForVblank(pScrn); : : /* Disable pipes */ : for (i = 0; i < xf86_config->num_crtc; i++) { : xf86CrtcPtr crtc = xf86_config->crtc[i]; : crtc->funcs->dpms(crtc, DPMSModeOff); : } : i830WaitForVblank(pScrn); : : if (IS_MOBILE(pI830) && !IS_I830(pI830)) : OUTREG(LVDS, pI830->saveLVDS); : : if (!IS_I830(pI830) && !IS_845G(pI830)) : OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); : : if (pI830->saveDPLL_A & DPLL_VCO_ENABLE) : { : OUTREG(DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE); : usleep(150); : } : OUTREG(FPA0, pI830->saveFPA0); : OUTREG(FPA1, pI830->saveFPA1); : OUTREG(DPLL_A, pI830->saveDPLL_A); : usleep(150); : if (IS_I965G(pI830)) : OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD); : else : OUTREG(DPLL_A, pI830->saveDPLL_A); : usleep(150); : : OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); : OUTREG(HBLANK_A, pI830->saveHBLANK_A); : OUTREG(HSYNC_A, pI830->saveHSYNC_A); : OUTREG(VTOTAL_A, pI830->saveVTOTAL_A); : OUTREG(VBLANK_A, pI830->saveVBLANK_A); : OUTREG(VSYNC_A, pI830->saveVSYNC_A); : OUTREG(BCLRPAT_A, pI830->saveBCLRPAT_A); : : OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); : OUTREG(DSPASIZE, pI830->saveDSPASIZE); : OUTREG(DSPAPOS, pI830->saveDSPAPOS); : OUTREG(PIPEASRC, pI830->savePIPEASRC); : OUTREG(DSPABASE, pI830->saveDSPABASE); : if (IS_I965G(pI830)) : OUTREG(DSPASURF, pI830->saveDSPASURF); : OUTREG(PIPEACONF, pI830->savePIPEACONF); : i830WaitForVblank(pScrn); : OUTREG(DSPACNTR, pI830->saveDSPACNTR); : OUTREG(DSPABASE, INREG(DSPABASE)); : i830WaitForVblank(pScrn); : : if(xf86_config->num_crtc == 2) : { : if (pI830->saveDPLL_B & DPLL_VCO_ENABLE) : { : OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE); : usleep(150); : } : OUTREG(FPB0, pI830->saveFPB0); : OUTREG(FPB1, pI830->saveFPB1); : OUTREG(DPLL_B, pI830->saveDPLL_B); : usleep(150); : if (IS_I965G(pI830)) : OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); : else : OUTREG(DPLL_B, pI830->saveDPLL_B); : usleep(150); : : OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); : OUTREG(HBLANK_B, pI830->saveHBLANK_B); : OUTREG(HSYNC_B, pI830->saveHSYNC_B); : OUTREG(VTOTAL_B, pI830->saveVTOTAL_B); : OUTREG(VBLANK_B, pI830->saveVBLANK_B); : OUTREG(VSYNC_B, pI830->saveVSYNC_B); : OUTREG(BCLRPAT_B, pI830->saveBCLRPAT_B); : OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); : OUTREG(DSPBSIZE, pI830->saveDSPBSIZE); : OUTREG(DSPBPOS, pI830->saveDSPBPOS); : OUTREG(PIPEBSRC, pI830->savePIPEBSRC); : OUTREG(DSPBBASE, pI830->saveDSPBBASE); : if (IS_I965G(pI830)) : OUTREG(DSPBSURF, pI830->saveDSPBSURF); : OUTREG(PIPEBCONF, pI830->savePIPEBCONF); : i830WaitForVblank(pScrn); : OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); : OUTREG(DSPBBASE, INREG(DSPBBASE)); : i830WaitForVblank(pScrn); : } : : /* Restore outputs */ : for (i = 0; i < xf86_config->num_output; i++) { : xf86OutputPtr output = xf86_config->output[i]; : if (output->funcs->restore) : output->funcs->restore(output); : } : : OUTREG(VGACNTRL, pI830->saveVGACNTRL); : : OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); : OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); : OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); : : for(i = 0; i < 256; i++) { : OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); : } : : if(xf86_config->num_crtc == 2) { : for(i= 0; i < 256; i++) { : OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]); : } : } : : for(i = 0; i < 7; i++) { : OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); : OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); : } : : OUTREG(SWF30, pI830->saveSWF[14]); : OUTREG(SWF31, pI830->saveSWF[15]); : OUTREG(SWF32, pI830->saveSWF[16]); : : vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); : vgaHWLock(hwp); : : return TRUE; :} : :static void :I830PointerMoved(int index, int x, int y) :{ : ScrnInfoPtr pScrn = xf86Screens[index]; : I830Ptr pI830 = I830PTR(pScrn); : int newX = x, newY = y; : : switch (pI830->rotation) { : case RR_Rotate_0: : break; : case RR_Rotate_90: : newX = y; : newY = pScrn->pScreen->width - x - 1; : break; : case RR_Rotate_180: : newX = pScrn->pScreen->width - x - 1; : newY = pScrn->pScreen->height - y - 1; : break; : case RR_Rotate_270: : newX = pScrn->pScreen->height - y - 1; : newY = x; : break; : } : : (*pI830->PointerMoved)(index, newX, newY); :} : :static Bool :I830InitFBManager( : ScreenPtr pScreen, : BoxPtr FullBox :){ : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : RegionRec ScreenRegion; : RegionRec FullRegion; : BoxRec ScreenBox; : Bool ret; : : ScreenBox.x1 = 0; : ScreenBox.y1 = 0; : ScreenBox.x2 = pScrn->displayWidth; : if (pScrn->virtualX > pScrn->virtualY) : ScreenBox.y2 = pScrn->virtualX; : else : ScreenBox.y2 = pScrn->virtualY; : : if((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) || : (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) { : return FALSE; : } : : if (FullBox->y2 < FullBox->y1) return FALSE; : if (FullBox->x2 < FullBox->x2) return FALSE; : : REGION_INIT(pScreen, &ScreenRegion, &ScreenBox, 1); : REGION_INIT(pScreen, &FullRegion, FullBox, 1); : : REGION_SUBTRACT(pScreen, &FullRegion, &FullRegion, &ScreenRegion); : : ret = xf86InitFBManagerRegion(pScreen, &FullRegion); : : REGION_UNINIT(pScreen, &ScreenRegion); : REGION_UNINIT(pScreen, &FullRegion); : : return ret; :} : :/** : * Intialiazes the hardware for the 3D pipeline use in the 2D driver. : * : * Some state caching is performed to avoid redundant state emits. This : * function is also responsible for marking the state as clobbered for DRI : * clients. : */ :void :IntelEmitInvarientState(ScrnInfoPtr pScrn) 3 0.0033 :{ /* IntelEmitInvarientState total: 36 0.0392 */ 3 0.0033 : I830Ptr pI830 = I830PTR(pScrn); : CARD32 ctx_addr; : 2 0.0022 : if (pI830->noAccel) : return; : :#ifdef XF86DRI 4 0.0044 : if (pI830->directRenderingEnabled) { 4 0.0044 : drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn->pScreen); : : /* Mark that the X Server was the last holder of the context */ 5 0.0054 : if (sarea) 3 0.0033 : sarea->ctxOwner = DRIGetContext(pScrn->pScreen); : } :#endif : : /* If we've emitted our state since the last clobber by another client, : * skip it. : */ 8 0.0087 : if (*pI830->last_3d != LAST_3D_OTHER) : return; : : ctx_addr = pI830->logical_context->offset; : assert((pI830->logical_context->offset & 2047) == 0); : { : BEGIN_LP_RING(2); : OUT_RING(MI_SET_CONTEXT); : OUT_RING(pI830->logical_context->offset | : CTXT_NO_RESTORE | : CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE); : ADVANCE_LP_RING(); : } : : if (!IS_I965G(pI830)) : { : if (IS_I9XX(pI830)) : I915EmitInvarientState(pScrn); : else : I830EmitInvarientState(pScrn); : } 4 0.0044 :} : :#ifdef XF86DRI_MM :#ifndef XSERVER_LIBDRM_MM : :static int :I830DrmMMInit(int drmFD, unsigned long pageOffs, unsigned long pageSize, : unsigned memType) :{ : : drm_mm_init_arg_t arg; : int ret; : : memset(&arg, 0, sizeof(arg)); : arg.req.op = mm_init; : arg.req.p_offset = pageOffs; : arg.req.p_size = pageSize; : arg.req.mem_type = memType; : : ret = ioctl(drmFD, DRM_IOCTL_MM_INIT, &arg); : : if (ret) : return -errno; : : return 0; : :} : :static int :I830DrmMMTakedown(int drmFD, unsigned memType) :{ : drm_mm_init_arg_t arg; : int ret = 0; : : memset(&arg, 0, sizeof(arg)); : arg.req.op = mm_takedown; : arg.req.mem_type = memType; : if (ioctl(drmFD, DRM_IOCTL_MM_INIT, &arg)) { : ret = -errno; : } : : return ret; :} : :static int I830DrmMMLock(int fd, unsigned memType) :{ : drm_mm_init_arg_t arg; : int ret; : : memset(&arg, 0, sizeof(arg)); : arg.req.op = mm_lock; : arg.req.mem_type = memType; : : do{ : ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg); : } while (ret && errno == EAGAIN); : : return ret; :} : :static int I830DrmMMUnlock(int fd, unsigned memType) :{ : drm_mm_init_arg_t arg; : int ret; : : memset(&arg, 0, sizeof(arg)); : arg.req.op = mm_unlock; : arg.req.mem_type = memType; : : do{ : ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg); : } while (ret && errno == EAGAIN); : : return ret; :} : :#endif :#endif /* XF86DRI_MM */ : :static Bool :I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) :{ : ScrnInfoPtr pScrn; : vgaHWPtr hwp; : I830Ptr pI830; : VisualPtr visual; : I830Ptr pI8301 = NULL; : unsigned long sys_mem; : int i; : Bool allocation_done = FALSE; : MessageType from; :#ifdef XF86DRI : Bool driDisabled; :#ifdef XF86DRI_MM : unsigned long savedMMSize; :#endif :#endif : : pScrn = xf86Screens[pScreen->myNum]; : pI830 = I830PTR(pScrn); : hwp = VGAHWPTR(pScrn); : : pScrn->displayWidth = (pScrn->virtualX + 63) & ~63; : : /* : * The "VideoRam" config file parameter specifies the maximum amount of : * memory that will be used/allocated. When not present, we allow the : * driver to allocate as much memory as it wishes to satisfy its : * allocations, but if agpgart support isn't available, it gets limited : * to the amount of pre-allocated ("stolen") memory. : * : * Note that in using this value for allocator initialization, we're : * limiting aperture allocation to the VideoRam option, rather than limiting : * actual memory allocation, so alignment and things will cause less than : * VideoRam to be actually used. : */ : if (pI830->pEnt->device->videoRam == 0) { : from = X_DEFAULT; : pScrn->videoRam = pI830->FbMapSize / KB(1); : } else { :#if 0 : from = X_CONFIG; : pScrn->videoRam = pI830->pEnt->device->videoRam; :#else : /* Disable VideoRam configuration, at least for now. Previously, : * VideoRam was necessary to avoid overly low limits on allocated : * memory, so users created larger, yet still small, fixed allocation : * limits in their config files. Now, the driver wants to allocate more, : * and the old intention of the VideoRam lines that had been entered is : * obsolete. : */ : from = X_DEFAULT; : pScrn->videoRam = pI830->FbMapSize / KB(1); : : if (pScrn->videoRam != pI830->pEnt->device->videoRam) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "VideoRam configuration found, which is no longer " : "recommended.\n"); : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "Continuing with default %dkB VideoRam instead of %d " : "kB.\n", : pScrn->videoRam, pI830->pEnt->device->videoRam); : } :#endif : } : : /* Limit videoRam to how much we might be able to allocate from AGP */ : sys_mem = I830CheckAvailableMemory(pScrn); : if (sys_mem == -1) { : if (pScrn->videoRam > pI830->stolen_size / KB(1)) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "/dev/agpgart is either not available, or no memory " : "is available\nfor allocation. " : "Using pre-allocated memory only.\n"); : pScrn->videoRam = pI830->stolen_size / KB(1); : } : pI830->StolenOnly = TRUE; : } else { : if (sys_mem + (pI830->stolen_size / 1024) < pScrn->videoRam) { : pScrn->videoRam = sys_mem + (pI830->stolen_size / 1024); : from = X_PROBED; : if (sys_mem + (pI830->stolen_size / 1024) < : pI830->pEnt->device->videoRam) : { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "VideoRAM reduced to %d kByte " : "(limited to available sysmem)\n", pScrn->videoRam); : } : } : } : : /* Limit video RAM to the actual aperture size */ : if (pScrn->videoRam > pI830->FbMapSize / 1024) { : pScrn->videoRam = pI830->FbMapSize / 1024; : if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "VideoRam reduced to %d kByte (limited to aperture " : "size)\n", : pScrn->videoRam); : } : } : : /* Make sure it's on a page boundary */ : if (pScrn->videoRam & 3) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB " : "(page aligned - was %d KB)\n", : pScrn->videoRam & ~3, pScrn->videoRam); : pScrn->videoRam &= ~3; : } : : /* Set up our video memory allocator for the chosen videoRam */ : if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Couldn't initialize video memory allocator\n"); : PreInitCleanup(pScrn); : return FALSE; : } : : xf86DrvMsg(pScrn->scrnIndex, : pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT, : "VideoRam: %d KB\n", pScrn->videoRam); : : if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES, : &(pI830->CacheLines))) { : xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n", : pI830->CacheLines); : } else { : pI830->CacheLines = -1; : } : : pI830->disableTiling = FALSE; : : if (I830IsPrimary(pScrn)) { : /* Alloc our pointers for the primary head */ : if (!pI830->LpRing) : pI830->LpRing = xcalloc(1, sizeof(I830RingBuffer)); : if (!pI830->overlayOn) : pI830->overlayOn = xalloc(sizeof(Bool)); : if (!pI830->last_3d) : pI830->last_3d = xalloc(sizeof(enum last_3d)); : if (!pI830->LpRing || !pI830->overlayOn || !pI830->last_3d) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Could not allocate primary data structures.\n"); : return FALSE; : } : *pI830->last_3d = LAST_3D_OTHER; : *pI830->overlayOn = FALSE; : if (pI830->entityPrivate) : pI830->entityPrivate->XvInUse = -1; : } else { : /* Make our second head point to the first heads structures */ : pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); : pI830->LpRing = pI8301->LpRing; : pI830->overlay_regs = pI8301->overlay_regs; : pI830->overlayOn = pI8301->overlayOn; : pI830->last_3d = pI8301->last_3d; : } : : /* Need MMIO mapped to do GTT lookups during memory allocation. */ : I830MapMMIO(pScrn); : :#if defined(XF86DRI) : /* : * If DRI is potentially usable, check if there is enough memory available : * for it, and if there's also enough to allow tiling to be enabled. : */ : : if (!I830CheckDRIAvailable(pScrn)) { : pI830->directRenderingDisabled = TRUE; :#ifdef XF86DRI_MM : pI830->mmSize = 0; :#endif : } : :#ifdef I830_XV : /* : * Set this so that the overlay allocation is factored in when : * appropriate. : */ : pI830->XvEnabled = !pI830->XvDisabled; :#endif : : if (!pI830->directRenderingDisabled) { : int savedDisplayWidth = pScrn->displayWidth; : Bool tiled = FALSE; : : if (IS_I965G(pI830)) { : int tile_pixels = 512 / pI830->cpp; : pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) & : ~(tile_pixels - 1); : tiled = TRUE; : } else { : /* Good pitches to allow tiling. Don't care about pitches < 1024 : * pixels. : */ : static const int pitches[] = { : 1024, : 2048, : 4096, : 8192, : 0 : }; : : for (i = 0; pitches[i] != 0; i++) { : if (pitches[i] >= pScrn->displayWidth) { : pScrn->displayWidth = pitches[i]; : tiled = TRUE; : break; : } : } : } : : /* Attempt several rounds of allocation to get 2d and 3d memory to fit: : * : * 0: tiled, large memory manager : * 1: tiled, small memory manager : * 2: untiled, large : * 3: untiled, small : */ : : pI830->disableTiling = FALSE; :#ifdef XF86DRI_MM : savedMMSize = pI830->mmSize; :#define MM_TURNS 4 :#else :#define MM_TURNS 2 :#endif : for (i = 0; i < MM_TURNS; i++) { : if (!tiled && i < 2) : continue; : : if (i >= MM_TURNS/2) { : /* For further allocations, disable tiling */ : pI830->disableTiling = TRUE; : pScrn->displayWidth = savedDisplayWidth; : if (pI830->allowPageFlip) : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "Couldn't allocate tiled memory, page flipping " : "disabled\n"); : pI830->allowPageFlip = FALSE; : } : :#ifdef XF86DRI_MM : if (i & 1) { : /* For this allocation, switch to a smaller DRI memory manager : * size. : */ : pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE / KB(1); : } else { : pI830->mmSize = savedMMSize; : } : : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "Attempting memory allocation with %s buffers and \n" : "\t %s DRI memory manager reservation:\n", : (i & 2) ? "untiled" : "tiled", : (i & 1) ? "small" : "large"); :#else : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "Attempting memory allocation with %s buffers:\n", : (i & 1) ? "untiled" : "tiled"); :#endif : : if (i830_allocate_2d_memory(pScrn) && : i830_allocate_3d_memory(pScrn)) : { : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Success.\n"); : if (pScrn->displayWidth != savedDisplayWidth) { : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "Increasing the scanline pitch to allow tiling mode " : "(%d -> %d).\n", : savedDisplayWidth, pScrn->displayWidth); : } : allocation_done = TRUE; : break; : } : : i830_reset_allocations(pScrn); : } : : if (i == MM_TURNS) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "Not enough video memory. Disabling DRI.\n"); :#ifdef XF86DRI_MM : pI830->mmSize = 0; :#endif : pI830->directRenderingDisabled = TRUE; : } : } else :#endif : pI830->disableTiling = TRUE; /* no DRI - so disableTiling */ : : if (!allocation_done) { : if (!i830_allocate_2d_memory(pScrn)) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Couldn't allocate video memory\n"); : return FALSE; : } : allocation_done = TRUE; : } : : I830UnmapMMIO(pScrn); : : i830_describe_allocations(pScrn, 1, ""); : : if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Cannot support DRI with frame buffer width > 2048.\n"); : pI830->disableTiling = TRUE; : pI830->directRenderingDisabled = TRUE; : } : : pScrn->displayWidth = pScrn->displayWidth; : :#ifdef HAS_MTRR_SUPPORT : { : int fd; : struct mtrr_gentry gentry; : struct mtrr_sentry sentry; : : if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) != -1 ) { : for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0; : ++gentry.regnum) { : : if (gentry.size < 1) { : /* DISABLED */ : continue; : } : : /* Check the MTRR range is one we like and if not - remove it. : * The Xserver common layer will then setup the right range : * for us. : */ : if (gentry.base == pI830->LinearAddr && : gentry.size < pI830->FbMapSize) { : : xf86DrvMsg(pScrn->scrnIndex, X_INFO, : "Removing bad MTRR range (base 0x%lx, size 0x%x)\n", : gentry.base, gentry.size); : : sentry.base = gentry.base; : sentry.size = gentry.size; : sentry.type = gentry.type; : : if (ioctl (fd, MTRRIOC_DEL_ENTRY, &sentry) == -1) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Failed to remove bad MTRR range\n"); : } : } : } : close(fd); : } : } :#endif : : pI830->starting = TRUE; : : miClearVisualTypes(); : if (!miSetVisualTypes(pScrn->depth, : miGetDefaultVisualMask(pScrn->depth), : pScrn->rgbBits, pScrn->defaultVisual)) : return FALSE; : if (!miSetPixmapDepths()) : return FALSE; : :#ifdef I830_XV : pI830->XvEnabled = !pI830->XvDisabled; : if (pI830->XvEnabled) { : if (!I830IsPrimary(pScrn)) { : if (!pI8301->XvEnabled || pI830->noAccel) { : pI830->XvEnabled = FALSE; : xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n"); : } : } else : if (pI830->noAccel || pI830->StolenOnly) { : xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled because it " : "needs 2D accel and AGPGART.\n"); : pI830->XvEnabled = FALSE; : } : } :#else : pI830->XvEnabled = FALSE; :#endif : : if (!pI830->noAccel) { : if (pI830->LpRing->mem->size == 0) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "Disabling acceleration because the ring buffer " : "allocation failed.\n"); : pI830->noAccel = TRUE; : } : } : :#ifdef I830_XV : if (pI830->XvEnabled) { : if (pI830->noAccel) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because it " : "needs 2D acceleration.\n"); : pI830->XvEnabled = FALSE; : } : if (!IS_I9XX(pI830) && pI830->overlay_regs == NULL) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "Disabling Xv because the overlay register buffer " : "allocation failed.\n"); : pI830->XvEnabled = FALSE; : } : } :#endif : :#ifdef XF86DRI : /* : * pI830->directRenderingDisabled is set once in PreInit. Reinitialise : * pI830->directRenderingEnabled based on it each generation. : */ : pI830->directRenderingEnabled = !pI830->directRenderingDisabled; : /* : * Setup DRI after visuals have been established, but before fbScreenInit : * is called. fbScreenInit will eventually call into the drivers : * InitGLXVisuals call back. : */ : : if (pI830->directRenderingEnabled) { : if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) { : xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it " : "needs HW cursor, 2D accel and AGPGART.\n"); : pI830->directRenderingEnabled = FALSE; : i830_free_3d_memory(pScrn); : } : } : : driDisabled = !pI830->directRenderingEnabled; : : if (pI830->directRenderingEnabled) : pI830->directRenderingEnabled = I830DRIScreenInit(pScreen); : : if (!pI830->directRenderingEnabled) { : i830_free_3d_memory(pScrn); : } : :#else : pI830->directRenderingEnabled = FALSE; :#endif : :#ifdef XF86DRI : if (pI830->directRenderingEnabled) : pI830->directRenderingEnabled = I830DRIDoMappings(pScreen); : : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n", : pI830->allowPageFlip ? "en" : "dis"); :#endif : : DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n"); : if (!I830MapMem(pScrn)) : return FALSE; : : pScrn->memPhysBase = (unsigned long)pI830->FbBase; : : if (I830IsPrimary(pScrn)) { : pScrn->fbOffset = pI830->front_buffer->offset; : } else { : pScrn->fbOffset = pI8301->front_buffer_2->offset; : } : : pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth; : pI830->yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth; : : vgaHWSetMmioFuncs(hwp, pI830->MMIOBase, 0); : vgaHWGetIOBase(hwp); : DPRINTF(PFX, "assert( if(!vgaHWMapMem(pScrn)) )\n"); : if (!vgaHWMapMem(pScrn)) : return FALSE; : : DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n"); : : if (!pI830->useEXA) { : if (I830IsPrimary(pScrn)) { : if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Failed to init memory manager\n"); : } : } else { : if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Failed to init memory manager\n"); : } : } : } : : if (pScrn->virtualX > pScrn->displayWidth) : pScrn->displayWidth = pScrn->virtualX; : : DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n"); : if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, : pScrn->virtualX, pScrn->virtualY, : pScrn->xDpi, pScrn->yDpi, : pScrn->displayWidth, pScrn->bitsPerPixel)) : return FALSE; : : if (pScrn->bitsPerPixel > 8) { : /* Fixup RGB ordering */ : visual = pScreen->visuals + pScreen->numVisuals; : while (--visual >= pScreen->visuals) { : if ((visual->class | DynamicClass) == DirectColor) { : visual->offsetRed = pScrn->offset.red; : visual->offsetGreen = pScrn->offset.green; : visual->offsetBlue = pScrn->offset.blue; : visual->redMask = pScrn->mask.red; : visual->greenMask = pScrn->mask.green; : visual->blueMask = pScrn->mask.blue; : } : } : } : : fbPictureInit(pScreen, NULL, 0); : : xf86SetBlackWhitePixels(pScreen); : : xf86DiDGAInit (pScreen, pI830->LinearAddr + pScrn->fbOffset); : : DPRINTF(PFX, : "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n"); : : if (!pI830->noAccel) { : if (!I830AccelInit(pScreen)) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Hardware acceleration initialization failed\n"); : } : } : : miInitializeBackingStore(pScreen); : xf86SetBackingStore(pScreen); : xf86SetSilkenMouse(pScreen); : miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); : : if (!pI830->SWCursor) { : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing HW Cursor\n"); : if (!I830CursorInit(pScreen)) : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Hardware cursor initialization failed\n"); : } else : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n"); : : if (!I830EnterVT(scrnIndex, 0)) : return FALSE; : : DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n"); : if (!miCreateDefColormap(pScreen)) : return FALSE; : : DPRINTF(PFX, "assert( if(!xf86HandleColormaps(pScreen, ...)) )\n"); : if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, NULL, : CMAP_RELOAD_ON_MODE_SWITCH | : CMAP_PALETTED_TRUECOLOR)) { : return FALSE; : } : : xf86DPMSInit(pScreen, xf86DPMSSet, 0); : :#ifdef I830_XV : /* Init video */ : if (pI830->XvEnabled) : I830InitVideo(pScreen); :#endif : :#ifdef XF86DRI : if (pI830->directRenderingEnabled) { : pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen); : } :#endif : : /* Setup 3D engine, needed for rotation too */ : IntelEmitInvarientState(pScrn); : :#ifdef XF86DRI : if (pI830->directRenderingEnabled) { : pI830->directRenderingOpen = TRUE; : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Enabled\n"); : } else { : if (driDisabled) : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n"); : else : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Failed\n"); : } :#else : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Not available\n"); :#endif : : pScreen->SaveScreen = xf86SaveScreen; : pI830->CloseScreen = pScreen->CloseScreen; : pScreen->CloseScreen = I830CloseScreen; : : if (!xf86CrtcScreenInit (pScreen)) : return FALSE; : : /* Wrap pointer motion to flip touch screen around */ : pI830->PointerMoved = pScrn->PointerMoved; : pScrn->PointerMoved = I830PointerMoved; : : if (serverGeneration == 1) : xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); : : if (IS_I965G(pI830)) { : /* turn off clock gating */ :#if 0 : OUTREG(0x6204, 0x70804000); : OUTREG(0x6208, 0x00000001); :#else : OUTREG(0x6204, 0x70000000); :#endif : /* Enable DAP stateless accesses. : * Required for all i965 steppings. : */ : OUTREG(SVG_WORK_CTL, 0x00000010); : } : : pI830->starting = FALSE; : pI830->closing = FALSE; : pI830->suspended = FALSE; : :#ifdef XF86DRI_MM : if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) : { : if (pI830->memory_manager == NULL) { : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Too little AGP aperture space for DRM memory manager.\n" : "\tPlease increase AGP aperture size from BIOS configuration screen.\n" : "\tDisabling DRI.\n"); : pI830->directRenderingOpen = FALSE; : I830DRICloseScreen(pScreen); : pI830->directRenderingEnabled = FALSE; : } else { : unsigned long aperEnd = ROUND_DOWN_TO(pI830->memory_manager->offset + : pI830->memory_manager->size, : GTT_PAGE_SIZE) / GTT_PAGE_SIZE; : unsigned long aperStart = ROUND_TO(pI830->memory_manager->offset, : GTT_PAGE_SIZE) / GTT_PAGE_SIZE; : :#ifndef XSERVER_LIBDRM_MM : if (I830DrmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart, : DRM_BO_MEM_TT)) { :#else : if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart, : DRM_BO_MEM_TT)) { :#endif : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, : "Could not initialize the DRM memory manager.\n"); : : pI830->directRenderingOpen = FALSE; : I830DRICloseScreen(pScreen); : pI830->directRenderingEnabled = FALSE; : } : } : } :#endif /* XF86DRI_MM */ : : return TRUE; :} : :static void :i830AdjustFrame(int scrnIndex, int x, int y, int flags) :{ : ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; : xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); : I830Ptr pI830 = I830PTR(pScrn); : xf86OutputPtr output = config->output[config->compat_output]; : xf86CrtcPtr crtc = output->crtc; : : DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", : x, pI830->xoffset, y, pI830->yoffset); : : if (crtc && crtc->enabled) : { : /* Sync the engine before adjust frame */ : i830WaitSync(pScrn); : i830PipeSetBase(crtc, crtc->desiredX + x, crtc->desiredY + y); : crtc->x = output->initial_x + x; : crtc->y = output->initial_y + y; : } :} : :static void :I830FreeScreen(int scrnIndex, int flags) :{ : I830FreeRec(xf86Screens[scrnIndex]); : if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) : vgaHWFreeHWRec(xf86Screens[scrnIndex]); :} : :static void :I830LeaveVT(int scrnIndex, int flags) :{ : ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; : I830Ptr pI830 = I830PTR(pScrn); : : DPRINTF(PFX, "Leave VT\n"); : : pI830->leaving = TRUE; : : if (pI830->devicesTimer) : TimerCancel(pI830->devicesTimer); : pI830->devicesTimer = NULL; : : i830SetHotkeyControl(pScrn, HOTKEY_BIOS_SWITCH); : : if (!I830IsPrimary(pScrn)) { : I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); : if (!pI8301->gtt_acquired) { : return; : } : } : :#ifdef XF86DRI : if (pI830->directRenderingOpen) { : DRILock(screenInfo.screens[pScrn->scrnIndex], 0); :#ifdef XF86DRI_MM : if (pI830->mmModeFlags & I830_KERNEL_MM) { :#ifndef XSERVER_LIBDRM_MM : I830DrmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT); :#else : drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT); :#endif : } :#endif /* XF86DRI_MM */ : I830DRISetVBlankInterrupt (pScrn, FALSE); : : drmCtlUninstHandler(pI830->drmSubFD); : } :#endif : : xf86_hide_cursors (pScrn); : : ResetState(pScrn, TRUE); : : RestoreHWState(pScrn); : : if (pI830->debug_modes) { : i830CompareRegsToSnapshot(pScrn, "After LeaveVT"); : i830DumpRegs (pScrn); : } : : if (I830IsPrimary(pScrn)) : i830_unbind_all_memory(pScrn); : if (pI830->AccelInfoRec) : pI830->AccelInfoRec->NeedToSync = FALSE; :} : :/* : * This gets called when gaining control of the VT, and from ScreenInit(). : */ :static Bool :I830EnterVT(int scrnIndex, int flags) :{ : ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; : I830Ptr pI830 = I830PTR(pScrn); : xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); : int o; : : DPRINTF(PFX, "Enter VT\n"); : : /* : * Only save state once per server generation since that's what most : * drivers do. Could change this to save state at each VT enter. : */ : if (pI830->SaveGeneration != serverGeneration) { : pI830->SaveGeneration = serverGeneration; : SaveHWState(pScrn); : } : : pI830->leaving = FALSE; : : if (I830IsPrimary(pScrn)) : if (!i830_bind_all_memory(pScrn)) : return FALSE; : : if (i830_check_error_state(pScrn)) { : xf86DrvMsg(pScrn->scrnIndex, X_WARNING, : "Existing errors found in hardware state.\n"); : } : : ResetState(pScrn, FALSE); : SetHWOperatingState(pScrn); : : /* Clear the framebuffer */ : memset(pI830->FbBase + pScrn->fbOffset, 0, : pScrn->virtualY * pScrn->displayWidth * pI830->cpp); : : for (o = 0; o < config->num_output; o++) { : xf86OutputPtr output = config->output[o]; : output->funcs->dpms(output, DPMSModeOff); : } : : if (!xf86SetDesiredModes (pScrn)) : return FALSE; : : if (pI830->debug_modes) { : xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state at EnterVT:\n"); : i830DumpRegs (pScrn); : } : i830DescribeOutputConfiguration(pScrn); : : ResetState(pScrn, TRUE); : SetHWOperatingState(pScrn); : :#ifdef XF86DRI : if (pI830->directRenderingEnabled) { : : I830DRISetVBlankInterrupt (pScrn, TRUE); : : if (!pI830->starting) { : ScreenPtr pScreen = pScrn->pScreen; : drmI830Sarea *sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); : int i; : : I830DRIResume(screenInfo.screens[scrnIndex]); : : I830RefreshRing(pScrn); : I830Sync(pScrn); : DO_RING_IDLE(); : : sarea->texAge++; : for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++) : sarea->texList[i].age = sarea->texAge; : :#ifdef XF86DRI_MM : if (pI830->mmModeFlags & I830_KERNEL_MM) { :#ifndef XSERVER_LIBDRM_MM : I830DrmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT); :#else : drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT); :#endif : } :#endif /* XF86DRI_MM */ : : DPRINTF(PFX, "calling dri unlock\n"); : DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); : } : pI830->LockHeld = 0; : } :#endif : : /* Set the hotkey to just notify us. We can check its results periodically : * in the CheckDevicesTimer. Eventually we want the kernel to just hand us : * an input event when someone presses the button, but for now we just have : * to poll. : */ : i830SetHotkeyControl(pScrn, HOTKEY_DRIVER_NOTIFY); : : if (pI830->checkDevices) : pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn); : : /* Mark 3D state as being clobbered */ : *pI830->last_3d = LAST_3D_OTHER; : : return TRUE; :} : :static Bool :I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) :{ : ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; : I830Ptr pI830 = I830PTR(pScrn); : : return xf86SetSingleMode (pScrn, mode, pI830->rotation); :} : :static Bool :I830CloseScreen(int scrnIndex, ScreenPtr pScreen) :{ : ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; : I830Ptr pI830 = I830PTR(pScrn); :#ifdef I830_USE_XAA : XAAInfoRecPtr infoPtr = pI830->AccelInfoRec; :#endif : : pI830->closing = TRUE; :#ifdef XF86DRI : if (pI830->directRenderingOpen) { :#ifdef DAMAGE : if (pI830->pDamage) { : PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); : : DamageUnregister(&pPix->drawable, pI830->pDamage); : DamageDestroy(pI830->pDamage); : pI830->pDamage = NULL; : } :#endif :#ifdef XF86DRI_MM : if (pI830->mmModeFlags & I830_KERNEL_MM) { :#ifndef XSERVER_LIBDRM_MM : I830DrmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT); :#else : drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT); :#endif : } :#endif /* XF86DRI_MM */ : pI830->directRenderingOpen = FALSE; : I830DRICloseScreen(pScreen); : } :#endif : : if (pScrn->vtSema == TRUE) { : I830LeaveVT(scrnIndex, 0); : } : : if (pI830->devicesTimer) : TimerCancel(pI830->devicesTimer); : pI830->devicesTimer = NULL; : : DPRINTF(PFX, "\nUnmapping memory\n"); : I830UnmapMem(pScrn); : vgaHWUnmapMem(pScrn); : : if (pI830->ScanlineColorExpandBuffers) { : xfree(pI830->ScanlineColorExpandBuffers); : pI830->ScanlineColorExpandBuffers = NULL; : } :#ifdef I830_USE_XAA : if (infoPtr) { : if (infoPtr->ScanlineColorExpandBuffers) : xfree(infoPtr->ScanlineColorExpandBuffers); : XAADestroyInfoRec(infoPtr); : pI830->AccelInfoRec = NULL; : } :#endif :#ifdef I830_USE_EXA : if (pI830->useEXA && pI830->EXADriverPtr) { : exaDriverFini(pScreen); : xfree(pI830->EXADriverPtr); : pI830->EXADriverPtr = NULL; : } :#endif : xf86_cursors_fini (pScreen); : : i830_reset_allocations(pScrn); : : if (I830IsPrimary(pScrn)) { : xf86GARTCloseScreen(scrnIndex); : : xfree(pI830->LpRing); : pI830->LpRing = NULL; : xfree(pI830->overlayOn); : pI830->overlayOn = NULL; : xfree(pI830->last_3d); : pI830->last_3d = NULL; : } : : pScrn->PointerMoved = pI830->PointerMoved; : pScrn->vtSema = FALSE; : pI830->closing = FALSE; : pScreen->CloseScreen = pI830->CloseScreen; : return (*pScreen->CloseScreen) (scrnIndex, pScreen); :} : :static ModeStatus :I830ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) :{ : if (mode->Flags & V_INTERLACE) { : if (verbose) { : xf86DrvMsg(scrnIndex, X_PROBED, : "Removing interlaced mode \"%s\"\n", mode->name); : } : return MODE_BAD; : } : return MODE_OK; :} : :#ifndef SUSPEND_SLEEP :#define SUSPEND_SLEEP 0 :#endif :#ifndef RESUME_SLEEP :#define RESUME_SLEEP 0 :#endif : :/* : * This function is only required if we need to do anything differently from : * DoApmEvent() in common/xf86PM.c, including if we want to see events other : * than suspend/resume. : */ :static Bool :I830PMEvent(int scrnIndex, pmEvent event, Bool undo) :{ : ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; : I830Ptr pI830 = I830PTR(pScrn); : : DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event, BOOLTOSTRING(undo)); : : switch(event) { : case XF86_APM_SYS_SUSPEND: : case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/ : case XF86_APM_USER_SUSPEND: : case XF86_APM_SYS_STANDBY: : case XF86_APM_USER_STANDBY: : if (!undo && !pI830->suspended) { : pScrn->LeaveVT(scrnIndex, 0); : pI830->suspended = TRUE; : sleep(SUSPEND_SLEEP); : } else if (undo && pI830->suspended) { : sleep(RESUME_SLEEP); : pScrn->EnterVT(scrnIndex, 0); : pI830->suspended = FALSE; : } : break; : case XF86_APM_STANDBY_RESUME: : case XF86_APM_NORMAL_RESUME: : case XF86_APM_CRITICAL_RESUME: : if (pI830->suspended) { : sleep(RESUME_SLEEP); : pScrn->EnterVT(scrnIndex, 0); : pI830->suspended = FALSE; : /* : * Turn the screen saver off when resuming. This seems to be : * needed to stop xscreensaver kicking in (when used). : * : * XXX DoApmEvent() should probably call this just like : * xf86VTSwitch() does. Maybe do it here only in 4.2 : * compatibility mode. : */ : SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); : } : break; : /* This is currently used for ACPI */ : case XF86_APM_CAPABILITY_CHANGED: :#if 0 : /* If we had status checking turned on, turn it off now */ : if (pI830->checkDevices) { : if (pI830->devicesTimer) : TimerCancel(pI830->devicesTimer); : pI830->devicesTimer = NULL; : pI830->checkDevices = FALSE; : } :#endif : if (!I830IsPrimary(pScrn)) : return TRUE; : : ErrorF("I830PMEvent: Capability change\n"); : : I830CheckDevicesTimer(NULL, 0, pScrn); : SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); : break; : default: : ErrorF("I830PMEvent: received APM event %d\n", event); : } : return TRUE; :} : :#if 0 :/** : * This function is used for testing of the screen detect functions from the : * periodic timer. : */ :static void :i830MonitorDetectDebugger(ScrnInfoPtr pScrn) :{ : Bool found_crt; : I830Ptr pI830 = I830PTR(pScrn); : int start, finish, i; : : if (!pScrn->vtSema) : return 1000; : : for (i = 0; i < xf86_config->num_output; i++) { : enum output_status ret; : char *result; : : start = GetTimeInMillis(); : ret = pI830->output[i].detect(pScrn, &pI830->output[i]); : finish = GetTimeInMillis(); : : if (ret == OUTPUT_STATUS_CONNECTED) : result = "connected"; : else if (ret == OUTPUT_STATUS_DISCONNECTED) : result = "disconnected"; : else : result = "unknown"; : : xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n", : result, finish - start); : } :} :#endif : :static CARD32 :I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) :{ : ScrnInfoPtr pScrn = (ScrnInfoPtr) arg; : I830Ptr pI830 = I830PTR(pScrn); : CARD8 gr18; : : if (!pScrn->vtSema) : return 1000; : :#if 0 : i830MonitorDetectDebugger(pScrn); :#endif : : /* Check for a hotkey press report from the BIOS. */ : gr18 = pI830->readControl(pI830, GRX, 0x18); : if ((gr18 & (HOTKEY_TOGGLE | HOTKEY_SWITCH)) != 0) { : /* The user has pressed the hotkey requesting a toggle or switch. : * Re-probe our connected displays and turn on whatever we find. : * : * In the future, we want the hotkey to dump down to a user app which : * implements a sensible policy using RandR-1.2. For now, all we get : * is this. : */ : : xf86ProbeOutputModes (pScrn, 0, 0); : xf86SetScrnInfoModes (pScrn); : xf86DiDGAReInit (pScrn->pScreen); : xf86SwitchMode(pScrn->pScreen, pScrn->currentMode); : : /* Clear the BIOS's hotkey press flags */ : gr18 &= ~(HOTKEY_TOGGLE | HOTKEY_SWITCH); : pI830->writeControl(pI830, GRX, 0x18, gr18); : } : : return 1000; :} : :void :i830WaitSync(ScrnInfoPtr pScrn) 31 0.0338 :{ /* i830WaitSync total: 103 0.1122 */ 1 0.0011 : I830Ptr pI830 = I830PTR(pScrn); : :#ifdef I830_USE_XAA 15 0.0163 : if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec : && pI830->AccelInfoRec->NeedToSync) { : (*pI830->AccelInfoRec->Sync)(pScrn); : pI830->AccelInfoRec->NeedToSync = FALSE; : } :#endif :#ifdef I830_USE_EXA 6 0.0065 : if (!pI830->noAccel && pI830->useEXA && pI830->EXADriverPtr) { : ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; 21 0.0229 : exaWaitSync(pScreen); : } :#endif 29 0.0316 :} : :void :i830MarkSync(ScrnInfoPtr pScrn) 7 0.0076 :{ /* i830MarkSync total: 15 0.0163 */ : I830Ptr pI830 = I830PTR(pScrn); : :#ifdef I830_USE_XAA : if (!pI830->useEXA && pI830->AccelInfoRec) : pI830->AccelInfoRec->NeedToSync = TRUE; :#endif :#ifdef I830_USE_EXA 2 0.0022 : if (pI830->useEXA && pI830->EXADriverPtr) { : ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; 3 0.0033 : exaMarkSync(pScreen); : } :#endif 3 0.0033 :} : :void :I830InitpScrn(ScrnInfoPtr pScrn) :{ : pScrn->PreInit = I830PreInit; : pScrn->ScreenInit = I830ScreenInit; : pScrn->SwitchMode = I830SwitchMode; : pScrn->AdjustFrame = i830AdjustFrame; : pScrn->EnterVT = I830EnterVT; : pScrn->LeaveVT = I830LeaveVT; : pScrn->FreeScreen = I830FreeScreen; : pScrn->ValidMode = I830ValidMode; : pScrn->PMEvent = I830PMEvent; :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/mi/misprite.c" * * 140 0.1525 */ :/* : * misprite.c : * : * machine independent software sprite routines : */ : : :/* : :Copyright 1989, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. :*/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :# include :# include :# include "misc.h" :# include "pixmapstr.h" :# include "input.h" :# include "mi.h" :# include "cursorstr.h" :# include :# include "scrnintstr.h" :# include "colormapst.h" :# include "windowstr.h" :# include "gcstruct.h" :# include "mipointer.h" :# include "mispritest.h" :# include "dixfontstr.h" :# include : :#ifdef RENDER :# include "mipict.h" :#endif :# include "damage.h" : :#define SPRITE_DEBUG_ENABLE 0 :#if SPRITE_DEBUG_ENABLE :#define SPRITE_DEBUG(x) ErrorF x :#else :#define SPRITE_DEBUG(x) :#endif : :/* : * screen wrappers : */ : :static int miSpriteScreenIndex; :static unsigned long miSpriteGeneration = 0; : :static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); :static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, : int w, int h, unsigned int format, : unsigned long planemask, char *pdstLine); :static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, : DDXPointPtr ppt, int *pwidth, int nspans, : char *pdstStart); :static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, : int width, int height); :static void miSpriteCopyWindow (WindowPtr pWindow, : DDXPointRec ptOldOrg, : RegionPtr prgnSrc); :static void miSpriteBlockHandler(int i, pointer blockData, : pointer pTimeout, : pointer pReadMask); :static void miSpriteInstallColormap(ColormapPtr pMap); :static void miSpriteStoreColors(ColormapPtr pMap, int ndef, : xColorItem *pdef); : :static void miSpriteSaveDoomedAreas(WindowPtr pWin, : RegionPtr pObscured, int dx, : int dy); :static void miSpriteComputeSaved(ScreenPtr pScreen); : :#define SCREEN_PROLOGUE(pScreen, field)\ : ((pScreen)->field = \ : ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field) : :#define SCREEN_EPILOGUE(pScreen, field)\ : ((pScreen)->field = miSprite##field) : :/* : * pointer-sprite method table : */ : :static Bool miSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); :static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); :static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor, : int x, int y); :static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y); : :_X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = { : miSpriteRealizeCursor, : miSpriteUnrealizeCursor, : miSpriteSetCursor, : miSpriteMoveCursor, :}; : :/* : * other misc functions : */ : :static void miSpriteRemoveCursor(ScreenPtr pScreen); :static void miSpriteRestoreCursor(ScreenPtr pScreen); : :static void :miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) :{ : ScreenPtr pScreen = closure; : miSpriteScreenPtr pScreenPriv; : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : : if (pScreenPriv->isUp && : RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) : { : SPRITE_DEBUG(("Damage remove\n")); : miSpriteRemoveCursor (pScreen); : } :} : :/* : * miSpriteInitialize -- called from device-dependent screen : * initialization proc after all of the function pointers have : * been stored in the screen structure. : */ : :Bool :miSpriteInitialize (pScreen, cursorFuncs, screenFuncs) : ScreenPtr pScreen; : miSpriteCursorFuncPtr cursorFuncs; : miPointerScreenFuncPtr screenFuncs; :{ : miSpriteScreenPtr pScreenPriv; : VisualPtr pVisual; : : if (!DamageSetup (pScreen)) : return FALSE; : : if (miSpriteGeneration != serverGeneration) : { : miSpriteScreenIndex = AllocateScreenPrivateIndex (); : if (miSpriteScreenIndex < 0) : return FALSE; : miSpriteGeneration = serverGeneration; : } : : pScreenPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec)); : if (!pScreenPriv) : return FALSE; : : pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, : (DamageDestroyFunc) 0, : DamageReportRawRegion, : TRUE, : pScreen, : (void *) pScreen); : : if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) : { : xfree ((pointer) pScreenPriv); : return FALSE; : } : for (pVisual = pScreen->visuals; : pVisual->vid != pScreen->rootVisual; : pVisual++) : ; : pScreenPriv->pVisual = pVisual; : pScreenPriv->CloseScreen = pScreen->CloseScreen; : pScreenPriv->GetImage = pScreen->GetImage; : pScreenPriv->GetSpans = pScreen->GetSpans; : pScreenPriv->SourceValidate = pScreen->SourceValidate; : : pScreenPriv->CopyWindow = pScreen->CopyWindow; : : pScreenPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas; : : pScreenPriv->InstallColormap = pScreen->InstallColormap; : pScreenPriv->StoreColors = pScreen->StoreColors; : : pScreenPriv->BlockHandler = pScreen->BlockHandler; : : pScreenPriv->pCursor = NULL; : pScreenPriv->x = 0; : pScreenPriv->y = 0; : pScreenPriv->isUp = FALSE; : pScreenPriv->shouldBeUp = FALSE; : pScreenPriv->pCacheWin = NullWindow; : pScreenPriv->isInCacheWin = FALSE; : pScreenPriv->checkPixels = TRUE; : pScreenPriv->pInstalledMap = NULL; : pScreenPriv->pColormap = NULL; : pScreenPriv->funcs = cursorFuncs; : pScreenPriv->colors[SOURCE_COLOR].red = 0; : pScreenPriv->colors[SOURCE_COLOR].green = 0; : pScreenPriv->colors[SOURCE_COLOR].blue = 0; : pScreenPriv->colors[MASK_COLOR].red = 0; : pScreenPriv->colors[MASK_COLOR].green = 0; : pScreenPriv->colors[MASK_COLOR].blue = 0; : pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv; : : pScreen->CloseScreen = miSpriteCloseScreen; : pScreen->GetImage = miSpriteGetImage; : pScreen->GetSpans = miSpriteGetSpans; : pScreen->SourceValidate = miSpriteSourceValidate; : : pScreen->CopyWindow = miSpriteCopyWindow; : : pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas; : : pScreen->InstallColormap = miSpriteInstallColormap; : pScreen->StoreColors = miSpriteStoreColors; : : pScreen->BlockHandler = miSpriteBlockHandler; : : return TRUE; :} : :/* : * Screen wrappers : */ : :/* : * CloseScreen wrapper -- unwrap everything, free the private data : * and call the wrapped function : */ : :static Bool :miSpriteCloseScreen (i, pScreen) : int i; : ScreenPtr pScreen; :{ : miSpriteScreenPtr pScreenPriv; : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : : pScreen->CloseScreen = pScreenPriv->CloseScreen; : pScreen->GetImage = pScreenPriv->GetImage; : pScreen->GetSpans = pScreenPriv->GetSpans; : pScreen->SourceValidate = pScreenPriv->SourceValidate; : pScreen->BlockHandler = pScreenPriv->BlockHandler; : pScreen->InstallColormap = pScreenPriv->InstallColormap; : pScreen->StoreColors = pScreenPriv->StoreColors; : : pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas; : miSpriteIsUpFALSE (pScreen, pScreenPriv); : DamageDestroy (pScreenPriv->pDamage); : : xfree ((pointer) pScreenPriv); : : return (*pScreen->CloseScreen) (i, pScreen); :} : :static void :miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) : DrawablePtr pDrawable; : int sx, sy, w, h; : unsigned int format; : unsigned long planemask; : char *pdstLine; :{ : ScreenPtr pScreen = pDrawable->pScreen; : miSpriteScreenPtr pScreenPriv; : : SCREEN_PROLOGUE (pScreen, GetImage); : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : : if (pDrawable->type == DRAWABLE_WINDOW && : pScreenPriv->isUp && : ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h)) : { : SPRITE_DEBUG (("GetImage remove\n")); : miSpriteRemoveCursor (pScreen); : } : : (*pScreen->GetImage) (pDrawable, sx, sy, w, h, : format, planemask, pdstLine); : : SCREEN_EPILOGUE (pScreen, GetImage); :} : :static void :miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) : DrawablePtr pDrawable; : int wMax; : DDXPointPtr ppt; : int *pwidth; : int nspans; : char *pdstStart; :{ : ScreenPtr pScreen = pDrawable->pScreen; : miSpriteScreenPtr pScreenPriv; : : SCREEN_PROLOGUE (pScreen, GetSpans); : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : : if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp) : { : DDXPointPtr pts; : int *widths; : int nPts; : int xorg, : yorg; : : xorg = pDrawable->x; : yorg = pDrawable->y; : : for (pts = ppt, widths = pwidth, nPts = nspans; : nPts--; : pts++, widths++) : { : if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg, : pts->x+xorg,*widths)) : { : SPRITE_DEBUG (("GetSpans remove\n")); : miSpriteRemoveCursor (pScreen); : break; : } : } : } : : (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); : : SCREEN_EPILOGUE (pScreen, GetSpans); :} : :static void :miSpriteSourceValidate (pDrawable, x, y, width, height) : DrawablePtr pDrawable; : int x, y, width, height; 31 0.0338 :{ /* miSpriteSourceValidate total: 140 0.1525 */ : ScreenPtr pScreen = pDrawable->pScreen; : miSpriteScreenPtr pScreenPriv; : 55 0.0599 : SCREEN_PROLOGUE (pScreen, SourceValidate); : 7 0.0076 : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : : if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp && : ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y, : x, y, width, height)) : { : SPRITE_DEBUG (("SourceValidate remove\n")); : miSpriteRemoveCursor (pScreen); : } : 26 0.0283 : if (pScreen->SourceValidate) : (*pScreen->SourceValidate) (pDrawable, x, y, width, height); : 5 0.0054 : SCREEN_EPILOGUE (pScreen, SourceValidate); 16 0.0174 :} : :static void :miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) :{ : ScreenPtr pScreen = pWindow->drawable.pScreen; : miSpriteScreenPtr pScreenPriv; : : SCREEN_PROLOGUE (pScreen, CopyWindow); : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : /* : * Damage will take care of destination check : */ : if (pScreenPriv->isUp && : RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->saved) != rgnOUT) : { : SPRITE_DEBUG (("CopyWindow remove\n")); : miSpriteRemoveCursor (pScreen); : } : : (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); : SCREEN_EPILOGUE (pScreen, CopyWindow); :} : :static void :miSpriteBlockHandler (i, blockData, pTimeout, pReadmask) : int i; : pointer blockData; : pointer pTimeout; : pointer pReadmask; :{ : ScreenPtr pScreen = screenInfo.screens[i]; : miSpriteScreenPtr pPriv; : : pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : : SCREEN_PROLOGUE(pScreen, BlockHandler); : : (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); : : SCREEN_EPILOGUE(pScreen, BlockHandler); : : if (!pPriv->isUp && pPriv->shouldBeUp) : { : SPRITE_DEBUG (("BlockHandler restore\n")); : miSpriteRestoreCursor (pScreen); : } :} : :static void :miSpriteInstallColormap (pMap) : ColormapPtr pMap; :{ : ScreenPtr pScreen = pMap->pScreen; : miSpriteScreenPtr pPriv; : : pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : : SCREEN_PROLOGUE(pScreen, InstallColormap); : : (*pScreen->InstallColormap) (pMap); : : SCREEN_EPILOGUE(pScreen, InstallColormap); : : pPriv->pInstalledMap = pMap; : if (pPriv->pColormap != pMap) : { : pPriv->checkPixels = TRUE; : if (pPriv->isUp) : miSpriteRemoveCursor (pScreen); : } :} : :static void :miSpriteStoreColors (pMap, ndef, pdef) : ColormapPtr pMap; : int ndef; : xColorItem *pdef; :{ : ScreenPtr pScreen = pMap->pScreen; : miSpriteScreenPtr pPriv; : int i; : int updated; : VisualPtr pVisual; : : pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : : SCREEN_PROLOGUE(pScreen, StoreColors); : : (*pScreen->StoreColors) (pMap, ndef, pdef); : : SCREEN_EPILOGUE(pScreen, StoreColors); : : if (pPriv->pColormap == pMap) : { : updated = 0; : pVisual = pMap->pVisual; : if (pVisual->class == DirectColor) : { : /* Direct color - match on any of the subfields */ : :#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) : :#define UpdateDAC(plane,dac,mask) {\ : if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\ : pPriv->colors[plane].dac = pdef[i].dac; \ : updated = 1; \ : } \ :} : :#define CheckDirect(plane) \ : UpdateDAC(plane,red,redMask) \ : UpdateDAC(plane,green,greenMask) \ : UpdateDAC(plane,blue,blueMask) : : for (i = 0; i < ndef; i++) : { : CheckDirect (SOURCE_COLOR) : CheckDirect (MASK_COLOR) : } : } : else : { : /* PseudoColor/GrayScale - match on exact pixel */ : for (i = 0; i < ndef; i++) : { : if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) : { : pPriv->colors[SOURCE_COLOR] = pdef[i]; : if (++updated == 2) : break; : } : if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) : { : pPriv->colors[MASK_COLOR] = pdef[i]; : if (++updated == 2) : break; : } : } : } : if (updated) : { : pPriv->checkPixels = TRUE; : if (pPriv->isUp) : miSpriteRemoveCursor (pScreen); : } : } :} : :static void :miSpriteFindColors (ScreenPtr pScreen) :{ : miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr) : pScreen->devPrivates[miSpriteScreenIndex].ptr; : CursorPtr pCursor; : xColorItem *sourceColor, *maskColor; : : pCursor = pScreenPriv->pCursor; : sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; : maskColor = &pScreenPriv->colors[MASK_COLOR]; : if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || : !(pCursor->foreRed == sourceColor->red && : pCursor->foreGreen == sourceColor->green && : pCursor->foreBlue == sourceColor->blue && : pCursor->backRed == maskColor->red && : pCursor->backGreen == maskColor->green && : pCursor->backBlue == maskColor->blue)) : { : pScreenPriv->pColormap = pScreenPriv->pInstalledMap; : sourceColor->red = pCursor->foreRed; : sourceColor->green = pCursor->foreGreen; : sourceColor->blue = pCursor->foreBlue; : FakeAllocColor (pScreenPriv->pColormap, sourceColor); : maskColor->red = pCursor->backRed; : maskColor->green = pCursor->backGreen; : maskColor->blue = pCursor->backBlue; : FakeAllocColor (pScreenPriv->pColormap, maskColor); : /* "free" the pixels right away, don't let this confuse you */ : FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); : FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); : } : pScreenPriv->checkPixels = FALSE; :} : :/* : * BackingStore wrappers : */ : :static void :miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy) : WindowPtr pWin; : RegionPtr pObscured; : int dx, dy; :{ : ScreenPtr pScreen; : miSpriteScreenPtr pScreenPriv; : BoxRec cursorBox; : : pScreen = pWin->drawable.pScreen; : : SCREEN_PROLOGUE (pScreen, SaveDoomedAreas); : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : if (pScreenPriv->isUp) : { : cursorBox = pScreenPriv->saved; : : if (dx || dy) : { : cursorBox.x1 += dx; : cursorBox.y1 += dy; : cursorBox.x2 += dx; : cursorBox.y2 += dy; : } : if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT) : miSpriteRemoveCursor (pScreen); : } : : (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy); : : SCREEN_EPILOGUE (pScreen, SaveDoomedAreas); :} : :/* : * miPointer interface routines : */ : :#define SPRITE_PAD 8 : :static Bool :miSpriteRealizeCursor (pScreen, pCursor) : ScreenPtr pScreen; : CursorPtr pCursor; :{ : miSpriteScreenPtr pScreenPriv; : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : if (pCursor == pScreenPriv->pCursor) : pScreenPriv->checkPixels = TRUE; : return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); :} : :static Bool :miSpriteUnrealizeCursor (pScreen, pCursor) : ScreenPtr pScreen; : CursorPtr pCursor; :{ : miSpriteScreenPtr pScreenPriv; : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); :} : :static void :miSpriteSetCursor (pScreen, pCursor, x, y) : ScreenPtr pScreen; : CursorPtr pCursor; : int x; : int y; :{ : miSpriteScreenPtr pScreenPriv; : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : if (!pCursor) : { : pScreenPriv->shouldBeUp = FALSE; : if (pScreenPriv->isUp) : miSpriteRemoveCursor (pScreen); : pScreenPriv->pCursor = 0; : return; : } : pScreenPriv->shouldBeUp = TRUE; : if (pScreenPriv->x == x && : pScreenPriv->y == y && : pScreenPriv->pCursor == pCursor && : !pScreenPriv->checkPixels) : { : return; : } : pScreenPriv->x = x; : pScreenPriv->y = y; : pScreenPriv->pCacheWin = NullWindow; : if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor) : { : pScreenPriv->pCursor = pCursor; : miSpriteFindColors (pScreen); : } : if (pScreenPriv->isUp) { : int sx, sy; : /* : * check to see if the old saved region : * encloses the new sprite, in which case we use : * the flicker-free MoveCursor primitive. : */ : sx = pScreenPriv->x - (int)pCursor->bits->xhot; : sy = pScreenPriv->y - (int)pCursor->bits->yhot; : if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 && : sx < pScreenPriv->saved.x2 && : sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 && : sy < pScreenPriv->saved.y2 && : (int) pCursor->bits->width + (2 * SPRITE_PAD) == : pScreenPriv->saved.x2 - pScreenPriv->saved.x1 && : (int) pCursor->bits->height + (2 * SPRITE_PAD) == : pScreenPriv->saved.y2 - pScreenPriv->saved.y1 : ) : { : DamageDrawInternal (pScreen, TRUE); : miSpriteIsUpFALSE (pScreen, pScreenPriv); : if (!(sx >= pScreenPriv->saved.x1 && : sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 && : sy >= pScreenPriv->saved.y1 && : sy + (int)pCursor->bits->height < pScreenPriv->saved.y2)) : { : int oldx1, oldy1, dx, dy; : : oldx1 = pScreenPriv->saved.x1; : oldy1 = pScreenPriv->saved.y1; : dx = oldx1 - (sx - SPRITE_PAD); : dy = oldy1 - (sy - SPRITE_PAD); : pScreenPriv->saved.x1 -= dx; : pScreenPriv->saved.y1 -= dy; : pScreenPriv->saved.x2 -= dx; : pScreenPriv->saved.y2 -= dy; : (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, : pScreenPriv->saved.x1, : pScreenPriv->saved.y1, : pScreenPriv->saved.x2 - pScreenPriv->saved.x1, : pScreenPriv->saved.y2 - pScreenPriv->saved.y1, : dx, dy); : } : (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, : pScreenPriv->saved.x1, : pScreenPriv->saved.y1, : pScreenPriv->saved.x2 - pScreenPriv->saved.x1, : pScreenPriv->saved.y2 - pScreenPriv->saved.y1, : sx - pScreenPriv->saved.x1, : sy - pScreenPriv->saved.y1, : pScreenPriv->colors[SOURCE_COLOR].pixel, : pScreenPriv->colors[MASK_COLOR].pixel); : miSpriteIsUpTRUE (pScreen, pScreenPriv); : DamageDrawInternal (pScreen, FALSE); : } : else : { : SPRITE_DEBUG (("SetCursor remove\n")); : miSpriteRemoveCursor (pScreen); : } : } : if (!pScreenPriv->isUp && pScreenPriv->pCursor) : { : SPRITE_DEBUG (("SetCursor restore\n")); : miSpriteRestoreCursor (pScreen); : } :} : :static void :miSpriteMoveCursor (pScreen, x, y) : ScreenPtr pScreen; : int x, y; :{ : miSpriteScreenPtr pScreenPriv; : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y); :} : :/* : * undraw/draw cursor : */ : :static void :miSpriteRemoveCursor (pScreen) : ScreenPtr pScreen; :{ : miSpriteScreenPtr pScreenPriv; : : DamageDrawInternal (pScreen, TRUE); : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : miSpriteIsUpFALSE (pScreen, pScreenPriv); : pScreenPriv->pCacheWin = NullWindow; : if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen, : pScreenPriv->saved.x1, : pScreenPriv->saved.y1, : pScreenPriv->saved.x2 - pScreenPriv->saved.x1, : pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) : { : miSpriteIsUpTRUE (pScreen, pScreenPriv); : } : DamageDrawInternal (pScreen, FALSE); :} : :/* : * Called from the block handler, restores the cursor : * before waiting for something to do. : */ : :static void :miSpriteRestoreCursor (pScreen) : ScreenPtr pScreen; :{ : miSpriteScreenPtr pScreenPriv; : int x, y; : CursorPtr pCursor; : : DamageDrawInternal (pScreen, TRUE); : miSpriteComputeSaved (pScreen); : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : pCursor = pScreenPriv->pCursor; : x = pScreenPriv->x - (int)pCursor->bits->xhot; : y = pScreenPriv->y - (int)pCursor->bits->yhot; : if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen, : pScreenPriv->saved.x1, : pScreenPriv->saved.y1, : pScreenPriv->saved.x2 - pScreenPriv->saved.x1, : pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) : { : if (pScreenPriv->checkPixels) : miSpriteFindColors (pScreen); : if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y, : pScreenPriv->colors[SOURCE_COLOR].pixel, : pScreenPriv->colors[MASK_COLOR].pixel)) : { : miSpriteIsUpTRUE (pScreen, pScreenPriv); : } : } : DamageDrawInternal (pScreen, FALSE); :} : :/* : * compute the desired area of the screen to save : */ : :static void :miSpriteComputeSaved (pScreen) : ScreenPtr pScreen; :{ : miSpriteScreenPtr pScreenPriv; : int x, y, w, h; : int wpad, hpad; : CursorPtr pCursor; : : pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; : pCursor = pScreenPriv->pCursor; : x = pScreenPriv->x - (int)pCursor->bits->xhot; : y = pScreenPriv->y - (int)pCursor->bits->yhot; : w = pCursor->bits->width; : h = pCursor->bits->height; : wpad = SPRITE_PAD; : hpad = SPRITE_PAD; : pScreenPriv->saved.x1 = x - wpad; : pScreenPriv->saved.y1 = y - hpad; : pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2; : pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2; :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbcopy.c" * * 127 0.1384 */ :/* : * Copyright © 1998 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include : :#include "fb.h" : :void :fbCopyNtoN (DrawablePtr pSrcDrawable, : DrawablePtr pDstDrawable, : GCPtr pGC, : BoxPtr pbox, : int nbox, : int dx, : int dy, : Bool reverse, : Bool upsidedown, : Pixel bitplane, : void *closure) :{ : CARD8 alu = pGC ? pGC->alu : GXcopy; : FbBits pm = pGC ? fbGetGCPrivate(pGC)->pm : FB_ALLONES; : FbBits *src; : FbStride srcStride; : int srcBpp; : int srcXoff, srcYoff; : FbBits *dst; : FbStride dstStride; : int dstBpp; : int dstXoff, dstYoff; : : fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); : fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); : : while (nbox--) : { :#ifndef FB_ACCESS_WRAPPER /* pixman_blt() doesn't support accessors yet */ : if (pm == FB_ALLONES && alu == GXcopy && !reverse && : !upsidedown) : { : if (!pixman_blt ((uint32_t *)src, (uint32_t *)dst, srcStride, dstStride, srcBpp, dstBpp, : (pbox->x1 + dx + srcXoff), : (pbox->y1 + dy + srcYoff), : (pbox->x1 + srcXoff), : (pbox->y1 + srcYoff), : (pbox->x2 - pbox->x1), : (pbox->y2 - pbox->y1))) : goto fallback; : else : goto next; : } : fallback: :#endif : fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride, : srcStride, : (pbox->x1 + dx + srcXoff) * srcBpp, : : dst + (pbox->y1 + dstYoff) * dstStride, : dstStride, : (pbox->x1 + dstXoff) * dstBpp, : : (pbox->x2 - pbox->x1) * dstBpp, : (pbox->y2 - pbox->y1), : : alu, : pm, : dstBpp, : : reverse, : upsidedown); :#ifndef FB_ACCESS_WRAPPER : next: :#endif : pbox++; : } : fbFinishAccess (pDstDrawable); : fbFinishAccess (pSrcDrawable); :} : :void :fbCopy1toN (DrawablePtr pSrcDrawable, : DrawablePtr pDstDrawable, : GCPtr pGC, : BoxPtr pbox, : int nbox, : int dx, : int dy, : Bool reverse, : Bool upsidedown, : Pixel bitplane, : void *closure) :{ : FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); : FbBits *src; : FbStride srcStride; : int srcBpp; : int srcXoff, srcYoff; : FbBits *dst; : FbStride dstStride; : int dstBpp; : int dstXoff, dstYoff; : : fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); : fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); : : while (nbox--) : { : if (dstBpp == 1) : { : fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride, : srcStride, : (pbox->x1 + dx + srcXoff) * srcBpp, : : dst + (pbox->y1 + dstYoff) * dstStride, : dstStride, : (pbox->x1 + dstXoff) * dstBpp, : : (pbox->x2 - pbox->x1) * dstBpp, : (pbox->y2 - pbox->y1), : : FbOpaqueStipple1Rop(pGC->alu, : pGC->fgPixel,pGC->bgPixel), : pPriv->pm, : dstBpp, : : reverse, : upsidedown); : } : else : { : fbBltOne ((FbStip *) (src + (pbox->y1 + dy + srcYoff) * srcStride), : srcStride*(FB_UNIT/FB_STIP_UNIT), : (pbox->x1 + dx + srcXoff), : : dst + (pbox->y1 + dstYoff) * dstStride, : dstStride, : (pbox->x1 + dstXoff) * dstBpp, : dstBpp, : : (pbox->x2 - pbox->x1) * dstBpp, : (pbox->y2 - pbox->y1), : : pPriv->and, pPriv->xor, : pPriv->bgand, pPriv->bgxor); : } : pbox++; : } : : fbFinishAccess (pDstDrawable); : fbFinishAccess (pSrcDrawable); :} : :void :fbCopyNto1 (DrawablePtr pSrcDrawable, : DrawablePtr pDstDrawable, : GCPtr pGC, : BoxPtr pbox, : int nbox, : int dx, : int dy, : Bool reverse, : Bool upsidedown, : Pixel bitplane, : void *closure) :{ : FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); : : while (nbox--) : { : if (pDstDrawable->bitsPerPixel == 1) : { : FbBits *src; : FbStride srcStride; : int srcBpp; : int srcXoff, srcYoff; : : FbStip *dst; : FbStride dstStride; : int dstBpp; : int dstXoff, dstYoff; : : fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); : fbGetStipDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); : fbBltPlane (src + (pbox->y1+ dy + srcYoff) * srcStride, : srcStride, : (pbox->x1 + dx + srcXoff) * srcBpp, : srcBpp, : : dst + (pbox->y1 + dstYoff) * dstStride, : dstStride, : (pbox->x1 + dstXoff) * dstBpp, : : (pbox->x2 - pbox->x1) * srcBpp, : (pbox->y2 - pbox->y1), : : (FbStip) pPriv->and, (FbStip) pPriv->xor, : (FbStip) pPriv->bgand, (FbStip) pPriv->bgxor, : bitplane); : fbFinishAccess (pDstDrawable); : fbFinishAccess (pSrcDrawable); : } : else : { : FbBits *src; : FbStride srcStride; : int srcBpp; : int srcXoff, srcYoff; : : FbBits *dst; : FbStride dstStride; : int dstBpp; : int dstXoff, dstYoff; : : FbStip *tmp; : FbStride tmpStride; : int width, height; : : width = pbox->x2 - pbox->x1; : height = pbox->y2 - pbox->y1; : : tmpStride = ((width + FB_STIP_MASK) >> FB_STIP_SHIFT); : tmp = xalloc (tmpStride * height * sizeof (FbStip)); : if (!tmp) : return; : : fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); : fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); : : fbBltPlane (src + (pbox->y1+ dy + srcYoff) * srcStride, : srcStride, : (pbox->x1 + dx + srcXoff) * srcBpp, : srcBpp, : : tmp, : tmpStride, : 0, : : width * srcBpp, : height, : : fbAndStip(GXcopy,FB_ALLONES,FB_ALLONES), : fbXorStip(GXcopy,FB_ALLONES,FB_ALLONES), : fbAndStip(GXcopy,0,FB_ALLONES), : fbXorStip(GXcopy,0,FB_ALLONES), : bitplane); : fbBltOne (tmp, : tmpStride, : 0, : : dst + (pbox->y1 + dstYoff) * dstStride, : dstStride, : (pbox->x1 + dstXoff) * dstBpp, : dstBpp, : : width * dstBpp, : height, : : pPriv->and, pPriv->xor, : pPriv->bgand, pPriv->bgxor); : xfree (tmp); : : fbFinishAccess (pDstDrawable); : fbFinishAccess (pSrcDrawable); : } : pbox++; : } :} : :void :fbCopyRegion (DrawablePtr pSrcDrawable, : DrawablePtr pDstDrawable, : GCPtr pGC, : RegionPtr pDstRegion, : int dx, : int dy, : fbCopyProc copyProc, : Pixel bitPlane, : void *closure) 4 0.0044 :{ /* fbCopyRegion total: 27 0.0294 */ : int careful; : Bool reverse; : Bool upsidedown; : BoxPtr pbox; : int nbox; : BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp; : 8 0.0087 : pbox = REGION_RECTS(pDstRegion); : nbox = REGION_NUM_RECTS(pDstRegion); : : /* XXX we have to err on the side of safety when both are windows, : * because we don't know if IncludeInferiors is being used. : */ 2 0.0022 : careful = ((pSrcDrawable == pDstDrawable) || : ((pSrcDrawable->type == DRAWABLE_WINDOW) && : (pDstDrawable->type == DRAWABLE_WINDOW))); : : pboxNew1 = NULL; : pboxNew2 = NULL; : if (careful && dy < 0) : { : upsidedown = TRUE; : : if (nbox > 1) : { : /* keep ordering in each band, reverse order of bands */ : pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); : if(!pboxNew1) : return; : pboxBase = pboxNext = pbox+nbox-1; : while (pboxBase >= pbox) : { : while ((pboxNext >= pbox) && : (pboxBase->y1 == pboxNext->y1)) : pboxNext--; : pboxTmp = pboxNext+1; : while (pboxTmp <= pboxBase) : { : *pboxNew1++ = *pboxTmp++; : } : pboxBase = pboxNext; : } : pboxNew1 -= nbox; : pbox = pboxNew1; : } : } : else : { : /* walk source top to bottom */ : upsidedown = FALSE; : } : : if (careful && dx < 0) : { : /* walk source right to left */ : if (dy <= 0) : reverse = TRUE; : else : reverse = FALSE; : : if (nbox > 1) : { : /* reverse order of rects in each band */ : pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); : if(!pboxNew2) : { : if (pboxNew1) : DEALLOCATE_LOCAL(pboxNew1); : return; : } : pboxBase = pboxNext = pbox; : while (pboxBase < pbox+nbox) : { : while ((pboxNext < pbox+nbox) && : (pboxNext->y1 == pboxBase->y1)) : pboxNext++; : pboxTmp = pboxNext; : while (pboxTmp != pboxBase) : { : *pboxNew2++ = *--pboxTmp; : } : pboxBase = pboxNext; : } 1 0.0011 : pboxNew2 -= nbox; : pbox = pboxNew2; : } : } : else : { : /* walk source left to right */ : reverse = FALSE; : } : 8 0.0087 : (*copyProc) (pSrcDrawable, : pDstDrawable, : pGC, : pbox, : nbox, : dx, dy, : reverse, upsidedown, bitPlane, closure); : : if (pboxNew1) : DEALLOCATE_LOCAL (pboxNew1); : if (pboxNew2) : DEALLOCATE_LOCAL (pboxNew2); 4 0.0044 :} : :RegionPtr :fbDoCopy (DrawablePtr pSrcDrawable, : DrawablePtr pDstDrawable, : GCPtr pGC, : int xIn, : int yIn, : int widthSrc, : int heightSrc, : int xOut, : int yOut, : fbCopyProc copyProc, : Pixel bitPlane, : void *closure) 5 0.0054 :{ /* fbDoCopy total: 100 0.1089 */ : RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ : Bool freeSrcClip = FALSE; : RegionPtr prgnExposed = NULL; : RegionRec rgnDst; : int dx; : int dy; : int numRects; : int box_x1; : int box_y1; : int box_x2; : int box_y2; : Bool fastSrc = FALSE; /* for fast clipping with pixmap source */ : Bool fastDst = FALSE; /* for fast clipping with one rect dest */ : Bool fastExpose = FALSE; /* for fast exposures with pixmap source */ : : /* Short cut for unmapped windows */ : 1 0.0011 : if (pDstDrawable->type == DRAWABLE_WINDOW && : !((WindowPtr)pDstDrawable)->realized) : { : return NULL; : } : 8 0.0087 : if ((pSrcDrawable != pDstDrawable) && : pSrcDrawable->pScreen->SourceValidate) : { 1 0.0011 : (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc); : } : : /* Compute source clip region */ 2 0.0022 : if (pSrcDrawable->type == DRAWABLE_PIXMAP) : { 6 0.0065 : if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) : prgnSrcClip = fbGetCompositeClip(pGC); : else : fastSrc = TRUE; : } : else : { : if (pGC->subWindowMode == IncludeInferiors) : { : /* : * XFree86 DDX empties the border clip when the : * VT is inactive, make sure the region isn't empty : */ : if (!((WindowPtr) pSrcDrawable)->parent && : REGION_NOTEMPTY (pSrcDrawable->pScreen, : &((WindowPtr) pSrcDrawable)->borderClip)) : { : /* : * special case bitblt from root window in : * IncludeInferiors mode; just like from a pixmap : */ : fastSrc = TRUE; : } : else if ((pSrcDrawable == pDstDrawable) && : (pGC->clientClipType == CT_NONE)) : { : prgnSrcClip = fbGetCompositeClip(pGC); : } : else : { : prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); : freeSrcClip = TRUE; : } : } : else : { : prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; : } : } : : xIn += pSrcDrawable->x; 2 0.0022 : yIn += pSrcDrawable->y; : 1 0.0011 : xOut += pDstDrawable->x; 2 0.0022 : yOut += pDstDrawable->y; : : box_x1 = xIn; : box_y1 = yIn; : box_x2 = xIn + widthSrc; 2 0.0022 : box_y2 = yIn + heightSrc; : 2 0.0022 : dx = xIn - xOut; 4 0.0044 : dy = yIn - yOut; : : /* Don't create a source region if we are doing a fast clip */ 3 0.0033 : if (fastSrc) : { : RegionPtr cclip; : : fastExpose = TRUE; : /* : * clip the source; if regions extend beyond the source size, : * make sure exposure events get sent : */ 4 0.0044 : if (box_x1 < pSrcDrawable->x) : { : box_x1 = pSrcDrawable->x; : fastExpose = FALSE; : } : if (box_y1 < pSrcDrawable->y) : { : box_y1 = pSrcDrawable->y; : fastExpose = FALSE; : } 7 0.0076 : if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) : { : box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width; : fastExpose = FALSE; : } 4 0.0044 : if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) : { : box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height; : fastExpose = FALSE; : } : : /* Translate and clip the dst to the destination composite clip */ : box_x1 -= dx; : box_x2 -= dx; 1 0.0011 : box_y1 -= dy; 1 0.0011 : box_y2 -= dy; : : /* If the destination composite clip is one rectangle we can : do the clip directly. Otherwise we have to create a full : blown region and call intersect */ : 1 0.0011 : cclip = fbGetCompositeClip(pGC); 2 0.0022 : if (REGION_NUM_RECTS(cclip) == 1) : { 9 0.0098 : BoxPtr pBox = REGION_RECTS(cclip); : : if (box_x1 < pBox->x1) box_x1 = pBox->x1; : if (box_x2 > pBox->x2) box_x2 = pBox->x2; : if (box_y1 < pBox->y1) box_y1 = pBox->y1; 1 0.0011 : if (box_y2 > pBox->y2) box_y2 = pBox->y2; : fastDst = TRUE; : } : } : : /* Check to see if the region is empty */ 2 0.0022 : if (box_x1 >= box_x2 || box_y1 >= box_y2) : { 3 0.0033 : REGION_NULL(pGC->pScreen, &rgnDst); : } : else : { : BoxRec box; : box.x1 = box_x1; : box.y1 = box_y1; : box.x2 = box_x2; : box.y2 = box_y2; : REGION_INIT(pGC->pScreen, &rgnDst, &box, 1); : } : : /* Clip against complex source if needed */ 2 0.0022 : if (!fastSrc) : { : REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); : REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); : } : : /* Clip against complex dest if needed */ 1 0.0011 : if (!fastDst) : { : REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, : fbGetCompositeClip(pGC)); : } : : /* Do bit blitting */ : numRects = REGION_NUM_RECTS(&rgnDst); 1 0.0011 : if (numRects && widthSrc && heightSrc) 16 0.0174 : fbCopyRegion (pSrcDrawable, pDstDrawable, pGC, : &rgnDst, dx, dy, copyProc, bitPlane, closure); : : /* Pixmap sources generate a NoExposed (we return NULL to do this) */ : if (!fastExpose && pGC->fExpose) : prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, : xIn - pSrcDrawable->x, : yIn - pSrcDrawable->y, : widthSrc, heightSrc, : xOut - pDstDrawable->x, : yOut - pDstDrawable->y, : (unsigned long) bitPlane); : REGION_UNINIT(pGC->pScreen, &rgnDst); 1 0.0011 : if (freeSrcClip) : REGION_DESTROY(pGC->pScreen, prgnSrcClip); : fbValidateDrawable (pDstDrawable); : return prgnExposed; 5 0.0054 :} : :RegionPtr :fbCopyArea (DrawablePtr pSrcDrawable, : DrawablePtr pDstDrawable, : GCPtr pGC, : int xIn, : int yIn, : int widthSrc, : int heightSrc, : int xOut, : int yOut) :{ : fbCopyProc copy; : :#ifdef FB_24_32BIT : if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel) : copy = fb24_32CopyMtoN; : else :#endif : copy = fbCopyNtoN; : return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn, : widthSrc, heightSrc, xOut, yOut, copy, 0, 0); :} : :RegionPtr :fbCopyPlane (DrawablePtr pSrcDrawable, : DrawablePtr pDstDrawable, : GCPtr pGC, : int xIn, : int yIn, : int widthSrc, : int heightSrc, : int xOut, : int yOut, : unsigned long bitplane) :{ : if (pSrcDrawable->bitsPerPixel > 1) : return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, : xIn, yIn, widthSrc, heightSrc, : xOut, yOut, fbCopyNto1, (Pixel) bitplane, 0); : else if (bitplane & 1) : return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn, : widthSrc, heightSrc, xOut, yOut, fbCopy1toN, : (Pixel) bitplane, 0); : else : return miHandleExposures(pSrcDrawable, pDstDrawable, pGC, : xIn, yIn, : widthSrc, : heightSrc, : xOut, yOut, bitplane); :} /* * Total samples for file : "msort.c" * * 125 0.1362 */ 125 0.1362 : /* msort_with_tmp total: 125 0.1362 */ /* * Total samples for file : "i810_hwmc.c" * * 119 0.1296 */ 119 0.1296 : /* __i686.get_pc_thunk.bx total: 119 0.1296 */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/dix/resource.c" * * 117 0.1275 */ :/************************************************************ : :Copyright 1987, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :********************************************************/ :/* The panoramix components contained the following notice */ :/***************************************************************** : :Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. : :Permission is hereby granted, free of charge, to any person obtaining a copy :of this software and associated documentation files (the "Software"), to deal :in the Software without restriction, including without limitation the rights :to use, copy, modify, merge, publish, distribute, sublicense, and/or sell :copies of the Software. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL :DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, :BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, :WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR :IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of Digital Equipment Corporation :shall not be used in advertising or otherwise to promote the sale, use or other :dealings in this Software without prior written authorization from Digital :Equipment Corporation. : :******************************************************************/ :/* XSERVER_DTRACE additions: : * Copyright 2005-2006 Sun Microsystems, Inc. All rights reserved. : * : * Permission is hereby granted, free of charge, to any person obtaining a : * copy of this software and associated documentation files (the : * "Software"), to deal in the Software without restriction, including : * without limitation the rights to use, copy, modify, merge, publish, : * distribute, and/or sell copies of the Software, and to permit persons : * to whom the Software is furnished to do so, provided that the above : * copyright notice(s) and this permission notice appear in all copies of : * the Software and that both the above copyright notice(s) and this : * permission notice appear in supporting documentation. : * : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT : * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR : * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL : * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING : * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION : * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : * : * Except as contained in this notice, the name of a copyright holder : * shall not be used in advertising or otherwise to promote the sale, use : * or other dealings in this Software without prior written authorization : * of the copyright holder. : */ : :/* Routines to manage various kinds of resources: : * : * CreateNewResourceType, CreateNewResourceClass, InitClientResources, : * FakeClientID, AddResource, FreeResource, FreeClientResources, : * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange : */ : :/* : * A resource ID is a 32 bit quantity, the upper 2 bits of which are : * off-limits for client-visible resources. The next 8 bits are : * used as client ID, and the low 22 bits come from the client. : * A resource ID is "hashed" by extracting and xoring subfields : * (varying with the size of the hash table). : * : * It is sometimes necessary for the server to create an ID that looks : * like it belongs to a client. This ID, however, must not be one : * the client actually can create, or we have the potential for conflict. : * The 31st bit of the ID is reserved for the server's use for this : * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to : * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a : * resource "owned" by the client. : */ : :#define NEED_EVENTS :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include "misc.h" :#include "os.h" :#include "resource.h" :#include "dixstruct.h" :#include "opaque.h" :#include "windowstr.h" :#include "dixfont.h" :#include "colormap.h" :#include "inputstr.h" :#include "dixevents.h" :#include "dixgrabs.h" :#include "cursor.h" :#ifdef PANORAMIX :#include "panoramiX.h" :#include "panoramiXsrv.h" :#endif :#include "xace.h" :#include : :#ifdef XSERVER_DTRACE :#include :typedef const char *string; :#include "Xserver-dtrace.h" : :#define TypeNameString(t) NameForAtom(ResourceNames[t & TypeMask]) :#endif : :static void RebuildTable( : int /*client*/ :); : :#define SERVER_MINID 32 : :#define INITBUCKETS 64 :#define INITHASHSIZE 6 :#define MAXHASHSIZE 11 : :typedef struct _Resource { : struct _Resource *next; : XID id; : RESTYPE type; : pointer value; :} ResourceRec, *ResourcePtr; :#define NullResource ((ResourcePtr)NULL) : :typedef struct _ClientResource { : ResourcePtr *resources; : int elements; : int buckets; : int hashsize; /* log(2)(buckets) */ : XID fakeID; : XID endFakeID; : XID expectID; :} ClientResourceRec; : :_X_EXPORT RESTYPE lastResourceType; :static RESTYPE lastResourceClass; :_X_EXPORT RESTYPE TypeMask; : :static DeleteType *DeleteFuncs = (DeleteType *)NULL; : :#ifdef XResExtension : :_X_EXPORT Atom * ResourceNames = NULL; : :_X_EXPORT void RegisterResourceName (RESTYPE type, char *name) :{ : ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE); :} : :#endif : :_X_EXPORT RESTYPE :CreateNewResourceType(DeleteType deleteFunc) :{ : RESTYPE next = lastResourceType + 1; : DeleteType *funcs; : : if (next & lastResourceClass) : return 0; : funcs = (DeleteType *)xrealloc(DeleteFuncs, : (next + 1) * sizeof(DeleteType)); : if (!funcs) : return 0; : :#ifdef XResExtension : { : Atom *newnames; : newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom)); : if(!newnames) : return 0; : ResourceNames = newnames; : ResourceNames[next] = 0; : } :#endif : : lastResourceType = next; : DeleteFuncs = funcs; : DeleteFuncs[next] = deleteFunc; : return next; :} : :_X_EXPORT RESTYPE :CreateNewResourceClass(void) :{ : RESTYPE next = lastResourceClass >> 1; : : if (next & lastResourceType) : return 0; : lastResourceClass = next; : TypeMask = next - 1; : return next; :} : :static ClientResourceRec clientTable[MAXCLIENTS]; : :/***************** : * InitClientResources : * When a new client is created, call this to allocate space : * in resource table : *****************/ : :Bool :InitClientResources(ClientPtr client) :{ : int i, j; : : if (client == serverClient) : { : lastResourceType = RT_LASTPREDEF; : lastResourceClass = RC_LASTPREDEF; : TypeMask = RC_LASTPREDEF - 1; : if (DeleteFuncs) : xfree(DeleteFuncs); : DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * : sizeof(DeleteType)); : if (!DeleteFuncs) : return FALSE; : DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; : DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; : DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; : DeleteFuncs[RT_GC & TypeMask] = FreeGC; : DeleteFuncs[RT_FONT & TypeMask] = CloseFont; : DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; : DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; : DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; : DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; : DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; : :#ifdef XResExtension : if(ResourceNames) : xfree(ResourceNames); : ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom)); : if(!ResourceNames) : return FALSE; :#endif : } : clientTable[i = client->index].resources = : (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); : if (!clientTable[i].resources) : return FALSE; : clientTable[i].buckets = INITBUCKETS; : clientTable[i].elements = 0; : clientTable[i].hashsize = INITHASHSIZE; : /* Many IDs allocated from the server client are visible to clients, : * so we don't use the SERVER_BIT for them, but we have to start : * past the magic value constants used in the protocol. For normal : * clients, we can start from zero, with SERVER_BIT set. : */ : clientTable[i].fakeID = client->clientAsMask | : (client->index ? SERVER_BIT : SERVER_MINID); : clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; : clientTable[i].expectID = client->clientAsMask; : for (j=0; j>6) ^ (id>>12)))); : case 7: 6 0.0065 : return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); : case 8: : return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); : case 9: : return ((int)(0x1FF & (id ^ (id>>9)))); : case 10: : return ((int)(0x3FF & (id ^ (id>>10)))); : case 11: : return ((int)(0x7FF & (id ^ (id>>11)))); : } : return -1; :} : :static XID :AvailableID( : int client, : XID id, : XID maxid, : XID goodid) :{ : ResourcePtr res; : : if ((goodid >= id) && (goodid <= maxid)) : return goodid; : for (; id <= maxid; id++) : { : res = clientTable[client].resources[Hash(client, id)]; : while (res && (res->id != id)) : res = res->next; : if (!res) : return id; : } : return 0; :} : :_X_EXPORT void :GetXIDRange(int client, Bool server, XID *minp, XID *maxp) :{ : XID id, maxid; : ResourcePtr *resp; : ResourcePtr res; : int i; : XID goodid; : : id = (Mask)client << CLIENTOFFSET; : if (server) : id |= client ? SERVER_BIT : SERVER_MINID; : maxid = id | RESOURCE_ID_MASK; : goodid = 0; : for (resp = clientTable[client].resources, i = clientTable[client].buckets; : --i >= 0;) : { : for (res = *resp++; res; res = res->next) : { : if ((res->id < id) || (res->id > maxid)) : continue; : if (((res->id - id) >= (maxid - res->id)) ? : (goodid = AvailableID(client, id, res->id - 1, goodid)) : : !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) : maxid = res->id - 1; : else : id = res->id + 1; : } : } : if (id > maxid) : id = maxid = 0; : *minp = id; : *maxp = maxid; :} : :/** : * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. : * This function tries to find count unused XIDs for the given client. It : * puts the IDs in the array pids and returns the number found, which should : * almost always be the number requested. : * : * The circumstances that lead to a call to this function are very rare. : * Xlib must run out of IDs while trying to generate a request that wants : * multiple ID's, like the Multi-buffering CreateImageBuffers request. : * : * No rocket science in the implementation; just iterate over all : * possible IDs for the given client and pick the first count IDs : * that aren't in use. A more efficient algorithm could probably be : * invented, but this will be used so rarely that this should suffice. : */ : :_X_EXPORT unsigned int :GetXIDList(ClientPtr pClient, unsigned count, XID *pids) :{ : unsigned int found = 0; : XID id = pClient->clientAsMask; : XID maxid; : : maxid = id | RESOURCE_ID_MASK; : while ( (found < count) && (id <= maxid) ) : { : if (!LookupIDByClass(id, RC_ANY)) : { : pids[found++] = id; : } : id++; : } : return found; :} : :/* : * Return the next usable fake client ID. : * : * Normally this is just the next one in line, but if we've used the last : * in the range, we need to find a new range of safe IDs to avoid : * over-running another client. : */ : :_X_EXPORT XID :FakeClientID(int client) :{ : XID id, maxid; : : id = clientTable[client].fakeID++; : if (id != clientTable[client].endFakeID) : return id; : GetXIDRange(client, TRUE, &id, &maxid); : if (!id) { : if (!client) : FatalError("FakeClientID: server internal ids exhausted\n"); : MarkClientException(clients[client]); : id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); : maxid = id | RESOURCE_ID_MASK; : } : clientTable[client].fakeID = id + 1; : clientTable[client].endFakeID = maxid + 1; : return id; :} : :_X_EXPORT Bool :AddResource(XID id, RESTYPE type, pointer value) 2 0.0022 :{ /* AddResource total: 8 0.0087 */ : int client; : ClientResourceRec *rrec; : ResourcePtr res, *head; : :#ifdef XSERVER_DTRACE : XSERVER_RESOURCE_ALLOC(id, type, value, TypeNameString(type)); :#endif : client = CLIENT_ID(id); 1 0.0011 : rrec = &clientTable[client]; 1 0.0011 : if (!rrec->buckets) : { : ErrorF("AddResource(%lx, %lx, %lx), client=%d \n", : (unsigned long)id, type, (unsigned long)value, client); : FatalError("client not in use\n"); : } : if ((rrec->elements >= 4*rrec->buckets) && : (rrec->hashsize < MAXHASHSIZE)) : RebuildTable(client); : head = &rrec->resources[Hash(client, id)]; : res = (ResourcePtr)xalloc(sizeof(ResourceRec)); : if (!res) : { : (*DeleteFuncs[type & TypeMask])(value, id); : return FALSE; : } 1 0.0011 : res->next = *head; : res->id = id; : res->type = type; 1 0.0011 : res->value = value; : *head = res; : rrec->elements++; 2 0.0022 : if (!(id & SERVER_BIT) && (id >= rrec->expectID)) : rrec->expectID = id + 1; : return TRUE; :} : :static void :RebuildTable(int client) :{ : int j; : ResourcePtr res, next; : ResourcePtr **tails, *resources; : ResourcePtr **tptr, *rptr; : : /* : * For now, preserve insertion order, since some ddx layers depend : * on resources being free in the opposite order they are added. : */ : : j = 2 * clientTable[client].buckets; : tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); : if (!tails) : return; : resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); : if (!resources) : { : DEALLOCATE_LOCAL(tails); : return; : } : for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) : { : *rptr = NullResource; : *tptr = rptr; : } : clientTable[client].hashsize++; : for (j = clientTable[client].buckets, : rptr = clientTable[client].resources; : --j >= 0; : rptr++) : { : for (res = *rptr; res; res = next) : { : next = res->next; : res->next = NullResource; : tptr = &tails[Hash(client, res->id)]; : **tptr = res; : *tptr = &res->next; : } : } : DEALLOCATE_LOCAL(tails); : clientTable[client].buckets *= 2; : xfree(clientTable[client].resources); : clientTable[client].resources = resources; :} : :_X_EXPORT void :FreeResource(XID id, RESTYPE skipDeleteFuncType) 1 0.0011 :{ /* FreeResource total: 27 0.0294 */ : int cid; : ResourcePtr res; : ResourcePtr *prev, *head; : int *eltptr; : int elements; : Bool gotOne = FALSE; : 1 0.0011 : if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) : { : head = &clientTable[cid].resources[Hash(cid, id)]; : eltptr = &clientTable[cid].elements; : : prev = head; 2 0.0022 : while ( (res = *prev) ) : { 2 0.0022 : if (res->id == id) : { : RESTYPE rtype = res->type; : :#ifdef XSERVER_DTRACE : XSERVER_RESOURCE_FREE(res->id, res->type, : res->value, TypeNameString(res->type)); :#endif : *prev = res->next; : elements = --*eltptr; : if (rtype & RC_CACHED) 1 0.0011 : FlushClientCaches(res->id); 1 0.0011 : if (rtype != skipDeleteFuncType) 6 0.0065 : (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); 1 0.0011 : xfree(res); : if (*eltptr != elements) : prev = head; /* prev may no longer be valid */ : gotOne = TRUE; : } : else 11 0.0120 : prev = &res->next; : } 1 0.0011 : if(clients[cid] && (id == clients[cid]->lastDrawableID)) : { : clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; : clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; : } : } : if (!gotOne) : ErrorF("Freeing resource id=%lX which isn't there.\n", : (unsigned long)id); :} : : :_X_EXPORT void :FreeResourceByType(XID id, RESTYPE type, Bool skipFree) :{ : int cid; : ResourcePtr res; : ResourcePtr *prev, *head; : if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) : { : head = &clientTable[cid].resources[Hash(cid, id)]; : : prev = head; : while ( (res = *prev) ) : { : if (res->id == id && res->type == type) : { :#ifdef XSERVER_DTRACE : XSERVER_RESOURCE_FREE(res->id, res->type, : res->value, TypeNameString(res->type)); :#endif : *prev = res->next; : if (type & RC_CACHED) : FlushClientCaches(res->id); : if (!skipFree) : (*DeleteFuncs[type & TypeMask])(res->value, res->id); : xfree(res); : break; : } : else : prev = &res->next; : } : if(clients[cid] && (id == clients[cid]->lastDrawableID)) : { : clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; : clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; : } : } :} : :/* : * Change the value associated with a resource id. Caller : * is responsible for "doing the right thing" with the old : * data : */ : :_X_EXPORT Bool :ChangeResourceValue (XID id, RESTYPE rtype, pointer value) :{ : int cid; : ResourcePtr res; : : if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) : { : res = clientTable[cid].resources[Hash(cid, id)]; : : for (; res; res = res->next) : if ((res->id == id) && (res->type == rtype)) : { : if (rtype & RC_CACHED) : FlushClientCaches(res->id); : res->value = value; : return TRUE; : } : } : return FALSE; :} : :/* Note: if func adds or deletes resources, then func can get called : * more than once for some resources. If func adds new resources, : * func might or might not get called for them. func cannot both : * add and delete an equal number of resources! : */ : :_X_EXPORT void :FindClientResourcesByType( : ClientPtr client, : RESTYPE type, : FindResType func, : pointer cdata :){ : ResourcePtr *resources; : ResourcePtr this, next; : int i, elements; : int *eltptr; : : if (!client) : client = serverClient; : : resources = clientTable[client->index].resources; : eltptr = &clientTable[client->index].elements; : for (i = 0; i < clientTable[client->index].buckets; i++) : { : for (this = resources[i]; this; this = next) : { : next = this->next; : if (!type || this->type == type) { : elements = *eltptr; : (*func)(this->value, this->id, cdata); : if (*eltptr != elements) : next = resources[i]; /* start over */ : } : } : } :} : :_X_EXPORT void :FindAllClientResources( : ClientPtr client, : FindAllRes func, : pointer cdata :){ : ResourcePtr *resources; : ResourcePtr this, next; : int i, elements; : int *eltptr; : : if (!client) : client = serverClient; : : resources = clientTable[client->index].resources; : eltptr = &clientTable[client->index].elements; : for (i = 0; i < clientTable[client->index].buckets; i++) : { : for (this = resources[i]; this; this = next) : { : next = this->next; : elements = *eltptr; : (*func)(this->value, this->id, this->type, cdata); : if (*eltptr != elements) : next = resources[i]; /* start over */ : } : } :} : : :pointer :LookupClientResourceComplex( : ClientPtr client, : RESTYPE type, : FindComplexResType func, : pointer cdata :){ : ResourcePtr *resources; : ResourcePtr this; : int i; : : if (!client) : client = serverClient; : : resources = clientTable[client->index].resources; : for (i = 0; i < clientTable[client->index].buckets; i++) { : for (this = resources[i]; this; this = this->next) { : if (!type || this->type == type) { : if((*func)(this->value, this->id, cdata)) : return this->value; : } : } : } : return NULL; :} : : :void :FreeClientNeverRetainResources(ClientPtr client) :{ : ResourcePtr *resources; : ResourcePtr this; : ResourcePtr *prev; : int j; : : if (!client) : return; : : resources = clientTable[client->index].resources; : for (j=0; j < clientTable[client->index].buckets; j++) : { : prev = &resources[j]; : while ( (this = *prev) ) : { : RESTYPE rtype = this->type; : if (rtype & RC_NEVERRETAIN) : { :#ifdef XSERVER_DTRACE : XSERVER_RESOURCE_FREE(this->id, this->type, : this->value, TypeNameString(this->type)); :#endif : *prev = this->next; : if (rtype & RC_CACHED) : FlushClientCaches(this->id); : (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); : xfree(this); : } : else : prev = &this->next; : } : } :} : :void :FreeClientResources(ClientPtr client) :{ : ResourcePtr *resources; : ResourcePtr this; : int j; : : /* This routine shouldn't be called with a null client, but just in : case ... */ : : if (!client) : return; : : HandleSaveSet(client); : : resources = clientTable[client->index].resources; : for (j=0; j < clientTable[client->index].buckets; j++) : { : /* It may seem silly to update the head of this resource list as : we delete the members, since the entire list will be deleted any way, : but there are some resource deletion functions "FreeClientPixels" for : one which do a LookupID on another resource id (a Colormap id in this : case), so the resource list must be kept valid up to the point that : it is deleted, so every time we delete a resource, we must update the : head, just like in FreeResource. I hope that this doesn't slow down : mass deletion appreciably. PRH */ : : ResourcePtr *head; : : head = &resources[j]; : : for (this = *head; this; this = *head) : { : RESTYPE rtype = this->type; :#ifdef XSERVER_DTRACE : XSERVER_RESOURCE_FREE(this->id, this->type, : this->value, TypeNameString(this->type)); :#endif : *head = this->next; : if (rtype & RC_CACHED) : FlushClientCaches(this->id); : (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); : xfree(this); : } : } : xfree(clientTable[client->index].resources); : clientTable[client->index].resources = NULL; : clientTable[client->index].buckets = 0; :} : :void :FreeAllResources(void) :{ : int i; : : for (i = currentMaxClients; --i >= 0; ) : { : if (clientTable[i].buckets) : FreeClientResources(clients[i]); : } :} : :_X_EXPORT Bool :LegalNewID(XID id, ClientPtr client) 3 0.0033 :{ /* LegalNewID total: 7 0.0076 */ : :#ifdef PANORAMIX : XID minid, maxid; : 2 0.0022 : if (!noPanoramiXExtension) { : minid = client->clientAsMask | (client->index ? : SERVER_BIT : SERVER_MINID); : maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; : if ((id >= minid) && (id <= maxid)) : return TRUE; : } :#endif /* PANORAMIX */ 1 0.0011 : return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && : ((clientTable[client->index].expectID <= id) || : !LookupIDByClass(id, RC_ANY))); 1 0.0011 :} : :/* SecurityLookupIDByType and SecurityLookupIDByClass: : * These are the heart of the resource ID security system. They take : * two additional arguments compared to the old LookupID functions: : * the client doing the lookup, and the access mode (see resource.h). : * The resource is returned if it exists and the client is allowed access, : * else NULL is returned. : */ : :_X_EXPORT pointer :SecurityLookupIDByType(ClientPtr client, XID id, RESTYPE rtype, Mask mode) 8 0.0087 :{ /* SecurityLookupIDByType total: 40 0.0436 */ : int cid; : ResourcePtr res; : pointer retval = NULL; : 11 0.0120 : if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && : clientTable[cid].buckets) : { 2 0.0022 : res = clientTable[cid].resources[Hash(cid, id)]; : 6 0.0065 : for (; res; res = res->next) 7 0.0076 : if ((res->id == id) && (res->type == rtype)) : { 1 0.0011 : retval = res->value; : break; : } : } 4 0.0044 : if (retval && client && : !XaceHook(XACE_RESOURCE_ACCESS, client, id, rtype, mode, retval)) : retval = NULL; : : return retval; 1 0.0011 :} : : :_X_EXPORT pointer :SecurityLookupIDByClass(ClientPtr client, XID id, RESTYPE classes, Mask mode) 3 0.0033 :{ /* SecurityLookupIDByClass total: 8 0.0087 */ : int cid; : ResourcePtr res = NULL; : pointer retval = NULL; : 1 0.0011 : if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && : clientTable[cid].buckets) : { : res = clientTable[cid].resources[Hash(cid, id)]; : 1 0.0011 : for (; res; res = res->next) 2 0.0022 : if ((res->id == id) && (res->type & classes)) : { : retval = res->value; : break; : } : } : if (retval && client && : !XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type, mode, retval)) : retval = NULL; : : return retval; 1 0.0011 :} : :/* We can't replace the LookupIDByType and LookupIDByClass functions with : * macros because of compatibility with loadable servers. : */ : :_X_EXPORT pointer :LookupIDByType(XID id, RESTYPE rtype) :{ : return SecurityLookupIDByType(NullClient, id, rtype, : DixUnknownAccess); :} : :_X_EXPORT pointer :LookupIDByClass(XID id, RESTYPE classes) :{ : return SecurityLookupIDByClass(NullClient, id, classes, : DixUnknownAccess); :} /* * Total samples for file : "xkbKillSrv.c" * * 111 0.1209 */ 111 0.1209 : /* __i686.get_pc_thunk.cx total: 2 0.0022 */ /* __i686.get_pc_thunk.bx total: 97 0.1057 */ /* __divdi3 total: 12 0.0131 */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/exa/exa_accel.c" * * 109 0.1187 */ :/* : * Copyright © 2001 Keith Packard : * : * Partly based on code that is Copyright © The XFree86 Project Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : * : * Authors: : * Eric Anholt : * Michel Dänzer : * : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif :#include "exa_priv.h" :#include :#include "dixfontstr.h" :#include "exa.h" :#include "cw.h" : :static void :exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, : DDXPointPtr ppt, int *pwidth, int fSorted) :{ : ScreenPtr pScreen = pDrawable->pScreen; : ExaScreenPriv (pScreen); : RegionPtr pClip = fbGetCompositeClip(pGC); : PixmapPtr pPixmap; : BoxPtr pextent, pbox; : int nbox; : int extentX1, extentX2, extentY1, extentY2; : int fullX1, fullX2, fullY1; : int partX1, partX2; : int off_x, off_y; : ExaMigrationRec pixmaps[1]; : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = FALSE; : pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); : : if (pExaScr->swappedOut || : pGC->fillStyle != FillSolid || : pPixmap->drawable.width > pExaScr->info->maxX || : pPixmap->drawable.height > pExaScr->info->maxY) : { : exaDoMigration (pixmaps, 1, FALSE); : ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); : return; : } else { : exaDoMigration (pixmaps, 1, TRUE); : } : : if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) || : !(*pExaScr->info->PrepareSolid) (pPixmap, : pGC->alu, : pGC->planemask, : pGC->fgPixel)) : { : exaDoMigration (pixmaps, 1, FALSE); : ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); : return; : } : : pextent = REGION_EXTENTS(pGC->pScreen, pClip); : extentX1 = pextent->x1; : extentY1 = pextent->y1; : extentX2 = pextent->x2; : extentY2 = pextent->y2; : while (n--) : { : fullX1 = ppt->x; : fullY1 = ppt->y; : fullX2 = fullX1 + (int) *pwidth; : ppt++; : pwidth++; : : if (fullY1 < extentY1 || extentY2 <= fullY1) : continue; : : if (fullX1 < extentX1) : fullX1 = extentX1; : : if (fullX2 > extentX2) : fullX2 = extentX2; : : if (fullX1 >= fullX2) : continue; : : nbox = REGION_NUM_RECTS (pClip); : if (nbox == 1) : { : (*pExaScr->info->Solid) (pPixmap, : fullX1 + off_x, fullY1 + off_y, : fullX2 + off_x, fullY1 + 1 + off_y); : } : else : { : pbox = REGION_RECTS(pClip); : while(nbox--) : { : if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) : { : partX1 = pbox->x1; : if (partX1 < fullX1) : partX1 = fullX1; : partX2 = pbox->x2; : if (partX2 > fullX2) : partX2 = fullX2; : if (partX2 > partX1) { : (*pExaScr->info->Solid) (pPixmap, : partX1 + off_x, fullY1 + off_y, : partX2 + off_x, fullY1 + 1 + off_y); : } : } : pbox++; : } : } : } : (*pExaScr->info->DoneSolid) (pPixmap); : exaMarkSync(pScreen); :} : :static void :exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, : int w, int h, int leftPad, int format, char *bits) :{ : ExaScreenPriv (pDrawable->pScreen); : PixmapPtr pPix; : ExaMigrationRec pixmaps[1]; : RegionPtr pClip; : BoxPtr pbox; : int nbox; : int xoff, yoff; : int src_stride, bpp = pDrawable->bitsPerPixel; : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = FALSE; : pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); : : /* Don't bother with under 8bpp, XYPixmaps. */ : if (format != ZPixmap || bpp < 8) : goto migrate_and_fallback; : : /* Only accelerate copies: no rop or planemask. */ : if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) : goto migrate_and_fallback; : : if (pExaScr->swappedOut) : goto fallback; : : exaDoMigration (pixmaps, 1, TRUE); : : if (pExaScr->info->UploadToScreen == NULL) : goto fallback; : : pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); : : if (pPix == NULL) : goto fallback; : : x += pDrawable->x; : y += pDrawable->y; : : pClip = fbGetCompositeClip(pGC); : src_stride = PixmapBytePad(w, pDrawable->depth); : for (nbox = REGION_NUM_RECTS(pClip), : pbox = REGION_RECTS(pClip); : nbox--; : pbox++) : { : int x1 = x; : int y1 = y; : int x2 = x + w; : int y2 = y + h; : char *src; : Bool ok; : : if (x1 < pbox->x1) : x1 = pbox->x1; : if (y1 < pbox->y1) : y1 = pbox->y1; : if (x2 > pbox->x2) : x2 = pbox->x2; : if (y2 > pbox->y2) : y2 = pbox->y2; : if (x1 >= x2 || y1 >= y2) : continue; : : src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); : ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, : x2 - x1, y2 - y1, src, src_stride); : /* If we fail to accelerate the upload, fall back to using unaccelerated : * fb calls. : */ : if (!ok) { : FbStip *dst; : FbStride dst_stride; : int dstBpp; : int dstXoff, dstYoff; : : exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); : : fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, : dstXoff, dstYoff); : : fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)), : src_stride / sizeof(FbStip), : (x1 - x) * dstBpp, : dst + (y1 + dstYoff) * dst_stride, : dst_stride, : (x1 + dstXoff) * dstBpp, : (x2 - x1) * dstBpp, : y2 - y1, : GXcopy, FB_ALLONES, dstBpp); : : exaFinishAccess(pDrawable, EXA_PREPARE_DEST); : } : : exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); : } : : return; : :migrate_and_fallback: : exaDoMigration (pixmaps, 1, FALSE); : :fallback: : ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); :} : :static Bool inline :exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, : GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) :{ : ExaScreenPriv (pDstDrawable->pScreen); : PixmapPtr pSrcPixmap, pDstPixmap; : int src_off_x, src_off_y, dst_off_x, dst_off_y; : int dirsetup; : : /* Need to get both pixmaps to call the driver routines */ : pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y); : pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y); : if (!pSrcPixmap || !pDstPixmap) : return FALSE; : : /* : * Now the case of a chip that only supports xdir = ydir = 1 or : * xdir = ydir = -1, but we have xdir != ydir. : */ : dirsetup = 0; /* No direction set up yet. */ : for (; nbox; pbox++, nbox--) { : if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { : /* Do a xdir = ydir = -1 blit instead. */ : if (dirsetup != -1) { : if (dirsetup != 0) : pExaScr->info->DoneCopy(pDstPixmap); : dirsetup = -1; : if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, : pDstPixmap, : -1, -1, : pGC ? pGC->alu : GXcopy, : pGC ? pGC->planemask : : FB_ALLONES)) : return FALSE; : } : (*pExaScr->info->Copy)(pDstPixmap, : src_off_x + pbox->x1 + dx, : src_off_y + pbox->y1 + dy, : dst_off_x + pbox->x1, : dst_off_y + pbox->y1, : pbox->x2 - pbox->x1, : pbox->y2 - pbox->y1); : } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { : /* Do a xdir = ydir = 1 blit instead. */ : if (dirsetup != 1) { : if (dirsetup != 0) : pExaScr->info->DoneCopy(pDstPixmap); : dirsetup = 1; : if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, : pDstPixmap, : 1, 1, : pGC ? pGC->alu : GXcopy, : pGC ? pGC->planemask : : FB_ALLONES)) : return FALSE; : } : (*pExaScr->info->Copy)(pDstPixmap, : src_off_x + pbox->x1 + dx, : src_off_y + pbox->y1 + dy, : dst_off_x + pbox->x1, : dst_off_y + pbox->y1, : pbox->x2 - pbox->x1, : pbox->y2 - pbox->y1); : } else if (dx >= 0) { : /* : * xdir = 1, ydir = -1. : * Perform line-by-line xdir = ydir = 1 blits, going up. : */ : int i; : if (dirsetup != 1) { : if (dirsetup != 0) : pExaScr->info->DoneCopy(pDstPixmap); : dirsetup = 1; : if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, : pDstPixmap, : 1, 1, : pGC ? pGC->alu : GXcopy, : pGC ? pGC->planemask : : FB_ALLONES)) : return FALSE; : } : for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) : (*pExaScr->info->Copy)(pDstPixmap, : src_off_x + pbox->x1 + dx, : src_off_y + pbox->y1 + dy + i, : dst_off_x + pbox->x1, : dst_off_y + pbox->y1 + i, : pbox->x2 - pbox->x1, 1); : } else { : /* : * xdir = -1, ydir = 1. : * Perform line-by-line xdir = ydir = -1 blits, going down. : */ : int i; : if (dirsetup != -1) { : if (dirsetup != 0) : pExaScr->info->DoneCopy(pDstPixmap); : dirsetup = -1; : if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, : pDstPixmap, : -1, -1, : pGC ? pGC->alu : GXcopy, : pGC ? pGC->planemask : : FB_ALLONES)) : return FALSE; : } : for (i = 0; i < pbox->y2 - pbox->y1; i++) : (*pExaScr->info->Copy)(pDstPixmap, : src_off_x + pbox->x1 + dx, : src_off_y + pbox->y1 + dy + i, : dst_off_x + pbox->x1, : dst_off_y + pbox->y1 + i, : pbox->x2 - pbox->x1, 1); : } : exaPixmapDirty(pDstPixmap, dst_off_x + pbox->x1, dst_off_y + pbox->y1, : dst_off_x + pbox->x2, dst_off_y + pbox->y2); : } : if (dirsetup != 0) : pExaScr->info->DoneCopy(pDstPixmap); : exaMarkSync(pDstDrawable->pScreen); : return TRUE; :} : :void :exaCopyNtoN (DrawablePtr pSrcDrawable, : DrawablePtr pDstDrawable, : GCPtr pGC, : BoxPtr pbox, : int nbox, : int dx, : int dy, : Bool reverse, : Bool upsidedown, : Pixel bitplane, : void *closure) 3 0.0033 :{ /* exaCopyNtoN total: 47 0.0512 */ 6 0.0065 : ExaScreenPriv (pDstDrawable->pScreen); : PixmapPtr pSrcPixmap, pDstPixmap; : int src_off_x, src_off_y; : int dst_off_x, dst_off_y; : ExaMigrationRec pixmaps[2]; : Bool fallback = FALSE; : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = FALSE; 5 0.0054 : pixmaps[0].pPix = pDstPixmap = exaGetDrawablePixmap (pDstDrawable); 3 0.0033 : pixmaps[1].as_dst = FALSE; 1 0.0011 : pixmaps[1].as_src = TRUE; 7 0.0076 : pixmaps[1].pPix = pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); : : /* Respect maxX/maxY in a trivial way: don't set up drawing when we might : * violate the limits. The proper solution would be a temporary pixmap : * adjusted so that the drawing happened within limits. : */ 11 0.0120 : if (pSrcPixmap->drawable.width > pExaScr->info->maxX || : pSrcPixmap->drawable.height > pExaScr->info->maxY || : pDstPixmap->drawable.width > pExaScr->info->maxX || : pDstPixmap->drawable.height > pExaScr->info->maxY) : { : fallback = TRUE; : } else { 1 0.0011 : exaDoMigration (pixmaps, 2, TRUE); : } : : /* Mixed directions must be handled specially if the card is lame */ 2 0.0022 : if (!fallback && (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && : reverse != upsidedown) { : if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, : dx, dy)) : return; : fallback = TRUE; : } : 2 0.0022 : pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); : pDstPixmap = exaGetDrawablePixmap (pDstDrawable); : : exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); 4 0.0044 : exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); : : if (fallback || !exaPixmapIsOffscreen(pSrcPixmap) || : !exaPixmapIsOffscreen(pDstPixmap) || : !(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, : upsidedown ? -1 : 1, : pGC ? pGC->alu : GXcopy, : pGC ? pGC->planemask : FB_ALLONES)) { : fallback = TRUE; : return; : EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, : exaDrawableLocation(pSrcDrawable), : exaDrawableLocation(pDstDrawable))); : exaDoMigration (pixmaps, 2, FALSE); : exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); : exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); : fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, : pbox, nbox, dx, dy, reverse, upsidedown, : bitplane, closure); : exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); : exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); : } : : while (nbox--) : { : if (!fallback) : (*pExaScr->info->Copy) (pDstPixmap, : pbox->x1 + dx + src_off_x, : pbox->y1 + dy + src_off_y, : pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, : pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); : exaPixmapDirty (pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, : pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); : pbox++; : } : : if (fallback) : return; : : (*pExaScr->info->DoneCopy) (pDstPixmap); : exaMarkSync (pDstDrawable->pScreen); 2 0.0022 :} : :RegionPtr :exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, : int srcx, int srcy, int width, int height, int dstx, int dsty) 5 0.0054 :{ /* exaCopyArea total: 33 0.0359 */ : ExaScreenPriv (pDstDrawable->pScreen); : 9 0.0098 : if (pExaScr->swappedOut) { : return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC, : srcx, srcy, width, height, dstx, dsty); : } : 14 0.0153 : return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, : srcx, srcy, width, height, : dstx, dsty, exaCopyNtoN, 0, NULL); 5 0.0054 :} : :static void :exaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, : DDXPointPtr ppt) :{ : int i; : xRectangle *prect; : : /* If we can't reuse the current GC as is, don't bother accelerating the : * points. : */ : if (pGC->fillStyle != FillSolid) { : ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt); : return; : } : : prect = ALLOCATE_LOCAL(sizeof(xRectangle) * npt); : for (i = 0; i < npt; i++) { : prect[i].x = ppt[i].x; : prect[i].y = ppt[i].y; : if (i > 0 && mode == CoordModePrevious) { : prect[i].x += prect[i - 1].x; : prect[i].y += prect[i - 1].y; : } : prect[i].width = 1; : prect[i].height = 1; : } : pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); : DEALLOCATE_LOCAL(prect); :} : :/** : * exaPolylines() checks if it can accelerate the lines as a group of : * horizontal or vertical lines (rectangles), and uses existing rectangle fill : * acceleration if so. : */ :static void :exaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, : DDXPointPtr ppt) :{ : xRectangle *prect; : int x1, x2, y1, y2; : int i; : : /* Don't try to do wide lines or non-solid fill style. */ : if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || : pGC->fillStyle != FillSolid) { : ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); : return; : } : : prect = ALLOCATE_LOCAL(sizeof(xRectangle) * (npt - 1)); : x1 = ppt[0].x; : y1 = ppt[0].y; : /* If we have any non-horizontal/vertical, fall back. */ : for (i = 0; i < npt; i++) { : if (mode == CoordModePrevious) { : x2 = x1 + ppt[i + 1].x; : y2 = y1 + ppt[i + 1].y; : } else { : x2 = ppt[i + 1].x; : y2 = ppt[i + 1].y; : } : : if (x1 != x2 && y1 != y2) { : DEALLOCATE_LOCAL(prect); : ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); : return; : } : : if (x1 < x2) { : prect[i].x = x1; : prect[i].width = x2 - x1 + 1; : } else { : prect[i].x = x2; : prect[i].width = x1 - x2 + 1; : } : if (y1 < y2) { : prect[i].y = y1; : prect[i].height = y2 - y1 + 1; : } else { : prect[i].y = y2; : prect[i].height = y1 - y2 + 1; : } : : x1 = x2; : y1 = y2; : } : pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); : DEALLOCATE_LOCAL(prect); :} : :/** : * exaPolySegment() checks if it can accelerate the lines as a group of : * horizontal or vertical lines (rectangles), and uses existing rectangle fill : * acceleration if so. : */ :static void :exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg, : xSegment *pSeg) 1 0.0011 :{ /* exaPolySegment total: 3 0.0033 */ : xRectangle *prect; : int i; : : /* Don't try to do wide lines or non-solid fill style. */ : if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || : pGC->fillStyle != FillSolid) : { : ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); : return; : } : : /* If we have any non-horizontal/vertical, fall back. */ : for (i = 0; i < nseg; i++) { : if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { : ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); : return; : } : } : 1 0.0011 : prect = ALLOCATE_LOCAL(sizeof(xRectangle) * nseg); : for (i = 0; i < nseg; i++) { : if (pSeg[i].x1 < pSeg[i].x2) { : prect[i].x = pSeg[i].x1; : prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1; : } else { : prect[i].x = pSeg[i].x2; : prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1; : } : if (pSeg[i].y1 < pSeg[i].y2) { : prect[i].y = pSeg[i].y1; : prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1; : } else { : prect[i].y = pSeg[i].y2; 1 0.0011 : prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1; : } : } : pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); : DEALLOCATE_LOCAL(prect); :} : :static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, : Pixel pixel, CARD32 planemask, CARD32 alu); : :static void :exaPolyFillRect(DrawablePtr pDrawable, : GCPtr pGC, : int nrect, : xRectangle *prect) 1 0.0011 :{ /* exaPolyFillRect total: 19 0.0207 */ 1 0.0011 : ExaScreenPriv (pDrawable->pScreen); : RegionPtr pClip = fbGetCompositeClip(pGC); : PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); : register BoxPtr pbox; : BoxPtr pextent; : int extentX1, extentX2, extentY1, extentY2; : int fullX1, fullX2, fullY1, fullY2; : int partX1, partX2, partY1, partY2; : int xoff, yoff; : int xorg, yorg; : int n; : ExaMigrationRec pixmaps[2]; : RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); : : /* Compute intersection of rects and clip region */ 1 0.0011 : REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); : REGION_INTERSECT(pScreen, pReg, pClip, pReg); : : if (!REGION_NUM_RECTS(pReg)) { : goto out; : } : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = FALSE; : pixmaps[0].pPix = pPixmap; : 4 0.0044 : exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); : 4 0.0044 : if (pExaScr->swappedOut || : pPixmap->drawable.width > pExaScr->info->maxX || : pPixmap->drawable.height > pExaScr->info->maxY) : { : goto fallback; : } : : /* For ROPs where overlaps don't matter, convert rectangles to region and : * call exaFillRegion{Solid,Tiled}. : */ 2 0.0022 : if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && : (pGC->alu == GXcopy || pGC->alu == GXclear || pGC->alu == GXnoop || : pGC->alu == GXcopyInverted || pGC->alu == GXset)) { 6 0.0065 : if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && : exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? : pGC->fgPixel : pGC->tile.pixel, pGC->planemask, : pGC->alu)) || : (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && : exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, : pGC->planemask, pGC->alu))) { : goto out; : } : } : : if (pGC->fillStyle != FillSolid && : !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) : { : goto fallback; : } : : exaDoMigration (pixmaps, 1, TRUE); : : if (!exaPixmapIsOffscreen (pPixmap) || : !(*pExaScr->info->PrepareSolid) (pPixmap, : pGC->alu, : pGC->planemask, : pGC->fgPixel)) : { :fallback: : if (pGC->fillStyle == FillTiled && !pGC->tileIsPixel) { : pixmaps[1].as_dst = FALSE; : pixmaps[1].as_src = TRUE; : pixmaps[1].pPix = pGC->tile.pixmap; : exaDoMigration (pixmaps, 2, FALSE); : } else { : exaDoMigration (pixmaps, 1, FALSE); : } : : ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); : goto out; : } : : xorg = pDrawable->x; : yorg = pDrawable->y; : : pextent = REGION_EXTENTS(pGC->pScreen, pClip); : extentX1 = pextent->x1; : extentY1 = pextent->y1; : extentX2 = pextent->x2; : extentY2 = pextent->y2; : while (nrect--) : { : fullX1 = prect->x + xorg; : fullY1 = prect->y + yorg; : fullX2 = fullX1 + (int) prect->width; : fullY2 = fullY1 + (int) prect->height; : prect++; : : if (fullX1 < extentX1) : fullX1 = extentX1; : : if (fullY1 < extentY1) : fullY1 = extentY1; : : if (fullX2 > extentX2) : fullX2 = extentX2; : : if (fullY2 > extentY2) : fullY2 = extentY2; : : if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) : continue; : n = REGION_NUM_RECTS (pClip); : if (n == 1) : { : (*pExaScr->info->Solid) (pPixmap, : fullX1 + xoff, fullY1 + yoff, : fullX2 + xoff, fullY2 + yoff); : } : else : { : pbox = REGION_RECTS(pClip); : /* : * clip the rectangle to each box in the clip region : * this is logically equivalent to calling Intersect(), : * but rectangles may overlap each other here. : */ : while(n--) : { : partX1 = pbox->x1; : if (partX1 < fullX1) : partX1 = fullX1; : partY1 = pbox->y1; : if (partY1 < fullY1) : partY1 = fullY1; : partX2 = pbox->x2; : if (partX2 > fullX2) : partX2 = fullX2; : partY2 = pbox->y2; : if (partY2 > fullY2) : partY2 = fullY2; : : pbox++; : : if (partX1 < partX2 && partY1 < partY2) { : (*pExaScr->info->Solid) (pPixmap, : partX1 + xoff, partY1 + yoff, : partX2 + xoff, partY2 + yoff); : } : } : } : } : (*pExaScr->info->DoneSolid) (pPixmap); : exaMarkSync(pDrawable->pScreen); : :out: : REGION_DESTROY(pScreen, pReg); :} : :static void :exaSolidBoxClipped (DrawablePtr pDrawable, : RegionPtr pClip, : FbBits pm, : FbBits fg, : int x1, : int y1, : int x2, : int y2) :{ : ExaScreenPriv (pDrawable->pScreen); : PixmapPtr pPixmap; : BoxPtr pbox; : int nbox; : int xoff, yoff; : int partX1, partX2, partY1, partY2; : ExaMigrationRec pixmaps[1]; : Bool fallback = FALSE; : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = FALSE; : pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); : : if (pExaScr->swappedOut || : pPixmap->drawable.width > pExaScr->info->maxX || : pPixmap->drawable.height > pExaScr->info->maxY) : { : fallback = TRUE; : } else { : exaDoMigration (pixmaps, 1, TRUE); : } : : exaGetDrawableDeltas (pDrawable, pPixmap, &xoff, &yoff); : : if (fallback || !exaPixmapIsOffscreen(pPixmap) || : !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg)) : { : EXA_FALLBACK(("to %p (%c)\n", pDrawable, : exaDrawableLocation(pDrawable))); : exaDoMigration (pixmaps, 1, FALSE); : fallback = TRUE; : exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); : fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); : fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, : fbAnd (GXcopy, fg, pm), : fbXor (GXcopy, fg, pm)); : exaFinishAccess (pDrawable, EXA_PREPARE_DEST); : } : for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); : nbox--; : pbox++) : { : partX1 = pbox->x1; : if (partX1 < x1) : partX1 = x1; : : partX2 = pbox->x2; : if (partX2 > x2) : partX2 = x2; : : if (partX2 <= partX1) : continue; : : partY1 = pbox->y1; : if (partY1 < y1) : partY1 = y1; : : partY2 = pbox->y2; : if (partY2 > y2) : partY2 = y2; : : if (partY2 <= partY1) : continue; : : if (!fallback) { : (*pExaScr->info->Solid) (pPixmap, : partX1 + xoff, partY1 + yoff, : partX2 + xoff, partY2 + yoff); : } : : exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, : partY2 + yoff); : } : : if (fallback) : return; : : (*pExaScr->info->DoneSolid) (pPixmap); : exaMarkSync(pDrawable->pScreen); :} : :static void :exaImageGlyphBlt (DrawablePtr pDrawable, : GCPtr pGC, : int x, : int y, : unsigned int nglyph, : CharInfoPtr *ppciInit, : pointer pglyphBase) :{ : FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); : CharInfoPtr *ppci; : CharInfoPtr pci; : unsigned char *pglyph; /* pointer bits in glyph */ : int gWidth, gHeight; /* width and height of glyph */ : FbStride gStride; /* stride of glyph */ : Bool opaque; : int n; : int gx, gy; : void (*glyph) (FbBits *, : FbStride, : int, : FbStip *, : FbBits, : int, : int); : FbBits *dst; : FbStride dstStride; : int dstBpp; : int dstXoff, dstYoff; : FbBits depthMask; : PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); : ExaMigrationRec pixmaps[1]; : int xBack, widthBack, yBack, heightBack; : : for (ppci = ppciInit, n = nglyph, widthBack = 0; n; n--) : widthBack += (*ppci++)->metrics.characterWidth; : : xBack = x; : if (widthBack < 0) : { : xBack += widthBack; : widthBack = -widthBack; : } : yBack = y - FONTASCENT(pGC->font); : heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); : : if (xBack >= pDrawable->width || yBack >= pDrawable->height || : (xBack + widthBack) <= 0 || (yBack + heightBack) <= 0) : return; : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = TRUE; : pixmaps[0].pPix = pPixmap; : : depthMask = FbFullMask(pDrawable->depth); : if ((pGC->planemask & depthMask) != depthMask) : { : exaDoMigration(pixmaps, 1, FALSE); : ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase); : goto damage; : } : glyph = NULL; : switch (pDrawable->bitsPerPixel) { : case 8: glyph = fbGlyph8; break; : case 16: glyph = fbGlyph16; break; : case 24: glyph = fbGlyph24; break; : case 32: glyph = fbGlyph32; break; : } : : x += pDrawable->x; : y += pDrawable->y; : xBack += pDrawable->x; : yBack += pDrawable->y; : : if (TERMINALFONT (pGC->font) && !glyph) : { : opaque = TRUE; : } : else : { : exaSolidBoxClipped (pDrawable, : fbGetCompositeClip(pGC), : pGC->planemask, : pGC->bgPixel, : xBack, : yBack, : xBack + widthBack, : yBack + heightBack); : opaque = FALSE; : } : : EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); : exaDoMigration(pixmaps, 1, FALSE); : exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); : exaPrepareAccessGC (pGC); : : fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); : : for (ppci = ppciInit; nglyph; nglyph--, x += pci->metrics.characterWidth) : { : pci = *ppci++; : gWidth = GLYPHWIDTHPIXELS(pci); : gHeight = GLYPHHEIGHTPIXELS(pci); : gx = x + pci->metrics.leftSideBearing; : gy = y - pci->metrics.ascent; : : if (!gWidth || !gHeight || (gx + gWidth) <= xBack || : (gy + gHeight) <= yBack || gx >= (xBack + widthBack) || : gy >= (yBack + heightBack)) : continue; : : pglyph = FONTGLYPHBITS(pglyphBase, pci); : : if (glyph && gWidth <= sizeof (FbStip) * 8 && : fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) : { : (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, : (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight); : } : else : { : RegionPtr pClip = fbGetCompositeClip(pGC); : : gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); : fbPutXYImage (pDrawable, pClip, pPriv->fg, pPriv->bg, pPriv->pm, : GXcopy, opaque, gx, gy, gWidth, gHeight, : (FbStip *) pglyph, gStride, 0); : } : } : exaFinishAccessGC (pGC); : exaFinishAccess (pDrawable, EXA_PREPARE_DEST); : :damage: : exaGetDrawableDeltas(pDrawable, pPixmap, &dstXoff, &dstYoff); : exaPixmapDirty(pPixmap, xBack + dstXoff, yBack + dstYoff, : xBack + dstXoff + widthBack, yBack + dstYoff + heightBack); :} : :const GCOps exaOps = { : exaFillSpans, : ExaCheckSetSpans, : exaPutImage, : exaCopyArea, : ExaCheckCopyPlane, : exaPolyPoint, : exaPolylines, : exaPolySegment, : miPolyRectangle, : ExaCheckPolyArc, : miFillPolygon, : exaPolyFillRect, : miPolyFillArc, : miPolyText8, : miPolyText16, : miImageText8, : miImageText16, : exaImageGlyphBlt, : ExaCheckPolyGlyphBlt, : ExaCheckPushPixels, :}; : :void :exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) :{ : RegionRec rgnDst; : int dx, dy; : PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); : : dx = ptOldOrg.x - pWin->drawable.x; : dy = ptOldOrg.y - pWin->drawable.y; : REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); : : REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); : : REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); :#ifdef COMPOSITE : if (pPixmap->screen_x || pPixmap->screen_y) : REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, : -pPixmap->screen_x, -pPixmap->screen_y); :#endif : : fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable, : NULL, : &rgnDst, dx, dy, exaCopyNtoN, 0, NULL); : : REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); :} : :static Bool :exaFillRegionSolid (DrawablePtr pDrawable, : RegionPtr pRegion, : Pixel pixel, : CARD32 planemask, : CARD32 alu) 2 0.0022 :{ /* exaFillRegionSolid total: 7 0.0076 */ : ExaScreenPriv(pDrawable->pScreen); : PixmapPtr pPixmap; : int xoff, yoff; : ExaMigrationRec pixmaps[1]; : int nbox = REGION_NUM_RECTS (pRegion); : BoxPtr pBox = REGION_RECTS (pRegion); : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = FALSE; 1 0.0011 : pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); : 1 0.0011 : if (pPixmap->drawable.width > pExaScr->info->maxX || : pPixmap->drawable.height > pExaScr->info->maxY) : { : goto fallback; : } else { : exaDoMigration (pixmaps, 1, TRUE); : } : 2 0.0022 : if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && : (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) : { : while (nbox--) : { : (*pExaScr->info->Solid) (pPixmap, : pBox->x1 + xoff, pBox->y1 + yoff, : pBox->x2 + xoff, pBox->y2 + yoff); : pBox++; : } : (*pExaScr->info->DoneSolid) (pPixmap); 1 0.0011 : exaMarkSync(pDrawable->pScreen); : } : else : { :fallback: : if (alu != GXcopy || planemask != FB_ALLONES) : return FALSE; : return TRUE; : EXA_FALLBACK(("to %p (%c)\n", pDrawable, : exaDrawableLocation(pDrawable))); : exaDoMigration (pixmaps, 1, FALSE); : exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); : fbFillRegionSolid (pDrawable, pRegion, 0, : fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); : exaFinishAccess (pDrawable, EXA_PREPARE_DEST); : } : : return TRUE; :} : :/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. : * Based on fbFillRegionTiled(), fbTile(). : */ :Bool :exaFillRegionTiled (DrawablePtr pDrawable, : RegionPtr pRegion, : PixmapPtr pTile, : DDXPointPtr pPatOrg, : CARD32 planemask, : CARD32 alu) :{ : ExaScreenPriv(pDrawable->pScreen); : PixmapPtr pPixmap; : int xoff, yoff, tileXoff, tileYoff; : int tileWidth, tileHeight; : ExaMigrationRec pixmaps[2]; : int nbox = REGION_NUM_RECTS (pRegion); : BoxPtr pBox = REGION_RECTS (pRegion); : : tileWidth = pTile->drawable.width; : tileHeight = pTile->drawable.height; : : /* If we're filling with a solid color, grab it out and go to : * FillRegionSolid, saving numerous copies. : */ : if (tileWidth == 1 && tileHeight == 1) : return exaFillRegionSolid(pDrawable, pRegion, : exaGetPixmapFirstPixel (pTile), planemask, : alu); : : pixmaps[0].as_dst = TRUE; : pixmaps[0].as_src = FALSE; : pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); : pixmaps[1].as_dst = FALSE; : pixmaps[1].as_src = TRUE; : pixmaps[1].pPix = pTile; : : if (pPixmap->drawable.width > pExaScr->info->maxX || : pPixmap->drawable.height > pExaScr->info->maxY || : tileWidth > pExaScr->info->maxX || : tileHeight > pExaScr->info->maxY) : { : goto fallback; : } else { : exaDoMigration (pixmaps, 2, TRUE); : } : : pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); : : if (!pPixmap) : goto fallback; : : if (!exaPixmapIsOffscreen(pTile)) : goto fallback; : : if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile, : &tileXoff, &tileYoff), : pPixmap, 0, 0, alu, planemask)) : { : while (nbox--) : { : int height = pBox->y2 - pBox->y1; : int dstY = pBox->y1; : int tileY; : : tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight; : while (height > 0) { : int width = pBox->x2 - pBox->x1; : int dstX = pBox->x1; : int tileX; : int h = tileHeight - tileY; : : if (h > height) : h = height; : height -= h; : : tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth; : while (width > 0) { : int w = tileWidth - tileX; : if (w > width) : w = width; : width -= w; : : (*pExaScr->info->Copy) (pPixmap, : tileX + tileXoff, tileY + tileYoff, : dstX + xoff, dstY + yoff, : w, h); : dstX += w; : tileX = 0; : } : dstY += h; : tileY = 0; : } : pBox++; : } : (*pExaScr->info->DoneCopy) (pPixmap); : exaMarkSync(pDrawable->pScreen); : return TRUE; : } : :fallback: : if (alu != GXcopy || planemask != FB_ALLONES) : return FALSE; : EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable, : exaDrawableLocation(&pTile->drawable), : exaDrawableLocation(pDrawable))); : exaDoMigration (pixmaps, 2, FALSE); : exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); : exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); : fbFillRegionTiled (pDrawable, pRegion, pTile); : exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); : exaFinishAccess (pDrawable, EXA_PREPARE_DEST); : : return TRUE; :} : :void :exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) :{ : ExaScreenPriv (pWin->drawable.pScreen); : PixmapPtr pPixmap = exaGetDrawablePixmap((DrawablePtr)pWin); : int xoff, yoff; : BoxPtr pBox; : int nbox = REGION_NUM_RECTS(pRegion); : : if (!nbox) : return; : : if (!pExaScr->swappedOut) { : DDXPointRec zeros = { 0, 0 }; : : switch (what) { : case PW_BACKGROUND: : switch (pWin->backgroundState) { : case None: : return; : case ParentRelative: : do { : pWin = pWin->parent; : } while (pWin->backgroundState == ParentRelative); : (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, : what); : return; : case BackgroundPixel: : exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel, : FB_ALLONES, GXcopy); : goto damage; : case BackgroundPixmap: : exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap, : &zeros, FB_ALLONES, GXcopy); : goto damage; : } : break; : case PW_BORDER: : if (pWin->borderIsPixel) { : exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel, : FB_ALLONES, GXcopy); : goto damage; : } else { : exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap, : &zeros, FB_ALLONES, GXcopy); : goto damage; : } : break; : } : } : ExaCheckPaintWindow (pWin, pRegion, what); : :damage: : exaGetDrawableDeltas((DrawablePtr)pWin, pPixmap, &xoff, &yoff); : : pBox = REGION_RECTS(pRegion); : : while (nbox--) : { : exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, : pBox->x2 + xoff, pBox->y2 + yoff); : pBox++; : } :} : :/** : * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. : * : * This is probably the only case we actually care about. The rest fall through : * to migration and ExaCheckGetImage, which hopefully will result in migration : * pushing the pixmap out of framebuffer. : */ :void :exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, : unsigned int format, unsigned long planeMask, char *d) :{ : ExaScreenPriv (pDrawable->pScreen); : ExaMigrationRec pixmaps[1]; : PixmapPtr pPix; : int xoff, yoff; : Bool ok; : : if (pExaScr->swappedOut || (w == 1 && h == 1)) : goto fallback; : : if (pExaScr->info->DownloadFromScreen == NULL) : goto migrate_and_fallback; : : /* Only cover the ZPixmap, solid copy case. */ : if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) : goto migrate_and_fallback; : : /* Only try to handle the 8bpp and up cases, since we don't want to think : * about <8bpp. : */ : if (pDrawable->bitsPerPixel < 8) : goto migrate_and_fallback; : : pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); : if (pPix == NULL) : goto fallback; : : xoff += pDrawable->x; : yoff += pDrawable->y; : : ok = pExaScr->info->DownloadFromScreen(pPix, x + xoff, y + yoff, w, h, d, : PixmapBytePad(w, pDrawable->depth)); : if (ok) { : exaWaitSync(pDrawable->pScreen); : return; : } : :migrate_and_fallback: : pixmaps[0].as_dst = FALSE; : pixmaps[0].as_src = TRUE; : pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); : exaDoMigration (pixmaps, 1, FALSE); :fallback: : ExaCheckGetImage (pDrawable, x, y, w, h, format, planeMask, d); :} : :/** : * GetSpans isn't accelerated yet, but performs migration so that we'll : * hopefully avoid the read-from-framebuffer cost. : */ :void :exaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, : int nspans, char *pdstStart) :{ : ExaMigrationRec pixmaps[1]; : : pixmaps[0].as_dst = FALSE; : pixmaps[0].as_src = TRUE; : pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); : exaDoMigration (pixmaps, 1, FALSE); : : ExaCheckGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/render/glyph.c" * * 103 0.1122 */ :/* : * : * Copyright © 2000 SuSE, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of SuSE not be used in advertising or : * publicity pertaining to distribution of the software without specific, : * written prior permission. SuSE makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : * : * Author: Keith Packard, SuSE, Inc. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "misc.h" :#include "scrnintstr.h" :#include "os.h" :#include "regionstr.h" :#include "validate.h" :#include "windowstr.h" :#include "input.h" :#include "resource.h" :#include "colormapst.h" :#include "cursorstr.h" :#include "dixstruct.h" :#include "gcstruct.h" :#include "servermd.h" :#include "picturestr.h" :#include "glyphstr.h" : :/* : * From Knuth -- a good choice for hash/rehash values is p, p-2 where : * p and p-2 are both prime. These tables are sized to have an extra 10% : * free to avoid exponential performance degradation as the hash table fills : */ :static GlyphHashSetRec glyphHashSets[] = { : { 32, 43, 41 }, : { 64, 73, 71 }, : { 128, 151, 149 }, : { 256, 283, 281 }, : { 512, 571, 569 }, : { 1024, 1153, 1151 }, : { 2048, 2269, 2267 }, : { 4096, 4519, 4517 }, : { 8192, 9013, 9011 }, : { 16384, 18043, 18041 }, : { 32768, 36109, 36107 }, : { 65536, 72091, 72089 }, : { 131072, 144409, 144407 }, : { 262144, 288361, 288359 }, : { 524288, 576883, 576881 }, : { 1048576, 1153459, 1153457 }, : { 2097152, 2307163, 2307161 }, : { 4194304, 4613893, 4613891 }, : { 8388608, 9227641, 9227639 }, : { 16777216, 18455029, 18455027 }, : { 33554432, 36911011, 36911009 }, : { 67108864, 73819861, 73819859 }, : { 134217728, 147639589, 147639587 }, : { 268435456, 295279081, 295279079 }, : { 536870912, 590559793, 590559791 } :}; : :#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) : :static const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; : :static GlyphHashRec globalGlyphs[GlyphFormatNum]; : :static int globalTotalGlyphPrivateSize = 0; : :static int glyphPrivateCount = 0; : :void :ResetGlyphPrivates (void) :{ : glyphPrivateCount = 0; :} : :int :AllocateGlyphPrivateIndex (void) :{ : return glyphPrivateCount++; :} : :Bool :AllocateGlyphPrivate (ScreenPtr pScreen, : int index2, : unsigned amount) :{ : PictureScreenPtr ps; : unsigned oldamount; : : ps = GetPictureScreenIfSet (pScreen); : if (!ps) : return FALSE; : : /* Round up sizes for proper alignment */ : amount = ((amount + (sizeof (DevUnion) - 1)) / sizeof (DevUnion)) * : sizeof (DevUnion); : : if (index2 >= ps->glyphPrivateLen) : { : unsigned *nsizes; : nsizes = (unsigned *) xrealloc (ps->glyphPrivateSizes, : (index2 + 1) * sizeof (unsigned)); : if (!nsizes) : return FALSE; : : while (ps->glyphPrivateLen <= index2) : { : nsizes[ps->glyphPrivateLen++] = 0; : ps->totalGlyphPrivateSize += sizeof (DevUnion); : } : ps->glyphPrivateSizes = nsizes; : } : oldamount = ps->glyphPrivateSizes[index2]; : if (amount > oldamount) : { : ps->glyphPrivateSizes[index2] = amount; : ps->totalGlyphPrivateSize += (amount - oldamount); : } : ps->totalGlyphPrivateSize = BitmapBytePad (ps->totalGlyphPrivateSize * 8); : : return TRUE; :} : :static void :SetGlyphScreenPrivateOffsets (void) :{ : PictureScreenPtr ps; : int offset = 0; : int i; : : for (i = 0; i < screenInfo.numScreens; i++) : { : ps = GetPictureScreenIfSet (screenInfo.screens[i]); : if (ps && ps->totalGlyphPrivateSize) : { : ps->glyphPrivateOffset = offset; : offset += ps->totalGlyphPrivateSize / sizeof (DevUnion); : } : } :} : :static void :SetGlyphPrivatePointers (GlyphPtr glyph) :{ : PictureScreenPtr ps; : int i; : char *ptr; : DevUnion *ppriv; : unsigned *sizes; : unsigned size; : int len; : : for (i = 0; i < screenInfo.numScreens; i++) : { : ps = GetPictureScreenIfSet (screenInfo.screens[i]); : if (ps && ps->totalGlyphPrivateSize) : { : ppriv = glyph->devPrivates + ps->glyphPrivateOffset; : sizes = ps->glyphPrivateSizes; : ptr = (char *) (ppriv + ps->glyphPrivateLen); : for (len = ps->glyphPrivateLen; --len >= 0; ppriv++, sizes++) : { : if ((size = *sizes) != 0) : { : ppriv->ptr = (pointer) ptr; : ptr += size; : } : else : ppriv->ptr = (pointer) 0; : } : } : } :} : :static Bool :ReallocGlobalGlyphPrivate (GlyphPtr glyph) :{ : PictureScreenPtr ps; : DevUnion *devPrivates; : char *ptr; : int i; : : devPrivates = xalloc (globalTotalGlyphPrivateSize); : if (!devPrivates) : return FALSE; : : ptr = (char *) devPrivates; : for (i = 0; i < screenInfo.numScreens; i++) : { : ps = GetPictureScreenIfSet (screenInfo.screens[i]); : if (ps && ps->totalGlyphPrivateSize) : { : if (ps->glyphPrivateOffset != -1) : { : memcpy (ptr, glyph->devPrivates + ps->glyphPrivateOffset, : ps->totalGlyphPrivateSize); : } : else if (ps->totalGlyphPrivateSize) : { : memset (ptr, 0, ps->totalGlyphPrivateSize); : } : : ptr += ps->totalGlyphPrivateSize; : } : } : : if (glyph->devPrivates) : xfree (glyph->devPrivates); : : glyph->devPrivates = devPrivates; : : return TRUE; :} : :Bool :GlyphInit (ScreenPtr pScreen) :{ : PictureScreenPtr ps = GetPictureScreen (pScreen); : : ps->totalGlyphPrivateSize = 0; : ps->glyphPrivateSizes = 0; : ps->glyphPrivateLen = 0; : ps->glyphPrivateOffset = -1; : : return TRUE; :} : :Bool :GlyphFinishInit (ScreenPtr pScreen) :{ : PictureScreenPtr ps = GetPictureScreen (pScreen); : : if (ps->totalGlyphPrivateSize) : { : GlyphPtr glyph; : int fdepth, i; : : globalTotalGlyphPrivateSize += ps->totalGlyphPrivateSize; : : for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) : { : if (!globalGlyphs[fdepth].hashSet) : continue; : : for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) : { : glyph = globalGlyphs[fdepth].table[i].glyph; : if (glyph && glyph != DeletedGlyph) : { : if (!ReallocGlobalGlyphPrivate (glyph)) : return FALSE; : } : } : } : : SetGlyphScreenPrivateOffsets (); : : for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) : { : if (!globalGlyphs[fdepth].hashSet) : continue; : : for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) : { : glyph = globalGlyphs[fdepth].table[i].glyph; : if (glyph && glyph != DeletedGlyph) : { : SetGlyphPrivatePointers (glyph); : : if (!(*ps->RealizeGlyph) (pScreen, glyph)) : return FALSE; : } : } : } : } : else : ps->glyphPrivateOffset = 0; : : return TRUE; :} : :void :GlyphUninit (ScreenPtr pScreen) :{ : PictureScreenPtr ps = GetPictureScreen (pScreen); : GlyphPtr glyph; : int fdepth, i; : : globalTotalGlyphPrivateSize -= ps->totalGlyphPrivateSize; : : for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) : { : if (!globalGlyphs[fdepth].hashSet) : continue; : : for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) : { : glyph = globalGlyphs[fdepth].table[i].glyph; : if (glyph && glyph != DeletedGlyph) : { : (*ps->UnrealizeGlyph) (pScreen, glyph); : : if (globalTotalGlyphPrivateSize) : { : if (!ReallocGlobalGlyphPrivate (glyph)) : return; : } : else : { : if (glyph->devPrivates) : xfree (glyph->devPrivates); : glyph->devPrivates = NULL; : } : } : } : } : : if (globalTotalGlyphPrivateSize) : SetGlyphScreenPrivateOffsets (); : : for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) : { : if (!globalGlyphs[fdepth].hashSet) : continue; : : for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) : { : glyph = globalGlyphs[fdepth].table[i].glyph; : if (glyph && glyph != DeletedGlyph) : { : if (globalTotalGlyphPrivateSize) : SetGlyphPrivatePointers (glyph); : } : } : } : : if (ps->glyphPrivateSizes) : xfree (ps->glyphPrivateSizes); :} : :GlyphHashSetPtr :FindGlyphHashSet (CARD32 filled) :{ : int i; : : for (i = 0; i < NGLYPHHASHSETS; i++) : if (glyphHashSets[i].entries >= filled) : return &glyphHashSets[i]; : return 0; :} : :static int _GlyphSetPrivateAllocateIndex = 0; : :int :AllocateGlyphSetPrivateIndex (void) :{ : return _GlyphSetPrivateAllocateIndex++; :} : :void :ResetGlyphSetPrivateIndex (void) :{ : _GlyphSetPrivateAllocateIndex = 0; :} : :Bool :_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr) :{ : pointer *new; : : if (n > glyphSet->maxPrivate) { : if (glyphSet->devPrivates && : glyphSet->devPrivates != (pointer)(&glyphSet[1])) { : new = (pointer *) xrealloc (glyphSet->devPrivates, : (n + 1) * sizeof (pointer)); : if (!new) : return FALSE; : } else { : new = (pointer *) xalloc ((n + 1) * sizeof (pointer)); : if (!new) : return FALSE; : if (glyphSet->devPrivates) : memcpy (new, : glyphSet->devPrivates, : (glyphSet->maxPrivate + 1) * sizeof (pointer)); : } : glyphSet->devPrivates = new; : /* Zero out new, uninitialize privates */ : while (++glyphSet->maxPrivate < n) : glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer)0; : } : glyphSet->devPrivates[n] = ptr; : return TRUE; :} : :GlyphRefPtr :FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) 9 0.0098 :{ /* FindGlyphRef total: 88 0.0959 */ : CARD32 elt, step, s; : GlyphPtr glyph; : GlyphRefPtr table, gr, del; 2 0.0022 : CARD32 tableSize = hash->hashSet->size; : 1 0.0011 : table = hash->table; 37 0.0403 : elt = signature % tableSize; : step = 0; : del = 0; : for (;;) : { 6 0.0065 : gr = &table[elt]; 13 0.0142 : s = gr->signature; 2 0.0022 : glyph = gr->glyph; 5 0.0054 : if (!glyph) : { : if (del) : gr = del; : break; : } : if (glyph == DeletedGlyph) : { : if (!del) : del = gr; : else if (gr == del) : break; : } 2 0.0022 : else if (s == signature && : (!match || : memcmp (&compare->info, &glyph->info, compare->size) == 0)) : { : break; : } 3 0.0033 : if (!step) : { 1 0.0011 : step = signature % hash->hashSet->rehash; 4 0.0044 : if (!step) : step = 1; : } : elt += step; : if (elt >= tableSize) : elt -= tableSize; : } : return gr; 3 0.0033 :} : :CARD32 :HashGlyph (GlyphPtr glyph) :{ : CARD32 *bits = (CARD32 *) &(glyph->info); : CARD32 hash; : int n = glyph->size / sizeof (CARD32); : : hash = 0; : while (n--) : hash ^= *bits++; : return hash; :} : :#ifdef CHECK_DUPLICATES :void :DuplicateRef (GlyphPtr glyph, char *where) :{ : ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); :} : :void :CheckDuplicates (GlyphHashPtr hash, char *where) :{ : GlyphPtr g; : int i, j; : : for (i = 0; i < hash->hashSet->size; i++) : { : g = hash->table[i].glyph; : if (!g || g == DeletedGlyph) : continue; : for (j = i + 1; j < hash->hashSet->size; j++) : if (hash->table[j].glyph == g) : DuplicateRef (g, where); : } :} :#else :#define CheckDuplicates(a,b) :#define DuplicateRef(a,b) :#endif : :void :FreeGlyph (GlyphPtr glyph, int format) :{ : CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); : if (--glyph->refcnt == 0) : { : PictureScreenPtr ps; : GlyphRefPtr gr; : int i; : int first; : : first = -1; : for (i = 0; i < globalGlyphs[format].hashSet->size; i++) : if (globalGlyphs[format].table[i].glyph == glyph) : { : if (first != -1) : DuplicateRef (glyph, "FreeGlyph check"); : first = i; : } : : gr = FindGlyphRef (&globalGlyphs[format], : HashGlyph (glyph), TRUE, glyph); : if (gr - globalGlyphs[format].table != first) : DuplicateRef (glyph, "Found wrong one"); : if (gr->glyph && gr->glyph != DeletedGlyph) : { : gr->glyph = DeletedGlyph; : gr->signature = 0; : globalGlyphs[format].tableEntries--; : } : : for (i = 0; i < screenInfo.numScreens; i++) : { : ps = GetPictureScreenIfSet (screenInfo.screens[i]); : if (ps) : (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); : } : : if (glyph->devPrivates) : xfree (glyph->devPrivates); : xfree (glyph); : } :} : :void :AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) :{ : GlyphRefPtr gr; : CARD32 hash; : : CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); : /* Locate existing matching glyph */ : hash = HashGlyph (glyph); : gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); : if (gr->glyph && gr->glyph != DeletedGlyph) : { : PictureScreenPtr ps; : int i; : : for (i = 0; i < screenInfo.numScreens; i++) : { : ps = GetPictureScreenIfSet (screenInfo.screens[i]); : if (ps) : (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); : } : if (glyph->devPrivates) : xfree (glyph->devPrivates); : xfree (glyph); : glyph = gr->glyph; : } : else : { : gr->glyph = glyph; : gr->signature = hash; : globalGlyphs[glyphSet->fdepth].tableEntries++; : } : : /* Insert/replace glyphset value */ : gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); : ++glyph->refcnt; : if (gr->glyph && gr->glyph != DeletedGlyph) : FreeGlyph (gr->glyph, glyphSet->fdepth); : else : glyphSet->hash.tableEntries++; : gr->glyph = glyph; : gr->signature = id; : CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); :} : :Bool :DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) :{ : GlyphRefPtr gr; : GlyphPtr glyph; : : gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); : glyph = gr->glyph; : if (glyph && glyph != DeletedGlyph) : { : gr->glyph = DeletedGlyph; : glyphSet->hash.tableEntries--; : FreeGlyph (glyph, glyphSet->fdepth); : return TRUE; : } : return FALSE; :} : :GlyphPtr :FindGlyph (GlyphSetPtr glyphSet, Glyph id) 6 0.0065 :{ /* FindGlyph total: 15 0.0163 */ : GlyphPtr glyph; : 3 0.0033 : glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; 2 0.0022 : if (glyph == DeletedGlyph) : glyph = 0; : return glyph; 4 0.0044 :} : :GlyphPtr :AllocateGlyph (xGlyphInfo *gi, int fdepth) :{ : PictureScreenPtr ps; : int size; : GlyphPtr glyph; : int i; : : size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); : glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); : if (!glyph) : return 0; : glyph->refcnt = 0; : glyph->size = size + sizeof (xGlyphInfo); : glyph->info = *gi; : : if (globalTotalGlyphPrivateSize) : { : glyph->devPrivates = xalloc (globalTotalGlyphPrivateSize); : if (!glyph->devPrivates) : return 0; : : SetGlyphPrivatePointers (glyph); : } else : glyph->devPrivates = NULL; : : for (i = 0; i < screenInfo.numScreens; i++) : { : ps = GetPictureScreenIfSet (screenInfo.screens[i]); : if (ps) : { : if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph)) : { : while (i--) : { : ps = GetPictureScreenIfSet (screenInfo.screens[i]); : if (ps) : (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); : } : : if (glyph->devPrivates) : xfree (glyph->devPrivates); : xfree (glyph); : return 0; : } : } : } : : return glyph; :} : :Bool :AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) :{ : hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); : if (!hash->table) : return FALSE; : memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); : hash->hashSet = hashSet; : hash->tableEntries = 0; : return TRUE; :} : :Bool :ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) :{ : CARD32 tableEntries; : GlyphHashSetPtr hashSet; : GlyphHashRec newHash; : GlyphRefPtr gr; : GlyphPtr glyph; : int i; : int oldSize; : CARD32 s; : : tableEntries = hash->tableEntries + change; : hashSet = FindGlyphHashSet (tableEntries); : if (hashSet == hash->hashSet) : return TRUE; : if (global) : CheckDuplicates (hash, "ResizeGlyphHash top"); : if (!AllocateGlyphHash (&newHash, hashSet)) : return FALSE; : if (hash->table) : { : oldSize = hash->hashSet->size; : for (i = 0; i < oldSize; i++) : { : glyph = hash->table[i].glyph; : if (glyph && glyph != DeletedGlyph) : { : s = hash->table[i].signature; : gr = FindGlyphRef (&newHash, s, global, glyph); : gr->signature = s; : gr->glyph = glyph; : ++newHash.tableEntries; : } : } : xfree (hash->table); : } : *hash = newHash; : if (global) : CheckDuplicates (hash, "ResizeGlyphHash bottom"); : return TRUE; :} : :Bool :ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) :{ : return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && : ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); :} : :GlyphSetPtr :AllocateGlyphSet (int fdepth, PictFormatPtr format) :{ : GlyphSetPtr glyphSet; : int size; : : if (!globalGlyphs[fdepth].hashSet) : { : if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) : return FALSE; : } : : size = (sizeof (GlyphSetRec) + : (sizeof (pointer) * _GlyphSetPrivateAllocateIndex)); : glyphSet = xalloc (size); : if (!glyphSet) : return FALSE; : bzero((char *)glyphSet, size); : glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1; : if (_GlyphSetPrivateAllocateIndex) : glyphSet->devPrivates = (pointer)(&glyphSet[1]); : : if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) : { : xfree (glyphSet); : return FALSE; : } : glyphSet->refcnt = 1; : glyphSet->fdepth = fdepth; : glyphSet->format = format; : return glyphSet; :} : :int :FreeGlyphSet (pointer value, : XID gid) :{ : GlyphSetPtr glyphSet = (GlyphSetPtr) value; : : if (--glyphSet->refcnt == 0) : { : CARD32 i, tableSize = glyphSet->hash.hashSet->size; : GlyphRefPtr table = glyphSet->hash.table; : GlyphPtr glyph; : : for (i = 0; i < tableSize; i++) : { : glyph = table[i].glyph; : if (glyph && glyph != DeletedGlyph) : FreeGlyph (glyph, glyphSet->fdepth); : } : if (!globalGlyphs[glyphSet->fdepth].tableEntries) : { : xfree (globalGlyphs[glyphSet->fdepth].table); : globalGlyphs[glyphSet->fdepth].table = 0; : globalGlyphs[glyphSet->fdepth].hashSet = 0; : } : else : ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); : xfree (table); : : if (glyphSet->devPrivates && : glyphSet->devPrivates != (pointer)(&glyphSet[1])) : xfree(glyphSet->devPrivates); : : xfree (glyphSet); : } : return Success; :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/Xext/xace.c" * * 101 0.1100 */ :/************************************************************ : :Author: Eamon Walsh : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :this permission notice appear in supporting documentation. This permission :notice shall be included in all copies or substantial portions of the :Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :********************************************************/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include "windowstr.h" :#include "scrnintstr.h" :#include "gcstruct.h" :#include "xacestr.h" :#include "modinit.h" : :CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0}; : :/* Proc vectors for untrusted clients, swapped and unswapped versions. : * These are the same as the normal proc vectors except that extensions : * that haven't declared themselves secure will have ProcBadRequest plugged : * in for their major opcode dispatcher. This prevents untrusted clients : * from guessing extension major opcodes and using the extension even though : * the extension can't be listed or queried. : */ :static int (*UntrustedProcVector[256])( : ClientPtr /*client*/ :); :static int (*SwappedUntrustedProcVector[256])( : ClientPtr /*client*/ :); : :/* Entry point for hook functions. Called by Xserver. : */ :int XaceHook(int hook, ...) 22 0.0240 :{ /* XaceHook total: 74 0.0806 */ : pointer calldata; /* data passed to callback */ : int *prv = NULL; /* points to return value from callback */ : va_list ap; /* argument list */ 8 0.0087 : va_start(ap, hook); : : /* Marshal arguments for passing to callback. : * Each callback has its own case, which sets up a structure to hold : * the arguments and integer return parameter, or in some cases just : * sets calldata directly to a single argument (with no return result) : */ 7 0.0076 : switch (hook) : { : case XACE_CORE_DISPATCH: { : XaceCoreDispatchRec rec = { : va_arg(ap, ClientPtr), : TRUE /* default allow */ : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_RESOURCE_ACCESS: { : XaceResourceAccessRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, XID), : va_arg(ap, RESTYPE), : va_arg(ap, Mask), : va_arg(ap, pointer), : TRUE /* default allow */ 13 0.0142 : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_DEVICE_ACCESS: { : XaceDeviceAccessRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, DeviceIntPtr), : va_arg(ap, Bool), : TRUE /* default allow */ : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_PROPERTY_ACCESS: { : XacePropertyAccessRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, WindowPtr), : va_arg(ap, Atom), : va_arg(ap, Mask), : XaceAllowOperation /* default allow */ : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_DRAWABLE_ACCESS: { : XaceDrawableAccessRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, DrawablePtr), : TRUE /* default allow */ : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_MAP_ACCESS: : case XACE_BACKGRND_ACCESS: { : XaceMapAccessRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, WindowPtr), : TRUE /* default allow */ : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_EXT_DISPATCH: : case XACE_EXT_ACCESS: { : XaceExtAccessRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, ExtensionEntry*), : TRUE /* default allow */ : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_HOSTLIST_ACCESS: { : XaceHostlistAccessRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, Mask), : TRUE /* default allow */ : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_SITE_POLICY: { : XaceSitePolicyRec rec = { : va_arg(ap, char*), : va_arg(ap, int), : FALSE /* default unrecognized */ : }; : calldata = &rec; : prv = &rec.rval; : break; : } : case XACE_DECLARE_EXT_SECURE: { : XaceDeclareExtSecureRec rec = { : va_arg(ap, ExtensionEntry*), : va_arg(ap, Bool) : }; : calldata = &rec; : break; : } : case XACE_AUTH_AVAIL: { : XaceAuthAvailRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, XID) : }; : calldata = &rec; : break; : } : case XACE_KEY_AVAIL: { : XaceKeyAvailRec rec = { : va_arg(ap, xEventPtr), : va_arg(ap, DeviceIntPtr), : va_arg(ap, int) : }; : calldata = &rec; : break; : } : case XACE_WINDOW_INIT: { : XaceWindowRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, WindowPtr) : }; : calldata = &rec; : break; : } : case XACE_AUDIT_BEGIN: { : XaceAuditRec rec = { : va_arg(ap, ClientPtr), : 0 2 0.0022 : }; : calldata = &rec; : break; : } : case XACE_AUDIT_END: { : XaceAuditRec rec = { : va_arg(ap, ClientPtr), : va_arg(ap, int) 2 0.0022 : }; : calldata = &rec; : break; : } : default: { : va_end(ap); : return 0; /* unimplemented hook number */ : } : } : va_end(ap); : : /* call callbacks and return result, if any. */ 10 0.0109 : CallCallbacks(&XaceHooks[hook], calldata); 4 0.0044 : return prv ? *prv : 0; 6 0.0065 :} : :static int :ProcXaceDispatch(ClientPtr client) :{ : REQUEST(xReq); : : switch (stuff->data) : { : default: : return BadRequest; : } :} /* ProcXaceDispatch */ : :static int :SProcXaceDispatch(ClientPtr client) :{ : REQUEST(xReq); : : switch (stuff->data) : { : default: : return BadRequest; : } :} /* SProcXaceDispatch */ : : :/* XaceResetProc : * : * Arguments: : * extEntry is the extension information for the XACE extension. : * : * Returns: nothing. : * : * Side Effects: : * Performs any cleanup needed by XACE at server shutdown time. : */ :static void :XaceResetProc(ExtensionEntry *extEntry) :{ : int i; : : for (i=0; ireqType; : 5 0.0054 : if (!ProcVector[major]) : return (BadRequest); : : if (!XaceHook(XACE_CORE_DISPATCH, client)) : return (BadAccess); : : return client->swapped ? : (* SwappedProcVector[major])(client) : : (* ProcVector[major])(client); :} : :static int :XaceCatchExtProc(ClientPtr client) 4 0.0044 :{ /* XaceCatchExtProc total: 22 0.0240 */ : REQUEST(xReq); : int major = stuff->reqType; 2 0.0022 : ExtensionEntry *ext = GetExtensionEntry(major); : 2 0.0022 : if (!ext || !ProcVector[major]) : return (BadRequest); : 1 0.0011 : if (!XaceHook(XACE_EXT_DISPATCH, client, ext)) : return (BadRequest); /* pretend extension doesn't exist */ : 1 0.0011 : return client->swapped ? : (* SwappedProcVector[major])(client) : : (* ProcVector[major])(client); 12 0.0131 :} : : :/* SecurityClientStateCallback : * : * Arguments: : * pcbl is &ClientStateCallback. : * nullata is NULL. : * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) : * which contains information about client state changes. : * : * Returns: nothing. : * : * Side Effects: : * : * If a new client is connecting, its authorization ID is copied to : * client->authID. If this is a generated authorization, its reference : * count is bumped, its timer is cancelled if it was running, and its : * trustlevel is copied to TRUSTLEVEL(client). : * : * If a client is disconnecting and the client was using a generated : * authorization, the authorization's reference count is decremented, and : * if it is now zero, the timer for this authorization is started. : */ : :static void :XaceClientStateCallback( : CallbackListPtr *pcbl, : pointer nulldata, : pointer calldata) :{ : NewClientInfoRec *pci = (NewClientInfoRec *)calldata; : ClientPtr client = pci->client; : : switch (client->clientState) : { : case ClientStateRunning: : { : client->requestVector = client->swapped ? : SwappedUntrustedProcVector : UntrustedProcVector; : break; : } : default: break; : } :} /* XaceClientStateCallback */ : :/* XaceExtensionInit : * : * Initialize the XACE Extension : */ :void XaceExtensionInit(INITARGS) :{ : ExtensionEntry *extEntry; : int i; : : if (!AddCallback(&ClientStateCallback, XaceClientStateCallback, NULL)) : return; : : extEntry = AddExtension(XACE_EXTENSION_NAME, : XaceNumberEvents, XaceNumberErrors, : ProcXaceDispatch, SProcXaceDispatch, : XaceResetProc, StandardMinorOpcode); : : /* initialize dispatching intercept functions */ : for (i = 0; i < 128; i++) : { : UntrustedProcVector[i] = XaceCatchDispatchProc; : SwappedUntrustedProcVector[i] = XaceCatchDispatchProc; : } : for (i = 128; i < 256; i++) : { : UntrustedProcVector[i] = XaceCatchExtProc; : SwappedUntrustedProcVector[i] = XaceCatchExtProc; : } :} : :/* XaceCensorImage : * : * Called after pScreen->GetImage to prevent pieces or trusted windows from : * being returned in image data from an untrusted window. : * : * Arguments: : * client is the client doing the GetImage. : * pVisibleRegion is the visible region of the window. : * widthBytesLine is the width in bytes of one horizontal line in pBuf. : * pDraw is the source window. : * x, y, w, h is the rectangle of image data from pDraw in pBuf. : * format is the format of the image data in pBuf: ZPixmap or XYPixmap. : * pBuf is the image data. : * : * Returns: nothing. : * : * Side Effects: : * Any part of the rectangle (x, y, w, h) that is outside the visible : * region of the window will be destroyed (overwritten) in pBuf. : */ :void :XaceCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h, : format, pBuf) : ClientPtr client; : RegionPtr pVisibleRegion; : long widthBytesLine; : DrawablePtr pDraw; : int x, y, w, h; : unsigned int format; : char * pBuf; :{ : ScreenPtr pScreen; : RegionRec imageRegion; /* region representing x,y,w,h */ : RegionRec censorRegion; /* region to obliterate */ : BoxRec imageBox; : int nRects; : : pScreen = pDraw->pScreen; : : imageBox.x1 = x; : imageBox.y1 = y; : imageBox.x2 = x + w; : imageBox.y2 = y + h; : REGION_INIT(pScreen, &imageRegion, &imageBox, 1); : REGION_NULL(pScreen, &censorRegion); : : /* censorRegion = imageRegion - visibleRegion */ : REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion); : nRects = REGION_NUM_RECTS(&censorRegion); : if (nRects > 0) : { /* we have something to censor */ : GCPtr pScratchGC = NULL; : PixmapPtr pPix = NULL; : xRectangle *pRects = NULL; : Bool failed = FALSE; : int depth = 1; : int bitsPerPixel = 1; : int i; : BoxPtr pBox; : : /* convert region to list-of-rectangles for PolyFillRect */ : : pRects = (xRectangle *)ALLOCATE_LOCAL(nRects * sizeof(xRectangle *)); : if (!pRects) : { : failed = TRUE; : goto failSafe; : } : for (pBox = REGION_RECTS(&censorRegion), i = 0; : i < nRects; : i++, pBox++) : { : pRects[i].x = pBox->x1; : pRects[i].y = pBox->y1 - imageBox.y1; : pRects[i].width = pBox->x2 - pBox->x1; : pRects[i].height = pBox->y2 - pBox->y1; : } : : /* use pBuf as a fake pixmap */ : : if (format == ZPixmap) : { : depth = pDraw->depth; : bitsPerPixel = pDraw->bitsPerPixel; : } : : pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, : depth, bitsPerPixel, : widthBytesLine, (pointer)pBuf); : if (!pPix) : { : failed = TRUE; : goto failSafe; : } : : pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); : if (!pScratchGC) : { : failed = TRUE; : goto failSafe; : } : : ValidateGC(&pPix->drawable, pScratchGC); : (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, : pScratchGC, nRects, pRects); : : failSafe: : if (failed) : { : /* Censoring was not completed above. To be safe, wipe out : * all the image data so that nothing trusted gets out. : */ : bzero(pBuf, (int)(widthBytesLine * h)); : } : if (pRects) DEALLOCATE_LOCAL(pRects); : if (pScratchGC) FreeScratchGC(pScratchGC); : if (pPix) FreeScratchPixmapHeader(pPix); : } : REGION_UNINIT(pScreen, &imageRegion); : REGION_UNINIT(pScreen, &censorRegion); :} /* XaceCensorImage */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/dix/dixutils.c" * * 87 0.0948 */ :/*********************************************************** : :Copyright 1987, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :******************************************************************/ : :/* : :(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved. : :Permission to use, copy, modify, distribute, and sublicense this software and its :documentation for any purpose and without fee is hereby granted, provided that :the above copyright notices appear in all copies and that both those copyright :notices and this permission notice appear in supporting documentation and that :the name of Adobe Systems Incorporated not be used in advertising or publicity :pertaining to distribution of the software without specific, written prior :permission. No trademark license to use the Adobe trademarks is hereby :granted. If the Adobe trademark "Display PostScript"(tm) is used to describe :this software, its functionality or for any other purpose, such use shall be :limited to a statement that this software works in conjunction with the Display :PostScript system. Proper trademark attribution to reflect Adobe's ownership :of the trademark shall be given whenever any such reference to the Display :PostScript system is made. : :ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY :PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE :DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED :WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- :INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU :OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY :DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT :LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR :PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER :SUPPORT FOR THE SOFTWARE. : :Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems :Incorporated which may be registered in certain jurisdictions. : :Author: Adobe Systems Incorporated : :*/ : : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include :#include "misc.h" :#include "windowstr.h" :#include "dixstruct.h" :#include "pixmapstr.h" :#include "scrnintstr.h" :#define XK_LATIN1 :#include :#include "xace.h" : :/* : * CompareTimeStamps returns -1, 0, or +1 depending on if the first : * argument is less than, equal to or greater than the second argument. : */ : :_X_EXPORT int :CompareTimeStamps(TimeStamp a, TimeStamp b) :{ : if (a.months < b.months) : return EARLIER; : if (a.months > b.months) : return LATER; : if (a.milliseconds < b.milliseconds) : return EARLIER; : if (a.milliseconds > b.milliseconds) : return LATER; : return SAMETIME; :} : :/* : * convert client times to server TimeStamps : */ : :#define HALFMONTH ((unsigned long) 1<<31) :_X_EXPORT TimeStamp :ClientTimeToServerTime(CARD32 c) :{ : TimeStamp ts; : if (c == CurrentTime) : return currentTime; : ts.months = currentTime.months; : ts.milliseconds = c; : if (c > currentTime.milliseconds) : { : if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH) : ts.months -= 1; : } : else if (c < currentTime.milliseconds) : { : if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH) : ts.months += 1; : } : return ts; :} : :/* : * ISO Latin-1 case conversion routine : * : * this routine always null-terminates the result, so : * beware of too-small buffers : */ : :static unsigned char :ISOLatin1ToLower (unsigned char source) :{ : unsigned char dest; : if ((source >= XK_A) && (source <= XK_Z)) : dest = source + (XK_a - XK_A); : else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis)) : dest = source + (XK_agrave - XK_Agrave); : else if ((source >= XK_Ooblique) && (source <= XK_Thorn)) : dest = source + (XK_oslash - XK_Ooblique); : else : dest = source; : return dest; :} : : :_X_EXPORT void :CopyISOLatin1Lowered(unsigned char *dest, unsigned char *source, int length) :{ : int i; : : for (i = 0; i < length; i++, source++, dest++) : *dest = ISOLatin1ToLower (*source); : *dest = '\0'; :} : :int :CompareISOLatin1Lowered(unsigned char *s1, int s1len, : unsigned char *s2, int s2len) 1 0.0011 :{ /* CompareISOLatin1Lowered total: 22 0.0240 */ : unsigned char c1, c2; : : for (;;) : { : /* note -- compare against zero so that -1 ignores len */ 8 0.0087 : c1 = s1len-- ? *s1++ : '\0'; 10 0.0109 : c2 = s2len-- ? *s2++ : '\0'; 3 0.0033 : if (!c1 || : (c1 != c2 && : (c1 = ISOLatin1ToLower (c1)) != (c2 = ISOLatin1ToLower (c2)))) : break; : } : return (int) c1 - (int) c2; :} : :/* : * dixLookupWindow and dixLookupDrawable: : * Look up the window/drawable taking into account the client doing the : * lookup, the type of drawable desired, and the type of access desired. : * Return Success with *pDraw set if the window/drawable exists and the client : * is allowed access, else return an error code with *pDraw set to NULL. The : * access mask values are defined in resource.h. The type mask values are : * defined in pixmap.h, with zero equivalent to M_DRAWABLE. : */ :_X_EXPORT int :dixLookupDrawable(DrawablePtr *pDraw, XID id, ClientPtr client, : Mask type, Mask access) 1 0.0011 :{ /* dixLookupDrawable total: 6 0.0065 */ : DrawablePtr pTmp; : RESTYPE rtype; : *pDraw = NULL; : client->errorValue = id; : : if (id == INVALID) : return BadDrawable; : : if (id == client->lastDrawableID) { : pTmp = client->lastDrawable; : : /* an access check is required for cached drawables */ : rtype = (type & M_WINDOW) ? RT_WINDOW : RT_PIXMAP; : if (!XaceHook(XACE_RESOURCE_ACCESS, client, id, rtype, access, pTmp)) : return BadDrawable; : } else : pTmp = (DrawablePtr)SecurityLookupIDByClass(client, id, RC_DRAWABLE, : access); : if (!pTmp) : return BadDrawable; 3 0.0033 : if (!((1 << pTmp->type) & (type ? type : M_DRAWABLE))) : return BadMatch; : : if (type & M_DRAWABLE) { : client->lastDrawable = pTmp; : client->lastDrawableID = id; : client->lastGCID = INVALID; : client->lastGC = (GCPtr)NULL; : } : *pDraw = pTmp; : return Success; 2 0.0022 :} : :_X_EXPORT int :dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access) :{ : int rc; : rc = dixLookupDrawable((DrawablePtr*)pWin, id, client, M_WINDOW, access); : return (rc == BadDrawable) ? BadWindow : rc; :} : :_X_EXPORT int :dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access) 1 0.0011 :{ /* dixLookupGC total: 2 0.0022 */ 1 0.0011 : GCPtr pTmp = (GCPtr)SecurityLookupIDByType(client, id, RT_GC, access); : if (pTmp) { : *pGC = pTmp; : return Success; : } : client->errorValue = id; : *pGC = NULL; : return BadGC; :} : :_X_EXPORT int :dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access) :{ : pointer pRes = (pointer)SecurityLookupIDByClass(client, rid, RC_ANY, : access); : int clientIndex = CLIENT_ID(rid); : client->errorValue = rid; : : if (clientIndex && pRes && clients[clientIndex] && !(rid & SERVER_BIT)) { : *pClient = clients[clientIndex]; : return Success; : } : *pClient = NULL; : return BadValue; :} : :/* : * These are deprecated compatibility functions and will be removed soon! : * Please use the new dixLookup*() functions above. : */ :_X_EXPORT _X_DEPRECATED WindowPtr :SecurityLookupWindow(XID id, ClientPtr client, Mask access_mode) :{ : WindowPtr pWin; : int i = dixLookupWindow(&pWin, id, client, access_mode); : static int warn = 1; : if (warn-- > 0) : ErrorF("Warning: LookupWindow()/SecurityLookupWindow() " : "are deprecated. Please convert your driver/module " : "to use dixLookupWindow().\n"); : return (i == Success) ? pWin : NULL; :} : :_X_EXPORT _X_DEPRECATED WindowPtr :LookupWindow(XID id, ClientPtr client) :{ : return SecurityLookupWindow(id, client, DixUnknownAccess); :} : :_X_EXPORT _X_DEPRECATED pointer :SecurityLookupDrawable(XID id, ClientPtr client, Mask access_mode) :{ : DrawablePtr pDraw; : int i = dixLookupDrawable(&pDraw, id, client, M_DRAWABLE, access_mode); : static int warn = 1; : if (warn-- > 0) : ErrorF("Warning: LookupDrawable()/SecurityLookupDrawable() " : "are deprecated. Please convert your driver/module " : "to use dixLookupDrawable().\n"); : return (i == Success) ? pDraw : NULL; :} : :_X_EXPORT _X_DEPRECATED pointer :LookupDrawable(XID id, ClientPtr client) :{ : return SecurityLookupDrawable(id, client, DixUnknownAccess); :} : :_X_EXPORT _X_DEPRECATED ClientPtr :LookupClient(XID id, ClientPtr client) :{ : ClientPtr pClient; : int i = dixLookupClient(&pClient, id, client, DixUnknownAccess); : static int warn = 1; : if (warn-- > 0) : ErrorF("Warning: LookupClient() is deprecated. Please convert your " : "driver/module to use dixLookupClient().\n"); : return (i == Success) ? pClient : NULL; :} : :/* end deprecated functions */ : :int :AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode, : Bool toRoot, Bool remap) :{ : int numnow; : SaveSetElt *pTmp = NULL; : int j; : : numnow = client->numSaved; : j = 0; : if (numnow) : { : pTmp = client->saveSet; : while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (pointer)pWin)) : j++; : } : if (mode == SetModeInsert) : { : if (j < numnow) /* duplicate */ : return(Success); : numnow++; : pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow); : if (!pTmp) : return(BadAlloc); : client->saveSet = pTmp; : client->numSaved = numnow; : SaveSetAssignWindow(client->saveSet[numnow - 1], pWin); : SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot); : SaveSetAssignRemap(client->saveSet[numnow - 1], remap); : return(Success); : } : else if ((mode == SetModeDelete) && (j < numnow)) : { : while (j < numnow-1) : { : pTmp[j] = pTmp[j+1]; : j++; : } : numnow--; : if (numnow) : { : pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow); : if (pTmp) : client->saveSet = pTmp; : } : else : { : xfree(client->saveSet); : client->saveSet = (SaveSetElt *)NULL; : } : client->numSaved = numnow; : return(Success); : } : return(Success); :} : :void :DeleteWindowFromAnySaveSet(WindowPtr pWin) :{ : int i; : ClientPtr client; : : for (i = 0; i< currentMaxClients; i++) : { : client = clients[i]; : if (client && client->numSaved) : (void)AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE, TRUE); : } :} : :/* No-op Don't Do Anything : sometimes we need to be able to call a procedure : * that doesn't do anything. For example, on screen with only static : * colormaps, if someone calls install colormap, it's easier to have a dummy : * procedure to call than to check if there's a procedure : */ :_X_EXPORT void :NoopDDA(void) :{ :} : :typedef struct _BlockHandler { : BlockHandlerProcPtr BlockHandler; : WakeupHandlerProcPtr WakeupHandler; : pointer blockData; : Bool deleted; :} BlockHandlerRec, *BlockHandlerPtr; : :static BlockHandlerPtr handlers; :static int numHandlers; :static int sizeHandlers; :static Bool inHandler; :static Bool handlerDeleted; : :/** : * : * \param pTimeout DIX doesn't want to know how OS represents time : * \param pReadMask nor how it represents the det of descriptors : */ :void :BlockHandler(pointer pTimeout, pointer pReadmask) :{ : int i, j; : : ++inHandler; : for (i = 0; i < screenInfo.numScreens; i++) : (* screenInfo.screens[i]->BlockHandler)(i, : screenInfo.screens[i]->blockData, : pTimeout, pReadmask); : for (i = 0; i < numHandlers; i++) : (*handlers[i].BlockHandler) (handlers[i].blockData, : pTimeout, pReadmask); : if (handlerDeleted) : { : for (i = 0; i < numHandlers;) : if (handlers[i].deleted) : { : for (j = i; j < numHandlers - 1; j++) : handlers[j] = handlers[j+1]; : numHandlers--; : } : else : i++; : handlerDeleted = FALSE; : } : --inHandler; :} : :/** : * : * \param result 32 bits of undefined result from the wait : * \param pReadmask the resulting descriptor mask : */ :void :WakeupHandler(int result, pointer pReadmask) :{ : int i, j; : : ++inHandler; : for (i = numHandlers - 1; i >= 0; i--) : (*handlers[i].WakeupHandler) (handlers[i].blockData, : result, pReadmask); : for (i = 0; i < screenInfo.numScreens; i++) : (* screenInfo.screens[i]->WakeupHandler)(i, : screenInfo.screens[i]->wakeupData, : result, pReadmask); : if (handlerDeleted) : { : for (i = 0; i < numHandlers;) : if (handlers[i].deleted) : { : for (j = i; j < numHandlers - 1; j++) : handlers[j] = handlers[j+1]; : numHandlers--; : } : else : i++; : handlerDeleted = FALSE; : } : --inHandler; :} : :/** : * Reentrant with BlockHandler and WakeupHandler, except wakeup won't : * get called until next time : */ :_X_EXPORT Bool :RegisterBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler, : WakeupHandlerProcPtr wakeupHandler, : pointer blockData) :{ : BlockHandlerPtr new; : : if (numHandlers >= sizeHandlers) : { : new = (BlockHandlerPtr) xrealloc (handlers, (numHandlers + 1) * : sizeof (BlockHandlerRec)); : if (!new) : return FALSE; : handlers = new; : sizeHandlers = numHandlers + 1; : } : handlers[numHandlers].BlockHandler = blockHandler; : handlers[numHandlers].WakeupHandler = wakeupHandler; : handlers[numHandlers].blockData = blockData; : handlers[numHandlers].deleted = FALSE; : numHandlers = numHandlers + 1; : return TRUE; :} : :_X_EXPORT void :RemoveBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler, : WakeupHandlerProcPtr wakeupHandler, : pointer blockData) :{ : int i; : : for (i = 0; i < numHandlers; i++) : if (handlers[i].BlockHandler == blockHandler && : handlers[i].WakeupHandler == wakeupHandler && : handlers[i].blockData == blockData) : { : if (inHandler) : { : handlerDeleted = TRUE; : handlers[i].deleted = TRUE; : } : else : { : for (; i < numHandlers - 1; i++) : handlers[i] = handlers[i+1]; : numHandlers--; : } : break; : } :} : :void :InitBlockAndWakeupHandlers (void) :{ : xfree (handlers); : handlers = (BlockHandlerPtr) 0; : numHandlers = 0; : sizeHandlers = 0; :} : :/* : * A general work queue. Perform some task before the server : * sleeps for input. : */ : :WorkQueuePtr workQueue; :static WorkQueuePtr *workQueueLast = &workQueue; : :void :ProcessWorkQueue(void) :{ : WorkQueuePtr q, *p; : : p = &workQueue; : /* : * Scan the work queue once, calling each function. Those : * which return TRUE are removed from the queue, otherwise : * they will be called again. This must be reentrant with : * QueueWorkProc. : */ : while ((q = *p)) : { : if ((*q->function) (q->client, q->closure)) : { : /* remove q from the list */ : *p = q->next; /* don't fetch until after func called */ : xfree (q); : } : else : { : p = &q->next; /* don't fetch until after func called */ : } : } : workQueueLast = p; :} : :void :ProcessWorkQueueZombies(void) :{ : WorkQueuePtr q, *p; : : p = &workQueue; : while ((q = *p)) : { : if (q->client && q->client->clientGone) : { : (void) (*q->function) (q->client, q->closure); : /* remove q from the list */ : *p = q->next; /* don't fetch until after func called */ : xfree (q); : } : else : { : p = &q->next; /* don't fetch until after func called */ : } : } : workQueueLast = p; :} : :_X_EXPORT Bool :QueueWorkProc ( : Bool (*function)(ClientPtr /* pClient */, pointer /* closure */), : ClientPtr client, pointer closure) :{ : WorkQueuePtr q; : : q = (WorkQueuePtr) xalloc (sizeof *q); : if (!q) : return FALSE; : q->function = function; : q->client = client; : q->closure = closure; : q->next = NULL; : *workQueueLast = q; : workQueueLast = &q->next; : return TRUE; :} : :/* : * Manage a queue of sleeping clients, awakening them : * when requested, by using the OS functions IgnoreClient : * and AttendClient. Note that this *ignores* the troubles : * with request data interleaving itself with events, but : * we'll leave that until a later time. : */ : :typedef struct _SleepQueue { : struct _SleepQueue *next; : ClientPtr client; : ClientSleepProcPtr function; : pointer closure; :} SleepQueueRec, *SleepQueuePtr; : :static SleepQueuePtr sleepQueue = NULL; : :_X_EXPORT Bool :ClientSleep (ClientPtr client, ClientSleepProcPtr function, pointer closure) :{ : SleepQueuePtr q; : : q = (SleepQueuePtr) xalloc (sizeof *q); : if (!q) : return FALSE; : : IgnoreClient (client); : q->next = sleepQueue; : q->client = client; : q->function = function; : q->closure = closure; : sleepQueue = q; : return TRUE; :} : :Bool :ClientSignal (ClientPtr client) :{ : SleepQueuePtr q; : : for (q = sleepQueue; q; q = q->next) : if (q->client == client) : { : return QueueWorkProc (q->function, q->client, q->closure); : } : return FALSE; :} : :_X_EXPORT void :ClientWakeup (ClientPtr client) :{ : SleepQueuePtr q, *prev; : : prev = &sleepQueue; : while ( (q = *prev) ) : { : if (q->client == client) : { : *prev = q->next; : xfree (q); : if (client->clientGone) : /* Oops -- new zombie cleanup code ensures this only : * happens from inside CloseDownClient; don't want to : * recurse here... : */ : /* CloseDownClient(client) */; : else : AttendClient (client); : break; : } : prev = &q->next; : } :} : :Bool :ClientIsAsleep (ClientPtr client) :{ : SleepQueuePtr q; : : for (q = sleepQueue; q; q = q->next) : if (q->client == client) : return TRUE; : return FALSE; :} : :/* : * Generic Callback Manager : */ : :/* ===== Private Procedures ===== */ : :static int numCallbackListsToCleanup = 0; :static CallbackListPtr **listsToCleanup = NULL; : :static Bool :_AddCallback( : CallbackListPtr *pcbl, : CallbackProcPtr callback, : pointer data) :{ : CallbackPtr cbr; : : cbr = (CallbackPtr) xalloc(sizeof(CallbackRec)); : if (!cbr) : return FALSE; : cbr->proc = callback; : cbr->data = data; : cbr->next = (*pcbl)->list; : cbr->deleted = FALSE; : (*pcbl)->list = cbr; : return TRUE; :} : :static Bool :_DeleteCallback( : CallbackListPtr *pcbl, : CallbackProcPtr callback, : pointer data) :{ : CallbackListPtr cbl = *pcbl; : CallbackPtr cbr, pcbr; : : for (pcbr = NULL, cbr = cbl->list; : cbr != NULL; : pcbr = cbr, cbr = cbr->next) : { : if ((cbr->proc == callback) && (cbr->data == data)) : break; : } : if (cbr != NULL) : { : if (cbl->inCallback) : { : ++(cbl->numDeleted); : cbr->deleted = TRUE; : } : else : { : if (pcbr == NULL) : cbl->list = cbr->next; : else : pcbr->next = cbr->next; : xfree(cbr); : } : return TRUE; : } : return FALSE; :} : :static void :_CallCallbacks( : CallbackListPtr *pcbl, : pointer call_data) 17 0.0185 :{ /* _CallCallbacks total: 30 0.0327 */ : CallbackListPtr cbl = *pcbl; : CallbackPtr cbr, pcbr; : 3 0.0033 : ++(cbl->inCallback); 3 0.0033 : for (cbr = cbl->list; cbr != NULL; cbr = cbr->next) : { 6 0.0065 : (*(cbr->proc)) (pcbl, cbr->data, call_data); : } : --(cbl->inCallback); : : if (cbl->inCallback) return; : : /* Was the entire list marked for deletion? */ : 1 0.0011 : if (cbl->deleted) : { : DeleteCallbackList(pcbl); : return; : } : : /* Were some individual callbacks on the list marked for deletion? : * If so, do the deletions. : */ : : if (cbl->numDeleted) : { : for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; ) : { : if (cbr->deleted) : { : if (pcbr) : { : cbr = cbr->next; : xfree(pcbr->next); : pcbr->next = cbr; : } else : { : cbr = cbr->next; : xfree(cbl->list); : cbl->list = cbr; : } : cbl->numDeleted--; : } : else /* this one wasn't deleted */ : { : pcbr = cbr; : cbr = cbr->next; : } : } : } :} : :static void :_DeleteCallbackList( : CallbackListPtr *pcbl) :{ : CallbackListPtr cbl = *pcbl; : CallbackPtr cbr, nextcbr; : int i; : : if (cbl->inCallback) : { : cbl->deleted = TRUE; : return; : } : : for (i = 0; i < numCallbackListsToCleanup; i++) : { : if ((listsToCleanup[i] = pcbl) != 0) : { : listsToCleanup[i] = NULL; : break; : } : } : : for (cbr = cbl->list; cbr != NULL; cbr = nextcbr) : { : nextcbr = cbr->next; : xfree(cbr); : } : xfree(cbl); : *pcbl = NULL; :} : :static CallbackFuncsRec default_cbfuncs = :{ : _AddCallback, : _DeleteCallback, : _CallCallbacks, : _DeleteCallbackList :}; : :static Bool :CreateCallbackList(CallbackListPtr *pcbl, CallbackFuncsPtr cbfuncs) :{ : CallbackListPtr cbl; : int i; : : if (!pcbl) return FALSE; : cbl = (CallbackListPtr) xalloc(sizeof(CallbackListRec)); : if (!cbl) return FALSE; : cbl->funcs = cbfuncs ? *cbfuncs : default_cbfuncs; : cbl->inCallback = 0; : cbl->deleted = FALSE; : cbl->numDeleted = 0; : cbl->list = NULL; : *pcbl = cbl; : : for (i = 0; i < numCallbackListsToCleanup; i++) : { : if (!listsToCleanup[i]) : { : listsToCleanup[i] = pcbl; : return TRUE; : } : } : : listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup, : sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1)); : listsToCleanup[numCallbackListsToCleanup] = pcbl; : numCallbackListsToCleanup++; : return TRUE; :} : :/* ===== Public Procedures ===== */ : :_X_EXPORT Bool :AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data) :{ : if (!pcbl) return FALSE; : if (!*pcbl) : { /* list hasn't been created yet; go create it */ : if (!CreateCallbackList(pcbl, (CallbackFuncsPtr)NULL)) : return FALSE; : } : return ((*(*pcbl)->funcs.AddCallback) (pcbl, callback, data)); :} : :_X_EXPORT Bool :DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data) :{ : if (!pcbl || !*pcbl) return FALSE; : return ((*(*pcbl)->funcs.DeleteCallback) (pcbl, callback, data)); :} : :void :CallCallbacks(CallbackListPtr *pcbl, pointer call_data) 6 0.0065 :{ /* CallCallbacks total: 27 0.0294 */ 10 0.0109 : if (!pcbl || !*pcbl) return; 5 0.0054 : (*(*pcbl)->funcs.CallCallbacks) (pcbl, call_data); 6 0.0065 :} : :void :DeleteCallbackList(CallbackListPtr *pcbl) :{ : if (!pcbl || !*pcbl) return; : (*(*pcbl)->funcs.DeleteCallbackList) (pcbl); :} : :void :InitCallbackManager(void) :{ : int i; : : for (i = 0; i < numCallbackListsToCleanup; i++) : { : DeleteCallbackList(listsToCleanup[i]); : } : if (listsToCleanup) xfree(listsToCleanup); : : numCallbackListsToCleanup = 0; : listsToCleanup = NULL; :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/render/render.c" * * 81 0.0882 */ :/* : * : * Copyright © 2000 SuSE, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of SuSE not be used in advertising or : * publicity pertaining to distribution of the software without specific, : * written prior permission. SuSE makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : * : * Author: Keith Packard, SuSE, Inc. : */ : :#define NEED_REPLIES :#define NEED_EVENTS :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include :#include "misc.h" :#include "os.h" :#include "dixstruct.h" :#include "resource.h" :#include "scrnintstr.h" :#include "windowstr.h" :#include "pixmapstr.h" :#include "colormapst.h" :#include "extnsionst.h" :#include "servermd.h" :#include :#include :#include "picturestr.h" :#include "glyphstr.h" :#include :#include "cursorstr.h" : :#if HAVE_STDINT_H :#include :#elif !defined(UINT32_MAX) :#define UINT32_MAX 0xffffffffU :#endif : :static int ProcRenderQueryVersion (ClientPtr pClient); :static int ProcRenderQueryPictFormats (ClientPtr pClient); :static int ProcRenderQueryPictIndexValues (ClientPtr pClient); :static int ProcRenderQueryDithers (ClientPtr pClient); :static int ProcRenderCreatePicture (ClientPtr pClient); :static int ProcRenderChangePicture (ClientPtr pClient); :static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); :static int ProcRenderFreePicture (ClientPtr pClient); :static int ProcRenderComposite (ClientPtr pClient); :static int ProcRenderScale (ClientPtr pClient); :static int ProcRenderTrapezoids (ClientPtr pClient); :static int ProcRenderTriangles (ClientPtr pClient); :static int ProcRenderTriStrip (ClientPtr pClient); :static int ProcRenderTriFan (ClientPtr pClient); :static int ProcRenderColorTrapezoids (ClientPtr pClient); :static int ProcRenderColorTriangles (ClientPtr pClient); :static int ProcRenderTransform (ClientPtr pClient); :static int ProcRenderCreateGlyphSet (ClientPtr pClient); :static int ProcRenderReferenceGlyphSet (ClientPtr pClient); :static int ProcRenderFreeGlyphSet (ClientPtr pClient); :static int ProcRenderAddGlyphs (ClientPtr pClient); :static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); :static int ProcRenderFreeGlyphs (ClientPtr pClient); :static int ProcRenderCompositeGlyphs (ClientPtr pClient); :static int ProcRenderFillRectangles (ClientPtr pClient); :static int ProcRenderCreateCursor (ClientPtr pClient); :static int ProcRenderSetPictureTransform (ClientPtr pClient); :static int ProcRenderQueryFilters (ClientPtr pClient); :static int ProcRenderSetPictureFilter (ClientPtr pClient); :static int ProcRenderCreateAnimCursor (ClientPtr pClient); :static int ProcRenderAddTraps (ClientPtr pClient); :static int ProcRenderCreateSolidFill (ClientPtr pClient); :static int ProcRenderCreateLinearGradient (ClientPtr pClient); :static int ProcRenderCreateRadialGradient (ClientPtr pClient); :static int ProcRenderCreateConicalGradient (ClientPtr pClient); : :static int ProcRenderDispatch (ClientPtr pClient); : :static int SProcRenderQueryVersion (ClientPtr pClient); :static int SProcRenderQueryPictFormats (ClientPtr pClient); :static int SProcRenderQueryPictIndexValues (ClientPtr pClient); :static int SProcRenderQueryDithers (ClientPtr pClient); :static int SProcRenderCreatePicture (ClientPtr pClient); :static int SProcRenderChangePicture (ClientPtr pClient); :static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); :static int SProcRenderFreePicture (ClientPtr pClient); :static int SProcRenderComposite (ClientPtr pClient); :static int SProcRenderScale (ClientPtr pClient); :static int SProcRenderTrapezoids (ClientPtr pClient); :static int SProcRenderTriangles (ClientPtr pClient); :static int SProcRenderTriStrip (ClientPtr pClient); :static int SProcRenderTriFan (ClientPtr pClient); :static int SProcRenderColorTrapezoids (ClientPtr pClient); :static int SProcRenderColorTriangles (ClientPtr pClient); :static int SProcRenderTransform (ClientPtr pClient); :static int SProcRenderCreateGlyphSet (ClientPtr pClient); :static int SProcRenderReferenceGlyphSet (ClientPtr pClient); :static int SProcRenderFreeGlyphSet (ClientPtr pClient); :static int SProcRenderAddGlyphs (ClientPtr pClient); :static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); :static int SProcRenderFreeGlyphs (ClientPtr pClient); :static int SProcRenderCompositeGlyphs (ClientPtr pClient); :static int SProcRenderFillRectangles (ClientPtr pClient); :static int SProcRenderCreateCursor (ClientPtr pClient); :static int SProcRenderSetPictureTransform (ClientPtr pClient); :static int SProcRenderQueryFilters (ClientPtr pClient); :static int SProcRenderSetPictureFilter (ClientPtr pClient); :static int SProcRenderCreateAnimCursor (ClientPtr pClient); :static int SProcRenderAddTraps (ClientPtr pClient); :static int SProcRenderCreateSolidFill (ClientPtr pClient); :static int SProcRenderCreateLinearGradient (ClientPtr pClient); :static int SProcRenderCreateRadialGradient (ClientPtr pClient); :static int SProcRenderCreateConicalGradient (ClientPtr pClient); : :static int SProcRenderDispatch (ClientPtr pClient); : :int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { : ProcRenderQueryVersion, : ProcRenderQueryPictFormats, : ProcRenderQueryPictIndexValues, : ProcRenderQueryDithers, : ProcRenderCreatePicture, : ProcRenderChangePicture, : ProcRenderSetPictureClipRectangles, : ProcRenderFreePicture, : ProcRenderComposite, : ProcRenderScale, : ProcRenderTrapezoids, : ProcRenderTriangles, : ProcRenderTriStrip, : ProcRenderTriFan, : ProcRenderColorTrapezoids, : ProcRenderColorTriangles, : ProcRenderTransform, : ProcRenderCreateGlyphSet, : ProcRenderReferenceGlyphSet, : ProcRenderFreeGlyphSet, : ProcRenderAddGlyphs, : ProcRenderAddGlyphsFromPicture, : ProcRenderFreeGlyphs, : ProcRenderCompositeGlyphs, : ProcRenderCompositeGlyphs, : ProcRenderCompositeGlyphs, : ProcRenderFillRectangles, : ProcRenderCreateCursor, : ProcRenderSetPictureTransform, : ProcRenderQueryFilters, : ProcRenderSetPictureFilter, : ProcRenderCreateAnimCursor, : ProcRenderAddTraps, : ProcRenderCreateSolidFill, : ProcRenderCreateLinearGradient, : ProcRenderCreateRadialGradient, : ProcRenderCreateConicalGradient :}; : :int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { : SProcRenderQueryVersion, : SProcRenderQueryPictFormats, : SProcRenderQueryPictIndexValues, : SProcRenderQueryDithers, : SProcRenderCreatePicture, : SProcRenderChangePicture, : SProcRenderSetPictureClipRectangles, : SProcRenderFreePicture, : SProcRenderComposite, : SProcRenderScale, : SProcRenderTrapezoids, : SProcRenderTriangles, : SProcRenderTriStrip, : SProcRenderTriFan, : SProcRenderColorTrapezoids, : SProcRenderColorTriangles, : SProcRenderTransform, : SProcRenderCreateGlyphSet, : SProcRenderReferenceGlyphSet, : SProcRenderFreeGlyphSet, : SProcRenderAddGlyphs, : SProcRenderAddGlyphsFromPicture, : SProcRenderFreeGlyphs, : SProcRenderCompositeGlyphs, : SProcRenderCompositeGlyphs, : SProcRenderCompositeGlyphs, : SProcRenderFillRectangles, : SProcRenderCreateCursor, : SProcRenderSetPictureTransform, : SProcRenderQueryFilters, : SProcRenderSetPictureFilter, : SProcRenderCreateAnimCursor, : SProcRenderAddTraps, : SProcRenderCreateSolidFill, : SProcRenderCreateLinearGradient, : SProcRenderCreateRadialGradient, : SProcRenderCreateConicalGradient :}; : :static void :RenderResetProc (ExtensionEntry *extEntry); : :#if 0 :static CARD8 RenderReqCode; :#endif :int RenderErrBase; :int RenderClientPrivateIndex; : :typedef struct _RenderClient { : int major_version; : int minor_version; :} RenderClientRec, *RenderClientPtr; : :#define GetRenderClient(pClient) ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr) : :static void :RenderClientCallback (CallbackListPtr *list, : pointer closure, : pointer data) :{ : NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; : ClientPtr pClient = clientinfo->client; : RenderClientPtr pRenderClient = GetRenderClient (pClient); : : pRenderClient->major_version = 0; : pRenderClient->minor_version = 0; :} : :void :RenderExtensionInit (void) :{ : ExtensionEntry *extEntry; : : if (!PictureType) : return; : if (!PictureFinishInit ()) : return; : RenderClientPrivateIndex = AllocateClientPrivateIndex (); : if (!AllocateClientPrivate (RenderClientPrivateIndex, : sizeof (RenderClientRec))) : return; : if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) : return; : : extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, : ProcRenderDispatch, SProcRenderDispatch, : RenderResetProc, StandardMinorOpcode); : if (!extEntry) : return; :#if 0 : RenderReqCode = (CARD8) extEntry->base; :#endif : RenderErrBase = extEntry->errorBase; :} : :static void :RenderResetProc (ExtensionEntry *extEntry) :{ : ResetPicturePrivateIndex(); : ResetGlyphSetPrivateIndex(); :} : :static int :ProcRenderQueryVersion (ClientPtr client) :{ : RenderClientPtr pRenderClient = GetRenderClient (client); : xRenderQueryVersionReply rep; : register int n; : REQUEST(xRenderQueryVersionReq); : : pRenderClient->major_version = stuff->majorVersion; : pRenderClient->minor_version = stuff->minorVersion; : : REQUEST_SIZE_MATCH(xRenderQueryVersionReq); : rep.type = X_Reply; : rep.length = 0; : rep.sequenceNumber = client->sequence; : rep.majorVersion = RENDER_MAJOR; : rep.minorVersion = RENDER_MINOR; : if (client->swapped) { : swaps(&rep.sequenceNumber, n); : swapl(&rep.length, n); : swapl(&rep.majorVersion, n); : swapl(&rep.minorVersion, n); : } : WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); : return (client->noClientException); :} : :#if 0 :static int :VisualDepth (ScreenPtr pScreen, VisualPtr pVisual) :{ : DepthPtr pDepth; : int d, v; : : for (d = 0; d < pScreen->numDepths; d++) : { : pDepth = pScreen->allowedDepths + d; : for (v = 0; v < pDepth->numVids; v++) : { : if (pDepth->vids[v] == pVisual->vid) : return pDepth->depth; : } : } : return 0; :} :#endif : :static VisualPtr :findVisual (ScreenPtr pScreen, VisualID vid) :{ : VisualPtr pVisual; : int v; : : for (v = 0; v < pScreen->numVisuals; v++) : { : pVisual = pScreen->visuals + v; : if (pVisual->vid == vid) : return pVisual; : } : return 0; :} : :extern char *ConnectionInfo; : :static int :ProcRenderQueryPictFormats (ClientPtr client) :{ : RenderClientPtr pRenderClient = GetRenderClient (client); : xRenderQueryPictFormatsReply *reply; : xPictScreen *pictScreen; : xPictDepth *pictDepth; : xPictVisual *pictVisual; : xPictFormInfo *pictForm; : CARD32 *pictSubpixel; : ScreenPtr pScreen; : VisualPtr pVisual; : DepthPtr pDepth; : int v, d; : PictureScreenPtr ps; : PictFormatPtr pFormat; : int nformat; : int ndepth; : int nvisual; : int rlength; : int s; : int n; : int numScreens; : int numSubpixel; :/* REQUEST(xRenderQueryPictFormatsReq); */ : : REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); : :#ifdef PANORAMIX : if (noPanoramiXExtension) : numScreens = screenInfo.numScreens; : else : numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; :#else : numScreens = screenInfo.numScreens; :#endif : ndepth = nformat = nvisual = 0; : for (s = 0; s < numScreens; s++) : { : pScreen = screenInfo.screens[s]; : for (d = 0; d < pScreen->numDepths; d++) : { : pDepth = pScreen->allowedDepths + d; : ++ndepth; : : for (v = 0; v < pDepth->numVids; v++) : { : pVisual = findVisual (pScreen, pDepth->vids[v]); : if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) : ++nvisual; : } : } : ps = GetPictureScreenIfSet(pScreen); : if (ps) : nformat += ps->nformats; : } : if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) : numSubpixel = 0; : else : numSubpixel = numScreens; : : rlength = (sizeof (xRenderQueryPictFormatsReply) + : nformat * sizeof (xPictFormInfo) + : numScreens * sizeof (xPictScreen) + : ndepth * sizeof (xPictDepth) + : nvisual * sizeof (xPictVisual) + : numSubpixel * sizeof (CARD32)); : reply = (xRenderQueryPictFormatsReply *) xalloc (rlength); : if (!reply) : return BadAlloc; : reply->type = X_Reply; : reply->sequenceNumber = client->sequence; : reply->length = (rlength - sizeof(xGenericReply)) >> 2; : reply->numFormats = nformat; : reply->numScreens = numScreens; : reply->numDepths = ndepth; : reply->numVisuals = nvisual; : reply->numSubpixel = numSubpixel; : : pictForm = (xPictFormInfo *) (reply + 1); : : for (s = 0; s < numScreens; s++) : { : pScreen = screenInfo.screens[s]; : ps = GetPictureScreenIfSet(pScreen); : if (ps) : { : for (nformat = 0, pFormat = ps->formats; : nformat < ps->nformats; : nformat++, pFormat++) : { : pictForm->id = pFormat->id; : pictForm->type = pFormat->type; : pictForm->depth = pFormat->depth; : pictForm->direct.red = pFormat->direct.red; : pictForm->direct.redMask = pFormat->direct.redMask; : pictForm->direct.green = pFormat->direct.green; : pictForm->direct.greenMask = pFormat->direct.greenMask; : pictForm->direct.blue = pFormat->direct.blue; : pictForm->direct.blueMask = pFormat->direct.blueMask; : pictForm->direct.alpha = pFormat->direct.alpha; : pictForm->direct.alphaMask = pFormat->direct.alphaMask; : if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) : pictForm->colormap = pFormat->index.pColormap->mid; : else : pictForm->colormap = None; : if (client->swapped) : { : swapl (&pictForm->id, n); : swaps (&pictForm->direct.red, n); : swaps (&pictForm->direct.redMask, n); : swaps (&pictForm->direct.green, n); : swaps (&pictForm->direct.greenMask, n); : swaps (&pictForm->direct.blue, n); : swaps (&pictForm->direct.blueMask, n); : swaps (&pictForm->direct.alpha, n); : swaps (&pictForm->direct.alphaMask, n); : swapl (&pictForm->colormap, n); : } : pictForm++; : } : } : } : : pictScreen = (xPictScreen *) pictForm; : for (s = 0; s < numScreens; s++) : { : pScreen = screenInfo.screens[s]; : pictDepth = (xPictDepth *) (pictScreen + 1); : ndepth = 0; : for (d = 0; d < pScreen->numDepths; d++) : { : pictVisual = (xPictVisual *) (pictDepth + 1); : pDepth = pScreen->allowedDepths + d; : : nvisual = 0; : for (v = 0; v < pDepth->numVids; v++) : { : pVisual = findVisual (pScreen, pDepth->vids[v]); : if (pVisual && (pFormat = PictureMatchVisual (pScreen, : pDepth->depth, : pVisual))) : { : pictVisual->visual = pVisual->vid; : pictVisual->format = pFormat->id; : if (client->swapped) : { : swapl (&pictVisual->visual, n); : swapl (&pictVisual->format, n); : } : pictVisual++; : nvisual++; : } : } : pictDepth->depth = pDepth->depth; : pictDepth->nPictVisuals = nvisual; : if (client->swapped) : { : swaps (&pictDepth->nPictVisuals, n); : } : ndepth++; : pictDepth = (xPictDepth *) pictVisual; : } : pictScreen->nDepth = ndepth; : ps = GetPictureScreenIfSet(pScreen); : if (ps) : pictScreen->fallback = ps->fallback->id; : else : pictScreen->fallback = 0; : if (client->swapped) : { : swapl (&pictScreen->nDepth, n); : swapl (&pictScreen->fallback, n); : } : pictScreen = (xPictScreen *) pictDepth; : } : pictSubpixel = (CARD32 *) pictScreen; : : for (s = 0; s < numSubpixel; s++) : { : pScreen = screenInfo.screens[s]; : ps = GetPictureScreenIfSet(pScreen); : if (ps) : *pictSubpixel = ps->subpixel; : else : *pictSubpixel = SubPixelUnknown; : if (client->swapped) : { : swapl (pictSubpixel, n); : } : ++pictSubpixel; : } : : if (client->swapped) : { : swaps (&reply->sequenceNumber, n); : swapl (&reply->length, n); : swapl (&reply->numFormats, n); : swapl (&reply->numScreens, n); : swapl (&reply->numDepths, n); : swapl (&reply->numVisuals, n); : swapl (&reply->numSubpixel, n); : } : WriteToClient(client, rlength, (char *) reply); : xfree (reply); : return client->noClientException; :} : :static int :ProcRenderQueryPictIndexValues (ClientPtr client) :{ : PictFormatPtr pFormat; : int num; : int rlength; : int i, n; : REQUEST(xRenderQueryPictIndexValuesReq); : xRenderQueryPictIndexValuesReply *reply; : xIndexValue *values; : : REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); : : pFormat = (PictFormatPtr) SecurityLookupIDByType (client, : stuff->format, : PictFormatType, : DixReadAccess); : : if (!pFormat) : { : client->errorValue = stuff->format; : return RenderErrBase + BadPictFormat; : } : if (pFormat->type != PictTypeIndexed) : { : client->errorValue = stuff->format; : return BadMatch; : } : num = pFormat->index.nvalues; : rlength = (sizeof (xRenderQueryPictIndexValuesReply) + : num * sizeof(xIndexValue)); : reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength); : if (!reply) : return BadAlloc; : : reply->type = X_Reply; : reply->sequenceNumber = client->sequence; : reply->length = (rlength - sizeof(xGenericReply)) >> 2; : reply->numIndexValues = num; : : values = (xIndexValue *) (reply + 1); : : memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); : : if (client->swapped) : { : for (i = 0; i < num; i++) : { : swapl (&values[i].pixel, n); : swaps (&values[i].red, n); : swaps (&values[i].green, n); : swaps (&values[i].blue, n); : swaps (&values[i].alpha, n); : } : swaps (&reply->sequenceNumber, n); : swapl (&reply->length, n); : swapl (&reply->numIndexValues, n); : } : : WriteToClient(client, rlength, (char *) reply); : xfree(reply); : return (client->noClientException); :} : :static int :ProcRenderQueryDithers (ClientPtr client) :{ : return BadImplementation; :} : :static int :ProcRenderCreatePicture (ClientPtr client) 6 0.0065 :{ /* ProcRenderCreatePicture total: 14 0.0153 */ : PicturePtr pPicture; : DrawablePtr pDrawable; : PictFormatPtr pFormat; : int len, error, rc; : REQUEST(xRenderCreatePictureReq); : : REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); : 1 0.0011 : LEGAL_NEW_RESOURCE(stuff->pid, client); 2 0.0022 : rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, : DixWriteAccess); : if (rc != Success) : return rc; : 1 0.0011 : pFormat = (PictFormatPtr) SecurityLookupIDByType (client, : stuff->format, : PictFormatType, : DixReadAccess); : if (!pFormat) : { : client->errorValue = stuff->format; : return RenderErrBase + BadPictFormat; : } : if (pFormat->depth != pDrawable->depth) : return BadMatch; : len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2); : if (Ones(stuff->mask) != len) : return BadLength; : : pPicture = CreatePicture (stuff->pid, : pDrawable, : pFormat, : stuff->mask, : (XID *) (stuff + 1), : client, : &error); : if (!pPicture) : return error; 4 0.0044 : if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) : return BadAlloc; : return Success; :} : :static int :ProcRenderChangePicture (ClientPtr client) 6 0.0065 :{ /* ProcRenderChangePicture total: 7 0.0076 */ : PicturePtr pPicture; : REQUEST(xRenderChangePictureReq); : int len; : : REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); 1 0.0011 : VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : : len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2); : if (Ones(stuff->mask) != len) : return BadLength; : : return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), : (DevUnion *) 0, client); :} : :static int :ProcRenderSetPictureClipRectangles (ClientPtr client) 1 0.0011 :{ /* ProcRenderSetPictureClipRectangles total: 1 0.0011 */ : REQUEST(xRenderSetPictureClipRectanglesReq); : PicturePtr pPicture; : int nr; : int result; : : REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); : VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pPicture->pDrawable) : return BadDrawable; : : nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq); : if (nr & 4) : return BadLength; : nr >>= 3; : result = SetPictureClipRects (pPicture, : stuff->xOrigin, stuff->yOrigin, : nr, (xRectangle *) &stuff[1]); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); :} : :static int :ProcRenderFreePicture (ClientPtr client) 1 0.0011 :{ /* ProcRenderFreePicture total: 2 0.0022 */ : PicturePtr pPicture; : REQUEST(xRenderFreePictureReq); : 1 0.0011 : REQUEST_SIZE_MATCH(xRenderFreePictureReq); : : VERIFY_PICTURE (pPicture, stuff->picture, client, DixDestroyAccess, : RenderErrBase + BadPicture); : FreeResource (stuff->picture, RT_NONE); : return(client->noClientException); :} : :static Bool :PictOpValid (CARD8 op) :{ : if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) : return TRUE; : if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) : return TRUE; : if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) : return TRUE; : return FALSE; :} : :static int :ProcRenderComposite (ClientPtr client) 1 0.0011 :{ /* ProcRenderComposite total: 1 0.0011 */ : PicturePtr pSrc, pMask, pDst; : REQUEST(xRenderCompositeReq); : : REQUEST_SIZE_MATCH(xRenderCompositeReq); : if (!PictOpValid (stuff->op)) : { : client->errorValue = stuff->op; : return BadValue; : } : VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pDst->pDrawable) : return BadDrawable; : VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_ALPHA (pMask, stuff->mask, client, DixReadAccess, : RenderErrBase + BadPicture); : if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) || : (pMask && pMask->pDrawable && pDst->pDrawable->pScreen != pMask->pDrawable->pScreen)) : return BadMatch; : CompositePicture (stuff->op, : pSrc, : pMask, : pDst, : stuff->xSrc, : stuff->ySrc, : stuff->xMask, : stuff->yMask, : stuff->xDst, : stuff->yDst, : stuff->width, : stuff->height); : return Success; :} : :static int :ProcRenderScale (ClientPtr client) :{ : return BadImplementation; :} : :static int :ProcRenderTrapezoids (ClientPtr client) :{ : int ntraps; : PicturePtr pSrc, pDst; : PictFormatPtr pFormat; : REQUEST(xRenderTrapezoidsReq); : : REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); : if (!PictOpValid (stuff->op)) : { : client->errorValue = stuff->op; : return BadValue; : } : VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pDst->pDrawable) : return BadDrawable; : if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) : return BadMatch; : if (stuff->maskFormat) : { : pFormat = (PictFormatPtr) SecurityLookupIDByType (client, : stuff->maskFormat, : PictFormatType, : DixReadAccess); : if (!pFormat) : { : client->errorValue = stuff->maskFormat; : return RenderErrBase + BadPictFormat; : } : } : else : pFormat = 0; : ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); : if (ntraps % sizeof (xTrapezoid)) : return BadLength; : ntraps /= sizeof (xTrapezoid); : if (ntraps) : CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, : stuff->xSrc, stuff->ySrc, : ntraps, (xTrapezoid *) &stuff[1]); : return client->noClientException; :} : :static int :ProcRenderTriangles (ClientPtr client) :{ : int ntris; : PicturePtr pSrc, pDst; : PictFormatPtr pFormat; : REQUEST(xRenderTrianglesReq); : : REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); : if (!PictOpValid (stuff->op)) : { : client->errorValue = stuff->op; : return BadValue; : } : VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pDst->pDrawable) : return BadDrawable; : if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) : return BadMatch; : if (stuff->maskFormat) : { : pFormat = (PictFormatPtr) SecurityLookupIDByType (client, : stuff->maskFormat, : PictFormatType, : DixReadAccess); : if (!pFormat) : { : client->errorValue = stuff->maskFormat; : return RenderErrBase + BadPictFormat; : } : } : else : pFormat = 0; : ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); : if (ntris % sizeof (xTriangle)) : return BadLength; : ntris /= sizeof (xTriangle); : if (ntris) : CompositeTriangles (stuff->op, pSrc, pDst, pFormat, : stuff->xSrc, stuff->ySrc, : ntris, (xTriangle *) &stuff[1]); : return client->noClientException; :} : :static int :ProcRenderTriStrip (ClientPtr client) :{ : int npoints; : PicturePtr pSrc, pDst; : PictFormatPtr pFormat; : REQUEST(xRenderTrianglesReq); : : REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); : if (!PictOpValid (stuff->op)) : { : client->errorValue = stuff->op; : return BadValue; : } : VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pDst->pDrawable) : return BadDrawable; : if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) : return BadMatch; : if (stuff->maskFormat) : { : pFormat = (PictFormatPtr) SecurityLookupIDByType (client, : stuff->maskFormat, : PictFormatType, : DixReadAccess); : if (!pFormat) : { : client->errorValue = stuff->maskFormat; : return RenderErrBase + BadPictFormat; : } : } : else : pFormat = 0; : npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); : if (npoints & 4) : return(BadLength); : npoints >>= 3; : if (npoints >= 3) : CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, : stuff->xSrc, stuff->ySrc, : npoints, (xPointFixed *) &stuff[1]); : return client->noClientException; :} : :static int :ProcRenderTriFan (ClientPtr client) :{ : int npoints; : PicturePtr pSrc, pDst; : PictFormatPtr pFormat; : REQUEST(xRenderTrianglesReq); : : REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); : if (!PictOpValid (stuff->op)) : { : client->errorValue = stuff->op; : return BadValue; : } : VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pDst->pDrawable) : return BadDrawable; : if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) : return BadMatch; : if (stuff->maskFormat) : { : pFormat = (PictFormatPtr) SecurityLookupIDByType (client, : stuff->maskFormat, : PictFormatType, : DixReadAccess); : if (!pFormat) : { : client->errorValue = stuff->maskFormat; : return RenderErrBase + BadPictFormat; : } : } : else : pFormat = 0; : npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); : if (npoints & 4) : return(BadLength); : npoints >>= 3; : if (npoints >= 3) : CompositeTriFan (stuff->op, pSrc, pDst, pFormat, : stuff->xSrc, stuff->ySrc, : npoints, (xPointFixed *) &stuff[1]); : return client->noClientException; :} : :static int :ProcRenderColorTrapezoids (ClientPtr client) :{ : return BadImplementation; :} : :static int :ProcRenderColorTriangles (ClientPtr client) :{ : return BadImplementation; :} : :static int :ProcRenderTransform (ClientPtr client) :{ : return BadImplementation; :} : :static int :ProcRenderCreateGlyphSet (ClientPtr client) :{ : GlyphSetPtr glyphSet; : PictFormatPtr format; : int f; : REQUEST(xRenderCreateGlyphSetReq); : : REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); : : LEGAL_NEW_RESOURCE(stuff->gsid, client); : format = (PictFormatPtr) SecurityLookupIDByType (client, : stuff->format, : PictFormatType, : DixReadAccess); : if (!format) : { : client->errorValue = stuff->format; : return RenderErrBase + BadPictFormat; : } : switch (format->depth) { : case 1: : f = GlyphFormat1; : break; : case 4: : f = GlyphFormat4; : break; : case 8: : f = GlyphFormat8; : break; : case 16: : f = GlyphFormat16; : break; : case 32: : f = GlyphFormat32; : break; : default: : return BadMatch; : } : if (format->type != PictTypeDirect) : return BadMatch; : glyphSet = AllocateGlyphSet (f, format); : if (!glyphSet) : return BadAlloc; : if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) : return BadAlloc; : return Success; :} : :static int :ProcRenderReferenceGlyphSet (ClientPtr client) :{ : GlyphSetPtr glyphSet; : REQUEST(xRenderReferenceGlyphSetReq); : : REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); : : LEGAL_NEW_RESOURCE(stuff->gsid, client); : : glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, : stuff->existing, : GlyphSetType, : DixWriteAccess); : if (!glyphSet) : { : client->errorValue = stuff->existing; : return RenderErrBase + BadGlyphSet; : } : glyphSet->refcnt++; : if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) : return BadAlloc; : return client->noClientException; :} : :#define NLOCALDELTA 64 :#define NLOCALGLYPH 256 : :static int :ProcRenderFreeGlyphSet (ClientPtr client) :{ : GlyphSetPtr glyphSet; : REQUEST(xRenderFreeGlyphSetReq); : : REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); : glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, : stuff->glyphset, : GlyphSetType, : DixDestroyAccess); : if (!glyphSet) : { : client->errorValue = stuff->glyphset; : return RenderErrBase + BadGlyphSet; : } : FreeResource (stuff->glyphset, RT_NONE); : return client->noClientException; :} : :typedef struct _GlyphNew { : Glyph id; : GlyphPtr glyph; :} GlyphNewRec, *GlyphNewPtr; : :static int :ProcRenderAddGlyphs (ClientPtr client) :{ : GlyphSetPtr glyphSet; : REQUEST(xRenderAddGlyphsReq); : GlyphNewRec glyphsLocal[NLOCALGLYPH]; : GlyphNewPtr glyphsBase, glyphs; : GlyphPtr glyph; : int remain, nglyphs; : CARD32 *gids; : xGlyphInfo *gi; : CARD8 *bits; : int size; : int err = BadAlloc; : : REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); : glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, : stuff->glyphset, : GlyphSetType, : DixWriteAccess); : if (!glyphSet) : { : client->errorValue = stuff->glyphset; : return RenderErrBase + BadGlyphSet; : } : : nglyphs = stuff->nglyphs; : if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec)) : return BadAlloc; : : if (nglyphs <= NLOCALGLYPH) : glyphsBase = glyphsLocal; : else : { : glyphsBase = (GlyphNewPtr) Xalloc (nglyphs * sizeof (GlyphNewRec)); : if (!glyphsBase) : return BadAlloc; : } : : remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); : : glyphs = glyphsBase; : : gids = (CARD32 *) (stuff + 1); : gi = (xGlyphInfo *) (gids + nglyphs); : bits = (CARD8 *) (gi + nglyphs); : remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; : while (remain >= 0 && nglyphs) : { : glyph = AllocateGlyph (gi, glyphSet->fdepth); : if (!glyph) : { : err = BadAlloc; : goto bail; : } : : glyphs->glyph = glyph; : glyphs->id = *gids; : : size = glyph->size - sizeof (xGlyphInfo); : if (remain < size) : break; : memcpy ((CARD8 *) (glyph + 1), bits, size); : : if (size & 3) : size += 4 - (size & 3); : bits += size; : remain -= size; : gi++; : gids++; : glyphs++; : nglyphs--; : } : if (nglyphs || remain) : { : err = BadLength; : goto bail; : } : nglyphs = stuff->nglyphs; : if (!ResizeGlyphSet (glyphSet, nglyphs)) : { : err = BadAlloc; : goto bail; : } : glyphs = glyphsBase; : while (nglyphs--) { : AddGlyph (glyphSet, glyphs->glyph, glyphs->id); : glyphs++; : } : : if (glyphsBase != glyphsLocal) : Xfree (glyphsBase); : return client->noClientException; :bail: : while (glyphs != glyphsBase) : { : --glyphs; : xfree (glyphs->glyph); : } : if (glyphsBase != glyphsLocal) : Xfree (glyphsBase); : return err; :} : :static int :ProcRenderAddGlyphsFromPicture (ClientPtr client) :{ : return BadImplementation; :} : :static int :ProcRenderFreeGlyphs (ClientPtr client) :{ : REQUEST(xRenderFreeGlyphsReq); : GlyphSetPtr glyphSet; : int nglyph; : CARD32 *gids; : CARD32 glyph; : : REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); : glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, : stuff->glyphset, : GlyphSetType, : DixWriteAccess); : if (!glyphSet) : { : client->errorValue = stuff->glyphset; : return RenderErrBase + BadGlyphSet; : } : nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2; : gids = (CARD32 *) (stuff + 1); : while (nglyph-- > 0) : { : glyph = *gids++; : if (!DeleteGlyph (glyphSet, glyph)) : { : client->errorValue = glyph; : return RenderErrBase + BadGlyph; : } : } : return client->noClientException; :} : :static int :ProcRenderCompositeGlyphs (ClientPtr client) 4 0.0044 :{ /* ProcRenderCompositeGlyphs total: 30 0.0327 */ : GlyphSetPtr glyphSet; : GlyphSet gs; : PicturePtr pSrc, pDst; : PictFormatPtr pFormat; : GlyphListRec listsLocal[NLOCALDELTA]; : GlyphListPtr lists, listsBase; : GlyphPtr glyphsLocal[NLOCALGLYPH]; : Glyph glyph; : GlyphPtr *glyphs, *glyphsBase; : xGlyphElt *elt; : CARD8 *buffer, *end; : int nglyph; : int nlist; : int space; : int size; : int n; : : REQUEST(xRenderCompositeGlyphsReq); : : REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); : : switch (stuff->renderReqType) { : default: size = 1; break; : case X_RenderCompositeGlyphs16: size = 2; break; : case X_RenderCompositeGlyphs32: size = 4; break; : } : : if (!PictOpValid (stuff->op)) : { : client->errorValue = stuff->op; : return BadValue; : } : VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pDst->pDrawable) : return BadDrawable; : if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) : return BadMatch; : if (stuff->maskFormat) : { 1 0.0011 : pFormat = (PictFormatPtr) SecurityLookupIDByType (client, : stuff->maskFormat, : PictFormatType, : DixReadAccess); : if (!pFormat) : { : client->errorValue = stuff->maskFormat; : return RenderErrBase + BadPictFormat; : } : } : else : pFormat = 0; : 1 0.0011 : glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, : stuff->glyphset, : GlyphSetType, : DixReadAccess); : if (!glyphSet) : { : client->errorValue = stuff->glyphset; : return RenderErrBase + BadGlyphSet; : } : : buffer = (CARD8 *) (stuff + 1); 2 0.0022 : end = (CARD8 *) stuff + (client->req_len << 2); : nglyph = 0; : nlist = 0; : while (buffer + sizeof (xGlyphElt) < end) : { : elt = (xGlyphElt *) buffer; : buffer += sizeof (xGlyphElt); : : if (elt->len == 0xff) : { : buffer += 4; : } : else : { 1 0.0011 : nlist++; : nglyph += elt->len; : space = size * elt->len; : if (space & 3) : space += 4 - (space & 3); : buffer += space; : } : } : if (nglyph <= NLOCALGLYPH) : glyphsBase = glyphsLocal; : else : { : glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr)); : if (!glyphsBase) : return BadAlloc; : } : if (nlist <= NLOCALDELTA) : listsBase = listsLocal; : else : { : listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec)); : if (!listsBase) : return BadAlloc; : } : buffer = (CARD8 *) (stuff + 1); : glyphs = glyphsBase; : lists = listsBase; 1 0.0011 : while (buffer + sizeof (xGlyphElt) < end) : { : elt = (xGlyphElt *) buffer; : buffer += sizeof (xGlyphElt); : : if (elt->len == 0xff) : { : if (buffer + sizeof (GlyphSet) < end) : { : memcpy(&gs, buffer, sizeof(GlyphSet)); : glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, : gs, : GlyphSetType, : DixReadAccess); : if (!glyphSet) : { : client->errorValue = gs; : if (glyphsBase != glyphsLocal) : DEALLOCATE_LOCAL (glyphsBase); : if (listsBase != listsLocal) : DEALLOCATE_LOCAL (listsBase); : return RenderErrBase + BadGlyphSet; : } : } : buffer += 4; : } : else : { : lists->xOff = elt->deltax; : lists->yOff = elt->deltay; 1 0.0011 : lists->format = glyphSet->format; : lists->len = 0; : n = elt->len; 3 0.0033 : while (n--) : { : if (buffer + size <= end) : { : switch (size) { : case 1: 7 0.0076 : glyph = *((CARD8 *)buffer); break; : case 2: : glyph = *((CARD16 *)buffer); break; : case 4: : default: : glyph = *((CARD32 *)buffer); break; : } 5 0.0054 : if ((*glyphs = FindGlyph (glyphSet, glyph))) : { 2 0.0022 : lists->len++; : glyphs++; : } : } : buffer += size; : } : space = size * elt->len; : if (space & 3) 1 0.0011 : buffer += 4 - (space & 3); : lists++; : } : } : if (buffer > end) : return BadLength; : 1 0.0011 : CompositeGlyphs (stuff->op, : pSrc, : pDst, : pFormat, : stuff->xSrc, : stuff->ySrc, : nlist, : listsBase, : glyphsBase); : : if (glyphsBase != glyphsLocal) : DEALLOCATE_LOCAL (glyphsBase); : if (listsBase != listsLocal) : DEALLOCATE_LOCAL (listsBase); : : return client->noClientException; :} : :static int :ProcRenderFillRectangles (ClientPtr client) 4 0.0044 :{ /* ProcRenderFillRectangles total: 10 0.0109 */ : PicturePtr pDst; : int things; : REQUEST(xRenderFillRectanglesReq); : : REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); 1 0.0011 : if (!PictOpValid (stuff->op)) : { : client->errorValue = stuff->op; : return BadValue; : } : VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pDst->pDrawable) : return BadDrawable; : : things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); : if (things & 4) : return(BadLength); : things >>= 3; : 2 0.0022 : CompositeRects (stuff->op, : pDst, : &stuff->color, : things, : (xRectangle *) &stuff[1]); : 1 0.0011 : return client->noClientException; 2 0.0022 :} : :static void :SetBit (unsigned char *line, int x, int bit) :{ : unsigned char mask; : : if (screenInfo.bitmapBitOrder == LSBFirst) : mask = (1 << (x & 7)); : else : mask = (0x80 >> (x & 7)); : /* XXX assumes byte order is host byte order */ : line += (x >> 3); : if (bit) : *line |= mask; : else : *line &= ~mask; :} : :#define DITHER_DIM 2 : :static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { : { 1, 3, }, : { 4, 2, }, :}; : :#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) : :static int :ProcRenderCreateCursor (ClientPtr client) :{ : REQUEST(xRenderCreateCursorReq); : PicturePtr pSrc; : ScreenPtr pScreen; : unsigned short width, height; : CARD32 *argbbits, *argb; : unsigned char *srcbits, *srcline; : unsigned char *mskbits, *mskline; : int stride; : int x, y; : int nbytes_mono; : CursorMetricRec cm; : CursorPtr pCursor; : CARD32 twocolor[3]; : int ncolor; : : REQUEST_SIZE_MATCH (xRenderCreateCursorReq); : LEGAL_NEW_RESOURCE(stuff->cid, client); : : VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : if (!pSrc->pDrawable) : return BadDrawable; : pScreen = pSrc->pDrawable->pScreen; : width = pSrc->pDrawable->width; : height = pSrc->pDrawable->height; : if ( stuff->x > width : || stuff->y > height ) : return (BadMatch); : argbbits = xalloc (width * height * sizeof (CARD32)); : if (!argbbits) : return (BadAlloc); : : stride = BitmapBytePad(width); : nbytes_mono = stride*height; : srcbits = (unsigned char *)xalloc(nbytes_mono); : if (!srcbits) : { : xfree (argbbits); : return (BadAlloc); : } : mskbits = (unsigned char *)xalloc(nbytes_mono); : if (!mskbits) : { : xfree(argbbits); : xfree(srcbits); : return (BadAlloc); : } : bzero ((char *) mskbits, nbytes_mono); : bzero ((char *) srcbits, nbytes_mono); : : if (pSrc->format == PICT_a8r8g8b8) : { : (*pScreen->GetImage) (pSrc->pDrawable, : 0, 0, width, height, ZPixmap, : 0xffffffff, (pointer) argbbits); : } : else : { : PixmapPtr pPixmap; : PicturePtr pPicture; : PictFormatPtr pFormat; : int error; : : pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); : if (!pFormat) : { : xfree (argbbits); : xfree (srcbits); : xfree (mskbits); : return (BadImplementation); : } : pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32); : if (!pPixmap) : { : xfree (argbbits); : xfree (srcbits); : xfree (mskbits); : return (BadAlloc); : } : pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, : client, &error); : if (!pPicture) : { : xfree (argbbits); : xfree (srcbits); : xfree (mskbits); : return error; : } : (*pScreen->DestroyPixmap) (pPixmap); : CompositePicture (PictOpSrc, : pSrc, 0, pPicture, : 0, 0, 0, 0, 0, 0, width, height); : (*pScreen->GetImage) (pPicture->pDrawable, : 0, 0, width, height, ZPixmap, : 0xffffffff, (pointer) argbbits); : FreePicture (pPicture, 0); : } : /* : * Check whether the cursor can be directly supported by : * the core cursor code : */ : ncolor = 0; : argb = argbbits; : for (y = 0; ncolor <= 2 && y < height; y++) : { : for (x = 0; ncolor <= 2 && x < width; x++) : { : CARD32 p = *argb++; : CARD32 a = (p >> 24); : : if (a == 0) /* transparent */ : continue; : if (a == 0xff) /* opaque */ : { : int n; : for (n = 0; n < ncolor; n++) : if (p == twocolor[n]) : break; : if (n == ncolor) : twocolor[ncolor++] = p; : } : else : ncolor = 3; : } : } : : /* : * Convert argb image to two plane cursor : */ : srcline = srcbits; : mskline = mskbits; : argb = argbbits; : for (y = 0; y < height; y++) : { : for (x = 0; x < width; x++) : { : CARD32 p = *argb++; : : if (ncolor <= 2) : { : CARD32 a = ((p >> 24)); : : SetBit (mskline, x, a != 0); : SetBit (srcline, x, a != 0 && p == twocolor[0]); : } : else : { : CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; : CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; : CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; : /* Set mask from dithered alpha value */ : SetBit(mskline, x, a > d); : /* Set src from dithered intensity value */ : SetBit(srcline, x, a > d && i <= d); : } : } : srcline += stride; : mskline += stride; : } : /* : * Dither to white and black if the cursor has more than two colors : */ : if (ncolor > 2) : { : twocolor[0] = 0xff000000; : twocolor[1] = 0xffffffff; : } : else : { : xfree (argbbits); : argbbits = 0; : } : :#define GetByte(p,s) (((p) >> (s)) & 0xff) :#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) : : cm.width = width; : cm.height = height; : cm.xhot = stuff->x; : cm.yhot = stuff->y; : pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm, : GetColor(twocolor[0], 16), : GetColor(twocolor[0], 8), : GetColor(twocolor[0], 0), : GetColor(twocolor[1], 16), : GetColor(twocolor[1], 8), : GetColor(twocolor[1], 0)); : if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) : return (client->noClientException); : return BadAlloc; :} : :static int :ProcRenderSetPictureTransform (ClientPtr client) :{ /* ProcRenderSetPictureTransform total: 2 0.0022 */ : REQUEST(xRenderSetPictureTransformReq); : PicturePtr pPicture; : int result; : 1 0.0011 : REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); : VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); 1 0.0011 :} : :static int :ProcRenderQueryFilters (ClientPtr client) :{ : REQUEST (xRenderQueryFiltersReq); : DrawablePtr pDrawable; : xRenderQueryFiltersReply *reply; : int nbytesName; : int nnames; : ScreenPtr pScreen; : PictureScreenPtr ps; : int i, j, len, total_bytes, rc; : INT16 *aliases; : char *names; : : REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); : rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, : DixReadAccess); : if (rc != Success) : return rc; : : pScreen = pDrawable->pScreen; : nbytesName = 0; : nnames = 0; : ps = GetPictureScreenIfSet(pScreen); : if (ps) : { : for (i = 0; i < ps->nfilters; i++) : nbytesName += 1 + strlen (ps->filters[i].name); : for (i = 0; i < ps->nfilterAliases; i++) : nbytesName += 1 + strlen (ps->filterAliases[i].alias); : nnames = ps->nfilters + ps->nfilterAliases; : } : len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2); : total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); : reply = (xRenderQueryFiltersReply *) xalloc (total_bytes); : if (!reply) : return BadAlloc; : aliases = (INT16 *) (reply + 1); : names = (char *) (aliases + ((nnames + 1) & ~1)); : : reply->type = X_Reply; : reply->sequenceNumber = client->sequence; : reply->length = len; : reply->numAliases = nnames; : reply->numFilters = nnames; : if (ps) : { : : /* fill in alias values */ : for (i = 0; i < ps->nfilters; i++) : aliases[i] = FilterAliasNone; : for (i = 0; i < ps->nfilterAliases; i++) : { : for (j = 0; j < ps->nfilters; j++) : if (ps->filterAliases[i].filter_id == ps->filters[j].id) : break; : if (j == ps->nfilters) : { : for (j = 0; j < ps->nfilterAliases; j++) : if (ps->filterAliases[i].filter_id == : ps->filterAliases[j].alias_id) : { : break; : } : if (j == ps->nfilterAliases) : j = FilterAliasNone; : else : j = j + ps->nfilters; : } : aliases[i + ps->nfilters] = j; : } : : /* fill in filter names */ : for (i = 0; i < ps->nfilters; i++) : { : j = strlen (ps->filters[i].name); : *names++ = j; : strncpy (names, ps->filters[i].name, j); : names += j; : } : : /* fill in filter alias names */ : for (i = 0; i < ps->nfilterAliases; i++) : { : j = strlen (ps->filterAliases[i].alias); : *names++ = j; : strncpy (names, ps->filterAliases[i].alias, j); : names += j; : } : } : : if (client->swapped) : { : register int n; : : for (i = 0; i < reply->numAliases; i++) : { : swaps (&aliases[i], n); : } : swaps(&reply->sequenceNumber, n); : swapl(&reply->length, n); : swapl(&reply->numAliases, n); : swapl(&reply->numFilters, n); : } : WriteToClient(client, total_bytes, (char *) reply); : xfree (reply); : : return(client->noClientException); :} : :static int :ProcRenderSetPictureFilter (ClientPtr client) :{ /* ProcRenderSetPictureFilter total: 4 0.0044 */ : REQUEST (xRenderSetPictureFilterReq); : PicturePtr pPicture; : int result; : xFixed *params; : int nparams; : char *name; : 1 0.0011 : REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); 2 0.0022 : VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : name = (char *) (stuff + 1); : params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3)); : nparams = ((xFixed *) stuff + client->req_len) - params; 1 0.0011 : result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); : return result; :} : :static int :ProcRenderCreateAnimCursor (ClientPtr client) :{ : REQUEST(xRenderCreateAnimCursorReq); : CursorPtr *cursors; : CARD32 *deltas; : CursorPtr pCursor; : int ncursor; : xAnimCursorElt *elt; : int i; : int ret; : : REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); : LEGAL_NEW_RESOURCE(stuff->cid, client); : if (client->req_len & 1) : return BadLength; : ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1; : cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); : if (!cursors) : return BadAlloc; : deltas = (CARD32 *) (cursors + ncursor); : elt = (xAnimCursorElt *) (stuff + 1); : for (i = 0; i < ncursor; i++) : { : cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor, : RT_CURSOR, DixReadAccess); : if (!cursors[i]) : { : xfree (cursors); : client->errorValue = elt->cursor; : return BadCursor; : } : deltas[i] = elt->delay; : elt++; : } : ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor); : xfree (cursors); : if (ret != Success) : return ret; : : if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) : return client->noClientException; : return BadAlloc; :} : :static int :ProcRenderAddTraps (ClientPtr client) :{ : int ntraps; : PicturePtr pPicture; : REQUEST(xRenderAddTrapsReq); : : REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq); : VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : if (!pPicture->pDrawable) : return BadDrawable; : ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); : if (ntraps % sizeof (xTrap)) : return BadLength; : ntraps /= sizeof (xTrap); : if (ntraps) : AddTraps (pPicture, : stuff->xOff, stuff->yOff, : ntraps, (xTrap *) &stuff[1]); : return client->noClientException; :} : :static int ProcRenderCreateSolidFill(ClientPtr client) :{ : PicturePtr pPicture; : int error = 0; : REQUEST(xRenderCreateSolidFillReq); : : REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); : : LEGAL_NEW_RESOURCE(stuff->pid, client); : : pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error); : if (!pPicture) : return error; : if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) : return BadAlloc; : return Success; :} : :static int ProcRenderCreateLinearGradient (ClientPtr client) :{ : PicturePtr pPicture; : int len; : int error = 0; : xFixed *stops; : xRenderColor *colors; : REQUEST(xRenderCreateLinearGradientReq); : : REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); : : LEGAL_NEW_RESOURCE(stuff->pid, client); : : len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); : if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) : return BadLength; : : stops = (xFixed *)(stuff + 1); : colors = (xRenderColor *)(stops + stuff->nStops); : : pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2, : stuff->nStops, stops, colors, &error); : if (!pPicture) : return error; : if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) : return BadAlloc; : return Success; :} : :static int ProcRenderCreateRadialGradient (ClientPtr client) :{ : PicturePtr pPicture; : int len; : int error = 0; : xFixed *stops; : xRenderColor *colors; : REQUEST(xRenderCreateRadialGradientReq); : : REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); : : LEGAL_NEW_RESOURCE(stuff->pid, client); : : len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); : if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) : return BadLength; : : stops = (xFixed *)(stuff + 1); : colors = (xRenderColor *)(stops + stuff->nStops); : : pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer, : stuff->inner_radius, stuff->outer_radius, : stuff->nStops, stops, colors, &error); : if (!pPicture) : return error; : if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) : return BadAlloc; : return Success; :} : :static int ProcRenderCreateConicalGradient (ClientPtr client) :{ : PicturePtr pPicture; : int len; : int error = 0; : xFixed *stops; : xRenderColor *colors; : REQUEST(xRenderCreateConicalGradientReq); : : REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); : : LEGAL_NEW_RESOURCE(stuff->pid, client); : : len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); : if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) : return BadLength; : : stops = (xFixed *)(stuff + 1); : colors = (xRenderColor *)(stops + stuff->nStops); : : pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle, : stuff->nStops, stops, colors, &error); : if (!pPicture) : return error; : if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) : return BadAlloc; : return Success; :} : : :static int :ProcRenderDispatch (ClientPtr client) 8 0.0087 :{ /* ProcRenderDispatch total: 10 0.0109 */ : REQUEST(xReq); : 1 0.0011 : if (stuff->data < RenderNumberRequests) : return (*ProcRenderVector[stuff->data]) (client); : else : return BadRequest; 1 0.0011 :} : :static int :SProcRenderQueryVersion (ClientPtr client) :{ : register int n; : REQUEST(xRenderQueryVersionReq); : : swaps(&stuff->length, n); : swapl(&stuff->majorVersion, n); : swapl(&stuff->minorVersion, n); : return (*ProcRenderVector[stuff->renderReqType])(client); :} : :static int :SProcRenderQueryPictFormats (ClientPtr client) :{ : register int n; : REQUEST(xRenderQueryPictFormatsReq); : swaps(&stuff->length, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderQueryPictIndexValues (ClientPtr client) :{ : register int n; : REQUEST(xRenderQueryPictIndexValuesReq); : swaps(&stuff->length, n); : swapl(&stuff->format, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderQueryDithers (ClientPtr client) :{ : return BadImplementation; :} : :static int :SProcRenderCreatePicture (ClientPtr client) :{ : register int n; : REQUEST(xRenderCreatePictureReq); : swaps(&stuff->length, n); : swapl(&stuff->pid, n); : swapl(&stuff->drawable, n); : swapl(&stuff->format, n); : swapl(&stuff->mask, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderChangePicture (ClientPtr client) :{ : register int n; : REQUEST(xRenderChangePictureReq); : swaps(&stuff->length, n); : swapl(&stuff->picture, n); : swapl(&stuff->mask, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderSetPictureClipRectangles (ClientPtr client) :{ : register int n; : REQUEST(xRenderSetPictureClipRectanglesReq); : swaps(&stuff->length, n); : swapl(&stuff->picture, n); : swaps(&stuff->xOrigin, n); : swaps(&stuff->yOrigin, n); : SwapRestS(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderFreePicture (ClientPtr client) :{ : register int n; : REQUEST(xRenderFreePictureReq); : swaps(&stuff->length, n); : swapl(&stuff->picture, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderComposite (ClientPtr client) :{ : register int n; : REQUEST(xRenderCompositeReq); : swaps(&stuff->length, n); : swapl(&stuff->src, n); : swapl(&stuff->mask, n); : swapl(&stuff->dst, n); : swaps(&stuff->xSrc, n); : swaps(&stuff->ySrc, n); : swaps(&stuff->xMask, n); : swaps(&stuff->yMask, n); : swaps(&stuff->xDst, n); : swaps(&stuff->yDst, n); : swaps(&stuff->width, n); : swaps(&stuff->height, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderScale (ClientPtr client) :{ : register int n; : REQUEST(xRenderScaleReq); : swaps(&stuff->length, n); : swapl(&stuff->src, n); : swapl(&stuff->dst, n); : swapl(&stuff->colorScale, n); : swapl(&stuff->alphaScale, n); : swaps(&stuff->xSrc, n); : swaps(&stuff->ySrc, n); : swaps(&stuff->xDst, n); : swaps(&stuff->yDst, n); : swaps(&stuff->width, n); : swaps(&stuff->height, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderTrapezoids (ClientPtr client) :{ : register int n; : REQUEST(xRenderTrapezoidsReq); : : REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); : swaps (&stuff->length, n); : swapl (&stuff->src, n); : swapl (&stuff->dst, n); : swapl (&stuff->maskFormat, n); : swaps (&stuff->xSrc, n); : swaps (&stuff->ySrc, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderTriangles (ClientPtr client) :{ : register int n; : REQUEST(xRenderTrianglesReq); : : REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); : swaps (&stuff->length, n); : swapl (&stuff->src, n); : swapl (&stuff->dst, n); : swapl (&stuff->maskFormat, n); : swaps (&stuff->xSrc, n); : swaps (&stuff->ySrc, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderTriStrip (ClientPtr client) :{ : register int n; : REQUEST(xRenderTriStripReq); : : REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); : swaps (&stuff->length, n); : swapl (&stuff->src, n); : swapl (&stuff->dst, n); : swapl (&stuff->maskFormat, n); : swaps (&stuff->xSrc, n); : swaps (&stuff->ySrc, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderTriFan (ClientPtr client) :{ : register int n; : REQUEST(xRenderTriFanReq); : : REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); : swaps (&stuff->length, n); : swapl (&stuff->src, n); : swapl (&stuff->dst, n); : swapl (&stuff->maskFormat, n); : swaps (&stuff->xSrc, n); : swaps (&stuff->ySrc, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderColorTrapezoids (ClientPtr client) :{ : return BadImplementation; :} : :static int :SProcRenderColorTriangles (ClientPtr client) :{ : return BadImplementation; :} : :static int :SProcRenderTransform (ClientPtr client) :{ : return BadImplementation; :} : :static int :SProcRenderCreateGlyphSet (ClientPtr client) :{ : register int n; : REQUEST(xRenderCreateGlyphSetReq); : swaps(&stuff->length, n); : swapl(&stuff->gsid, n); : swapl(&stuff->format, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderReferenceGlyphSet (ClientPtr client) :{ : register int n; : REQUEST(xRenderReferenceGlyphSetReq); : swaps(&stuff->length, n); : swapl(&stuff->gsid, n); : swapl(&stuff->existing, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderFreeGlyphSet (ClientPtr client) :{ : register int n; : REQUEST(xRenderFreeGlyphSetReq); : swaps(&stuff->length, n); : swapl(&stuff->glyphset, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderAddGlyphs (ClientPtr client) :{ : register int n; : register int i; : CARD32 *gids; : void *end; : xGlyphInfo *gi; : REQUEST(xRenderAddGlyphsReq); : swaps(&stuff->length, n); : swapl(&stuff->glyphset, n); : swapl(&stuff->nglyphs, n); : if (stuff->nglyphs & 0xe0000000) : return BadLength; : end = (CARD8 *) stuff + (client->req_len << 2); : gids = (CARD32 *) (stuff + 1); : gi = (xGlyphInfo *) (gids + stuff->nglyphs); : if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) : return BadLength; : if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) : return BadLength; : for (i = 0; i < stuff->nglyphs; i++) : { : swapl (&gids[i], n); : swaps (&gi[i].width, n); : swaps (&gi[i].height, n); : swaps (&gi[i].x, n); : swaps (&gi[i].y, n); : swaps (&gi[i].xOff, n); : swaps (&gi[i].yOff, n); : } : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderAddGlyphsFromPicture (ClientPtr client) :{ : return BadImplementation; :} : :static int :SProcRenderFreeGlyphs (ClientPtr client) :{ : register int n; : REQUEST(xRenderFreeGlyphsReq); : swaps(&stuff->length, n); : swapl(&stuff->glyphset, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderCompositeGlyphs (ClientPtr client) :{ : register int n; : xGlyphElt *elt; : CARD8 *buffer; : CARD8 *end; : int space; : int i; : int size; : : REQUEST(xRenderCompositeGlyphsReq); : : switch (stuff->renderReqType) { : default: size = 1; break; : case X_RenderCompositeGlyphs16: size = 2; break; : case X_RenderCompositeGlyphs32: size = 4; break; : } : : swaps(&stuff->length, n); : swapl(&stuff->src, n); : swapl(&stuff->dst, n); : swapl(&stuff->maskFormat, n); : swapl(&stuff->glyphset, n); : swaps(&stuff->xSrc, n); : swaps(&stuff->ySrc, n); : buffer = (CARD8 *) (stuff + 1); : end = (CARD8 *) stuff + (client->req_len << 2); : while (buffer + sizeof (xGlyphElt) < end) : { : elt = (xGlyphElt *) buffer; : buffer += sizeof (xGlyphElt); : : swaps (&elt->deltax, n); : swaps (&elt->deltay, n); : : i = elt->len; : if (i == 0xff) : { : swapl (buffer, n); : buffer += 4; : } : else : { : space = size * i; : switch (size) { : case 1: : buffer += i; : break; : case 2: : while (i--) : { : swaps (buffer, n); : buffer += 2; : } : break; : case 4: : while (i--) : { : swapl (buffer, n); : buffer += 4; : } : break; : } : if (space & 3) : buffer += 4 - (space & 3); : } : } : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderFillRectangles (ClientPtr client) :{ : register int n; : REQUEST(xRenderFillRectanglesReq); : : REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); : swaps(&stuff->length, n); : swapl(&stuff->dst, n); : swaps(&stuff->color.red, n); : swaps(&stuff->color.green, n); : swaps(&stuff->color.blue, n); : swaps(&stuff->color.alpha, n); : SwapRestS(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderCreateCursor (ClientPtr client) :{ : register int n; : REQUEST(xRenderCreateCursorReq); : REQUEST_SIZE_MATCH (xRenderCreateCursorReq); : : swaps(&stuff->length, n); : swapl(&stuff->cid, n); : swapl(&stuff->src, n); : swaps(&stuff->x, n); : swaps(&stuff->y, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderSetPictureTransform (ClientPtr client) :{ : register int n; : REQUEST(xRenderSetPictureTransformReq); : REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); : : swaps(&stuff->length, n); : swapl(&stuff->picture, n); : swapl(&stuff->transform.matrix11, n); : swapl(&stuff->transform.matrix12, n); : swapl(&stuff->transform.matrix13, n); : swapl(&stuff->transform.matrix21, n); : swapl(&stuff->transform.matrix22, n); : swapl(&stuff->transform.matrix23, n); : swapl(&stuff->transform.matrix31, n); : swapl(&stuff->transform.matrix32, n); : swapl(&stuff->transform.matrix33, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderQueryFilters (ClientPtr client) :{ : register int n; : REQUEST (xRenderQueryFiltersReq); : REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); : : swaps(&stuff->length, n); : swapl(&stuff->drawable, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderSetPictureFilter (ClientPtr client) :{ : register int n; : REQUEST (xRenderSetPictureFilterReq); : REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); : : swaps(&stuff->length, n); : swapl(&stuff->picture, n); : swaps(&stuff->nbytes, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderCreateAnimCursor (ClientPtr client) :{ : register int n; : REQUEST (xRenderCreateAnimCursorReq); : REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); : : swaps(&stuff->length, n); : swapl(&stuff->cid, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderAddTraps (ClientPtr client) :{ : register int n; : REQUEST (xRenderAddTrapsReq); : REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); : : swaps(&stuff->length, n); : swapl(&stuff->picture, n); : swaps(&stuff->xOff, n); : swaps(&stuff->yOff, n); : SwapRestL(stuff); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderCreateSolidFill(ClientPtr client) :{ : register int n; : REQUEST (xRenderCreateSolidFillReq); : REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq); : : swaps(&stuff->length, n); : swapl(&stuff->pid, n); : swaps(&stuff->color.alpha, n); : swaps(&stuff->color.red, n); : swaps(&stuff->color.green, n); : swaps(&stuff->color.blue, n); : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static void swapStops(void *stuff, int n) :{ : int i; : CARD32 *stops; : CARD16 *colors; : stops = (CARD32 *)(stuff); : for (i = 0; i < n; ++i) { : swapl(stops, n); : ++stops; : } : colors = (CARD16 *)(stops); : for (i = 0; i < 4*n; ++i) { : swaps(stops, n); : ++stops; : } :} : :static int :SProcRenderCreateLinearGradient (ClientPtr client) :{ : register int n; : int len; : REQUEST (xRenderCreateLinearGradientReq); : REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq); : : swaps(&stuff->length, n); : swapl(&stuff->pid, n); : swapl(&stuff->p1.x, n); : swapl(&stuff->p1.y, n); : swapl(&stuff->p2.x, n); : swapl(&stuff->p2.y, n); : swapl(&stuff->nStops, n); : : len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); : if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) : return BadLength; : : swapStops(stuff+1, stuff->nStops); : : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderCreateRadialGradient (ClientPtr client) :{ : register int n; : int len; : REQUEST (xRenderCreateRadialGradientReq); : REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq); : : swaps(&stuff->length, n); : swapl(&stuff->pid, n); : swapl(&stuff->inner.x, n); : swapl(&stuff->inner.y, n); : swapl(&stuff->outer.x, n); : swapl(&stuff->outer.y, n); : swapl(&stuff->inner_radius, n); : swapl(&stuff->outer_radius, n); : swapl(&stuff->nStops, n); : : len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); : if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) : return BadLength; : : swapStops(stuff+1, stuff->nStops); : : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderCreateConicalGradient (ClientPtr client) :{ : register int n; : int len; : REQUEST (xRenderCreateConicalGradientReq); : REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq); : : swaps(&stuff->length, n); : swapl(&stuff->pid, n); : swapl(&stuff->center.x, n); : swapl(&stuff->center.y, n); : swapl(&stuff->angle, n); : swapl(&stuff->nStops, n); : : len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); : if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) : return BadLength; : : swapStops(stuff+1, stuff->nStops); : : return (*ProcRenderVector[stuff->renderReqType]) (client); :} : :static int :SProcRenderDispatch (ClientPtr client) :{ : REQUEST(xReq); : : if (stuff->data < RenderNumberRequests) : return (*SProcRenderVector[stuff->data]) (client); : else : return BadRequest; :} : :#ifdef PANORAMIX :#include "panoramiX.h" :#include "panoramiXsrv.h" : :#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\ : pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\ : if (!pPicture) { \ : client->errorValue = pid; \ : return err; \ : } \ :} : :#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\ : if (pid == None) \ : pPicture = 0; \ : else { \ : VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \ : } \ :} \ : :int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); : :unsigned long XRT_PICTURE; : :static int :PanoramiXRenderCreatePicture (ClientPtr client) :{ : REQUEST(xRenderCreatePictureReq); : PanoramiXRes *refDraw, *newPict; : int result = Success, j; : : REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); : if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( : client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess))) : return BadDrawable; : if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) : return BadAlloc; : newPict->type = XRT_PICTURE; : newPict->info[0].id = stuff->pid; : : if (refDraw->type == XRT_WINDOW && : stuff->drawable == WindowTable[0]->drawable.id) : { : newPict->u.pict.root = TRUE; : } : else : newPict->u.pict.root = FALSE; : : for(j = 1; j < PanoramiXNumScreens; j++) : newPict->info[j].id = FakeClientID(client->index); : : FOR_NSCREENS_BACKWARD(j) { : stuff->pid = newPict->info[j].id; : stuff->drawable = refDraw->info[j].id; : result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); : if(result != Success) break; : } : : if (result == Success) : AddResource(newPict->info[0].id, XRT_PICTURE, newPict); : else : xfree(newPict); : : return (result); :} : :static int :PanoramiXRenderChangePicture (ClientPtr client) :{ : PanoramiXRes *pict; : int result = Success, j; : REQUEST(xRenderChangePictureReq); : : REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); : : VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : : FOR_NSCREENS_BACKWARD(j) { : stuff->picture = pict->info[j].id; : result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); : if(result != Success) break; : } : : return (result); :} : :static int :PanoramiXRenderSetPictureClipRectangles (ClientPtr client) :{ : REQUEST(xRenderSetPictureClipRectanglesReq); : int result = Success, j; : PanoramiXRes *pict; : : REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); : : VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : : FOR_NSCREENS_BACKWARD(j) { : stuff->picture = pict->info[j].id; : result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); : if(result != Success) break; : } : : return (result); :} : :static int :PanoramiXRenderSetPictureTransform (ClientPtr client) :{ : REQUEST(xRenderSetPictureTransformReq); : int result = Success, j; : PanoramiXRes *pict; : : REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq); : : VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : : FOR_NSCREENS_BACKWARD(j) { : stuff->picture = pict->info[j].id; : result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client); : if(result != Success) break; : } : : return (result); :} : :static int :PanoramiXRenderSetPictureFilter (ClientPtr client) :{ : REQUEST(xRenderSetPictureFilterReq); : int result = Success, j; : PanoramiXRes *pict; : : REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); : : VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : : FOR_NSCREENS_BACKWARD(j) { : stuff->picture = pict->info[j].id; : result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client); : if(result != Success) break; : } : : return (result); :} : :static int :PanoramiXRenderFreePicture (ClientPtr client) :{ : PanoramiXRes *pict; : int result = Success, j; : REQUEST(xRenderFreePictureReq); : : REQUEST_SIZE_MATCH(xRenderFreePictureReq); : : client->errorValue = stuff->picture; : : VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess, : RenderErrBase + BadPicture); : : : FOR_NSCREENS_BACKWARD(j) { : stuff->picture = pict->info[j].id; : result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); : if(result != Success) break; : } : : /* Since ProcRenderFreePicture is using FreeResource, it will free : our resource for us on the last pass through the loop above */ : : return (result); :} : :static int :PanoramiXRenderComposite (ClientPtr client) :{ : PanoramiXRes *src, *msk, *dst; : int result = Success, j; : xRenderCompositeReq orig; : REQUEST(xRenderCompositeReq); : : REQUEST_SIZE_MATCH(xRenderCompositeReq); : : VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_XIN_ALPHA (msk, stuff->mask, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : : orig = *stuff; : : FOR_NSCREENS_FORWARD(j) { : stuff->src = src->info[j].id; : if (src->u.pict.root) : { : stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; : stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; : } : stuff->dst = dst->info[j].id; : if (dst->u.pict.root) : { : stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; : stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; : } : if (msk) : { : stuff->mask = msk->info[j].id; : if (msk->u.pict.root) : { : stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; : stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; : } : } : result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); : if(result != Success) break; : } : : return result; :} : :static int :PanoramiXRenderCompositeGlyphs (ClientPtr client) :{ : PanoramiXRes *src, *dst; : int result = Success, j; : REQUEST(xRenderCompositeGlyphsReq); : xGlyphElt origElt, *elt; : INT16 xSrc, ySrc; : : REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); : VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : : if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + : sizeof (xGlyphElt))) : { : elt = (xGlyphElt *) (stuff + 1); : origElt = *elt; : xSrc = stuff->xSrc; : ySrc = stuff->ySrc; : FOR_NSCREENS_FORWARD(j) { : stuff->src = src->info[j].id; : if (src->u.pict.root) : { : stuff->xSrc = xSrc - panoramiXdataPtr[j].x; : stuff->ySrc = ySrc - panoramiXdataPtr[j].y; : } : stuff->dst = dst->info[j].id; : if (dst->u.pict.root) : { : elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; : elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; : } : result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); : if(result != Success) break; : } : } : : return result; :} : :static int :PanoramiXRenderFillRectangles (ClientPtr client) :{ : PanoramiXRes *dst; : int result = Success, j; : REQUEST(xRenderFillRectanglesReq); : char *extra; : int extra_len; : : REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); : if (extra_len && : (extra = (char *) ALLOCATE_LOCAL (extra_len))) : { : memcpy (extra, stuff + 1, extra_len); : FOR_NSCREENS_FORWARD(j) { : if (j) memcpy (stuff + 1, extra, extra_len); : if (dst->u.pict.root) : { : int x_off = panoramiXdataPtr[j].x; : int y_off = panoramiXdataPtr[j].y; : : if(x_off || y_off) { : xRectangle *rects = (xRectangle *) (stuff + 1); : int i = extra_len / sizeof (xRectangle); : : while (i--) : { : rects->x -= x_off; : rects->y -= y_off; : rects++; : } : } : } : stuff->dst = dst->info[j].id; : result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); : if(result != Success) break; : } : DEALLOCATE_LOCAL(extra); : } : : return result; :} : :static int :PanoramiXRenderTrapezoids(ClientPtr client) :{ : PanoramiXRes *src, *dst; : int result = Success, j; : REQUEST(xRenderTrapezoidsReq); : char *extra; : int extra_len; : : REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq); : : VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : : extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); : : if (extra_len && : (extra = (char *) ALLOCATE_LOCAL (extra_len))) { : memcpy (extra, stuff + 1, extra_len); : : FOR_NSCREENS_FORWARD(j) { : if (j) memcpy (stuff + 1, extra, extra_len); : if (dst->u.pict.root) { : int x_off = panoramiXdataPtr[j].x; : int y_off = panoramiXdataPtr[j].y; : : if(x_off || y_off) { : xTrapezoid *trap = (xTrapezoid *) (stuff + 1); : int i = extra_len / sizeof (xTrapezoid); : : while (i--) { : trap->top -= y_off; : trap->bottom -= y_off; : trap->left.p1.x -= x_off; : trap->left.p1.y -= y_off; : trap->left.p2.x -= x_off; : trap->left.p2.y -= y_off; : trap->right.p1.x -= x_off; : trap->right.p1.y -= y_off; : trap->right.p2.x -= x_off; : trap->right.p2.y -= y_off; : trap++; : } : } : } : : stuff->src = src->info[j].id; : stuff->dst = dst->info[j].id; : result = : (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client); : : if(result != Success) break; : } : : DEALLOCATE_LOCAL(extra); : } : : return result; :} : :static int :PanoramiXRenderTriangles(ClientPtr client) :{ : PanoramiXRes *src, *dst; : int result = Success, j; : REQUEST(xRenderTrianglesReq); : char *extra; : int extra_len; : : REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq); : : VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : : extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq); : : if (extra_len && : (extra = (char *) ALLOCATE_LOCAL (extra_len))) { : memcpy (extra, stuff + 1, extra_len); : : FOR_NSCREENS_FORWARD(j) { : if (j) memcpy (stuff + 1, extra, extra_len); : if (dst->u.pict.root) { : int x_off = panoramiXdataPtr[j].x; : int y_off = panoramiXdataPtr[j].y; : : if(x_off || y_off) { : xTriangle *tri = (xTriangle *) (stuff + 1); : int i = extra_len / sizeof (xTriangle); : : while (i--) { : tri->p1.x -= x_off; : tri->p1.y -= y_off; : tri->p2.x -= x_off; : tri->p2.y -= y_off; : tri->p3.x -= x_off; : tri->p3.y -= y_off; : tri++; : } : } : } : : stuff->src = src->info[j].id; : stuff->dst = dst->info[j].id; : result = : (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client); : : if(result != Success) break; : } : : DEALLOCATE_LOCAL(extra); : } : : return result; :} : :static int :PanoramiXRenderTriStrip(ClientPtr client) :{ : PanoramiXRes *src, *dst; : int result = Success, j; : REQUEST(xRenderTriStripReq); : char *extra; : int extra_len; : : REQUEST_AT_LEAST_SIZE (xRenderTriStripReq); : : VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : : extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq); : : if (extra_len && : (extra = (char *) ALLOCATE_LOCAL (extra_len))) { : memcpy (extra, stuff + 1, extra_len); : : FOR_NSCREENS_FORWARD(j) { : if (j) memcpy (stuff + 1, extra, extra_len); : if (dst->u.pict.root) { : int x_off = panoramiXdataPtr[j].x; : int y_off = panoramiXdataPtr[j].y; : : if(x_off || y_off) { : xPointFixed *fixed = (xPointFixed *) (stuff + 1); : int i = extra_len / sizeof (xPointFixed); : : while (i--) { : fixed->x -= x_off; : fixed->y -= y_off; : fixed++; : } : } : } : : stuff->src = src->info[j].id; : stuff->dst = dst->info[j].id; : result = : (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client); : : if(result != Success) break; : } : : DEALLOCATE_LOCAL(extra); : } : : return result; :} : :static int :PanoramiXRenderTriFan(ClientPtr client) :{ : PanoramiXRes *src, *dst; : int result = Success, j; : REQUEST(xRenderTriFanReq); : char *extra; : int extra_len; : : REQUEST_AT_LEAST_SIZE (xRenderTriFanReq); : : VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess, : RenderErrBase + BadPicture); : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : : extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq); : : if (extra_len && : (extra = (char *) ALLOCATE_LOCAL (extra_len))) { : memcpy (extra, stuff + 1, extra_len); : : FOR_NSCREENS_FORWARD(j) { : if (j) memcpy (stuff + 1, extra, extra_len); : if (dst->u.pict.root) { : int x_off = panoramiXdataPtr[j].x; : int y_off = panoramiXdataPtr[j].y; : : if(x_off || y_off) { : xPointFixed *fixed = (xPointFixed *) (stuff + 1); : int i = extra_len / sizeof (xPointFixed); : : while (i--) { : fixed->x -= x_off; : fixed->y -= y_off; : fixed++; : } : } : } : : stuff->src = src->info[j].id; : stuff->dst = dst->info[j].id; : result = : (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client); : : if(result != Success) break; : } : : DEALLOCATE_LOCAL(extra); : } : : return result; :} : :#if 0 /* Not implemented yet */ : :static int :PanoramiXRenderColorTrapezoids(ClientPtr client) :{ : PanoramiXRes *src, *dst; : int result = Success, j; : REQUEST(xRenderColorTrapezoidsReq); : char *extra; : int extra_len; : : REQUEST_AT_LEAST_SIZE (xRenderColorTrapezoidsReq); : : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : : extra_len = (client->req_len << 2) - sizeof (xRenderColorTrapezoidsReq); : : if (extra_len && : (extra = (char *) ALLOCATE_LOCAL (extra_len))) { : memcpy (extra, stuff + 1, extra_len); : : FOR_NSCREENS_FORWARD(j) { : if (j) memcpy (stuff + 1, extra, extra_len); : if (dst->u.pict.root) { : int x_off = panoramiXdataPtr[j].x; : int y_off = panoramiXdataPtr[j].y; : : if(x_off || y_off) { : ....; : } : } : : stuff->dst = dst->info[j].id; : result = : (*PanoramiXSaveRenderVector[X_RenderColorTrapezoids]) (client); : : if(result != Success) break; : } : : DEALLOCATE_LOCAL(extra); : } : : return result; :} : :static int :PanoramiXRenderColorTriangles(ClientPtr client) :{ : PanoramiXRes *src, *dst; : int result = Success, j; : REQUEST(xRenderColorTrianglesReq); : char *extra; : int extra_len; : : REQUEST_AT_LEAST_SIZE (xRenderColorTrianglesReq); : : VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess, : RenderErrBase + BadPicture); : : extra_len = (client->req_len << 2) - sizeof (xRenderColorTrianglesReq); : : if (extra_len && : (extra = (char *) ALLOCATE_LOCAL (extra_len))) { : memcpy (extra, stuff + 1, extra_len); : : FOR_NSCREENS_FORWARD(j) { : if (j) memcpy (stuff + 1, extra, extra_len); : if (dst->u.pict.root) { : int x_off = panoramiXdataPtr[j].x; : int y_off = panoramiXdataPtr[j].y; : : if(x_off || y_off) { : ....; : } : } : : stuff->dst = dst->info[j].id; : result = : (*PanoramiXSaveRenderVector[X_RenderColorTriangles]) (client); : : if(result != Success) break; : } : : DEALLOCATE_LOCAL(extra); : } : : return result; :} : :#endif : :static int :PanoramiXRenderAddTraps (ClientPtr client) :{ : PanoramiXRes *picture; : int result = Success, j; : REQUEST(xRenderAddTrapsReq); : char *extra; : int extra_len; : INT16 x_off, y_off; : : REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); : VERIFY_XIN_PICTURE (picture, stuff->picture, client, DixWriteAccess, : RenderErrBase + BadPicture); : extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); : if (extra_len && : (extra = (char *) ALLOCATE_LOCAL (extra_len))) : { : memcpy (extra, stuff + 1, extra_len); : x_off = stuff->xOff; : y_off = stuff->yOff; : FOR_NSCREENS_FORWARD(j) { : if (j) memcpy (stuff + 1, extra, extra_len); : stuff->picture = picture->info[j].id; : : if (picture->u.pict.root) : { : stuff->xOff = x_off + panoramiXdataPtr[j].x; : stuff->yOff = y_off + panoramiXdataPtr[j].y; : } : result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client); : if(result != Success) break; : } : DEALLOCATE_LOCAL(extra); : } : : return result; :} : :void :PanoramiXRenderInit (void) :{ : int i; : : XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource); : for (i = 0; i < RenderNumberRequests; i++) : PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; : /* : * Stuff in Xinerama aware request processing hooks : */ : ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; : ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; : ProcRenderVector[X_RenderSetPictureTransform] = PanoramiXRenderSetPictureTransform; : ProcRenderVector[X_RenderSetPictureFilter] = PanoramiXRenderSetPictureFilter; : ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; : ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; : ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; : ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; : ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; : ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; : ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; : : ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids; : ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles; : ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip; : ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan; : ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps; :} : :void :PanoramiXRenderReset (void) :{ : int i; : for (i = 0; i < RenderNumberRequests; i++) : ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; :} : :#endif /* PANORAMIX */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/render/picture.c" * * 74 0.0806 */ :/* : * : * Copyright © 2000 SuSE, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of SuSE not be used in advertising or : * publicity pertaining to distribution of the software without specific, : * written prior permission. SuSE makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : * : * Author: Keith Packard, SuSE, Inc. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "misc.h" :#include "scrnintstr.h" :#include "os.h" :#include "regionstr.h" :#include "validate.h" :#include "windowstr.h" :#include "input.h" :#include "resource.h" :#include "colormapst.h" :#include "cursorstr.h" :#include "dixstruct.h" :#include "gcstruct.h" :#include "servermd.h" :#include "picturestr.h" : :_X_EXPORT int PictureScreenPrivateIndex = -1; :int PictureWindowPrivateIndex; :static int PictureGeneration; :RESTYPE PictureType; :RESTYPE PictFormatType; :RESTYPE GlyphSetType; :int PictureCmapPolicy = PictureCmapPolicyDefault; : :/* Picture Private machinery */ : :static int picturePrivateCount; : :void :ResetPicturePrivateIndex (void) :{ : picturePrivateCount = 0; :} : :int :AllocatePicturePrivateIndex (void) :{ : return picturePrivateCount++; :} : :Bool :AllocatePicturePrivate (ScreenPtr pScreen, int index2, unsigned int amount) :{ : PictureScreenPtr ps = GetPictureScreen(pScreen); : unsigned int oldamount; : : /* Round up sizes for proper alignment */ : amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); : : if (index2 >= ps->PicturePrivateLen) : { : unsigned int *nsizes; : : nsizes = (unsigned int *)xrealloc(ps->PicturePrivateSizes, : (index2 + 1) * sizeof(unsigned int)); : if (!nsizes) : return FALSE; : while (ps->PicturePrivateLen <= index2) : { : nsizes[ps->PicturePrivateLen++] = 0; : ps->totalPictureSize += sizeof(DevUnion); : } : ps->PicturePrivateSizes = nsizes; : } : oldamount = ps->PicturePrivateSizes[index2]; : if (amount > oldamount) : { : ps->PicturePrivateSizes[index2] = amount; : ps->totalPictureSize += (amount - oldamount); : } : : return TRUE; :} : : :Bool :PictureDestroyWindow (WindowPtr pWindow) :{ : ScreenPtr pScreen = pWindow->drawable.pScreen; : PicturePtr pPicture; : PictureScreenPtr ps = GetPictureScreen(pScreen); : Bool ret; : : while ((pPicture = GetPictureWindow(pWindow))) : { : SetPictureWindow(pWindow, pPicture->pNext); : if (pPicture->id) : FreeResource (pPicture->id, PictureType); : FreePicture ((pointer) pPicture, pPicture->id); : } : pScreen->DestroyWindow = ps->DestroyWindow; : ret = (*pScreen->DestroyWindow) (pWindow); : ps->DestroyWindow = pScreen->DestroyWindow; : pScreen->DestroyWindow = PictureDestroyWindow; : return ret; :} : :Bool :PictureCloseScreen (int index, ScreenPtr pScreen) :{ : PictureScreenPtr ps = GetPictureScreen(pScreen); : Bool ret; : int n; : : pScreen->CloseScreen = ps->CloseScreen; : ret = (*pScreen->CloseScreen) (index, pScreen); : PictureResetFilters (pScreen); : for (n = 0; n < ps->nformats; n++) : if (ps->formats[n].type == PictTypeIndexed) : (*ps->CloseIndexed) (pScreen, &ps->formats[n]); : GlyphUninit (pScreen); : SetPictureScreen(pScreen, 0); : if (ps->PicturePrivateSizes) : xfree (ps->PicturePrivateSizes); : xfree (ps->formats); : xfree (ps); : return ret; :} : :void :PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) :{ : ScreenPtr pScreen = pColormap->pScreen; : PictureScreenPtr ps = GetPictureScreen(pScreen); : : pScreen->StoreColors = ps->StoreColors; : (*pScreen->StoreColors) (pColormap, ndef, pdef); : ps->StoreColors = pScreen->StoreColors; : pScreen->StoreColors = PictureStoreColors; : : if (pColormap->class == PseudoColor || pColormap->class == GrayScale) : { : PictFormatPtr format = ps->formats; : int nformats = ps->nformats; : : while (nformats--) : { : if (format->type == PictTypeIndexed && : format->index.pColormap == pColormap) : { : (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); : break; : } : format++; : } : } :} : :static int :visualDepth (ScreenPtr pScreen, VisualPtr pVisual) :{ : int d, v; : DepthPtr pDepth; : : for (d = 0; d < pScreen->numDepths; d++) : { : pDepth = &pScreen->allowedDepths[d]; : for (v = 0; v < pDepth->numVids; v++) : if (pDepth->vids[v] == pVisual->vid) : return pDepth->depth; : } : return 0; :} : :typedef struct _formatInit { : CARD32 format; : CARD8 depth; :} FormatInitRec, *FormatInitPtr; : :static int :addFormat (FormatInitRec formats[256], : int nformat, : CARD32 format, : CARD8 depth) :{ : int n; : : for (n = 0; n < nformat; n++) : if (formats[n].format == format && formats[n].depth == depth) : return nformat; : formats[nformat].format = format; : formats[nformat].depth = depth; : return ++nformat; :} : :#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) : :PictFormatPtr :PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) :{ : int nformats, f; : PictFormatPtr pFormats; : FormatInitRec formats[1024]; : CARD32 format; : CARD8 depth; : VisualPtr pVisual; : int v; : int bpp; : int type; : int r, g, b; : int d; : DepthPtr pDepth; : : nformats = 0; : /* formats required by protocol */ : formats[nformats].format = PICT_a1; : formats[nformats].depth = 1; : nformats++; : formats[nformats].format = PICT_FORMAT(BitsPerPixel(8), : PICT_TYPE_A, : 8, 0, 0, 0); : formats[nformats].depth = 8; : nformats++; : formats[nformats].format = PICT_FORMAT(BitsPerPixel(4), : PICT_TYPE_A, : 4, 0, 0, 0); : formats[nformats].depth = 4; : nformats++; : formats[nformats].format = PICT_a8r8g8b8; : formats[nformats].depth = 32; : nformats++; : formats[nformats].format = PICT_x8r8g8b8; : formats[nformats].depth = 32; : nformats++; : : /* now look through the depths and visuals adding other formats */ : for (v = 0; v < pScreen->numVisuals; v++) : { : pVisual = &pScreen->visuals[v]; : depth = visualDepth (pScreen, pVisual); : if (!depth) : continue; : bpp = BitsPerPixel (depth); : switch (pVisual->class) { : case DirectColor: : case TrueColor: : r = Ones (pVisual->redMask); : g = Ones (pVisual->greenMask); : b = Ones (pVisual->blueMask); : type = PICT_TYPE_OTHER; : /* : * Current rendering code supports only two direct formats, : * fields must be packed together at the bottom of the pixel : * and must be either RGB or BGR : */ : if (pVisual->offsetBlue == 0 && : pVisual->offsetGreen == b && : pVisual->offsetRed == b + g) : { : type = PICT_TYPE_ARGB; : } : else if (pVisual->offsetRed == 0 && : pVisual->offsetGreen == r && : pVisual->offsetBlue == r + g) : { : type = PICT_TYPE_ABGR; : } : if (type != PICT_TYPE_OTHER) : { : format = PICT_FORMAT(bpp, type, 0, r, g, b); : nformats = addFormat (formats, nformats, format, depth); : } : break; : case StaticColor: : case PseudoColor: : format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); : nformats = addFormat (formats, nformats, format, depth); : break; : case StaticGray: : case GrayScale: : format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); : nformats = addFormat (formats, nformats, format, depth); : break; : } : } : /* : * Walk supported depths and add useful Direct formats : */ : for (d = 0; d < pScreen->numDepths; d++) : { : pDepth = &pScreen->allowedDepths[d]; : bpp = BitsPerPixel (pDepth->depth); : format = 0; : switch (bpp) { : case 16: : /* depth 12 formats */ : if (pDepth->depth >= 12) : { : nformats = addFormat (formats, nformats, : PICT_x4r4g4b4, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_x4b4g4r4, pDepth->depth); : } : /* depth 15 formats */ : if (pDepth->depth >= 15) : { : nformats = addFormat (formats, nformats, : PICT_x1r5g5b5, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_x1b5g5r5, pDepth->depth); : } : /* depth 16 formats */ : if (pDepth->depth >= 16) : { : nformats = addFormat (formats, nformats, : PICT_a1r5g5b5, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_a1b5g5r5, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_r5g6b5, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_b5g6r5, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_a4r4g4b4, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_a4b4g4r4, pDepth->depth); : } : break; : case 24: : if (pDepth->depth >= 24) : { : nformats = addFormat (formats, nformats, : PICT_r8g8b8, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_b8g8r8, pDepth->depth); : } : break; : case 32: : if (pDepth->depth >= 24) : { : nformats = addFormat (formats, nformats, : PICT_x8r8g8b8, pDepth->depth); : nformats = addFormat (formats, nformats, : PICT_x8b8g8r8, pDepth->depth); : } : break; : } : } : : : pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); : if (!pFormats) : return 0; : memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); : for (f = 0; f < nformats; f++) : { : pFormats[f].id = FakeClientID (0); : pFormats[f].depth = formats[f].depth; : format = formats[f].format; : pFormats[f].format = format; : switch (PICT_FORMAT_TYPE(format)) { : case PICT_TYPE_ARGB: : pFormats[f].type = PictTypeDirect; : : pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); : if (pFormats[f].direct.alphaMask) : pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + : PICT_FORMAT_G(format) + : PICT_FORMAT_B(format)); : : pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); : pFormats[f].direct.red = (PICT_FORMAT_G(format) + : PICT_FORMAT_B(format)); : : pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); : pFormats[f].direct.green = PICT_FORMAT_B(format); : : pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); : pFormats[f].direct.blue = 0; : break; : : case PICT_TYPE_ABGR: : pFormats[f].type = PictTypeDirect; : : pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); : if (pFormats[f].direct.alphaMask) : pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + : PICT_FORMAT_G(format) + : PICT_FORMAT_R(format)); : : pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); : pFormats[f].direct.blue = (PICT_FORMAT_G(format) + : PICT_FORMAT_R(format)); : : pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); : pFormats[f].direct.green = PICT_FORMAT_R(format); : : pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); : pFormats[f].direct.red = 0; : break; : : case PICT_TYPE_A: : pFormats[f].type = PictTypeDirect; : : pFormats[f].direct.alpha = 0; : pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); : : /* remaining fields already set to zero */ : break; : : case PICT_TYPE_COLOR: : case PICT_TYPE_GRAY: : pFormats[f].type = PictTypeIndexed; : pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid; : break; : } : } : *nformatp = nformats; : return pFormats; :} : :static VisualPtr :PictureFindVisual (ScreenPtr pScreen, VisualID visual) :{ : int i; : VisualPtr pVisual; : for (i = 0, pVisual = pScreen->visuals; : i < pScreen->numVisuals; : i++, pVisual++) : { : if (pVisual->vid == visual) : return pVisual; : } : return 0; :} : :Bool :PictureInitIndexedFormats (ScreenPtr pScreen) :{ : PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); : PictFormatPtr format; : int nformat; : : if (!ps) : return FALSE; : format = ps->formats; : nformat = ps->nformats; : while (nformat--) : { : if (format->type == PictTypeIndexed && !format->index.pColormap) : { : if (format->index.vid == pScreen->rootVisual) : format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap, : RT_COLORMAP); : else : { : VisualPtr pVisual; : : pVisual = PictureFindVisual (pScreen, format->index.vid); : if (CreateColormap (FakeClientID (0), pScreen, : pVisual, : &format->index.pColormap, AllocNone, : 0) != Success) : { : return FALSE; : } : } : if (!(*ps->InitIndexed) (pScreen, format)) : return FALSE; : } : format++; : } : return TRUE; :} : :Bool :PictureFinishInit (void) :{ : int s; : : for (s = 0; s < screenInfo.numScreens; s++) : { : if (!GlyphFinishInit (screenInfo.screens[s])) : return FALSE; : if (!PictureInitIndexedFormats (screenInfo.screens[s])) : return FALSE; : (void) AnimCurInit (screenInfo.screens[s]); : } : : return TRUE; :} : :_X_EXPORT Bool :PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) :{ : PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); : : if (!ps) : return FALSE; : ps->subpixel = subpixel; : return TRUE; : :} : :_X_EXPORT int :PictureGetSubpixelOrder (ScreenPtr pScreen) :{ : PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); : : if (!ps) : return SubPixelUnknown; : return ps->subpixel; :} : :PictFormatPtr :PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) :{ : PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); : PictFormatPtr format; : int nformat; : int type; : : if (!ps) : return 0; : format = ps->formats; : nformat = ps->nformats; : switch (pVisual->class) { : case StaticGray: : case GrayScale: : case StaticColor: : case PseudoColor: : type = PictTypeIndexed; : break; : case TrueColor: : case DirectColor: : type = PictTypeDirect; : break; : default: : return 0; : } : while (nformat--) : { : if (format->depth == depth && format->type == type) : { : if (type == PictTypeIndexed) : { : if (format->index.vid == pVisual->vid) : return format; : } : else : { : if (format->direct.redMask << format->direct.red == : pVisual->redMask && : format->direct.greenMask << format->direct.green == : pVisual->greenMask && : format->direct.blueMask << format->direct.blue == : pVisual->blueMask) : { : return format; : } : } : } : format++; : } : return 0; :} : :PictFormatPtr :PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) :{ : PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); : PictFormatPtr format; : int nformat; : : if (!ps) : return 0; : format = ps->formats; : nformat = ps->nformats; : while (nformat--) : { : if (format->depth == depth && format->format == (f & 0xffffff)) : return format; : format++; : } : return 0; :} : :int :PictureParseCmapPolicy (const char *name) :{ : if ( strcmp (name, "default" ) == 0) : return PictureCmapPolicyDefault; : else if ( strcmp (name, "mono" ) == 0) : return PictureCmapPolicyMono; : else if ( strcmp (name, "gray" ) == 0) : return PictureCmapPolicyGray; : else if ( strcmp (name, "color" ) == 0) : return PictureCmapPolicyColor; : else if ( strcmp (name, "all" ) == 0) : return PictureCmapPolicyAll; : else : return PictureCmapPolicyInvalid; :} : :_X_EXPORT Bool :PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) :{ : PictureScreenPtr ps; : int n; : CARD32 type, a, r, g, b; : : if (PictureGeneration != serverGeneration) : { : PictureType = CreateNewResourceType (FreePicture); : if (!PictureType) : return FALSE; : PictFormatType = CreateNewResourceType (FreePictFormat); : if (!PictFormatType) : return FALSE; : GlyphSetType = CreateNewResourceType (FreeGlyphSet); : if (!GlyphSetType) : return FALSE; : PictureScreenPrivateIndex = AllocateScreenPrivateIndex(); : if (PictureScreenPrivateIndex < 0) : return FALSE; : PictureWindowPrivateIndex = AllocateWindowPrivateIndex(); : PictureGeneration = serverGeneration; :#ifdef XResExtension : RegisterResourceName (PictureType, "PICTURE"); : RegisterResourceName (PictFormatType, "PICTFORMAT"); : RegisterResourceName (GlyphSetType, "GLYPHSET"); :#endif : } : if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0)) : return FALSE; : : if (!formats) : { : formats = PictureCreateDefaultFormats (pScreen, &nformats); : if (!formats) : return FALSE; : } : for (n = 0; n < nformats; n++) : { : if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) : { : xfree (formats); : return FALSE; : } : if (formats[n].type == PictTypeIndexed) : { : VisualPtr pVisual = PictureFindVisual (pScreen, formats[n].index.vid); : if ((pVisual->class | DynamicClass) == PseudoColor) : type = PICT_TYPE_COLOR; : else : type = PICT_TYPE_GRAY; : a = r = g = b = 0; : } : else : { : if ((formats[n].direct.redMask| : formats[n].direct.blueMask| : formats[n].direct.greenMask) == 0) : type = PICT_TYPE_A; : else if (formats[n].direct.red > formats[n].direct.blue) : type = PICT_TYPE_ARGB; : else : type = PICT_TYPE_ABGR; : a = Ones (formats[n].direct.alphaMask); : r = Ones (formats[n].direct.redMask); : g = Ones (formats[n].direct.greenMask); : b = Ones (formats[n].direct.blueMask); : } : formats[n].format = PICT_FORMAT(0,type,a,r,g,b); : } : ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec)); : if (!ps) : { : xfree (formats); : return FALSE; : } : SetPictureScreen(pScreen, ps); : if (!GlyphInit (pScreen)) : { : SetPictureScreen(pScreen, 0); : xfree (formats); : xfree (ps); : return FALSE; : } : : ps->totalPictureSize = sizeof (PictureRec); : ps->PicturePrivateSizes = 0; : ps->PicturePrivateLen = 0; : : ps->formats = formats; : ps->fallback = formats; : ps->nformats = nformats; : : ps->filters = 0; : ps->nfilters = 0; : ps->filterAliases = 0; : ps->nfilterAliases = 0; : : ps->subpixel = SubPixelUnknown; : : ps->CloseScreen = pScreen->CloseScreen; : ps->DestroyWindow = pScreen->DestroyWindow; : ps->StoreColors = pScreen->StoreColors; : pScreen->DestroyWindow = PictureDestroyWindow; : pScreen->CloseScreen = PictureCloseScreen; : pScreen->StoreColors = PictureStoreColors; : : if (!PictureSetDefaultFilters (pScreen)) : { : PictureResetFilters (pScreen); : SetPictureScreen(pScreen, 0); : xfree (formats); : xfree (ps); : return FALSE; : } : : return TRUE; :} : :void :SetPictureToDefaults (PicturePtr pPicture) :{ /* SetPictureToDefaults total: 8 0.0087 */ : pPicture->refcnt = 1; : pPicture->repeat = 0; : pPicture->graphicsExposures = FALSE; : pPicture->subWindowMode = ClipByChildren; : pPicture->polyEdge = PolyEdgeSharp; : pPicture->polyMode = PolyModePrecise; : pPicture->freeCompClip = FALSE; : pPicture->clientClipType = CT_NONE; : pPicture->componentAlpha = FALSE; : pPicture->repeatType = RepeatNone; : : pPicture->alphaMap = 0; : pPicture->alphaOrigin.x = 0; : pPicture->alphaOrigin.y = 0; : : pPicture->clipOrigin.x = 0; 1 0.0011 : pPicture->clipOrigin.y = 0; : pPicture->clientClip = 0; : : pPicture->transform = 0; : : pPicture->dither = None; 4 0.0044 : pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); : pPicture->filter_params = 0; : pPicture->filter_nparams = 0; : : pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; 1 0.0011 : pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; 1 0.0011 : pPicture->pSourcePict = 0; 1 0.0011 :} : :PicturePtr :AllocatePicture (ScreenPtr pScreen) :{ /* AllocatePicture total: 4 0.0044 */ : PictureScreenPtr ps = GetPictureScreen(pScreen); : PicturePtr pPicture; : char *ptr; : DevUnion *ppriv; : unsigned int *sizes; : unsigned int size; : int i; : 3 0.0033 : pPicture = (PicturePtr) xalloc (ps->totalPictureSize); : if (!pPicture) : return 0; : ppriv = (DevUnion *)(pPicture + 1); : pPicture->devPrivates = ppriv; : sizes = ps->PicturePrivateSizes; : ptr = (char *)(ppriv + ps->PicturePrivateLen); : for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++) : { : if ( (size = *sizes) ) : { : ppriv->ptr = (pointer)ptr; : ptr += size; : } : else : ppriv->ptr = (pointer)NULL; : } : return pPicture; 1 0.0011 :} : :PicturePtr :CreatePicture (Picture pid, : DrawablePtr pDrawable, : PictFormatPtr pFormat, : Mask vmask, : XID *vlist, : ClientPtr client, : int *error) 2 0.0022 :{ /* CreatePicture total: 12 0.0131 */ : PicturePtr pPicture; 2 0.0022 : PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); : : pPicture = AllocatePicture (pDrawable->pScreen); : if (!pPicture) : { : *error = BadAlloc; : return 0; : } : : pPicture->id = pid; : pPicture->pDrawable = pDrawable; : pPicture->pFormat = pFormat; 1 0.0011 : pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); 1 0.0011 : if (pDrawable->type == DRAWABLE_PIXMAP) : { : ++((PixmapPtr)pDrawable)->refcnt; : pPicture->pNext = 0; : } : else : { : pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); : SetPictureWindow(((WindowPtr) pDrawable), pPicture); : } : : SetPictureToDefaults (pPicture); : : if (vmask) : *error = ChangePicture (pPicture, vmask, vlist, 0, client); : else : *error = Success; : if (*error == Success) 4 0.0044 : *error = (*ps->CreatePicture) (pPicture); 1 0.0011 : if (*error != Success) : { : FreePicture (pPicture, (XID) 0); : pPicture = 0; : } : return pPicture; 1 0.0011 :} : :static CARD32 xRenderColorToCard32(xRenderColor c) :{ : return : (c.alpha >> 8 << 24) | : (c.red >> 8 << 16) | : (c.green & 0xff00) | : (c.blue >> 8); :} : :static unsigned int premultiply(unsigned int x) :{ : unsigned int a = x >> 24; : unsigned int t = (x & 0xff00ff) * a + 0x800080; : t = (t + ((t >> 8) & 0xff00ff)) >> 8; : t &= 0xff00ff; : : x = ((x >> 8) & 0xff) * a + 0x80; : x = (x + ((x >> 8) & 0xff)); : x &= 0xff00; : x |= t | (a << 24); : return x; :} : :static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a, : unsigned int y, unsigned int b) :{ : CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; : t >>= 8; : t &= 0xff00ff; : : x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; : x &= 0xff00ff00; : x |= t; : return x; :} : :CARD32 :PictureGradientColor (PictGradientStopPtr stop1, : PictGradientStopPtr stop2, : CARD32 x) :{ : CARD32 current_color, next_color; : int dist, idist; : : current_color = xRenderColorToCard32 (stop1->color); : next_color = xRenderColorToCard32 (stop2->color); : : dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x)); : idist = 256 - dist; : : return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist, : next_color, dist)); :} : :static void initGradient(SourcePictPtr pGradient, int stopCount, : xFixed *stopPoints, xRenderColor *stopColors, int *error) :{ : int i; : xFixed dpos; : : if (stopCount <= 0) { : *error = BadValue; : return; : } : : dpos = -1; : for (i = 0; i < stopCount; ++i) { : if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) { : *error = BadValue; : return; : } : dpos = stopPoints[i]; : } : : pGradient->gradient.stops = xalloc(stopCount*sizeof(PictGradientStop)); : if (!pGradient->gradient.stops) { : *error = BadAlloc; : return; : } : : pGradient->gradient.nstops = stopCount; : : for (i = 0; i < stopCount; ++i) { : pGradient->gradient.stops[i].x = stopPoints[i]; : pGradient->gradient.stops[i].color = stopColors[i]; : } : : pGradient->gradient.class = SourcePictClassUnknown; : pGradient->gradient.stopRange = 0xffff; : pGradient->gradient.colorTable = NULL; : pGradient->gradient.colorTableSize = 0; :} : :static PicturePtr createSourcePicture(void) :{ : PicturePtr pPicture; : pPicture = (PicturePtr) xalloc(sizeof(PictureRec)); : pPicture->pDrawable = 0; : pPicture->pFormat = 0; : pPicture->pNext = 0; : pPicture->format = PICT_a8r8g8b8; : pPicture->devPrivates = 0; : : SetPictureToDefaults(pPicture); : return pPicture; :} : :PicturePtr :CreateSolidPicture (Picture pid, xRenderColor *color, int *error) :{ : PicturePtr pPicture; : pPicture = createSourcePicture(); : if (!pPicture) { : *error = BadAlloc; : return 0; : } : : pPicture->id = pid; : pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill)); : if (!pPicture->pSourcePict) { : *error = BadAlloc; : xfree(pPicture); : return 0; : } : pPicture->pSourcePict->type = SourcePictTypeSolidFill; : pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color); : return pPicture; :} : :PicturePtr :CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2, : int nStops, xFixed *stops, xRenderColor *colors, int *error) :{ : PicturePtr pPicture; : : if (nStops < 2) { : *error = BadValue; : return 0; : } : : pPicture = createSourcePicture(); : if (!pPicture) { : *error = BadAlloc; : return 0; : } : : pPicture->id = pid; : pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient)); : if (!pPicture->pSourcePict) { : *error = BadAlloc; : xfree(pPicture); : return 0; : } : : pPicture->pSourcePict->linear.type = SourcePictTypeLinear; : pPicture->pSourcePict->linear.p1 = *p1; : pPicture->pSourcePict->linear.p2 = *p2; : : initGradient(pPicture->pSourcePict, nStops, stops, colors, error); : if (*error) { : xfree(pPicture); : return 0; : } : return pPicture; :} : :#define FixedToDouble(x) ((x)/65536.) : :PicturePtr :CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer, : xFixed innerRadius, xFixed outerRadius, : int nStops, xFixed *stops, xRenderColor *colors, int *error) :{ : PicturePtr pPicture; : PictRadialGradient *radial; : : if (nStops < 2) { : *error = BadValue; : return 0; : } : : pPicture = createSourcePicture(); : if (!pPicture) { : *error = BadAlloc; : return 0; : } : : pPicture->id = pid; : pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient)); : if (!pPicture->pSourcePict) { : *error = BadAlloc; : xfree(pPicture); : return 0; : } : radial = &pPicture->pSourcePict->radial; : : radial->type = SourcePictTypeRadial; : radial->c1.x = inner->x; : radial->c1.y = inner->y; : radial->c1.radius = innerRadius; : radial->c2.x = outer->x; : radial->c2.y = outer->y; : radial->c2.radius = outerRadius; : radial->cdx = (radial->c2.x - radial->c1.x) / 65536.; : radial->cdy = (radial->c2.y - radial->c1.y) / 65536.; : radial->dr = (radial->c2.radius - radial->c1.radius) / 65536.; : radial->A = ( radial->cdx * radial->cdx : + radial->cdy * radial->cdy : - radial->dr * radial->dr); : : initGradient(pPicture->pSourcePict, nStops, stops, colors, error); : if (*error) { : xfree(pPicture); : return 0; : } : return pPicture; :} : :PicturePtr :CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle, : int nStops, xFixed *stops, xRenderColor *colors, int *error) :{ : PicturePtr pPicture; : : if (nStops < 2) { : *error = BadValue; : return 0; : } : : pPicture = createSourcePicture(); : if (!pPicture) { : *error = BadAlloc; : return 0; : } : : pPicture->id = pid; : pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient)); : if (!pPicture->pSourcePict) { : *error = BadAlloc; : xfree(pPicture); : return 0; : } : : pPicture->pSourcePict->conical.type = SourcePictTypeConical; : pPicture->pSourcePict->conical.center = *center; : pPicture->pSourcePict->conical.angle = angle; : : initGradient(pPicture->pSourcePict, nStops, stops, colors, error); : if (*error) { : xfree(pPicture); : return 0; : } : return pPicture; :} : :#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) : :#define NEXT_PTR(_type) ((_type) ulist++->ptr) : :int :ChangePicture (PicturePtr pPicture, : Mask vmask, : XID *vlist, : DevUnion *ulist, : ClientPtr client) 4 0.0044 :{ /* ChangePicture total: 16 0.0174 */ : ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0; 4 0.0044 : PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0; : BITS32 index2; : int error = 0; : BITS32 maskQ; : : pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; : maskQ = vmask; 1 0.0011 : while (vmask && !error) : { : index2 = (BITS32) lowbit (vmask); 1 0.0011 : vmask &= ~index2; : pPicture->stateChanges |= index2; 1 0.0011 : switch (index2) : { : case CPRepeat: : { : unsigned int newr; 1 0.0011 : newr = NEXT_VAL(unsigned int); : if (newr <= RepeatReflect) : { 1 0.0011 : pPicture->repeat = (newr != RepeatNone); 1 0.0011 : pPicture->repeatType = newr; : } : else : { : client->errorValue = newr; : error = BadValue; : } : } : break; : case CPAlphaMap: : { : PicturePtr pAlpha; : : if (vlist) : { : Picture pid = NEXT_VAL(Picture); : : if (pid == None) : pAlpha = 0; : else : { : pAlpha = (PicturePtr) SecurityLookupIDByType(client, : pid, : PictureType, : DixWriteAccess|DixReadAccess); : if (!pAlpha) : { : client->errorValue = pid; : error = BadPixmap; : break; : } : if (pAlpha->pDrawable == NULL || : pAlpha->pDrawable->type != DRAWABLE_PIXMAP) : { : client->errorValue = pid; : error = BadMatch; : break; : } : } : } : else : pAlpha = NEXT_PTR(PicturePtr); : if (!error) : { : if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) : pAlpha->refcnt++; : if (pPicture->alphaMap) : FreePicture ((pointer) pPicture->alphaMap, (XID) 0); : pPicture->alphaMap = pAlpha; : } : } : break; : case CPAlphaXOrigin: : pPicture->alphaOrigin.x = NEXT_VAL(INT16); : break; : case CPAlphaYOrigin: : pPicture->alphaOrigin.y = NEXT_VAL(INT16); : break; : case CPClipXOrigin: : pPicture->clipOrigin.x = NEXT_VAL(INT16); : break; : case CPClipYOrigin: : pPicture->clipOrigin.y = NEXT_VAL(INT16); : break; : case CPClipMask: : { : Pixmap pid; : PixmapPtr pPixmap; : int clipType; : if (!pScreen) : return BadDrawable; : : if (vlist) : { : pid = NEXT_VAL(Pixmap); : if (pid == None) : { : clipType = CT_NONE; : pPixmap = NullPixmap; : } : else : { : clipType = CT_PIXMAP; : pPixmap = (PixmapPtr)SecurityLookupIDByType(client, : pid, : RT_PIXMAP, : DixReadAccess); : if (!pPixmap) : { : client->errorValue = pid; : error = BadPixmap; : break; : } : } : } : else : { : pPixmap = NEXT_PTR(PixmapPtr); : if (pPixmap) : clipType = CT_PIXMAP; : else : clipType = CT_NONE; : } : : if (pPixmap) : { : if ((pPixmap->drawable.depth != 1) || : (pPixmap->drawable.pScreen != pScreen)) : { : error = BadMatch; : break; : } : else : { : clipType = CT_PIXMAP; : pPixmap->refcnt++; : } : } : error = (*ps->ChangePictureClip)(pPicture, clipType, : (pointer)pPixmap, 0); : break; : } : case CPGraphicsExposure: : { : unsigned int newe; : newe = NEXT_VAL(unsigned int); : if (newe <= xTrue) : pPicture->graphicsExposures = newe; : else : { : client->errorValue = newe; : error = BadValue; : } : } : break; : case CPSubwindowMode: : { : unsigned int news; : news = NEXT_VAL(unsigned int); : if (news == ClipByChildren || news == IncludeInferiors) : pPicture->subWindowMode = news; : else : { : client->errorValue = news; : error = BadValue; : } : } : break; : case CPPolyEdge: : { : unsigned int newe; : newe = NEXT_VAL(unsigned int); : if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) : pPicture->polyEdge = newe; : else : { : client->errorValue = newe; : error = BadValue; : } : } : break; : case CPPolyMode: : { : unsigned int newm; : newm = NEXT_VAL(unsigned int); : if (newm == PolyModePrecise || newm == PolyModeImprecise) : pPicture->polyMode = newm; : else : { : client->errorValue = newm; : error = BadValue; : } : } : break; : case CPDither: : pPicture->dither = NEXT_VAL(Atom); : break; : case CPComponentAlpha: : { : unsigned int newca; : 1 0.0011 : newca = NEXT_VAL (unsigned int); : if (newca <= xTrue) : pPicture->componentAlpha = newca; : else : { : client->errorValue = newca; : error = BadValue; : } : } : break; : default: : client->errorValue = maskQ; : error = BadValue; : break; : } : } : if (ps) : (*ps->ChangePicture) (pPicture, maskQ); : return error; 1 0.0011 :} : :int :SetPictureClipRects (PicturePtr pPicture, : int xOrigin, : int yOrigin, : int nRect, : xRectangle *rects) :{ : ScreenPtr pScreen = pPicture->pDrawable->pScreen; : PictureScreenPtr ps = GetPictureScreen(pScreen); : RegionPtr clientClip; : int result; : : clientClip = RECTS_TO_REGION(pScreen, : nRect, rects, CT_UNSORTED); : if (!clientClip) : return BadAlloc; : result =(*ps->ChangePictureClip) (pPicture, CT_REGION, : (pointer) clientClip, 0); : if (result == Success) : { : pPicture->clipOrigin.x = xOrigin; : pPicture->clipOrigin.y = yOrigin; : pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; : pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; : } : return result; :} : :int :SetPictureClipRegion (PicturePtr pPicture, : int xOrigin, : int yOrigin, : RegionPtr pRegion) :{ : ScreenPtr pScreen = pPicture->pDrawable->pScreen; : PictureScreenPtr ps = GetPictureScreen(pScreen); : RegionPtr clientClip; : int result; : int type; : : if (pRegion) : { : type = CT_REGION; : clientClip = REGION_CREATE (pScreen, : REGION_EXTENTS(pScreen, pRegion), : REGION_NUM_RECTS(pRegion)); : if (!clientClip) : return BadAlloc; : if (!REGION_COPY (pSCreen, clientClip, pRegion)) : { : REGION_DESTROY (pScreen, clientClip); : return BadAlloc; : } : } : else : { : type = CT_NONE; : clientClip = 0; : } : : result =(*ps->ChangePictureClip) (pPicture, type, : (pointer) clientClip, 0); : if (result == Success) : { : pPicture->clipOrigin.x = xOrigin; : pPicture->clipOrigin.y = yOrigin; : pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; : pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; : } : return result; :} : :static Bool :transformIsIdentity(PictTransform *t) :{ : return ((t->matrix[0][0] == t->matrix[1][1]) && : (t->matrix[0][0] == t->matrix[2][2]) && : (t->matrix[0][0] != 0) && : (t->matrix[0][1] == 0) && : (t->matrix[0][2] == 0) && : (t->matrix[1][0] == 0) && : (t->matrix[1][2] == 0) && : (t->matrix[2][0] == 0) && : (t->matrix[2][1] == 0)); :} : :int :SetPictureTransform (PicturePtr pPicture, : PictTransform *transform) 2 0.0022 :{ /* SetPictureTransform total: 10 0.0109 */ : if (transform && transformIsIdentity (transform)) : transform = 0; : : if (transform) : { : if (!pPicture->transform) : { : pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform)); : if (!pPicture->transform) : return BadAlloc; : } : *pPicture->transform = *transform; : } : else : { : if (pPicture->transform) : { : xfree (pPicture->transform); : pPicture->transform = 0; : } : } : pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; : 5 0.0054 : if (pPicture->pDrawable != NULL) { : int result; : PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); : 1 0.0011 : result = (*ps->ChangePictureTransform) (pPicture, transform); : : return result; : } : : return Success; :} : :void :CopyPicture (PicturePtr pSrc, : Mask mask, : PicturePtr pDst) :{ : PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen); : Mask origMask = mask; : : pDst->serialNumber |= GC_CHANGE_SERIAL_BIT; : pDst->stateChanges |= mask; : : while (mask) { : Mask bit = lowbit(mask); : : switch (bit) : { : case CPRepeat: : pDst->repeat = pSrc->repeat; : pDst->repeatType = pSrc->repeatType; : break; : case CPAlphaMap: : if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP) : pSrc->alphaMap->refcnt++; : if (pDst->alphaMap) : FreePicture ((pointer) pDst->alphaMap, (XID) 0); : pDst->alphaMap = pSrc->alphaMap; : break; : case CPAlphaXOrigin: : pDst->alphaOrigin.x = pSrc->alphaOrigin.x; : break; : case CPAlphaYOrigin: : pDst->alphaOrigin.y = pSrc->alphaOrigin.y; : break; : case CPClipXOrigin: : pDst->clipOrigin.x = pSrc->clipOrigin.x; : break; : case CPClipYOrigin: : pDst->clipOrigin.y = pSrc->clipOrigin.y; : break; : case CPClipMask: : switch (pSrc->clientClipType) { : case CT_NONE: : (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); : break; : case CT_REGION: : if (!pSrc->clientClip) { : (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); : } else { : RegionPtr clientClip; : RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip; : : clientClip = REGION_CREATE(pSrc->pDrawable->pScreen, : REGION_EXTENTS(pSrc->pDrawable->pScreen, srcClientClip), : REGION_NUM_RECTS(srcClientClip)); : (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0); : } : break; : default: : /* XXX: CT_PIXMAP unimplemented */ : break; : } : break; : case CPGraphicsExposure: : pDst->graphicsExposures = pSrc->graphicsExposures; : break; : case CPPolyEdge: : pDst->polyEdge = pSrc->polyEdge; : break; : case CPPolyMode: : pDst->polyMode = pSrc->polyMode; : break; : case CPDither: : pDst->dither = pSrc->dither; : break; : case CPComponentAlpha: : pDst->componentAlpha = pSrc->componentAlpha; : break; : } : mask &= ~bit; : } : : (*ps->ChangePicture)(pDst, origMask); :} : :static void :ValidateOnePicture (PicturePtr pPicture) 5 0.0054 :{ /* ValidateOnePicture total: 10 0.0109 */ 1 0.0011 : if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber) : { : PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); : 4 0.0044 : (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); : pPicture->stateChanges = 0; : pPicture->serialNumber = pPicture->pDrawable->serialNumber; : } :} : :void :ValidatePicture(PicturePtr pPicture) 1 0.0011 :{ /* ValidatePicture total: 3 0.0033 */ : ValidateOnePicture (pPicture); 1 0.0011 : if (pPicture->alphaMap) : ValidateOnePicture (pPicture->alphaMap); 1 0.0011 :} : :int :FreePicture (pointer value, : XID pid) 3 0.0033 :{ /* FreePicture total: 8 0.0087 */ : PicturePtr pPicture = (PicturePtr) value; : 2 0.0022 : if (--pPicture->refcnt == 0) : { : if (pPicture->transform) : xfree (pPicture->transform); : : if (pPicture->pSourcePict) : { : if (pPicture->pSourcePict->type != SourcePictTypeSolidFill) : xfree(pPicture->pSourcePict->linear.stops); : : xfree(pPicture->pSourcePict); : } : : if (pPicture->pDrawable) : { : ScreenPtr pScreen = pPicture->pDrawable->pScreen; 2 0.0022 : PictureScreenPtr ps = GetPictureScreen(pScreen); : : if (pPicture->alphaMap) : FreePicture ((pointer) pPicture->alphaMap, (XID) 0); : (*ps->DestroyPicture) (pPicture); : (*ps->DestroyPictureClip) (pPicture); : if (pPicture->pDrawable->type == DRAWABLE_WINDOW) : { : WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; : PicturePtr *pPrev; : : for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr); : *pPrev; : pPrev = &(*pPrev)->pNext) : { : if (*pPrev == pPicture) : { : *pPrev = pPicture->pNext; : break; : } : } : } 1 0.0011 : else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) : { : (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); : } : } : xfree (pPicture); : } : return Success; :} : :int :FreePictFormat (pointer pPictFormat, : XID pid) :{ : return Success; :} : :/** : * ReduceCompositeOp is used to choose simpler ops for cases where alpha : * channels are always one and so math on the alpha channel per pixel becomes : * unnecessary. It may also avoid destination reads sometimes if apps aren't : * being careful to avoid these cases. : */ :static Bool :ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) :{ : Bool no_src_alpha, no_dst_alpha; : : no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) && : PICT_FORMAT_A(pSrc->format) == 0 && : pSrc->alphaMap == NULL && : pMask == NULL; : no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) && : PICT_FORMAT_A(pDst->format) == 0 && : pDst->alphaMap == NULL; : : /* TODO, maybe: Conjoint and Disjoint op reductions? */ : : /* Deal with simplifications where the source alpha is always 1. */ : if (no_src_alpha) : { : switch (op) { : case PictOpOver: : op = PictOpSrc; : break; : case PictOpInReverse: : op = PictOpDst; : break; : case PictOpOutReverse: : op = PictOpClear; : break; : case PictOpAtop: : op = PictOpIn; : break; : case PictOpAtopReverse: : op = PictOpOverReverse; : break; : case PictOpXor: : op = PictOpOut; : break; : default: : break; : } : } : : /* Deal with simplifications when the destination alpha is always 1 */ : if (no_dst_alpha) : { : switch (op) { : case PictOpOverReverse: : op = PictOpDst; : break; : case PictOpIn: : op = PictOpSrc; : break; : case PictOpOut: : op = PictOpClear; : break; : case PictOpAtop: : op = PictOpOver; : break; : case PictOpXor: : op = PictOpOutReverse; : break; : default: : break; : } : } : : /* Reduce some con/disjoint ops to the basic names. */ : switch (op) { : case PictOpDisjointClear: : case PictOpConjointClear: : op = PictOpClear; : break; : case PictOpDisjointSrc: : case PictOpConjointSrc: : op = PictOpSrc; : break; : case PictOpDisjointDst: : case PictOpConjointDst: : op = PictOpDst; : break; : default: : break; : } : : return op; :} : :void :CompositePicture (CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) 1 0.0011 :{ /* CompositePicture total: 4 0.0044 */ : PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); : : ValidatePicture (pSrc); : if (pMask) : ValidatePicture (pMask); 2 0.0022 : ValidatePicture (pDst); : : op = ReduceCompositeOp (op, pSrc, pMask, pDst); : if (op == PictOpDst) : return; : : (*ps->Composite) (op, : pSrc, : pMask, : pDst, : xSrc, : ySrc, : xMask, : yMask, : xDst, : yDst, : width, : height); :} : :void :CompositeGlyphs (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int nlist, : GlyphListPtr lists, : GlyphPtr *glyphs) 1 0.0011 :{ /* CompositeGlyphs total: 1 0.0011 */ : PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); : : ValidatePicture (pSrc); : ValidatePicture (pDst); : (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); :} : :void :CompositeRects (CARD8 op, : PicturePtr pDst, : xRenderColor *color, : int nRect, : xRectangle *rects) :{ /* CompositeRects total: 1 0.0011 */ 1 0.0011 : PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); : : ValidatePicture (pDst); : (*ps->CompositeRects) (op, pDst, color, nRect, rects); :} : :void :CompositeTrapezoids (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int ntrap, : xTrapezoid *traps) :{ : PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); : : ValidatePicture (pSrc); : ValidatePicture (pDst); : (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); :} : :void :CompositeTriangles (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int ntriangles, : xTriangle *triangles) :{ : PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); : : ValidatePicture (pSrc); : ValidatePicture (pDst); : (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); :} : :void :CompositeTriStrip (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int npoints, : xPointFixed *points) :{ : PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); : : ValidatePicture (pSrc); : ValidatePicture (pDst); : (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); :} : :void :CompositeTriFan (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int npoints, : xPointFixed *points) :{ : PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); : : ValidatePicture (pSrc); : ValidatePicture (pDst); : (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); :} : :void :AddTraps (PicturePtr pPicture, : INT16 xOff, : INT16 yOff, : int ntrap, : xTrap *traps) :{ : PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); : : ValidatePicture (pPicture); : (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps); :} : :_X_EXPORT Bool :PictureTransformPoint3d (PictTransformPtr transform, : PictVectorPtr vector) :{ : PictVector result; : int i, j; : xFixed_32_32 partial; : xFixed_48_16 v; : : for (j = 0; j < 3; j++) : { : v = 0; : for (i = 0; i < 3; i++) : { : partial = ((xFixed_48_16) transform->matrix[j][i] * : (xFixed_48_16) vector->vector[i]); : v += partial >> 16; : } : if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) : return FALSE; : result.vector[j] = (xFixed) v; : } : if (!result.vector[2]) : return FALSE; : *vector = result; : return TRUE; :} : : :_X_EXPORT Bool :PictureTransformPoint (PictTransformPtr transform, : PictVectorPtr vector) :{ : PictVector result; : int i, j; : xFixed_32_32 partial; : xFixed_48_16 v; : : for (j = 0; j < 3; j++) : { : v = 0; : for (i = 0; i < 3; i++) : { : partial = ((xFixed_48_16) transform->matrix[j][i] * : (xFixed_48_16) vector->vector[i]); : v += partial >> 16; : } : if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) : return FALSE; : result.vector[j] = (xFixed) v; : } : if (!result.vector[2]) : return FALSE; : for (j = 0; j < 2; j++) : { : partial = (xFixed_48_16) result.vector[j] << 16; : v = partial / result.vector[2]; : if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) : return FALSE; : vector->vector[j] = (xFixed) v; : } : vector->vector[2] = xFixed1; : return TRUE; :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/mi/miscrinit.c" * * 66 0.0719 */ :/* : :Copyright 1990, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included :in all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR :OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall :not be used in advertising or otherwise to promote the sale, use or :other dealings in this Software without prior written authorization :from The Open Group. : :*/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include "servermd.h" :#include "misc.h" :#include "mi.h" :#include "scrnintstr.h" :#include "pixmapstr.h" :#include "dix.h" :#include "miline.h" :#ifdef MITSHM :#define _XSHM_SERVER_ :#include :#endif : :/* We use this structure to propogate some information from miScreenInit to : * miCreateScreenResources. miScreenInit allocates the structure, fills it : * in, and puts it into pScreen->devPrivate. miCreateScreenResources : * extracts the info and frees the structure. We could've accomplished the : * same thing by adding fields to the screen structure, but they would have : * ended up being redundant, and would have exposed this mi implementation : * detail to the whole server. : */ : :typedef struct :{ : pointer pbits; /* pointer to framebuffer */ : int width; /* delta to add to a framebuffer addr to move one row down */ :} miScreenInitParmsRec, *miScreenInitParmsPtr; : : :/* this plugs into pScreen->ModifyPixmapHeader */ :_X_EXPORT Bool :miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, : pPixData) : PixmapPtr pPixmap; : int width; : int height; : int depth; : int bitsPerPixel; : int devKind; : pointer pPixData; 12 0.0131 :{ /* miModifyPixmapHeader total: 66 0.0719 */ 2 0.0022 : if (!pPixmap) : return FALSE; : : /* : * If all arguments are specified, reinitialize everything (including : * validated state). : */ 7 0.0076 : if ((width > 0) && (height > 0) && (depth > 0) && (bitsPerPixel > 0) && : (devKind > 0) && pPixData) { : pPixmap->drawable.depth = depth; : pPixmap->drawable.bitsPerPixel = bitsPerPixel; : pPixmap->drawable.id = 0; : pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; : pPixmap->drawable.x = 0; : pPixmap->drawable.y = 0; : pPixmap->drawable.width = width; : pPixmap->drawable.height = height; : pPixmap->devKind = devKind; : pPixmap->refcnt = 1; : pPixmap->devPrivate.ptr = pPixData; : } else { : /* : * Only modify specified fields, keeping all others intact. : */ : 3 0.0033 : if (width > 0) : pPixmap->drawable.width = width; : 5 0.0054 : if (height > 0) 1 0.0011 : pPixmap->drawable.height = height; : 1 0.0011 : if (depth > 0) : pPixmap->drawable.depth = depth; : 8 0.0087 : if (bitsPerPixel > 0) : pPixmap->drawable.bitsPerPixel = bitsPerPixel; 1 0.0011 : else if ((bitsPerPixel < 0) && (depth > 0)) : pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth); : : /* : * CAVEAT: Non-SI DDXen may use devKind and devPrivate fields for : * other purposes. : */ 1 0.0011 : if (devKind > 0) : pPixmap->devKind = devKind; : else if ((devKind < 0) && ((width > 0) || (depth > 0))) 14 0.0153 : pPixmap->devKind = PixmapBytePad(pPixmap->drawable.width, : pPixmap->drawable.depth); : 4 0.0044 : if (pPixData) 2 0.0022 : pPixmap->devPrivate.ptr = pPixData; : } : return TRUE; 5 0.0054 :} : :static Bool :miCloseScreen (int iScreen, ScreenPtr pScreen) :{ : return ((*pScreen->DestroyPixmap)((PixmapPtr)pScreen->devPrivate)); :} : :/* With the introduction of pixmap privates, the "screen pixmap" can no : * longer be created in miScreenInit, since all the modules that could : * possibly ask for pixmap private space have not been initialized at : * that time. pScreen->CreateScreenResources is called after all : * possible private-requesting modules have been inited; we create the : * screen pixmap here. : */ :_X_EXPORT Bool :miCreateScreenResources(pScreen) : ScreenPtr pScreen; :{ : miScreenInitParmsPtr pScrInitParms; : pointer value; : : pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; : : /* if width is non-zero, pScreen->devPrivate will be a pixmap : * else it will just take the value pbits : */ : if (pScrInitParms->width) : { : PixmapPtr pPixmap; : : /* create a pixmap with no data, then redirect it to point to : * the screen : */ : pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth); : if (!pPixmap) : return FALSE; : : if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width, : pScreen->height, pScreen->rootDepth, : BitsPerPixel(pScreen->rootDepth), : PixmapBytePad(pScrInitParms->width, pScreen->rootDepth), : pScrInitParms->pbits)) : return FALSE; : value = (pointer)pPixmap; : } : else : { : value = pScrInitParms->pbits; : } : xfree(pScreen->devPrivate); /* freeing miScreenInitParmsRec */ : pScreen->devPrivate = value; /* pPixmap or pbits */ : return TRUE; :} : :Bool :miScreenDevPrivateInit(pScreen, width, pbits) : ScreenPtr pScreen; : int width; : pointer pbits; :{ : miScreenInitParmsPtr pScrInitParms; : : /* Stash pbits and width in a short-lived miScreenInitParmsRec attached : * to the screen, until CreateScreenResources can put them in the : * screen pixmap. : */ : pScrInitParms = (miScreenInitParmsPtr)xalloc(sizeof(miScreenInitParmsRec)); : if (!pScrInitParms) : return FALSE; : pScrInitParms->pbits = pbits; : pScrInitParms->width = width; : pScreen->devPrivate = (pointer)pScrInitParms; : return TRUE; :} : :_X_EXPORT Bool :miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width, : rootDepth, numDepths, depths, rootVisual, numVisuals, visuals) : ScreenPtr pScreen; : pointer pbits; /* pointer to screen bits */ : int xsize, ysize; /* in pixels */ : int dpix, dpiy; /* dots per inch */ : int width; /* pixel width of frame buffer */ : int rootDepth; /* depth of root window */ : int numDepths; /* number of depths supported */ : DepthRec *depths; /* supported depths */ : VisualID rootVisual; /* root visual */ : int numVisuals; /* number of visuals supported */ : VisualRec *visuals; /* supported visuals */ :{ : pScreen->width = xsize; : pScreen->height = ysize; : pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10); : pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10); : pScreen->numDepths = numDepths; : pScreen->rootDepth = rootDepth; : pScreen->allowedDepths = depths; : pScreen->rootVisual = rootVisual; : /* defColormap */ : pScreen->minInstalledCmaps = 1; : pScreen->maxInstalledCmaps = 1; : pScreen->backingStoreSupport = NotUseful; : pScreen->saveUnderSupport = NotUseful; : /* whitePixel, blackPixel */ : pScreen->ModifyPixmapHeader = miModifyPixmapHeader; : pScreen->CreateScreenResources = miCreateScreenResources; : pScreen->GetScreenPixmap = miGetScreenPixmap; : pScreen->SetScreenPixmap = miSetScreenPixmap; : pScreen->numVisuals = numVisuals; : pScreen->visuals = visuals; : if (width) : { :#ifdef MITSHM : ShmRegisterFbFuncs(pScreen); :#endif : pScreen->CloseScreen = miCloseScreen; : } : /* else CloseScreen */ : /* QueryBestSize, SaveScreen, GetImage, GetSpans */ : pScreen->PointerNonInterestBox = (PointerNonInterestBoxProcPtr) 0; : pScreen->SourceValidate = (SourceValidateProcPtr) 0; : /* CreateWindow, DestroyWindow, PositionWindow, ChangeWindowAttributes */ : /* RealizeWindow, UnrealizeWindow */ : pScreen->ValidateTree = miValidateTree; : pScreen->PostValidateTree = (PostValidateTreeProcPtr) 0; : pScreen->WindowExposures = miWindowExposures; : /* PaintWindowBackground, PaintWindowBorder, CopyWindow */ : pScreen->ClearToBackground = miClearToBackground; : pScreen->ClipNotify = (ClipNotifyProcPtr) 0; : pScreen->RestackWindow = (RestackWindowProcPtr) 0; : /* CreatePixmap, DestroyPixmap */ : /* RealizeFont, UnrealizeFont */ : /* CreateGC */ : /* CreateColormap, DestroyColormap, InstallColormap, UninstallColormap */ : /* ListInstalledColormaps, StoreColors, ResolveColor */ : /* BitmapToRegion */ : pScreen->SendGraphicsExpose = miSendGraphicsExpose; : pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA; : pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA; : pScreen->blockData = (pointer)0; : pScreen->wakeupData = (pointer)0; : pScreen->MarkWindow = miMarkWindow; : pScreen->MarkOverlappedWindows = miMarkOverlappedWindows; : pScreen->ChangeSaveUnder = miChangeSaveUnder; : pScreen->PostChangeSaveUnder = miPostChangeSaveUnder; : pScreen->MoveWindow = miMoveWindow; : pScreen->ResizeWindow = miSlideAndSizeWindow; : pScreen->GetLayerWindow = miGetLayerWindow; : pScreen->HandleExposures = miHandleValidateExposures; : pScreen->ReparentWindow = (ReparentWindowProcPtr) 0; : pScreen->ChangeBorderWidth = miChangeBorderWidth; :#ifdef SHAPE : pScreen->SetShape = miSetShape; :#endif : pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow; : : pScreen->SaveDoomedAreas = 0; : pScreen->RestoreAreas = 0; : pScreen->ExposeCopy = 0; : pScreen->TranslateBackingStore = 0; : pScreen->ClearBackingStore = 0; : pScreen->DrawGuarantee = 0; : : miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS); : : return miScreenDevPrivateInit(pScreen, width, pbits); :} : :_X_EXPORT int :miAllocateGCPrivateIndex() :{ : static int privateIndex = -1; : static unsigned long miGeneration = 0; : : if (miGeneration != serverGeneration) : { : privateIndex = AllocateGCPrivateIndex(); : miGeneration = serverGeneration; : } : return privateIndex; :} : :_X_EXPORT int miZeroLineScreenIndex; :static unsigned int miZeroLineGeneration = 0; : :_X_EXPORT void :miSetZeroLineBias(pScreen, bias) : ScreenPtr pScreen; : unsigned int bias; :{ : if (miZeroLineGeneration != serverGeneration) : { : miZeroLineScreenIndex = AllocateScreenPrivateIndex(); : miZeroLineGeneration = serverGeneration; : } : if (miZeroLineScreenIndex >= 0) : pScreen->devPrivates[miZeroLineScreenIndex].uval = bias; :} : :_X_EXPORT PixmapPtr :miGetScreenPixmap(pScreen) : ScreenPtr pScreen; :{ : return (PixmapPtr)(pScreen->devPrivate); :} : :_X_EXPORT void :miSetScreenPixmap(pPix) : PixmapPtr pPix; :{ : if (pPix) : pPix->drawable.pScreen->devPrivate = (pointer)pPix; :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/mi/miregion.c" * * 66 0.0719 */ :/*********************************************************** : :Copyright 1987, 1988, 1989, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987, 1988, 1989 by :Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :******************************************************************/ : :/* The panoramix components contained the following notice */ :/***************************************************************** : :Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. : :Permission is hereby granted, free of charge, to any person obtaining a copy :of this software and associated documentation files (the "Software"), to deal :in the Software without restriction, including without limitation the rights :to use, copy, modify, merge, publish, distribute, sublicense, and/or sell :copies of the Software. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL :DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, :BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, :WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR :IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of Digital Equipment Corporation :shall not be used in advertising or otherwise to promote the sale, use or other :dealings in this Software without prior written authorization from Digital :Equipment Corporation. : :******************************************************************/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "regionstr.h" :#include :#include :#include "gc.h" :#include "mi.h" :#include "mispans.h" :#include : :#undef assert :#ifdef DEBUG :#define assert(expr) {if (!(expr)) \ : FatalError("Assertion failed file %s, line %d: expr\n", \ : __FILE__, __LINE__); } :#else :#define assert(expr) :#endif : :#define good(reg) assert(miValidRegion(reg)) : :/* : * The functions in this file implement the Region abstraction used extensively : * throughout the X11 sample server. A Region is simply a set of disjoint : * (non-overlapping) rectangles, plus an "extent" rectangle which is the : * smallest single rectangle that contains all the non-overlapping rectangles. : * : * A Region is implemented as a "y-x-banded" array of rectangles. This array : * imposes two degrees of order. First, all rectangles are sorted by top side : * y coordinate first (y1), and then by left side x coordinate (x1). : * : * Furthermore, the rectangles are grouped into "bands". Each rectangle in a : * band has the same top y coordinate (y1), and each has the same bottom y : * coordinate (y2). Thus all rectangles in a band differ only in their left : * and right side (x1 and x2). Bands are implicit in the array of rectangles: : * there is no separate list of band start pointers. : * : * The y-x band representation does not minimize rectangles. In particular, : * if a rectangle vertically crosses a band (the rectangle has scanlines in : * the y1 to y2 area spanned by the band), then the rectangle may be broken : * down into two or more smaller rectangles stacked one atop the other. : * : * ----------- ----------- : * | | | | band 0 : * | | -------- ----------- -------- : * | | | | in y-x banded | | | | band 1 : * | | | | form is | | | | : * ----------- | | ----------- -------- : * | | | | band 2 : * -------- -------- : * : * An added constraint on the rectangles is that they must cover as much : * horizontal area as possible: no two rectangles within a band are allowed : * to touch. : * : * Whenever possible, bands will be merged together to cover a greater vertical : * distance (and thus reduce the number of rectangles). Two bands can be merged : * only if the bottom of one touches the top of the other and they have : * rectangles in the same places (of the same width, of course). : * : * Adam de Boor wrote most of the original region code. Joel McCormack : * substantially modified or rewrote most of the core arithmetic routines, : * and added miRegionValidate in order to support several speed improvements : * to miValidateTree. Bob Scheifler changed the representation to be more : * compact when empty or a single rectangle, and did a bunch of gratuitous : * reformatting. : */ : :/* true iff two Boxes overlap */ :#define EXTENTCHECK(r1,r2) \ : (!( ((r1)->x2 <= (r2)->x1) || \ : ((r1)->x1 >= (r2)->x2) || \ : ((r1)->y2 <= (r2)->y1) || \ : ((r1)->y1 >= (r2)->y2) ) ) : :/* true iff (x,y) is in Box */ :#define INBOX(r,x,y) \ : ( ((r)->x2 > x) && \ : ((r)->x1 <= x) && \ : ((r)->y2 > y) && \ : ((r)->y1 <= y) ) : :/* true iff Box r1 contains Box r2 */ :#define SUBSUMES(r1,r2) \ : ( ((r1)->x1 <= (r2)->x1) && \ : ((r1)->x2 >= (r2)->x2) && \ : ((r1)->y1 <= (r2)->y1) && \ : ((r1)->y2 >= (r2)->y2) ) : :#define xallocData(n) (RegDataPtr)xalloc(REGION_SZOF(n)) :#define xfreeData(reg) if ((reg)->data && (reg)->data->size) xfree((reg)->data) : :#define RECTALLOC_BAIL(pReg,n,bail) \ :if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ : if (!miRectAlloc(pReg, n)) { goto bail; } : :#define RECTALLOC(pReg,n) \ :if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ : if (!miRectAlloc(pReg, n)) { return FALSE; } : :#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \ :{ \ : pNextRect->x1 = nx1; \ : pNextRect->y1 = ny1; \ : pNextRect->x2 = nx2; \ : pNextRect->y2 = ny2; \ : pNextRect++; \ :} : :#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \ :{ \ : if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\ : { \ : if (!miRectAlloc(pReg, 1)) \ : return FALSE; \ : pNextRect = REGION_TOP(pReg); \ : } \ : ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \ : pReg->data->numRects++; \ : assert(pReg->data->numRects<=pReg->data->size); \ :} : : :#define DOWNSIZE(reg,numRects) \ :if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ :{ \ : RegDataPtr NewData; \ : NewData = (RegDataPtr)xrealloc((reg)->data, REGION_SZOF(numRects)); \ : if (NewData) \ : { \ : NewData->size = (numRects); \ : (reg)->data = NewData; \ : } \ :} : : :_X_EXPORT BoxRec miEmptyBox = {0, 0, 0, 0}; :_X_EXPORT RegDataRec miEmptyData = {0, 0}; : :RegDataRec miBrokenData = {0, 0}; :static RegionRec miBrokenRegion = { { 0, 0, 0, 0 }, &miBrokenData }; : :extern void :InitRegions (void) :{ : pixman_region_set_static_pointers (&miEmptyBox, &miEmptyData, &miBrokenData); :} : :/***************************************************************** : * RegionCreate(rect, size) : * This routine does a simple malloc to make a structure of : * REGION of "size" number of rectangles. : *****************************************************************/ : :_X_EXPORT RegionPtr :miRegionCreate(rect, size) : BoxPtr rect; : int size; 3 0.0033 :{ /* miRegionCreate total: 5 0.0054 */ : RegionPtr pReg; : : pReg = (RegionPtr)xalloc(sizeof(RegionRec)); 1 0.0011 : if (!pReg) : return &miBrokenRegion; : 1 0.0011 : miRegionInit (pReg, rect, size); : : return(pReg); :} : :_X_EXPORT void :miRegionDestroy(pReg) : RegionPtr pReg; 3 0.0033 :{ /* miRegionDestroy total: 5 0.0054 */ : pixman_region_fini (pReg); : if (pReg != &miBrokenRegion) 1 0.0011 : xfree(pReg); 1 0.0011 :} : :_X_EXPORT void :miPrintRegion(rgn) : RegionPtr rgn; :{ : int num, size; : int i; : BoxPtr rects; : : num = REGION_NUM_RECTS(rgn); : size = REGION_SIZE(rgn); : rects = REGION_RECTS(rgn); : ErrorF("num: %d size: %d\n", num, size); : ErrorF("extents: %d %d %d %d\n", : rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2); : for (i = 0; i < num; i++) : ErrorF("%d %d %d %d \n", : rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); : ErrorF("\n"); :} : :_X_EXPORT Bool :miRegionEqual(reg1, reg2) : RegionPtr reg1; : RegionPtr reg2; :{ : return pixman_region_equal (reg1, reg2); :} : :#ifdef DEBUG :Bool :miValidRegion(reg) : RegionPtr reg; :{ : int i, numRects; : : if ((reg->extents.x1 > reg->extents.x2) || : (reg->extents.y1 > reg->extents.y2)) : return FALSE; : numRects = REGION_NUM_RECTS(reg); : if (!numRects) : return ((reg->extents.x1 == reg->extents.x2) && : (reg->extents.y1 == reg->extents.y2) && : (reg->data->size || (reg->data == &miEmptyData))); : else if (numRects == 1) : return (!reg->data); : else : { : BoxPtr pboxP, pboxN; : BoxRec box; : : pboxP = REGION_RECTS(reg); : box = *pboxP; : box.y2 = pboxP[numRects-1].y2; : pboxN = pboxP + 1; : for (i = numRects; --i > 0; pboxP++, pboxN++) : { : if ((pboxN->x1 >= pboxN->x2) || : (pboxN->y1 >= pboxN->y2)) : return FALSE; : if (pboxN->x1 < box.x1) : box.x1 = pboxN->x1; : if (pboxN->x2 > box.x2) : box.x2 = pboxN->x2; : if ((pboxN->y1 < pboxP->y1) || : ((pboxN->y1 == pboxP->y1) && : ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2)))) : return FALSE; : } : return ((box.x1 == reg->extents.x1) && : (box.x2 == reg->extents.x2) && : (box.y1 == reg->extents.y1) && : (box.y2 == reg->extents.y2)); : } :} :#endif /* DEBUG */ : :/***************************************************************** : * RegionInit(pReg, rect, size) : * Outer region rect is statically allocated. : *****************************************************************/ : :_X_EXPORT void :miRegionInit(pReg, rect, size) : RegionPtr pReg; : BoxPtr rect; : int size; 3 0.0033 :{ /* miRegionInit total: 5 0.0054 */ : if (rect) : pixman_region_init_with_extents (pReg, rect); : else : pixman_region_init (pReg); 2 0.0022 :} : :_X_EXPORT void :miRegionUninit(pReg) : RegionPtr pReg; :{ : pixman_region_fini (pReg); :} : :Bool :miRegionBreak (pReg) : RegionPtr pReg; :{ : xfreeData (pReg); : pReg->extents = miEmptyBox; : pReg->data = &miBrokenData; : return FALSE; :} : :_X_EXPORT Bool :miRectAlloc( : RegionPtr pRgn, : int n) :{ : RegDataPtr data; : : if (!pRgn->data) : { : n++; : pRgn->data = xallocData(n); : if (!pRgn->data) : return miRegionBreak (pRgn); : pRgn->data->numRects = 1; : *REGION_BOXPTR(pRgn) = pRgn->extents; : } : else if (!pRgn->data->size) : { : pRgn->data = xallocData(n); : if (!pRgn->data) : return miRegionBreak (pRgn); : pRgn->data->numRects = 0; : } : else : { : if (n == 1) : { : n = pRgn->data->numRects; : if (n > 500) /* XXX pick numbers out of a hat */ : n = 250; : } : n += pRgn->data->numRects; : data = (RegDataPtr)xrealloc(pRgn->data, REGION_SZOF(n)); : if (!data) : return miRegionBreak (pRgn); : pRgn->data = data; : } : pRgn->data->size = n; : return TRUE; :} : :_X_EXPORT Bool :miRegionCopy(dst, src) : RegionPtr dst; : RegionPtr src; 1 0.0011 :{ /* miRegionCopy total: 1 0.0011 */ : return pixman_region_copy (dst, src); :} : :/*====================================================================== : * Generic Region Operator : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * miCoalesce -- : * Attempt to merge the boxes in the current band with those in the : * previous one. We are guaranteed that the current band extends to : * the end of the rects array. Used only by miRegionOp. : * : * Results: : * The new index for the previous band. : * : * Side Effects: : * If coalescing takes place: : * - rectangles in the previous band will have their y2 fields : * altered. : * - pReg->data->numRects will be decreased. : * : *----------------------------------------------------------------------- : */ :_X_INLINE static int :miCoalesce ( : RegionPtr pReg, /* Region to coalesce */ : int prevStart, /* Index of start of previous band */ : int curStart) /* Index of start of current band */ :{ : BoxPtr pPrevBox; /* Current box in previous band */ : BoxPtr pCurBox; /* Current box in current band */ : int numRects; /* Number rectangles in both bands */ : int y2; /* Bottom of current band */ : /* : * Figure out how many rectangles are in the band. : */ : numRects = curStart - prevStart; : assert(numRects == pReg->data->numRects - curStart); : : if (!numRects) return curStart; : : /* : * The bands may only be coalesced if the bottom of the previous : * matches the top scanline of the current. : */ : pPrevBox = REGION_BOX(pReg, prevStart); : pCurBox = REGION_BOX(pReg, curStart); : if (pPrevBox->y2 != pCurBox->y1) return curStart; : : /* : * Make sure the bands have boxes in the same places. This : * assumes that boxes have been added in such a way that they : * cover the most area possible. I.e. two boxes in a band must : * have some horizontal space between them. : */ : y2 = pCurBox->y2; : : do { : if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) { : return (curStart); : } : pPrevBox++; : pCurBox++; : numRects--; : } while (numRects); : : /* : * The bands may be merged, so set the bottom y of each box : * in the previous band to the bottom y of the current band. : */ : numRects = curStart - prevStart; : pReg->data->numRects -= numRects; : do { : pPrevBox--; : pPrevBox->y2 = y2; : numRects--; : } while (numRects); : return prevStart; :} : : :/* Quicky macro to avoid trivial reject procedure calls to miCoalesce */ : :#define Coalesce(newReg, prevBand, curBand) \ : if (curBand - prevBand == newReg->data->numRects - curBand) { \ : prevBand = miCoalesce(newReg, prevBand, curBand); \ : } else { \ : prevBand = curBand; \ : } : :/*- : *----------------------------------------------------------------------- : * miAppendNonO -- : * Handle a non-overlapping band for the union and subtract operations. : * Just adds the (top/bottom-clipped) rectangles into the region. : * Doesn't have to check for subsumption or anything. : * : * Results: : * None. : * : * Side Effects: : * pReg->data->numRects is incremented and the rectangles overwritten : * with the rectangles we're passed. : * : *----------------------------------------------------------------------- : */ : :_X_INLINE static Bool :miAppendNonO ( : RegionPtr pReg, : BoxPtr r, : BoxPtr rEnd, : int y1, : int y2) :{ : BoxPtr pNextRect; : int newRects; : : newRects = rEnd - r; : : assert(y1 < y2); : assert(newRects != 0); : : /* Make sure we have enough space for all rectangles to be added */ : RECTALLOC(pReg, newRects); : pNextRect = REGION_TOP(pReg); : pReg->data->numRects += newRects; : do { : assert(r->x1 < r->x2); : ADDRECT(pNextRect, r->x1, y1, r->x2, y2); : r++; : } while (r != rEnd); : : return TRUE; :} : :#define FindBand(r, rBandEnd, rEnd, ry1) \ :{ \ : ry1 = r->y1; \ : rBandEnd = r+1; \ : while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \ : rBandEnd++; \ : } \ :} : :#define AppendRegions(newReg, r, rEnd) \ :{ \ : int newRects; \ : if ((newRects = rEnd - r)) { \ : RECTALLOC(newReg, newRects); \ : memmove((char *)REGION_TOP(newReg),(char *)r, \ : newRects * sizeof(BoxRec)); \ : newReg->data->numRects += newRects; \ : } \ :} : :/*- : *----------------------------------------------------------------------- : * miRegionOp -- : * Apply an operation to two regions. Called by miUnion, miInverse, : * miSubtract, miIntersect.... Both regions MUST have at least one : * rectangle, and cannot be the same object. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * The new region is overwritten. : * pOverlap set to TRUE if overlapFunc ever returns TRUE. : * : * Notes: : * The idea behind this function is to view the two regions as sets. : * Together they cover a rectangle of area that this function divides : * into horizontal bands where points are covered only by one region : * or by both. For the first case, the nonOverlapFunc is called with : * each the band and the band's upper and lower extents. For the : * second, the overlapFunc is called to process the entire band. It : * is responsible for clipping the rectangles in the band, though : * this function provides the boundaries. : * At the end of each band, the new region is coalesced, if possible, : * to reduce the number of rectangles in the region. : * : *----------------------------------------------------------------------- : */ : :typedef Bool (*OverlapProcPtr)( : RegionPtr pReg, : BoxPtr r1, : BoxPtr r1End, : BoxPtr r2, : BoxPtr r2End, : short y1, : short y2, : Bool *pOverlap); : :static Bool :miRegionOp( : RegionPtr newReg, /* Place to store result */ : RegionPtr reg1, /* First region in operation */ : RegionPtr reg2, /* 2d region in operation */ : OverlapProcPtr overlapFunc, /* Function to call for over- : * lapping bands */ : Bool appendNon1, /* Append non-overlapping bands */ : /* in region 1 ? */ : Bool appendNon2, /* Append non-overlapping bands */ : /* in region 2 ? */ : Bool *pOverlap) :{ : BoxPtr r1; /* Pointer into first region */ : BoxPtr r2; /* Pointer into 2d region */ : BoxPtr r1End; /* End of 1st region */ : BoxPtr r2End; /* End of 2d region */ : short ybot; /* Bottom of intersection */ : short ytop; /* Top of intersection */ : RegDataPtr oldData; /* Old data for newReg */ : int prevBand; /* Index of start of : * previous band in newReg */ : int curBand; /* Index of start of current : * band in newReg */ : BoxPtr r1BandEnd; /* End of current band in r1 */ : BoxPtr r2BandEnd; /* End of current band in r2 */ : short top; /* Top of non-overlapping band */ : short bot; /* Bottom of non-overlapping band*/ : int r1y1; /* Temps for r1->y1 and r2->y1 */ : int r2y1; : int newSize; : int numRects; : : /* : * Break any region computed from a broken region : */ : if (REGION_NAR (reg1) || REGION_NAR(reg2)) : return miRegionBreak (newReg); : : /* : * Initialization: : * set r1, r2, r1End and r2End appropriately, save the rectangles : * of the destination region until the end in case it's one of : * the two source regions, then mark the "new" region empty, allocating : * another array of rectangles for it to use. : */ : : r1 = REGION_RECTS(reg1); : newSize = REGION_NUM_RECTS(reg1); : r1End = r1 + newSize; : numRects = REGION_NUM_RECTS(reg2); : r2 = REGION_RECTS(reg2); : r2End = r2 + numRects; : assert(r1 != r1End); : assert(r2 != r2End); : : oldData = (RegDataPtr)NULL; : if (((newReg == reg1) && (newSize > 1)) || : ((newReg == reg2) && (numRects > 1))) : { : oldData = newReg->data; : newReg->data = &miEmptyData; : } : /* guess at new size */ : if (numRects > newSize) : newSize = numRects; : newSize <<= 1; : if (!newReg->data) : newReg->data = &miEmptyData; : else if (newReg->data->size) : newReg->data->numRects = 0; : if (newSize > newReg->data->size) : if (!miRectAlloc(newReg, newSize)) : return FALSE; : : /* : * Initialize ybot. : * In the upcoming loop, ybot and ytop serve different functions depending : * on whether the band being handled is an overlapping or non-overlapping : * band. : * In the case of a non-overlapping band (only one of the regions : * has points in the band), ybot is the bottom of the most recent : * intersection and thus clips the top of the rectangles in that band. : * ytop is the top of the next intersection between the two regions and : * serves to clip the bottom of the rectangles in the current band. : * For an overlapping band (where the two regions intersect), ytop clips : * the top of the rectangles of both regions and ybot clips the bottoms. : */ : : ybot = min(r1->y1, r2->y1); : : /* : * prevBand serves to mark the start of the previous band so rectangles : * can be coalesced into larger rectangles. qv. miCoalesce, above. : * In the beginning, there is no previous band, so prevBand == curBand : * (curBand is set later on, of course, but the first band will always : * start at index 0). prevBand and curBand must be indices because of : * the possible expansion, and resultant moving, of the new region's : * array of rectangles. : */ : prevBand = 0; : : do { : /* : * This algorithm proceeds one source-band (as opposed to a : * destination band, which is determined by where the two regions : * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the : * rectangle after the last one in the current band for their : * respective regions. : */ : assert(r1 != r1End); : assert(r2 != r2End); : : FindBand(r1, r1BandEnd, r1End, r1y1); : FindBand(r2, r2BandEnd, r2End, r2y1); : : /* : * First handle the band that doesn't intersect, if any. : * : * Note that attention is restricted to one band in the : * non-intersecting region at once, so if a region has n : * bands between the current position and the next place it overlaps : * the other, this entire loop will be passed through n times. : */ : if (r1y1 < r2y1) { : if (appendNon1) { : top = max(r1y1, ybot); : bot = min(r1->y2, r2y1); : if (top != bot) { : curBand = newReg->data->numRects; : miAppendNonO(newReg, r1, r1BandEnd, top, bot); : Coalesce(newReg, prevBand, curBand); : } : } : ytop = r2y1; : } else if (r2y1 < r1y1) { : if (appendNon2) { : top = max(r2y1, ybot); : bot = min(r2->y2, r1y1); : if (top != bot) { : curBand = newReg->data->numRects; : miAppendNonO(newReg, r2, r2BandEnd, top, bot); : Coalesce(newReg, prevBand, curBand); : } : } : ytop = r1y1; : } else { : ytop = r1y1; : } : : /* : * Now see if we've hit an intersecting band. The two bands only : * intersect if ybot > ytop : */ : ybot = min(r1->y2, r2->y2); : if (ybot > ytop) { : curBand = newReg->data->numRects; : (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot, : pOverlap); : Coalesce(newReg, prevBand, curBand); : } : : /* : * If we've finished with a band (y2 == ybot) we skip forward : * in the region to the next band. : */ : if (r1->y2 == ybot) r1 = r1BandEnd; : if (r2->y2 == ybot) r2 = r2BandEnd; : : } while (r1 != r1End && r2 != r2End); : : /* : * Deal with whichever region (if any) still has rectangles left. : * : * We only need to worry about banding and coalescing for the very first : * band left. After that, we can just group all remaining boxes, : * regardless of how many bands, into one final append to the list. : */ : : if ((r1 != r1End) && appendNon1) { : /* Do first nonOverlap1Func call, which may be able to coalesce */ : FindBand(r1, r1BandEnd, r1End, r1y1); : curBand = newReg->data->numRects; : miAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2); : Coalesce(newReg, prevBand, curBand); : /* Just append the rest of the boxes */ : AppendRegions(newReg, r1BandEnd, r1End); : : } else if ((r2 != r2End) && appendNon2) { : /* Do first nonOverlap2Func call, which may be able to coalesce */ : FindBand(r2, r2BandEnd, r2End, r2y1); : curBand = newReg->data->numRects; : miAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2); : Coalesce(newReg, prevBand, curBand); : /* Append rest of boxes */ : AppendRegions(newReg, r2BandEnd, r2End); : } : : if (oldData) : xfree(oldData); : : if (!(numRects = newReg->data->numRects)) : { : xfreeData(newReg); : newReg->data = &miEmptyData; : } : else if (numRects == 1) : { : newReg->extents = *REGION_BOXPTR(newReg); : xfreeData(newReg); : newReg->data = (RegDataPtr)NULL; : } : else : { : DOWNSIZE(newReg, numRects); : } : : return TRUE; :} : :/*- : *----------------------------------------------------------------------- : * miSetExtents -- : * Reset the extents of a region to what they should be. Called by : * miSubtract and miIntersect as they can't figure it out along the : * way or do so easily, as miUnion can. : * : * Results: : * None. : * : * Side Effects: : * The region's 'extents' structure is overwritten. : * : *----------------------------------------------------------------------- : */ :static void :miSetExtents (RegionPtr pReg) :{ : BoxPtr pBox, pBoxEnd; : : if (!pReg->data) : return; : if (!pReg->data->size) : { : pReg->extents.x2 = pReg->extents.x1; : pReg->extents.y2 = pReg->extents.y1; : return; : } : : pBox = REGION_BOXPTR(pReg); : pBoxEnd = REGION_END(pReg); : : /* : * Since pBox is the first rectangle in the region, it must have the : * smallest y1 and since pBoxEnd is the last rectangle in the region, : * it must have the largest y2, because of banding. Initialize x1 and : * x2 from pBox and pBoxEnd, resp., as good things to initialize them : * to... : */ : pReg->extents.x1 = pBox->x1; : pReg->extents.y1 = pBox->y1; : pReg->extents.x2 = pBoxEnd->x2; : pReg->extents.y2 = pBoxEnd->y2; : : assert(pReg->extents.y1 < pReg->extents.y2); : while (pBox <= pBoxEnd) { : if (pBox->x1 < pReg->extents.x1) : pReg->extents.x1 = pBox->x1; : if (pBox->x2 > pReg->extents.x2) : pReg->extents.x2 = pBox->x2; : pBox++; : }; : : assert(pReg->extents.x1 < pReg->extents.x2); :} : :/*====================================================================== : * Region Intersection : *====================================================================*/ :/*- : *----------------------------------------------------------------------- : * miIntersectO -- : * Handle an overlapping band for miIntersect. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * Rectangles may be added to the region. : * : *----------------------------------------------------------------------- : */ :/*ARGSUSED*/ :_X_EXPORT Bool :miIntersect(newReg, reg1, reg2) : RegionPtr newReg; /* destination Region */ : RegionPtr reg1; : RegionPtr reg2; /* source regions */ 1 0.0011 :{ /* miIntersect total: 6 0.0065 */ 2 0.0022 : return pixman_region_intersect (newReg, reg1, reg2); 3 0.0033 :} : :#define MERGERECT(r) \ :{ \ : if (r->x1 <= x2) { \ : /* Merge with current rectangle */ \ : if (r->x1 < x2) *pOverlap = TRUE; \ : if (x2 < r->x2) x2 = r->x2; \ : } else { \ : /* Add current rectangle, start new one */ \ : NEWRECT(pReg, pNextRect, x1, y1, x2, y2); \ : x1 = r->x1; \ : x2 = r->x2; \ : } \ : r++; \ :} : :/*====================================================================== : * Region Union : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * miUnionO -- : * Handle an overlapping band for the union operation. Picks the : * left-most rectangle each time and merges it into the region. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * pReg is overwritten. : * pOverlap is set to TRUE if any boxes overlap. : * : *----------------------------------------------------------------------- : */ :static Bool :miUnionO ( : RegionPtr pReg, : BoxPtr r1, : BoxPtr r1End, : BoxPtr r2, : BoxPtr r2End, : short y1, : short y2, : Bool *pOverlap) :{ : BoxPtr pNextRect; : int x1; /* left and right side of current union */ : int x2; : : assert (y1 < y2); : assert(r1 != r1End && r2 != r2End); : : pNextRect = REGION_TOP(pReg); : : /* Start off current rectangle */ : if (r1->x1 < r2->x1) : { : x1 = r1->x1; : x2 = r1->x2; : r1++; : } : else : { : x1 = r2->x1; : x2 = r2->x2; : r2++; : } : while (r1 != r1End && r2 != r2End) : { : if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2); : } : : /* Finish off whoever (if any) is left */ : if (r1 != r1End) : { : do : { : MERGERECT(r1); : } while (r1 != r1End); : } : else if (r2 != r2End) : { : do : { : MERGERECT(r2); : } while (r2 != r2End); : } : : /* Add current rectangle */ : NEWRECT(pReg, pNextRect, x1, y1, x2, y2); : : return TRUE; :} : :_X_EXPORT Bool :miUnion(newReg, reg1, reg2) : RegionPtr newReg; /* destination Region */ : RegionPtr reg1; : RegionPtr reg2; /* source regions */ 14 0.0153 :{ /* miUnion total: 27 0.0294 */ 2 0.0022 : return pixman_region_union (newReg, reg1, reg2); 11 0.0120 :} : :/*====================================================================== : * Batch Rectangle Union : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * miRegionAppend -- : * : * "Append" the rgn rectangles onto the end of dstrgn, maintaining : * knowledge of YX-banding when it's easy. Otherwise, dstrgn just : * becomes a non-y-x-banded random collection of rectangles, and not : * yet a true region. After a sequence of appends, the caller must : * call miRegionValidate to ensure that a valid region is constructed. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * dstrgn is modified if rgn has rectangles. : * : */ :_X_EXPORT Bool :miRegionAppend(dstrgn, rgn) : RegionPtr dstrgn; : RegionPtr rgn; :{ : int numRects, dnumRects, size; : BoxPtr new, old; : Bool prepend; : : if (REGION_NAR(rgn)) : return miRegionBreak (dstrgn); : : if (!rgn->data && (dstrgn->data == &miEmptyData)) : { : dstrgn->extents = rgn->extents; : dstrgn->data = (RegDataPtr)NULL; : return TRUE; : } : : numRects = REGION_NUM_RECTS(rgn); : if (!numRects) : return TRUE; : prepend = FALSE; : size = numRects; : dnumRects = REGION_NUM_RECTS(dstrgn); : if (!dnumRects && (size < 200)) : size = 200; /* XXX pick numbers out of a hat */ : RECTALLOC(dstrgn, size); : old = REGION_RECTS(rgn); : if (!dnumRects) : dstrgn->extents = rgn->extents; : else if (dstrgn->extents.x2 > dstrgn->extents.x1) : { : BoxPtr first, last; : : first = old; : last = REGION_BOXPTR(dstrgn) + (dnumRects - 1); : if ((first->y1 > last->y2) || : ((first->y1 == last->y1) && (first->y2 == last->y2) && : (first->x1 > last->x2))) : { : if (rgn->extents.x1 < dstrgn->extents.x1) : dstrgn->extents.x1 = rgn->extents.x1; : if (rgn->extents.x2 > dstrgn->extents.x2) : dstrgn->extents.x2 = rgn->extents.x2; : dstrgn->extents.y2 = rgn->extents.y2; : } : else : { : first = REGION_BOXPTR(dstrgn); : last = old + (numRects - 1); : if ((first->y1 > last->y2) || : ((first->y1 == last->y1) && (first->y2 == last->y2) && : (first->x1 > last->x2))) : { : prepend = TRUE; : if (rgn->extents.x1 < dstrgn->extents.x1) : dstrgn->extents.x1 = rgn->extents.x1; : if (rgn->extents.x2 > dstrgn->extents.x2) : dstrgn->extents.x2 = rgn->extents.x2; : dstrgn->extents.y1 = rgn->extents.y1; : } : else : dstrgn->extents.x2 = dstrgn->extents.x1; : } : } : if (prepend) : { : new = REGION_BOX(dstrgn, numRects); : if (dnumRects == 1) : *new = *REGION_BOXPTR(dstrgn); : else : memmove((char *)new,(char *)REGION_BOXPTR(dstrgn), : dnumRects * sizeof(BoxRec)); : new = REGION_BOXPTR(dstrgn); : } : else : new = REGION_BOXPTR(dstrgn) + dnumRects; : if (numRects == 1) : *new = *old; : else : memmove((char *)new, (char *)old, numRects * sizeof(BoxRec)); : dstrgn->data->numRects += numRects; : return TRUE; :} : : :#define ExchangeRects(a, b) \ :{ \ : BoxRec t; \ : t = rects[a]; \ : rects[a] = rects[b]; \ : rects[b] = t; \ :} : :static void :QuickSortRects( : BoxRec rects[], : int numRects) :{ /* QuickSortRects total: 1 0.0011 */ : int y1; : int x1; : int i, j; : BoxPtr r; : : /* Always called with numRects > 1 */ : : do : { : if (numRects == 2) : { 1 0.0011 : if (rects[0].y1 > rects[1].y1 || : (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1)) : ExchangeRects(0, 1); : return; : } : : /* Choose partition element, stick in location 0 */ : ExchangeRects(0, numRects >> 1); : y1 = rects[0].y1; : x1 = rects[0].x1; : : /* Partition array */ : i = 0; : j = numRects; : do : { : r = &(rects[i]); : do : { : r++; : i++; : } while (i != numRects && : (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1))); : r = &(rects[j]); : do : { : r--; : j--; : } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1)); : if (i < j) : ExchangeRects(i, j); : } while (i < j); : : /* Move partition element back to middle */ : ExchangeRects(0, j); : : /* Recurse */ : if (numRects-j-1 > 1) : QuickSortRects(&rects[j+1], numRects-j-1); : numRects = j; : } while (numRects > 1); :} : :/*- : *----------------------------------------------------------------------- : * miRegionValidate -- : * : * Take a ``region'' which is a non-y-x-banded random collection of : * rectangles, and compute a nice region which is the union of all the : * rectangles. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * The passed-in ``region'' may be modified. : * pOverlap set to TRUE if any retangles overlapped, else FALSE; : * : * Strategy: : * Step 1. Sort the rectangles into ascending order with primary key y1 : * and secondary key x1. : * : * Step 2. Split the rectangles into the minimum number of proper y-x : * banded regions. This may require horizontally merging : * rectangles, and vertically coalescing bands. With any luck, : * this step in an identity tranformation (ala the Box widget), : * or a coalescing into 1 box (ala Menus). : * : * Step 3. Merge the separate regions down to a single region by calling : * miUnion. Maximize the work each miUnion call does by using : * a binary merge. : * : *----------------------------------------------------------------------- : */ : :_X_EXPORT Bool :miRegionValidate(badreg, pOverlap) : RegionPtr badreg; : Bool *pOverlap; 1 0.0011 :{ /* miRegionValidate total: 7 0.0076 */ : /* Descriptor for regions under construction in Step 2. */ : typedef struct { : RegionRec reg; : int prevBand; : int curBand; : } RegionInfo; : : int numRects; /* Original numRects for badreg */ : RegionInfo *ri; /* Array of current regions */ : int numRI; /* Number of entries used in ri */ : int sizeRI; /* Number of entries available in ri */ : int i; /* Index into rects */ : int j; /* Index into ri */ : RegionInfo *rit; /* &ri[j] */ : RegionPtr reg; /* ri[j].reg */ : BoxPtr box; /* Current box in rects */ : BoxPtr riBox; /* Last box in ri[j].reg */ : RegionPtr hreg; /* ri[j_half].reg */ : Bool ret = TRUE; : : *pOverlap = FALSE; : if (!badreg->data) : { : good(badreg); : return TRUE; : } : numRects = badreg->data->numRects; : if (!numRects) : { : if (REGION_NAR(badreg)) : return FALSE; : good(badreg); : return TRUE; : } 1 0.0011 : if (badreg->extents.x1 < badreg->extents.x2) : { : if ((numRects) == 1) : { : xfreeData(badreg); : badreg->data = (RegDataPtr) NULL; : } : else : { : DOWNSIZE(badreg, numRects); : } : good(badreg); : return TRUE; : } : : /* Step 1: Sort the rects array into ascending (y1, x1) order */ : QuickSortRects(REGION_BOXPTR(badreg), numRects); : : /* Step 2: Scatter the sorted array into the minimum number of regions */ : : /* Set up the first region to be the first rectangle in badreg */ : /* Note that step 2 code will never overflow the ri[0].reg rects array */ : ri = (RegionInfo *) xalloc(4 * sizeof(RegionInfo)); : if (!ri) : return miRegionBreak (badreg); : sizeRI = 4; : numRI = 1; : ri[0].prevBand = 0; : ri[0].curBand = 0; : ri[0].reg = *badreg; : box = REGION_BOXPTR(&ri[0].reg); : ri[0].reg.extents = *box; : ri[0].reg.data->numRects = 1; : : /* Now scatter rectangles into the minimum set of valid regions. If the : next rectangle to be added to a region would force an existing rectangle : in the region to be split up in order to maintain y-x banding, just : forget it. Try the next region. If it doesn't fit cleanly into any : region, make a new one. */ : : for (i = numRects; --i > 0;) : { : box++; : /* Look for a region to append box to */ : for (j = numRI, rit = ri; --j >= 0; rit++) : { : reg = &rit->reg; : riBox = REGION_END(reg); : : if (box->y1 == riBox->y1 && box->y2 == riBox->y2) : { : /* box is in same band as riBox. Merge or append it */ : if (box->x1 <= riBox->x2) : { : /* Merge it with riBox */ : if (box->x1 < riBox->x2) *pOverlap = TRUE; : if (box->x2 > riBox->x2) riBox->x2 = box->x2; : } : else : { : RECTALLOC_BAIL(reg, 1, bail); : *REGION_TOP(reg) = *box; : reg->data->numRects++; : } : goto NextRect; /* So sue me */ : } 1 0.0011 : else if (box->y1 >= riBox->y2) : { : /* Put box into new band */ : if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; : if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1; : Coalesce(reg, rit->prevBand, rit->curBand); : rit->curBand = reg->data->numRects; : RECTALLOC_BAIL(reg, 1, bail); : *REGION_TOP(reg) = *box; : reg->data->numRects++; : goto NextRect; : } : /* Well, this region was inappropriate. Try the next one. */ : } /* for j */ : : /* Uh-oh. No regions were appropriate. Create a new one. */ 1 0.0011 : if (sizeRI == numRI) : { : /* Oops, allocate space for new region information */ : sizeRI <<= 1; : rit = (RegionInfo *) xrealloc(ri, sizeRI * sizeof(RegionInfo)); : if (!rit) : goto bail; : ri = rit; : rit = &ri[numRI]; : } : numRI++; : rit->prevBand = 0; : rit->curBand = 0; : rit->reg.extents = *box; : rit->reg.data = (RegDataPtr)NULL; : if (!miRectAlloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */ : goto bail; :NextRect: ; : } /* for i */ : : /* Make a final pass over each region in order to Coalesce and set : extents.x2 and extents.y2 */ : : for (j = numRI, rit = ri; --j >= 0; rit++) : { : reg = &rit->reg; : riBox = REGION_END(reg); : reg->extents.y2 = riBox->y2; : if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; : Coalesce(reg, rit->prevBand, rit->curBand); : if (reg->data->numRects == 1) /* keep unions happy below */ : { : xfreeData(reg); : reg->data = (RegDataPtr)NULL; : } : } : : /* Step 3: Union all regions into a single region */ 1 0.0011 : while (numRI > 1) : { : int half = numRI/2; : for (j = numRI & 1; j < (half + (numRI & 1)); j++) : { : reg = &ri[j].reg; : hreg = &ri[j+half].reg; : if (!miRegionOp(reg, reg, hreg, miUnionO, TRUE, TRUE, pOverlap)) : ret = FALSE; : if (hreg->extents.x1 < reg->extents.x1) : reg->extents.x1 = hreg->extents.x1; : if (hreg->extents.y1 < reg->extents.y1) : reg->extents.y1 = hreg->extents.y1; : if (hreg->extents.x2 > reg->extents.x2) : reg->extents.x2 = hreg->extents.x2; 1 0.0011 : if (hreg->extents.y2 > reg->extents.y2) : reg->extents.y2 = hreg->extents.y2; : xfreeData(hreg); : } : numRI -= half; : } : *badreg = ri[0].reg; : xfree(ri); : good(badreg); : return ret; :bail: : for (i = 0; i < numRI; i++) : xfreeData(&ri[i].reg); : xfree (ri); : return miRegionBreak (badreg); :} : :_X_EXPORT RegionPtr :miRectsToRegion(nrects, prect, ctype) : int nrects; : xRectangle *prect; : int ctype; 1 0.0011 :{ /* miRectsToRegion total: 8 0.0087 */ : : RegionPtr pRgn; : RegDataPtr pData; : BoxPtr pBox; : int i; : int x1, y1, x2, y2; : : pRgn = miRegionCreate(NullBox, 0); : if (REGION_NAR (pRgn)) : return pRgn; 4 0.0044 : if (!nrects) : return pRgn; : if (nrects == 1) : { : x1 = prect->x; : y1 = prect->y; 1 0.0011 : if ((x2 = x1 + (int) prect->width) > MAXSHORT) : x2 = MAXSHORT; : if ((y2 = y1 + (int) prect->height) > MAXSHORT) : y2 = MAXSHORT; : if (x1 != x2 && y1 != y2) : { : pRgn->extents.x1 = x1; : pRgn->extents.y1 = y1; : pRgn->extents.x2 = x2; : pRgn->extents.y2 = y2; : pRgn->data = (RegDataPtr)NULL; : } : return pRgn; : } : pData = xallocData(nrects); : if (!pData) : { : miRegionBreak (pRgn); : return pRgn; : } : pBox = (BoxPtr) (pData + 1); : for (i = nrects; --i >= 0; prect++) : { : x1 = prect->x; : y1 = prect->y; : if ((x2 = x1 + (int) prect->width) > MAXSHORT) : x2 = MAXSHORT; : if ((y2 = y1 + (int) prect->height) > MAXSHORT) : y2 = MAXSHORT; : if (x1 != x2 && y1 != y2) : { : pBox->x1 = x1; : pBox->y1 = y1; : pBox->x2 = x2; : pBox->y2 = y2; : pBox++; : } : } 1 0.0011 : if (pBox != (BoxPtr) (pData + 1)) : { : pData->size = nrects; : pData->numRects = pBox - (BoxPtr) (pData + 1); : pRgn->data = pData; : if (ctype != CT_YXBANDED) : { : Bool overlap; /* result ignored */ : pRgn->extents.x1 = pRgn->extents.x2 = 0; : miRegionValidate(pRgn, &overlap); : } : else : miSetExtents(pRgn); : good(pRgn); : } : else : { : xfree (pData); : } : return pRgn; 1 0.0011 :} : :/*====================================================================== : * Region Subtraction : *====================================================================*/ : : :/*- : *----------------------------------------------------------------------- : * miSubtractO -- : * Overlapping band subtraction. x1 is the left-most point not yet : * checked. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * pReg may have rectangles added to it. : * : *----------------------------------------------------------------------- : */ :/*ARGSUSED*/ : :/*- : *----------------------------------------------------------------------- : * miSubtract -- : * Subtract regS from regM and leave the result in regD. : * S stands for subtrahend, M for minuend and D for difference. : * : * Results: : * TRUE if successful. : * : * Side Effects: : * regD is overwritten. : * : *----------------------------------------------------------------------- : */ :_X_EXPORT Bool :miSubtract(regD, regM, regS) : RegionPtr regD; : RegionPtr regM; : RegionPtr regS; :{ : return pixman_region_subtract (regD, regM, regS); :} : :/*====================================================================== : * Region Inversion : *====================================================================*/ : :/*- : *----------------------------------------------------------------------- : * miInverse -- : * Take a region and a box and return a region that is everything : * in the box but not in the region. The careful reader will note : * that this is the same as subtracting the region from the box... : * : * Results: : * TRUE. : * : * Side Effects: : * newReg is overwritten. : * : *----------------------------------------------------------------------- : */ :_X_EXPORT Bool :miInverse(newReg, reg1, invRect) : RegionPtr newReg; /* Destination region */ : RegionPtr reg1; /* Region to invert */ : BoxPtr invRect; /* Bounding box for inversion */ :{ : return pixman_region_inverse (newReg, reg1, invRect); :} :_X_EXPORT int :miRectIn(region, prect) : RegionPtr region; : BoxPtr prect; :{ : return pixman_region_contains_rectangle (region, prect); :} : :/* TranslateRegion(pReg, x, y) : translates in place :*/ : :_X_EXPORT void :miTranslateRegion(pReg, x, y) : RegionPtr pReg; : int x; : int y; 2 0.0022 :{ /* miTranslateRegion total: 2 0.0022 */ : pixman_region_translate (pReg, x, y); :} : :_X_EXPORT void :miRegionReset(pReg, pBox) : RegionPtr pReg; : BoxPtr pBox; :{ : pixman_region_reset (pReg, pBox); :} : :_X_EXPORT Bool :miPointInRegion(pReg, x, y, box) : RegionPtr pReg; : int x, y; : BoxPtr box; /* "return" value */ :{ : return pixman_region_contains_point (pReg, x, y, box); :} : :_X_EXPORT Bool :miRegionNotEmpty(pReg) : RegionPtr pReg; :{ : return pixman_region_not_empty (pReg); :} : :Bool :miRegionBroken(RegionPtr pReg) :{ : good(pReg); : return (REGION_NAR(pReg)); :} : :_X_EXPORT void :miRegionEmpty(pReg) : RegionPtr pReg; :{ : good(pReg); : xfreeData(pReg); : pReg->extents.x2 = pReg->extents.x1; : pReg->extents.y2 = pReg->extents.y1; : pReg->data = &miEmptyData; :} : :_X_EXPORT BoxPtr :miRegionExtents(pReg) : RegionPtr pReg; :{ : good(pReg); : return(&pReg->extents); :} : :#define ExchangeSpans(a, b) \ :{ \ : DDXPointRec tpt; \ : int tw; \ : \ : tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \ : tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ :} : :/* ||| I should apply the merge sort code to rectangle sorting above, and see : if mapping time can be improved. But right now I've been at work 12 hours, : so forget it. :*/ : :static void QuickSortSpans( : DDXPointRec spans[], : int widths[], : int numSpans) :{ : int y; : int i, j, m; : DDXPointPtr r; : : /* Always called with numSpans > 1 */ : /* Sorts only by y, doesn't bother to sort by x */ : : do : { : if (numSpans < 9) : { : /* Do insertion sort */ : int yprev; : : yprev = spans[0].y; : i = 1; : do : { /* while i != numSpans */ : y = spans[i].y; : if (yprev > y) : { : /* spans[i] is out of order. Move into proper location. */ : DDXPointRec tpt; : int tw, k; : : for (j = 0; y >= spans[j].y; j++) {} : tpt = spans[i]; : tw = widths[i]; : for (k = i; k != j; k--) : { : spans[k] = spans[k-1]; : widths[k] = widths[k-1]; : } : spans[j] = tpt; : widths[j] = tw; : y = spans[i].y; : } /* if out of order */ : yprev = y; : i++; : } while (i != numSpans); : return; : } : : /* Choose partition element, stick in location 0 */ : m = numSpans / 2; : if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); : if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1); : if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); : y = spans[0].y; : : /* Partition array */ : i = 0; : j = numSpans; : do : { : r = &(spans[i]); : do : { : r++; : i++; : } while (i != numSpans && r->y < y); : r = &(spans[j]); : do : { : r--; : j--; : } while (y < r->y); : if (i < j) : ExchangeSpans(i, j); : } while (i < j); : : /* Move partition element back to middle */ : ExchangeSpans(0, j); : : /* Recurse */ : if (numSpans-j-1 > 1) : QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1); : numSpans = j; : } while (numSpans > 1); :} : :#define NextBand() \ :{ \ : clipy1 = pboxBandStart->y1; \ : clipy2 = pboxBandStart->y2; \ : pboxBandEnd = pboxBandStart + 1; \ : while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \ : pboxBandEnd++; \ : } \ : for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \ :} : :/* : Clip a list of scanlines to a region. The caller has allocated the : space. FSorted is non-zero if the scanline origins are in ascending : order. : returns the number of new, clipped scanlines. :*/ : :_X_EXPORT int :miClipSpans( : RegionPtr prgnDst, : DDXPointPtr ppt, : int *pwidth, : int nspans, : DDXPointPtr pptNew, : int *pwidthNew, : int fSorted) :{ : DDXPointPtr pptLast; : int *pwidthNewStart; /* the vengeance of Xerox! */ : int y, x1, x2; : int numRects; : : good(prgnDst); : pptLast = ppt + nspans; : pwidthNewStart = pwidthNew; : : if (!prgnDst->data) : { : /* Do special fast code with clip boundaries in registers(?) */ : /* It doesn't pay much to make use of fSorted in this case, : so we lump everything together. */ : : int clipx1, clipx2, clipy1, clipy2; : : clipx1 = prgnDst->extents.x1; : clipy1 = prgnDst->extents.y1; : clipx2 = prgnDst->extents.x2; : clipy2 = prgnDst->extents.y2; : : for (; ppt != pptLast; ppt++, pwidth++) : { : y = ppt->y; : x1 = ppt->x; : if (clipy1 <= y && y < clipy2) : { : x2 = x1 + *pwidth; : if (x1 < clipx1) x1 = clipx1; : if (x2 > clipx2) x2 = clipx2; : if (x1 < x2) : { : /* part of span in clip rectangle */ : pptNew->x = x1; : pptNew->y = y; : *pwidthNew = x2 - x1; : pptNew++; : pwidthNew++; : } : } : } /* end for */ : : } : else if ((numRects = prgnDst->data->numRects)) : { : /* Have to clip against many boxes */ : BoxPtr pboxBandStart, pboxBandEnd; : BoxPtr pbox; : BoxPtr pboxLast; : int clipy1, clipy2; : : /* In this case, taking advantage of sorted spans gains more than : the sorting costs. */ : if ((! fSorted) && (nspans > 1)) : QuickSortSpans(ppt, pwidth, nspans); : : pboxBandStart = REGION_BOXPTR(prgnDst); : pboxLast = pboxBandStart + numRects; : : NextBand(); : : for (; ppt != pptLast; ) : { : y = ppt->y; : if (y < clipy2) : { : /* span is in the current band */ : pbox = pboxBandStart; : x1 = ppt->x; : x2 = x1 + *pwidth; : do : { /* For each box in band */ : int newx1, newx2; : : newx1 = x1; : newx2 = x2; : if (newx1 < pbox->x1) newx1 = pbox->x1; : if (newx2 > pbox->x2) newx2 = pbox->x2; : if (newx1 < newx2) : { : /* Part of span in clip rectangle */ : pptNew->x = newx1; : pptNew->y = y; : *pwidthNew = newx2 - newx1; : pptNew++; : pwidthNew++; : } : pbox++; : } while (pbox != pboxBandEnd); : ppt++; : pwidth++; : } : else : { : /* Move to next band, adjust ppt as needed */ : pboxBandStart = pboxBandEnd; : if (pboxBandStart == pboxLast) : break; /* We're completely done */ : NextBand(); : } : } : } : return (pwidthNew - pwidthNewStart); :} : :/* find the band in a region with the most rectangles */ :_X_EXPORT int :miFindMaxBand(prgn) : RegionPtr prgn; :{ : int nbox; : BoxPtr pbox; : int nThisBand; : int nMaxBand = 0; : short yThisBand; : : good(prgn); : nbox = REGION_NUM_RECTS(prgn); : pbox = REGION_RECTS(prgn); : : while(nbox > 0) : { : yThisBand = pbox->y1; : nThisBand = 0; : while((nbox > 0) && (pbox->y1 == yThisBand)) : { : nbox--; : pbox++; : nThisBand++; : } : if (nThisBand > nMaxBand) : nMaxBand = nThisBand; : } : return (nMaxBand); :} /* * Total samples for file : "malloc.c" * * 65 0.0708 */ 65 0.0708 : /* malloc_consolidate total: 65 0.0708 */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/os/io.c" * * 60 0.0654 */ :/*********************************************************** : :Copyright 1987, 1989, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : : :******************************************************************/ :/***************************************************************** : * i/o functions : * : * WriteToClient, ReadRequestFromClient : * InsertFakeRequest, ResetCurrentRequest : * : *****************************************************************/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#if 0 :#define DEBUG_COMMUNICATION :#endif :#ifdef WIN32 :#include :#endif :#include :#define XSERV_t :#define TRANS_SERVER :#define TRANS_REOPEN :#include :#include :#include :#if !defined(WIN32) :#ifndef Lynx :#include :#else :#include :#endif :#endif :#include :#define NEED_REPLIES :#include :#include "os.h" :#include "osdep.h" :#include :#include "opaque.h" :#include "dixstruct.h" :#include "misc.h" : :_X_EXPORT CallbackListPtr ReplyCallback; :_X_EXPORT CallbackListPtr FlushCallback; : :static ConnectionInputPtr AllocateInputBuffer(void); :static ConnectionOutputPtr AllocateOutputBuffer(void); :static xReqPtr PeekNextRequest(xReqPtr req, ClientPtr client, Bool readmore); :static void SkipRequests(xReqPtr req, ClientPtr client, int numskipped); : :/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX : * systems are broken and return EWOULDBLOCK when they should return EAGAIN : */ :#ifndef WIN32 :#if defined(EAGAIN) && defined(EWOULDBLOCK) :#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK) :#else :#ifdef EAGAIN :#define ETEST(err) (err == EAGAIN) :#else :#define ETEST(err) (err == EWOULDBLOCK) :#endif :#endif :#else /* WIN32 The socket errorcodes differ from the normal errors*/ :#define ETEST(err) (err == EAGAIN || err == WSAEWOULDBLOCK) :#endif : :static Bool CriticalOutputPending; :static int timesThisConnection = 0; :static ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL; :static ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL; :static OsCommPtr AvailableInput = (OsCommPtr)NULL; : :#define get_req_len(req,cli) ((cli)->swapped ? \ : lswaps((req)->length) : (req)->length) : :#ifdef BIGREQS :#include : :#define get_big_req_len(req,cli) ((cli)->swapped ? \ : lswapl(((xBigReq *)(req))->length) : \ : ((xBigReq *)(req))->length) :#endif : :#define MAX_TIMES_PER 10 : :/* : * A lot of the code in this file manipulates a ConnectionInputPtr: : * : * ----------------------------------------------- : * |------- bufcnt ------->| | | : * | |- gotnow ->| | | : * | |-------- needed ------>| | : * |-----------+--------- size --------+---------->| : * ----------------------------------------------- : * ^ ^ : * | | : * buffer bufptr : * : * buffer is a pointer to the start of the buffer. : * bufptr points to the start of the current request. : * bufcnt counts how many bytes are in the buffer. : * size is the size of the buffer in bytes. : * : * In several of the functions, gotnow and needed are local variables : * that do the following: : * : * gotnow is the number of bytes of the request that we're : * trying to read that are currently in the buffer. : * Typically, gotnow = (buffer + bufcnt) - bufptr : * : * needed = the length of the request that we're trying to : * read. Watch out: needed sometimes counts bytes and sometimes : * counts CARD32's. : */ : : :/***************************************************************** : * ReadRequestFromClient : * Returns one request in client->requestBuffer. The request : * length will be in client->req_len. Return status is: : * : * > 0 if successful, specifies length in bytes of the request : * = 0 if entire request is not yet available : * < 0 if client should be terminated : * : * The request returned must be contiguous so that it can be : * cast in the dispatcher to the correct request type. Because requests : * are variable length, ReadRequestFromClient() must look at the first 4 : * or 8 bytes of a request to determine the length (the request length is : * in the 3rd and 4th bytes of the request unless it is a Big Request : * (see the Big Request Extension), in which case the 3rd and 4th bytes : * are zero and the following 4 bytes are the request length. : * : * Note: in order to make the server scheduler (WaitForSomething()) : * "fair", the ClientsWithInput mask is used. This mask tells which : * clients have FULL requests left in their buffers. Clients with : * partial requests require a read. Basically, client buffers : * are drained before select() is called again. But, we can't keep : * reading from a client that is sending buckets of data (or has : * a partial request) because others clients need to be scheduled. : *****************************************************************/ : :#define YieldControl() \ : { isItTimeToYield = TRUE; \ : timesThisConnection = 0; } :#define YieldControlNoInput() \ : { YieldControl(); \ : FD_CLR(fd, &ClientsWithInput); } :#define YieldControlDeath() \ : { timesThisConnection = 0; } : :int :ReadRequestFromClient(ClientPtr client) 2 0.0022 :{ /* ReadRequestFromClient total: 60 0.0654 */ 3 0.0033 : OsCommPtr oc = (OsCommPtr)client->osPrivate; : ConnectionInputPtr oci = oc->input; : int fd = oc->fd; : unsigned int gotnow, needed; : int result; : register xReq *request; : Bool need_header; :#ifdef BIGREQS : Bool move_header; :#endif : : /* If an input buffer was empty, either free it if it is too big : * or link it into our list of free input buffers. This means that : * different clients can share the same input buffer (at different : * times). This was done to save memory. : */ : : if (AvailableInput) : { : if (AvailableInput != oc) : { : register ConnectionInputPtr aci = AvailableInput->input; : if (aci->size > BUFWATERMARK) : { : xfree(aci->buffer); : xfree(aci); : } : else : { : aci->next = FreeInputs; : FreeInputs = aci; : } : AvailableInput->input = (ConnectionInputPtr)NULL; : } : AvailableInput = (OsCommPtr)NULL; : } : : /* make sure we have an input buffer */ : : if (!oci) : { : if ((oci = FreeInputs)) : { : FreeInputs = oci->next; : } : else if (!(oci = AllocateInputBuffer())) : { : YieldControlDeath(); : return -1; : } : oc->input = oci; : } : : /* advance to start of next request */ : 3 0.0033 : oci->bufptr += oci->lenLastReq; : : need_header = FALSE; :#ifdef BIGREQS : move_header = FALSE; :#endif 6 0.0065 : gotnow = oci->bufcnt + oci->buffer - oci->bufptr; 2 0.0022 : if (gotnow < sizeof(xReq)) : { : /* We don't have an entire xReq yet. Can't tell how big : * the request will be until we get the whole xReq. : */ : needed = sizeof(xReq); : need_header = TRUE; : } : else : { : /* We have a whole xReq. We can tell how big the whole : * request will be unless it is a Big Request. : */ : request = (xReq *)oci->bufptr; 2 0.0022 : needed = get_req_len(request, client); :#ifdef BIGREQS 1 0.0011 : if (!needed && client->big_requests) : { : /* It's a Big Request. */ : move_header = TRUE; : if (gotnow < sizeof(xBigReq)) : { : /* Still need more data to tell just how big. */ : needed = sizeof(xBigReq) >> 2; /* needed is in CARD32s now */ : need_header = TRUE; : } : else : needed = get_big_req_len(request, client); : } :#endif 1 0.0011 : client->req_len = needed; : needed <<= 2; /* needed is in bytes now */ : } : if (gotnow < needed) : { : /* Need to read more data, either so that we can get a : * complete xReq (if need_header is TRUE), a complete : * xBigReq (if move_header is TRUE), or the rest of the : * request (if need_header and move_header are both FALSE). : */ : : oci->lenLastReq = 0; 2 0.0022 : if (needed > MAXBUFSIZE) : { : /* request is too big for us to handle */ : YieldControlDeath(); : return -1; : } : if ((gotnow == 0) || : ((oci->bufptr - oci->buffer + needed) > oci->size)) : { : /* no data, or the request is too big to fit in the buffer */ : : if ((gotnow > 0) && (oci->bufptr != oci->buffer)) : /* save the data we've already read */ : memmove(oci->buffer, oci->bufptr, gotnow); : if (needed > oci->size) : { : /* make buffer bigger to accomodate request */ : char *ibuf; : : ibuf = (char *)xrealloc(oci->buffer, needed); : if (!ibuf) : { : YieldControlDeath(); : return -1; : } : oci->size = needed; : oci->buffer = ibuf; : } : oci->bufptr = oci->buffer; : oci->bufcnt = gotnow; : } : /* XXX this is a workaround. This function is sometimes called : * after the trans_conn has been freed. In this case trans_conn : * will be null. Really ought to restructure things so that we : * never get here in those circumstances. : */ : if (!oc->trans_conn) : { : /* treat as if an error occured on the read, which is what : * used to happen : */ : YieldControlDeath(); : return -1; : } : result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt, : oci->size - oci->bufcnt); : if (result <= 0) : { : if ((result < 0) && ETEST(errno)) : { :#if defined(SVR4) && defined(i386) && !defined(sun) : if (0) :#endif : { : YieldControlNoInput(); : return 0; : } : } : YieldControlDeath(); : return -1; : } : oci->bufcnt += result; : gotnow += result; : /* free up some space after huge requests */ : if ((oci->size > BUFWATERMARK) && : (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE)) : { : char *ibuf; : : ibuf = (char *)xrealloc(oci->buffer, BUFSIZE); : if (ibuf) : { : oci->size = BUFSIZE; : oci->buffer = ibuf; : oci->bufptr = ibuf + oci->bufcnt - gotnow; : } : } : if (need_header && gotnow >= needed) : { : /* We wanted an xReq, now we've gotten it. */ : request = (xReq *)oci->bufptr; : needed = get_req_len(request, client); :#ifdef BIGREQS : if (!needed && client->big_requests) : { : move_header = TRUE; : if (gotnow < sizeof(xBigReq)) : needed = sizeof(xBigReq) >> 2; : else : needed = get_big_req_len(request, client); : } :#endif : client->req_len = needed; : needed <<= 2; : } : if (gotnow < needed) : { : /* Still don't have enough; punt. */ : YieldControlNoInput(); : return 0; : } : } 1 0.0011 : if (needed == 0) : { :#ifdef BIGREQS : if (client->big_requests) : needed = sizeof(xBigReq); : else :#endif : needed = sizeof(xReq); : } 3 0.0033 : oci->lenLastReq = needed; : : /* : * Check to see if client has at least one whole request in the : * buffer beyond the request we're returning to the caller. : * If there is only a partial request, treat like buffer : * is empty so that select() will be called again and other clients : * can get into the queue. : */ : 1 0.0011 : gotnow -= needed; : if (gotnow >= sizeof(xReq)) : { 1 0.0011 : request = (xReq *)(oci->bufptr + needed); 9 0.0098 : if (gotnow >= (result = (get_req_len(request, client) << 2)) :#ifdef BIGREQS : && (result || : (client->big_requests && : (gotnow >= sizeof(xBigReq) && : gotnow >= (get_big_req_len(request, client) << 2)))) :#endif : ) 11 0.0120 : FD_SET(fd, &ClientsWithInput); : else : { :#ifdef SMART_SCHEDULE 1 0.0011 : if (!SmartScheduleDisable) : FD_CLR(fd, &ClientsWithInput); : else :#endif : YieldControlNoInput(); : } : } : else : { : if (!gotnow) : AvailableInput = oc; :#ifdef SMART_SCHEDULE : if (!SmartScheduleDisable) : FD_CLR(fd, &ClientsWithInput); : else :#endif : YieldControlNoInput(); : } :#ifdef SMART_SCHEDULE 3 0.0033 : if (SmartScheduleDisable) :#endif : if (++timesThisConnection >= MAX_TIMES_PER) : YieldControl(); :#ifdef BIGREQS : if (move_header) : { : request = (xReq *)oci->bufptr; : oci->bufptr += (sizeof(xBigReq) - sizeof(xReq)); : *(xReq *)oci->bufptr = *request; : oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq)); : client->req_len -= (sizeof(xBigReq) - sizeof(xReq)) >> 2; : } :#endif 3 0.0033 : client->requestBuffer = (pointer)oci->bufptr; :#ifdef DEBUG_COMMUNICATION : { : xReq *req = client->requestBuffer; : ErrorF("REQUEST: ClientIDX: %i, type: 0x%x data: 0x%x len: %i\n", : client->index,req->reqType,req->data,req->length); : } :#endif : return needed; 5 0.0054 :} : :/***************************************************************** : * InsertFakeRequest : * Splice a consed up (possibly partial) request in as the next request. : * : **********************/ : :Bool :InsertFakeRequest(ClientPtr client, char *data, int count) :{ : OsCommPtr oc = (OsCommPtr)client->osPrivate; : ConnectionInputPtr oci = oc->input; : int fd = oc->fd; : int gotnow, moveup; : : if (AvailableInput) : { : if (AvailableInput != oc) : { : ConnectionInputPtr aci = AvailableInput->input; : if (aci->size > BUFWATERMARK) : { : xfree(aci->buffer); : xfree(aci); : } : else : { : aci->next = FreeInputs; : FreeInputs = aci; : } : AvailableInput->input = (ConnectionInputPtr)NULL; : } : AvailableInput = (OsCommPtr)NULL; : } : if (!oci) : { : if ((oci = FreeInputs)) : FreeInputs = oci->next; : else if (!(oci = AllocateInputBuffer())) : return FALSE; : oc->input = oci; : } : oci->bufptr += oci->lenLastReq; : oci->lenLastReq = 0; : gotnow = oci->bufcnt + oci->buffer - oci->bufptr; : if ((gotnow + count) > oci->size) : { : char *ibuf; : : ibuf = (char *)xrealloc(oci->buffer, gotnow + count); : if (!ibuf) : return(FALSE); : oci->size = gotnow + count; : oci->buffer = ibuf; : oci->bufptr = ibuf + oci->bufcnt - gotnow; : } : moveup = count - (oci->bufptr - oci->buffer); : if (moveup > 0) : { : if (gotnow > 0) : memmove(oci->bufptr + moveup, oci->bufptr, gotnow); : oci->bufptr += moveup; : oci->bufcnt += moveup; : } : memmove(oci->bufptr - count, data, count); : oci->bufptr -= count; : gotnow += count; : if ((gotnow >= sizeof(xReq)) && : (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2))) : FD_SET(fd, &ClientsWithInput); : else : YieldControlNoInput(); : return(TRUE); :} : :/***************************************************************** : * ResetRequestFromClient : * Reset to reexecute the current request, and yield. : * : **********************/ : :_X_EXPORT void :ResetCurrentRequest(ClientPtr client) :{ : OsCommPtr oc = (OsCommPtr)client->osPrivate; : register ConnectionInputPtr oci = oc->input; : int fd = oc->fd; : register xReq *request; : int gotnow, needed; : if (AvailableInput == oc) : AvailableInput = (OsCommPtr)NULL; : oci->lenLastReq = 0; : gotnow = oci->bufcnt + oci->buffer - oci->bufptr; : if (gotnow < sizeof(xReq)) : { : YieldControlNoInput(); : } : else : { : request = (xReq *)oci->bufptr; : needed = get_req_len(request, client); :#ifdef BIGREQS : if (!needed && client->big_requests) : { : oci->bufptr -= sizeof(xBigReq) - sizeof(xReq); : *(xReq *)oci->bufptr = *request; : ((xBigReq *)oci->bufptr)->length = client->req_len; : if (client->swapped) : { : char n; : swapl(&((xBigReq *)oci->bufptr)->length, n); : } : } :#endif : if (gotnow >= (needed << 2)) : { : if (FD_ISSET(fd, &AllClients)) : { : FD_SET(fd, &ClientsWithInput); : } : else : { : FD_SET(fd, &IgnoredClientsWithInput); : } : YieldControl(); : } : else : YieldControlNoInput(); : } :} : : : :/***************************************************************** : * PeekNextRequest and SkipRequests were implemented to support DBE : * idioms, but can certainly be used outside of DBE. There are two : * related macros in os.h, ReqLen and CastxReq. See the porting : * layer document for more details. : * : **********************/ : : :/***************************************************************** : * PeekNextRequest : * lets you look ahead at the unexecuted requests in a : * client's request buffer. : * : * Note: this implementation of PeekNextRequest ignores the : * readmore parameter. : * : **********************/ : :static xReqPtr :PeekNextRequest( : xReqPtr req, /* request we're starting from */ : ClientPtr client, /* client whose requests we're skipping */ : Bool readmore) /* attempt to read more if next request isn't there? */ :{ : register ConnectionInputPtr oci = ((OsCommPtr)client->osPrivate)->input; : xReqPtr pnextreq; : int needed, gotnow, reqlen; : : if (!oci) return NULL; : : if (!req) : { : /* caller wants the request after the one currently being executed */ : pnextreq = (xReqPtr) : (((CARD32 *)client->requestBuffer) + client->req_len); : } : else : { : /* caller wants the request after the one specified by req */ : reqlen = get_req_len(req, client); :#ifdef BIGREQS : if (!reqlen) reqlen = get_big_req_len(req, client); :#endif : pnextreq = (xReqPtr)(((char *)req) + (reqlen << 2)); : } : : /* see how much of the next request we have available */ : : gotnow = oci->bufcnt - (((char *)pnextreq) - oci->buffer); : : if (gotnow < sizeof(xReq)) : return NULL; : : needed = get_req_len(pnextreq, client) << 2; :#ifdef BIGREQS : if (!needed) : { : /* it's a big request */ : if (gotnow < sizeof(xBigReq)) : return NULL; : needed = get_big_req_len(pnextreq, client) << 2; : } :#endif : : /* if we have less than we need, return NULL */ : : return (gotnow < needed) ? NULL : pnextreq; :} : :/***************************************************************** : * SkipRequests : * lets you skip over some of the requests in a client's : * request buffer. Presumably the caller has used PeekNextRequest : * to examine the requests being skipped and has performed whatever : * actions they dictate. : * : **********************/ : :_X_EXPORT CallbackListPtr SkippedRequestsCallback = NULL; : :static void :SkipRequests( : xReqPtr req, /* last request being skipped */ : ClientPtr client, /* client whose requests we're skipping */ : int numskipped) /* how many requests we're skipping */ :{ : OsCommPtr oc = (OsCommPtr)client->osPrivate; : register ConnectionInputPtr oci = oc->input; : int reqlen; : : /* see if anyone wants to snoop the skipped requests */ : : if (SkippedRequestsCallback) : { : SkippedRequestInfoRec skipinfo; : skipinfo.req = req; : skipinfo.client = client; : skipinfo.numskipped = numskipped; : CallCallbacks(&SkippedRequestsCallback, &skipinfo); : } : : /* adjust the sequence number */ : client->sequence += numskipped; : : /* twiddle the oci to skip over the requests */ : : reqlen = get_req_len(req, client); :#ifdef BIGREQS : if (!reqlen) reqlen = get_big_req_len(req, client); :#endif : reqlen <<= 2; : oci->bufptr = (char *)req; : oci->lenLastReq = reqlen; : : /* see if any requests left in the buffer */ : : if ( ((char *)req + reqlen) == (oci->buffer + oci->bufcnt) ) : { : /* no requests; mark input buffer as available and client : * as having no input : */ : int fd = oc->fd; : AvailableInput = oc; : YieldControlNoInput(); : } :} : : : /* lookup table for adding padding bytes to data that is read from : or written to the X socket. */ :static int padlength[4] = {0, 3, 2, 1}; : : /******************** : * FlushAllOutput() : * Flush all clients with output. However, if some client still : * has input in the queue (more requests), then don't flush. This : * will prevent the output queue from being flushed every time around : * the round robin queue. Now, some say that it SHOULD be flushed : * every time around, but... : * : **********************/ : :void :FlushAllOutput(void) :{ : register int index, base; : register fd_mask mask; /* raphael */ : OsCommPtr oc; : register ClientPtr client; : Bool newoutput = NewOutputPending; :#if defined(WIN32) : fd_set newOutputPending; :#endif : : if (FlushCallback) : CallCallbacks(&FlushCallback, NULL); : : if (!newoutput) : return; : : /* : * It may be that some client still has critical output pending, : * but he is not yet ready to receive it anyway, so we will : * simply wait for the select to tell us when he's ready to receive. : */ : CriticalOutputPending = FALSE; : NewOutputPending = FALSE; : :#ifndef WIN32 : for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) : { : mask = OutputPending.fds_bits[ base ]; : OutputPending.fds_bits[ base ] = 0; : while (mask) : { : index = ffs(mask) - 1; : mask &= ~lowbit(mask); : if ((index = ConnectionTranslation[(base * (sizeof(fd_mask)*8)) + index]) == 0) : continue; : client = clients[index]; : if (client->clientGone) : continue; : oc = (OsCommPtr)client->osPrivate; : if (FD_ISSET(oc->fd, &ClientsWithInput)) : { : FD_SET(oc->fd, &OutputPending); /* set the bit again */ : NewOutputPending = TRUE; : } : else : (void)FlushClient(client, oc, (char *)NULL, 0); : } : } :#else /* WIN32 */ : FD_ZERO(&newOutputPending); : for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++) : { : index = XFD_FD(&OutputPending, base); : if ((index = GetConnectionTranslation(index)) == 0) : continue; : client = clients[index]; : if (client->clientGone) : continue; : oc = (OsCommPtr)client->osPrivate; : if (FD_ISSET(oc->fd, &ClientsWithInput)) : { : FD_SET(oc->fd, &newOutputPending); /* set the bit again */ : NewOutputPending = TRUE; : } : else : (void)FlushClient(client, oc, (char *)NULL, 0); : } : XFD_COPYSET(&newOutputPending, &OutputPending); :#endif /* WIN32 */ :} : :void :FlushIfCriticalOutputPending(void) :{ : if (CriticalOutputPending) : FlushAllOutput(); :} : :_X_EXPORT void :SetCriticalOutputPending(void) :{ : CriticalOutputPending = TRUE; :} : :/***************** : * WriteToClient : * Copies buf into ClientPtr.buf if it fits (with padding), else : * flushes ClientPtr.buf and buf to client. As of this writing, : * every use of WriteToClient is cast to void, and the result : * is ignored. Potentially, this could be used by requests : * that are sending several chunks of data and want to break : * out of a loop on error. Thus, we will leave the type of : * this routine as int. : *****************/ : :_X_EXPORT int :WriteToClient (ClientPtr who, int count, char *buf) :{ : OsCommPtr oc = (OsCommPtr)who->osPrivate; : ConnectionOutputPtr oco = oc->output; : int padBytes; :#ifdef DEBUG_COMMUNICATION : Bool multicount = FALSE; :#endif : if (!count) : return(0); :#ifdef DEBUG_COMMUNICATION : { : char info[128]; : xError *err; : xGenericReply *rep; : xEvent *ev; : : if (!who->replyBytesRemaining) { : switch(buf[0]) { : case X_Reply: : rep = (xGenericReply*)buf; : if (rep->sequenceNumber == who->sequence) { : snprintf(info,127,"Xreply: type: 0x%x data: 0x%x " : "len: %i seq#: 0x%x", rep->type, rep->data1, : rep->length, rep->sequenceNumber); : multicount = TRUE; : } : break; : case X_Error: : err = (xError*)buf; : snprintf(info,127,"Xerror: Code: 0x%x resID: 0x%x maj: 0x%x " : "min: %x", err->errorCode,err->resourceID, : err->minorCode,err->majorCode); : break; : default: : if ((buf[0] & 0x7f) == KeymapNotify) : snprintf(info,127,"KeymapNotifyEvent: %i",buf[0]); : else { : ev = (xEvent*)buf; : snprintf(info,127,"XEvent: type: 0x%x detail: 0x%x " : "seq#: 0x%x", ev->u.u.type, ev->u.u.detail, : ev->u.u.sequenceNumber); : } : } : ErrorF("REPLY: ClientIDX: %i %s\n",who->index, info); : } else : multicount = TRUE; : } :#endif : : if (!oco) : { : if ((oco = FreeOutputs)) : { : FreeOutputs = oco->next; : } : else if (!(oco = AllocateOutputBuffer())) : { : if (oc->trans_conn) { : _XSERVTransDisconnect(oc->trans_conn); : _XSERVTransClose(oc->trans_conn); : oc->trans_conn = NULL; : } : MarkClientException(who); : return -1; : } : oc->output = oco; : } : : padBytes = padlength[count & 3]; : : if(ReplyCallback) : { : ReplyInfoRec replyinfo; : : replyinfo.client = who; : replyinfo.replyData = buf; : replyinfo.dataLenBytes = count + padBytes; : if (who->replyBytesRemaining) : { /* still sending data of an earlier reply */ : who->replyBytesRemaining -= count + padBytes; : replyinfo.startOfReply = FALSE; : replyinfo.bytesRemaining = who->replyBytesRemaining; : CallCallbacks((&ReplyCallback), (pointer)&replyinfo); : } : else if (who->clientState == ClientStateRunning : && buf[0] == X_Reply) : { /* start of new reply */ : CARD32 replylen; : unsigned long bytesleft; : char n; : : replylen = ((xGenericReply *)buf)->length; : if (who->swapped) : swapl(&replylen, n); : bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes; : replyinfo.startOfReply = TRUE; : replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft; : CallCallbacks((&ReplyCallback), (pointer)&replyinfo); : } : } :#ifdef DEBUG_COMMUNICATION : else if (multicount) { : if (who->replyBytesRemaining) { : who->replyBytesRemaining -= (count + padBytes); : } else { : CARD32 replylen; : replylen = ((xGenericReply *)buf)->length; : who->replyBytesRemaining = : (replylen * 4) + SIZEOF(xReply) - count - padBytes; : } : } :#endif : if (oco->count + count + padBytes > oco->size) : { : FD_CLR(oc->fd, &OutputPending); : if(!XFD_ANYSET(&OutputPending)) { : CriticalOutputPending = FALSE; : NewOutputPending = FALSE; : } : return FlushClient(who, oc, buf, count); : } : : NewOutputPending = TRUE; : FD_SET(oc->fd, &OutputPending); : memmove((char *)oco->buf + oco->count, buf, count); : oco->count += count + padBytes; : return(count); :} : : /******************** : * FlushClient() : * If the client isn't keeping up with us, then we try to continue : * buffering the data and set the apropriate bit in ClientsWritable : * (which is used by WaitFor in the select). If the connection yields : * a permanent error, or we can't allocate any more space, we then : * close the connection. : * : **********************/ : :int :FlushClient(ClientPtr who, OsCommPtr oc, char *extraBuf, int extraCount) :{ : ConnectionOutputPtr oco = oc->output; : int connection = oc->fd; : XtransConnInfo trans_conn = oc->trans_conn; : struct iovec iov[3]; : static char padBuffer[3]; : long written; : long padsize; : long notWritten; : long todo; : : if (!oco) : return 0; : written = 0; : padsize = padlength[extraCount & 3]; : notWritten = oco->count + extraCount + padsize; : todo = notWritten; : while (notWritten) { : long before = written; /* amount of whole thing written */ : long remain = todo; /* amount to try this time, <= notWritten */ : int i = 0; : long len; : : /* You could be very general here and have "in" and "out" iovecs : * and write a loop without using a macro, but what the heck. This : * translates to: : * : * how much of this piece is new? : * if more new then we are trying this time, clamp : * if nothing new : * then bump down amount already written, for next piece : * else put new stuff in iovec, will need all of next piece : * : * Note that todo had better be at least 1 or else we'll end up : * writing 0 iovecs. : */ :#define InsertIOV(pointer, length) \ : len = (length) - before; \ : if (len > remain) \ : len = remain; \ : if (len <= 0) { \ : before = (-len); \ : } else { \ : iov[i].iov_len = len; \ : iov[i].iov_base = (pointer) + before; \ : i++; \ : remain -= len; \ : before = 0; \ : } : : InsertIOV ((char *)oco->buf, oco->count) : InsertIOV (extraBuf, extraCount) : InsertIOV (padBuffer, padsize) : : errno = 0; : if (trans_conn && (len = _XSERVTransWritev(trans_conn, iov, i)) >= 0) : { : written += len; : notWritten -= len; : todo = notWritten; : } : else if (ETEST(errno) :#ifdef SUNSYSV /* check for another brain-damaged OS bug */ : || (errno == 0) :#endif :#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ : || ((errno == EMSGSIZE) && (todo == 1)) :#endif : ) : { : /* If we've arrived here, then the client is stuffed to the gills : and not ready to accept more. Make a note of it and buffer : the rest. */ : FD_SET(connection, &ClientsWriteBlocked); : AnyClientsWriteBlocked = TRUE; : : if (written < oco->count) : { : if (written > 0) : { : oco->count -= written; : memmove((char *)oco->buf, : (char *)oco->buf + written, : oco->count); : written = 0; : } : } : else : { : written -= oco->count; : oco->count = 0; : } : : if (notWritten > oco->size) : { : unsigned char *obuf; : : obuf = (unsigned char *)xrealloc(oco->buf, : notWritten + BUFSIZE); : if (!obuf) : { : _XSERVTransDisconnect(oc->trans_conn); : _XSERVTransClose(oc->trans_conn); : oc->trans_conn = NULL; : MarkClientException(who); : oco->count = 0; : return(-1); : } : oco->size = notWritten + BUFSIZE; : oco->buf = obuf; : } : : /* If the amount written extended into the padBuffer, then the : difference "extraCount - written" may be less than 0 */ : if ((len = extraCount - written) > 0) : memmove ((char *)oco->buf + oco->count, : extraBuf + written, : len); : : oco->count = notWritten; /* this will include the pad */ : /* return only the amount explicitly requested */ : return extraCount; : } :#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ : else if (errno == EMSGSIZE) : { : todo >>= 1; : } :#endif : else : { : if (oc->trans_conn) : { : _XSERVTransDisconnect(oc->trans_conn); : _XSERVTransClose(oc->trans_conn); : oc->trans_conn = NULL; : } : MarkClientException(who); : oco->count = 0; : return(-1); : } : } : : /* everything was flushed out */ : oco->count = 0; : /* check to see if this client was write blocked */ : if (AnyClientsWriteBlocked) : { : FD_CLR(oc->fd, &ClientsWriteBlocked); : if (! XFD_ANYSET(&ClientsWriteBlocked)) : AnyClientsWriteBlocked = FALSE; : } : if (oco->size > BUFWATERMARK) : { : xfree(oco->buf); : xfree(oco); : } : else : { : oco->next = FreeOutputs; : FreeOutputs = oco; : } : oc->output = (ConnectionOutputPtr)NULL; : return extraCount; /* return only the amount explicitly requested */ :} : :static ConnectionInputPtr :AllocateInputBuffer(void) :{ : ConnectionInputPtr oci; : : oci = (ConnectionInputPtr)xalloc(sizeof(ConnectionInput)); : if (!oci) : return (ConnectionInputPtr)NULL; : oci->buffer = (char *)xalloc(BUFSIZE); : if (!oci->buffer) : { : xfree(oci); : return (ConnectionInputPtr)NULL; : } : oci->size = BUFSIZE; : oci->bufptr = oci->buffer; : oci->bufcnt = 0; : oci->lenLastReq = 0; : return oci; :} : :static ConnectionOutputPtr :AllocateOutputBuffer(void) :{ : ConnectionOutputPtr oco; : : oco = (ConnectionOutputPtr)xalloc(sizeof(ConnectionOutput)); : if (!oco) : return (ConnectionOutputPtr)NULL; : oco->buf = (unsigned char *) xalloc(BUFSIZE); : if (!oco->buf) : { : xfree(oco); : return (ConnectionOutputPtr)NULL; : } : oco->size = BUFSIZE; : oco->count = 0; : return oco; :} : :void :FreeOsBuffers(OsCommPtr oc) :{ : ConnectionInputPtr oci; : ConnectionOutputPtr oco; : : if (AvailableInput == oc) : AvailableInput = (OsCommPtr)NULL; : if ((oci = oc->input)) : { : if (FreeInputs) : { : xfree(oci->buffer); : xfree(oci); : } : else : { : FreeInputs = oci; : oci->next = (ConnectionInputPtr)NULL; : oci->bufptr = oci->buffer; : oci->bufcnt = 0; : oci->lenLastReq = 0; : } : } : if ((oco = oc->output)) : { : if (FreeOutputs) : { : xfree(oco->buf); : xfree(oco); : } : else : { : FreeOutputs = oco; : oco->next = (ConnectionOutputPtr)NULL; : oco->count = 0; : } : } :} : :void :ResetOsBuffers(void) :{ : ConnectionInputPtr oci; : ConnectionOutputPtr oco; : : while ((oci = FreeInputs)) : { : FreeInputs = oci->next; : xfree(oci->buffer); : xfree(oci); : } : while ((oco = FreeOutputs)) : { : FreeOutputs = oco->next; : xfree(oco->buf); : xfree(oco); : } :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/dix/dispatch.c" * * 60 0.0654 */ :/************************************************************ : :Copyright 1987, 1989, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :********************************************************/ : :/* The panoramix components contained the following notice */ :/***************************************************************** : :Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. : :Permission is hereby granted, free of charge, to any person obtaining a copy :of this software and associated documentation files (the "Software"), to deal :in the Software without restriction, including without limitation the rights :to use, copy, modify, merge, publish, distribute, sublicense, and/or sell :copies of the Software. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL :DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, :BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, :WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR :IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of Digital Equipment Corporation :shall not be used in advertising or otherwise to promote the sale, use or other :dealings in this Software without prior written authorization from Digital :Equipment Corporation. : :******************************************************************/ : :/* XSERVER_DTRACE additions: : * Copyright 2005-2006 Sun Microsystems, Inc. All rights reserved. : * : * Permission is hereby granted, free of charge, to any person obtaining a : * copy of this software and associated documentation files (the : * "Software"), to deal in the Software without restriction, including : * without limitation the rights to use, copy, modify, merge, publish, : * distribute, and/or sell copies of the Software, and to permit persons : * to whom the Software is furnished to do so, provided that the above : * copyright notice(s) and this permission notice appear in all copies of : * the Software and that both the above copyright notice(s) and this : * permission notice appear in supporting documentation. : * : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT : * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR : * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL : * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING : * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION : * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : * : * Except as contained in this notice, the name of a copyright holder : * shall not be used in advertising or otherwise to promote the sale, use : * or other dealings in this Software without prior written authorization : * of the copyright holder. : */ : : : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#ifdef PANORAMIX_DEBUG :#include :int ProcInitialConnection(); :#endif : :#include "windowstr.h" :#include :#include "dixfontstr.h" :#include "gcstruct.h" :#include "selection.h" :#include "colormapst.h" :#include "cursorstr.h" :#include "scrnintstr.h" :#include "opaque.h" :#include "input.h" :#include "servermd.h" :#include "extnsionst.h" :#include "dixfont.h" :#include "dispatch.h" :#include "swaprep.h" :#include "swapreq.h" :#ifdef PANORAMIX :#include "panoramiX.h" :#include "panoramiXsrv.h" :#endif :#include "xace.h" :#ifdef XAPPGROUP :#include "appgroup.h" :#endif :#ifdef XKB :#ifndef XKB_IN_SERVER :#define XKB_IN_SERVER :#endif :#include "inputstr.h" :#include :#endif : :#ifdef XSERVER_DTRACE :#include :typedef const char *string; :#include "Xserver-dtrace.h" : :char *RequestNames[256]; :static void LoadRequestNames(void); :static void FreeRequestNames(void); :#define GetRequestName(i) (RequestNames[i]) :#endif : :#define mskcnt ((MAXCLIENTS + 31) / 32) :#define BITMASK(i) (1U << ((i) & 31)) :#define MASKIDX(i) ((i) >> 5) :#define MASKWORD(buf, i) buf[MASKIDX(i)] :#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) :#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) :#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) : :extern xConnSetupPrefix connSetupPrefix; :extern char *ConnectionInfo; : :_X_EXPORT Selection *CurrentSelections; :_X_EXPORT int NumCurrentSelections; :CallbackListPtr SelectionCallback = NULL; : :static ClientPtr grabClient; :#define GrabNone 0 :#define GrabActive 1 :#define GrabKickout 2 :static int grabState = GrabNone; :static long grabWaiters[mskcnt]; :_X_EXPORT CallbackListPtr ServerGrabCallback = NULL; :HWEventQueuePtr checkForInput[2]; :extern int connBlockScreenStart; : :static void KillAllClients(void); : :static void DeleteClientFromAnySelections(ClientPtr client); : :static int nextFreeClientID; /* always MIN free client ID */ : :static int nClients; /* number of authorized clients */ : :_X_EXPORT CallbackListPtr ClientStateCallback; : :/* dispatchException & isItTimeToYield must be declared volatile since they : * are modified by signal handlers - otherwise optimizer may assume it doesn't : * need to actually check value in memory when used and may miss changes from : * signal handlers. : */ :_X_EXPORT volatile char dispatchException = 0; :_X_EXPORT volatile char isItTimeToYield; : :/* Various of the DIX function interfaces were not designed to allow : * the client->errorValue to be set on BadValue and other errors. : * Rather than changing interfaces and breaking untold code we introduce : * a new global that dispatch can use. : */ :XID clientErrorValue; /* XXX this is a kludge */ : :#define SAME_SCREENS(a, b) (\ : (a.pScreen == b.pScreen)) : :_X_EXPORT void :SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) :{ : checkForInput[0] = c0; : checkForInput[1] = c1; :} : :_X_EXPORT void :UpdateCurrentTime(void) :{ : TimeStamp systime; : : /* To avoid time running backwards, we must call GetTimeInMillis before : * calling ProcessInputEvents. : */ : systime.months = currentTime.months; : systime.milliseconds = GetTimeInMillis(); : if (systime.milliseconds < currentTime.milliseconds) : systime.months++; : if (*checkForInput[0] != *checkForInput[1]) : ProcessInputEvents(); : if (CompareTimeStamps(systime, currentTime) == LATER) : currentTime = systime; :} : :/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ :_X_EXPORT void :UpdateCurrentTimeIf(void) :{ : TimeStamp systime; : : systime.months = currentTime.months; : systime.milliseconds = GetTimeInMillis(); : if (systime.milliseconds < currentTime.milliseconds) : systime.months++; : if (*checkForInput[0] == *checkForInput[1]) : currentTime = systime; :} : :void :InitSelections(void) :{ : if (CurrentSelections) : xfree(CurrentSelections); : CurrentSelections = (Selection *)NULL; : NumCurrentSelections = 0; :} : :void :FlushClientCaches(XID id) :{ /* FlushClientCaches total: 4 0.0044 */ : int i; : ClientPtr client; : : client = clients[CLIENT_ID(id)]; 1 0.0011 : if (client == NullClient) : return ; 1 0.0011 : for (i=0; ilastDrawableID == id) : { : client->lastDrawableID = WindowTable[0]->drawable.id; : client->lastDrawable = (DrawablePtr)WindowTable[0]; : } : else if (client->lastGCID == id) : { : client->lastGCID = INVALID; : client->lastGC = (GCPtr)NULL; : } : } : } 2 0.0022 :} :#ifdef SMART_SCHEDULE : :#undef SMART_DEBUG : :#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ :#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ : :Bool SmartScheduleDisable = FALSE; :long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; :long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; :long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; :long SmartScheduleTime; :static ClientPtr SmartLastClient; :static int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; : :#ifdef SMART_DEBUG :long SmartLastPrint; :#endif : :void Dispatch(void); :void InitProcVectors(void); : :static int :SmartScheduleClient (int *clientReady, int nready) :{ : ClientPtr pClient; : int i; : int client; : int bestPrio, best = 0; : int bestRobin, robin; : long now = SmartScheduleTime; : long idle; : : bestPrio = -0x7fffffff; : bestRobin = 0; : idle = 2 * SmartScheduleSlice; : for (i = 0; i < nready; i++) : { : client = clientReady[i]; : pClient = clients[client]; : /* Praise clients which are idle */ : if ((now - pClient->smart_check_tick) >= idle) : { : if (pClient->smart_priority < 0) : pClient->smart_priority++; : } : pClient->smart_check_tick = now; : : /* check priority to select best client */ : robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; : if (pClient->smart_priority > bestPrio || : (pClient->smart_priority == bestPrio && robin > bestRobin)) : { : bestPrio = pClient->smart_priority; : bestRobin = robin; : best = client; : } :#ifdef SMART_DEBUG : if ((now - SmartLastPrint) >= 5000) : fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); :#endif : } :#ifdef SMART_DEBUG : if ((now - SmartLastPrint) >= 5000) : { : fprintf (stderr, " use %2d\n", best); : SmartLastPrint = now; : } :#endif : pClient = clients[best]; : SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; : /* : * Set current client pointer : */ : if (SmartLastClient != pClient) : { : pClient->smart_start_tick = now; : SmartLastClient = pClient; : } : /* : * Adjust slice : */ : if (nready == 1) : { : /* : * If it's been a long time since another client : * has run, bump the slice up to get maximal : * performance from a single client : */ : if ((now - pClient->smart_start_tick) > 1000 && : SmartScheduleSlice < SmartScheduleMaxSlice) : { : SmartScheduleSlice += SmartScheduleInterval; : } : } : else : { : SmartScheduleSlice = SmartScheduleInterval; : } : return best; :} :#endif : :#define MAJOROP ((xReq *)client->requestBuffer)->reqType : :void :Dispatch(void) :{ /* Dispatch total: 37 0.0403 */ : int *clientReady; /* array of request ready clients */ : int result; : ClientPtr client; : int nready; : HWEventQueuePtr* icheck = checkForInput; :#ifdef SMART_SCHEDULE : long start_tick; :#endif : : nextFreeClientID = 1; : InitSelections(); : nClients = 0; : : clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); : if (!clientReady) : return; : :#ifdef XSERVER_DTRACE : LoadRequestNames(); :#endif : : while (!dispatchException) : { : if (*icheck[0] != *icheck[1]) : { : ProcessInputEvents(); : FlushIfCriticalOutputPending(); : } : : nready = WaitForSomething(clientReady); : :#ifdef SMART_SCHEDULE : if (nready && !SmartScheduleDisable) : { : clientReady[0] = SmartScheduleClient (clientReady, nready); : nready = 1; : } :#endif : /***************** : * Handle events in round robin fashion, doing input between : * each round : *****************/ : : while (!dispatchException && (--nready >= 0)) : { : client = clients[clientReady[nready]]; : if (! client) : { : /* KillClient can cause this to happen */ : continue; : } : /* GrabServer activation can cause this to be true */ : if (grabState == GrabKickout) : { : grabState = GrabActive; : break; : } : isItTimeToYield = FALSE; : : requestingClient = client; :#ifdef SMART_SCHEDULE : start_tick = SmartScheduleTime; :#endif 1 0.0011 : while (!isItTimeToYield) : { 8 0.0087 : if (*icheck[0] != *icheck[1]) : { : ProcessInputEvents(); : FlushIfCriticalOutputPending(); : } :#ifdef SMART_SCHEDULE 6 0.0065 : if (!SmartScheduleDisable && : (SmartScheduleTime - start_tick) >= SmartScheduleSlice) : { : /* Penalize clients which consume ticks */ : if (client->smart_priority > SMART_MIN_PRIORITY) : client->smart_priority--; : break; : } :#endif : /* now, finally, deal with client requests */ : 2 0.0022 : result = ReadRequestFromClient(client); 2 0.0022 : if (result <= 0) : { : if (result < 0) : CloseDownClient(client); : break; : } : 2 0.0022 : client->sequence++; :#ifdef DEBUG : if (client->requestLogIndex == MAX_REQUEST_LOG) : client->requestLogIndex = 0; : client->requestLog[client->requestLogIndex] = MAJOROP; : client->requestLogIndex++; :#endif :#ifdef XSERVER_DTRACE : XSERVER_REQUEST_START(GetRequestName(MAJOROP), MAJOROP, : ((xReq *)client->requestBuffer)->length, : client->index, client->requestBuffer); :#endif 4 0.0044 : if (result > (maxBigRequestSize << 2)) : result = BadLength; : else { : XaceHook(XACE_AUDIT_BEGIN, client); 3 0.0033 : result = (* client->requestVector[MAJOROP])(client); 8 0.0087 : XaceHook(XACE_AUDIT_END, client, result); : } :#ifdef XSERVER_DTRACE : XSERVER_REQUEST_DONE(GetRequestName(MAJOROP), MAJOROP, : client->sequence, client->index, result); :#endif : 1 0.0011 : if (result != Success) : { : if (client->noClientException != Success) : CloseDownClient(client); : else : SendErrorToClient(client, MAJOROP, : MinorOpcodeOfRequest(client), : client->errorValue, result); : break; : } :#ifdef DAMAGEEXT : FlushIfCriticalOutputPending (); :#endif : } : FlushAllOutput(); :#ifdef SMART_SCHEDULE : client = clients[clientReady[nready]]; : if (client) : client->smart_stop_tick = SmartScheduleTime; :#endif : requestingClient = NULL; : } : dispatchException &= ~DE_PRIORITYCHANGE; : } :#if defined(DDXBEFORERESET) : ddxBeforeReset (); :#endif : KillAllClients(); : DEALLOCATE_LOCAL(clientReady); : dispatchException &= ~DE_RESET; :#ifdef XSERVER_DTRACE : FreeRequestNames(); :#endif :} : :#undef MAJOROP : :_X_EXPORT int :ProcBadRequest(ClientPtr client) :{ : return (BadRequest); :} : :int :ProcCreateWindow(ClientPtr client) :{ : WindowPtr pParent, pWin; : REQUEST(xCreateWindowReq); : int result, len, rc; : : REQUEST_AT_LEAST_SIZE(xCreateWindowReq); : : LEGAL_NEW_RESOURCE(stuff->wid, client); : rc = dixLookupWindow(&pParent, stuff->parent, client, DixWriteAccess); : if (rc != Success) : return rc; : len = client->req_len - (sizeof(xCreateWindowReq) >> 2); : if (Ones(stuff->mask) != len) : return BadLength; : if (!stuff->width || !stuff->height) : { : client->errorValue = 0; : return BadValue; : } : pWin = CreateWindow(stuff->wid, pParent, stuff->x, : stuff->y, stuff->width, stuff->height, : stuff->borderWidth, stuff->class, : stuff->mask, (XID *) &stuff[1], : (int)stuff->depth, : client, stuff->visual, &result); : if (pWin) : { : Mask mask = pWin->eventMask; : : pWin->eventMask = 0; /* subterfuge in case AddResource fails */ : if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) : return BadAlloc; : pWin->eventMask = mask; : } : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); :} : :int :ProcChangeWindowAttributes(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xChangeWindowAttributesReq); : int result; : int len, rc; : : REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); : rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); : if (rc != Success) : return rc; : len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); : if (len != Ones(stuff->valueMask)) : return BadLength; : result = ChangeWindowAttributes(pWin, : stuff->valueMask, : (XID *) &stuff[1], : client); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); :} : :int :ProcGetWindowAttributes(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xResourceReq); : xGetWindowAttributesReply wa; : int rc; : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess); : if (rc != Success) : return rc; : GetWindowAttributes(pWin, client, &wa); : WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); : return(client->noClientException); :} : :int :ProcDestroyWindow(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xResourceReq); : int rc; : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess); : if (rc != Success) : return rc; : if (pWin->parent) : FreeResource(stuff->id, RT_NONE); : return(client->noClientException); :} : :int :ProcDestroySubwindows(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xResourceReq); : int rc; : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess); : if (rc != Success) : return rc; : DestroySubwindows(pWin, client); : return(client->noClientException); :} : :int :ProcChangeSaveSet(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xChangeSaveSetReq); : int result, rc; : : REQUEST_SIZE_MATCH(xChangeSaveSetReq); : rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); : if (rc != Success) : return rc; : if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) : return BadMatch; : if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) : { : result = AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); : } : else : { : client->errorValue = stuff->mode; : return( BadValue ); : } :} : :int :ProcReparentWindow(ClientPtr client) :{ : WindowPtr pWin, pParent; : REQUEST(xReparentWindowReq); : int result, rc; : : REQUEST_SIZE_MATCH(xReparentWindowReq); : rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); : if (rc != Success) : return rc; : rc = dixLookupWindow(&pParent, stuff->parent, client, DixWriteAccess); : if (rc != Success) : return rc; : if (SAME_SCREENS(pWin->drawable, pParent->drawable)) : { : if ((pWin->backgroundState == ParentRelative) && : (pParent->drawable.depth != pWin->drawable.depth)) : return BadMatch; : if ((pWin->drawable.class != InputOnly) && : (pParent->drawable.class == InputOnly)) : return BadMatch; : result = ReparentWindow(pWin, pParent, : (short)stuff->x, (short)stuff->y, client); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); : } : else : return (BadMatch); :} : :int :ProcMapWindow(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xResourceReq); : int rc; : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess); : if (rc != Success) : return rc; : MapWindow(pWin, client); : /* update cache to say it is mapped */ : return(client->noClientException); :} : :int :ProcMapSubwindows(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xResourceReq); : int rc; : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess); : if (rc != Success) : return rc; : MapSubwindows(pWin, client); : /* update cache to say it is mapped */ : return(client->noClientException); :} : :int :ProcUnmapWindow(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xResourceReq); : int rc; : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess); : if (rc != Success) : return rc; : UnmapWindow(pWin, FALSE); : /* update cache to say it is mapped */ : return(client->noClientException); :} : :int :ProcUnmapSubwindows(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xResourceReq); : int rc; : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess); : if (rc != Success) : return rc; : UnmapSubwindows(pWin); : return(client->noClientException); :} : :int :ProcConfigureWindow(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xConfigureWindowReq); : int result; : int len, rc; : : REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); : rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); : if (rc != Success) : return rc; : len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); : if (Ones((Mask)stuff->mask) != len) : return BadLength; : result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], : client); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); :} : :int :ProcCirculateWindow(ClientPtr client) :{ : WindowPtr pWin; : REQUEST(xCirculateWindowReq); : int rc; : : REQUEST_SIZE_MATCH(xCirculateWindowReq); : if ((stuff->direction != RaiseLowest) && : (stuff->direction != LowerHighest)) : { : client->errorValue = stuff->direction; : return BadValue; : } : rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); : if (rc != Success) : return rc; : CirculateWindow(pWin, (int)stuff->direction, client); : return(client->noClientException); :} : :static int :GetGeometry(ClientPtr client, xGetGeometryReply *rep) :{ : DrawablePtr pDraw; : int rc; : REQUEST(xResourceReq); : REQUEST_SIZE_MATCH(xResourceReq); : : rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixReadAccess); : if (rc != Success) : return rc; : : rep->type = X_Reply; : rep->length = 0; : rep->sequenceNumber = client->sequence; : rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; : rep->depth = pDraw->depth; : rep->width = pDraw->width; : rep->height = pDraw->height; : : /* XXX - Because the pixmap-implementation of the multibuffer extension : * may have the buffer-id's drawable resource value be a pointer : * to the buffer's window instead of the buffer itself : * (this happens if the buffer is the displayed buffer), : * we also have to check that the id matches before we can : * truly say that it is a DRAWABLE_WINDOW. : */ : : if ((pDraw->type == UNDRAWABLE_WINDOW) || : ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) : { : WindowPtr pWin = (WindowPtr)pDraw; : rep->x = pWin->origin.x - wBorderWidth (pWin); : rep->y = pWin->origin.y - wBorderWidth (pWin); : rep->borderWidth = pWin->borderWidth; : } : else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ : { : rep->x = rep->y = rep->borderWidth = 0; : } : : return Success; :} : : :int :ProcGetGeometry(ClientPtr client) :{ : xGetGeometryReply rep; : int status; : : if ((status = GetGeometry(client, &rep)) != Success) : return status; : : WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); : return(client->noClientException); :} : : :int :ProcQueryTree(ClientPtr client) :{ : xQueryTreeReply reply; : int rc, numChildren = 0; : WindowPtr pChild, pWin, pHead; : Window *childIDs = (Window *)NULL; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess); : if (rc != Success) : return rc; : reply.type = X_Reply; : reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; : reply.sequenceNumber = client->sequence; : if (pWin->parent) : reply.parent = pWin->parent->drawable.id; : else : reply.parent = (Window)None; : pHead = RealChildHead(pWin); : for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) : numChildren++; : if (numChildren) : { : int curChild = 0; : : childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); : if (!childIDs) : return BadAlloc; : for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) : childIDs[curChild++] = pChild->drawable.id; : } : : reply.nChildren = numChildren; : reply.length = (numChildren * sizeof(Window)) >> 2; : : WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); : if (numChildren) : { : client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; : WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); : DEALLOCATE_LOCAL(childIDs); : } : : return(client->noClientException); :} : :int :ProcInternAtom(ClientPtr client) :{ : Atom atom; : char *tchar; : REQUEST(xInternAtomReq); : : REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); : if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) : { : client->errorValue = stuff->onlyIfExists; : return(BadValue); : } : tchar = (char *) &stuff[1]; : atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); : if (atom != BAD_RESOURCE) : { : xInternAtomReply reply; : reply.type = X_Reply; : reply.length = 0; : reply.sequenceNumber = client->sequence; : reply.atom = atom; : WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); : return(client->noClientException); : } : else : return (BadAlloc); :} : :int :ProcGetAtomName(ClientPtr client) :{ : char *str; : xGetAtomNameReply reply; : int len; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : if ( (str = NameForAtom(stuff->id)) ) : { : len = strlen(str); : reply.type = X_Reply; : reply.length = (len + 3) >> 2; : reply.sequenceNumber = client->sequence; : reply.nameLength = len; : WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); : (void)WriteToClient(client, len, str); : return(client->noClientException); : } : else : { : client->errorValue = stuff->id; : return (BadAtom); : } :} : :int :ProcSetSelectionOwner(ClientPtr client) :{ : WindowPtr pWin; : TimeStamp time; : REQUEST(xSetSelectionOwnerReq); : : REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); : UpdateCurrentTime(); : time = ClientTimeToServerTime(stuff->time); : : /* If the client's time stamp is in the future relative to the server's : time stamp, do not set the selection, just return success. */ : if (CompareTimeStamps(time, currentTime) == LATER) : return Success; : if (stuff->window != None) : { : int rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); : if (rc != Success) : return rc; : } : else : pWin = (WindowPtr)None; : if (ValidAtom(stuff->selection)) : { : int i = 0; : : /* : * First, see if the selection is already set... : */ : while ((i < NumCurrentSelections) && : CurrentSelections[i].selection != stuff->selection) : i++; : if (i < NumCurrentSelections) : { : xEvent event; : : /* If the timestamp in client's request is in the past relative : to the time stamp indicating the last time the owner of the : selection was set, do not set the selection, just return : success. */ : if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) : == EARLIER) : return Success; : if (CurrentSelections[i].client && : (!pWin || (CurrentSelections[i].client != client))) : { : event.u.u.type = SelectionClear; : event.u.selectionClear.time = time.milliseconds; : event.u.selectionClear.window = CurrentSelections[i].window; : event.u.selectionClear.atom = CurrentSelections[i].selection; : (void) TryClientEvents (CurrentSelections[i].client, &event, 1, : NoEventMask, NoEventMask /* CantBeFiltered */, : NullGrab); : } : } : else : { : /* : * It doesn't exist, so add it... : */ : Selection *newsels; : : if (i == 0) : newsels = (Selection *)xalloc(sizeof(Selection)); : else : newsels = (Selection *)xrealloc(CurrentSelections, : (NumCurrentSelections + 1) * sizeof(Selection)); : if (!newsels) : return BadAlloc; : NumCurrentSelections++; : CurrentSelections = newsels; : CurrentSelections[i].selection = stuff->selection; : } : CurrentSelections[i].lastTimeChanged = time; : CurrentSelections[i].window = stuff->window; : CurrentSelections[i].pWin = pWin; : CurrentSelections[i].client = (pWin ? client : NullClient); : if (SelectionCallback) : { : SelectionInfoRec info; : : info.selection = &CurrentSelections[i]; : info.kind= SelectionSetOwner; : CallCallbacks(&SelectionCallback, &info); : } : return (client->noClientException); : } : else : { : client->errorValue = stuff->selection; : return (BadAtom); : } :} : :int :ProcGetSelectionOwner(ClientPtr client) :{ : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : if (ValidAtom(stuff->id)) : { : int i; : xGetSelectionOwnerReply reply; : : i = 0; : while ((i < NumCurrentSelections) && : CurrentSelections[i].selection != stuff->id) i++; : reply.type = X_Reply; : reply.length = 0; : reply.sequenceNumber = client->sequence; : if (i < NumCurrentSelections) : reply.owner = CurrentSelections[i].window; : else : reply.owner = None; : WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); : return(client->noClientException); : } : else : { : client->errorValue = stuff->id; : return (BadAtom); : } :} : :int :ProcConvertSelection(ClientPtr client) :{ : Bool paramsOkay; : xEvent event; : WindowPtr pWin; : REQUEST(xConvertSelectionReq); : int rc; : : REQUEST_SIZE_MATCH(xConvertSelectionReq); : rc = dixLookupWindow(&pWin, stuff->requestor, client, DixReadAccess); : if (rc != Success) : return rc; : : paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); : if (stuff->property != None) : paramsOkay &= ValidAtom(stuff->property); : if (paramsOkay) : { : int i; : : i = 0; : while ((i < NumCurrentSelections) && : CurrentSelections[i].selection != stuff->selection) i++; : if ((i < NumCurrentSelections) && : (CurrentSelections[i].window != None) && : XaceHook(XACE_RESOURCE_ACCESS, client, : CurrentSelections[i].window, RT_WINDOW, : DixReadAccess, CurrentSelections[i].pWin)) : { : event.u.u.type = SelectionRequest; : event.u.selectionRequest.time = stuff->time; : event.u.selectionRequest.owner = : CurrentSelections[i].window; : event.u.selectionRequest.requestor = stuff->requestor; : event.u.selectionRequest.selection = stuff->selection; : event.u.selectionRequest.target = stuff->target; : event.u.selectionRequest.property = stuff->property; : if (TryClientEvents( : CurrentSelections[i].client, &event, 1, NoEventMask, : NoEventMask /* CantBeFiltered */, NullGrab)) : return (client->noClientException); : } : event.u.u.type = SelectionNotify; : event.u.selectionNotify.time = stuff->time; : event.u.selectionNotify.requestor = stuff->requestor; : event.u.selectionNotify.selection = stuff->selection; : event.u.selectionNotify.target = stuff->target; : event.u.selectionNotify.property = None; : (void) TryClientEvents(client, &event, 1, NoEventMask, : NoEventMask /* CantBeFiltered */, NullGrab); : return (client->noClientException); : } : else : { : client->errorValue = stuff->property; : return (BadAtom); : } :} : :int :ProcGrabServer(ClientPtr client) :{ : REQUEST_SIZE_MATCH(xReq); : if (grabState != GrabNone && client != grabClient) : { : ResetCurrentRequest(client); : client->sequence--; : BITSET(grabWaiters, client->index); : IgnoreClient(client); : return(client->noClientException); : } : OnlyListenToOneClient(client); : grabState = GrabKickout; : grabClient = client; : : if (ServerGrabCallback) : { : ServerGrabInfoRec grabinfo; : grabinfo.client = client; : grabinfo.grabstate = SERVER_GRABBED; : CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); : } : : return(client->noClientException); :} : :static void :UngrabServer(ClientPtr client) :{ : int i; : : grabState = GrabNone; : ListenToAllClients(); : for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) : ; : if (i >= 0) : { : i <<= 5; : while (!GETBIT(grabWaiters, i)) : i++; : BITCLEAR(grabWaiters, i); : AttendClient(clients[i]); : } : : if (ServerGrabCallback) : { : ServerGrabInfoRec grabinfo; : grabinfo.client = client; : grabinfo.grabstate = SERVER_UNGRABBED; : CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); : } :} : :int :ProcUngrabServer(ClientPtr client) :{ : REQUEST_SIZE_MATCH(xReq); : UngrabServer(client); : return(client->noClientException); :} : :int :ProcTranslateCoords(ClientPtr client) :{ : REQUEST(xTranslateCoordsReq); : : WindowPtr pWin, pDst; : xTranslateCoordsReply rep; : int rc; : : REQUEST_SIZE_MATCH(xTranslateCoordsReq); : rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixReadAccess); : if (rc != Success) : return rc; : rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixReadAccess); : if (rc != Success) : return rc; : rep.type = X_Reply; : rep.length = 0; : rep.sequenceNumber = client->sequence; : if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) : { : rep.sameScreen = xFalse; : rep.child = None; : rep.dstX = rep.dstY = 0; : } : else : { : INT16 x, y; : rep.sameScreen = xTrue; : rep.child = None; : /* computing absolute coordinates -- adjust to destination later */ : x = pWin->drawable.x + stuff->srcX; : y = pWin->drawable.y + stuff->srcY; : pWin = pDst->firstChild; : while (pWin) : { :#ifdef SHAPE : BoxRec box; :#endif : if ((pWin->mapped) && : (x >= pWin->drawable.x - wBorderWidth (pWin)) && : (x < pWin->drawable.x + (int)pWin->drawable.width + : wBorderWidth (pWin)) && : (y >= pWin->drawable.y - wBorderWidth (pWin)) && : (y < pWin->drawable.y + (int)pWin->drawable.height + : wBorderWidth (pWin)) :#ifdef SHAPE : /* When a window is shaped, a further check : * is made to see if the point is inside : * borderSize : */ : && (!wBoundingShape(pWin) || : POINT_IN_REGION(pWin->drawable.pScreen, : &pWin->borderSize, x, y, &box)) : : && (!wInputShape(pWin) || : POINT_IN_REGION(pWin->drawable.pScreen, : wInputShape(pWin), : x - pWin->drawable.x, : y - pWin->drawable.y, &box)) :#endif : ) : { : rep.child = pWin->drawable.id; : pWin = (WindowPtr) NULL; : } : else : pWin = pWin->nextSib; : } : /* adjust to destination coordinates */ : rep.dstX = x - pDst->drawable.x; : rep.dstY = y - pDst->drawable.y; : } : WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); : return(client->noClientException); :} : :int :ProcOpenFont(ClientPtr client) :{ : int err; : REQUEST(xOpenFontReq); : : REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); : client->errorValue = stuff->fid; : LEGAL_NEW_RESOURCE(stuff->fid, client); : err = OpenFont(client, stuff->fid, (Mask) 0, : stuff->nbytes, (char *)&stuff[1]); : if (err == Success) : { : return(client->noClientException); : } : else : return err; :} : :int :ProcCloseFont(ClientPtr client) :{ : FontPtr pFont; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, : DixDestroyAccess); : if ( pFont != (FontPtr)NULL) /* id was valid */ : { : FreeResource(stuff->id, RT_NONE); : return(client->noClientException); : } : else : { : client->errorValue = stuff->id; : return (BadFont); : } :} : :int :ProcQueryFont(ClientPtr client) :{ : xQueryFontReply *reply; : FontPtr pFont; : GC *pGC; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : client->errorValue = stuff->id; /* EITHER font or gc */ : pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, : DixReadAccess); : if (!pFont) : { : pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, : DixReadAccess); : if (!pGC) : { : client->errorValue = stuff->id; : return(BadFont); /* procotol spec says only error is BadFont */ : } : pFont = pGC->font; : } : : { : xCharInfo *pmax = FONTINKMAX(pFont); : xCharInfo *pmin = FONTINKMIN(pFont); : int nprotoxcistructs; : int rlength; : : nprotoxcistructs = ( : pmax->rightSideBearing == pmin->rightSideBearing && : pmax->leftSideBearing == pmin->leftSideBearing && : pmax->descent == pmin->descent && : pmax->ascent == pmin->ascent && : pmax->characterWidth == pmin->characterWidth) ? : 0 : N2dChars(pFont); : : rlength = sizeof(xQueryFontReply) + : FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + : nprotoxcistructs * sizeof(xCharInfo); : reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); : if(!reply) : { : return(BadAlloc); : } : : reply->type = X_Reply; : reply->length = (rlength - sizeof(xGenericReply)) >> 2; : reply->sequenceNumber = client->sequence; : QueryFont( pFont, reply, nprotoxcistructs); : : WriteReplyToClient(client, rlength, reply); : DEALLOCATE_LOCAL(reply); : return(client->noClientException); : } :} : :int :ProcQueryTextExtents(ClientPtr client) :{ : REQUEST(xQueryTextExtentsReq); : xQueryTextExtentsReply reply; : FontPtr pFont; : GC *pGC; : ExtentInfoRec info; : unsigned long length; : : REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); : : pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, : DixReadAccess); : if (!pFont) : { : pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, : DixReadAccess); : if (!pGC) : { : client->errorValue = stuff->fid; : return(BadFont); : } : pFont = pGC->font; : } : length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); : length = length << 1; : if (stuff->oddLength) : { : if (length == 0) : return(BadLength); : length--; : } : if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) : return(BadAlloc); : reply.type = X_Reply; : reply.length = 0; : reply.sequenceNumber = client->sequence; : reply.drawDirection = info.drawDirection; : reply.fontAscent = info.fontAscent; : reply.fontDescent = info.fontDescent; : reply.overallAscent = info.overallAscent; : reply.overallDescent = info.overallDescent; : reply.overallWidth = info.overallWidth; : reply.overallLeft = info.overallLeft; : reply.overallRight = info.overallRight; : WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); : return(client->noClientException); :} : :int :ProcListFonts(ClientPtr client) :{ : REQUEST(xListFontsReq); : : REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); : : return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, : stuff->maxNames); :} : :int :ProcListFontsWithInfo(ClientPtr client) :{ : REQUEST(xListFontsWithInfoReq); : : REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); : : return StartListFontsWithInfo(client, stuff->nbytes, : (unsigned char *) &stuff[1], stuff->maxNames); :} : :/** : * : * \param value must conform to DeleteType : */ :int :dixDestroyPixmap(pointer value, XID pid) :{ : PixmapPtr pPixmap = (PixmapPtr)value; : return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); :} : :int :ProcCreatePixmap(ClientPtr client) 1 0.0011 :{ /* ProcCreatePixmap total: 9 0.0098 */ : PixmapPtr pMap; : DrawablePtr pDraw; : REQUEST(xCreatePixmapReq); : DepthPtr pDepth; : int i, rc; : : REQUEST_SIZE_MATCH(xCreatePixmapReq); : client->errorValue = stuff->pid; 1 0.0011 : LEGAL_NEW_RESOURCE(stuff->pid, client); : 1 0.0011 : rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, : DixReadAccess); : if (rc != Success) : return rc; : : if (!stuff->width || !stuff->height) : { : client->errorValue = 0; : return BadValue; : } 1 0.0011 : if (stuff->width > 32767 || stuff->height > 32767) : { : /* It is allowed to try and allocate a pixmap which is larger than : * 32767 in either dimension. However, all of the framebuffer code : * is buggy and does not reliably draw to such big pixmaps, basically : * because the Region data structure operates with signed shorts : * for the rectangles in it. : * : * Furthermore, several places in the X server computes the : * size in bytes of the pixmap and tries to store it in an : * integer. This integer can overflow and cause the allocated size : * to be much smaller. : * : * So, such big pixmaps are rejected here with a BadAlloc : */ : return BadAlloc; : } : if (stuff->depth != 1) : { 1 0.0011 : pDepth = pDraw->pScreen->allowedDepths; 1 0.0011 : for (i=0; ipScreen->numDepths; i++, pDepth++) 2 0.0022 : if (pDepth->depth == stuff->depth) : goto CreatePmap; : client->errorValue = stuff->depth; : return BadValue; : } :CreatePmap: 1 0.0011 : pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) : (pDraw->pScreen, stuff->width, : stuff->height, stuff->depth); : if (pMap) : { : pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; : pMap->drawable.id = stuff->pid; : if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) : return(client->noClientException); : } : return (BadAlloc); :} : :int :ProcFreePixmap(ClientPtr client) 1 0.0011 :{ /* ProcFreePixmap total: 6 0.0065 */ : PixmapPtr pMap; : : REQUEST(xResourceReq); : 4 0.0044 : REQUEST_SIZE_MATCH(xResourceReq); : pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, : DixDestroyAccess); : if (pMap) : { 1 0.0011 : FreeResource(stuff->id, RT_NONE); : return(client->noClientException); : } : else : { : client->errorValue = stuff->id; : return (BadPixmap); : } :} : :int :ProcCreateGC(ClientPtr client) :{ : int error, rc; : GC *pGC; : DrawablePtr pDraw; : unsigned len; : REQUEST(xCreateGCReq); : : REQUEST_AT_LEAST_SIZE(xCreateGCReq); : client->errorValue = stuff->gc; : LEGAL_NEW_RESOURCE(stuff->gc, client); : rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess); : if (rc != Success) : return rc; : : len = client->req_len - (sizeof(xCreateGCReq) >> 2); : if (len != Ones(stuff->mask)) : return BadLength; : pGC = (GC *)CreateGC(pDraw, stuff->mask, : (XID *) &stuff[1], &error); : if (error != Success) : return error; : if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) : return (BadAlloc); : return(client->noClientException); :} : :int :ProcChangeGC(ClientPtr client) 1 0.0011 :{ /* ProcChangeGC total: 1 0.0011 */ : GC *pGC; : int result; : unsigned len; : REQUEST(xChangeGCReq); : REQUEST_AT_LEAST_SIZE(xChangeGCReq); : : result = dixLookupGC(&pGC, stuff->gc, client, DixWriteAccess); : if (result != Success) : return result; : : len = client->req_len - (sizeof(xChangeGCReq) >> 2); : if (len != Ones(stuff->mask)) : return BadLength; : : result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); : if (client->noClientException != Success) : return(client->noClientException); : else : { : client->errorValue = clientErrorValue; : return(result); : } :} : :int :ProcCopyGC(ClientPtr client) :{ : GC *dstGC; : GC *pGC; : int result; : REQUEST(xCopyGCReq); : REQUEST_SIZE_MATCH(xCopyGCReq); : : result = dixLookupGC(&pGC, stuff->srcGC, client, DixReadAccess); : if (result != Success) : return result; : result = dixLookupGC(&dstGC, stuff->dstGC, client, DixWriteAccess); : if (result != Success) : return result; : if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) : return (BadMatch); : result = CopyGC(pGC, dstGC, stuff->mask); : if (client->noClientException != Success) : return(client->noClientException); : else : { : client->errorValue = clientErrorValue; : return(result); : } :} : :int :ProcSetDashes(ClientPtr client) :{ : GC *pGC; : int result; : REQUEST(xSetDashesReq); : : REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); : if (stuff->nDashes == 0) : { : client->errorValue = 0; : return BadValue; : } : : result = dixLookupGC(&pGC,stuff->gc, client, DixWriteAccess); : if (result != Success) : return result; : : result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, : (unsigned char *)&stuff[1]); : if (client->noClientException != Success) : return(client->noClientException); : else : { : client->errorValue = clientErrorValue; : return(result); : } :} : :int :ProcSetClipRectangles(ClientPtr client) :{ /* ProcSetClipRectangles total: 1 0.0011 */ : int nr, result; : GC *pGC; : REQUEST(xSetClipRectanglesReq); : : REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); : if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && : (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) : { : client->errorValue = stuff->ordering; : return BadValue; : } 1 0.0011 : result = dixLookupGC(&pGC,stuff->gc, client, DixWriteAccess); : if (result != Success) : return result; : : nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); : if (nr & 4) : return(BadLength); : nr >>= 3; : result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, : nr, (xRectangle *)&stuff[1], (int)stuff->ordering); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); :} : :int :ProcFreeGC(ClientPtr client) :{ : GC *pGC; : int rc; : REQUEST(xResourceReq); : REQUEST_SIZE_MATCH(xResourceReq); : : rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess); : if (rc != Success) : return rc; : : FreeResource(stuff->id, RT_NONE); : return(client->noClientException); :} : :int :ProcClearToBackground(ClientPtr client) :{ : REQUEST(xClearAreaReq); : WindowPtr pWin; : int rc; : : REQUEST_SIZE_MATCH(xClearAreaReq); : rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); : if (rc != Success) : return rc; : if (pWin->drawable.class == InputOnly) : { : client->errorValue = stuff->window; : return (BadMatch); : } : if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) : { : client->errorValue = stuff->exposures; : return(BadValue); : } : (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, : stuff->width, stuff->height, : (Bool)stuff->exposures); : return(client->noClientException); :} : :int :ProcCopyArea(ClientPtr client) 1 0.0011 :{ /* ProcCopyArea total: 1 0.0011 */ : DrawablePtr pDst; : DrawablePtr pSrc; : GC *pGC; : REQUEST(xCopyAreaReq); : RegionPtr pRgn; : int rc; : : REQUEST_SIZE_MATCH(xCopyAreaReq); : : VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); : if (stuff->dstDrawable != stuff->srcDrawable) : { : rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0, : DixReadAccess); : if (rc != Success) : return rc; : if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) : { : client->errorValue = stuff->dstDrawable; : return (BadMatch); : } : } : else : pSrc = pDst; : : pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, : stuff->width, stuff->height, : stuff->dstX, stuff->dstY); : if (pGC->graphicsExposures) : { : (*pDst->pScreen->SendGraphicsExpose) : (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); : if (pRgn) : REGION_DESTROY(pDst->pScreen, pRgn); : } : : return(client->noClientException); :} : :int :ProcCopyPlane(ClientPtr client) :{ : DrawablePtr psrcDraw, pdstDraw; : GC *pGC; : REQUEST(xCopyPlaneReq); : RegionPtr pRgn; : int rc; : : REQUEST_SIZE_MATCH(xCopyPlaneReq); : : VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); : if (stuff->dstDrawable != stuff->srcDrawable) : { : rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0, : DixReadAccess); : if (rc != Success) : return rc; : : if (pdstDraw->pScreen != psrcDraw->pScreen) : { : client->errorValue = stuff->dstDrawable; : return (BadMatch); : } : } : else : psrcDraw = pdstDraw; : : /* Check to see if stuff->bitPlane has exactly ONE good bit set */ : if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || : (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) : { : client->errorValue = stuff->bitPlane; : return(BadValue); : } : : pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, : stuff->width, stuff->height, : stuff->dstX, stuff->dstY, stuff->bitPlane); : if (pGC->graphicsExposures) : { : (*pdstDraw->pScreen->SendGraphicsExpose) : (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); : if (pRgn) : REGION_DESTROY(pdstDraw->pScreen, pRgn); : } : return(client->noClientException); :} : :int :ProcPolyPoint(ClientPtr client) :{ : int npoint; : GC *pGC; : DrawablePtr pDraw; : REQUEST(xPolyPointReq); : : REQUEST_AT_LEAST_SIZE(xPolyPointReq); : if ((stuff->coordMode != CoordModeOrigin) && : (stuff->coordMode != CoordModePrevious)) : { : client->errorValue = stuff->coordMode; : return BadValue; : } : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; : if (npoint) : (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, : (xPoint *) &stuff[1]); : return (client->noClientException); :} : :int :ProcPolyLine(ClientPtr client) :{ : int npoint; : GC *pGC; : DrawablePtr pDraw; : REQUEST(xPolyLineReq); : : REQUEST_AT_LEAST_SIZE(xPolyLineReq); : if ((stuff->coordMode != CoordModeOrigin) && : (stuff->coordMode != CoordModePrevious)) : { : client->errorValue = stuff->coordMode; : return BadValue; : } : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; : if (npoint > 1) : (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, : (DDXPointPtr) &stuff[1]); : return(client->noClientException); :} : :int :ProcPolySegment(ClientPtr client) :{ : int nsegs; : GC *pGC; : DrawablePtr pDraw; : REQUEST(xPolySegmentReq); : : REQUEST_AT_LEAST_SIZE(xPolySegmentReq); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); : if (nsegs & 4) : return(BadLength); : nsegs >>= 3; : if (nsegs) : (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); : return (client->noClientException); :} : :int :ProcPolyRectangle (ClientPtr client) :{ : int nrects; : GC *pGC; : DrawablePtr pDraw; : REQUEST(xPolyRectangleReq); : : REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); : if (nrects & 4) : return(BadLength); : nrects >>= 3; : if (nrects) : (*pGC->ops->PolyRectangle)(pDraw, pGC, : nrects, (xRectangle *) &stuff[1]); : return(client->noClientException); :} : :int :ProcPolyArc(ClientPtr client) :{ : int narcs; : GC *pGC; : DrawablePtr pDraw; : REQUEST(xPolyArcReq); : : REQUEST_AT_LEAST_SIZE(xPolyArcReq); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : narcs = (client->req_len << 2) - sizeof(xPolyArcReq); : if (narcs % sizeof(xArc)) : return(BadLength); : narcs /= sizeof(xArc); : if (narcs) : (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); : return (client->noClientException); :} : :int :ProcFillPoly(ClientPtr client) :{ : int things; : GC *pGC; : DrawablePtr pDraw; : REQUEST(xFillPolyReq); : : REQUEST_AT_LEAST_SIZE(xFillPolyReq); : if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && : (stuff->shape != Convex)) : { : client->errorValue = stuff->shape; : return BadValue; : } : if ((stuff->coordMode != CoordModeOrigin) && : (stuff->coordMode != CoordModePrevious)) : { : client->errorValue = stuff->coordMode; : return BadValue; : } : : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; : if (things) : (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, : stuff->coordMode, things, : (DDXPointPtr) &stuff[1]); : return(client->noClientException); :} : :int :ProcPolyFillRectangle(ClientPtr client) :{ /* ProcPolyFillRectangle total: 1 0.0011 */ : int things; : GC *pGC; : DrawablePtr pDraw; : REQUEST(xPolyFillRectangleReq); : : REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); : if (things & 4) : return(BadLength); 1 0.0011 : things >>= 3; : : if (things) : (*pGC->ops->PolyFillRect) (pDraw, pGC, things, : (xRectangle *) &stuff[1]); : return (client->noClientException); :} : :int :ProcPolyFillArc(ClientPtr client) :{ : int narcs; : GC *pGC; : DrawablePtr pDraw; : REQUEST(xPolyFillArcReq); : : REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); : if (narcs % sizeof(xArc)) : return(BadLength); : narcs /= sizeof(xArc); : if (narcs) : (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); : return (client->noClientException); :} : :#ifdef MATCH_CLIENT_ENDIAN : :int :ServerOrder (void) :{ : int whichbyte = 1; : : if (*((char *) &whichbyte)) : return LSBFirst; : return MSBFirst; :} : :#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) : :void :ReformatImage (char *base, int nbytes, int bpp, int order) :{ : switch (bpp) { : case 1: /* yuck */ : if (BITMAP_BIT_ORDER != order) : BitOrderInvert ((unsigned char *) base, nbytes); :#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 : ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); :#endif : break; : case 4: : break; /* yuck */ : case 8: : break; : case 16: : if (IMAGE_BYTE_ORDER != order) : TwoByteSwap ((unsigned char *) base, nbytes); : break; : case 32: : if (IMAGE_BYTE_ORDER != order) : FourByteSwap ((unsigned char *) base, nbytes); : break; : } :} :#else :#define ReformatImage(b,n,bpp,o) :#endif : :/* 64-bit server notes: the protocol restricts padding of images to : * 8-, 16-, or 32-bits. We would like to have 64-bits for the server : * to use internally. Removes need for internal alignment checking. : * All of the PutImage functions could be changed individually, but : * as currently written, they call other routines which require things : * to be 64-bit padded on scanlines, so we changed things here. : * If an image would be padded differently for 64- versus 32-, then : * copy each scanline to a 64-bit padded scanline. : * Also, we need to make sure that the image is aligned on a 64-bit : * boundary, even if the scanlines are padded to our satisfaction. : */ :int :ProcPutImage(ClientPtr client) :{ : GC *pGC; : DrawablePtr pDraw; : long length; /* length of scanline server padded */ : long lengthProto; /* length of scanline protocol padded */ : char *tmpImage; : REQUEST(xPutImageReq); : : REQUEST_AT_LEAST_SIZE(xPutImageReq); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : if (stuff->format == XYBitmap) : { : if ((stuff->depth != 1) || : (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) : return BadMatch; : length = BitmapBytePad(stuff->width + stuff->leftPad); : } : else if (stuff->format == XYPixmap) : { : if ((pDraw->depth != stuff->depth) || : (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) : return BadMatch; : length = BitmapBytePad(stuff->width + stuff->leftPad); : length *= stuff->depth; : } : else if (stuff->format == ZPixmap) : { : if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) : return BadMatch; : length = PixmapBytePad(stuff->width, stuff->depth); : } : else : { : client->errorValue = stuff->format; : return BadValue; : } : : tmpImage = (char *)&stuff[1]; : lengthProto = length; : : if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + : (sizeof(xPutImageReq) >> 2)) != client->req_len) : return BadLength; : : ReformatImage (tmpImage, lengthProto * stuff->height, : stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, : ClientOrder(client)); : : (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, : stuff->width, stuff->height, : stuff->leftPad, stuff->format, tmpImage); : : return (client->noClientException); :} : :static int :DoGetImage(ClientPtr client, int format, Drawable drawable, : int x, int y, int width, int height, : Mask planemask, xGetImageReply **im_return) :{ : DrawablePtr pDraw; : int nlines, linesPerBuf, rc; : int linesDone; : long widthBytesLine, length; : Mask plane = 0; : char *pBuf; : xGetImageReply xgi; : RegionPtr pVisibleRegion = NULL; : : if ((format != XYPixmap) && (format != ZPixmap)) : { : client->errorValue = format; : return(BadValue); : } : rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess); : if (rc != Success) : return rc; : : if(pDraw->type == DRAWABLE_WINDOW) : { : if( /* check for being viewable */ : !((WindowPtr) pDraw)->realized || : /* check for being on screen */ : pDraw->x + x < 0 || : pDraw->x + x + width > pDraw->pScreen->width || : pDraw->y + y < 0 || : pDraw->y + y + height > pDraw->pScreen->height || : /* check for being inside of border */ : x < - wBorderWidth((WindowPtr)pDraw) || : x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || : y < -wBorderWidth((WindowPtr)pDraw) || : y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height : ) : return(BadMatch); : xgi.visual = wVisual (((WindowPtr) pDraw)); : } : else : { : if(x < 0 || : x+width > (int)pDraw->width || : y < 0 || : y+height > (int)pDraw->height : ) : return(BadMatch); : xgi.visual = None; : } : : xgi.type = X_Reply; : xgi.sequenceNumber = client->sequence; : xgi.depth = pDraw->depth; : if(format == ZPixmap) : { : widthBytesLine = PixmapBytePad(width, pDraw->depth); : length = widthBytesLine * height; : : } : else : { : widthBytesLine = BitmapBytePad(width); : plane = ((Mask)1) << (pDraw->depth - 1); : /* only planes asked for */ : length = widthBytesLine * height * : Ones(planemask & (plane | (plane - 1))); : : } : : xgi.length = length; : : if (im_return) { : pBuf = (char *)xalloc(sz_xGetImageReply + length); : if (!pBuf) : return (BadAlloc); : if (widthBytesLine == 0) : linesPerBuf = 0; : else : linesPerBuf = height; : *im_return = (xGetImageReply *)pBuf; : *(xGetImageReply *)pBuf = xgi; : pBuf += sz_xGetImageReply; : } else { : xgi.length = (xgi.length + 3) >> 2; : if (widthBytesLine == 0 || height == 0) : linesPerBuf = 0; : else if (widthBytesLine >= IMAGE_BUFSIZE) : linesPerBuf = 1; : else : { : linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; : if (linesPerBuf > height) : linesPerBuf = height; : } : length = linesPerBuf * widthBytesLine; : if (linesPerBuf < height) : { : /* we have to make sure intermediate buffers don't need padding */ : while ((linesPerBuf > 1) && : (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) : { : linesPerBuf--; : length -= widthBytesLine; : } : while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) : { : linesPerBuf++; : length += widthBytesLine; : } : } : if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) : return (BadAlloc); : WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); : } : : if (pDraw->type == DRAWABLE_WINDOW && : !XaceHook(XACE_DRAWABLE_ACCESS, client, pDraw)) : { : pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); : if (pVisibleRegion) : { : REGION_TRANSLATE(pDraw->pScreen, pVisibleRegion, : -pDraw->x, -pDraw->y); : } : } : : if (linesPerBuf == 0) : { : /* nothing to do */ : } : else if (format == ZPixmap) : { : linesDone = 0; : while (height - linesDone > 0) : { : nlines = min(linesPerBuf, height - linesDone); : (*pDraw->pScreen->GetImage) (pDraw, : x, : y + linesDone, : width, : nlines, : format, : planemask, : (pointer) pBuf); : if (pVisibleRegion) : XaceCensorImage(client, pVisibleRegion, widthBytesLine, : pDraw, x, y + linesDone, width, : nlines, format, pBuf); : : /* Note that this is NOT a call to WriteSwappedDataToClient, : as we do NOT byte swap */ : if (!im_return) : { : ReformatImage (pBuf, (int)(nlines * widthBytesLine), : BitsPerPixel (pDraw->depth), : ClientOrder(client)); : :/* Don't split me, gcc pukes when you do */ : (void)WriteToClient(client, : (int)(nlines * widthBytesLine), : pBuf); : } : linesDone += nlines; : } : } : else /* XYPixmap */ : { : for (; plane; plane >>= 1) : { : if (planemask & plane) : { : linesDone = 0; : while (height - linesDone > 0) : { : nlines = min(linesPerBuf, height - linesDone); : (*pDraw->pScreen->GetImage) (pDraw, : x, : y + linesDone, : width, : nlines, : format, : plane, : (pointer)pBuf); : if (pVisibleRegion) : XaceCensorImage(client, pVisibleRegion, : widthBytesLine, : pDraw, x, y + linesDone, width, : nlines, format, pBuf); : : /* Note: NOT a call to WriteSwappedDataToClient, : as we do NOT byte swap */ : if (im_return) { : pBuf += nlines * widthBytesLine; : } else { : ReformatImage (pBuf, : (int)(nlines * widthBytesLine), : 1, : ClientOrder (client)); : :/* Don't split me, gcc pukes when you do */ : (void)WriteToClient(client, : (int)(nlines * widthBytesLine), : pBuf); : } : linesDone += nlines; : } : } : } : } : if (pVisibleRegion) : REGION_DESTROY(pDraw->pScreen, pVisibleRegion); : if (!im_return) : DEALLOCATE_LOCAL(pBuf); : return (client->noClientException); :} : :int :ProcGetImage(ClientPtr client) :{ : REQUEST(xGetImageReq); : : REQUEST_SIZE_MATCH(xGetImageReq); : : return DoGetImage(client, stuff->format, stuff->drawable, : stuff->x, stuff->y, : (int)stuff->width, (int)stuff->height, : stuff->planeMask, (xGetImageReply **)NULL); :} : :int :ProcPolyText(ClientPtr client) :{ : int err; : REQUEST(xPolyTextReq); : DrawablePtr pDraw; : GC *pGC; : : REQUEST_AT_LEAST_SIZE(xPolyTextReq); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : : err = PolyText(client, : pDraw, : pGC, : (unsigned char *)&stuff[1], : ((unsigned char *) stuff) + (client->req_len << 2), : stuff->x, : stuff->y, : stuff->reqType, : stuff->drawable); : : if (err == Success) : { : return(client->noClientException); : } : else : return err; :} : :int :ProcImageText8(ClientPtr client) :{ : int err; : DrawablePtr pDraw; : GC *pGC; : : REQUEST(xImageTextReq); : : REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : : err = ImageText(client, : pDraw, : pGC, : stuff->nChars, : (unsigned char *)&stuff[1], : stuff->x, : stuff->y, : stuff->reqType, : stuff->drawable); : : if (err == Success) : { : return(client->noClientException); : } : else : return err; :} : :int :ProcImageText16(ClientPtr client) :{ : int err; : DrawablePtr pDraw; : GC *pGC; : : REQUEST(xImageTextReq); : : REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); : VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); : : err = ImageText(client, : pDraw, : pGC, : stuff->nChars, : (unsigned char *)&stuff[1], : stuff->x, : stuff->y, : stuff->reqType, : stuff->drawable); : : if (err == Success) : { : return(client->noClientException); : } : else : return err; :} : : :int :ProcCreateColormap(ClientPtr client) :{ : VisualPtr pVisual; : ColormapPtr pmap; : Colormap mid; : WindowPtr pWin; : ScreenPtr pScreen; : REQUEST(xCreateColormapReq); : int i, result; : : REQUEST_SIZE_MATCH(xCreateColormapReq); : : if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) : { : client->errorValue = stuff->alloc; : return(BadValue); : } : mid = stuff->mid; : LEGAL_NEW_RESOURCE(mid, client); : result = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); : if (result != Success) : return result; : : pScreen = pWin->drawable.pScreen; : for (i = 0, pVisual = pScreen->visuals; : i < pScreen->numVisuals; : i++, pVisual++) : { : if (pVisual->vid != stuff->visual) : continue; : result = CreateColormap(mid, pScreen, pVisual, &pmap, : (int)stuff->alloc, client->index); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); : } : client->errorValue = stuff->visual; : return(BadMatch); :} : :int :ProcFreeColormap(ClientPtr client) :{ : ColormapPtr pmap; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, : DixDestroyAccess); : if (pmap) : { : /* Freeing a default colormap is a no-op */ : if (!(pmap->flags & IsDefault)) : FreeResource(stuff->id, RT_NONE); : return (client->noClientException); : } : else : { : client->errorValue = stuff->id; : return (BadColor); : } :} : : :int :ProcCopyColormapAndFree(ClientPtr client) :{ : Colormap mid; : ColormapPtr pSrcMap; : REQUEST(xCopyColormapAndFreeReq); : int result; : : REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); : mid = stuff->mid; : LEGAL_NEW_RESOURCE(mid, client); : if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, : RT_COLORMAP, DixReadAccess|DixWriteAccess)) ) : { : result = CopyColormapAndFree(mid, pSrcMap, client->index); : if (client->noClientException != Success) : return(client->noClientException); : else : return(result); : } : else : { : client->errorValue = stuff->srcCmap; : return(BadColor); : } :} : :int :ProcInstallColormap(ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, : RT_COLORMAP, DixReadAccess); : if (pcmp) : { : (*(pcmp->pScreen->InstallColormap)) (pcmp); : return (client->noClientException); : } : else : { : client->errorValue = stuff->id; : return (BadColor); : } :} : :int :ProcUninstallColormap(ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, : RT_COLORMAP, DixReadAccess); : if (pcmp) : { : if(pcmp->mid != pcmp->pScreen->defColormap) : (*(pcmp->pScreen->UninstallColormap)) (pcmp); : return (client->noClientException); : } : else : { : client->errorValue = stuff->id; : return (BadColor); : } :} : :int :ProcListInstalledColormaps(ClientPtr client) :{ : xListInstalledColormapsReply *preply; : int nummaps, rc; : WindowPtr pWin; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess); : if (rc != Success) : return rc; : : preply = (xListInstalledColormapsReply *) : ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + : pWin->drawable.pScreen->maxInstalledCmaps * : sizeof(Colormap)); : if(!preply) : return(BadAlloc); : : preply->type = X_Reply; : preply->sequenceNumber = client->sequence; : nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) : (pWin->drawable.pScreen, (Colormap *)&preply[1]); : preply->nColormaps = nummaps; : preply->length = nummaps; : WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); : client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; : WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); : DEALLOCATE_LOCAL(preply); : return(client->noClientException); :} : :int :ProcAllocColor (ClientPtr client) :{ : ColormapPtr pmap; : int retval; : xAllocColorReply acr; : REQUEST(xAllocColorReq); : : REQUEST_SIZE_MATCH(xAllocColorReq); : pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixWriteAccess); : if (pmap) : { : acr.type = X_Reply; : acr.length = 0; : acr.sequenceNumber = client->sequence; : acr.red = stuff->red; : acr.green = stuff->green; : acr.blue = stuff->blue; : acr.pixel = 0; : if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, : &acr.pixel, client->index)) ) : { : if (client->noClientException != Success) : return(client->noClientException); : else : return (retval); : } :#ifdef PANORAMIX : if (noPanoramiXExtension || !pmap->pScreen->myNum) :#endif : WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); : return (client->noClientException); : : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcAllocNamedColor (ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xAllocNamedColorReq); : : REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixWriteAccess); : if (pcmp) : { : int retval; : : xAllocNamedColorReply ancr; : : ancr.type = X_Reply; : ancr.length = 0; : ancr.sequenceNumber = client->sequence; : : if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, : &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) : { : ancr.screenRed = ancr.exactRed; : ancr.screenGreen = ancr.exactGreen; : ancr.screenBlue = ancr.exactBlue; : ancr.pixel = 0; : if( (retval = AllocColor(pcmp, : &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, : &ancr.pixel, client->index)) ) : { : if (client->noClientException != Success) : return(client->noClientException); : else : return(retval); : } :#ifdef PANORAMIX : if (noPanoramiXExtension || !pcmp->pScreen->myNum) :#endif : WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); : return (client->noClientException); : } : else : return(BadName); : : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcAllocColorCells (ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xAllocColorCellsReq); : : REQUEST_SIZE_MATCH(xAllocColorCellsReq); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixWriteAccess); : if (pcmp) : { : xAllocColorCellsReply accr; : int npixels, nmasks, retval; : long length; : Pixel *ppixels, *pmasks; : : npixels = stuff->colors; : if (!npixels) : { : client->errorValue = npixels; : return (BadValue); : } : if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) : { : client->errorValue = stuff->contiguous; : return (BadValue); : } : nmasks = stuff->planes; : length = ((long)npixels + (long)nmasks) * sizeof(Pixel); : ppixels = (Pixel *)ALLOCATE_LOCAL(length); : if(!ppixels) : return(BadAlloc); : pmasks = ppixels + npixels; : : if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, : (Bool)stuff->contiguous, ppixels, pmasks)) ) : { : DEALLOCATE_LOCAL(ppixels); : if (client->noClientException != Success) : return(client->noClientException); : else : return(retval); : } :#ifdef PANORAMIX : if (noPanoramiXExtension || !pcmp->pScreen->myNum) :#endif : { : accr.type = X_Reply; : accr.length = length >> 2; : accr.sequenceNumber = client->sequence; : accr.nPixels = npixels; : accr.nMasks = nmasks; : WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); : client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; : WriteSwappedDataToClient(client, length, ppixels); : } : DEALLOCATE_LOCAL(ppixels); : return (client->noClientException); : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcAllocColorPlanes(ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xAllocColorPlanesReq); : : REQUEST_SIZE_MATCH(xAllocColorPlanesReq); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixWriteAccess); : if (pcmp) : { : xAllocColorPlanesReply acpr; : int npixels, retval; : long length; : Pixel *ppixels; : : npixels = stuff->colors; : if (!npixels) : { : client->errorValue = npixels; : return (BadValue); : } : if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) : { : client->errorValue = stuff->contiguous; : return (BadValue); : } : acpr.type = X_Reply; : acpr.sequenceNumber = client->sequence; : acpr.nPixels = npixels; : length = (long)npixels * sizeof(Pixel); : ppixels = (Pixel *)ALLOCATE_LOCAL(length); : if(!ppixels) : return(BadAlloc); : if( (retval = AllocColorPlanes(client->index, pcmp, npixels, : (int)stuff->red, (int)stuff->green, (int)stuff->blue, : (Bool)stuff->contiguous, ppixels, : &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) : { : DEALLOCATE_LOCAL(ppixels); : if (client->noClientException != Success) : return(client->noClientException); : else : return(retval); : } : acpr.length = length >> 2; :#ifdef PANORAMIX : if (noPanoramiXExtension || !pcmp->pScreen->myNum) :#endif : { : WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); : client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; : WriteSwappedDataToClient(client, length, ppixels); : } : DEALLOCATE_LOCAL(ppixels); : return (client->noClientException); : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcFreeColors(ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xFreeColorsReq); : : REQUEST_AT_LEAST_SIZE(xFreeColorsReq); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixWriteAccess); : if (pcmp) : { : int count; : int retval; : : if(pcmp->flags & AllAllocated) : return(BadAccess); : count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; : retval = FreeColors(pcmp, client->index, count, : (Pixel *)&stuff[1], (Pixel)stuff->planeMask); : if (client->noClientException != Success) : return(client->noClientException); : else : { : client->errorValue = clientErrorValue; : return(retval); : } : : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcStoreColors (ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xStoreColorsReq); : : REQUEST_AT_LEAST_SIZE(xStoreColorsReq); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixWriteAccess); : if (pcmp) : { : int count; : int retval; : : count = (client->req_len << 2) - sizeof(xStoreColorsReq); : if (count % sizeof(xColorItem)) : return(BadLength); : count /= sizeof(xColorItem); : retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); : if (client->noClientException != Success) : return(client->noClientException); : else : { : client->errorValue = clientErrorValue; : return(retval); : } : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcStoreNamedColor (ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xStoreNamedColorReq); : : REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixWriteAccess); : if (pcmp) : { : xColorItem def; : int retval; : : if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], : stuff->nbytes, &def.red, &def.green, &def.blue)) : { : def.flags = stuff->flags; : def.pixel = stuff->pixel; : retval = StoreColors(pcmp, 1, &def); : if (client->noClientException != Success) : return(client->noClientException); : else : return(retval); : } : return (BadName); : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcQueryColors(ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xQueryColorsReq); : : REQUEST_AT_LEAST_SIZE(xQueryColorsReq); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixReadAccess); : if (pcmp) : { : int count, retval; : xrgb *prgbs; : xQueryColorsReply qcr; : : count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; : prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); : if(!prgbs && count) : return(BadAlloc); : if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) : { : if (prgbs) DEALLOCATE_LOCAL(prgbs); : if (client->noClientException != Success) : return(client->noClientException); : else : { : client->errorValue = clientErrorValue; : return (retval); : } : } : qcr.type = X_Reply; : qcr.length = (count * sizeof(xrgb)) >> 2; : qcr.sequenceNumber = client->sequence; : qcr.nColors = count; : WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); : if (count) : { : client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; : WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); : } : if (prgbs) DEALLOCATE_LOCAL(prgbs); : return(client->noClientException); : : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcLookupColor(ClientPtr client) :{ : ColormapPtr pcmp; : REQUEST(xLookupColorReq); : : REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); : pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, : RT_COLORMAP, DixReadAccess); : if (pcmp) : { : xLookupColorReply lcr; : : if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, : &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) : { : lcr.type = X_Reply; : lcr.length = 0; : lcr.sequenceNumber = client->sequence; : lcr.screenRed = lcr.exactRed; : lcr.screenGreen = lcr.exactGreen; : lcr.screenBlue = lcr.exactBlue; : (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, : &lcr.screenGreen, : &lcr.screenBlue, : pcmp->pVisual); : WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); : return(client->noClientException); : } : return (BadName); : } : else : { : client->errorValue = stuff->cmap; : return (BadColor); : } :} : :int :ProcCreateCursor (ClientPtr client) :{ : CursorPtr pCursor; : PixmapPtr src; : PixmapPtr msk; : unsigned char * srcbits; : unsigned char * mskbits; : unsigned short width, height; : long n; : CursorMetricRec cm; : : : REQUEST(xCreateCursorReq); : : REQUEST_SIZE_MATCH(xCreateCursorReq); : LEGAL_NEW_RESOURCE(stuff->cid, client); : : src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, : RT_PIXMAP, DixReadAccess); : msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, : RT_PIXMAP, DixReadAccess); : if ( src == (PixmapPtr)NULL) : { : client->errorValue = stuff->source; : return (BadPixmap); : } : if ( msk == (PixmapPtr)NULL) : { : if (stuff->mask != None) : { : client->errorValue = stuff->mask; : return (BadPixmap); : } : } : else if ( src->drawable.width != msk->drawable.width : || src->drawable.height != msk->drawable.height : || src->drawable.depth != 1 : || msk->drawable.depth != 1) : return (BadMatch); : : width = src->drawable.width; : height = src->drawable.height; : : if ( stuff->x > width : || stuff->y > height ) : return (BadMatch); : : n = BitmapBytePad(width)*height; : srcbits = (unsigned char *)xalloc(n); : if (!srcbits) : return (BadAlloc); : mskbits = (unsigned char *)xalloc(n); : if (!mskbits) : { : xfree(srcbits); : return (BadAlloc); : } : : /* zeroing the (pad) bits helps some ddx cursor handling */ : bzero((char *)srcbits, n); : (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, : XYPixmap, 1, (pointer)srcbits); : if ( msk == (PixmapPtr)NULL) : { : unsigned char *bits = mskbits; : while (--n >= 0) : *bits++ = ~0; : } : else : { : /* zeroing the (pad) bits helps some ddx cursor handling */ : bzero((char *)mskbits, n); : (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, : height, XYPixmap, 1, (pointer)mskbits); : } : cm.width = width; : cm.height = height; : cm.xhot = stuff->x; : cm.yhot = stuff->y; : pCursor = AllocCursor( srcbits, mskbits, &cm, : stuff->foreRed, stuff->foreGreen, stuff->foreBlue, : stuff->backRed, stuff->backGreen, stuff->backBlue); : : if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) : return (client->noClientException); : return BadAlloc; :} : :int :ProcCreateGlyphCursor (ClientPtr client) :{ : CursorPtr pCursor; : int res; : : REQUEST(xCreateGlyphCursorReq); : : REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); : LEGAL_NEW_RESOURCE(stuff->cid, client); : : res = AllocGlyphCursor(stuff->source, stuff->sourceChar, : stuff->mask, stuff->maskChar, : stuff->foreRed, stuff->foreGreen, stuff->foreBlue, : stuff->backRed, stuff->backGreen, stuff->backBlue, : &pCursor, client); : if (res != Success) : return res; : if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) : return client->noClientException; : return BadAlloc; :} : : :int :ProcFreeCursor (ClientPtr client) :{ : CursorPtr pCursor; : REQUEST(xResourceReq); : : REQUEST_SIZE_MATCH(xResourceReq); : pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, : RT_CURSOR, DixDestroyAccess); : if (pCursor) : { : FreeResource(stuff->id, RT_NONE); : return (client->noClientException); : } : else : { : client->errorValue = stuff->id; : return (BadCursor); : } :} : :int :ProcQueryBestSize (ClientPtr client) :{ : xQueryBestSizeReply reply; : DrawablePtr pDraw; : ScreenPtr pScreen; : int rc; : REQUEST(xQueryBestSizeReq); : REQUEST_SIZE_MATCH(xQueryBestSizeReq); : : if ((stuff->class != CursorShape) && : (stuff->class != TileShape) && : (stuff->class != StippleShape)) : { : client->errorValue = stuff->class; : return(BadValue); : } : : rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, : DixReadAccess); : if (rc != Success) : return rc; : if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) : return (BadMatch); : pScreen = pDraw->pScreen; : (* pScreen->QueryBestSize)(stuff->class, &stuff->width, : &stuff->height, pScreen); : reply.type = X_Reply; : reply.length = 0; : reply.sequenceNumber = client->sequence; : reply.width = stuff->width; : reply.height = stuff->height; : WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); : return (client->noClientException); :} : : :int :ProcSetScreenSaver (ClientPtr client) :{ : int blankingOption, exposureOption; : REQUEST(xSetScreenSaverReq); : : REQUEST_SIZE_MATCH(xSetScreenSaverReq); : blankingOption = stuff->preferBlank; : if ((blankingOption != DontPreferBlanking) && : (blankingOption != PreferBlanking) && : (blankingOption != DefaultBlanking)) : { : client->errorValue = blankingOption; : return BadValue; : } : exposureOption = stuff->allowExpose; : if ((exposureOption != DontAllowExposures) && : (exposureOption != AllowExposures) && : (exposureOption != DefaultExposures)) : { : client->errorValue = exposureOption; : return BadValue; : } : if (stuff->timeout < -1) : { : client->errorValue = stuff->timeout; : return BadValue; : } : if (stuff->interval < -1) : { : client->errorValue = stuff->interval; : return BadValue; : } : : if (blankingOption == DefaultBlanking) : ScreenSaverBlanking = defaultScreenSaverBlanking; : else : ScreenSaverBlanking = blankingOption; : if (exposureOption == DefaultExposures) : ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; : else : ScreenSaverAllowExposures = exposureOption; : : if (stuff->timeout >= 0) : ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; : else : ScreenSaverTime = defaultScreenSaverTime; : if (stuff->interval >= 0) : ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; : else : ScreenSaverInterval = defaultScreenSaverInterval; : : SetScreenSaverTimer(); : return (client->noClientException); :} : :int :ProcGetScreenSaver(ClientPtr client) :{ : xGetScreenSaverReply rep; : : REQUEST_SIZE_MATCH(xReq); : rep.type = X_Reply; : rep.length = 0; : rep.sequenceNumber = client->sequence; : rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; : rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; : rep.preferBlanking = ScreenSaverBlanking; : rep.allowExposures = ScreenSaverAllowExposures; : WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); : return (client->noClientException); :} : :int :ProcChangeHosts(ClientPtr client) :{ : REQUEST(xChangeHostsReq); : int result; : : REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); : : if(stuff->mode == HostInsert) : result = AddHost(client, (int)stuff->hostFamily, : stuff->hostLength, (pointer)&stuff[1]); : else if (stuff->mode == HostDelete) : result = RemoveHost(client, (int)stuff->hostFamily, : stuff->hostLength, (pointer)&stuff[1]); : else : { : client->errorValue = stuff->mode; : return BadValue; : } : if (!result) : result = client->noClientException; : return (result); :} : :int :ProcListHosts(ClientPtr client) :{ : xListHostsReply reply; : int len, nHosts, result; : pointer pdata; : /* REQUEST(xListHostsReq); */ : : REQUEST_SIZE_MATCH(xListHostsReq); : : /* untrusted clients can't list hosts */ : if (!XaceHook(XACE_HOSTLIST_ACCESS, client, DixReadAccess)) : return BadAccess; : : result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); : if (result != Success) : return(result); : reply.type = X_Reply; : reply.sequenceNumber = client->sequence; : reply.nHosts = nHosts; : reply.length = len >> 2; : WriteReplyToClient(client, sizeof(xListHostsReply), &reply); : if (nHosts) : { : client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; : WriteSwappedDataToClient(client, len, pdata); : } : xfree(pdata); : return (client->noClientException); :} : :int :ProcChangeAccessControl(ClientPtr client) :{ : int result; : REQUEST(xSetAccessControlReq); : : REQUEST_SIZE_MATCH(xSetAccessControlReq); : if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) : { : client->errorValue = stuff->mode; : return BadValue; : } : result = ChangeAccessControl(client, stuff->mode == EnableAccess); : if (!result) : result = client->noClientException; : return (result); :} : :/********************* : * CloseDownRetainedResources : * : * Find all clients that are gone and have terminated in RetainTemporary : * and destroy their resources. : *********************/ : :static void :CloseDownRetainedResources(void) :{ : int i; : ClientPtr client; : : for (i=1; icloseDownMode == RetainTemporary) : && (client->clientGone)) : CloseDownClient(client); : } :} : :int :ProcKillClient(ClientPtr client) :{ : REQUEST(xResourceReq); : ClientPtr killclient; : int rc; : : REQUEST_SIZE_MATCH(xResourceReq); : if (stuff->id == AllTemporary) : { : CloseDownRetainedResources(); : return (client->noClientException); : } : : rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess); : if (rc == Success) { : CloseDownClient(killclient); : /* if an LBX proxy gets killed, isItTimeToYield will be set */ : if (isItTimeToYield || (client == killclient)) : { : /* force yield and return Success, so that Dispatch() : * doesn't try to touch client : */ : isItTimeToYield = TRUE; : return (Success); : } : return (client->noClientException); : } : else : return rc; :} : :int :ProcSetFontPath(ClientPtr client) :{ : unsigned char *ptr; : unsigned long nbytes, total; : long nfonts; : int n, result; : int error; : REQUEST(xSetFontPathReq); : : REQUEST_AT_LEAST_SIZE(xSetFontPathReq); : : nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); : total = nbytes; : ptr = (unsigned char *)&stuff[1]; : nfonts = stuff->nFonts; : while (--nfonts >= 0) : { : if ((total == 0) || (total < (n = (*ptr + 1)))) : return(BadLength); : total -= n; : ptr += n; : } : if (total >= 4) : return(BadLength); : result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], : &error); : if (!result) : { : result = client->noClientException; : client->errorValue = error; : } : return (result); :} : :int :ProcGetFontPath(ClientPtr client) :{ : xGetFontPathReply reply; : int stringLens, numpaths; : unsigned char *bufferStart; : /* REQUEST (xReq); */ : : REQUEST_SIZE_MATCH(xReq); : bufferStart = GetFontPath(&numpaths, &stringLens); : : reply.type = X_Reply; : reply.sequenceNumber = client->sequence; : reply.length = (stringLens + numpaths + 3) >> 2; : reply.nPaths = numpaths; : : WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); : if (stringLens || numpaths) : (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); : return(client->noClientException); :} : :int :ProcChangeCloseDownMode(ClientPtr client) :{ : REQUEST(xSetCloseDownModeReq); : : REQUEST_SIZE_MATCH(xSetCloseDownModeReq); : if ((stuff->mode == AllTemporary) || : (stuff->mode == RetainPermanent) || : (stuff->mode == RetainTemporary)) : { : client->closeDownMode = stuff->mode; : return (client->noClientException); : } : else : { : client->errorValue = stuff->mode; : return (BadValue); : } :} : :int ProcForceScreenSaver(ClientPtr client) :{ : REQUEST(xForceScreenSaverReq); : : REQUEST_SIZE_MATCH(xForceScreenSaverReq); : : if ((stuff->mode != ScreenSaverReset) && : (stuff->mode != ScreenSaverActive)) : { : client->errorValue = stuff->mode; : return BadValue; : } : SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); : return client->noClientException; :} : :int ProcNoOperation(ClientPtr client) :{ : REQUEST_AT_LEAST_SIZE(xReq); : : /* noop -- don't do anything */ : return(client->noClientException); :} : :void :InitProcVectors(void) :{ : int i; : for (i = 0; i<256; i++) : { : if(!ProcVector[i]) : { : ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; : ReplySwapVector[i] = ReplyNotSwappd; : } : } : for(i = LASTEvent; i < 128; i++) : { : EventSwapVector[i] = NotImplemented; : } : :} : :/********************** : * CloseDownClient : * : * Client can either mark his resources destroy or retain. If retained and : * then killed again, the client is really destroyed. : *********************/ : :char dispatchExceptionAtReset = DE_RESET; : :void :CloseDownClient(ClientPtr client) :{ : Bool really_close_down = client->clientGone || : client->closeDownMode == DestroyAll; : : if (!client->clientGone) : { : /* ungrab server if grabbing client dies */ : if (grabState != GrabNone && grabClient == client) : { : UngrabServer(client); : } : BITCLEAR(grabWaiters, client->index); : DeleteClientFromAnySelections(client); : ReleaseActiveGrabs(client); : DeleteClientFontStuff(client); : if (!really_close_down) : { : /* This frees resources that should never be retained : * no matter what the close down mode is. Actually we : * could do this unconditionally, but it's probably : * better not to traverse all the client's resources : * twice (once here, once a few lines down in : * FreeClientResources) in the common case of : * really_close_down == TRUE. : */ : FreeClientNeverRetainResources(client); : client->clientState = ClientStateRetained; : if (ClientStateCallback) : { : NewClientInfoRec clientinfo; : : clientinfo.client = client; : clientinfo.prefix = (xConnSetupPrefix *)NULL; : clientinfo.setup = (xConnSetup *) NULL; : CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); : } : } : client->clientGone = TRUE; /* so events aren't sent to client */ : if (ClientIsAsleep(client)) : ClientSignal (client); : ProcessWorkQueueZombies(); : CloseDownConnection(client); : : /* If the client made it to the Running stage, nClients has : * been incremented on its behalf, so we need to decrement it : * now. If it hasn't gotten to Running, nClients has *not* : * been incremented, so *don't* decrement it. : */ : if (client->clientState != ClientStateInitial && : client->clientState != ClientStateAuthenticating ) : { : --nClients; : } : } : : if (really_close_down) : { : if (client->clientState == ClientStateRunning && nClients == 0) : dispatchException |= dispatchExceptionAtReset; : : client->clientState = ClientStateGone; : if (ClientStateCallback) : { : NewClientInfoRec clientinfo; : : clientinfo.client = client; : clientinfo.prefix = (xConnSetupPrefix *)NULL; : clientinfo.setup = (xConnSetup *) NULL; : CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); : } : FreeClientResources(client); :#ifdef XSERVER_DTRACE : XSERVER_CLIENT_DISCONNECT(client->index); :#endif : if (client->index < nextFreeClientID) : nextFreeClientID = client->index; : clients[client->index] = NullClient; :#ifdef SMART_SCHEDULE : SmartLastClient = NullClient; :#endif : xfree(client); : : while (!clients[currentMaxClients-1]) : currentMaxClients--; : } :} : :static void :KillAllClients(void) :{ : int i; : for (i=1; icloseDownMode = DestroyAll; : CloseDownClient(clients[i]); : } :} : :extern int clientPrivateLen; :extern unsigned *clientPrivateSizes; :extern unsigned totalClientSize; : :void InitClient(ClientPtr client, int i, pointer ospriv) :{ : client->index = i; : client->sequence = 0; : client->clientAsMask = ((Mask)i) << CLIENTOFFSET; : client->clientGone = FALSE; : if (i) : { : client->closeDownMode = DestroyAll; : client->lastDrawable = (DrawablePtr)WindowTable[0]; : client->lastDrawableID = WindowTable[0]->drawable.id; : } : else : { : client->closeDownMode = RetainPermanent; : client->lastDrawable = (DrawablePtr)NULL; : client->lastDrawableID = INVALID; : } : client->lastGC = (GCPtr) NULL; : client->lastGCID = INVALID; : client->numSaved = 0; : client->saveSet = (SaveSetElt *)NULL; : client->noClientException = Success; :#ifdef DEBUG : client->requestLogIndex = 0; :#endif : client->requestVector = InitialVector; : client->osPrivate = ospriv; : client->swapped = FALSE; : client->big_requests = FALSE; : client->priority = 0; : client->clientState = ClientStateInitial; :#ifdef XKB : if (!noXkbExtension) { : client->xkbClientFlags = 0; : client->mapNotifyMask = 0; : QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); : } :#endif : client->replyBytesRemaining = 0; :#ifdef XAPPGROUP : client->appgroup = NULL; :#endif : client->fontResFunc = NULL; :#ifdef SMART_SCHEDULE : client->smart_priority = 0; : client->smart_start_tick = SmartScheduleTime; : client->smart_stop_tick = SmartScheduleTime; : client->smart_check_tick = SmartScheduleTime; :#endif :} : :int :InitClientPrivates(ClientPtr client) :{ : char *ptr; : DevUnion *ppriv; : unsigned *sizes; : unsigned size; : int i; : : if (totalClientSize == sizeof(ClientRec)) : ppriv = (DevUnion *)NULL; : else if (client->index) : ppriv = (DevUnion *)(client + 1); : else : { : ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); : if (!ppriv) : return 0; : } : client->devPrivates = ppriv; : sizes = clientPrivateSizes; : ptr = (char *)(ppriv + clientPrivateLen); : if (ppriv) : bzero(ppriv, totalClientSize - sizeof(ClientRec)); : for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) : { : if ( (size = *sizes) ) : { : ppriv->ptr = (pointer)ptr; : ptr += size; : } : else : ppriv->ptr = (pointer)NULL; : } : : /* Allow registrants to initialize the serverClient devPrivates */ : if (!client->index && ClientStateCallback) : { : NewClientInfoRec clientinfo; : : clientinfo.client = client; : clientinfo.prefix = (xConnSetupPrefix *)NULL; : clientinfo.setup = (xConnSetup *) NULL; : CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); : } : return 1; :} : :/************************ : * int NextAvailableClient(ospriv) : * : * OS dependent portion can't assign client id's because of CloseDownModes. : * Returns NULL if there are no free clients. : *************************/ : :ClientPtr NextAvailableClient(pointer ospriv) :{ : int i; : ClientPtr client; : xReq data; : : i = nextFreeClientID; : if (i == MAXCLIENTS) : return (ClientPtr)NULL; : clients[i] = client = (ClientPtr)xalloc(totalClientSize); : if (!client) : return (ClientPtr)NULL; : InitClient(client, i, ospriv); : InitClientPrivates(client); : if (!InitClientResources(client)) : { : xfree(client); : return (ClientPtr)NULL; : } : data.reqType = 1; : data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; : if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) : { : FreeClientResources(client); : xfree(client); : return (ClientPtr)NULL; : } : if (i == currentMaxClients) : currentMaxClients++; : while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) : nextFreeClientID++; : if (ClientStateCallback) : { : NewClientInfoRec clientinfo; : : clientinfo.client = client; : clientinfo.prefix = (xConnSetupPrefix *)NULL; : clientinfo.setup = (xConnSetup *) NULL; : CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); : } : return(client); :} : :int :ProcInitialConnection(ClientPtr client) :{ : REQUEST(xReq); : xConnClientPrefix *prefix; : int whichbyte = 1; : : prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); : if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) : return (client->noClientException = -1); : if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || : (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) : { : client->swapped = TRUE; : SwapConnClientPrefix(prefix); : } : stuff->reqType = 2; : stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + : ((prefix->nbytesAuthString + (unsigned)3) >> 2); : if (client->swapped) : { : swaps(&stuff->length, whichbyte); : } : ResetCurrentRequest(client); : return (client->noClientException); :} : :int :SendConnSetup(ClientPtr client, char *reason) :{ : xWindowRoot *root; : int i; : int numScreens; : char* lConnectionInfo; : xConnSetupPrefix* lconnSetupPrefix; : : if (reason) : { : xConnSetupPrefix csp; : : csp.success = xFalse; : csp.lengthReason = strlen(reason); : csp.length = (csp.lengthReason + (unsigned)3) >> 2; : csp.majorVersion = X_PROTOCOL; : csp.minorVersion = X_PROTOCOL_REVISION; : if (client->swapped) : WriteSConnSetupPrefix(client, &csp); : else : (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); : (void)WriteToClient(client, (int)csp.lengthReason, reason); : return (client->noClientException = -1); : } : : numScreens = screenInfo.numScreens; : lConnectionInfo = ConnectionInfo; : lconnSetupPrefix = &connSetupPrefix; : : /* We're about to start speaking X protocol back to the client by : * sending the connection setup info. This means the authorization : * step is complete, and we can count the client as an : * authorized one. : */ : nClients++; : : client->requestVector = client->swapped ? SwappedProcVector : ProcVector; : client->sequence = 0; :#ifdef XAPPGROUP : XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); :#endif : ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; : ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; :#ifdef MATCH_CLIENT_ENDIAN : ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); : ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); :#endif : /* fill in the "currentInputMask" */ : root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); :#ifdef PANORAMIX : if (noPanoramiXExtension) : numScreens = screenInfo.numScreens; : else : numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; :#endif : : for (i=0; icurrentInputMask = WindowTable[i]->eventMask | : wOtherEventMasks (WindowTable[i]); : pDepth = (xDepth *)(root + 1); : for (j = 0; j < root->nDepths; j++) : { : pDepth = (xDepth *)(((char *)(pDepth + 1)) + : pDepth->nVisuals * sizeof(xVisualType)); : } : root = (xWindowRoot *)pDepth; : } : : if (client->swapped) : { : WriteSConnSetupPrefix(client, lconnSetupPrefix); : WriteSConnectionInfo(client, : (unsigned long)(lconnSetupPrefix->length << 2), : lConnectionInfo); : } : else : { : (void)WriteToClient(client, sizeof(xConnSetupPrefix), : (char *) lconnSetupPrefix); : (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), : lConnectionInfo); : } : client->clientState = ClientStateRunning; : if (ClientStateCallback) : { : NewClientInfoRec clientinfo; : : clientinfo.client = client; : clientinfo.prefix = lconnSetupPrefix; : clientinfo.setup = (xConnSetup *)lConnectionInfo; : CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); : } : return (client->noClientException); :} : :int :ProcEstablishConnection(ClientPtr client) :{ : char *reason, *auth_proto, *auth_string; : xConnClientPrefix *prefix; : REQUEST(xReq); : : prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); : auth_proto = (char *)prefix + sz_xConnClientPrefix; : auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); : if ((prefix->majorVersion != X_PROTOCOL) || : (prefix->minorVersion != X_PROTOCOL_REVISION)) : reason = "Protocol version mismatch"; : else : reason = ClientAuthorized(client, : (unsigned short)prefix->nbytesAuthProto, : auth_proto, : (unsigned short)prefix->nbytesAuthString, : auth_string); : /* : * If Kerberos is being used for this client, the clientState : * will be set to ClientStateAuthenticating at this point. : * More messages need to be exchanged among the X server, Kerberos : * server, and client to figure out if everyone is authorized. : * So we don't want to send the connection setup info yet, since : * the auth step isn't really done. : */ : if (client->clientState == ClientStateCheckingSecurity) : client->clientState = ClientStateCheckedSecurity; : else if (client->clientState != ClientStateAuthenticating) : return(SendConnSetup(client, reason)); : return(client->noClientException); :} : :_X_EXPORT void :SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, : XID resId, int errorCode) :{ : xError rep; : : rep.type = X_Error; : rep.sequenceNumber = client->sequence; : rep.errorCode = errorCode; : rep.majorCode = majorCode; : rep.minorCode = minorCode; : rep.resourceID = resId; : : WriteEventsToClient (client, 1, (xEvent *)&rep); :} : :void :DeleteWindowFromAnySelections(WindowPtr pWin) :{ : int i; : : for (i = 0; i< NumCurrentSelections; i++) : if (CurrentSelections[i].pWin == pWin) : { : if (SelectionCallback) : { : SelectionInfoRec info; : : info.selection = &CurrentSelections[i]; : info.kind = SelectionWindowDestroy; : CallCallbacks(&SelectionCallback, &info); : } : CurrentSelections[i].pWin = (WindowPtr)NULL; : CurrentSelections[i].window = None; : CurrentSelections[i].client = NullClient; : } :} : :static void :DeleteClientFromAnySelections(ClientPtr client) :{ : int i; : : for (i = 0; i< NumCurrentSelections; i++) : if (CurrentSelections[i].client == client) : { : if (SelectionCallback) : { : SelectionInfoRec info; : : info.selection = &CurrentSelections[i]; : info.kind = SelectionWindowDestroy; : CallCallbacks(&SelectionCallback, &info); : } : CurrentSelections[i].pWin = (WindowPtr)NULL; : CurrentSelections[i].window = None; : CurrentSelections[i].client = NullClient; : } :} : :void :MarkClientException(ClientPtr client) :{ : client->noClientException = -1; :} : :#ifdef XSERVER_DTRACE :#include : :/* Load table of request names for dtrace probes */ :static void LoadRequestNames(void) :{ : int i; : FILE *xedb; : extern void LoadExtensionNames(char **RequestNames); : : bzero(RequestNames, 256 * sizeof(char *)); : : xedb = fopen(XERRORDB_PATH, "r"); : if (xedb != NULL) { : char buf[256]; : while (fgets(buf, sizeof(buf), xedb)) { : if ((strncmp("XRequest.", buf, 9) == 0) && (isdigit(buf[9]))) { : char *name; : i = strtol(buf + 9, &name, 10); : if (RequestNames[i] == 0) { : char *end = strchr(name, '\n'); : if (end) { *end = '\0'; } : RequestNames[i] = strdup(name + 1); : } : } : } : fclose(xedb); : } : : LoadExtensionNames(RequestNames); : : for (i = 0; i < 256; i++) { : if (RequestNames[i] == 0) { :#define RN_SIZE 12 /* "Request#' + up to 3 digits + \0 */ : RequestNames[i] = xalloc(RN_SIZE); : if (RequestNames[i]) { : snprintf(RequestNames[i], RN_SIZE, "Request#%d", i); : } : } : /* fprintf(stderr, "%d: %s\n", i, RequestNames[i]); */ : } :} : :static void FreeRequestNames(void) :{ : int i; : : for (i = 0; i < 256; i++) { : if (RequestNames[i] != 0) { : free(RequestNames[i]); : RequestNames[i] = 0; : } : } :} : :#endif /* * Total samples for file : "/home/cworth/src/xorg/xserver/dix/gc.c" * * 57 0.0621 */ :/*********************************************************** : :Copyright 1987, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :******************************************************************/ : : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include :#include :#include "misc.h" :#include "resource.h" :#include "gcstruct.h" :#include "pixmapstr.h" :#include "dixfontstr.h" :#include "scrnintstr.h" :#include "region.h" : :#include "dix.h" :#include : :extern XID clientErrorValue; :extern FontPtr defaultFont; : :static Bool CreateDefaultTile(GCPtr pGC); : :static unsigned char DefaultDash[2] = {4, 4}; : :_X_EXPORT void :ValidateGC(DrawablePtr pDraw, GC *pGC) 3 0.0033 :{ /* ValidateGC total: 3 0.0033 */ : (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); : pGC->stateChanges = 0; : pGC->serialNumber = pDraw->serialNumber; :} : : :/* dixChangeGC(client, pGC, mask, pC32, pUnion) : * : * This function was created as part of the Security extension : * implementation. The client performing the gc change must be passed so : * that access checks can be performed on any tiles, stipples, or fonts : * that are specified. ddxen can call this too; they should normally : * pass NullClient for the client since any access checking should have : * already been done at a higher level. : * : * Since we had to create a new function anyway, we decided to change the : * way the list of gc values is passed to eliminate the compiler warnings : * caused by the DoChangeGC interface. You can pass the values via pC32 : * or pUnion, but not both; one of them must be NULL. If you don't need : * to pass any pointers, you can use either one: : * : * example calling dixChangeGC using pC32 parameter : * : * CARD32 v[2]; : * v[0] = foreground; : * v[1] = background; : * dixChangeGC(client, pGC, GCForeground|GCBackground, v, NULL); : * : * example calling dixChangeGC using pUnion parameter; : * same effect as above : * : * ChangeGCVal v[2]; : * v[0].val = foreground; : * v[1].val = background; : * dixChangeGC(client, pGC, GCForeground|GCBackground, NULL, v); : * : * However, if you need to pass a pointer to a pixmap or font, you MUST : * use the pUnion parameter. : * : * example calling dixChangeGC passing pointers in the value list : * v[1].ptr is a pointer to a pixmap : * : * ChangeGCVal v[2]; : * v[0].val = FillTiled; : * v[1].ptr = pPixmap; : * dixChangeGC(client, pGC, GCFillStyle|GCTile, NULL, v); : * : * Note: we could have gotten by with just the pUnion parameter, but on : * 64 bit machines that would have forced us to copy the value list that : * comes in the ChangeGC request. : * : * Ideally, we'd change all the DoChangeGC calls to dixChangeGC, but this : * is far too many changes to consider at this time, so we've only : * changed the ones that caused compiler warnings. New code should use : * dixChangeGC. : * : * dpw : */ : :#define NEXTVAL(_type, _var) { \ : if (pC32) _var = (_type)*pC32++; \ : else { \ : _var = (_type)(pUnion->val); pUnion++; \ : } \ : } : :#define NEXT_PTR(_type, _var) { \ : assert(pUnion); _var = (_type)pUnion->ptr; pUnion++; } : :_X_EXPORT int :dixChangeGC(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32, ChangeGCValPtr pUnion) :{ /* dixChangeGC total: 24 0.0261 */ : BITS32 index2; : int error = 0; : PixmapPtr pPixmap; : BITS32 maskQ; : : assert( (pC32 && !pUnion) || (!pC32 && pUnion) ); : pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; : : maskQ = mask; /* save these for when we walk the GCque */ 5 0.0054 : while (mask && !error) : { 1 0.0011 : index2 = (BITS32) lowbit (mask); 7 0.0076 : mask &= ~index2; : pGC->stateChanges |= index2; 1 0.0011 : switch (index2) : { : case GCFunction: : { : CARD8 newalu; 3 0.0033 : NEXTVAL(CARD8, newalu); : if (newalu <= GXset) 1 0.0011 : pGC->alu = newalu; : else : { : clientErrorValue = newalu; : error = BadValue; : } : break; : } : case GCPlaneMask: : NEXTVAL(unsigned long, pGC->planemask); : break; : case GCForeground: 1 0.0011 : NEXTVAL(unsigned long, pGC->fgPixel); : /* : * this is for CreateGC : */ : if (!pGC->tileIsPixel && !pGC->tile.pixmap) : { : pGC->tileIsPixel = TRUE; : pGC->tile.pixel = pGC->fgPixel; : } : break; : case GCBackground: : NEXTVAL(unsigned long, pGC->bgPixel); : break; : case GCLineWidth: /* ??? line width is a CARD16 */ : NEXTVAL(CARD16, pGC->lineWidth); : break; : case GCLineStyle: : { : unsigned int newlinestyle; : NEXTVAL(unsigned int, newlinestyle); : if (newlinestyle <= LineDoubleDash) : pGC->lineStyle = newlinestyle; : else : { : clientErrorValue = newlinestyle; : error = BadValue; : } : break; : } : case GCCapStyle: : { : unsigned int newcapstyle; : NEXTVAL(unsigned int, newcapstyle); : if (newcapstyle <= CapProjecting) : pGC->capStyle = newcapstyle; : else : { : clientErrorValue = newcapstyle; : error = BadValue; : } : break; : } : case GCJoinStyle: : { : unsigned int newjoinstyle; : NEXTVAL(unsigned int, newjoinstyle); : if (newjoinstyle <= JoinBevel) : pGC->joinStyle = newjoinstyle; : else : { : clientErrorValue = newjoinstyle; : error = BadValue; : } : break; : } : case GCFillStyle: : { : unsigned int newfillstyle; : NEXTVAL(unsigned int, newfillstyle); : if (newfillstyle <= FillOpaqueStippled) : pGC->fillStyle = newfillstyle; : else : { : clientErrorValue = newfillstyle; : error = BadValue; : } : break; : } : case GCFillRule: : { : unsigned int newfillrule; : NEXTVAL(unsigned int, newfillrule); : if (newfillrule <= WindingRule) : pGC->fillRule = newfillrule; : else : { : clientErrorValue = newfillrule; : error = BadValue; : } : break; : } : case GCTile: : { : XID newpix = 0; : if (pUnion) : { : NEXT_PTR(PixmapPtr, pPixmap); : } : else : { : NEXTVAL(XID, newpix); : pPixmap = (PixmapPtr)SecurityLookupIDByType(client, : newpix, RT_PIXMAP, DixReadAccess); : } : if (pPixmap) : { : if ((pPixmap->drawable.depth != pGC->depth) || : (pPixmap->drawable.pScreen != pGC->pScreen)) : { : error = BadMatch; : } : else : { : pPixmap->refcnt++; : if (!pGC->tileIsPixel) : (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); : pGC->tileIsPixel = FALSE; : pGC->tile.pixmap = pPixmap; : } : } : else : { : clientErrorValue = newpix; : error = BadPixmap; : } : break; : } : case GCStipple: : { : XID newstipple = 0; : if (pUnion) : { : NEXT_PTR(PixmapPtr, pPixmap); : } : else : { : NEXTVAL(XID, newstipple) : pPixmap = (PixmapPtr)SecurityLookupIDByType(client, : newstipple, RT_PIXMAP, DixReadAccess); : } : if (pPixmap) : { : if ((pPixmap->drawable.depth != 1) || : (pPixmap->drawable.pScreen != pGC->pScreen)) : { : error = BadMatch; : } : else : { : pPixmap->refcnt++; : if (pGC->stipple) : (* pGC->pScreen->DestroyPixmap)(pGC->stipple); : pGC->stipple = pPixmap; : } : } : else : { : clientErrorValue = newstipple; : error = BadPixmap; : } : break; : } : case GCTileStipXOrigin: : NEXTVAL(INT16, pGC->patOrg.x); : break; : case GCTileStipYOrigin: : NEXTVAL(INT16, pGC->patOrg.y); : break; : case GCFont: : { : FontPtr pFont; : XID newfont = 0; : if (pUnion) : { : NEXT_PTR(FontPtr, pFont); : } : else : { : NEXTVAL(XID, newfont) : pFont = (FontPtr)SecurityLookupIDByType(client, newfont, : RT_FONT, DixReadAccess); : } : if (pFont) : { : pFont->refcnt++; : if (pGC->font) : CloseFont(pGC->font, (Font)0); : pGC->font = pFont; : } : else : { : clientErrorValue = newfont; : error = BadFont; : } : break; : } : case GCSubwindowMode: : { : unsigned int newclipmode; 1 0.0011 : NEXTVAL(unsigned int, newclipmode); : if (newclipmode <= IncludeInferiors) 1 0.0011 : pGC->subWindowMode = newclipmode; : else : { : clientErrorValue = newclipmode; : error = BadValue; : } : break; : } : case GCGraphicsExposures: : { : unsigned int newge; : NEXTVAL(unsigned int, newge); : if (newge <= xTrue) : pGC->graphicsExposures = newge; : else : { : clientErrorValue = newge; : error = BadValue; : } : break; : } : case GCClipXOrigin: 2 0.0022 : NEXTVAL(INT16, pGC->clipOrg.x); : break; : case GCClipYOrigin: : NEXTVAL(INT16, pGC->clipOrg.y); : break; : case GCClipMask: : { : Pixmap pid = 0; : int clipType = 0; : : if (pUnion) : { : NEXT_PTR(PixmapPtr, pPixmap); : } : else : { : NEXTVAL(Pixmap, pid) : if (pid == None) : { : clipType = CT_NONE; : pPixmap = NullPixmap; : } : else : pPixmap = (PixmapPtr)SecurityLookupIDByType(client, : pid, RT_PIXMAP, DixReadAccess); : } : : if (pPixmap) : { : if ((pPixmap->drawable.depth != 1) || : (pPixmap->drawable.pScreen != pGC->pScreen)) : { : error = BadMatch; : } : else : { : clipType = CT_PIXMAP; : pPixmap->refcnt++; : } : } : else if (!pUnion && (pid != None)) : { : clientErrorValue = pid; : error = BadPixmap; : } : if(error == Success) : { : (*pGC->funcs->ChangeClip)(pGC, clipType, : (pointer)pPixmap, 0); : } : break; : } : case GCDashOffset: : NEXTVAL(INT16, pGC->dashOffset); : break; : case GCDashList: : { : CARD8 newdash; : NEXTVAL(CARD8, newdash); : if (newdash == 4) : { : if (pGC->dash != DefaultDash) : { : xfree(pGC->dash); : pGC->numInDashList = 2; : pGC->dash = DefaultDash; : } : } : else if (newdash != 0) : { : unsigned char *dash; : : dash = (unsigned char *)xalloc(2 * sizeof(unsigned char)); : if (dash) : { : if (pGC->dash != DefaultDash) : xfree(pGC->dash); : pGC->numInDashList = 2; : pGC->dash = dash; : dash[0] = newdash; : dash[1] = newdash; : } : else : error = BadAlloc; : } : else : { : clientErrorValue = newdash; : error = BadValue; : } : break; : } : case GCArcMode: : { : unsigned int newarcmode; : NEXTVAL(unsigned int, newarcmode); : if (newarcmode <= ArcPieSlice) : pGC->arcMode = newarcmode; : else : { : clientErrorValue = newarcmode; : error = BadValue; : } : break; : } : default: : clientErrorValue = maskQ; : error = BadValue; : break; : } : } /* end while mask && !error */ : 1 0.0011 : if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) : { : if (!CreateDefaultTile (pGC)) : { : pGC->fillStyle = FillSolid; : error = BadAlloc; : } : } : (*pGC->funcs->ChangeGC)(pGC, maskQ); : return error; :} : :#undef NEXTVAL :#undef NEXT_PTR : :/* Publically defined entry to ChangeGC. Just calls dixChangeGC and tells : * it that all of the entries are constants or IDs */ :_X_EXPORT int :ChangeGC(GC *pGC, BITS32 mask, XID *pval) 2 0.0022 :{ /* ChangeGC total: 5 0.0054 */ 3 0.0033 : return (dixChangeGC(NullClient, pGC, mask, pval, NULL)); :} : :/* DoChangeGC(pGC, mask, pval, fPointer) : mask is a set of bits indicating which values to change. : pval contains an appropriate value for each mask. : fPointer is true if the values for tiles, stipples, fonts or clipmasks : are pointers instead of IDs. Note: if you are passing pointers you : MUST declare the array of values as type pointer! Other data types : may not be large enough to hold pointers on some machines. Yes, : this means you have to cast to (XID *) when you pass the array to : DoChangeGC. Similarly, if you are not passing pointers (fPointer = 0) you : MUST declare the array as type XID (not unsigned long!), or again the wrong : size data type may be used. To avoid this cruftiness, use dixChangeGC : above. : : if there is an error, the value is marked as changed : anyway, which is probably wrong, but infrequent. : :NOTE: : all values sent over the protocol for ChangeGC requests are :32 bits long :*/ :_X_EXPORT int :DoChangeGC(GC *pGC, BITS32 mask, XID *pval, int fPointer) :{ : if (fPointer) : /* XXX might be a problem on 64 bit big-endian servers */ : return dixChangeGC(NullClient, pGC, mask, NULL, (ChangeGCValPtr)pval); : else : return dixChangeGC(NullClient, pGC, mask, pval, NULL); :} : : :/* CreateGC(pDrawable, mask, pval, pStatus) : creates a default GC for the given drawable, using mask to fill : in any non-default values. : Returns a pointer to the new GC on success, NULL otherwise. : returns status of non-default fields in pStatus :BUG: : should check for failure to create default tile : :*/ : :static GCPtr :AllocateGC(ScreenPtr pScreen) :{ /* AllocateGC total: 2 0.0022 */ : GCPtr pGC; : char *ptr; : DevUnion *ppriv; : unsigned *sizes; : unsigned size; : int i; : : pGC = (GCPtr)xalloc(pScreen->totalGCSize); : if (pGC) : { : ppriv = (DevUnion *)(pGC + 1); : pGC->devPrivates = ppriv; : sizes = pScreen->GCPrivateSizes; : ptr = (char *)(ppriv + pScreen->GCPrivateLen); : for (i = pScreen->GCPrivateLen; --i >= 0; ppriv++, sizes++) : { : if ( (size = *sizes) ) : { : ppriv->ptr = (pointer)ptr; : ptr += size; : } : else 1 0.0011 : ppriv->ptr = (pointer)NULL; : } : } : return pGC; 1 0.0011 :} : :_X_EXPORT GCPtr :CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus) :{ /* CreateGC total: 1 0.0011 */ : GCPtr pGC; : : pGC = AllocateGC(pDrawable->pScreen); : if (!pGC) : { : *pStatus = BadAlloc; : return (GCPtr)NULL; : } : : pGC->pScreen = pDrawable->pScreen; : pGC->depth = pDrawable->depth; : pGC->alu = GXcopy; /* dst <- src */ : pGC->planemask = ~0; : pGC->serialNumber = GC_CHANGE_SERIAL_BIT; : pGC->funcs = 0; : : pGC->fgPixel = 0; : pGC->bgPixel = 1; : pGC->lineWidth = 0; : pGC->lineStyle = LineSolid; : pGC->capStyle = CapButt; : pGC->joinStyle = JoinMiter; : pGC->fillStyle = FillSolid; : pGC->fillRule = EvenOddRule; : pGC->arcMode = ArcPieSlice; : if (mask & GCForeground) : { : /* : * magic special case -- ChangeGC checks for this condition : * and snags the Foreground value to create a pseudo default-tile : */ : pGC->tileIsPixel = FALSE; : pGC->tile.pixmap = NullPixmap; : } : else : { : pGC->tileIsPixel = TRUE; : pGC->tile.pixel = 0; : } : 1 0.0011 : pGC->patOrg.x = 0; : pGC->patOrg.y = 0; : pGC->subWindowMode = ClipByChildren; : pGC->graphicsExposures = TRUE; : pGC->clipOrg.x = 0; : pGC->clipOrg.y = 0; : pGC->clientClipType = CT_NONE; : pGC->clientClip = (pointer)NULL; : pGC->numInDashList = 2; : pGC->dash = DefaultDash; : pGC->dashOffset = 0; : pGC->lastWinOrg.x = 0; : pGC->lastWinOrg.y = 0; : : /* use the default font and stipple */ : pGC->font = defaultFont; : defaultFont->refcnt++; : pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; : pGC->stipple->refcnt++; : : pGC->stateChanges = (1 << (GCLastBit+1)) - 1; : if (!(*pGC->pScreen->CreateGC)(pGC)) : *pStatus = BadAlloc; : else if (mask) : *pStatus = ChangeGC(pGC, mask, pval); : else : *pStatus = Success; : if (*pStatus != Success) : { : if (!pGC->tileIsPixel && !pGC->tile.pixmap) : pGC->tileIsPixel = TRUE; /* undo special case */ : FreeGC(pGC, (XID)0); : pGC = (GCPtr)NULL; : } : : return (pGC); :} : :static Bool :CreateDefaultTile (GCPtr pGC) :{ : XID tmpval[3]; : PixmapPtr pTile; : GCPtr pgcScratch; : xRectangle rect; : CARD16 w, h; : : w = 1; : h = 1; : (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); : pTile = (PixmapPtr) : (*pGC->pScreen->CreatePixmap)(pGC->pScreen, : w, h, pGC->depth); : pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); : if (!pTile || !pgcScratch) : { : if (pTile) : (*pTile->drawable.pScreen->DestroyPixmap)(pTile); : if (pgcScratch) : FreeScratchGC(pgcScratch); : return FALSE; : } : tmpval[0] = GXcopy; : tmpval[1] = pGC->tile.pixel; : tmpval[2] = FillSolid; : (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle, : tmpval); : ValidateGC((DrawablePtr)pTile, pgcScratch); : rect.x = 0; : rect.y = 0; : rect.width = w; : rect.height = h; : (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); : /* Always remember to free the scratch graphics context after use. */ : FreeScratchGC(pgcScratch); : : pGC->tileIsPixel = FALSE; : pGC->tile.pixmap = pTile; : return TRUE; :} : :_X_EXPORT int :CopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask) :{ : BITS32 index2; : BITS32 maskQ; : int error = 0; : : if (pgcSrc == pgcDst) : return Success; : pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; : pgcDst->stateChanges |= mask; : maskQ = mask; : while (mask) : { : index2 = (BITS32) lowbit (mask); : mask &= ~index2; : switch (index2) : { : case GCFunction: : pgcDst->alu = pgcSrc->alu; : break; : case GCPlaneMask: : pgcDst->planemask = pgcSrc->planemask; : break; : case GCForeground: : pgcDst->fgPixel = pgcSrc->fgPixel; : break; : case GCBackground: : pgcDst->bgPixel = pgcSrc->bgPixel; : break; : case GCLineWidth: : pgcDst->lineWidth = pgcSrc->lineWidth; : break; : case GCLineStyle: : pgcDst->lineStyle = pgcSrc->lineStyle; : break; : case GCCapStyle: : pgcDst->capStyle = pgcSrc->capStyle; : break; : case GCJoinStyle: : pgcDst->joinStyle = pgcSrc->joinStyle; : break; : case GCFillStyle: : pgcDst->fillStyle = pgcSrc->fillStyle; : break; : case GCFillRule: : pgcDst->fillRule = pgcSrc->fillRule; : break; : case GCTile: : { : if (EqualPixUnion(pgcDst->tileIsPixel, : pgcDst->tile, : pgcSrc->tileIsPixel, : pgcSrc->tile)) : { : break; : } : if (!pgcDst->tileIsPixel) : (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); : pgcDst->tileIsPixel = pgcSrc->tileIsPixel; : pgcDst->tile = pgcSrc->tile; : if (!pgcDst->tileIsPixel) : pgcDst->tile.pixmap->refcnt++; : break; : } : case GCStipple: : { : if (pgcDst->stipple == pgcSrc->stipple) : break; : if (pgcDst->stipple) : (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); : pgcDst->stipple = pgcSrc->stipple; : if (pgcDst->stipple) : pgcDst->stipple->refcnt ++; : break; : } : case GCTileStipXOrigin: : pgcDst->patOrg.x = pgcSrc->patOrg.x; : break; : case GCTileStipYOrigin: : pgcDst->patOrg.y = pgcSrc->patOrg.y; : break; : case GCFont: : if (pgcDst->font == pgcSrc->font) : break; : if (pgcDst->font) : CloseFont(pgcDst->font, (Font)0); : if ((pgcDst->font = pgcSrc->font) != NullFont) : (pgcDst->font)->refcnt++; : break; : case GCSubwindowMode: : pgcDst->subWindowMode = pgcSrc->subWindowMode; : break; : case GCGraphicsExposures: : pgcDst->graphicsExposures = pgcSrc->graphicsExposures; : break; : case GCClipXOrigin: : pgcDst->clipOrg.x = pgcSrc->clipOrg.x; : break; : case GCClipYOrigin: : pgcDst->clipOrg.y = pgcSrc->clipOrg.y; : break; : case GCClipMask: : (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); : break; : case GCDashOffset: : pgcDst->dashOffset = pgcSrc->dashOffset; : break; : case GCDashList: : if (pgcSrc->dash == DefaultDash) : { : if (pgcDst->dash != DefaultDash) : { : xfree(pgcDst->dash); : pgcDst->numInDashList = pgcSrc->numInDashList; : pgcDst->dash = pgcSrc->dash; : } : } : else : { : unsigned char *dash; : unsigned int i; : : dash = (unsigned char *)xalloc(pgcSrc->numInDashList * : sizeof(unsigned char)); : if (dash) : { : if (pgcDst->dash != DefaultDash) : xfree(pgcDst->dash); : pgcDst->numInDashList = pgcSrc->numInDashList; : pgcDst->dash = dash; : for (i=0; inumInDashList; i++) : dash[i] = pgcSrc->dash[i]; : } : else : error = BadAlloc; : } : break; : case GCArcMode: : pgcDst->arcMode = pgcSrc->arcMode; : break; : default: : clientErrorValue = maskQ; : error = BadValue; : break; : } : } : if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) : { : if (!CreateDefaultTile (pgcDst)) : { : pgcDst->fillStyle = FillSolid; : error = BadAlloc; : } : } : (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); : return error; :} : :/** : * does the diX part of freeing the characteristics in the GC. : * : * \param value must conform to DeleteType : */ :_X_EXPORT int :FreeGC(pointer value, XID gid) :{ /* FreeGC total: 1 0.0011 */ : GCPtr pGC = (GCPtr)value; : : CloseFont(pGC->font, (Font)0); : (* pGC->funcs->DestroyClip)(pGC); : : if (!pGC->tileIsPixel) : (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); : if (pGC->stipple) : (* pGC->pScreen->DestroyPixmap)(pGC->stipple); : : (*pGC->funcs->DestroyGC) (pGC); 1 0.0011 : if (pGC->dash != DefaultDash) : xfree(pGC->dash); : xfree(pGC); : return(Success); :} : :/* CreateScratchGC(pScreen, depth) : like CreateGC, but doesn't do the default tile or stipple, :since we can't create them without already having a GC. any code :using the tile or stipple has to set them explicitly anyway, :since the state of the scratch gc is unknown. This is OK :because ChangeGC() has to be able to deal with NULL tiles and :stipples anyway (in case the CreateGC() call has provided a :value for them -- we can't set the default tile until the :client-supplied attributes are installed, since the fgPixel :is what fills the default tile. (maybe this comment should :go with CreateGC() or ChangeGC().) :*/ : :_X_EXPORT GCPtr :CreateScratchGC(ScreenPtr pScreen, unsigned depth) :{ : GCPtr pGC; : : pGC = AllocateGC(pScreen); : if (!pGC) : return (GCPtr)NULL; : : pGC->pScreen = pScreen; : pGC->depth = depth; : pGC->alu = GXcopy; /* dst <- src */ : pGC->planemask = ~0; : pGC->serialNumber = 0; : : pGC->fgPixel = 0; : pGC->bgPixel = 1; : pGC->lineWidth = 0; : pGC->lineStyle = LineSolid; : pGC->capStyle = CapButt; : pGC->joinStyle = JoinMiter; : pGC->fillStyle = FillSolid; : pGC->fillRule = EvenOddRule; : pGC->arcMode = ArcPieSlice; : pGC->font = defaultFont; : if ( pGC->font) /* necessary, because open of default font could fail */ : pGC->font->refcnt++; : pGC->tileIsPixel = TRUE; : pGC->tile.pixel = 0; : pGC->stipple = NullPixmap; : pGC->patOrg.x = 0; : pGC->patOrg.y = 0; : pGC->subWindowMode = ClipByChildren; : pGC->graphicsExposures = TRUE; : pGC->clipOrg.x = 0; : pGC->clipOrg.y = 0; : pGC->clientClipType = CT_NONE; : pGC->dashOffset = 0; : pGC->numInDashList = 2; : pGC->dash = DefaultDash; : pGC->lastWinOrg.x = 0; : pGC->lastWinOrg.y = 0; : : pGC->stateChanges = (1 << (GCLastBit+1)) - 1; : if (!(*pScreen->CreateGC)(pGC)) : { : FreeGC(pGC, (XID)0); : pGC = (GCPtr)NULL; : } : return pGC; :} : :void :FreeGCperDepth(int screenNum) :{ : int i; : ScreenPtr pScreen; : GCPtr *ppGC; : : pScreen = screenInfo.screens[screenNum]; : ppGC = pScreen->GCperDepth; : : for (i = 0; i <= pScreen->numDepths; i++) : (void)FreeGC(ppGC[i], (XID)0); : pScreen->rgf = ~0L; :} : : :Bool :CreateGCperDepth(int screenNum) :{ : int i; : ScreenPtr pScreen; : DepthPtr pDepth; : GCPtr *ppGC; : : pScreen = screenInfo.screens[screenNum]; : pScreen->rgf = 0; : ppGC = pScreen->GCperDepth; : /* do depth 1 separately because it's not included in list */ : if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) : return FALSE; : ppGC[0]->graphicsExposures = FALSE; : /* Make sure we don't overflow GCperDepth[] */ : if( pScreen->numDepths > MAXFORMATS ) : return FALSE; : : pDepth = pScreen->allowedDepths; : for (i=0; inumDepths; i++, pDepth++) : { : if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) : { : for (; i >= 0; i--) : (void)FreeGC(ppGC[i], (XID)0); : return FALSE; : } : ppGC[i+1]->graphicsExposures = FALSE; : } : return TRUE; :} : :Bool :CreateDefaultStipple(int screenNum) :{ : ScreenPtr pScreen; : XID tmpval[3]; : xRectangle rect; : CARD16 w, h; : GCPtr pgcScratch; : : pScreen = screenInfo.screens[screenNum]; : : w = 16; : h = 16; : (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); : if (!(pScreen->PixmapPerDepth[0] = : (*pScreen->CreatePixmap)(pScreen, w, h, 1))) : return FALSE; : /* fill stipple with 1 */ : tmpval[0] = GXcopy; tmpval[1] = 1; tmpval[2] = FillSolid; : pgcScratch = GetScratchGC(1, pScreen); : if (!pgcScratch) : { : (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); : return FALSE; : } : (void)ChangeGC(pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); : ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); : rect.x = 0; : rect.y = 0; : rect.width = w; : rect.height = h; : (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], : pgcScratch, 1, &rect); : FreeScratchGC(pgcScratch); : return TRUE; :} : :void :FreeDefaultStipple(int screenNum) :{ : ScreenPtr pScreen = screenInfo.screens[screenNum]; : (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); :} : :_X_EXPORT int :SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) :{ : long i; : unsigned char *p, *indash; : BITS32 maskQ = 0; : : i = ndash; : p = pdash; : while (i--) : { : if (!*p++) : { : /* dash segment must be > 0 */ : clientErrorValue = 0; : return BadValue; : } : } : : if (ndash & 1) : p = (unsigned char *)xalloc(2 * ndash * sizeof(unsigned char)); : else : p = (unsigned char *)xalloc(ndash * sizeof(unsigned char)); : if (!p) : return BadAlloc; : : pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; : if (offset != pGC->dashOffset) : { : pGC->dashOffset = offset; : pGC->stateChanges |= GCDashOffset; : maskQ |= GCDashOffset; : } : : if (pGC->dash != DefaultDash) : xfree(pGC->dash); : pGC->numInDashList = ndash; : pGC->dash = p; : if (ndash & 1) : { : pGC->numInDashList += ndash; : indash = pdash; : i = ndash; : while (i--) : *p++ = *indash++; : } : while(ndash--) : *p++ = *pdash++; : pGC->stateChanges |= GCDashList; : maskQ |= GCDashList; : : if (pGC->funcs->ChangeGC) : (*pGC->funcs->ChangeGC) (pGC, maskQ); : return Success; :} : :_X_EXPORT int :VerifyRectOrder(int nrects, xRectangle *prects, int ordering) :{ /* VerifyRectOrder total: 1 0.0011 */ : xRectangle *prectP, *prectN; : int i; : : switch(ordering) : { : case Unsorted: : return CT_UNSORTED; : case YSorted: : if(nrects > 1) : { : for(i = 1, prectP = prects, prectN = prects + 1; : i < nrects; : i++, prectP++, prectN++) : if(prectN->y < prectP->y) : return -1; : } : return CT_YSORTED; : case YXSorted: : if(nrects > 1) : { : for(i = 1, prectP = prects, prectN = prects + 1; : i < nrects; : i++, prectP++, prectN++) : if((prectN->y < prectP->y) || : ( (prectN->y == prectP->y) && : (prectN->x < prectP->x) ) ) : return -1; : } : return CT_YXSORTED; : case YXBanded: 1 0.0011 : if(nrects > 1) : { : for(i = 1, prectP = prects, prectN = prects + 1; : i < nrects; : i++, prectP++, prectN++) : if((prectN->y != prectP->y && : prectN->y < prectP->y + (int) prectP->height) || : ((prectN->y == prectP->y) && : (prectN->height != prectP->height || : prectN->x < prectP->x + (int) prectP->width))) : return -1; : } : return CT_YXBANDED; : } : return -1; :} : :_X_EXPORT int :SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, : xRectangle *prects, int ordering) :{ /* SetClipRects total: 2 0.0022 */ : int newct, size; : xRectangle *prectsNew; : : newct = VerifyRectOrder(nrects, prects, ordering); : if (newct < 0) : return(BadMatch); : size = nrects * sizeof(xRectangle); : prectsNew = (xRectangle *) xalloc(size); : if (!prectsNew && size) : return BadAlloc; : : pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 1 0.0011 : pGC->clipOrg.x = xOrigin; : pGC->stateChanges |= GCClipXOrigin; : : pGC->clipOrg.y = yOrigin; : pGC->stateChanges |= GCClipYOrigin; : : if (size) : memmove((char *)prectsNew, (char *)prects, size); : (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); 1 0.0011 : if (pGC->funcs->ChangeGC) : (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); : return Success; :} : : :/* : sets reasonable defaults : if we can get a pre-allocated one, use it and mark it as used. : if we can't, create one out of whole cloth (The Velveteen GC -- if : you use it often enough it will become real.) :*/ :_X_EXPORT GCPtr :GetScratchGC(unsigned depth, ScreenPtr pScreen) 2 0.0022 :{ /* GetScratchGC total: 8 0.0087 */ : int i; : GCPtr pGC; : : for (i=0; i<=pScreen->numDepths; i++) 2 0.0022 : if ( pScreen->GCperDepth[i]->depth == depth && : !(pScreen->rgf & (1L << (i+1))) : ) : { : pScreen->rgf |= (1L << (i+1)); : pGC = (pScreen->GCperDepth[i]); : : pGC->alu = GXcopy; : pGC->planemask = ~0; : pGC->serialNumber = 0; : pGC->fgPixel = 0; : pGC->bgPixel = 1; : pGC->lineWidth = 0; : pGC->lineStyle = LineSolid; : pGC->capStyle = CapButt; : pGC->joinStyle = JoinMiter; : pGC->fillStyle = FillSolid; : pGC->fillRule = EvenOddRule; : pGC->arcMode = ArcChord; 3 0.0033 : pGC->patOrg.x = 0; : pGC->patOrg.y = 0; : pGC->subWindowMode = ClipByChildren; : pGC->graphicsExposures = FALSE; : pGC->clipOrg.x = 0; : pGC->clipOrg.y = 0; : if (pGC->clientClipType != CT_NONE) : (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); : pGC->stateChanges = (1 << (GCLastBit+1)) - 1; : return pGC; : } : /* if we make it this far, need to roll our own */ : pGC = CreateScratchGC(pScreen, depth); : if (pGC) : pGC->graphicsExposures = FALSE; : return pGC; 1 0.0011 :} : :/* : if the gc to free is in the table of pre-existing ones, :mark it as available. : if not, free it for real :*/ :_X_EXPORT void :FreeScratchGC(GCPtr pGC) 4 0.0044 :{ /* FreeScratchGC total: 10 0.0109 */ : ScreenPtr pScreen = pGC->pScreen; : int i; : 1 0.0011 : for (i=0; i<=pScreen->numDepths; i++) : { 3 0.0033 : if ( pScreen->GCperDepth[i] == pGC) : { : pScreen->rgf &= ~(1L << (i+1)); 1 0.0011 : return; : } : } : (void)FreeGC(pGC, (GContext)0); 1 0.0011 :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/Xext/security.c" * * 50 0.0545 */ :/* : :Copyright 1996, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : :*/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "dixstruct.h" :#include "extnsionst.h" :#include "windowstr.h" :#include "inputstr.h" :#include "scrnintstr.h" :#include "gcstruct.h" :#include "colormapst.h" :#include "propertyst.h" :#include "xacestr.h" :#include "securitysrv.h" :#include :#include :#include :#ifdef XAPPGROUP :#include "appgroup.h" :#endif :#include /* for file reading operations */ :#include /* for XA_STRING */ : :#ifndef DEFAULTPOLICYFILE :# define DEFAULTPOLICYFILE NULL :#endif :#if defined(WIN32) || defined(__CYGWIN__) :#include :#undef index :#endif : :#include "modinit.h" : :static int SecurityErrorBase; /* first Security error number */ :static int SecurityEventBase; /* first Security event number */ :static int securityClientPrivateIndex; :static int securityExtnsnPrivateIndex; : :/* this is what we store as client security state */ :typedef struct { : unsigned int trustLevel; : XID authId; :} SecurityClientStateRec; : :#define STATEVAL(extnsn) \ : ((extnsn)->devPrivates[securityExtnsnPrivateIndex].val) :#define STATEPTR(client) \ : ((client)->devPrivates[securityClientPrivateIndex].ptr) :#define TRUSTLEVEL(client) \ : (((SecurityClientStateRec*)STATEPTR(client))->trustLevel) :#define AUTHID(client) \ : (((SecurityClientStateRec*)STATEPTR(client))->authId) : :static CallbackListPtr SecurityValidateGroupCallback = NULL; : :RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */ : :static RESTYPE RTEventClient; : :#define CALLBACK(name) static void \ :name(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) : :/* SecurityAudit : * : * Arguments: : * format is the formatting string to be used to interpret the : * remaining arguments. : * : * Returns: nothing. : * : * Side Effects: : * Writes the message to the log file if security logging is on. : */ : :static void :SecurityAudit(char *format, ...) :{ : va_list args; : : if (auditTrailLevel < SECURITY_AUDIT_LEVEL) : return; : va_start(args, format); : VAuditF(format, args); : va_end(args); :} /* SecurityAudit */ : :#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) : :/* SecurityDeleteAuthorization : * : * Arguments: : * value is the authorization to delete. : * id is its resource ID. : * : * Returns: Success. : * : * Side Effects: : * Frees everything associated with the authorization. : */ : :static int :SecurityDeleteAuthorization( : pointer value, : XID id) :{ : SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; : unsigned short name_len, data_len; : char *name, *data; : int status; : int i; : OtherClientsPtr pEventClient; : : /* Remove the auth using the os layer auth manager */ : : status = AuthorizationFromID(pAuth->id, &name_len, &name, : &data_len, &data); : assert(status); : status = RemoveAuthorization(name_len, name, data_len, data); : assert(status); : (void)status; : : /* free the auth timer if there is one */ : : if (pAuth->timer) TimerFree(pAuth->timer); : : /* send revoke events */ : : while ((pEventClient = pAuth->eventClients)) : { : /* send revocation event event */ : ClientPtr client = rClient(pEventClient); : : if (!client->clientGone) : { : xSecurityAuthorizationRevokedEvent are; : are.type = SecurityEventBase + XSecurityAuthorizationRevoked; : are.sequenceNumber = client->sequence; : are.authId = pAuth->id; : WriteEventsToClient(client, 1, (xEvent *)&are); : } : FreeResource(pEventClient->resource, RT_NONE); : } : : /* kill all clients using this auth */ : : for (i = 1; iid)) : CloseDownClient(clients[i]); : } : : SecurityAudit("revoked authorization ID %d\n", pAuth->id); : xfree(pAuth); : return Success; : :} /* SecurityDeleteAuthorization */ : : :/* resource delete function for RTEventClient */ :static int :SecurityDeleteAuthorizationEventClient( : pointer value, : XID id) :{ : OtherClientsPtr pEventClient, prev = NULL; : SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; : : for (pEventClient = pAuth->eventClients; : pEventClient; : pEventClient = pEventClient->next) : { : if (pEventClient->resource == id) : { : if (prev) : prev->next = pEventClient->next; : else : pAuth->eventClients = pEventClient->next; : xfree(pEventClient); : return(Success); : } : prev = pEventClient; : } : /*NOTREACHED*/ : return -1; /* make compiler happy */ :} /* SecurityDeleteAuthorizationEventClient */ : : :/* SecurityComputeAuthorizationTimeout : * : * Arguments: : * pAuth is the authorization for which we are computing the timeout : * seconds is the number of seconds we want to wait : * : * Returns: : * the number of milliseconds that the auth timer should be set to : * : * Side Effects: : * Sets pAuth->secondsRemaining to any "overflow" amount of time : * that didn't fit in 32 bits worth of milliseconds : */ : :static CARD32 :SecurityComputeAuthorizationTimeout( : SecurityAuthorizationPtr pAuth, : unsigned int seconds) :{ : /* maxSecs is the number of full seconds that can be expressed in : * 32 bits worth of milliseconds : */ : CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND; : : if (seconds > maxSecs) : { /* only come here if we want to wait more than 49 days */ : pAuth->secondsRemaining = seconds - maxSecs; : return maxSecs * MILLI_PER_SECOND; : } : else : { /* by far the common case */ : pAuth->secondsRemaining = 0; : return seconds * MILLI_PER_SECOND; : } :} /* SecurityStartAuthorizationTimer */ : :/* SecurityAuthorizationExpired : * : * This function is passed as an argument to TimerSet and gets called from : * the timer manager in the os layer when its time is up. : * : * Arguments: : * timer is the timer for this authorization. : * time is the current time. : * pval is the authorization whose time is up. : * : * Returns: : * A new time delay in milliseconds if the timer should wait some : * more, else zero. : * : * Side Effects: : * Frees the authorization resource if the timeout period is really : * over, otherwise recomputes pAuth->secondsRemaining. : */ : :static CARD32 :SecurityAuthorizationExpired( : OsTimerPtr timer, : CARD32 time, : pointer pval) :{ : SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval; : : assert(pAuth->timer == timer); : : if (pAuth->secondsRemaining) : { : return SecurityComputeAuthorizationTimeout(pAuth, : pAuth->secondsRemaining); : } : else : { : FreeResource(pAuth->id, RT_NONE); : return 0; : } :} /* SecurityAuthorizationExpired */ : :/* SecurityStartAuthorizationTimer : * : * Arguments: : * pAuth is the authorization whose timer should be started. : * : * Returns: nothing. : * : * Side Effects: : * A timer is started, set to expire after the timeout period for : * this authorization. When it expires, the function : * SecurityAuthorizationExpired will be called. : */ : :static void :SecurityStartAuthorizationTimer( : SecurityAuthorizationPtr pAuth) :{ : pAuth->timer = TimerSet(pAuth->timer, 0, : SecurityComputeAuthorizationTimeout(pAuth, pAuth->timeout), : SecurityAuthorizationExpired, pAuth); :} /* SecurityStartAuthorizationTimer */ : : :/* Proc functions all take a client argument, execute the request in : * client->requestBuffer, and return a protocol error status. : */ : :static int :ProcSecurityQueryVersion( : ClientPtr client) :{ : /* REQUEST(xSecurityQueryVersionReq); */ : xSecurityQueryVersionReply rep; : : /* paranoia: this "can't happen" because this extension is hidden : * from untrusted clients, but just in case... : */ : if (TRUSTLEVEL(client) != XSecurityClientTrusted) : return BadRequest; : : REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); : rep.type = X_Reply; : rep.sequenceNumber = client->sequence; : rep.length = 0; : rep.majorVersion = SECURITY_MAJOR_VERSION; : rep.minorVersion = SECURITY_MINOR_VERSION; : if(client->swapped) : { : register char n; : swaps(&rep.sequenceNumber, n); : swaps(&rep.majorVersion, n); : swaps(&rep.minorVersion, n); : } : (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply), : (char *)&rep); : return (client->noClientException); :} /* ProcSecurityQueryVersion */ : : :static int :SecurityEventSelectForAuthorization( : SecurityAuthorizationPtr pAuth, : ClientPtr client, : Mask mask) :{ : OtherClients *pEventClient; : : for (pEventClient = pAuth->eventClients; : pEventClient; : pEventClient = pEventClient->next) : { : if (SameClient(pEventClient, client)) : { : if (mask == 0) : FreeResource(pEventClient->resource, RT_NONE); : else : pEventClient->mask = mask; : return Success; : } : } : : pEventClient = (OtherClients *) xalloc(sizeof(OtherClients)); : if (!pEventClient) : return BadAlloc; : pEventClient->mask = mask; : pEventClient->resource = FakeClientID(client->index); : pEventClient->next = pAuth->eventClients; : if (!AddResource(pEventClient->resource, RTEventClient, : (pointer)pAuth)) : { : xfree(pEventClient); : return BadAlloc; : } : pAuth->eventClients = pEventClient; : : return Success; :} /* SecurityEventSelectForAuthorization */ : : :static int :ProcSecurityGenerateAuthorization( : ClientPtr client) :{ : REQUEST(xSecurityGenerateAuthorizationReq); : int len; /* request length in CARD32s*/ : Bool removeAuth = FALSE; /* if bailout, call RemoveAuthorization? */ : SecurityAuthorizationPtr pAuth = NULL; /* auth we are creating */ : int err; /* error to return from this function */ : XID authId; /* authorization ID assigned by os layer */ : xSecurityGenerateAuthorizationReply rep; /* reply struct */ : unsigned int trustLevel; /* trust level of new auth */ : XID group; /* group of new auth */ : CARD32 timeout; /* timeout of new auth */ : CARD32 *values; /* list of supplied attributes */ : char *protoname; /* auth proto name sent in request */ : char *protodata; /* auth proto data sent in request */ : unsigned int authdata_len; /* # bytes of generated auth data */ : char *pAuthdata; /* generated auth data */ : Mask eventMask; /* what events on this auth does client want */ : : /* paranoia: this "can't happen" because this extension is hidden : * from untrusted clients, but just in case... : */ : if (TRUSTLEVEL(client) != XSecurityClientTrusted) : return BadRequest; : : /* check request length */ : : REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); : len = SIZEOF(xSecurityGenerateAuthorizationReq) >> 2; : len += (stuff->nbytesAuthProto + (unsigned)3) >> 2; : len += (stuff->nbytesAuthData + (unsigned)3) >> 2; : values = ((CARD32 *)stuff) + len; : len += Ones(stuff->valueMask); : if (client->req_len != len) : return BadLength; : : /* check valuemask */ : if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes) : { : client->errorValue = stuff->valueMask; : return BadValue; : } : : /* check timeout */ : timeout = 60; : if (stuff->valueMask & XSecurityTimeout) : { : timeout = *values++; : } : : /* check trustLevel */ : trustLevel = XSecurityClientUntrusted; : if (stuff->valueMask & XSecurityTrustLevel) : { : trustLevel = *values++; : if (trustLevel != XSecurityClientTrusted && : trustLevel != XSecurityClientUntrusted) : { : client->errorValue = trustLevel; : return BadValue; : } : } : : /* check group */ : group = None; : if (stuff->valueMask & XSecurityGroup) : { : group = *values++; : if (SecurityValidateGroupCallback) : { : SecurityValidateGroupInfoRec vgi; : vgi.group = group; : vgi.valid = FALSE; : CallCallbacks(&SecurityValidateGroupCallback, (pointer)&vgi); : : /* if nobody said they recognized it, it's an error */ : : if (!vgi.valid) : { : client->errorValue = group; : return BadValue; : } : } : } : : /* check event mask */ : eventMask = 0; : if (stuff->valueMask & XSecurityEventMask) : { : eventMask = *values++; : if (eventMask & ~XSecurityAllEventMasks) : { : client->errorValue = eventMask; : return BadValue; : } : } : : protoname = (char *)&stuff[1]; : protodata = protoname + ((stuff->nbytesAuthProto + (unsigned)3) >> 2); : : /* call os layer to generate the authorization */ : : authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname, : stuff->nbytesAuthData, protodata, : &authdata_len, &pAuthdata); : if ((XID) ~0L == authId) : { : err = SecurityErrorBase + XSecurityBadAuthorizationProtocol; : goto bailout; : } : : /* now that we've added the auth, remember to remove it if we have to : * abort the request for some reason (like allocation failure) : */ : removeAuth = TRUE; : : /* associate additional information with this auth ID */ : : pAuth = (SecurityAuthorizationPtr)xalloc(sizeof(SecurityAuthorizationRec)); : if (!pAuth) : { : err = BadAlloc; : goto bailout; : } : : /* fill in the auth fields */ : : pAuth->id = authId; : pAuth->timeout = timeout; : pAuth->group = group; : pAuth->trustLevel = trustLevel; : pAuth->refcnt = 0; /* the auth was just created; nobody's using it yet */ : pAuth->secondsRemaining = 0; : pAuth->timer = NULL; : pAuth->eventClients = NULL; : : /* handle event selection */ : if (eventMask) : { : err = SecurityEventSelectForAuthorization(pAuth, client, eventMask); : if (err != Success) : goto bailout; : } : : if (!AddResource(authId, SecurityAuthorizationResType, pAuth)) : { : err = BadAlloc; : goto bailout; : } : : /* start the timer ticking */ : : if (pAuth->timeout != 0) : SecurityStartAuthorizationTimer(pAuth); : : /* tell client the auth id and data */ : : rep.type = X_Reply; : rep.length = (authdata_len + 3) >> 2; : rep.sequenceNumber = client->sequence; : rep.authId = authId; : rep.dataLength = authdata_len; : : if (client->swapped) : { : register char n; : swapl(&rep.length, n); : swaps(&rep.sequenceNumber, n); : swapl(&rep.authId, n); : swaps(&rep.dataLength, n); : } : : WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply), : (char *)&rep); : WriteToClient(client, authdata_len, pAuthdata); : : SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n", : client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout, : pAuth->group, eventMask); : : /* the request succeeded; don't call RemoveAuthorization or free pAuth */ : : removeAuth = FALSE; : pAuth = NULL; : err = client->noClientException; : :bailout: : if (removeAuth) : RemoveAuthorization(stuff->nbytesAuthProto, protoname, : authdata_len, pAuthdata); : if (pAuth) xfree(pAuth); : return err; : :} /* ProcSecurityGenerateAuthorization */ : :static int :ProcSecurityRevokeAuthorization( : ClientPtr client) :{ : REQUEST(xSecurityRevokeAuthorizationReq); : SecurityAuthorizationPtr pAuth; : : /* paranoia: this "can't happen" because this extension is hidden : * from untrusted clients, but just in case... : */ : if (TRUSTLEVEL(client) != XSecurityClientTrusted) : return BadRequest; : : REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); : : pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(client, : stuff->authId, SecurityAuthorizationResType, DixDestroyAccess); : if (!pAuth) : return SecurityErrorBase + XSecurityBadAuthorization; : : FreeResource(stuff->authId, RT_NONE); : return Success; :} /* ProcSecurityRevokeAuthorization */ : : :static int :ProcSecurityDispatch( : ClientPtr client) :{ : REQUEST(xReq); : : switch (stuff->data) : { : case X_SecurityQueryVersion: : return ProcSecurityQueryVersion(client); : case X_SecurityGenerateAuthorization: : return ProcSecurityGenerateAuthorization(client); : case X_SecurityRevokeAuthorization: : return ProcSecurityRevokeAuthorization(client); : default: : return BadRequest; : } :} /* ProcSecurityDispatch */ : :static int :SProcSecurityQueryVersion( : ClientPtr client) :{ : REQUEST(xSecurityQueryVersionReq); : register char n; : : swaps(&stuff->length, n); : REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); : swaps(&stuff->majorVersion, n); : swaps(&stuff->minorVersion,n); : return ProcSecurityQueryVersion(client); :} /* SProcSecurityQueryVersion */ : : :static int :SProcSecurityGenerateAuthorization( : ClientPtr client) :{ : REQUEST(xSecurityGenerateAuthorizationReq); : register char n; : CARD32 *values; : unsigned long nvalues; : : swaps(&stuff->length, n); : REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); : swaps(&stuff->nbytesAuthProto, n); : swaps(&stuff->nbytesAuthData, n); : swapl(&stuff->valueMask, n); : values = (CARD32 *)(&stuff[1]) + : ((stuff->nbytesAuthProto + (unsigned)3) >> 2) + : ((stuff->nbytesAuthData + (unsigned)3) >> 2); : nvalues = (((CARD32 *)stuff) + stuff->length) - values; : SwapLongs(values, nvalues); : return ProcSecurityGenerateAuthorization(client); :} /* SProcSecurityGenerateAuthorization */ : : :static int :SProcSecurityRevokeAuthorization( : ClientPtr client) :{ : REQUEST(xSecurityRevokeAuthorizationReq); : register char n; : : swaps(&stuff->length, n); : REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); : swapl(&stuff->authId, n); : return ProcSecurityRevokeAuthorization(client); :} /* SProcSecurityRevokeAuthorization */ : : :static int :SProcSecurityDispatch( : ClientPtr client) :{ : REQUEST(xReq); : : switch (stuff->data) : { : case X_SecurityQueryVersion: : return SProcSecurityQueryVersion(client); : case X_SecurityGenerateAuthorization: : return SProcSecurityGenerateAuthorization(client); : case X_SecurityRevokeAuthorization: : return SProcSecurityRevokeAuthorization(client); : default: : return BadRequest; : } :} /* SProcSecurityDispatch */ : :static void :SwapSecurityAuthorizationRevokedEvent( : xSecurityAuthorizationRevokedEvent *from, : xSecurityAuthorizationRevokedEvent *to) :{ : to->type = from->type; : to->detail = from->detail; : cpswaps(from->sequenceNumber, to->sequenceNumber); : cpswapl(from->authId, to->authId); :} : :/* SecurityDetermineEventPropogationLimits : * : * This is a helper function for SecurityCheckDeviceAccess. : * : * Arguments: : * dev is the device for which the starting and stopping windows for : * event propogation should be determined. : * The values pointed to by ppWin and ppStopWin are not used. : * : * Returns: : * ppWin is filled in with a pointer to the window at which event : * propogation for the given device should start given the current : * state of the server (pointer position, window layout, etc.) : * ppStopWin is filled in with the window at which event propogation : * should stop; events should not go to ppStopWin. : * : * Side Effects: none. : */ : :static void :SecurityDetermineEventPropogationLimits( : DeviceIntPtr dev, : WindowPtr *ppWin, : WindowPtr *ppStopWin) :{ : WindowPtr pFocusWin = dev->focus ? dev->focus->win : NoneWin; : : if (pFocusWin == NoneWin) : { /* no focus -- events don't go anywhere */ : *ppWin = *ppStopWin = NULL; : return; : } : : if (pFocusWin == PointerRootWin) : { /* focus follows the pointer */ : *ppWin = GetSpriteWindow(); : *ppStopWin = NULL; /* propogate all the way to the root */ : } : else : { /* a real window is set for the focus */ : WindowPtr pSpriteWin = GetSpriteWindow(); : *ppStopWin = pFocusWin->parent; /* don't go past the focus window */ : : /* if the pointer is in a subwindow of the focus window, start : * at that subwindow, else start at the focus window itself : */ : if (IsParent(pFocusWin, pSpriteWin)) : *ppWin = pSpriteWin; : else *ppWin = pFocusWin; : } :} /* SecurityDetermineEventPropogationLimits */ : : :/* SecurityCheckDeviceAccess : * : * Arguments: : * client is the client attempting to access a device. : * dev is the device being accessed. : * fromRequest is TRUE if the device access is a direct result of : * the client executing some request and FALSE if it is a : * result of the server trying to send an event (e.g. KeymapNotify) : * to the client. : * Returns: : * TRUE if the device access should be allowed, else FALSE. : * : * Side Effects: : * An audit message is generated if access is denied. : */ : :CALLBACK(SecurityCheckDeviceAccess) :{ : XaceDeviceAccessRec *rec = (XaceDeviceAccessRec*)calldata; : ClientPtr client = rec->client; : DeviceIntPtr dev = rec->dev; : Bool fromRequest = rec->fromRequest; : WindowPtr pWin, pStopWin; : Bool untrusted_got_event; : Bool found_event_window; : Mask eventmask; : int reqtype = 0; : : /* trusted clients always allowed to do anything */ : if (TRUSTLEVEL(client) == XSecurityClientTrusted) : return; : : /* device security other than keyboard is not implemented yet */ : if (dev != inputInfo.keyboard) : return; : : /* some untrusted client wants access */ : : if (fromRequest) : { : reqtype = ((xReq *)client->requestBuffer)->reqType; : switch (reqtype) : { : /* never allow these */ : case X_ChangeKeyboardMapping: : case X_ChangeKeyboardControl: : case X_SetModifierMapping: : SecurityAudit("client %d attempted request %d\n", : client->index, reqtype); : rec->rval = FALSE; : return; : default: : break; : } : } : : untrusted_got_event = FALSE; : found_event_window = FALSE; : : if (dev->grab) : { : untrusted_got_event = : (TRUSTLEVEL(rClient(dev->grab)) != XSecurityClientTrusted); : } : else : { : SecurityDetermineEventPropogationLimits(dev, &pWin, &pStopWin); : : eventmask = KeyPressMask | KeyReleaseMask; : while ( (pWin != pStopWin) && !found_event_window) : { : OtherClients *other; : : if (pWin->eventMask & eventmask) : { : found_event_window = TRUE; : client = wClient(pWin); : if (TRUSTLEVEL(client) != XSecurityClientTrusted) : { : untrusted_got_event = TRUE; : } : } : if (wOtherEventMasks(pWin) & eventmask) : { : found_event_window = TRUE; : for (other = wOtherClients(pWin); other; other = other->next) : { : if (other->mask & eventmask) : { : client = rClient(other); : if (TRUSTLEVEL(client) != XSecurityClientTrusted) : { : untrusted_got_event = TRUE; : break; : } : } : } : } : if (wDontPropagateMask(pWin) & eventmask) : break; : pWin = pWin->parent; : } /* while propogating the event */ : } : : /* allow access by untrusted clients only if an event would have gone : * to an untrusted client : */ : : if (!untrusted_got_event) : { : char *devname = dev->name; : if (!devname) devname = "unnamed"; : if (fromRequest) : SecurityAudit("client %d attempted request %d device %d (%s)\n", : client->index, reqtype, dev->id, devname); : else : SecurityAudit("client %d attempted to access device %d (%s)\n", : client->index, dev->id, devname); : rec->rval = FALSE; : } : return; :} /* SecurityCheckDeviceAccess */ : : : :/* SecurityAuditResourceIDAccess : * : * Arguments: : * client is the client doing the resource access. : * id is the resource id. : * : * Returns: NULL : * : * Side Effects: : * An audit message is generated with details of the denied : * resource access. : */ : :static pointer :SecurityAuditResourceIDAccess( : ClientPtr client, : XID id) :{ : int cid = CLIENT_ID(id); : int reqtype = ((xReq *)client->requestBuffer)->reqType; : switch (reqtype) : { : case X_ChangeProperty: : case X_DeleteProperty: : case X_GetProperty: : { : xChangePropertyReq *req = : (xChangePropertyReq *)client->requestBuffer; : int propertyatom = req->property; : char *propertyname = NameForAtom(propertyatom); : : SecurityAudit("client %d attempted request %d with window 0x%x property %s of client %d\n", : client->index, reqtype, id, propertyname, cid); : break; : } : default: : { : SecurityAudit("client %d attempted request %d with resource 0x%x of client %d\n", : client->index, reqtype, id, cid); : break; : } : } : return NULL; :} /* SecurityAuditResourceIDAccess */ : : :/* SecurityCheckResourceIDAccess : * : * This function gets plugged into client->CheckAccess and is called from : * SecurityLookupIDByType/Class to determine if the client can access the : * resource. : * : * Arguments: : * client is the client doing the resource access. : * id is the resource id. : * rtype is its type or class. : * access_mode represents the intended use of the resource; see : * resource.h. : * res is a pointer to the resource structure for this resource. : * : * Returns: : * If access is granted, the value of rval that was passed in, else FALSE. : * : * Side Effects: : * Disallowed resource accesses are audited. : */ : :CALLBACK(SecurityCheckResourceIDAccess) 8 0.0087 :{ /* SecurityCheckResourceIDAccess total: 36 0.0392 */ : XaceResourceAccessRec *rec = (XaceResourceAccessRec*)calldata; : ClientPtr client = rec->client; 1 0.0011 : XID id = rec->id; 3 0.0033 : RESTYPE rtype = rec->rtype; : Mask access_mode = rec->access_mode; : pointer rval = rec->res; : int cid, reqtype; : 22 0.0240 : if (TRUSTLEVEL(client) == XSecurityClientTrusted || : DixUnknownAccess == access_mode) : return; /* for compatibility, we have to allow access */ : : cid = CLIENT_ID(id); : reqtype = ((xReq *)client->requestBuffer)->reqType; : switch (reqtype) : { /* these are always allowed */ : case X_QueryTree: : case X_TranslateCoords: : case X_GetGeometry: : /* property access is controlled in SecurityCheckPropertyAccess */ : case X_GetProperty: : case X_ChangeProperty: : case X_DeleteProperty: : case X_RotateProperties: : case X_ListProperties: : return; : default: : break; : } : : if (cid != 0) : { /* not a server-owned resource */ : /* : * The following 'if' restricts clients to only access resources at : * the same trustLevel. Since there are currently only two trust levels, : * and trusted clients never call this function, this degenerates into : * saying that untrusted clients can only access resources of other : * untrusted clients. One way to add the notion of groups would be to : * allow values other than Trusted (0) and Untrusted (1) for this field. : * Clients at the same trust level would be able to use each other's : * resources, but not those of clients at other trust levels. I haven't : * tried it, but this probably mostly works already. The obvious : * competing alternative for grouping clients for security purposes is to : * use app groups. dpw : */ : if (TRUSTLEVEL(client) == TRUSTLEVEL(clients[cid]) :#ifdef XAPPGROUP : || (RT_COLORMAP == rtype && : XagDefaultColormap (client) == (Colormap) id) :#endif : ) : return; : else : goto deny; : } : else /* server-owned resource - probably a default colormap or root window */ : { : if (RT_WINDOW == rtype || RC_DRAWABLE == rtype) : { : switch (reqtype) : { /* the following operations are allowed on root windows */ : case X_CreatePixmap: : case X_CreateGC: : case X_CreateWindow: : case X_CreateColormap: : case X_ListProperties: : case X_GrabPointer: : case X_UngrabButton: : case X_QueryBestSize: : case X_GetWindowAttributes: : break; : case X_SendEvent: : { /* see if it is an event specified by the ICCCM */ : xSendEventReq *req = (xSendEventReq *) : (client->requestBuffer); : if (req->propagate == xTrue : || : (req->eventMask != ColormapChangeMask && : req->eventMask != StructureNotifyMask && : req->eventMask != : (SubstructureRedirectMask|SubstructureNotifyMask) : ) : || : (req->event.u.u.type != UnmapNotify && : req->event.u.u.type != ConfigureRequest && : req->event.u.u.type != ClientMessage : ) : ) : { /* not an ICCCM event */ : goto deny; : } : break; : } /* case X_SendEvent on root */ : : case X_ChangeWindowAttributes: : { /* Allow selection of PropertyNotify and StructureNotify : * events on the root. : */ : xChangeWindowAttributesReq *req = : (xChangeWindowAttributesReq *)(client->requestBuffer); : if (req->valueMask == CWEventMask) : { : CARD32 value = *((CARD32 *)(req + 1)); : if ( (value & : ~(PropertyChangeMask|StructureNotifyMask)) == 0) : break; : } : goto deny; : } /* case X_ChangeWindowAttributes on root */ : : default: : { : /* others not allowed */ : goto deny; : } : } : } /* end server-owned window or drawable */ : else if (SecurityAuthorizationResType == rtype) : { : SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)rval; : if (pAuth->trustLevel != TRUSTLEVEL(client)) : goto deny; : } : else if (RT_COLORMAP != rtype) : { /* don't allow anything else besides colormaps */ : goto deny; : } : } : return; : deny: : SecurityAuditResourceIDAccess(client, id); : rec->rval = FALSE; /* deny access */ 2 0.0022 :} /* SecurityCheckResourceIDAccess */ : : :/* SecurityClientStateCallback : * : * Arguments: : * pcbl is &ClientStateCallback. : * nullata is NULL. : * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) : * which contains information about client state changes. : * : * Returns: nothing. : * : * Side Effects: : * : * If a new client is connecting, its authorization ID is copied to : * client->authID. If this is a generated authorization, its reference : * count is bumped, its timer is cancelled if it was running, and its : * trustlevel is copied to TRUSTLEVEL(client). : * : * If a client is disconnecting and the client was using a generated : * authorization, the authorization's reference count is decremented, and : * if it is now zero, the timer for this authorization is started. : */ : :CALLBACK(SecurityClientStateCallback) :{ : NewClientInfoRec *pci = (NewClientInfoRec *)calldata; : ClientPtr client = pci->client; : : switch (client->clientState) : { : case ClientStateInitial: : TRUSTLEVEL(client) = XSecurityClientTrusted; : AUTHID(client) = None; : break; : : case ClientStateRunning: : { : XID authId = AuthorizationIDOfClient(client); : SecurityAuthorizationPtr pAuth; : : TRUSTLEVEL(client) = XSecurityClientTrusted; : AUTHID(client) = authId; : pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, : SecurityAuthorizationResType); : if (pAuth) : { /* it is a generated authorization */ : pAuth->refcnt++; : if (pAuth->refcnt == 1) : { : if (pAuth->timer) TimerCancel(pAuth->timer); : } : TRUSTLEVEL(client) = pAuth->trustLevel; : } : break; : } : case ClientStateGone: : case ClientStateRetained: /* client disconnected */ : { : SecurityAuthorizationPtr pAuth; : : /* client may not have any state (bad authorization) */ : if (!STATEPTR(client)) : break; : : pAuth = (SecurityAuthorizationPtr)LookupIDByType(AUTHID(client), : SecurityAuthorizationResType); : if (pAuth) : { /* it is a generated authorization */ : pAuth->refcnt--; : if (pAuth->refcnt == 0) : { : SecurityStartAuthorizationTimer(pAuth); : } : } : break; : } : default: break; : } :} /* SecurityClientStateCallback */ : :CALLBACK(SecurityCheckDrawableAccess) :{ : XaceDrawableAccessRec *rec = (XaceDrawableAccessRec*)calldata; : : if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted) : rec->rval = FALSE; :} : :CALLBACK(SecurityCheckMapAccess) :{ : XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata; : WindowPtr pWin = rec->pWin; : : if (STATEPTR(rec->client) && : (TRUSTLEVEL(rec->client) != XSecurityClientTrusted) && : (pWin->drawable.class == InputOnly) && : pWin->parent && pWin->parent->parent && : (TRUSTLEVEL(wClient(pWin->parent)) == XSecurityClientTrusted)) : : rec->rval = FALSE; :} : :CALLBACK(SecurityCheckBackgrndAccess) :{ : XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata; : : if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted) : rec->rval = FALSE; :} : :CALLBACK(SecurityCheckExtAccess) 3 0.0033 :{ /* SecurityCheckExtAccess total: 14 0.0153 */ : XaceExtAccessRec *rec = (XaceExtAccessRec*)calldata; : 10 0.0109 : if ((TRUSTLEVEL(rec->client) != XSecurityClientTrusted) && : !STATEVAL(rec->ext)) : : rec->rval = FALSE; 1 0.0011 :} : :CALLBACK(SecurityCheckHostlistAccess) :{ : XaceHostlistAccessRec *rec = (XaceHostlistAccessRec*)calldata; : : if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted) : { : rec->rval = FALSE; : if (rec->access_mode == DixWriteAccess) : SecurityAudit("client %d attempted to change host access\n", : rec->client->index); : else : SecurityAudit("client %d attempted to list hosts\n", : rec->client->index); : } :} : :CALLBACK(SecurityDeclareExtSecure) :{ : XaceDeclareExtSecureRec *rec = (XaceDeclareExtSecureRec*)calldata; : : /* security state for extensions is simply a boolean trust value */ : STATEVAL(rec->ext) = rec->secure; :} : :/**********************************************************************/ : :typedef struct _PropertyAccessRec { : ATOM name; : ATOM mustHaveProperty; : char *mustHaveValue; : char windowRestriction; :#define SecurityAnyWindow 0 :#define SecurityRootWindow 1 :#define SecurityWindowWithProperty 2 : char readAction; : char writeAction; : char destroyAction; : struct _PropertyAccessRec *next; :} PropertyAccessRec, *PropertyAccessPtr; : :static PropertyAccessPtr PropertyAccessList = NULL; :static char SecurityDefaultAction = XaceErrorOperation; :static char *SecurityPolicyFile = DEFAULTPOLICYFILE; :static ATOM SecurityMaxPropertyName = 0; : :static char *SecurityKeywords[] = { :#define SecurityKeywordComment 0 : "#", :#define SecurityKeywordProperty 1 : "property", :#define SecurityKeywordSitePolicy 2 : "sitepolicy", :#define SecurityKeywordRoot 3 : "root", :#define SecurityKeywordAny 4 : "any" :}; : :#define NUMKEYWORDS (sizeof(SecurityKeywords) / sizeof(char *)) : :#undef PROPDEBUG :/*#define PROPDEBUG 1*/ : :static void :SecurityFreePropertyAccessList(void) :{ : while (PropertyAccessList) : { : PropertyAccessPtr freeit = PropertyAccessList; : PropertyAccessList = PropertyAccessList->next; : xfree(freeit); : } :} /* SecurityFreePropertyAccessList */ : :#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') ) : :static char * :SecuritySkipWhitespace( : char *p) :{ : while (SecurityIsWhitespace(*p)) : p++; : return p; :} /* SecuritySkipWhitespace */ : : :static char * :SecurityParseString( : char **rest) :{ : char *startOfString; : char *s = *rest; : char endChar = 0; : : s = SecuritySkipWhitespace(s); : : if (*s == '"' || *s == '\'') : { : endChar = *s++; : startOfString = s; : while (*s && (*s != endChar)) : s++; : } : else : { : startOfString = s; : while (*s && !SecurityIsWhitespace(*s)) : s++; : } : if (*s) : { : *s = '\0'; : *rest = s + 1; : return startOfString; : } : else : { : *rest = s; : return (endChar) ? NULL : startOfString; : } :} /* SecurityParseString */ : : :static int :SecurityParseKeyword( : char **p) :{ : int i; : char *s = *p; : s = SecuritySkipWhitespace(s); : for (i = 0; i < NUMKEYWORDS; i++) : { : int len = strlen(SecurityKeywords[i]); : if (strncmp(s, SecurityKeywords[i], len) == 0) : { : *p = s + len; : return (i); : } : } : *p = s; : return -1; :} /* SecurityParseKeyword */ : : :static Bool :SecurityParsePropertyAccessRule( : char *p) :{ : char *propname; : char c; : char action = SecurityDefaultAction; : char readAction, writeAction, destroyAction; : PropertyAccessPtr pacl, prev, cur; : char *mustHaveProperty = NULL; : char *mustHaveValue = NULL; : Bool invalid; : char windowRestriction; : int size; : int keyword; : : /* get property name */ : propname = SecurityParseString(&p); : if (!propname || (strlen(propname) == 0)) : return FALSE; : : /* get window on which property must reside for rule to apply */ : : keyword = SecurityParseKeyword(&p); : if (keyword == SecurityKeywordRoot) : windowRestriction = SecurityRootWindow; : else if (keyword == SecurityKeywordAny) : windowRestriction = SecurityAnyWindow; : else /* not root or any, must be a property name */ : { : mustHaveProperty = SecurityParseString(&p); : if (!mustHaveProperty || (strlen(mustHaveProperty) == 0)) : return FALSE; : windowRestriction = SecurityWindowWithProperty; : p = SecuritySkipWhitespace(p); : if (*p == '=') : { /* property value is specified too */ : p++; /* skip over '=' */ : mustHaveValue = SecurityParseString(&p); : if (!mustHaveValue) : return FALSE; : } : } : : /* get operations and actions */ : : invalid = FALSE; : readAction = writeAction = destroyAction = SecurityDefaultAction; : while ( (c = *p++) && !invalid) : { : switch (c) : { : case 'i': action = XaceIgnoreOperation; break; : case 'a': action = XaceAllowOperation; break; : case 'e': action = XaceErrorOperation; break; : : case 'r': readAction = action; break; : case 'w': writeAction = action; break; : case 'd': destroyAction = action; break; : : default : : if (!SecurityIsWhitespace(c)) : invalid = TRUE; : break; : } : } : if (invalid) : return FALSE; : : /* We've successfully collected all the information needed for this : * property access rule. Now record it in a PropertyAccessRec. : */ : size = sizeof(PropertyAccessRec); : : /* If there is a property value string, allocate space for it : * right after the PropertyAccessRec. : */ : if (mustHaveValue) : size += strlen(mustHaveValue) + 1; : pacl = (PropertyAccessPtr)Xalloc(size); : if (!pacl) : return FALSE; : : pacl->name = MakeAtom(propname, strlen(propname), TRUE); : if (pacl->name == BAD_RESOURCE) : { : Xfree(pacl); : return FALSE; : } : if (mustHaveProperty) : { : pacl->mustHaveProperty = MakeAtom(mustHaveProperty, : strlen(mustHaveProperty), TRUE); : if (pacl->mustHaveProperty == BAD_RESOURCE) : { : Xfree(pacl); : return FALSE; : } : } : else : pacl->mustHaveProperty = 0; : : if (mustHaveValue) : { : pacl->mustHaveValue = (char *)(pacl + 1); : strcpy(pacl->mustHaveValue, mustHaveValue); : } : else : pacl->mustHaveValue = NULL; : : SecurityMaxPropertyName = max(SecurityMaxPropertyName, pacl->name); : : pacl->windowRestriction = windowRestriction; : pacl->readAction = readAction; : pacl->writeAction = writeAction; : pacl->destroyAction = destroyAction; : : /* link the new rule into the list of rules in order of increasing : * property name (atom) value to make searching easier : */ : : for (prev = NULL, cur = PropertyAccessList; : cur && cur->name <= pacl->name; : prev = cur, cur = cur->next) : ; : if (!prev) : { : pacl->next = cur; : PropertyAccessList = pacl; : } : else : { : prev->next = pacl; : pacl->next = cur; : } : return TRUE; :} /* SecurityParsePropertyAccessRule */ : :static char **SecurityPolicyStrings = NULL; :static int nSecurityPolicyStrings = 0; : :static Bool :SecurityParseSitePolicy( : char *p) :{ : char *policyStr = SecurityParseString(&p); : char *copyPolicyStr; : char **newStrings; : : if (!policyStr) : return FALSE; : : copyPolicyStr = (char *)Xalloc(strlen(policyStr) + 1); : if (!copyPolicyStr) : return TRUE; : strcpy(copyPolicyStr, policyStr); : newStrings = (char **)Xrealloc(SecurityPolicyStrings, : sizeof (char *) * (nSecurityPolicyStrings + 1)); : if (!newStrings) : { : Xfree(copyPolicyStr); : return TRUE; : } : : SecurityPolicyStrings = newStrings; : SecurityPolicyStrings[nSecurityPolicyStrings++] = copyPolicyStr; : : return TRUE; : :} /* SecurityParseSitePolicy */ : : :char ** :SecurityGetSitePolicyStrings(n) : int *n; :{ : *n = nSecurityPolicyStrings; : return SecurityPolicyStrings; :} /* SecurityGetSitePolicyStrings */ : :static void :SecurityFreeSitePolicyStrings(void) :{ : if (SecurityPolicyStrings) : { : assert(nSecurityPolicyStrings); : while (nSecurityPolicyStrings--) : { : Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]); : } : Xfree(SecurityPolicyStrings); : SecurityPolicyStrings = NULL; : nSecurityPolicyStrings = 0; : } :} /* SecurityFreeSitePolicyStrings */ : : :static void :SecurityLoadPropertyAccessList(void) :{ : FILE *f; : int lineNumber = 0; : : SecurityMaxPropertyName = 0; : : if (!SecurityPolicyFile) : return; : : f = fopen(SecurityPolicyFile, "r"); : if (!f) : { : ErrorF("error opening security policy file %s\n", : SecurityPolicyFile); : return; : } : : while (!feof(f)) : { : char buf[200]; : Bool validLine; : char *p; : : if (!(p = fgets(buf, sizeof(buf), f))) : break; : lineNumber++; : : /* if first line, check version number */ : if (lineNumber == 1) : { : char *v = SecurityParseString(&p); : if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0) : { : ErrorF("%s: invalid security policy file version, ignoring file\n", : SecurityPolicyFile); : break; : } : validLine = TRUE; : } : else : { : switch (SecurityParseKeyword(&p)) : { : case SecurityKeywordComment: : validLine = TRUE; : break; : : case SecurityKeywordProperty: : validLine = SecurityParsePropertyAccessRule(p); : break; : : case SecurityKeywordSitePolicy: : validLine = SecurityParseSitePolicy(p); : break; : : default: : validLine = (*p == '\0'); /* blank lines OK, others not */ : break; : } : } : : if (!validLine) : ErrorF("Line %d of %s invalid, ignoring\n", : lineNumber, SecurityPolicyFile); : } /* end while more input */ : :#ifdef PROPDEBUG : { : PropertyAccessPtr pacl; : char *op = "aie"; : for (pacl = PropertyAccessList; pacl; pacl = pacl->next) : { : ErrorF("property %s ", NameForAtom(pacl->name)); : switch (pacl->windowRestriction) : { : case SecurityAnyWindow: ErrorF("any "); break; : case SecurityRootWindow: ErrorF("root "); break; : case SecurityWindowWithProperty: : { : ErrorF("%s ", NameForAtom(pacl->mustHaveProperty)); : if (pacl->mustHaveValue) : ErrorF(" = \"%s\" ", pacl->mustHaveValue); : : } : break; : } : ErrorF("%cr %cw %cd\n", op[pacl->readAction], : op[pacl->writeAction], op[pacl->destroyAction]); : } : } :#endif /* PROPDEBUG */ : : fclose(f); :} /* SecurityLoadPropertyAccessList */ : : :static Bool :SecurityMatchString( : char *ws, : char *cs) :{ : while (*ws && *cs) : { : if (*ws == '*') : { : Bool match = FALSE; : ws++; : while (!(match = SecurityMatchString(ws, cs)) && *cs) : { : cs++; : } : return match; : } : else if (*ws == *cs) : { : ws++; : cs++; : } : else break; : } : return ( ( (*ws == '\0') || ((*ws == '*') && *(ws+1) == '\0') ) : && (*cs == '\0') ); :} /* SecurityMatchString */ : :#ifdef PROPDEBUG :#include :#include :#endif : : :CALLBACK(SecurityCheckPropertyAccess) :{ : XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata; : ClientPtr client = rec->client; : WindowPtr pWin = rec->pWin; : ATOM propertyName = rec->propertyName; : Mask access_mode = rec->access_mode; : PropertyAccessPtr pacl; : char action = SecurityDefaultAction; : : /* if client trusted or window untrusted, allow operation */ : : if ( (TRUSTLEVEL(client) == XSecurityClientTrusted) || : (TRUSTLEVEL(wClient(pWin)) != XSecurityClientTrusted) ) : return; : :#ifdef PROPDEBUG : /* For testing, it's more convenient if the property rules file gets : * reloaded whenever it changes, so we can rapidly try things without : * having to reset the server. : */ : { : struct stat buf; : static time_t lastmod = 0; : int ret = stat(SecurityPolicyFile , &buf); : if ( (ret == 0) && (buf.st_mtime > lastmod) ) : { : ErrorF("reloading property rules\n"); : SecurityFreePropertyAccessList(); : SecurityLoadPropertyAccessList(); : lastmod = buf.st_mtime; : } : } :#endif : : /* If the property atom is bigger than any atoms on the list, : * we know we won't find it, so don't even bother looking. : */ : if (propertyName <= SecurityMaxPropertyName) : { : /* untrusted client operating on trusted window; see if it's allowed */ : : for (pacl = PropertyAccessList; pacl; pacl = pacl->next) : { : if (pacl->name < propertyName) : continue; : if (pacl->name > propertyName) : break; : : /* pacl->name == propertyName, so see if it applies to this window */ : : switch (pacl->windowRestriction) : { : case SecurityAnyWindow: /* always applies */ : break; : : case SecurityRootWindow: : { : /* if not a root window, this rule doesn't apply */ : if (pWin->parent) : continue; : } : break; : : case SecurityWindowWithProperty: : { : PropertyPtr pProp = wUserProps (pWin); : Bool match = FALSE; : char *p; : char *pEndData; : : while (pProp) : { : if (pProp->propertyName == pacl->mustHaveProperty) : break; : pProp = pProp->next; : } : if (!pProp) : continue; : if (!pacl->mustHaveValue) : break; : if (pProp->type != XA_STRING || pProp->format != 8) : continue; : : p = pProp->data; : pEndData = ((char *)pProp->data) + pProp->size; : while (!match && p < pEndData) : { : if (SecurityMatchString(pacl->mustHaveValue, p)) : match = TRUE; : else : { /* skip to the next string */ : while (*p++ && p < pEndData) : ; : } : } : if (!match) : continue; : } : break; /* end case SecurityWindowWithProperty */ : } /* end switch on windowRestriction */ : : /* If we get here, the property access rule pacl applies. : * If pacl doesn't apply, something above should have : * executed a continue, which will skip the follwing code. : */ : action = XaceAllowOperation; : if (access_mode & DixReadAccess) : action = max(action, pacl->readAction); : if (access_mode & DixWriteAccess) : action = max(action, pacl->writeAction); : if (access_mode & DixDestroyAccess) : action = max(action, pacl->destroyAction); : break; : } /* end for each pacl */ : } /* end if propertyName <= SecurityMaxPropertyName */ : : if (XaceAllowOperation != action) : { /* audit the access violation */ : int cid = CLIENT_ID(pWin->drawable.id); : int reqtype = ((xReq *)client->requestBuffer)->reqType; : char *actionstr = (XaceIgnoreOperation == action) ? : "ignored" : "error"; : SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n", : client->index, reqtype, pWin->drawable.id, : NameForAtom(propertyName), propertyName, cid, actionstr); : } : /* return codes increase with strictness */ : if (action > rec->rval) : rec->rval = action; :} /* SecurityCheckPropertyAccess */ : : :/* SecurityResetProc : * : * Arguments: : * extEntry is the extension information for the security extension. : * : * Returns: nothing. : * : * Side Effects: : * Performs any cleanup needed by Security at server shutdown time. : */ : :static void :SecurityResetProc( : ExtensionEntry *extEntry) :{ : SecurityFreePropertyAccessList(); : SecurityFreeSitePolicyStrings(); :} /* SecurityResetProc */ : : :int :XSecurityOptions(argc, argv, i) : int argc; : char **argv; : int i; :{ : if (strcmp(argv[i], "-sp") == 0) : { : if (i < argc) : SecurityPolicyFile = argv[++i]; : return (i + 1); : } : return (i); :} /* XSecurityOptions */ : : :/* SecurityExtensionSetup : * : * Arguments: none. : * : * Returns: nothing. : * : * Side Effects: : * Sets up the Security extension if possible. : * This function contains things that need to be done : * before any other extension init functions get called. : */ : :void :SecurityExtensionSetup(INITARGS) :{ : /* Allocate the client private index */ : securityClientPrivateIndex = AllocateClientPrivateIndex(); : if (!AllocateClientPrivate(securityClientPrivateIndex, : sizeof (SecurityClientStateRec))) : FatalError("SecurityExtensionSetup: Can't allocate client private.\n"); : : /* Allocate the extension private index */ : securityExtnsnPrivateIndex = AllocateExtensionPrivateIndex(); : if (!AllocateExtensionPrivate(securityExtnsnPrivateIndex, 0)) : FatalError("SecurityExtensionSetup: Can't allocate extnsn private.\n"); : : /* register callbacks */ :#define XaceRC XaceRegisterCallback : XaceRC(XACE_RESOURCE_ACCESS, SecurityCheckResourceIDAccess, NULL); : XaceRC(XACE_DEVICE_ACCESS, SecurityCheckDeviceAccess, NULL); : XaceRC(XACE_PROPERTY_ACCESS, SecurityCheckPropertyAccess, NULL); : XaceRC(XACE_DRAWABLE_ACCESS, SecurityCheckDrawableAccess, NULL); : XaceRC(XACE_MAP_ACCESS, SecurityCheckMapAccess, NULL); : XaceRC(XACE_BACKGRND_ACCESS, SecurityCheckBackgrndAccess, NULL); : XaceRC(XACE_EXT_DISPATCH, SecurityCheckExtAccess, NULL); : XaceRC(XACE_EXT_ACCESS, SecurityCheckExtAccess, NULL); : XaceRC(XACE_HOSTLIST_ACCESS, SecurityCheckHostlistAccess, NULL); : XaceRC(XACE_DECLARE_EXT_SECURE, SecurityDeclareExtSecure, NULL); :} /* SecurityExtensionSetup */ : : :/* SecurityExtensionInit : * : * Arguments: none. : * : * Returns: nothing. : * : * Side Effects: : * Enables the Security extension if possible. : */ : :void :SecurityExtensionInit(INITARGS) :{ : ExtensionEntry *extEntry; : : SecurityAuthorizationResType = : CreateNewResourceType(SecurityDeleteAuthorization); : : RTEventClient = CreateNewResourceType( : SecurityDeleteAuthorizationEventClient); : : if (!SecurityAuthorizationResType || !RTEventClient) : return; : : RTEventClient |= RC_NEVERRETAIN; : : if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL)) : return; : : extEntry = AddExtension(SECURITY_EXTENSION_NAME, : XSecurityNumberEvents, XSecurityNumberErrors, : ProcSecurityDispatch, SProcSecurityDispatch, : SecurityResetProc, StandardMinorOpcode); : : SecurityErrorBase = extEntry->errorBase; : SecurityEventBase = extEntry->eventBase; : : EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] = : (EventSwapPtr)SwapSecurityAuthorizationRevokedEvent; : : SecurityLoadPropertyAccessList(); : :} /* SecurityExtensionInit */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/hw/xfree86/dri/dri.c" * * 41 0.0447 */ :/************************************************************************** : :Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. :Copyright 2000 VA Linux Systems, Inc. :All Rights Reserved. : :Permission is hereby granted, free of charge, to any person obtaining a :copy of this software and associated documentation files (the :"Software"), to deal in the Software without restriction, including :without limitation the rights to use, copy, modify, merge, publish, :distribute, sub license, and/or sell copies of the Software, and to :permit persons to whom the Software is furnished to do so, subject to :the following conditions: : :The above copyright notice and this permission notice (including the :next paragraph) shall be included in all copies or substantial portions :of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. :IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR :ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, :TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE :SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :**************************************************************************/ : :/* : * Authors: : * Jens Owen : * Rickard E. (Rik) Faith : * : */ : :#ifdef HAVE_XORG_CONFIG_H :#include :#endif : :#include "xf86.h" :#include :#include :#include :#include :#include :#include : :#define NEED_REPLIES :#define NEED_EVENTS :#include :#include :#include "xf86drm.h" :#include "misc.h" :#include "dixstruct.h" :#include "extnsionst.h" :#include "colormapst.h" :#include "cursorstr.h" :#include "scrnintstr.h" :#include "windowstr.h" :#include "servermd.h" :#define _XF86DRI_SERVER_ :#include "xf86dristr.h" :#include "swaprep.h" :#include "xf86str.h" :#include "dri.h" :#include "sarea.h" :#include "dristruct.h" :#include "xf86.h" :#include "xf86drm.h" :#include "glxserver.h" :#include "mi.h" :#include "mipointer.h" :#include "xf86_OSproc.h" : :#define PCI_BUS_NO_DOMAIN(bus) ((bus) & 0xffu) : :#if !defined(PANORAMIX) :extern Bool noPanoramiXExtension; :#endif : :static int DRIEntPrivIndex = -1; :static int DRIScreenPrivIndex = -1; :static int DRIWindowPrivIndex = -1; :static unsigned long DRIGeneration = 0; :static unsigned int DRIDrawableValidationStamp = 0; : :static RESTYPE DRIDrawablePrivResType; :static RESTYPE DRIContextPrivResType; :static void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv); : :drmServerInfo DRIDRMServerInfo; : : /* Wrapper just like xf86DrvMsg, but : without the verbosity level checking. : This will make it easy to turn off some : messages later, based on verbosity : level. */ : :/* : * Since we're already referencing things from the XFree86 common layer in : * this file, we'd might as well just call xf86VDrvMsgVerb, and have : * consistent message formatting. The verbosity of these messages can be : * easily changed here. : */ :#define DRI_MSG_VERBOSITY 1 :static void :DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) :{ : va_list ap; : : va_start(ap, format); : xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap); : va_end(ap); :} : : :static void :DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv) :{ : if (pDRIEntPriv->pLSAREA != NULL) { : drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize); : pDRIEntPriv->pLSAREA = NULL; : } : if (pDRIEntPriv->hLSAREA != 0) { : drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA); : } : if (pDRIEntPriv->drmFD >= 0) { : drmClose(pDRIEntPriv->drmFD); : pDRIEntPriv->drmFD = 0; : } :} : :int :DRIMasterFD(ScrnInfoPtr pScrn) :{ : return DRI_ENT_PRIV(pScrn)->drmFD; :} : :void * :DRIMasterSareaPointer(ScrnInfoPtr pScrn) :{ : return DRI_ENT_PRIV(pScrn)->pLSAREA; :} : :drm_handle_t :DRIMasterSareaHandle(ScrnInfoPtr pScrn) :{ : return DRI_ENT_PRIV(pScrn)->hLSAREA; :} : : :Bool :DRIOpenDRMMaster(ScrnInfoPtr pScrn, : unsigned long sAreaSize, : const char *busID, : const char *drmDriverName) :{ : drmSetVersion saveSv, sv; : Bool drmWasAvailable; : DRIEntPrivPtr pDRIEntPriv; : DRIEntPrivRec tmp; : drmVersionPtr drmlibv; : int drmlibmajor, drmlibminor; : const char *openBusID; : int count; : int err; : : if (DRIEntPrivIndex == -1) : DRIEntPrivIndex = xf86AllocateEntityPrivateIndex(); : : pDRIEntPriv = DRI_ENT_PRIV(pScrn); : : if (pDRIEntPriv && pDRIEntPriv->drmFD != -1) : return TRUE; : : drmWasAvailable = drmAvailable(); : : memset(&tmp, 0, sizeof(tmp)); : : /* Check the DRM lib version. : * drmGetLibVersion was not supported in version 1.0, so check for : * symbol first to avoid possible crash or hang. : */ : : drmlibmajor = 1; : drmlibminor = 0; : if (xf86LoaderCheckSymbol("drmGetLibVersion")) { : drmlibv = drmGetLibVersion(-1); : if (drmlibv != NULL) { : drmlibmajor = drmlibv->version_major; : drmlibminor = drmlibv->version_minor; : drmFreeVersion(drmlibv); : } : } : : /* Check if the libdrm can handle falling back to loading based on name : * if a busid string is passed. : */ : openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL; : : tmp.drmFD = -1; : sv.drm_di_major = 1; : sv.drm_di_minor = 1; : sv.drm_dd_major = -1; : : saveSv = sv; : count = 10; : while (count--) { : tmp.drmFD = drmOpen(drmDriverName, openBusID); : : if (tmp.drmFD < 0) { : DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n"); : goto out_err; : } : : err = drmSetInterfaceVersion(tmp.drmFD, &sv); : : if (err != -EPERM) : break; : : sv = saveSv; : drmClose(tmp.drmFD); : tmp.drmFD = -1; : usleep(100000); : } : : if (tmp.drmFD <= 0) { : DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n"); : goto out_err; : } : : if (!drmWasAvailable) { : DRIDrvMsg(-1, X_INFO, : "[drm] loaded kernel module for \"%s\" driver.\n", : drmDriverName); : } : : if (err != 0) { : sv.drm_di_major = 1; : sv.drm_di_minor = 0; : } : : DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n", : sv.drm_di_major, sv.drm_di_minor); : : if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1) : err = 0; : else : err = drmSetBusid(tmp.drmFD, busID); : : if (err) { : DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n"); : goto out_err; : } : : /* : * Create a lock-containing sarea. : */ : : if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM, : DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) { : DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n"); : tmp.hLSAREA = 0; : goto out_err; : } : : if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize, : (drmAddressPtr)(&tmp.pLSAREA)) < 0) { : DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n"); : tmp.pLSAREA = NULL; : goto out_err; : } : : memset(tmp.pLSAREA, 0, sAreaSize); : : /* : * Reserved contexts are handled by the first opened screen. : */ : : tmp.resOwner = NULL; : : if (!pDRIEntPriv) : pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1); : : if (!pDRIEntPriv) { : DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for " : "DRM device.\n"); : goto out_err; : } : *pDRIEntPriv = tmp; : xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr = : pDRIEntPriv; : : DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n"); : return TRUE; : : out_err: : : DRIOpenDRMCleanup(&tmp); : return FALSE; :} : : :Bool :DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) :{ : DRIScreenPrivPtr pDRIPriv; : drm_context_t * reserved; : int reserved_count; : int i; : Bool xineramaInCore = FALSE; : DRIEntPrivPtr pDRIEntPriv; : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : : /* If the DRI extension is disabled, do not initialize the DRI */ : if (noXFree86DRIExtension) { : DRIDrvMsg(pScreen->myNum, X_WARNING, : "Direct rendering has been disabled.\n"); : return FALSE; : } : : /* : * If Xinerama is on, don't allow DRI to initialise. It won't be usable : * anyway. : */ : if (xf86LoaderCheckSymbol("noPanoramiXExtension")) : xineramaInCore = TRUE; : : if (xineramaInCore) { : if (!noPanoramiXExtension) { : DRIDrvMsg(pScreen->myNum, X_WARNING, : "Direct rendering is not supported when Xinerama is enabled\n"); : return FALSE; : } : } : : if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize, : pDRIInfo->busIdString, : pDRIInfo->drmDriverName)) : return FALSE; : : pDRIEntPriv = DRI_ENT_PRIV(pScrn); : : if (DRIGeneration != serverGeneration) { : if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) : return FALSE; : DRIGeneration = serverGeneration; : } : : pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec)); : if (!pDRIPriv) { : pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; : DRIScreenPrivIndex = -1; : return FALSE; : } : : pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv; : pDRIPriv->drmFD = pDRIEntPriv->drmFD; : pDRIPriv->directRenderingSupport = TRUE; : pDRIPriv->pDriverInfo = pDRIInfo; : pDRIPriv->nrWindows = 0; : pDRIPriv->nrWindowsVisible = 0; : pDRIPriv->fullscreen = NULL; : : pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx; : pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv; : : pDRIPriv->grabbedDRILock = FALSE; : pDRIPriv->drmSIGIOHandlerInstalled = FALSE; : *pDRMFD = pDRIPriv->drmFD; : : if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) { : : if (drmAddMap( pDRIPriv->drmFD, : 0, : pDRIPriv->pDriverInfo->SAREASize, : DRM_SHM, : 0, : &pDRIPriv->hSAREA) < 0) : { : pDRIPriv->directRenderingSupport = FALSE; : pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; : drmClose(pDRIPriv->drmFD); : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] drmAddMap failed\n"); : return FALSE; : } : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] added %d byte SAREA at %p\n", : pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA); : : /* Backwards compat. */ : if (drmMap( pDRIPriv->drmFD, : pDRIPriv->hSAREA, : pDRIPriv->pDriverInfo->SAREASize, : (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0) : { : pDRIPriv->directRenderingSupport = FALSE; : pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; : drmClose(pDRIPriv->drmFD); : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] drmMap failed\n"); : return FALSE; : } : DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n", : pDRIPriv->hSAREA, pDRIPriv->pSAREA); : memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize); : } else { : DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock " : "SAREA also for drawables.\n"); : pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA; : pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA; : pDRIEntPriv->sAreaGrabbed = TRUE; : } : : pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA; : pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA; : : if (drmAddMap( pDRIPriv->drmFD, : (drm_handle_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress, : pDRIPriv->pDriverInfo->frameBufferSize, : DRM_FRAME_BUFFER, : 0, : &pDRIPriv->hFrameBuffer) < 0) : { : pDRIPriv->directRenderingSupport = FALSE; : pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; : drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); : drmClose(pDRIPriv->drmFD); : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] drmAddMap failed\n"); : return FALSE; : } : DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n", : pDRIPriv->hFrameBuffer); : : if (pDRIEntPriv->resOwner == NULL) { : pDRIEntPriv->resOwner = pScreen; : : /* Add tags for reserved contexts */ : if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, : &reserved_count))) { : int i; : void *tag; : : for (i = 0; i < reserved_count; i++) { : tag = DRICreateContextPrivFromHandle(pScreen, : reserved[i], : DRI_CONTEXT_RESERVED); : drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag); : } : drmFreeReservedContextList(reserved); : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] added %d reserved context%s for kernel\n", : reserved_count, reserved_count > 1 ? "s" : ""); : } : } : : /* validate max drawable table entry set by driver */ : if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) || : (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "Invalid max drawable table size set by driver: %d\n", : pDRIPriv->pDriverInfo->maxDrawableTableEntry); : } : : /* Initialize drawable tables (screen private and SAREA) */ : for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { : pDRIPriv->DRIDrawables[i] = NULL; : pDRIPriv->pSAREA->drawableTable[i].stamp = 0; : pDRIPriv->pSAREA->drawableTable[i].flags = 0; : } : : pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount; : pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext; : : if (!pDRIEntPriv->keepFDOpen) : pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen; : : pDRIEntPriv->refCount++; : : return TRUE; :} : :Bool :DRIFinishScreenInit(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; : DRIContextFlags flags = 0; : DRIContextPrivPtr pDRIContextPriv; : : /* Set up flags for DRICreateContextPriv */ : switch (pDRIInfo->driverSwapMethod) { : case DRI_KERNEL_SWAP: flags = DRI_CONTEXT_2DONLY; break; : case DRI_HIDE_X_CONTEXT: flags = DRI_CONTEXT_PRESERVED; break; : } : : if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, : &pDRIPriv->myContext, : flags))) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "failed to create server context\n"); : return FALSE; : } : pDRIPriv->myContextPriv = pDRIContextPriv; : : DRIDrvMsg(pScreen->myNum, X_INFO, : "X context handle = %p\n", pDRIPriv->myContext); : : /* Now that we have created the X server's context, we can grab the : * hardware lock for the X server. : */ : DRILock(pScreen, 0); : pDRIPriv->grabbedDRILock = TRUE; : : /* pointers so that we can prevent memory leaks later */ : pDRIPriv->hiddenContextStore = NULL; : pDRIPriv->partial3DContextStore = NULL; : : switch(pDRIInfo->driverSwapMethod) { : case DRI_HIDE_X_CONTEXT: : /* Server will handle 3D swaps, and hide 2D swaps from kernel. : * Register server context as a preserved context. : */ : : /* allocate memory for hidden context store */ : pDRIPriv->hiddenContextStore : = (void *)xcalloc(1, pDRIInfo->contextSize); : if (!pDRIPriv->hiddenContextStore) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "failed to allocate hidden context\n"); : DRIDestroyContextPriv(pDRIContextPriv); : return FALSE; : } : : /* allocate memory for partial 3D context store */ : pDRIPriv->partial3DContextStore : = (void *)xcalloc(1, pDRIInfo->contextSize); : if (!pDRIPriv->partial3DContextStore) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[DRI] failed to allocate partial 3D context\n"); : xfree(pDRIPriv->hiddenContextStore); : DRIDestroyContextPriv(pDRIContextPriv); : return FALSE; : } : : /* save initial context store */ : if (pDRIInfo->SwapContext) { : (*pDRIInfo->SwapContext)( : pScreen, : DRI_NO_SYNC, : DRI_2D_CONTEXT, : pDRIPriv->hiddenContextStore, : DRI_NO_CONTEXT, : NULL); : } : /* fall through */ : : case DRI_SERVER_SWAP: : /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT : * setup signal handler for receiving swap requests from kernel : */ : if (!(pDRIPriv->drmSIGIOHandlerInstalled = : drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[drm] failed to setup DRM signal handler\n"); : if (pDRIPriv->hiddenContextStore) : xfree(pDRIPriv->hiddenContextStore); : if (pDRIPriv->partial3DContextStore) : xfree(pDRIPriv->partial3DContextStore); : DRIDestroyContextPriv(pDRIContextPriv); : return FALSE; : } else { : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] installed DRM signal handler\n"); : } : : default: : break; : } : : /* Wrap DRI support */ : if (pDRIInfo->wrap.ValidateTree) { : pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; : pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree; : } : if (pDRIInfo->wrap.PostValidateTree) { : pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; : pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree; : } : if (pDRIInfo->wrap.WindowExposures) { : pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; : pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures; : } : if (pDRIInfo->wrap.CopyWindow) { : pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; : pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow; : } : if (pDRIInfo->wrap.ClipNotify) { : pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; : pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify; : } : if (pDRIInfo->wrap.AdjustFrame) { : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; : pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame; : } : pDRIPriv->wrapped = TRUE; : : DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n"); : : return TRUE; :} : :void :DRICloseScreen(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIInfoPtr pDRIInfo; : drm_context_t * reserved; : int reserved_count; : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn); : Bool closeMaster; : : if (pDRIPriv) { : : pDRIInfo = pDRIPriv->pDriverInfo; : : if (pDRIPriv->wrapped) { : /* Unwrap DRI Functions */ : if (pDRIInfo->wrap.ValidateTree) { : pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; : pDRIPriv->wrap.ValidateTree = NULL; : } : if (pDRIInfo->wrap.PostValidateTree) { : pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; : pDRIPriv->wrap.PostValidateTree = NULL; : } : if (pDRIInfo->wrap.WindowExposures) { : pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; : pDRIPriv->wrap.WindowExposures = NULL; : } : if (pDRIInfo->wrap.CopyWindow) { : pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; : pDRIPriv->wrap.CopyWindow = NULL; : } : if (pDRIInfo->wrap.ClipNotify) { : pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; : pDRIPriv->wrap.ClipNotify = NULL; : } : if (pDRIInfo->wrap.AdjustFrame) { : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; : pDRIPriv->wrap.AdjustFrame = NULL; : } : pDRIPriv->wrapped = FALSE; : } : : if (pDRIPriv->drmSIGIOHandlerInstalled) { : if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[drm] failed to remove DRM signal handler\n"); : } : } : : if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) { : DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv); : } : : if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "failed to destroy server context\n"); : } : : /* Remove tags for reserved contexts */ : if (pDRIEntPriv->resOwner == pScreen) { : pDRIEntPriv->resOwner = NULL; : : if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, : &reserved_count))) { : int i; : : for (i = 0; i < reserved_count; i++) { : DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD, : reserved[i])); : } : drmFreeReservedContextList(reserved); : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] removed %d reserved context%s for kernel\n", : reserved_count, reserved_count > 1 ? "s" : ""); : } : } : : /* Make sure signals get unblocked etc. */ : drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext); : pDRIPriv->pLockRefCount = NULL; : closeMaster = (--pDRIEntPriv->refCount == 0) && : !pDRIEntPriv->keepFDOpen; : if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) { : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] unmapping %d bytes of SAREA %p at %p\n", : pDRIInfo->SAREASize, : pDRIPriv->hSAREA, : pDRIPriv->pSAREA); : if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[drm] unable to unmap %d bytes" : " of SAREA %p at %p\n", : pDRIInfo->SAREASize, : pDRIPriv->hSAREA, : pDRIPriv->pSAREA); : } : } else { : pDRIEntPriv->sAreaGrabbed = FALSE; : } : : if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) { : drmClose(pDRIPriv->drmFD); : if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) { : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] Closed DRM master.\n"); : pDRIEntPriv->drmFD = -1; : } : } : : xfree(pDRIPriv); : pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; : DRIScreenPrivIndex = -1; : } :} : :#define DRM_MSG_VERBOSITY 3 : :static int dri_drm_debug_print(const char *format, va_list ap) :{ : xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); : return 0; :} : :static void dri_drm_get_perms(gid_t *group, mode_t *mode) :{ : *group = xf86ConfigDRI.group; : *mode = xf86ConfigDRI.mode; :} : :drmServerInfo DRIDRMServerInfo = { : dri_drm_debug_print, : xf86LoadKernelModule, : dri_drm_get_perms, :}; : :Bool :DRIExtensionInit(void) :{ : int i; : ScreenPtr pScreen; : : if (DRIScreenPrivIndex < 0 || DRIGeneration != serverGeneration) { : return FALSE; : } : : /* Allocate a window private index with a zero sized private area for : * each window, then should a window become a DRI window, we'll hang : * a DRIWindowPrivateRec off of this private index. : */ : if ((DRIWindowPrivIndex = AllocateWindowPrivateIndex()) < 0) : return FALSE; : : DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete); : DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete); : : for (i = 0; i < screenInfo.numScreens; i++) : { : pScreen = screenInfo.screens[i]; : if (!AllocateWindowPrivate(pScreen, DRIWindowPrivIndex, 0)) : return FALSE; : } : : RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); : : return TRUE; :} : :void :DRIReset(void) :{ : /* : * This stub routine is called when the X Server recycles, resources : * allocated by DRIExtensionInit need to be managed here. : * : * Currently this routine is a stub because all the interesting resources : * are managed via the screen init process. : */ :} : :Bool :DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (pDRIPriv) : *isCapable = pDRIPriv->directRenderingSupport; : else : *isCapable = FALSE; : : return TRUE; :} : :Bool :DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : *hSAREA = pDRIPriv->hSAREA; : *busIdString = pDRIPriv->pDriverInfo->busIdString; : : return TRUE; :} : :Bool :DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; : return TRUE; :} : :Bool :DRICloseConnection(ScreenPtr pScreen) :{ : return TRUE; :} : :Bool :DRIGetClientDriverName(ScreenPtr pScreen, : int *ddxDriverMajorVersion, : int *ddxDriverMinorVersion, : int *ddxDriverPatchVersion, : char **clientDriverName) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion; : *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion; : *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion; : *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName; : : return TRUE; :} : :/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper : functions that layer on drmCreateContext and drmAddContextTag. : : DRICreateContextPriv always creates a kernel drm_context_t and then calls : DRICreateContextPrivFromHandle to create a DRIContextPriv structure for : DRI tracking. For the SIGIO handler, the drm_context_t is associated with : DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv : area and are passed to the kernel (if necessary). : : DRICreateContextPriv returns a pointer to newly allocated : DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */ : :DRIContextPrivPtr :DRICreateContextPriv(ScreenPtr pScreen, : drm_context_t * pHWContext, : DRIContextFlags flags) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) { : return NULL; : } : : return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags); :} : :DRIContextPrivPtr :DRICreateContextPrivFromHandle(ScreenPtr pScreen, : drm_context_t hHWContext, : DRIContextFlags flags) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIContextPrivPtr pDRIContextPriv; : int contextPrivSize; : : contextPrivSize = sizeof(DRIContextPrivRec) + : pDRIPriv->pDriverInfo->contextSize; : if (!(pDRIContextPriv = xcalloc(1, contextPrivSize))) { : return NULL; : } : pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1); : : drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv); : : pDRIContextPriv->hwContext = hHWContext; : pDRIContextPriv->pScreen = pScreen; : pDRIContextPriv->flags = flags; : pDRIContextPriv->valid3D = FALSE; : : if (flags & DRI_CONTEXT_2DONLY) { : if (drmSetContextFlags(pDRIPriv->drmFD, : hHWContext, : DRM_CONTEXT_2DONLY)) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[drm] failed to set 2D context flag\n"); : DRIDestroyContextPriv(pDRIContextPriv); : return NULL; : } : } : if (flags & DRI_CONTEXT_PRESERVED) { : if (drmSetContextFlags(pDRIPriv->drmFD, : hHWContext, : DRM_CONTEXT_PRESERVED)) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[drm] failed to set preserved flag\n"); : DRIDestroyContextPriv(pDRIContextPriv); : return NULL; : } : } : return pDRIContextPriv; :} : :Bool :DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv) :{ : DRIScreenPrivPtr pDRIPriv; : : if (!pDRIContextPriv) return TRUE; : : pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); : : if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) { : /* Don't delete reserved contexts from : kernel area -- the kernel manages its : reserved contexts itself. */ : if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext)) : return FALSE; : } : : /* Remove the tag last to prevent a race : condition where the context has pending : buffers. The context can't be re-used : while in this thread, but buffers can be : dispatched asynchronously. */ : drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext); : xfree(pDRIContextPriv); : return TRUE; :} : :static Bool :DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : __GLXscreen *pGLXScreen = __glXgetActiveScreen(pScreen->myNum); : __GLcontextModes *modes = pGLXScreen->modes; : void **pVisualConfigPriv = pGLXScreen->pVisualPriv; : DRIContextPrivPtr pDRIContextPriv; : void *contextStore; : VisualPtr visual; : int visNum; : : visual = pScreen->visuals; : : /* Find the X visual that corresponds the the first GLX visual */ : for (visNum = 0; : visNum < pScreen->numVisuals; : visNum++, visual++) { : if (modes->visualID == visual->vid) : break; : } : if (visNum == pScreen->numVisuals) return FALSE; : : if (!(pDRIContextPriv = : DRICreateContextPriv(pScreen, : &pDRIPriv->pSAREA->dummy_context, 0))) { : return FALSE; : } : : contextStore = DRIGetContextStore(pDRIContextPriv); : if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { : if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, visual, : pDRIPriv->pSAREA->dummy_context, : *pVisualConfigPriv, : (DRIContextType)(long)contextStore)) { : DRIDestroyContextPriv(pDRIContextPriv); : return FALSE; : } : } : : pDRIPriv->dummyCtxPriv = pDRIContextPriv; : return TRUE; :} : :static void :DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv; : void *contextStore; : : if (!pDRIContextPriv) return; : if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) { : contextStore = DRIGetContextStore(pDRIContextPriv); : pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, : pDRIContextPriv->hwContext, : (DRIContextType)(long)contextStore); : } : : DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv); : pDRIPriv->dummyCtxPriv = NULL; :} : :Bool :DRICreateContext(ScreenPtr pScreen, VisualPtr visual, : XID context, drm_context_t * pHWContext) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : __GLXscreen *pGLXScreen = __glXgetActiveScreen(pScreen->myNum); : __GLcontextModes *modes = pGLXScreen->modes; : void **pVisualConfigPriv = pGLXScreen->pVisualPriv; : DRIContextPrivPtr pDRIContextPriv; : void *contextStore; : : if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) { : if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) { : DRIDrvMsg(pScreen->myNum, X_INFO, : "[drm] Could not create dummy context\n"); : return FALSE; : } : } : : /* Find the GLX visual associated with the one requested */ : for (modes = pGLXScreen->modes; modes != NULL; modes = modes->next) { : if (modes->visualID == visual->vid) : break; : pVisualConfigPriv++; : } : : if (modes == NULL) { : /* No matching GLX visual found */ : return FALSE; : } : : if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { : return FALSE; : } : : contextStore = DRIGetContextStore(pDRIContextPriv); : if (pDRIPriv->pDriverInfo->CreateContext) { : if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, visual, : *pHWContext, *pVisualConfigPriv, : (DRIContextType)(long)contextStore))) { : DRIDestroyContextPriv(pDRIContextPriv); : return FALSE; : } : } : : /* track this in case the client dies before cleanup */ : AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv); : : return TRUE; :} : :Bool :DRIDestroyContext(ScreenPtr pScreen, XID context) :{ : FreeResourceByType(context, DRIContextPrivResType, FALSE); : : return TRUE; :} : :/* DRIContextPrivDelete is called by the resource manager. */ :Bool :DRIContextPrivDelete(pointer pResource, XID id) :{ : DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource; : DRIScreenPrivPtr pDRIPriv; : void *contextStore; : : pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); : if (pDRIPriv->pDriverInfo->DestroyContext) { : contextStore = DRIGetContextStore(pDRIContextPriv); : pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, : pDRIContextPriv->hwContext, : (DRIContextType)(long)contextStore); : } : return DRIDestroyContextPriv(pDRIContextPriv); :} : : :/* This walks the drawable timestamp array and invalidates all of them : * in the case of transition from private to shared backbuffers. It's : * not necessary for correctness, because DRIClipNotify gets called in : * time to prevent any conflict, but the transition from : * shared->private is sometimes missed if we don't do this. : */ :static void :DRIClipNotifyAllDrawables(ScreenPtr pScreen) :{ : int i; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { : pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++; : } :} : : :static void :DRITransitionToSharedBuffers(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; : : DRIClipNotifyAllDrawables( pScreen ); : : if (pDRIInfo->TransitionSingleToMulti3D) : pDRIInfo->TransitionSingleToMulti3D( pScreen ); :} : : :static void :DRITransitionToPrivateBuffers(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; : : DRIClipNotifyAllDrawables( pScreen ); : : if (pDRIInfo->TransitionMultiToSingle3D) : pDRIInfo->TransitionMultiToSingle3D( pScreen ); :} : : :static void :DRITransitionTo3d(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; : : DRIClipNotifyAllDrawables( pScreen ); : : if (pDRIInfo->TransitionTo3d) : pDRIInfo->TransitionTo3d( pScreen ); :} : :static void :DRITransitionTo2d(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; : : DRIClipNotifyAllDrawables( pScreen ); : : if (pDRIInfo->TransitionTo2d) : pDRIInfo->TransitionTo2d( pScreen ); :} : : :static int :DRIDCNTreeTraversal(WindowPtr pWin, pointer data) :{ : DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); : : if (pDRIDrawablePriv) { : ScreenPtr pScreen = pWin->drawable.pScreen; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (REGION_NUM_RECTS(&pWin->clipList) > 0) { : WindowPtr *pDRIWindows = (WindowPtr*)data; : int i = 0; : : while (pDRIWindows[i]) : i++; : : pDRIWindows[i] = pWin; : : pDRIPriv->nrWalked++; : } : : if (pDRIPriv->nrWindows == pDRIPriv->nrWalked) : return WT_STOPWALKING; : } : : return WT_WALKCHILDREN; :} : :static void :DRIDriverClipNotify(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (pDRIPriv->pDriverInfo->ClipNotify) { : WindowPtr *pDRIWindows = xcalloc(sizeof(WindowPtr), pDRIPriv->nrWindows); : DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; : : if (pDRIPriv->nrWindows > 0) { : pDRIPriv->nrWalked = 0; : TraverseTree(WindowTable[pScreen->myNum], DRIDCNTreeTraversal, : (pointer)pDRIWindows); : } : : pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows); : : xfree(pDRIWindows); : } :} : :static void :DRIIncreaseNumberVisible(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : switch (++pDRIPriv->nrWindowsVisible) { : case 1: : DRITransitionTo3d( pScreen ); : break; : case 2: : DRITransitionToSharedBuffers( pScreen ); : break; : default: : break; : } : : DRIDriverClipNotify(pScreen); :} : :static void :DRIDecreaseNumberVisible(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : switch (--pDRIPriv->nrWindowsVisible) { : case 0: : DRITransitionTo2d( pScreen ); : break; : case 1: : DRITransitionToPrivateBuffers( pScreen ); : break; : default: : break; : } : : DRIDriverClipNotify(pScreen); :} : :Bool :DRICreateDrawable(ScreenPtr pScreen, Drawable id, : DrawablePtr pDrawable, drm_drawable_t * hHWDrawable) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIDrawablePrivPtr pDRIDrawablePriv; : WindowPtr pWin; : : if (pDrawable->type == DRAWABLE_WINDOW) { : pWin = (WindowPtr)pDrawable; : if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { : pDRIDrawablePriv->refCount++; : : if (!pDRIDrawablePriv->hwDrawable) { : drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable); : } : } : else { : /* allocate a DRI Window Private record */ : if (!(pDRIDrawablePriv = xalloc(sizeof(DRIDrawablePrivRec)))) { : return FALSE; : } : : /* Only create a drm_drawable_t once */ : if (drmCreateDrawable(pDRIPriv->drmFD, : &pDRIDrawablePriv->hwDrawable)) { : xfree(pDRIDrawablePriv); : return FALSE; : } : : /* add it to the list of DRI drawables for this screen */ : pDRIDrawablePriv->pScreen = pScreen; : pDRIDrawablePriv->refCount = 1; : pDRIDrawablePriv->drawableIndex = -1; : pDRIDrawablePriv->nrects = REGION_NUM_RECTS(&pWin->clipList); : : /* save private off of preallocated index */ : pWin->devPrivates[DRIWindowPrivIndex].ptr = : (pointer)pDRIDrawablePriv; : : pDRIPriv->nrWindows++; : : if (pDRIDrawablePriv->nrects) : DRIIncreaseNumberVisible(pScreen); : : /* track this in case this window is destroyed */ : AddResource(id, DRIDrawablePrivResType, (pointer)pWin); : } : : if (pDRIDrawablePriv->hwDrawable) { : drmUpdateDrawableInfo(pDRIPriv->drmFD, : pDRIDrawablePriv->hwDrawable, : DRM_DRAWABLE_CLIPRECTS, : REGION_NUM_RECTS(&pWin->clipList), : REGION_RECTS(&pWin->clipList)); : *hHWDrawable = pDRIDrawablePriv->hwDrawable; : } : } : else { /* pixmap (or for GLX 1.3, a PBuffer) */ : /* NOT_DONE */ : return FALSE; : } : : return TRUE; :} : :Bool :DRIDestroyDrawable(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable) :{ : DRIDrawablePrivPtr pDRIDrawablePriv; : WindowPtr pWin; : : : if (pDrawable->type == DRAWABLE_WINDOW) { : pWin = (WindowPtr)pDrawable; : pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); : pDRIDrawablePriv->refCount--; : if (pDRIDrawablePriv->refCount <= 0) { : /* This calls back DRIDrawablePrivDelete which frees private area */ : FreeResourceByType(id, DRIDrawablePrivResType, FALSE); : } : } : else { /* pixmap (or for GLX 1.3, a PBuffer) */ : /* NOT_DONE */ : return FALSE; : } : : return TRUE; :} : :Bool :DRIDrawablePrivDelete(pointer pResource, XID id) :{ : DrawablePtr pDrawable = (DrawablePtr)pResource; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen); : DRIDrawablePrivPtr pDRIDrawablePriv; : WindowPtr pWin; : : if (pDrawable->type == DRAWABLE_WINDOW) { : pWin = (WindowPtr)pDrawable; : pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); : : if (pDRIDrawablePriv->drawableIndex != -1) { : /* bump stamp to force outstanding 3D requests to resync */ : pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp : = DRIDrawableValidationStamp++; : : /* release drawable table entry */ : pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; : } : : if (drmDestroyDrawable(pDRIPriv->drmFD, : pDRIDrawablePriv->hwDrawable)) { : return FALSE; : } : : xfree(pDRIDrawablePriv); : pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL; : : pDRIPriv->nrWindows--; : : if (REGION_NUM_RECTS(&pWin->clipList)) : DRIDecreaseNumberVisible(pDrawable->pScreen); : } : else { /* pixmap (or for GLX 1.3, a PBuffer) */ : /* NOT_DONE */ : return FALSE; : } : : return TRUE; :} : :Bool :DRIGetDrawableInfo(ScreenPtr pScreen, : DrawablePtr pDrawable, : unsigned int* index, : unsigned int* stamp, : int* X, : int* Y, : int* W, : int* H, : int* numClipRects, : drm_clip_rect_t ** pClipRects, : int* backX, : int* backY, : int* numBackClipRects, : drm_clip_rect_t ** pBackClipRects) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv; : WindowPtr pWin, pOldWin; : int i; : :#if 0 : printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry); :#endif : : if (pDrawable->type == DRAWABLE_WINDOW) { : pWin = (WindowPtr)pDrawable; : if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { : : /* Manage drawable table */ : if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */ : : /* Search table for empty entry */ : i = 0; : while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) { : if (!(pDRIPriv->DRIDrawables[i])) { : pDRIPriv->DRIDrawables[i] = pDrawable; : pDRIDrawablePriv->drawableIndex = i; : pDRIPriv->pSAREA->drawableTable[i].stamp = : DRIDrawableValidationStamp++; : break; : } : i++; : } : : /* Search table for oldest entry */ : if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) { : unsigned int oldestStamp = ~0; : int oldestIndex = 0; : i = pDRIPriv->pDriverInfo->maxDrawableTableEntry; : while (i--) { : if (pDRIPriv->pSAREA->drawableTable[i].stamp < : oldestStamp) { : oldestIndex = i; : oldestStamp = : pDRIPriv->pSAREA->drawableTable[i].stamp; : } : } : pDRIDrawablePriv->drawableIndex = oldestIndex; : : /* release oldest drawable table entry */ : pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex]; : pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin); : pOldDrawPriv->drawableIndex = -1; : : /* claim drawable table entry */ : pDRIPriv->DRIDrawables[oldestIndex] = pDrawable; : : /* validate SAREA entry */ : pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp = : DRIDrawableValidationStamp++; : : /* check for stamp wrap around */ : if (oldestStamp > DRIDrawableValidationStamp) { : : /* walk SAREA table and invalidate all drawables */ : for( i=0; : i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; : i++) { : pDRIPriv->pSAREA->drawableTable[i].stamp = : DRIDrawableValidationStamp++; : } : } : } : : /* If the driver wants to be notified when the index is : * set for a drawable, let it know now. : */ : if (pDRIPriv->pDriverInfo->SetDrawableIndex) : pDRIPriv->pDriverInfo->SetDrawableIndex(pWin, : pDRIDrawablePriv->drawableIndex); : : /* reinit drawable ID if window is visible */ : if ((pWin->viewable) && : (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) : { : (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, : &pWin->clipList, pDRIDrawablePriv->drawableIndex); : } : } : : *index = pDRIDrawablePriv->drawableIndex; : *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp; : *X = (int)(pWin->drawable.x); : *Y = (int)(pWin->drawable.y); :#if 0 : *W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1); : *H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1); :#endif : *W = (int)(pWin->drawable.width); : *H = (int)(pWin->drawable.height); : *numClipRects = REGION_NUM_RECTS(&pWin->clipList); : *pClipRects = (drm_clip_rect_t *)REGION_RECTS(&pWin->clipList); : : if (!*numClipRects && pDRIPriv->fullscreen) { : /* use fake full-screen clip rect */ : pDRIPriv->fullscreen_rect.x1 = *X; : pDRIPriv->fullscreen_rect.y1 = *Y; : pDRIPriv->fullscreen_rect.x2 = *X + *W; : pDRIPriv->fullscreen_rect.y2 = *Y + *H; : : *numClipRects = 1; : *pClipRects = &pDRIPriv->fullscreen_rect; : } : : *backX = *X; : *backY = *Y; : : if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) { : /* Use a single cliprect. */ : : int x0 = *X; : int y0 = *Y; : int x1 = x0 + *W; : int y1 = y0 + *H; : : if (x0 < 0) x0 = 0; : if (y0 < 0) y0 = 0; : if (x1 > pScreen->width) x1 = pScreen->width; : if (y1 > pScreen->height) y1 = pScreen->height; : : if (y0 >= y1 || x0 >= x1) { : *numBackClipRects = 0; : *pBackClipRects = NULL; : } else { : pDRIPriv->private_buffer_rect.x1 = x0; : pDRIPriv->private_buffer_rect.y1 = y0; : pDRIPriv->private_buffer_rect.x2 = x1; : pDRIPriv->private_buffer_rect.y2 = y1; : : *numBackClipRects = 1; : *pBackClipRects = &(pDRIPriv->private_buffer_rect); : } : } else { : /* Use the frontbuffer cliprects for back buffers. */ : *numBackClipRects = 0; : *pBackClipRects = 0; : } : } : else { : /* Not a DRIDrawable */ : return FALSE; : } : } : else { /* pixmap (or for GLX 1.3, a PBuffer) */ : /* NOT_DONE */ : return FALSE; : } : : return TRUE; :} : :Bool :DRIGetDeviceInfo(ScreenPtr pScreen, : drm_handle_t * hFrameBuffer, : int* fbOrigin, : int* fbSize, : int* fbStride, : int* devPrivateSize, : void** pDevPrivate) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : *hFrameBuffer = pDRIPriv->hFrameBuffer; : *fbOrigin = 0; : *fbSize = pDRIPriv->pDriverInfo->frameBufferSize; : *fbStride = pDRIPriv->pDriverInfo->frameBufferStride; : *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize; : *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate; : : return TRUE; :} : :DRIInfoPtr :DRICreateInfoRec(void) :{ : DRIInfoPtr inforec = (DRIInfoPtr)xcalloc(1, sizeof(DRIInfoRec)); : if (!inforec) return NULL; : : /* Initialize defaults */ : inforec->busIdString = NULL; : : /* Wrapped function defaults */ : inforec->wrap.WakeupHandler = DRIDoWakeupHandler; : inforec->wrap.BlockHandler = DRIDoBlockHandler; : inforec->wrap.WindowExposures = DRIWindowExposures; : inforec->wrap.CopyWindow = DRICopyWindow; : inforec->wrap.ValidateTree = DRIValidateTree; : inforec->wrap.PostValidateTree = DRIPostValidateTree; : inforec->wrap.ClipNotify = DRIClipNotify; : inforec->wrap.AdjustFrame = DRIAdjustFrame; : : inforec->TransitionTo2d = 0; : inforec->TransitionTo3d = 0; : inforec->SetDrawableIndex = 0; : : return inforec; :} : :void :DRIDestroyInfoRec(DRIInfoPtr DRIInfo) :{ : if (DRIInfo->busIdString) xfree(DRIInfo->busIdString); : xfree((char*)DRIInfo); :} : : :void :DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask) :{ : int i; : : for (i = 0; i < screenInfo.numScreens; i++) { : ScreenPtr pScreen = screenInfo.screens[i]; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (pDRIPriv && : pDRIPriv->pDriverInfo->wrap.WakeupHandler) : (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData, : result, pReadmask); : } :} : :void :DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) :{ : int i; : : for (i = 0; i < screenInfo.numScreens; i++) { : ScreenPtr pScreen = screenInfo.screens[i]; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (pDRIPriv && : pDRIPriv->pDriverInfo->wrap.BlockHandler) : (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData, : pTimeout, pReadmask); : } :} : :void :DRIDoWakeupHandler(int screenNum, pointer wakeupData, : unsigned long result, pointer pReadmask) :{ : ScreenPtr pScreen = screenInfo.screens[screenNum]; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : DRILock(pScreen, 0); : if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { : /* hide X context by swapping 2D component here */ : (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, : DRI_3D_SYNC, : DRI_2D_CONTEXT, : pDRIPriv->partial3DContextStore, : DRI_2D_CONTEXT, : pDRIPriv->hiddenContextStore); : } :} : :void :DRIDoBlockHandler(int screenNum, pointer blockData, : pointer pTimeout, pointer pReadmask) :{ : ScreenPtr pScreen = screenInfo.screens[screenNum]; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { : /* hide X context by swapping 2D component here */ : (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, : DRI_2D_SYNC, : DRI_NO_CONTEXT, : NULL, : DRI_2D_CONTEXT, : pDRIPriv->partial3DContextStore); : } : : if (pDRIPriv->windowsTouched) : DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1); : pDRIPriv->windowsTouched = FALSE; : : DRIUnlock(pScreen); :} : :void :DRISwapContext(int drmFD, void *oldctx, void *newctx) :{ : DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx; : DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx; : ScreenPtr pScreen = newContext->pScreen; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : void* oldContextStore = NULL; : DRIContextType oldContextType; : void* newContextStore = NULL; : DRIContextType newContextType; : DRISyncType syncType; :#ifdef DEBUG : static int count = 0; : : if (!newContext) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n", : oldContext, newContext); : return; : } : : /* usefull for debugging, just print out after n context switches */ : if (!count || !(count % 1)) { : DRIDrvMsg(pScreen->myNum, X_INFO, : "[DRI] Context switch %5d from %p/0x%08x (%d)\n", : count, : oldContext, : oldContext ? oldContext->flags : 0, : oldContext ? oldContext->hwContext : -1); : DRIDrvMsg(pScreen->myNum, X_INFO, : "[DRI] Context switch %5d to %p/0x%08x (%d)\n", : count, : newContext, : newContext ? newContext->flags : 0, : newContext ? newContext->hwContext : -1); : } : ++count; :#endif : : if (!pDRIPriv->pDriverInfo->SwapContext) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[DRI] DDX driver missing context swap call back\n"); : return; : } : : if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { : : /* only 3D contexts are swapped in this case */ : if (oldContext) { : oldContextStore = DRIGetContextStore(oldContext); : oldContext->valid3D = TRUE; : oldContextType = DRI_3D_CONTEXT; : } else { : oldContextType = DRI_NO_CONTEXT; : } : newContextStore = DRIGetContextStore(newContext); : if ((newContext->valid3D) && : (newContext->hwContext != pDRIPriv->myContext)) { : newContextType = DRI_3D_CONTEXT; : } : else { : newContextType = DRI_2D_CONTEXT; : } : syncType = DRI_3D_SYNC; : } : else /* default: driverSwapMethod == DRI_SERVER_SWAP */ { : : /* optimize 2D context swaps */ : : if (newContext->flags & DRI_CONTEXT_2DONLY) { : /* go from 3D context to 2D context and only save 2D : * subset of 3D state : */ : oldContextStore = DRIGetContextStore(oldContext); : oldContextType = DRI_2D_CONTEXT; : newContextStore = DRIGetContextStore(newContext); : newContextType = DRI_2D_CONTEXT; : syncType = DRI_3D_SYNC; : pDRIPriv->lastPartial3DContext = oldContext; : } : else if (oldContext->flags & DRI_CONTEXT_2DONLY) { : if (pDRIPriv->lastPartial3DContext == newContext) { : /* go from 2D context back to previous 3D context and : * only restore 2D subset of previous 3D state : */ : oldContextStore = DRIGetContextStore(oldContext); : oldContextType = DRI_2D_CONTEXT; : newContextStore = DRIGetContextStore(newContext); : newContextType = DRI_2D_CONTEXT; : syncType = DRI_2D_SYNC; : } : else { : /* go from 2D context to a different 3D context */ : : /* call DDX driver to do partial restore */ : oldContextStore = DRIGetContextStore(oldContext); : newContextStore = : DRIGetContextStore(pDRIPriv->lastPartial3DContext); : (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, : DRI_2D_SYNC, : DRI_2D_CONTEXT, : oldContextStore, : DRI_2D_CONTEXT, : newContextStore); : : /* now setup for a complete 3D swap */ : oldContextStore = newContextStore; : oldContext->valid3D = TRUE; : oldContextType = DRI_3D_CONTEXT; : newContextStore = DRIGetContextStore(newContext); : if ((newContext->valid3D) && : (newContext->hwContext != pDRIPriv->myContext)) { : newContextType = DRI_3D_CONTEXT; : } : else { : newContextType = DRI_2D_CONTEXT; : } : syncType = DRI_NO_SYNC; : } : } : else { : /* now setup for a complete 3D swap */ : oldContextStore = newContextStore; : oldContext->valid3D = TRUE; : oldContextType = DRI_3D_CONTEXT; : newContextStore = DRIGetContextStore(newContext); : if ((newContext->valid3D) && : (newContext->hwContext != pDRIPriv->myContext)) { : newContextType = DRI_3D_CONTEXT; : } : else { : newContextType = DRI_2D_CONTEXT; : } : syncType = DRI_3D_SYNC; : } : } : : /* call DDX driver to perform the swap */ : (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, : syncType, : oldContextType, : oldContextStore, : newContextType, : newContextStore); :} : :void* :DRIGetContextStore(DRIContextPrivPtr context) :{ : return((void *)context->pContextStore); :} : :void :DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) :{ : ScreenPtr pScreen = pWin->drawable.pScreen; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); : : if(pDRIDrawablePriv) { : (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn, : pDRIDrawablePriv->drawableIndex); : } : : /* call lower wrapped functions */ : if (pDRIPriv && pDRIPriv->wrap.WindowExposures) { : : /* unwrap */ : pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; : : /* call lower layers */ : (*pScreen->WindowExposures)(pWin, prgn, bsreg); : : /* rewrap */ : pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; : pScreen->WindowExposures = DRIWindowExposures; : } :} : : :static int :DRITreeTraversal(WindowPtr pWin, pointer data) :{ : DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); : : if(pDRIDrawablePriv) { : ScreenPtr pScreen = pWin->drawable.pScreen; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if(REGION_NUM_RECTS(&(pWin->clipList)) > 0) { : RegionPtr reg = (RegionPtr)data; : : REGION_UNION(pScreen, reg, reg, &(pWin->clipList)); : pDRIPriv->nrWalked++; : } : : if(pDRIPriv->nrWindows == pDRIPriv->nrWalked) : return WT_STOPWALKING; : } : return WT_WALKCHILDREN; :} : :void :DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) :{ : ScreenPtr pScreen = pWin->drawable.pScreen; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if(!pDRIPriv) return; : : if(pDRIPriv->nrWindowsVisible > 0) { : RegionRec reg; : : REGION_NULL(pScreen, ®); : pDRIPriv->nrWalked = 0; : TraverseTree(pWin, DRITreeTraversal, (pointer)(®)); : : if(REGION_NOTEMPTY(pScreen, ®)) { : REGION_TRANSLATE(pScreen, ®, ptOldOrg.x - pWin->drawable.x, : ptOldOrg.y - pWin->drawable.y); : REGION_INTERSECT(pScreen, ®, ®, prgnSrc); : : /* The MoveBuffers interface is not ideal */ : (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®, : pDRIPriv->pDriverInfo->ddxDrawableTableEntry); : } : : REGION_UNINIT(pScreen, ®); : } : : /* call lower wrapped functions */ : if(pDRIPriv->wrap.CopyWindow) { : /* unwrap */ : pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; : : /* call lower layers */ : (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); : : /* rewrap */ : pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; : pScreen->CopyWindow = DRICopyWindow; : } :} : :static void :DRIGetSecs(long *secs, long *usecs) :{ : struct timeval tv; : : gettimeofday(&tv, NULL); : : *secs = tv.tv_sec; : *usecs = tv.tv_usec; :} : :static unsigned long :DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs, : unsigned long f_secs, unsigned long f_usecs) :{ : if (f_usecs < s_usecs) { : --f_secs; : f_usecs += 1000000; : } : return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000; :} : :static void :DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */) :{ : int count = 10000; :#if !defined(__alpha__) && !defined(__powerpc__) : char ret; :#else : int ret; :#endif : long s_secs, s_usecs; : long f_secs, f_usecs; : long msecs; : long prev = 0; : : DRIGetSecs(&s_secs, &s_usecs); : : do { : DRM_SPINLOCK_COUNT(lock, val, count, ret); : if (!ret) return; /* Got lock */ : DRIGetSecs(&f_secs, &f_usecs); : msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs); : if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */ : } while (msecs < timeout); : : /* Didn't get lock, so take it. The worst : that can happen is that there is some : garbage written to the wrong part of the : framebuffer that a refresh will repair. : That's undesirable, but better than : locking the server. This should be a : very rare event. */ : DRM_SPINLOCK_TAKE(lock, val); :} : :static void :DRILockTree(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if(!pDRIPriv) return; : : /* Restore the last known 3D context if the X context is hidden */ : if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { : (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, : DRI_2D_SYNC, : DRI_NO_CONTEXT, : NULL, : DRI_2D_CONTEXT, : pDRIPriv->partial3DContextStore); : } : : /* Call kernel to release lock */ : DRIUnlock(pScreen); : : /* Grab drawable spin lock: a time out between 10 and 30 seconds is : appropriate, since this should never time out except in the case of : client death while the lock is being held. The timeout must be : greater than any reasonable rendering time. */ : DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/ : : /* Call kernel flush outstanding buffers and relock */ : DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL); : : /* Switch back to our 2D context if the X context is hidden */ : if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { : /* hide X context by swapping 2D component here */ : (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, : DRI_3D_SYNC, : DRI_2D_CONTEXT, : pDRIPriv->partial3DContextStore, : DRI_2D_CONTEXT, : pDRIPriv->hiddenContextStore); : } :} : :int :DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) :{ : ScreenPtr pScreen = pParent->drawable.pScreen; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : int returnValue = 1; /* always return 1, not checked by dix/window.c */ : : if(!pDRIPriv) return returnValue; : : /* call lower wrapped functions */ : if(pDRIPriv->wrap.ValidateTree) { : /* unwrap */ : pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; : : /* call lower layers */ : returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); : : /* rewrap */ : pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; : pScreen->ValidateTree = DRIValidateTree; : } : : return returnValue; :} : :void :DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) :{ : ScreenPtr pScreen; : DRIScreenPrivPtr pDRIPriv; : : if (pParent) { : pScreen = pParent->drawable.pScreen; : } else { : pScreen = pChild->drawable.pScreen; : } : if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return; : : if (pDRIPriv->wrap.PostValidateTree) { : /* unwrap */ : pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; : : /* call lower layers */ : (*pScreen->PostValidateTree)(pParent, pChild, kind); : : /* rewrap */ : pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; : pScreen->PostValidateTree = DRIPostValidateTree; : } :} : :void :DRIClipNotify(WindowPtr pWin, int dx, int dy) :{ : ScreenPtr pScreen = pWin->drawable.pScreen; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIDrawablePrivPtr pDRIDrawablePriv; : : if(!pDRIPriv) return; : : if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { : int nrects = REGION_NUM_RECTS(&pWin->clipList); : : if(!pDRIPriv->windowsTouched) { : DRILockTree(pScreen); : pDRIPriv->windowsTouched = TRUE; : } : : if (nrects && !pDRIDrawablePriv->nrects) : DRIIncreaseNumberVisible(pScreen); : else if (!nrects && pDRIDrawablePriv->nrects) : DRIDecreaseNumberVisible(pScreen); : else : DRIDriverClipNotify(pScreen); : : pDRIDrawablePriv->nrects = nrects; : : pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp : = DRIDrawableValidationStamp++; : : drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable, : DRM_DRAWABLE_CLIPRECTS, : nrects, REGION_RECTS(&pWin->clipList)); : } : : /* call lower wrapped functions */ : if(pDRIPriv->wrap.ClipNotify) { : : /* unwrap */ : pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; : : /* call lower layers */ : (*pScreen->ClipNotify)(pWin, dx, dy); : : /* rewrap */ : pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; : pScreen->ClipNotify = DRIClipNotify; : } :} : :CARD32 :DRIGetDrawableIndex(WindowPtr pWin) :{ : ScreenPtr pScreen = pWin->drawable.pScreen; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); : CARD32 index; : : if (pDRIDrawablePriv) { : index = pDRIDrawablePriv->drawableIndex; : } : else { : index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry; : } : : return index; :} : :unsigned int :DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp; :} : : :void :DRIPrintDrawableLock(ScreenPtr pScreen, char *msg) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock); :} : :void :DRILock(ScreenPtr pScreen, int flags) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; : : if (!*pDRIPriv->pLockRefCount) { : DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags); : *pDRIPriv->pLockingContext = pDRIPriv->myContext; : } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[DRI] Locking deadlock.\n" : "\tAlready locked with context %d,\n" : "\ttrying to lock with context %d.\n", : pDRIPriv->pLockingContext, : pDRIPriv->myContext); : } : (*pDRIPriv->pLockRefCount)++; :} : :void :DRIUnlock(ScreenPtr pScreen) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; : : if (*pDRIPriv->pLockRefCount > 0) { : if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "[DRI] Unlocking inconsistency:\n" : "\tContext %d trying to unlock lock held by context %d\n", : pDRIPriv->pLockingContext, : pDRIPriv->myContext); : } : (*pDRIPriv->pLockRefCount)--; : } else { : DRIDrvMsg(pScreen->myNum, X_ERROR, : "DRIUnlock called when not locked.\n"); : return; : } : if (! *pDRIPriv->pLockRefCount) : DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext); :} : :void * :DRIGetSAREAPrivate(ScreenPtr pScreen) 6 0.0065 :{ /* DRIGetSAREAPrivate total: 25 0.0272 */ 4 0.0044 : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2 0.0022 : if (!pDRIPriv) return 0; : 1 0.0011 : return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec)); 12 0.0131 :} : :drm_context_t :DRIGetContext(ScreenPtr pScreen) 8 0.0087 :{ /* DRIGetContext total: 16 0.0174 */ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1 0.0011 : if (!pDRIPriv) return 0; : : return pDRIPriv->myContext; 7 0.0076 :} : :void :DRIGetTexOffsetFuncs(ScreenPtr pScreen, : DRITexOffsetStartProcPtr *texOffsetStartFunc, : DRITexOffsetFinishProcPtr *texOffsetFinishFunc) :{ : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : : if (!pDRIPriv) return; : : *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart; : *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish; :} : :/* This lets get at the unwrapped functions so that they can correctly : * call the lowerlevel functions, and choose whether they will be : * called at every level of recursion (eg in validatetree). : */ :DRIWrappedFuncsRec * :DRIGetWrappedFuncs(ScreenPtr pScreen) :{ : return &(DRI_SCREEN_PRIV(pScreen)->wrap); :} : :/* note that this returns the library version, not the protocol version */ :void :DRIQueryVersion(int *majorVersion, : int *minorVersion, : int *patchVersion) :{ : *majorVersion = DRIINFO_MAJOR_VERSION; : *minorVersion = DRIINFO_MINOR_VERSION; : *patchVersion = DRIINFO_PATCH_VERSION; :} : :static void :_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y) :{ : pDRIPriv->pSAREA->frame.x = x; : pDRIPriv->pSAREA->frame.y = y; : pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1; : pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1; :} : :void :DRIAdjustFrame(int scrnIndex, int x, int y, int flags) :{ : ScreenPtr pScreen = screenInfo.screens[scrnIndex]; : DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); : ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; : int px, py; : : if (!pDRIPriv || !pDRIPriv->pSAREA) { : DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n", : pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL); : return; : } : : if (pDRIPriv->fullscreen) { : /* Fix up frame */ : pScrn->frameX0 = pDRIPriv->pSAREA->frame.x; : pScrn->frameY0 = pDRIPriv->pSAREA->frame.y; : pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1; : pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1; : : /* Fix up cursor */ : miPointerPosition(&px, &py); : if (px < pScrn->frameX0) px = pScrn->frameX0; : if (px > pScrn->frameX1) px = pScrn->frameX1; : if (py < pScrn->frameY0) py = pScrn->frameY0; : if (py > pScrn->frameY1) py = pScrn->frameY1; : pScreen->SetCursorPosition(pScreen, px, py, TRUE); : return; : } : : if (pDRIPriv->wrap.AdjustFrame) { : /* unwrap */ : pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; : /* call lower layers */ : (*pScrn->AdjustFrame)(scrnIndex, x, y, flags); : /* rewrap */ : pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; : pScrn->AdjustFrame = DRIAdjustFrame; : } : : _DRIAdjustFrame(pScrn, pDRIPriv, x, y); :} : :/* : * DRIMoveBuffersHelper swaps the regions rects in place leaving you : * a region with the rects in the order that you need to blit them, : * but it is possibly (likely) an invalid region afterwards. If you : * need to use the region again for anything you have to call : * REGION_VALIDATE on it, or better yet, save a copy first. : */ : :void :DRIMoveBuffersHelper( : ScreenPtr pScreen, : int dx, : int dy, : int *xdir, : int *ydir, : RegionPtr reg :) :{ : BoxPtr extents, pbox, firstBox, lastBox; : BoxRec tmpBox; : int y, nbox; : : extents = REGION_EXTENTS(pScreen, reg); : nbox = REGION_NUM_RECTS(reg); : pbox = REGION_RECTS(reg); : : if((dy > 0) && (dy < (extents->y2 - extents->y1))) { : *ydir = -1; : if(nbox > 1) { : firstBox = pbox; : lastBox = pbox + nbox - 1; : while((unsigned long)firstBox < (unsigned long)lastBox) { : tmpBox = *firstBox; : *firstBox = *lastBox; : *lastBox = tmpBox; : firstBox++; : lastBox--; : } : } : } else *ydir = 1; : : if((dx > 0) && (dx < (extents->x2 - extents->x1))) { : *xdir = -1; : if(nbox > 1) { : firstBox = lastBox = pbox; : y = pbox->y1; : while(--nbox) { : pbox++; : if(pbox->y1 == y) lastBox++; : else { : while((unsigned long)firstBox < (unsigned long)lastBox) { : tmpBox = *firstBox; : *firstBox = *lastBox; : *lastBox = tmpBox; : firstBox++; : lastBox--; : } : : firstBox = lastBox = pbox; : y = pbox->y1; : } : } : while((unsigned long)firstBox < (unsigned long)lastBox) { : tmpBox = *firstBox; : *firstBox = *lastBox; : *lastBox = tmpBox; : firstBox++; : lastBox--; : } : } : } else *xdir = 1; : :} : :char * :DRICreatePCIBusID(pciVideoPtr PciInfo) :{ : char *busID; : int domain; : PCITAG tag; : : busID = xalloc(20); : if (busID == NULL) : return NULL; : : tag = pciTag(PciInfo->bus, PciInfo->device, PciInfo->func); : domain = xf86GetPciDomain(tag); : snprintf(busID, 20, "pci:%04x:%02x:%02x.%d", domain, : PCI_BUS_NO_DOMAIN(PciInfo->bus), PciInfo->device, PciInfo->func); : return busID; :} : :static void drmSIGIOHandler(int interrupt, void *closure) :{ : unsigned long key; : void *value; : ssize_t count; : drm_ctx_t ctx; : typedef void (*_drmCallback)(int, void *, void *); : char buf[256]; : drm_context_t old; : drm_context_t new; : void *oldctx; : void *newctx; : char *pt; : drmHashEntry *entry; : void *hash_table; : : hash_table = drmGetHashTable(); : : if (!hash_table) return; : if (drmHashFirst(hash_table, &key, &value)) { : entry = value; : do { :#if 0 : fprintf(stderr, "Trying %d\n", entry->fd); :#endif : if ((count = read(entry->fd, buf, sizeof(buf))) > 0) { : buf[count] = '\0'; :#if 0 : fprintf(stderr, "Got %s\n", buf); :#endif : : for (pt = buf; *pt != ' '; ++pt); /* Find first space */ : ++pt; : old = strtol(pt, &pt, 0); : new = strtol(pt, NULL, 0); : oldctx = drmGetContextTag(entry->fd, old); : newctx = drmGetContextTag(entry->fd, new); :#if 0 : fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); :#endif : ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); : ctx.handle = new; : ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); : } : } while (drmHashNext(hash_table, &key, &value)); : } :} : : :int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) :{ : drmHashEntry *entry; : : entry = drmGetEntry(fd); : entry->f = f; : : return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); :} : :int drmRemoveSIGIOHandler(int fd) :{ : drmHashEntry *entry = drmGetEntry(fd); : : entry->f = NULL; : : return xf86RemoveSIGIOHandler(fd); :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/render/filter.c" * * 34 0.0370 */ :/* : * Copyright © 2002 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "misc.h" :#include "scrnintstr.h" :#include "os.h" :#include "regionstr.h" :#include "validate.h" :#include "windowstr.h" :#include "input.h" :#include "resource.h" :#include "colormapst.h" :#include "cursorstr.h" :#include "dixstruct.h" :#include "gcstruct.h" :#include "servermd.h" :#include "picturestr.h" : :static char **filterNames; :static int nfilterNames; : :/* : * standard but not required filters don't have constant indices : */ : :int :PictureGetFilterId (char *filter, int len, Bool makeit) 3 0.0033 :{ /* PictureGetFilterId total: 16 0.0174 */ : int i; : char *name; : char **names; : : if (len < 0) 7 0.0076 : len = strlen (filter); : for (i = 0; i < nfilterNames; i++) 6 0.0065 : if (!CompareISOLatin1Lowered ((unsigned char *) filterNames[i], -1, (unsigned char *) filter, len)) : return i; : if (!makeit) : return -1; : name = xalloc (len + 1); : if (!name) : return -1; : memcpy (name, filter, len); : name[len] = '\0'; : if (filterNames) : names = xrealloc (filterNames, (nfilterNames + 1) * sizeof (char *)); : else : names = xalloc (sizeof (char *)); : if (!names) : { : xfree (name); : return -1; : } : filterNames = names; : i = nfilterNames++; : filterNames[i] = name; : return i; :} : :static Bool :PictureSetDefaultIds (void) :{ : /* careful here -- this list must match the #define values */ : : if (PictureGetFilterId (FilterNearest, -1, TRUE) != PictFilterNearest) : return FALSE; : if (PictureGetFilterId (FilterBilinear, -1, TRUE) != PictFilterBilinear) : return FALSE; : : if (PictureGetFilterId (FilterFast, -1, TRUE) != PictFilterFast) : return FALSE; : if (PictureGetFilterId (FilterGood, -1, TRUE) != PictFilterGood) : return FALSE; : if (PictureGetFilterId (FilterBest, -1, TRUE) != PictFilterBest) : return FALSE; : : if (PictureGetFilterId (FilterConvolution, -1, TRUE) != PictFilterConvolution) : return FALSE; : return TRUE; :} : :char * :PictureGetFilterName (int id) :{ : if (0 <= id && id < nfilterNames) : return filterNames[id]; : else : return 0; :} : :static void :PictureFreeFilterIds (void) :{ : int i; : : for (i = 0; i < nfilterNames; i++) : xfree (filterNames[i]); : xfree (filterNames); : nfilterNames = 0; : filterNames = 0; :} : :_X_EXPORT int :PictureAddFilter (ScreenPtr pScreen, : char *filter, : PictFilterValidateParamsProcPtr ValidateParams) :{ : PictureScreenPtr ps = GetPictureScreen(pScreen); : int id = PictureGetFilterId (filter, -1, TRUE); : int i; : PictFilterPtr filters; : : if (id < 0) : return -1; : /* : * It's an error to attempt to reregister a filter : */ : for (i = 0; i < ps->nfilters; i++) : if (ps->filters[i].id == id) : return -1; : if (ps->filters) : filters = xrealloc (ps->filters, (ps->nfilters + 1) * sizeof (PictFilterRec)); : else : filters = xalloc (sizeof (PictFilterRec)); : if (!filters) : return -1; : ps->filters = filters; : i = ps->nfilters++; : ps->filters[i].name = PictureGetFilterName (id); : ps->filters[i].id = id; : ps->filters[i].ValidateParams = ValidateParams; : return id; :} : :_X_EXPORT Bool :PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias) :{ : PictureScreenPtr ps = GetPictureScreen(pScreen); : int filter_id = PictureGetFilterId (filter, -1, FALSE); : int alias_id = PictureGetFilterId (alias, -1, TRUE); : int i; : : if (filter_id < 0 || alias_id < 0) : return FALSE; : for (i = 0; i < ps->nfilterAliases; i++) : if (ps->filterAliases[i].alias_id == alias_id) : break; : if (i == ps->nfilterAliases) : { : PictFilterAliasPtr aliases; : : if (ps->filterAliases) : aliases = xrealloc (ps->filterAliases, : (ps->nfilterAliases + 1) * : sizeof (PictFilterAliasRec)); : else : aliases = xalloc (sizeof (PictFilterAliasRec)); : if (!aliases) : return FALSE; : ps->filterAliases = aliases; : ps->filterAliases[i].alias = PictureGetFilterName (alias_id); : ps->filterAliases[i].alias_id = alias_id; : ps->nfilterAliases++; : } : ps->filterAliases[i].filter_id = filter_id; : return TRUE; :} : :PictFilterPtr :PictureFindFilter (ScreenPtr pScreen, char *name, int len) 2 0.0022 :{ /* PictureFindFilter total: 8 0.0087 */ 1 0.0011 : PictureScreenPtr ps = GetPictureScreen(pScreen); : int id = PictureGetFilterId (name, len, FALSE); : int i; : : if (id < 0) : return 0; : /* Check for an alias, allow them to recurse */ : for (i = 0; i < ps->nfilterAliases; i++) 4 0.0044 : if (ps->filterAliases[i].alias_id == id) : { : id = ps->filterAliases[i].filter_id; : i = 0; : } : /* find the filter */ : for (i = 0; i < ps->nfilters; i++) : if (ps->filters[i].id == id) : return &ps->filters[i]; : return 0; 1 0.0011 :} : :static Bool :convolutionFilterValidateParams (PicturePtr pPicture, : int filter, : xFixed *params, : int nparams) :{ : if (nparams < 3) : return FALSE; : : if (xFixedFrac (params[0]) || xFixedFrac (params[1])) : return FALSE; : : nparams -= 2; : if ((xFixedToInt (params[0]) * xFixedToInt (params[1])) > nparams) : return FALSE; : : return TRUE; :} : : :Bool :PictureSetDefaultFilters (ScreenPtr pScreen) :{ : if (!filterNames) : if (!PictureSetDefaultIds ()) : return FALSE; : if (PictureAddFilter (pScreen, FilterNearest, 0) < 0) : return FALSE; : if (PictureAddFilter (pScreen, FilterBilinear, 0) < 0) : return FALSE; : : if (!PictureSetFilterAlias (pScreen, FilterNearest, FilterFast)) : return FALSE; : if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterGood)) : return FALSE; : if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterBest)) : return FALSE; : : if (PictureAddFilter (pScreen, FilterConvolution, convolutionFilterValidateParams) < 0) : return FALSE; : : return TRUE; :} : :void :PictureResetFilters (ScreenPtr pScreen) :{ : PictureScreenPtr ps = GetPictureScreen(pScreen); : : xfree (ps->filters); : xfree (ps->filterAliases); : PictureFreeFilterIds (); :} : :int :SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams) :{ /* SetPictureFilter total: 10 0.0109 */ : PictFilterPtr pFilter; : xFixed *new_params; : int i, s, result; : 3 0.0033 : pFilter = PictureFindFilter (screenInfo.screens[0], name, len); : : if (pPicture->pDrawable == NULL) { : /* For source pictures, the picture isn't tied to a screen. So, ensure : * that all screens can handle a filter we set for the picture. : */ : for (s = 0; s < screenInfo.numScreens; s++) { : if (PictureFindFilter (screenInfo.screens[s], name, len)->id != : pFilter->id) : { : return BadMatch; : } : } : } : : if (!pFilter) : return BadName; : if (pFilter->ValidateParams) : { : if (!(*pFilter->ValidateParams) (pPicture, pFilter->id, params, nparams)) : return BadMatch; : } : else if (nparams) : return BadMatch; : 5 0.0054 : if (nparams != pPicture->filter_nparams) : { : new_params = xalloc (nparams * sizeof (xFixed)); : if (!new_params) : return BadAlloc; : xfree (pPicture->filter_params); : pPicture->filter_params = new_params; : pPicture->filter_nparams = nparams; : } : for (i = 0; i < nparams; i++) : pPicture->filter_params[i] = params[i]; : pPicture->filter = pFilter->id; : : if (pPicture->pDrawable) { : ScreenPtr pScreen = pPicture->pDrawable->pScreen; : PictureScreenPtr ps = GetPictureScreen(pScreen); : 1 0.0011 : result = (*ps->ChangePictureFilter) (pPicture, pPicture->filter, : params, nparams); : return result; : } : return Success; 1 0.0011 :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbgc.c" * * 34 0.0370 */ :/* : * Copyright © 1998 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include : :#include "fb.h" : :const GCFuncs fbGCFuncs = { : fbValidateGC, : miChangeGC, : miCopyGC, : miDestroyGC, : miChangeClip, : miDestroyClip, : miCopyClip, :}; : :const GCOps fbGCOps = { : fbFillSpans, : fbSetSpans, : fbPutImage, : fbCopyArea, : fbCopyPlane, : fbPolyPoint, : fbPolyLine, : fbPolySegment, : fbPolyRectangle, : fbPolyArc, : miFillPolygon, : fbPolyFillRect, : fbPolyFillArc, : miPolyText8, : miPolyText16, : miImageText8, : miImageText16, : fbImageGlyphBlt, : fbPolyGlyphBlt, : fbPushPixels :}; : :Bool :fbCreateGC(GCPtr pGC) :{ : pGC->clientClip = NULL; : pGC->clientClipType = CT_NONE; : : pGC->ops = (GCOps *) &fbGCOps; : pGC->funcs = (GCFuncs *) &fbGCFuncs; : : /* fb wants to translate before scan conversion */ : pGC->miTranslate = 1; : : fbGetRotatedPixmap(pGC) = 0; : fbGetExpose(pGC) = 1; : fbGetFreeCompClip(pGC) = 0; : fbGetCompositeClip(pGC) = 0; : fbGetGCPrivate(pGC)->bpp = BitsPerPixel (pGC->depth); : return TRUE; :} : :/* : * Pad pixmap to FB_UNIT bits wide : */ :void :fbPadPixmap (PixmapPtr pPixmap) :{ : int width; : FbBits *bits; : FbBits b; : FbBits mask; : int height; : int w; : int stride; : int bpp; : int xOff, yOff; : : fbGetDrawable (&pPixmap->drawable, bits, stride, bpp, xOff, yOff); : : width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel; : height = pPixmap->drawable.height; : mask = FbBitsMask (0, width); : while (height--) : { : b = READ(bits) & mask; : w = width; : while (w < FB_UNIT) : { : b = b | FbScrRight(b, w); : w <<= 1; : } : WRITE(bits, b); : bits += stride; : } : : fbFinishAccess (&pPixmap->drawable); :} : :/* : * Verify that 'bits' repeats every 'len' bits : */ :static Bool :fbBitsRepeat (FbBits bits, int len, int width) :{ : FbBits mask = FbBitsMask(0, len); : FbBits orig = bits & mask; : int i; : : if (width > FB_UNIT) : width = FB_UNIT; : for (i = 0; i < width / len; i++) : { : if ((bits & mask) != orig) : return FALSE; : bits = FbScrLeft(bits,len); : } : return TRUE; :} : :/* : * Check whether an entire bitmap line is a repetition of : * the first 'len' bits : */ :static Bool :fbLineRepeat (FbBits *bits, int len, int width) :{ : FbBits first = bits[0]; : : if (!fbBitsRepeat (first, len, width)) : return FALSE; : width = (width + FB_UNIT-1) >> FB_SHIFT; : bits++; : while (--width) : if (READ(bits) != first) : return FALSE; : return TRUE; :} : :/* : * The even stipple code wants the first FB_UNIT/bpp bits on : * each scanline to represent the entire stipple : */ :static Bool :fbCanEvenStipple (PixmapPtr pStipple, int bpp) :{ : int len = FB_UNIT / bpp; : FbBits *bits; : int stride; : int stip_bpp; : int stipXoff, stipYoff; : int h; : : /* can't even stipple 24bpp drawables */ : if ((bpp & (bpp-1)) != 0) : return FALSE; : /* make sure the stipple width is a multiple of the even stipple width */ : if (pStipple->drawable.width % len != 0) : return FALSE; : fbGetDrawable (&pStipple->drawable, bits, stride, stip_bpp, stipXoff, stipYoff); : h = pStipple->drawable.height; : /* check to see that the stipple repeats horizontally */ : while (h--) : { : if (!fbLineRepeat (bits, len, pStipple->drawable.width)) { : fbFinishAccess (&pStipple->drawable); : return FALSE; : } : bits += stride; : } : fbFinishAccess (&pStipple->drawable); : return TRUE; :} : :void :fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 2 0.0022 :{ /* fbValidateGC total: 34 0.0370 */ : FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); : FbBits mask; : 1 0.0011 : pGC->lastWinOrg.x = pDrawable->x; : pGC->lastWinOrg.y = pDrawable->y; : : /* : * if the client clip is different or moved OR the subwindowMode has : * changed OR the window's clip has changed since the last validation : * we need to recompute the composite clip : */ : : if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || : (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) : ) : { : miComputeCompositeClip (pGC, pDrawable); 1 0.0011 : pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1; : } : :#ifdef FB_24_32BIT : if (pPriv->bpp != pDrawable->bitsPerPixel) : { : changes |= GCStipple|GCForeground|GCBackground|GCPlaneMask; : pPriv->bpp = pDrawable->bitsPerPixel; : } : if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) : { : (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); : fbGetRotatedPixmap(pGC) = 0; : } : : if (pGC->fillStyle == FillTiled) : { : PixmapPtr pOldTile, pNewTile; : : pOldTile = pGC->tile.pixmap; : if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) : { : pNewTile = fbGetRotatedPixmap(pGC); : if (!pNewTile || pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) : { : if (pNewTile) : (*pGC->pScreen->DestroyPixmap) (pNewTile); : pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel); : } : if (pNewTile) : { : fbGetRotatedPixmap(pGC) = pOldTile; : pGC->tile.pixmap = pNewTile; : changes |= GCTile; : } : } : } :#endif : if (changes & GCTile) : { : if (!pGC->tileIsPixel && : FbEvenTile (pGC->tile.pixmap->drawable.width * : pDrawable->bitsPerPixel)) : fbPadPixmap (pGC->tile.pixmap); : } 1 0.0011 : if (changes & GCStipple) : { : pPriv->evenStipple = FALSE; : 3 0.0033 : if (pGC->stipple) { : : /* can we do an even stipple ?? */ : if (FbEvenStip (pGC->stipple->drawable.width, : pDrawable->bitsPerPixel) && : (fbCanEvenStipple (pGC->stipple, pDrawable->bitsPerPixel))) : pPriv->evenStipple = TRUE; : : if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel < FB_UNIT) : fbPadPixmap (pGC->stipple); : } : } : /* : * Recompute reduced rop values : */ 3 0.0033 : if (changes & (GCForeground|GCBackground|GCPlaneMask|GCFunction)) : { : int s; : FbBits depthMask; : 3 0.0033 : mask = FbFullMask(pDrawable->bitsPerPixel); 2 0.0022 : depthMask = FbFullMask(pDrawable->depth); : 1 0.0011 : pPriv->fg = pGC->fgPixel & mask; 1 0.0011 : pPriv->bg = pGC->bgPixel & mask; : : if ((pGC->planemask & depthMask) == depthMask) 2 0.0022 : pPriv->pm = mask; : else : pPriv->pm = pGC->planemask & mask; : 1 0.0011 : s = pDrawable->bitsPerPixel; : while (s < FB_UNIT) : { : pPriv->fg |= pPriv->fg << s; : pPriv->bg |= pPriv->bg << s; : pPriv->pm |= pPriv->pm << s; : s <<= 1; : } 7 0.0076 : pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm); 1 0.0011 : pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm); : pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm); 3 0.0033 : pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm); : } : if (changes & GCDashList) : { : unsigned short n = pGC->numInDashList; : unsigned char *dash = pGC->dash; : unsigned int dashLength = 0; : : while (n--) 1 0.0011 : dashLength += (unsigned int ) *dash++; : pPriv->dashLength = dashLength; : } 1 0.0011 :} /* * Total samples for file : "pixman-mmx.c" * * 33 0.0359 */ 33 0.0359 : /* __i686.get_pc_thunk.bx total: 15 0.0163 */ /* __divdi3 total: 18 0.0196 */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/mi/migc.c" * * 31 0.0338 */ :/* : :Copyright 1993, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included :in all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR :OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall :not be used in advertising or otherwise to promote the sale, use or :other dealings in this Software without prior written authorization :from The Open Group. : :*/ : : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "scrnintstr.h" :#include "gcstruct.h" :#include "pixmapstr.h" :#include "windowstr.h" :#include "migc.h" : :/* ARGSUSED */ :_X_EXPORT void :miChangeGC(pGC, mask) : GCPtr pGC; : unsigned long mask; 6 0.0065 :{ /* miChangeGC total: 6 0.0065 */ : return; :} : :_X_EXPORT void :miDestroyGC(pGC) : GCPtr pGC; :{ : if (pGC->pRotatedPixmap) : (*pGC->pScreen->DestroyPixmap) (pGC->pRotatedPixmap); : if (pGC->freeCompClip) : REGION_DESTROY(pGC->pScreen, pGC->pCompositeClip); : miDestroyGCOps(pGC->ops); :} : :/* : * create a private op array for a gc : */ : :_X_EXPORT GCOpsPtr :miCreateGCOps(prototype) : GCOpsPtr prototype; :{ : GCOpsPtr ret; : : /* XXX */ Must_have_memory = TRUE; : ret = (GCOpsPtr) xalloc(sizeof(GCOps)); : /* XXX */ Must_have_memory = FALSE; : if (!ret) : return 0; : *ret = *prototype; : ret->devPrivate.val = 1; : return ret; :} : :_X_EXPORT void :miDestroyGCOps(ops) : GCOpsPtr ops; :{ : if (ops->devPrivate.val) : xfree(ops); :} : : :_X_EXPORT void :miDestroyClip(pGC) : GCPtr pGC; 1 0.0011 :{ /* miDestroyClip total: 1 0.0011 */ : if (pGC->clientClipType == CT_NONE) : return; : else if (pGC->clientClipType == CT_PIXMAP) : { : (*pGC->pScreen->DestroyPixmap) ((PixmapPtr) (pGC->clientClip)); : } : else : { : /* : * we know we'll never have a list of rectangles, since ChangeClip : * immediately turns them into a region : */ : REGION_DESTROY(pGC->pScreen, pGC->clientClip); : } : pGC->clientClip = NULL; : pGC->clientClipType = CT_NONE; :} : :_X_EXPORT void :miChangeClip(pGC, type, pvalue, nrects) : GCPtr pGC; : int type; : pointer pvalue; : int nrects; 3 0.0033 :{ /* miChangeClip total: 4 0.0044 */ : (*pGC->funcs->DestroyClip) (pGC); : if (type == CT_PIXMAP) : { : /* convert the pixmap to a region */ : pGC->clientClip = (pointer) BITMAP_TO_REGION(pGC->pScreen, : (PixmapPtr) pvalue); : (*pGC->pScreen->DestroyPixmap) (pvalue); : } : else if (type == CT_REGION) : { : /* stuff the region in the GC */ : pGC->clientClip = pvalue; : } 1 0.0011 : else if (type != CT_NONE) : { : pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nrects, : (xRectangle *) pvalue, : type); : xfree(pvalue); : } : pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION : CT_NONE; : pGC->stateChanges |= GCClipMask; :} : :_X_EXPORT void :miCopyClip(pgcDst, pgcSrc) : GCPtr pgcDst, pgcSrc; :{ : RegionPtr prgnNew; : : switch (pgcSrc->clientClipType) : { : case CT_PIXMAP: : ((PixmapPtr) pgcSrc->clientClip)->refcnt++; : /* Fall through !! */ : case CT_NONE: : (*pgcDst->funcs->ChangeClip) (pgcDst, (int) pgcSrc->clientClipType, : pgcSrc->clientClip, 0); : break; : case CT_REGION: : prgnNew = REGION_CREATE(pgcSrc->pScreen, NULL, 1); : REGION_COPY(pgcDst->pScreen, prgnNew, : (RegionPtr) (pgcSrc->clientClip)); : (*pgcDst->funcs->ChangeClip) (pgcDst, CT_REGION, (pointer) prgnNew, 0); : break; : } :} : :/* ARGSUSED */ :_X_EXPORT void :miCopyGC(pGCSrc, changes, pGCDst) : GCPtr pGCSrc; : unsigned long changes; : GCPtr pGCDst; :{ : return; :} : :_X_EXPORT void :miComputeCompositeClip(pGC, pDrawable) : GCPtr pGC; : DrawablePtr pDrawable; 4 0.0044 :{ /* miComputeCompositeClip total: 20 0.0218 */ : ScreenPtr pScreen; : : /* This prevents warnings about pScreen not being used. */ : pGC->pScreen = pScreen = pGC->pScreen; : : if (pDrawable->type == DRAWABLE_WINDOW) : { : WindowPtr pWin = (WindowPtr) pDrawable; : RegionPtr pregWin; : Bool freeTmpClip, freeCompClip; : : if (pGC->subWindowMode == IncludeInferiors) : { : pregWin = NotClippedByChildren(pWin); : freeTmpClip = TRUE; : } : else : { : pregWin = &pWin->clipList; : freeTmpClip = FALSE; : } : freeCompClip = pGC->freeCompClip; : : /* : * if there is no client clip, we can get by with just keeping the : * pointer we got, and remembering whether or not should destroy (or : * maybe re-use) it later. this way, we avoid unnecessary copying of : * regions. (this wins especially if many clients clip by children : * and have no client clip.) : */ : if (pGC->clientClipType == CT_NONE) : { : if (freeCompClip) : REGION_DESTROY(pScreen, pGC->pCompositeClip); : pGC->pCompositeClip = pregWin; : pGC->freeCompClip = freeTmpClip; : } : else : { : /* : * we need one 'real' region to put into the composite clip. if : * pregWin the current composite clip are real, we can get rid of : * one. if pregWin is real and the current composite clip isn't, : * use pregWin for the composite clip. if the current composite : * clip is real and pregWin isn't, use the current composite : * clip. if neither is real, create a new region. : */ : : REGION_TRANSLATE(pScreen, pGC->clientClip, : pDrawable->x + pGC->clipOrg.x, : pDrawable->y + pGC->clipOrg.y); : : if (freeCompClip) : { : REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip, : pregWin, pGC->clientClip); : if (freeTmpClip) : REGION_DESTROY(pScreen, pregWin); : } : else if (freeTmpClip) : { : REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip); : pGC->pCompositeClip = pregWin; : } : else : { 1 0.0011 : pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0); : REGION_INTERSECT(pScreen, pGC->pCompositeClip, : pregWin, pGC->clientClip); : } : pGC->freeCompClip = TRUE; : REGION_TRANSLATE(pScreen, pGC->clientClip, : -(pDrawable->x + pGC->clipOrg.x), : -(pDrawable->y + pGC->clipOrg.y)); : } : } /* end of composite clip for a window */ : else : { : BoxRec pixbounds; : : /* XXX should we translate by drawable.x/y here ? */ : /* If you want pixmaps in offscreen memory, yes */ 3 0.0033 : pixbounds.x1 = pDrawable->x; 1 0.0011 : pixbounds.y1 = pDrawable->y; : pixbounds.x2 = pDrawable->x + pDrawable->width; : pixbounds.y2 = pDrawable->y + pDrawable->height; : 1 0.0011 : if (pGC->freeCompClip) : { 8 0.0087 : REGION_RESET(pScreen, pGC->pCompositeClip, &pixbounds); : } : else : { : pGC->freeCompClip = TRUE; : pGC->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1); : } : : if (pGC->clientClipType == CT_REGION) : { : if(pDrawable->x || pDrawable->y) { : REGION_TRANSLATE(pScreen, pGC->clientClip, : pDrawable->x + pGC->clipOrg.x, : pDrawable->y + pGC->clipOrg.y); : REGION_INTERSECT(pScreen, pGC->pCompositeClip, : pGC->pCompositeClip, pGC->clientClip); : REGION_TRANSLATE(pScreen, pGC->clientClip, : -(pDrawable->x + pGC->clipOrg.x), : -(pDrawable->y + pGC->clipOrg.y)); : } else { 1 0.0011 : REGION_TRANSLATE(pScreen, pGC->pCompositeClip, : -pGC->clipOrg.x, -pGC->clipOrg.y); : REGION_INTERSECT(pScreen, pGC->pCompositeClip, : pGC->pCompositeClip, pGC->clientClip); : REGION_TRANSLATE(pScreen, pGC->pCompositeClip, : pGC->clipOrg.x, pGC->clipOrg.y); : } : } : } /* end of composite clip for pixmap */ 1 0.0011 :} /* end miComputeCompositeClip */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/Xext/xvmain.c" * * 26 0.0283 */ :/*********************************************************** :Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, :and the Massachusetts Institute of Technology, Cambridge, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the names of Digital or MIT not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :******************************************************************/ : :/* :** File: :** :** xvmain.c --- Xv server extension main device independent module. :** :** Author: :** :** David Carver (Digital Workstation Engineering/Project Athena) :** :** Revisions: :** :** 04.09.91 Carver :** - change: stop video always generates an event even when video :** wasn't active :** :** 29.08.91 Carver :** - change: unrealizing windows no longer preempts video :** :** 11.06.91 Carver :** - changed SetPortControl to SetPortAttribute :** - changed GetPortControl to GetPortAttribute :** - changed QueryBestSize :** :** 28.05.91 Carver :** - fixed Put and Get requests to not preempt operations to same drawable :** :** 15.05.91 Carver :** - version 2.0 upgrade :** :** 19.03.91 Carver :** - fixed Put and Get requests to honor grabbed ports. :** - fixed Video requests to update di structure with new drawable, and :** client after calling ddx. :** :** 24.01.91 Carver :** - version 1.4 upgrade :** :** Notes: :** :** Port structures reference client structures in a two different :** ways: when grabs, or video is active. Each reference is encoded :** as fake client resources and thus when the client is goes away so :** does the reference (it is zeroed). No other action is taken, so :** video doesn't necessarily stop. It probably will as a result of :** other resources going away, but if a client starts video using :** none of its own resources, then the video will continue to play :** after the client disappears. :** :** :*/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include : :#include :#include :#include "misc.h" :#include "os.h" :#include "scrnintstr.h" :#include "windowstr.h" :#include "pixmapstr.h" :#include "gc.h" :#include "extnsionst.h" :#include "dixstruct.h" :#include "resource.h" :#include "opaque.h" :#include "input.h" : :#define GLOBAL : :#include :#include :#include "xvdix.h" : :#ifdef PANORAMIX :#include "panoramiX.h" :#include "panoramiXsrv.h" :#include "xvdisp.h" :#endif : :int XvScreenIndex = -1; :unsigned long XvExtensionGeneration = 0; :unsigned long XvScreenGeneration = 0; :unsigned long XvResourceGeneration = 0; : :int XvReqCode; :int XvEventBase; :int XvErrorBase; : :unsigned long XvRTPort; :unsigned long XvRTEncoding; :unsigned long XvRTGrab; :unsigned long XvRTVideoNotify; :unsigned long XvRTVideoNotifyList; :unsigned long XvRTPortNotify; : : : :/* EXTERNAL */ : :extern XID clientErrorValue; : :static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *); :static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *); :static Bool CreateResourceTypes(void); : :static Bool XvCloseScreen(int, ScreenPtr); :static Bool XvDestroyPixmap(PixmapPtr); :static Bool XvDestroyWindow(WindowPtr); :static void XvResetProc(ExtensionEntry*); :static int XvdiDestroyGrab(pointer, XID); :static int XvdiDestroyEncoding(pointer, XID); :static int XvdiDestroyVideoNotify(pointer, XID); :static int XvdiDestroyPortNotify(pointer, XID); :static int XvdiDestroyVideoNotifyList(pointer, XID); :static int XvdiDestroyPort(pointer, XID); :static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int); : : : : :/* :** XvExtensionInit :** :** :*/ : :void :XvExtensionInit(void) :{ : ExtensionEntry *extEntry; : : /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN : INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */ : if (XvScreenGeneration != serverGeneration) : { : if (!CreateResourceTypes()) : { : ErrorF("XvExtensionInit: Unable to allocate resource types\n"); : return; : } : XvScreenIndex = AllocateScreenPrivateIndex (); : if (XvScreenIndex < 0) : { : ErrorF("XvExtensionInit: Unable to allocate screen private index\n"); : return; : } :#ifdef PANORAMIX : XineramaRegisterConnectionBlockCallback(XineramifyXv); :#endif : XvScreenGeneration = serverGeneration; : } : : if (XvExtensionGeneration != serverGeneration) : { : XvExtensionGeneration = serverGeneration; : : extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors, : ProcXvDispatch, SProcXvDispatch, : XvResetProc, StandardMinorOpcode); : if (!extEntry) : { : FatalError("XvExtensionInit: AddExtensions failed\n"); : } : : XvReqCode = extEntry->base; : XvEventBase = extEntry->eventBase; : XvErrorBase = extEntry->errorBase; : : EventSwapVector[XvEventBase+XvVideoNotify] = : (EventSwapPtr)WriteSwappedVideoNotifyEvent; : EventSwapVector[XvEventBase+XvPortNotify] = : (EventSwapPtr)WriteSwappedPortNotifyEvent; : : (void)MakeAtom(XvName, strlen(XvName), xTrue); : : } :} : :static Bool :CreateResourceTypes(void) : :{ : : if (XvResourceGeneration == serverGeneration) return TRUE; : : XvResourceGeneration = serverGeneration; : : if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort))) : { : ErrorF("CreateResourceTypes: failed to allocate port resource.\n"); : return FALSE; : } : : if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab))) : { : ErrorF("CreateResourceTypes: failed to allocate grab resource.\n"); : return FALSE; : } : : if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding))) : { : ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n"); : return FALSE; : } : : if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify))) : { : ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n"); : return FALSE; : } : : if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList))) : { : ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n"); : return FALSE; : } : : if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify))) : { : ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n"); : return FALSE; : } : : return TRUE; : :} : :_X_EXPORT int :XvScreenInit(ScreenPtr pScreen) :{ : XvScreenPtr pxvs; : : if (XvScreenGeneration != serverGeneration) : { : if (!CreateResourceTypes()) : { : ErrorF("XvScreenInit: Unable to allocate resource types\n"); : return BadAlloc; : } : XvScreenIndex = AllocateScreenPrivateIndex (); : if (XvScreenIndex < 0) : { : ErrorF("XvScreenInit: Unable to allocate screen private index\n"); : return BadAlloc; : } :#ifdef PANORAMIX : XineramaRegisterConnectionBlockCallback(XineramifyXv); :#endif : XvScreenGeneration = serverGeneration; : } : : if (pScreen->devPrivates[XvScreenIndex].ptr) : { : ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n"); : } : : /* ALLOCATE SCREEN PRIVATE RECORD */ : : pxvs = (XvScreenPtr) xalloc (sizeof (XvScreenRec)); : if (!pxvs) : { : ErrorF("XvScreenInit: Unable to allocate screen private structure\n"); : return BadAlloc; : } : : pScreen->devPrivates[XvScreenIndex].ptr = (pointer)pxvs; : : : pxvs->DestroyPixmap = pScreen->DestroyPixmap; : pxvs->DestroyWindow = pScreen->DestroyWindow; : pxvs->CloseScreen = pScreen->CloseScreen; : : pScreen->DestroyPixmap = XvDestroyPixmap; : pScreen->DestroyWindow = XvDestroyWindow; : pScreen->CloseScreen = XvCloseScreen; : : return Success; :} : :static Bool :XvCloseScreen( : int ii, : ScreenPtr pScreen :){ : : XvScreenPtr pxvs; : : pxvs = (XvScreenPtr) pScreen->devPrivates[XvScreenIndex].ptr; : : pScreen->DestroyPixmap = pxvs->DestroyPixmap; : pScreen->DestroyWindow = pxvs->DestroyWindow; : pScreen->CloseScreen = pxvs->CloseScreen; : : (* pxvs->ddCloseScreen)(ii, pScreen); : : xfree(pxvs); : : pScreen->devPrivates[XvScreenIndex].ptr = (pointer)NULL; : : return (*pScreen->CloseScreen)(ii, pScreen); : :} : :static void :XvResetProc(ExtensionEntry* extEntry) :{ :} : :_X_EXPORT int :XvGetScreenIndex(void) :{ : return XvScreenIndex; :} : :_X_EXPORT unsigned long :XvGetRTPort(void) :{ : return XvRTPort; :} : :static Bool :XvDestroyPixmap(PixmapPtr pPix) 4 0.0044 :{ /* XvDestroyPixmap total: 26 0.0283 */ : Bool status; : ScreenPtr pScreen; : XvScreenPtr pxvs; : XvAdaptorPtr pa; : int na; : XvPortPtr pp; : int np; : 2 0.0022 : pScreen = pPix->drawable.pScreen; : 1 0.0011 : SCREEN_PROLOGUE(pScreen, DestroyPixmap); : : pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; : : /* CHECK TO SEE IF THIS PORT IS IN USE */ : : pa = pxvs->pAdaptors; 1 0.0011 : na = pxvs->nAdaptors; 1 0.0011 : while (na--) : { 1 0.0011 : np = pa->nPorts; 1 0.0011 : pp = pa->pPorts; : 3 0.0033 : while (np--) : { 2 0.0022 : if (pp->pDraw == (DrawablePtr)pPix) : { : XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); : : (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, : pp->pDraw); : : pp->pDraw = (DrawablePtr)NULL; : pp->client = (ClientPtr)NULL; 4 0.0044 : pp->time = currentTime; : } 4 0.0044 : pp++; : } : pa++; : } : : status = (* pScreen->DestroyPixmap)(pPix); : 1 0.0011 : SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap); : : return status; : 1 0.0011 :} : :static Bool :XvDestroyWindow(WindowPtr pWin) :{ : Bool status; : ScreenPtr pScreen; : XvScreenPtr pxvs; : XvAdaptorPtr pa; : int na; : XvPortPtr pp; : int np; : : pScreen = pWin->drawable.pScreen; : : SCREEN_PROLOGUE(pScreen, DestroyWindow); : : pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; : : /* CHECK TO SEE IF THIS PORT IS IN USE */ : : pa = pxvs->pAdaptors; : na = pxvs->nAdaptors; : while (na--) : { : np = pa->nPorts; : pp = pa->pPorts; : : while (np--) : { : if (pp->pDraw == (DrawablePtr)pWin) : { : XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); : : (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, : pp->pDraw); : : pp->pDraw = (DrawablePtr)NULL; : pp->client = (ClientPtr)NULL; : pp->time = currentTime; : } : pp++; : } : pa++; : } : : : status = (* pScreen->DestroyWindow)(pWin); : : SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow); : : return status; : :} : :/* The XvdiVideoStopped procedure is a hook for the device dependent layer. : It provides a way for the dd layer to inform the di layer that video has : stopped in a port for reasons that the di layer had no control over; note : that it doesn't call back into the dd layer */ : :int :XvdiVideoStopped(XvPortPtr pPort, int reason) :{ : : /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ : : if (!pPort->pDraw) return Success; : : XvdiSendVideoNotify(pPort, pPort->pDraw, reason); : : pPort->pDraw = (DrawablePtr)NULL; : pPort->client = (ClientPtr)NULL; : pPort->time = currentTime; : : return Success; : :} : :static int :XvdiDestroyPort(pointer pPort, XID id) :{ : return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort); :} : :static int :XvdiDestroyGrab(pointer pGrab, XID id) :{ : ((XvGrabPtr)pGrab)->client = (ClientPtr)NULL; : return Success; :} : :static int :XvdiDestroyVideoNotify(pointer pn, XID id) :{ : /* JUST CLEAR OUT THE client POINTER FIELD */ : : ((XvVideoNotifyPtr)pn)->client = (ClientPtr)NULL; : return Success; :} : :static int :XvdiDestroyPortNotify(pointer pn, XID id) :{ : /* JUST CLEAR OUT THE client POINTER FIELD */ : : ((XvPortNotifyPtr)pn)->client = (ClientPtr)NULL; : return Success; :} : :static int :XvdiDestroyVideoNotifyList(pointer pn, XID id) :{ : XvVideoNotifyPtr npn,cpn; : : /* ACTUALLY DESTROY THE NOTITY LIST */ : : cpn = (XvVideoNotifyPtr)pn; : : while (cpn) : { : npn = cpn->next; : if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify); : xfree(cpn); : cpn = npn; : } : return Success; :} : :static int :XvdiDestroyEncoding(pointer value, XID id) :{ : return Success; :} : :static int :XvdiSendVideoNotify(pPort, pDraw, reason) : :XvPortPtr pPort; :DrawablePtr pDraw; :int reason; : :{ : xvEvent event; : XvVideoNotifyPtr pn; : : pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList); : : while (pn) : { : if (pn->client) : { : event.u.u.type = XvEventBase + XvVideoNotify; : event.u.u.sequenceNumber = pn->client->sequence; : event.u.videoNotify.time = currentTime.milliseconds; : event.u.videoNotify.drawable = pDraw->id; : event.u.videoNotify.port = pPort->id; : event.u.videoNotify.reason = reason; : (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask, : NoEventMask, NullGrab); : } : pn = pn->next; : } : : return Success; : :} : : :int :XvdiSendPortNotify( : XvPortPtr pPort, : Atom attribute, : INT32 value :){ : xvEvent event; : XvPortNotifyPtr pn; : : pn = pPort->pNotify; : : while (pn) : { : if (pn->client) : { : event.u.u.type = XvEventBase + XvPortNotify; : event.u.u.sequenceNumber = pn->client->sequence; : event.u.portNotify.time = currentTime.milliseconds; : event.u.portNotify.port = pPort->id; : event.u.portNotify.attribute = attribute; : event.u.portNotify.value = value; : (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask, : NoEventMask, NullGrab); : } : pn = pn->next; : } : : return Success; : :} : : :#define CHECK_SIZE(dw, dh, sw, sh) { \ : if(!dw || !dh || !sw || !sh) return Success; \ : /* The region code will break these if they are too large */ \ : if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \ : return BadValue; \ :} : : :int :XvdiPutVideo( : ClientPtr client, : DrawablePtr pDraw, : XvPortPtr pPort, : GCPtr pGC, : INT16 vid_x, INT16 vid_y, : CARD16 vid_w, CARD16 vid_h, : INT16 drw_x, INT16 drw_y, : CARD16 drw_w, CARD16 drw_h :){ : DrawablePtr pOldDraw; : : CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); : : /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ : : UpdateCurrentTime(); : : /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN : INFORM CLIENT OF ITS FAILURE */ : : if (pPort->grab.client && (pPort->grab.client != client)) : { : XvdiSendVideoNotify(pPort, pDraw, XvBusy); : return Success; : } : : /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED : EVENTS TO ANY CLIENTS WHO WANT THEM */ : : pOldDraw = pPort->pDraw; : if ((pOldDraw) && (pOldDraw != pDraw)) : { : XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); : } : : (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC, : vid_x, vid_y, vid_w, vid_h, : drw_x, drw_y, drw_w, drw_h); : : if ((pPort->pDraw) && (pOldDraw != pDraw)) : { : pPort->client = client; : XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); : } : : pPort->time = currentTime; : : return (Success); : :} : :int :XvdiPutStill( : ClientPtr client, : DrawablePtr pDraw, : XvPortPtr pPort, : GCPtr pGC, : INT16 vid_x, INT16 vid_y, : CARD16 vid_w, CARD16 vid_h, : INT16 drw_x, INT16 drw_y, : CARD16 drw_w, CARD16 drw_h :){ : int status; : : CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); : : /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ : : UpdateCurrentTime(); : : /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN : INFORM CLIENT OF ITS FAILURE */ : : if (pPort->grab.client && (pPort->grab.client != client)) : { : XvdiSendVideoNotify(pPort, pDraw, XvBusy); : return Success; : } : : pPort->time = currentTime; : : status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC, : vid_x, vid_y, vid_w, vid_h, : drw_x, drw_y, drw_w, drw_h); : : return status; : :} : :int :XvdiPutImage( : ClientPtr client, : DrawablePtr pDraw, : XvPortPtr pPort, : GCPtr pGC, : INT16 src_x, INT16 src_y, : CARD16 src_w, CARD16 src_h, : INT16 drw_x, INT16 drw_y, : CARD16 drw_w, CARD16 drw_h, : XvImagePtr image, : unsigned char* data, : Bool sync, : CARD16 width, CARD16 height :){ : CHECK_SIZE(drw_w, drw_h, src_w, src_h); : : /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ : : UpdateCurrentTime(); : : /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN : INFORM CLIENT OF ITS FAILURE */ : : if (pPort->grab.client && (pPort->grab.client != client)) : { : XvdiSendVideoNotify(pPort, pDraw, XvBusy); : return Success; : } : : pPort->time = currentTime; : : return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC, : src_x, src_y, src_w, src_h, : drw_x, drw_y, drw_w, drw_h, : image, data, sync, width, height); :} : : :int :XvdiGetVideo( : ClientPtr client, : DrawablePtr pDraw, : XvPortPtr pPort, : GCPtr pGC, : INT16 vid_x, INT16 vid_y, : CARD16 vid_w, CARD16 vid_h, : INT16 drw_x, INT16 drw_y, : CARD16 drw_w, CARD16 drw_h :){ : DrawablePtr pOldDraw; : : CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); : : /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ : : UpdateCurrentTime(); : : /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN : INFORM CLIENT OF ITS FAILURE */ : : if (pPort->grab.client && (pPort->grab.client != client)) : { : XvdiSendVideoNotify(pPort, pDraw, XvBusy); : return Success; : } : : /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED : EVENTS TO ANY CLIENTS WHO WANT THEM */ : : pOldDraw = pPort->pDraw; : if ((pOldDraw) && (pOldDraw != pDraw)) : { : XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); : } : : (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC, : vid_x, vid_y, vid_w, vid_h, : drw_x, drw_y, drw_w, drw_h); : : if ((pPort->pDraw) && (pOldDraw != pDraw)) : { : pPort->client = client; : XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); : } : : pPort->time = currentTime; : : return (Success); : :} : :int :XvdiGetStill( : ClientPtr client, : DrawablePtr pDraw, : XvPortPtr pPort, : GCPtr pGC, : INT16 vid_x, INT16 vid_y, : CARD16 vid_w, CARD16 vid_h, : INT16 drw_x, INT16 drw_y, : CARD16 drw_w, CARD16 drw_h :){ : int status; : : CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); : : /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ : : UpdateCurrentTime(); : : /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN : INFORM CLIENT OF ITS FAILURE */ : : if (pPort->grab.client && (pPort->grab.client != client)) : { : XvdiSendVideoNotify(pPort, pDraw, XvBusy); : return Success; : } : : status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC, : vid_x, vid_y, vid_w, vid_h, : drw_x, drw_y, drw_w, drw_h); : : pPort->time = currentTime; : : return status; : :} : :int :XvdiGrabPort( : ClientPtr client, : XvPortPtr pPort, : Time ctime, : int *p_result :){ : unsigned long id; : TimeStamp time; : : UpdateCurrentTime(); : time = ClientTimeToServerTime(ctime); : : if (pPort->grab.client && (client != pPort->grab.client)) : { : *p_result = XvAlreadyGrabbed; : return Success; : } : : if ((CompareTimeStamps(time, currentTime) == LATER) || : (CompareTimeStamps(time, pPort->time) == EARLIER)) : { : *p_result = XvInvalidTime; : return Success; : } : : if (client == pPort->grab.client) : { : *p_result = Success; : return Success; : } : : id = FakeClientID(client->index); : : if (!AddResource(id, XvRTGrab, &pPort->grab)) : { : return BadAlloc; : } : : /* IF THERE IS ACTIVE VIDEO THEN STOP IT */ : : if ((pPort->pDraw) && (client != pPort->client)) : { : XVCALL(diStopVideo)((ClientPtr)NULL, pPort, pPort->pDraw); : } : : pPort->grab.client = client; : pPort->grab.id = id; : : pPort->time = currentTime; : : *p_result = Success; : : return Success; : :} : :int :XvdiUngrabPort( : ClientPtr client, : XvPortPtr pPort, : Time ctime :){ : TimeStamp time; : : UpdateCurrentTime(); : time = ClientTimeToServerTime(ctime); : : if ((!pPort->grab.client) || (client != pPort->grab.client)) : { : return Success; : } : : if ((CompareTimeStamps(time, currentTime) == LATER) || : (CompareTimeStamps(time, pPort->time) == EARLIER)) : { : return Success; : } : : /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */ : : FreeResource(pPort->grab.id, XvRTGrab); : pPort->grab.client = (ClientPtr)NULL; : : pPort->time = currentTime; : : return Success; : :} : : :int :XvdiSelectVideoNotify( : ClientPtr client, : DrawablePtr pDraw, : BOOL onoff :){ : XvVideoNotifyPtr pn,tpn,fpn; : : /* FIND VideoNotify LIST */ : : pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList); : : /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */ : : if (!onoff && !pn) return Success; : : /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST : WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */ : : if (!pn) : { : if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec)))) : return BadAlloc; : tpn->next = (XvVideoNotifyPtr)NULL; : if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn)) : { : xfree(tpn); : return BadAlloc; : } : } : else : { : /* LOOK TO SEE IF ENTRY ALREADY EXISTS */ : : fpn = (XvVideoNotifyPtr)NULL; : tpn = pn; : while (tpn) : { : if (tpn->client == client) : { : if (!onoff) tpn->client = (ClientPtr)NULL; : return Success; : } : if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */ : tpn = tpn->next; : } : : /* IF TUNNING OFF, THEN JUST RETURN */ : : if (!onoff) return Success; : : /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */ : : if (fpn) : { : tpn = fpn; : } : else : { : if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec)))) : return BadAlloc; : tpn->next = pn->next; : pn->next = tpn; : } : } : : /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */ : /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */ : : tpn->client = (ClientPtr)NULL; : tpn->id = FakeClientID(client->index); : AddResource(tpn->id, XvRTVideoNotify, tpn); : : tpn->client = client; : return Success; : :} : :int :XvdiSelectPortNotify( : ClientPtr client, : XvPortPtr pPort, : BOOL onoff :){ : XvPortNotifyPtr pn,tpn; : : /* SEE IF CLIENT IS ALREADY IN LIST */ : : tpn = (XvPortNotifyPtr)NULL; : pn = pPort->pNotify; : while (pn) : { : if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */ : if (pn->client == client) break; : pn = pn->next; : } : : /* IS THE CLIENT ALREADY ON THE LIST? */ : : if (pn) : { : /* REMOVE IT? */ : : if (!onoff) : { : pn->client = (ClientPtr)NULL; : FreeResource(pn->id, XvRTPortNotify); : } : : return Success; : } : : /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE : CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */ : : if (!tpn) : { : if (!(tpn = (XvPortNotifyPtr)xalloc(sizeof(XvPortNotifyRec)))) : return BadAlloc; : tpn->next = pPort->pNotify; : pPort->pNotify = tpn; : } : : tpn->client = client; : tpn->id = FakeClientID(client->index); : AddResource(tpn->id, XvRTPortNotify, tpn); : : return Success; : :} : :int :XvdiStopVideo( : ClientPtr client, : XvPortPtr pPort, : DrawablePtr pDraw :){ : int status; : : /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ : : if (!pPort->pDraw || (pPort->pDraw != pDraw)) : { : XvdiSendVideoNotify(pPort, pDraw, XvStopped); : return Success; : } : : /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN : INFORM CLIENT OF ITS FAILURE */ : : if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) : { : XvdiSendVideoNotify(pPort, pDraw, XvBusy); : return Success; : } : : XvdiSendVideoNotify(pPort, pDraw, XvStopped); : : status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw); : : pPort->pDraw = (DrawablePtr)NULL; : pPort->client = (ClientPtr)client; : pPort->time = currentTime; : : return status; : :} : :int :XvdiPreemptVideo( : ClientPtr client, : XvPortPtr pPort, : DrawablePtr pDraw :){ : int status; : : /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ : : if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success; : : XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); : : status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw); : : pPort->pDraw = (DrawablePtr)NULL; : pPort->client = (ClientPtr)client; : pPort->time = currentTime; : : return status; : :} : :int :XvdiMatchPort( : XvPortPtr pPort, : DrawablePtr pDraw :){ : : XvAdaptorPtr pa; : XvFormatPtr pf; : int nf; : : pa = pPort->pAdaptor; : : if (pa->pScreen != pDraw->pScreen) return BadMatch; : : nf = pa->nFormats; : pf = pa->pFormats; : : while (nf--) : { : if ((pf->depth == pDraw->depth) :#if 0 : && ((pDraw->type == DRAWABLE_PIXMAP) || : (wVisual(((WindowPtr)pDraw)) == pf->visual)) :#endif : ) : return Success; : pf++; : } : : return BadMatch; : :} : :int :XvdiSetPortAttribute( : ClientPtr client, : XvPortPtr pPort, : Atom attribute, : INT32 value :){ : : XvdiSendPortNotify(pPort, attribute, value); : : return : (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value); : :} : :int :XvdiGetPortAttribute( : ClientPtr client, : XvPortPtr pPort, : Atom attribute, : INT32 *p_value :){ : : return : (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value); : :} : :static void :WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to) : :{ : : to->u.u.type = from->u.u.type; : to->u.u.detail = from->u.u.detail; : cpswaps(from->u.videoNotify.sequenceNumber, : to->u.videoNotify.sequenceNumber); : cpswapl(from->u.videoNotify.time, to->u.videoNotify.time); : cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable); : cpswapl(from->u.videoNotify.port, to->u.videoNotify.port); : :} : :static void :WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to) : :{ : : to->u.u.type = from->u.u.type; : to->u.u.detail = from->u.u.detail; : cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber); : cpswapl(from->u.portNotify.time, to->u.portNotify.time); : cpswapl(from->u.portNotify.port, to->u.portNotify.port); : cpswapl(from->u.portNotify.value, to->u.portNotify.value); : :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/render/mirect.c" * * 24 0.0261 */ :/* : * : * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "scrnintstr.h" :#include "gcstruct.h" :#include "pixmapstr.h" :#include "windowstr.h" :#include "mi.h" :#include "picturestr.h" :#include "mipict.h" : :static void :miColorRects (PicturePtr pDst, : PicturePtr pClipPict, : xRenderColor *color, : int nRect, : xRectangle *rects, : int xoff, : int yoff) 1 0.0011 :{ /* miColorRects total: 15 0.0163 */ : ScreenPtr pScreen = pDst->pDrawable->pScreen; : CARD32 pixel; : GCPtr pGC; : CARD32 tmpval[5]; : RegionPtr pClip; : unsigned long mask; : 1 0.0011 : miRenderColorToPixel (pDst->pFormat, color, &pixel); : : pGC = GetScratchGC (pDst->pDrawable->depth, pScreen); : if (!pGC) : return; : tmpval[0] = GXcopy; : tmpval[1] = pixel; 1 0.0011 : tmpval[2] = pDst->subWindowMode; : mask = GCFunction | GCForeground | GCSubwindowMode; 4 0.0044 : if (pClipPict->clientClipType == CT_REGION) : { 1 0.0011 : tmpval[3] = pDst->clipOrigin.x - xoff; : tmpval[4] = pDst->clipOrigin.y - yoff; : mask |= GCClipXOrigin|GCClipYOrigin; : : pClip = REGION_CREATE (pScreen, NULL, 1); : REGION_COPY (pScreen, pClip, : (RegionPtr) pClipPict->clientClip); : (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0); : } : 1 0.0011 : ChangeGC (pGC, mask, tmpval); 2 0.0022 : ValidateGC (pDst->pDrawable, pGC); 1 0.0011 : if (xoff || yoff) : { : int i; : for (i = 0; i < nRect; i++) : { : rects[i].x -= xoff; : rects[i].y -= yoff; : } : } 3 0.0033 : (*pGC->ops->PolyFillRect) (pDst->pDrawable, pGC, nRect, rects); : if (xoff || yoff) : { : int i; : for (i = 0; i < nRect; i++) : { : rects[i].x += xoff; : rects[i].y += yoff; : } : } : FreeScratchGC (pGC); :} : :_X_EXPORT void :miCompositeRects (CARD8 op, : PicturePtr pDst, : xRenderColor *color, : int nRect, : xRectangle *rects) 3 0.0033 :{ /* miCompositeRects total: 9 0.0098 */ : ScreenPtr pScreen = pDst->pDrawable->pScreen; : : if (color->alpha == 0xffff) : { 2 0.0022 : if (op == PictOpOver) : op = PictOpSrc; : } 1 0.0011 : if (op == PictOpClear) : color->red = color->green = color->blue = color->alpha = 0; : 1 0.0011 : if (op == PictOpSrc || op == PictOpClear) : { : miColorRects (pDst, pDst, color, nRect, rects, 0, 0); 1 0.0011 : if (pDst->alphaMap) : miColorRects (pDst->alphaMap, pDst, : color, nRect, rects, : pDst->alphaOrigin.x, : pDst->alphaOrigin.y); : } : else : { : PictFormatPtr rgbaFormat; : PixmapPtr pPixmap; : PicturePtr pSrc; : xRectangle one; : int error; : Pixel pixel; : GCPtr pGC; : CARD32 tmpval[2]; : : rgbaFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); : if (!rgbaFormat) : goto bail1; : : pPixmap = (*pScreen->CreatePixmap) (pScreen, 1, 1, : rgbaFormat->depth); : if (!pPixmap) : goto bail2; : : miRenderColorToPixel (rgbaFormat, color, &pixel); : : pGC = GetScratchGC (rgbaFormat->depth, pScreen); : if (!pGC) : goto bail3; : tmpval[0] = GXcopy; : tmpval[1] = pixel; : : ChangeGC (pGC, GCFunction | GCForeground, tmpval); : ValidateGC (&pPixmap->drawable, pGC); : one.x = 0; : one.y = 0; : one.width = 1; : one.height = 1; : (*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &one); : : tmpval[0] = xTrue; : pSrc = CreatePicture (0, &pPixmap->drawable, rgbaFormat, : CPRepeat, tmpval, 0, &error); : : if (!pSrc) : goto bail4; : : while (nRect--) : { : CompositePicture (op, pSrc, 0, pDst, 0, 0, 0, 0, : rects->x, : rects->y, : rects->width, : rects->height); : rects++; : } : : FreePicture ((pointer) pSrc, 0); :bail4: : FreeScratchGC (pGC); :bail3: : (*pScreen->DestroyPixmap) (pPixmap); :bail2: :bail1: : ; : } 1 0.0011 :} /* * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-utils.c" * * 24 0.0261 */ :/* : * Copyright © 2000 SuSE, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of SuSE not be used in advertising or : * publicity pertaining to distribution of the software without specific, : * written prior permission. SuSE makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : * : * Author: Keith Packard, SuSE, Inc. : */ : :#include :#include "pixman.h" :#include "pixman-private.h" :#include "pixman-mmx.h" : :pixman_bool_t :pixman_transform_point_3d (pixman_transform_t *transform, : pixman_vector_t *vector) :{ : pixman_vector_t result; : int i, j; : pixman_fixed_32_32_t partial; : pixman_fixed_48_16_t v; : : for (j = 0; j < 3; j++) : { : v = 0; : for (i = 0; i < 3; i++) : { : partial = ((pixman_fixed_48_16_t) transform->matrix[j][i] * : (pixman_fixed_48_16_t) vector->vector[i]); : v += partial >> 16; : } : : if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16) : return FALSE; : : result.vector[j] = (pixman_fixed_48_16_t) v; : } : : if (!result.vector[2]) : return FALSE; : : *vector = result; : return TRUE; :} : :pixman_bool_t :pixman_blt (uint32_t *src_bits, : uint32_t *dst_bits, : int src_stride, : int dst_stride, : int src_bpp, : int dst_bpp, : int src_x, int src_y, : int dst_x, int dst_y, : int width, int height) :{ :#ifdef USE_MMX : if (pixman_have_mmx()) : { : return pixman_blt_mmx (src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, : src_x, src_y, dst_x, dst_y, width, height); : } : else :#endif : return FALSE; :} : :static void :pixman_fill8 (uint32_t *bits, : int stride, : int x, : int y, : int width, : int height, : uint32_t xor) :{ : int byte_stride = stride * sizeof (uint32_t); : uint8_t *dst = (uint8_t *) bits; : uint8_t v = xor & 0xff; : int i; : : dst = dst + y * byte_stride + x; : : while (height--) : { : for (i = 0; i < width; ++i) : dst[i] = v; : : dst += byte_stride; : } :} : :static void :pixman_fill16 (uint32_t *bits, : int stride, : int x, : int y, : int width, : int height, : uint32_t xor) :{ : int short_stride = (stride * sizeof (uint32_t)) / sizeof (uint16_t); : uint16_t *dst = (uint16_t *)bits; : uint16_t v = xor & 0xffff; : int i; : : dst = dst + y * short_stride + x; : : while (height--) : { : for (i = 0; i < width; ++i) : dst[i] = v; : : dst += short_stride; : } :} : :static void :pixman_fill32 (uint32_t *bits, : int stride, : int x, : int y, : int width, : int height, : uint32_t xor) :{ : int i; : : bits = bits + y * stride + x; : : while (height--) : { : for (i = 0; i < width; ++i) : bits[i] = xor; : : bits += stride; : } :} : :pixman_bool_t :pixman_fill (uint32_t *bits, : int stride, : int bpp, : int x, : int y, : int width, : int height, : uint32_t xor) :{ :#if 0 : printf ("filling: %d %d %d %d (stride: %d, bpp: %d) pixel: %x\n", : x, y, width, height, stride, bpp, xor); :#endif : :#ifdef USE_MMX : if (!pixman_have_mmx() || !pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor)) :#endif : { : switch (bpp) : { : case 8: : pixman_fill8 (bits, stride, x, y, width, height, xor); : break; : : case 16: : pixman_fill16 (bits, stride, x, y, width, height, xor); : break; : : case 32: : pixman_fill32 (bits, stride, x, y, width, height, xor); : break; : : default: : return FALSE; : break; : } : } : : return TRUE; :} : : :/* : * Compute the smallest value no less than y which is on a : * grid row : */ : :pixman_fixed_t :pixman_sample_ceil_y (pixman_fixed_t y, int n) :{ /* pixman_sample_ceil_y total: 1 0.0011 */ : pixman_fixed_t f = pixman_fixed_frac(y); : pixman_fixed_t i = pixman_fixed_floor(y); : 1 0.0011 : f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n); : if (f > Y_FRAC_LAST(n)) : { : f = Y_FRAC_FIRST(n); : i += pixman_fixed_1; : } : return (i | f); :} : :#define _div(a,b) ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b))) : :/* : * Compute the largest value no greater than y which is on a : * grid row : */ :pixman_fixed_t :pixman_sample_floor_y (pixman_fixed_t y, int n) :{ /* pixman_sample_floor_y total: 5 0.0054 */ : pixman_fixed_t f = pixman_fixed_frac(y); 1 0.0011 : pixman_fixed_t i = pixman_fixed_floor (y); : 4 0.0044 : f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n); : if (f < Y_FRAC_FIRST(n)) : { : f = Y_FRAC_LAST(n); : i -= pixman_fixed_1; : } : return (i | f); :} : :/* : * Step an edge by any amount (including negative values) : */ :void :pixman_edge_step (pixman_edge_t *e, int n) :{ /* pixman_edge_step total: 3 0.0033 */ : pixman_fixed_48_16_t ne; : : e->x += n * e->stepx; : : ne = e->e + n * (pixman_fixed_48_16_t) e->dx; : : if (n >= 0) : { 1 0.0011 : if (ne > 0) : { 2 0.0022 : int nx = (ne + e->dy - 1) / e->dy; : e->e = ne - nx * (pixman_fixed_48_16_t) e->dy; : e->x += nx * e->signdx; : } : } : else : { : if (ne <= -e->dy) : { : int nx = (-ne) / e->dy; : e->e = ne + nx * (pixman_fixed_48_16_t) e->dy; : e->x -= nx * e->signdx; : } : } :} : :/* : * A private routine to initialize the multi-step : * elements of an edge structure : */ :static void :_pixman_edge_tMultiInit (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p) 2 0.0022 :{ /* _pixman_edge_tMultiInit total: 7 0.0076 */ : pixman_fixed_t stepx; : pixman_fixed_48_16_t ne; : 2 0.0022 : ne = n * (pixman_fixed_48_16_t) e->dx; : stepx = n * e->stepx; : if (ne > 0) : { 1 0.0011 : int nx = ne / e->dy; : ne -= nx * e->dy; 1 0.0011 : stepx += nx * e->signdx; : } 1 0.0011 : *dx_p = ne; : *stepx_p = stepx; :} : :/* : * Initialize one edge structure given the line endpoints and a : * starting y value : */ :void :pixman_edge_init (pixman_edge_t *e, : int n, : pixman_fixed_t y_start, : pixman_fixed_t x_top, : pixman_fixed_t y_top, : pixman_fixed_t x_bot, : pixman_fixed_t y_bot) 2 0.0022 :{ /* pixman_edge_init total: 7 0.0076 */ : pixman_fixed_t dx, dy; : : e->x = x_top; : e->e = 0; : dx = x_bot - x_top; : dy = y_bot - y_top; : e->dy = dy; : e->dx = 0; : if (dy) : { : if (dx >= 0) : { : e->signdx = 1; : e->stepx = dx / dy; : e->dx = dx % dy; : e->e = -dy; : } : else : { 1 0.0011 : e->signdx = -1; : e->stepx = -(-dx / dy); : e->dx = -dx % dy; : e->e = 0; : } : 3 0.0033 : _pixman_edge_tMultiInit (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small); : _pixman_edge_tMultiInit (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big); : } 1 0.0011 : pixman_edge_step (e, y_start - y_top); :} : :/* : * Initialize one edge structure given a line, starting y value : * and a pixel offset for the line : */ :void :pixman_line_fixed_edge_init (pixman_edge_t *e, : int n, : pixman_fixed_t y, : const pixman_line_fixed_t *line, : int x_off, : int y_off) 1 0.0011 :{ /* pixman_line_fixed_edge_init total: 1 0.0011 */ : pixman_fixed_t x_off_fixed = pixman_int_to_fixed(x_off); : pixman_fixed_t y_off_fixed = pixman_int_to_fixed(y_off); : const pixman_point_fixed_t *top, *bot; : : if (line->p1.y <= line->p2.y) : { : top = &line->p1; : bot = &line->p2; : } : else : { : top = &line->p2; : bot = &line->p1; : } : pixman_edge_init (e, n, y, : top->x + x_off_fixed, : top->y + y_off_fixed, : bot->x + x_off_fixed, : bot->y + y_off_fixed); :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/os/utils.c" * * 21 0.0229 */ :/* : :Copyright 1987, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included :in all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR :OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall :not be used in advertising or otherwise to promote the sale, use or :other dealings in this Software without prior written authorization :from The Open Group. : : :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, :Copyright 1994 Quarterdeck Office Systems. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the names of Digital and :Quarterdeck not be used in advertising or publicity pertaining to :distribution of the software without specific, written prior :permission. : :DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS :SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND :FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT :OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS :OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE :OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE :OR PERFORMANCE OF THIS SOFTWARE. : :*/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#ifdef __CYGWIN__ :#include :#include :#endif : :#if defined(WIN32) && !defined(__CYGWIN__) :#include :#endif :#include :#include :#include :#if !defined(WIN32) || !defined(__MINGW32__) :#include :#include :#endif :#include "misc.h" :#include :#define XSERV_t :#define TRANS_SERVER :#define TRANS_REOPEN :#include :#include "input.h" :#include "dixfont.h" :#include "osdep.h" :#include "extension.h" :#ifdef X_POSIX_C_SOURCE :#define _POSIX_C_SOURCE X_POSIX_C_SOURCE :#include :#undef _POSIX_C_SOURCE :#else :#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) :#include :#else :#define _POSIX_SOURCE :#include :#undef _POSIX_SOURCE :#endif :#endif :#ifndef WIN32 :#include :#endif :#if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4) :#include :#endif :#include :#include /* for isspace */ :#include : :#if defined(DGUX) :#include :#include :#endif : :#include /* for malloc() */ : :#if defined(TCPCONN) || defined(STREAMSCONN) :# ifndef WIN32 :# include :# endif :#endif : :#include "opaque.h" : :#ifdef SMART_SCHEDULE :#include "dixstruct.h" :#endif : :#ifdef XKB :#include :#endif :#ifdef XCSECURITY :#include "securitysrv.h" :#endif : :#ifdef RENDER :#include "picture.h" :#endif : :#ifdef XPRINT :#include "DiPrint.h" :#endif : :_X_EXPORT Bool noTestExtensions; :#ifdef BIGREQS :_X_EXPORT Bool noBigReqExtension = FALSE; :#endif :#ifdef COMPOSITE :_X_EXPORT Bool noCompositeExtension = FALSE; :#endif : :#ifdef DAMAGE :_X_EXPORT Bool noDamageExtension = FALSE; :#endif :#ifdef DBE :_X_EXPORT Bool noDbeExtension = FALSE; :#endif :#ifdef DPMSExtension :_X_EXPORT Bool noDPMSExtension = FALSE; :#endif :#ifdef EVI :_X_EXPORT Bool noEVIExtension = FALSE; :#endif :#ifdef FONTCACHE :_X_EXPORT Bool noFontCacheExtension = FALSE; :#endif :#ifdef GLXEXT :_X_EXPORT Bool noGlxExtension = FALSE; :#endif :#ifdef SCREENSAVER :_X_EXPORT Bool noScreenSaverExtension = FALSE; :#endif :#ifdef MITSHM :_X_EXPORT Bool noMITShmExtension = FALSE; :#endif :#ifdef MITMISC :_X_EXPORT Bool noMITMiscExtension = FALSE; :#endif :#ifdef MULTIBUFFER :_X_EXPORT Bool noMultibufferExtension = FALSE; :#endif :#ifdef RANDR :_X_EXPORT Bool noRRExtension = FALSE; :#endif :#ifdef RENDER :_X_EXPORT Bool noRenderExtension = FALSE; :#endif :#ifdef SHAPE :_X_EXPORT Bool noShapeExtension = FALSE; :#endif :#ifdef XCSECURITY :_X_EXPORT Bool noSecurityExtension = FALSE; :#endif :#ifdef XSYNC :_X_EXPORT Bool noSyncExtension = FALSE; :#endif :#ifdef TOGCUP :_X_EXPORT Bool noXcupExtension = FALSE; :#endif :#ifdef RES :_X_EXPORT Bool noResExtension = FALSE; :#endif :#ifdef XAPPGROUP :_X_EXPORT Bool noXagExtension = FALSE; :#endif :#ifdef XCMISC :_X_EXPORT Bool noXCMiscExtension = FALSE; :#endif :#ifdef XEVIE :/* Xevie is disabled by default for now until the : * interface is stable */ :_X_EXPORT Bool noXevieExtension = TRUE; :#endif :#ifdef XF86BIGFONT :_X_EXPORT Bool noXFree86BigfontExtension = FALSE; :#endif :#ifdef XFreeXDGA :_X_EXPORT Bool noXFree86DGAExtension = FALSE; :#endif :#ifdef XF86DRI :_X_EXPORT Bool noXFree86DRIExtension = FALSE; :#endif :#ifdef XF86MISC :_X_EXPORT Bool noXFree86MiscExtension = FALSE; :#endif :#ifdef XF86VIDMODE :_X_EXPORT Bool noXFree86VidModeExtension = FALSE; :#endif :#ifdef XFIXES :_X_EXPORT Bool noXFixesExtension = FALSE; :#endif :/* |noXkbExtension| is defined in xc/programs/Xserver/xkb/xkbInit.c */ :#ifdef PANORAMIX :/* Xinerama is disabled by default unless enabled via +xinerama */ :_X_EXPORT Bool noPanoramiXExtension = TRUE; :#endif :#ifdef XINPUT :_X_EXPORT Bool noXInputExtension = FALSE; :#endif :#ifdef XIDLE :_X_EXPORT Bool noXIdleExtension = FALSE; :#endif :#ifdef XV :_X_EXPORT Bool noXvExtension = FALSE; :#endif : :#define X_INCLUDE_NETDB_H :#include : :#include : :Bool CoreDump; : :#ifdef PANORAMIX :Bool PanoramiXExtensionDisabledHack = FALSE; :#endif : :int auditTrailLevel = 1; : :_X_EXPORT Bool Must_have_memory = FALSE; : :#ifdef AIXV3 :int SyncOn = 0; :extern int SelectWaitTime; :#endif : :#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED) :#define HAS_SAVED_IDS_AND_SETEUID :#endif : :#ifdef MEMBUG :#define MEM_FAIL_SCALE 100000 :long Memory_fail = 0; :#include /* for random() */ :#endif : :static char *dev_tty_from_init = NULL; /* since we need to parse it anyway */ : :OsSigHandlerPtr :OsSignal(sig, handler) : int sig; : OsSigHandlerPtr handler; :{ :#ifdef X_NOT_POSIX : return signal(sig, handler); :#else : struct sigaction act, oact; : : sigemptyset(&act.sa_mask); : if (handler != SIG_IGN) : sigaddset(&act.sa_mask, sig); : act.sa_flags = 0; : act.sa_handler = handler; : sigaction(sig, &act, &oact); : return oact.sa_handler; :#endif :} : :#ifdef SERVER_LOCK :/* : * Explicit support for a server lock file like the ones used for UUCP. : * For architectures with virtual terminals that can run more than one : * server at a time. This keeps the servers from stomping on each other : * if the user forgets to give them different display numbers. : */ :#define LOCK_DIR "/tmp" :#define LOCK_TMP_PREFIX "/.tX" :#define LOCK_PREFIX "/.X" :#define LOCK_SUFFIX "-lock" : :#if defined(DGUX) :#include :#include :#endif : :#ifndef PATH_MAX :#ifndef Lynx :#include :#else :#include :#endif :#ifndef PATH_MAX :#ifdef MAXPATHLEN :#define PATH_MAX MAXPATHLEN :#else :#define PATH_MAX 1024 :#endif :#endif :#endif : :static Bool StillLocking = FALSE; :static char LockFile[PATH_MAX]; :static Bool nolock = FALSE; : :/* : * LockServer -- : * Check if the server lock file exists. If so, check if the PID : * contained inside is valid. If so, then die. Otherwise, create : * the lock file containing the PID. : */ :void :LockServer(void) :{ : char tmp[PATH_MAX], pid_str[12]; : int lfd, i, haslock, l_pid, t; : char *tmppath = NULL; : int len; : char port[20]; : : if (nolock) return; : /* : * Path names : */ : tmppath = LOCK_DIR; : : sprintf(port, "%d", atoi(display)); : len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) : : strlen(LOCK_TMP_PREFIX); : len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1; : if (len > sizeof(LockFile)) : FatalError("Display name `%s' is too long\n", port); : (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port); : (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port); : : /* : * Create a temporary file containing our PID. Attempt three times : * to create the file. : */ : StillLocking = TRUE; : i = 0; : do { : i++; : lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); : if (lfd < 0) : sleep(2); : else : break; : } while (i < 3); : if (lfd < 0) { : unlink(tmp); : i = 0; : do { : i++; : lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); : if (lfd < 0) : sleep(2); : else : break; : } while (i < 3); : } : if (lfd < 0) : FatalError("Could not create lock file in %s\n", tmp); : (void) sprintf(pid_str, "%10ld\n", (long)getpid()); : (void) write(lfd, pid_str, 11); :#ifndef USE_CHMOD : (void) fchmod(lfd, 0444); :#else : (void) chmod(tmp, 0444); :#endif : (void) close(lfd); : : /* : * OK. Now the tmp file exists. Try three times to move it in place : * for the lock. : */ : i = 0; : haslock = 0; : while ((!haslock) && (i++ < 3)) { : haslock = (link(tmp,LockFile) == 0); : if (haslock) { : /* : * We're done. : */ : break; : } : else { : /* : * Read the pid from the existing file : */ : lfd = open(LockFile, O_RDONLY); : if (lfd < 0) { : unlink(tmp); : FatalError("Can't read lock file %s\n", LockFile); : } : pid_str[0] = '\0'; : if (read(lfd, pid_str, 11) != 11) { : /* : * Bogus lock file. : */ : unlink(LockFile); : close(lfd); : continue; : } : pid_str[11] = '\0'; : sscanf(pid_str, "%d", &l_pid); : close(lfd); : : /* : * Now try to kill the PID to see if it exists. : */ : errno = 0; : t = kill(l_pid, 0); : if ((t< 0) && (errno == ESRCH)) { : /* : * Stale lock file. : */ : unlink(LockFile); : continue; : } : else if (((t < 0) && (errno == EPERM)) || (t == 0)) { : /* : * Process is still active. : */ : unlink(tmp); : FatalError("Server is already active for display %s\n%s %s\n%s\n", : port, "\tIf this server is no longer running, remove", : LockFile, "\tand start again."); : } : } : } : unlink(tmp); : if (!haslock) : FatalError("Could not create server lock file: %s\n", LockFile); : StillLocking = FALSE; :} : :/* : * UnlockServer -- : * Remove the server lock file. : */ :void :UnlockServer(void) :{ : if (nolock) return; : : if (!StillLocking){ : : (void) unlink(LockFile); : } :} :#endif /* SERVER_LOCK */ : :/* Force connections to close on SIGHUP from init */ : :/*ARGSUSED*/ :SIGVAL :AutoResetServer (int sig) :{ : int olderrno = errno; : : dispatchException |= DE_RESET; : isItTimeToYield = TRUE; :#ifdef GPROF : chdir ("/tmp"); : exit (0); :#endif :#if defined(SYSV) && defined(X_NOT_POSIX) : OsSignal (SIGHUP, AutoResetServer); :#endif : errno = olderrno; :} : :/* Force connections to close and then exit on SIGTERM, SIGINT */ : :/*ARGSUSED*/ :_X_EXPORT SIGVAL :GiveUp(int sig) :{ : int olderrno = errno; : : dispatchException |= DE_TERMINATE; : isItTimeToYield = TRUE; :#if defined(SYSV) && defined(X_NOT_POSIX) : if (sig) : OsSignal(sig, SIG_IGN); :#endif : errno = olderrno; :} : :#if defined WIN32 && defined __MINGW32__ :_X_EXPORT CARD32 :GetTimeInMillis (void) :{ : return GetTickCount (); :} :#else :_X_EXPORT CARD32 :GetTimeInMillis(void) 1 0.0011 :{ /* GetTimeInMillis total: 1 0.0011 */ : struct timeval tv; : :#ifdef MONOTONIC_CLOCK : struct timespec tp; : if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) : return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L); :#endif : : X_GETTIMEOFDAY(&tv); : return(tv.tv_sec * 1000) + (tv.tv_usec / 1000); :} :#endif : :_X_EXPORT void :AdjustWaitForDelay (pointer waitTime, unsigned long newdelay) :{ : static struct timeval delay_val; : struct timeval **wt = (struct timeval **) waitTime; : unsigned long olddelay; : : if (*wt == NULL) : { : delay_val.tv_sec = newdelay / 1000; : delay_val.tv_usec = 1000 * (newdelay % 1000); : *wt = &delay_val; : } : else : { : olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000; : if (newdelay < olddelay) : { : (*wt)->tv_sec = newdelay / 1000; : (*wt)->tv_usec = 1000 * (newdelay % 1000); : } : } :} : :void UseMsg(void) :{ :#if !defined(AIXrt) && !defined(AIX386) : ErrorF("use: X [:] [option]\n"); : ErrorF("-a # mouse acceleration (pixels)\n"); : ErrorF("-ac disable access control restrictions\n"); :#ifdef MEMBUG : ErrorF("-alloc int chance alloc should fail\n"); :#endif : ErrorF("-audit int set audit trail level\n"); : ErrorF("-auth file select authorization file\n"); : ErrorF("-br create root window with black background\n"); : ErrorF("+bs enable any backing store support\n"); : ErrorF("-bs disable any backing store support\n"); : ErrorF("-c turns off key-click\n"); : ErrorF("c # key-click volume (0-100)\n"); : ErrorF("-cc int default color visual class\n"); : ErrorF("-co file color database file\n"); :#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS : ErrorF("-config file read options from file\n"); :#endif : ErrorF("-core generate core dump on fatal error\n"); : ErrorF("-dpi int screen resolution in dots per inch\n"); :#ifdef DPMSExtension : ErrorF("dpms enables VESA DPMS monitor control\n"); : ErrorF("-dpms disables VESA DPMS monitor control\n"); :#endif : ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n"); : ErrorF("-f # bell base (0-100)\n"); : ErrorF("-fc string cursor font\n"); : ErrorF("-fn string default font name\n"); : ErrorF("-fp string default font path\n"); : ErrorF("-help prints message with these options\n"); : ErrorF("-I ignore all remaining arguments\n"); :#ifdef RLIMIT_DATA : ErrorF("-ld int limit data space to N Kb\n"); :#endif :#ifdef RLIMIT_NOFILE : ErrorF("-lf int limit number of open files to N\n"); :#endif :#ifdef RLIMIT_STACK : ErrorF("-ls int limit stack space to N Kb\n"); :#endif :#ifdef SERVER_LOCK : ErrorF("-nolock disable the locking mechanism\n"); :#endif :#ifndef NOLOGOHACK : ErrorF("-logo enable logo in screen saver\n"); : ErrorF("nologo disable logo in screen saver\n"); :#endif : ErrorF("-nolisten string don't listen on protocol\n"); : ErrorF("-noreset don't reset after last client exists\n"); : ErrorF("-reset reset after last client exists\n"); : ErrorF("-p # screen-saver pattern duration (minutes)\n"); : ErrorF("-pn accept failure to listen on all ports\n"); : ErrorF("-nopn reject failure to listen on all ports\n"); : ErrorF("-r turns off auto-repeat\n"); : ErrorF("r turns on auto-repeat \n"); :#ifdef RENDER : ErrorF("-render [default|mono|gray|color] set render color alloc policy\n"); :#endif : ErrorF("-s # screen-saver timeout (minutes)\n"); :#ifdef XCSECURITY : ErrorF("-sp file security policy file\n"); :#endif :#ifdef XPRINT : PrinterUseMsg(); :#endif : ErrorF("-su disable any save under support\n"); : ErrorF("-t # mouse threshold (pixels)\n"); : ErrorF("-terminate terminate at server reset\n"); : ErrorF("-to # connection time out\n"); : ErrorF("-tst disable testing extensions\n"); : ErrorF("ttyxx server started from init on /dev/ttyxx\n"); : ErrorF("v video blanking for screen-saver\n"); : ErrorF("-v screen-saver without video blanking\n"); : ErrorF("-wm WhenMapped default backing-store\n"); : ErrorF("-wr create root window with white background\n"); : ErrorF("-x string loads named extension at init time \n"); : ErrorF("-maxbigreqsize set maximal bigrequest size \n"); :#ifdef PANORAMIX : ErrorF("+xinerama Enable XINERAMA extension\n"); : ErrorF("-xinerama Disable XINERAMA extension\n"); :#endif :#ifdef SMART_SCHEDULE : ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n"); : ErrorF("-schedInterval int Set scheduler interval in msec\n"); :#endif : ErrorF("+extension name Enable extension\n"); : ErrorF("-extension name Disable extension\n"); :#ifdef XDMCP : XdmcpUseMsg(); :#endif :#endif /* !AIXrt && ! AIX386 */ :#ifdef XKB : XkbUseMsg(); :#endif : ddxUseMsg(); :} : :/* This function performs a rudimentary sanity check : * on the display name passed in on the command-line, : * since this string is used to generate filenames. : * It is especially important that the display name : * not contain a "/" and not start with a "-". : * --kvajk : */ :static int :VerifyDisplayName(const char *d) :{ : if ( d == (char *)0 ) return( 0 ); /* null */ : if ( *d == '\0' ) return( 0 ); /* empty */ : if ( *d == '-' ) return( 0 ); /* could be confused for an option */ : if ( *d == '.' ) return( 0 ); /* must not equal "." or ".." */ : if ( strchr(d, '/') != (char *)0 ) return( 0 ); /* very important!!! */ : return( 1 ); :} : :/* : * This function is responsible for doing initalisation of any global : * variables at an very early point of server startup (even before : * |ProcessCommandLine()|. : */ :void InitGlobals(void) :{ : ddxInitGlobals(); :} : : :/* : * This function parses the command line. Handles device-independent fields : * and allows ddx to handle additional fields. It is not allowed to modify : * argc or any of the strings pointed to by argv. : */ :void :ProcessCommandLine(int argc, char *argv[]) :{ : int i, skip; : : defaultKeyboardControl.autoRepeat = TRUE; : :#ifdef NO_PART_NET : PartialNetwork = FALSE; :#else : PartialNetwork = TRUE; :#endif : : for ( i = 1; i < argc; i++ ) : { : /* call ddx first, so it can peek/override if it wants */ : if((skip = ddxProcessArgument(argc, argv, i))) : { : i += (skip - 1); : } : else if(argv[i][0] == ':') : { : /* initialize display */ : display = argv[i]; : display++; : if( ! VerifyDisplayName( display ) ) { : ErrorF("Bad display name: %s\n", display); : UseMsg(); : FatalError("Bad display name, exiting: %s\n", display); : } : } : else if ( strcmp( argv[i], "-a") == 0) : { : if(++i < argc) : defaultPointerControl.num = atoi(argv[i]); : else : UseMsg(); : } : else if ( strcmp( argv[i], "-ac") == 0) : { : defeatAccessControl = TRUE; : } :#ifdef MEMBUG : else if ( strcmp( argv[i], "-alloc") == 0) : { : if(++i < argc) : Memory_fail = atoi(argv[i]); : else : UseMsg(); : } :#endif : else if ( strcmp( argv[i], "-audit") == 0) : { : if(++i < argc) : auditTrailLevel = atoi(argv[i]); : else : UseMsg(); : } : else if ( strcmp( argv[i], "-auth") == 0) : { : if(++i < argc) : InitAuthorization (argv[i]); : else : UseMsg(); : } : else if ( strcmp( argv[i], "-br") == 0) : blackRoot = TRUE; : else if ( strcmp( argv[i], "+bs") == 0) : enableBackingStore = TRUE; : else if ( strcmp( argv[i], "-bs") == 0) : disableBackingStore = TRUE; : else if ( strcmp( argv[i], "c") == 0) : { : if(++i < argc) : defaultKeyboardControl.click = atoi(argv[i]); : else : UseMsg(); : } : else if ( strcmp( argv[i], "-c") == 0) : { : defaultKeyboardControl.click = 0; : } : else if ( strcmp( argv[i], "-cc") == 0) : { : if(++i < argc) : defaultColorVisualClass = atoi(argv[i]); : else : UseMsg(); : } : else if ( strcmp( argv[i], "-co") == 0) : { : if(++i < argc) : rgbPath = argv[i]; : else : UseMsg(); : } : else if ( strcmp( argv[i], "-core") == 0) : { : CoreDump = TRUE; :#if !defined(WIN32) || !defined(__MINGW32__) : struct rlimit core_limit; : getrlimit (RLIMIT_CORE, &core_limit); : core_limit.rlim_cur = core_limit.rlim_max; : setrlimit (RLIMIT_CORE, &core_limit); :#endif : } : else if ( strcmp( argv[i], "-dpi") == 0) : { : if(++i < argc) : monitorResolution = atoi(argv[i]); : else : UseMsg(); : } :#ifdef DPMSExtension : else if ( strcmp( argv[i], "dpms") == 0) : DPMSEnabledSwitch = TRUE; : else if ( strcmp( argv[i], "-dpms") == 0) : DPMSDisabledSwitch = TRUE; :#endif : else if ( strcmp( argv[i], "-deferglyphs") == 0) : { : if(++i >= argc || !ParseGlyphCachingMode(argv[i])) : UseMsg(); : } : else if ( strcmp( argv[i], "-f") == 0) : { : if(++i < argc) : defaultKeyboardControl.bell = atoi(argv[i]); : else : UseMsg(); : } : else if ( strcmp( argv[i], "-fc") == 0) : { : if(++i < argc) : defaultCursorFont = argv[i]; : else : UseMsg(); : } : else if ( strcmp( argv[i], "-fn") == 0) : { : if(++i < argc) : defaultTextFont = argv[i]; : else : UseMsg(); : } : else if ( strcmp( argv[i], "-fp") == 0) : { : if(++i < argc) : { : defaultFontPath = argv[i]; : } : else : UseMsg(); : } : else if ( strcmp( argv[i], "-help") == 0) : { : UseMsg(); : exit(0); : } :#ifdef XKB : else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) { : if (skip>0) : i+= skip-1; : else UseMsg(); : } :#endif :#ifdef RLIMIT_DATA : else if ( strcmp( argv[i], "-ld") == 0) : { : if(++i < argc) : { : limitDataSpace = atoi(argv[i]); : if (limitDataSpace > 0) : limitDataSpace *= 1024; : } : else : UseMsg(); : } :#endif :#ifdef RLIMIT_NOFILE : else if ( strcmp( argv[i], "-lf") == 0) : { : if(++i < argc) : limitNoFile = atoi(argv[i]); : else : UseMsg(); : } :#endif :#ifdef RLIMIT_STACK : else if ( strcmp( argv[i], "-ls") == 0) : { : if(++i < argc) : { : limitStackSpace = atoi(argv[i]); : if (limitStackSpace > 0) : limitStackSpace *= 1024; : } : else : UseMsg(); : } :#endif :#ifdef SERVER_LOCK : else if ( strcmp ( argv[i], "-nolock") == 0) : { :#if !defined(WIN32) && !defined(__CYGWIN__) : if (getuid() != 0) : ErrorF("Warning: the -nolock option can only be used by root\n"); : else :#endif : nolock = TRUE; : } :#endif :#ifndef NOLOGOHACK : else if ( strcmp( argv[i], "-logo") == 0) : { : logoScreenSaver = 1; : } : else if ( strcmp( argv[i], "nologo") == 0) : { : logoScreenSaver = 0; : } :#endif : else if ( strcmp( argv[i], "-nolisten") == 0) : { : if(++i < argc) { : if (_XSERVTransNoListen(argv[i])) : FatalError ("Failed to disable listen for %s transport", : argv[i]); : } else : UseMsg(); : } : else if ( strcmp( argv[i], "-noreset") == 0) : { : dispatchExceptionAtReset = 0; : } : else if ( strcmp( argv[i], "-reset") == 0) : { : dispatchExceptionAtReset = DE_RESET; : } : else if ( strcmp( argv[i], "-p") == 0) : { : if(++i < argc) : defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) * : MILLI_PER_MIN; : else : UseMsg(); : } : else if ( strcmp( argv[i], "-pn") == 0) : PartialNetwork = TRUE; : else if ( strcmp( argv[i], "-nopn") == 0) : PartialNetwork = FALSE; : else if ( strcmp( argv[i], "r") == 0) : defaultKeyboardControl.autoRepeat = TRUE; : else if ( strcmp( argv[i], "-r") == 0) : defaultKeyboardControl.autoRepeat = FALSE; : else if ( strcmp( argv[i], "-s") == 0) : { : if(++i < argc) : defaultScreenSaverTime = ((CARD32)atoi(argv[i])) * : MILLI_PER_MIN; : else : UseMsg(); : } : else if ( strcmp( argv[i], "-su") == 0) : disableSaveUnders = TRUE; : else if ( strcmp( argv[i], "-t") == 0) : { : if(++i < argc) : defaultPointerControl.threshold = atoi(argv[i]); : else : UseMsg(); : } : else if ( strcmp( argv[i], "-terminate") == 0) : { : dispatchExceptionAtReset = DE_TERMINATE; : } : else if ( strcmp( argv[i], "-to") == 0) : { : if(++i < argc) : TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND; : else : UseMsg(); : } : else if ( strcmp( argv[i], "-tst") == 0) : { : noTestExtensions = TRUE; : } : else if ( strcmp( argv[i], "v") == 0) : defaultScreenSaverBlanking = PreferBlanking; : else if ( strcmp( argv[i], "-v") == 0) : defaultScreenSaverBlanking = DontPreferBlanking; : else if ( strcmp( argv[i], "-wm") == 0) : defaultBackingStore = WhenMapped; : else if ( strcmp( argv[i], "-wr") == 0) : whiteRoot = TRUE; : else if ( strcmp( argv[i], "-maxbigreqsize") == 0) { : if(++i < argc) { : long reqSizeArg = atol(argv[i]); : : /* Request size > 128MB does not make much sense... */ : if( reqSizeArg > 0L && reqSizeArg < 128L ) { : maxBigRequestSize = (reqSizeArg * 1048576L) - 1L; : } : else : { : UseMsg(); : } : } : else : { : UseMsg(); : } : } :#ifdef PANORAMIX : else if ( strcmp( argv[i], "+xinerama") == 0){ : noPanoramiXExtension = FALSE; : } : else if ( strcmp( argv[i], "-xinerama") == 0){ : noPanoramiXExtension = TRUE; : } : else if ( strcmp( argv[i], "-disablexineramaextension") == 0){ : PanoramiXExtensionDisabledHack = TRUE; : } :#endif : else if ( strcmp( argv[i], "-x") == 0) : { : if(++i >= argc) : UseMsg(); : /* For U**x, which doesn't support dynamic loading, there's nothing : * to do when we see a -x. Either the extension is linked in or : * it isn't */ : } : else if ( strcmp( argv[i], "-I") == 0) : { : /* ignore all remaining arguments */ : break; : } : else if (strncmp (argv[i], "tty", 3) == 0) : { : /* just in case any body is interested */ : dev_tty_from_init = argv[i]; : } :#ifdef XDMCP : else if ((skip = XdmcpOptions(argc, argv, i)) != i) : { : i = skip - 1; : } :#endif :#ifdef XPRINT : else if ((skip = PrinterOptions(argc, argv, i)) != i) : { : i = skip - 1; : } :#endif :#ifdef XCSECURITY : else if ((skip = XSecurityOptions(argc, argv, i)) != i) : { : i = skip - 1; : } :#endif :#ifdef AIXV3 : else if ( strcmp( argv[i], "-timeout") == 0) : { : if(++i < argc) : SelectWaitTime = atoi(argv[i]); : else : UseMsg(); : } : else if ( strcmp( argv[i], "-sync") == 0) : { : SyncOn++; : } :#endif :#ifdef SMART_SCHEDULE : else if ( strcmp( argv[i], "-dumbSched") == 0) : { : SmartScheduleDisable = TRUE; : } : else if ( strcmp( argv[i], "-schedInterval") == 0) : { : if (++i < argc) : { : SmartScheduleInterval = atoi(argv[i]); : SmartScheduleSlice = SmartScheduleInterval; : } : else : UseMsg(); : } : else if ( strcmp( argv[i], "-schedMax") == 0) : { : if (++i < argc) : { : SmartScheduleMaxSlice = atoi(argv[i]); : } : else : UseMsg(); : } :#endif :#ifdef RENDER : else if ( strcmp( argv[i], "-render" ) == 0) : { : if (++i < argc) : { : int policy = PictureParseCmapPolicy (argv[i]); : : if (policy != PictureCmapPolicyInvalid) : PictureCmapPolicy = policy; : else : UseMsg (); : } : else : UseMsg (); : } :#endif : else if ( strcmp( argv[i], "+extension") == 0) : { : if (++i < argc) : { : if (!EnableDisableExtension(argv[i], TRUE)) : EnableDisableExtensionError(argv[i], TRUE); : } : else : UseMsg(); : } : else if ( strcmp( argv[i], "-extension") == 0) : { : if (++i < argc) : { : if (!EnableDisableExtension(argv[i], FALSE)) : EnableDisableExtensionError(argv[i], FALSE); : } : else : UseMsg(); : } : else : { : ErrorF("Unrecognized option: %s\n", argv[i]); : UseMsg(); : FatalError("Unrecognized option: %s\n", argv[i]); : } : } :} : :#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS :static void :InsertFileIntoCommandLine( : int *resargc, char ***resargv, : int prefix_argc, char **prefix_argv, : char *filename, : int suffix_argc, char **suffix_argv) :{ : struct stat st; : FILE *f; : char *p; : char *q; : int insert_argc; : char *buf; : int len; : int i; : : f = fopen(filename, "r"); : if (!f) : FatalError("Can't open option file %s\n", filename); : : fstat(fileno(f), &st); : : buf = (char *) xalloc((unsigned) st.st_size + 1); : if (!buf) : FatalError("Out of Memory\n"); : : len = fread(buf, 1, (unsigned) st.st_size, f); : : fclose(f); : : if (len < 0) : FatalError("Error reading option file %s\n", filename); : : buf[len] = '\0'; : : p = buf; : q = buf; : insert_argc = 0; : : while (*p) : { : while (isspace(*p)) : p++; : if (!*p) : break; : if (*p == '#') : { : while (*p && *p != '\n') : p++; : } else : { : while (*p && !isspace(*p)) : *q++ = *p++; : /* Since p and q might still be pointing at the same place, we */ : /* need to step p over the whitespace now before we add the null. */ : if (*p) : p++; : *q++ = '\0'; : insert_argc++; : } : } : : buf = (char *) xrealloc(buf, q - buf); : if (!buf) : FatalError("Out of memory reallocing option buf\n"); : : *resargc = prefix_argc + insert_argc + suffix_argc; : *resargv = (char **) xalloc((*resargc + 1) * sizeof(char *)); : if (!*resargv) : FatalError("Out of Memory\n"); : : memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *)); : : p = buf; : for (i = 0; i < insert_argc; i++) : { : (*resargv)[prefix_argc + i] = p; : p += strlen(p) + 1; : } : : memcpy(*resargv + prefix_argc + insert_argc, : suffix_argv, suffix_argc * sizeof(char *)); : : (*resargv)[*resargc] = NULL; :} /* end InsertFileIntoCommandLine */ : : :void :ExpandCommandLine(int *pargc, char ***pargv) :{ : int i; : :#if !defined(WIN32) && !defined(__CYGWIN__) : if (getuid() != geteuid()) : return; :#endif : : for (i = 1; i < *pargc; i++) : { : if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) ) : { : InsertFileIntoCommandLine(pargc, pargv, : i, *pargv, : (*pargv)[i+1], /* filename */ : *pargc - i - 2, *pargv + i + 2); : i--; : } : } :} /* end ExpandCommandLine */ :#endif : :/* Implement a simple-minded font authorization scheme. The authorization : name is "hp-hostname-1", the contents are simply the host name. */ :int :set_font_authorizations(char **authorizations, int *authlen, pointer client) :{ :#define AUTHORIZATION_NAME "hp-hostname-1" :#if defined(TCPCONN) || defined(STREAMSCONN) : static char *result = NULL; : static char *p = NULL; : : if (p == NULL) : { : char hname[1024], *hnameptr; : unsigned int len; :#if defined(IPv6) && defined(AF_INET6) : struct addrinfo hints, *ai = NULL; :#else : struct hostent *host; :#ifdef XTHREADS_NEEDS_BYNAMEPARAMS : _Xgethostbynameparams hparams; :#endif :#endif : : gethostname(hname, 1024); :#if defined(IPv6) && defined(AF_INET6) : bzero(&hints, sizeof(hints)); : hints.ai_flags = AI_CANONNAME; : if (getaddrinfo(hname, NULL, &hints, &ai) == 0) { : hnameptr = ai->ai_canonname; : } else { : hnameptr = hname; : } :#else : host = _XGethostbyname(hname, hparams); : if (host == NULL) : hnameptr = hname; : else : hnameptr = host->h_name; :#endif : : len = strlen(hnameptr) + 1; : result = xalloc(len + sizeof(AUTHORIZATION_NAME) + 4); : : p = result; : *p++ = sizeof(AUTHORIZATION_NAME) >> 8; : *p++ = sizeof(AUTHORIZATION_NAME) & 0xff; : *p++ = (len) >> 8; : *p++ = (len & 0xff); : : memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME)); : p += sizeof(AUTHORIZATION_NAME); : memmove(p, hnameptr, len); : p += len; :#if defined(IPv6) && defined(AF_INET6) : if (ai) { : freeaddrinfo(ai); : } :#endif : } : *authlen = p - result; : *authorizations = result; : return 1; :#else /* TCPCONN */ : return 0; :#endif /* TCPCONN */ :} : :/* XALLOC -- X's internal memory allocator. Why does it return unsigned : * long * instead of the more common char *? Well, if you read K&R you'll : * see they say that alloc must return a pointer "suitable for conversion" : * to whatever type you really want. In a full-blown generic allocator : * there's no way to solve the alignment problems without potentially : * wasting lots of space. But we have a more limited problem. We know : * we're only ever returning pointers to structures which will have to : * be long word aligned. So we are making a stronger guarantee. It might : * have made sense to make Xalloc return char * to conform with people's : * expectations of malloc, but this makes lint happier. : */ : :#ifndef INTERNAL_MALLOC : :_X_EXPORT void * :Xalloc(unsigned long amount) 6 0.0065 :{ /* Xalloc total: 10 0.0109 */ : register pointer ptr; : 1 0.0011 : if ((long)amount <= 0) { : return (unsigned long *)NULL; : } : /* aligned extra on long word boundary */ : amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); :#ifdef MEMBUG : if (!Must_have_memory && Memory_fail && : ((random() % MEM_FAIL_SCALE) < Memory_fail)) : return (unsigned long *)NULL; :#endif 1 0.0011 : if ((ptr = (pointer)malloc(amount))) { : return (unsigned long *)ptr; : } : if (Must_have_memory) : FatalError("Out of memory"); : return (unsigned long *)NULL; 2 0.0022 :} : :/***************** : * XNFalloc : * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory : *****************/ : :_X_EXPORT void * :XNFalloc(unsigned long amount) :{ : register pointer ptr; : : if ((long)amount <= 0) : { : return (unsigned long *)NULL; : } : /* aligned extra on long word boundary */ : amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); : ptr = (pointer)malloc(amount); : if (!ptr) : { : FatalError("Out of memory"); : } : return ((unsigned long *)ptr); :} : :/***************** : * Xcalloc : *****************/ : :_X_EXPORT void * :Xcalloc(unsigned long amount) :{ : unsigned long *ret; : : ret = Xalloc (amount); : if (ret) : bzero ((char *) ret, (int) amount); : return ret; :} : :/***************** : * XNFcalloc : *****************/ : :_X_EXPORT void * :XNFcalloc(unsigned long amount) :{ : unsigned long *ret; : : ret = Xalloc (amount); : if (ret) : bzero ((char *) ret, (int) amount); : else if ((long)amount > 0) : FatalError("Out of memory"); : return ret; :} : :/***************** : * Xrealloc : *****************/ : :_X_EXPORT void * :Xrealloc(pointer ptr, unsigned long amount) :{ :#ifdef MEMBUG : if (!Must_have_memory && Memory_fail && : ((random() % MEM_FAIL_SCALE) < Memory_fail)) : return (unsigned long *)NULL; :#endif : if ((long)amount <= 0) : { : if (ptr && !amount) : free(ptr); : return (unsigned long *)NULL; : } : amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); : if (ptr) : ptr = (pointer)realloc((char *)ptr, amount); : else : ptr = (pointer)malloc(amount); : if (ptr) : return (unsigned long *)ptr; : if (Must_have_memory) : FatalError("Out of memory"); : return (unsigned long *)NULL; :} : :/***************** : * XNFrealloc : * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory : *****************/ : :_X_EXPORT void * :XNFrealloc(pointer ptr, unsigned long amount) :{ : if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL) : { : if ((long)amount > 0) : FatalError( "Out of memory" ); : } : return ((unsigned long *)ptr); :} : :/***************** : * Xfree : * calls free : *****************/ : :_X_EXPORT void :Xfree(pointer ptr) 7 0.0076 :{ /* Xfree total: 10 0.0109 */ 1 0.0011 : if (ptr) 1 0.0011 : free((char *)ptr); 1 0.0011 :} : :void :OsInitAllocator (void) :{ :#ifdef MEMBUG : static int been_here; : : /* Check the memory system after each generation */ : if (been_here) : CheckMemory (); : else : been_here = 1; :#endif :} :#endif /* !INTERNAL_MALLOC */ : : :char * :Xstrdup(const char *s) :{ : char *sd; : : if (s == NULL) : return NULL; : : sd = (char *)Xalloc(strlen(s) + 1); : if (sd != NULL) : strcpy(sd, s); : return sd; :} : : :_X_EXPORT char * :XNFstrdup(const char *s) :{ : char *sd; : : if (s == NULL) : return NULL; : : sd = (char *)XNFalloc(strlen(s) + 1); : strcpy(sd, s); : return sd; :} : :#ifdef SMART_SCHEDULE : :unsigned long SmartScheduleIdleCount; :Bool SmartScheduleIdle; :Bool SmartScheduleTimerStopped; : :#ifdef SIGVTALRM :#define SMART_SCHEDULE_POSSIBLE :#endif : :#ifdef SMART_SCHEDULE_POSSIBLE :#define SMART_SCHEDULE_SIGNAL SIGALRM :#define SMART_SCHEDULE_TIMER ITIMER_REAL :#endif : :static void :SmartScheduleStopTimer (void) :{ :#ifdef SMART_SCHEDULE_POSSIBLE : struct itimerval timer; : : timer.it_interval.tv_sec = 0; : timer.it_interval.tv_usec = 0; : timer.it_value.tv_sec = 0; : timer.it_value.tv_usec = 0; : (void) setitimer (ITIMER_REAL, &timer, 0); : SmartScheduleTimerStopped = TRUE; :#endif :} : :Bool :SmartScheduleStartTimer (void) :{ :#ifdef SMART_SCHEDULE_POSSIBLE : struct itimerval timer; : : SmartScheduleTimerStopped = FALSE; : timer.it_interval.tv_sec = 0; : timer.it_interval.tv_usec = SmartScheduleInterval * 1000; : timer.it_value.tv_sec = 0; : timer.it_value.tv_usec = SmartScheduleInterval * 1000; : return setitimer (ITIMER_REAL, &timer, 0) >= 0; :#endif : return FALSE; :} : :#ifdef SMART_SCHEDULE_POSSIBLE :static void :SmartScheduleTimer (int sig) :{ : int olderrno = errno; : : SmartScheduleTime += SmartScheduleInterval; : if (SmartScheduleIdle) : { : SmartScheduleStopTimer (); : } : errno = olderrno; :} :#endif : :Bool :SmartScheduleInit (void) :{ :#ifdef SMART_SCHEDULE_POSSIBLE : struct sigaction act; : : if (SmartScheduleDisable) : return TRUE; : : bzero ((char *) &act, sizeof(struct sigaction)); : : /* Set up the timer signal function */ : act.sa_handler = SmartScheduleTimer; : sigemptyset (&act.sa_mask); : sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL); : if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0) : { : perror ("sigaction for smart scheduler"); : return FALSE; : } : /* Set up the virtual timer */ : if (!SmartScheduleStartTimer ()) : { : perror ("scheduling timer"); : return FALSE; : } : /* stop the timer and wait for WaitForSomething to start it */ : SmartScheduleStopTimer (); : return TRUE; :#else : return FALSE; :#endif :} :#endif : :#ifdef SIG_BLOCK :static sigset_t PreviousSignalMask; :static int BlockedSignalCount; :#endif : :void :OsBlockSignals (void) :{ :#ifdef SIG_BLOCK : if (BlockedSignalCount++ == 0) : { : sigset_t set; : : sigemptyset (&set); :#ifdef SIGALRM : sigaddset (&set, SIGALRM); :#endif :#ifdef SIGVTALRM : sigaddset (&set, SIGVTALRM); :#endif :#ifdef SIGWINCH : sigaddset (&set, SIGWINCH); :#endif :#ifdef SIGIO : sigaddset (&set, SIGIO); :#endif :#ifdef SIGTSTP : sigaddset (&set, SIGTSTP); :#endif :#ifdef SIGTTIN : sigaddset (&set, SIGTTIN); :#endif :#ifdef SIGTTOU : sigaddset (&set, SIGTTOU); :#endif :#ifdef SIGCHLD : sigaddset (&set, SIGCHLD); :#endif : sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask); : } :#endif :} : :void :OsReleaseSignals (void) :{ :#ifdef SIG_BLOCK : if (--BlockedSignalCount == 0) : { : sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0); : } :#endif :} : :#if !defined(WIN32) :/* : * "safer" versions of system(3), popen(3) and pclose(3) which give up : * all privs before running a command. : * : * This is based on the code in FreeBSD 2.2 libc. : * : * XXX It'd be good to redirect stderr so that it ends up in the log file : * as well. As it is now, xkbcomp messages don't end up in the log file. : */ : :int :System(char *command) :{ : int pid, p; :#ifdef SIGCHLD : void (*csig)(int); :#endif : int status; : : if (!command) : return(1); : :#ifdef SIGCHLD : csig = signal(SIGCHLD, SIG_DFL); :#endif : :#ifdef DEBUG : ErrorF("System: `%s'\n", command); :#endif : : switch (pid = fork()) { : case -1: /* error */ : p = -1; : case 0: /* child */ : if (setgid(getgid()) == -1) : _exit(127); : if (setuid(getuid()) == -1) : _exit(127); : execl("/bin/sh", "sh", "-c", command, (char *)NULL); : _exit(127); : default: /* parent */ : do { : p = waitpid(pid, &status, 0); : } while (p == -1 && errno == EINTR); : : } : :#ifdef SIGCHLD : signal(SIGCHLD, csig); :#endif : : return p == -1 ? -1 : status; :} : :static struct pid { : struct pid *next; : FILE *fp; : int pid; :} *pidlist; : :pointer :Popen(char *command, char *type) :{ : struct pid *cur; : FILE *iop; : int pdes[2], pid; : : if (command == NULL || type == NULL) : return NULL; : : if ((*type != 'r' && *type != 'w') || type[1]) : return NULL; : : if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL) : return NULL; : : if (pipe(pdes) < 0) { : xfree(cur); : return NULL; : } : : switch (pid = fork()) { : case -1: /* error */ : close(pdes[0]); : close(pdes[1]); : xfree(cur); : return NULL; : case 0: /* child */ : if (setgid(getgid()) == -1) : _exit(127); : if (setuid(getuid()) == -1) : _exit(127); : if (*type == 'r') { : if (pdes[1] != 1) { : /* stdout */ : dup2(pdes[1], 1); : close(pdes[1]); : } : close(pdes[0]); : } else { : if (pdes[0] != 0) { : /* stdin */ : dup2(pdes[0], 0); : close(pdes[0]); : } : close(pdes[1]); : } : execl("/bin/sh", "sh", "-c", command, (char *)NULL); : _exit(127); : } : : /* Avoid EINTR during stdio calls */ : OsBlockSignals (); : : /* parent */ : if (*type == 'r') { : iop = fdopen(pdes[0], type); : close(pdes[1]); : } else { : iop = fdopen(pdes[1], type); : close(pdes[0]); : } : : cur->fp = iop; : cur->pid = pid; : cur->next = pidlist; : pidlist = cur; : :#ifdef DEBUG : ErrorF("Popen: `%s', fp = %p\n", command, iop); :#endif : : return iop; :} : :/* fopen that drops privileges */ :pointer :Fopen(char *file, char *type) :{ : FILE *iop; :#ifndef HAS_SAVED_IDS_AND_SETEUID : struct pid *cur; : int pdes[2], pid; : : if (file == NULL || type == NULL) : return NULL; : : if ((*type != 'r' && *type != 'w') || type[1]) : return NULL; : : if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL) : return NULL; : : if (pipe(pdes) < 0) { : xfree(cur); : return NULL; : } : : switch (pid = fork()) { : case -1: /* error */ : close(pdes[0]); : close(pdes[1]); : xfree(cur); : return NULL; : case 0: /* child */ : if (setgid(getgid()) == -1) : _exit(127); : if (setuid(getuid()) == -1) : _exit(127); : if (*type == 'r') { : if (pdes[1] != 1) { : /* stdout */ : dup2(pdes[1], 1); : close(pdes[1]); : } : close(pdes[0]); : } else { : if (pdes[0] != 0) { : /* stdin */ : dup2(pdes[0], 0); : close(pdes[0]); : } : close(pdes[1]); : } : execl("/bin/cat", "cat", file, (char *)NULL); : _exit(127); : } : : /* Avoid EINTR during stdio calls */ : OsBlockSignals (); : : /* parent */ : if (*type == 'r') { : iop = fdopen(pdes[0], type); : close(pdes[1]); : } else { : iop = fdopen(pdes[1], type); : close(pdes[0]); : } : : cur->fp = iop; : cur->pid = pid; : cur->next = pidlist; : pidlist = cur; : :#ifdef DEBUG : ErrorF("Fopen(%s), fp = %p\n", file, iop); :#endif : : return iop; :#else : int ruid, euid; : : ruid = getuid(); : euid = geteuid(); : : if (seteuid(ruid) == -1) { : return NULL; : } : iop = fopen(file, type); : : if (seteuid(euid) == -1) { : fclose(iop); : return NULL; : } : return iop; :#endif /* HAS_SAVED_IDS_AND_SETEUID */ :} : :int :Pclose(pointer iop) :{ : struct pid *cur, *last; : int pstat; : int pid; : :#ifdef DEBUG : ErrorF("Pclose: fp = %p\n", iop); :#endif : : fclose(iop); : : for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) : if (cur->fp == iop) : break; : if (cur == NULL) : return -1; : : do { : pid = waitpid(cur->pid, &pstat, 0); : } while (pid == -1 && errno == EINTR); : : if (last == NULL) : pidlist = cur->next; : else : last->next = cur->next; : xfree(cur); : : /* allow EINTR again */ : OsReleaseSignals (); : : return pid == -1 ? -1 : pstat; :} : :int :Fclose(pointer iop) :{ :#ifdef HAS_SAVED_IDS_AND_SETEUID : return fclose(iop); :#else : return Pclose(iop); :#endif :} : :#endif /* !WIN32 */ : : :/* : * CheckUserParameters: check for long command line arguments and long : * environment variables. By default, these checks are only done when : * the server's euid != ruid. In 3.3.x, these checks were done in an : * external wrapper utility. : */ : :/* Consider LD* variables insecure? */ :#ifndef REMOVE_ENV_LD :#define REMOVE_ENV_LD 1 :#endif : :/* Remove long environment variables? */ :#ifndef REMOVE_LONG_ENV :#define REMOVE_LONG_ENV 1 :#endif : :/* : * Disallow stdout or stderr as pipes? It's possible to block the X server : * when piping stdout+stderr to a pipe. : * : * Don't enable this because it looks like it's going to cause problems. : */ :#ifndef NO_OUTPUT_PIPES :#define NO_OUTPUT_PIPES 0 :#endif : : :/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */ :#ifndef CHECK_EUID :#ifndef WIN32 :#define CHECK_EUID 1 :#else :#define CHECK_EUID 0 :#endif :#endif : :/* : * Maybe the locale can be faked to make isprint(3) report that everything : * is printable? Avoid it by default. : */ :#ifndef USE_ISPRINT :#define USE_ISPRINT 0 :#endif : :#define MAX_ARG_LENGTH 128 :#define MAX_ENV_LENGTH 256 :#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */ : :#if USE_ISPRINT :#include :#define checkPrintable(c) isprint(c) :#else :#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f) :#endif : :enum BadCode { : NotBad = 0, : UnsafeArg, : ArgTooLong, : UnprintableArg, : EnvTooLong, : OutputIsPipe, : InternalError :}; : :#if defined(VENDORSUPPORT) :#define BUGADDRESS VENDORSUPPORT :#elif defined(BUILDERADDR) :#define BUGADDRESS BUILDERADDR :#else :#define BUGADDRESS "xorg@freedesktop.org" :#endif : :#define ARGMSG \ : "\nIf the arguments used are valid, and have been rejected incorrectly\n" \ : "please send details of the arguments and why they are valid to\n" \ : "%s. In the meantime, you can start the Xserver as\n" \ : "the \"super user\" (root).\n" : :#define ENVMSG \ : "\nIf the environment is valid, and have been rejected incorrectly\n" \ : "please send details of the environment and why it is valid to\n" \ : "%s. In the meantime, you can start the Xserver as\n" \ : "the \"super user\" (root).\n" : :void :CheckUserParameters(int argc, char **argv, char **envp) :{ : enum BadCode bad = NotBad; : int i = 0, j; : char *a, *e = NULL; :#if defined(__QNX__) && !defined(__QNXNTO__) : char cmd_name[64]; :#endif : :#if CHECK_EUID : if (geteuid() == 0 && getuid() != geteuid()) :#endif : { : /* Check each argv[] */ : for (i = 1; i < argc; i++) { : if (strcmp(argv[i], "-fp") == 0) : { : i++; /* continue with next argument. skip the length check */ : if (i >= argc) : break; : } else : { : if (strlen(argv[i]) > MAX_ARG_LENGTH) { : bad = ArgTooLong; : break; : } : } : a = argv[i]; : while (*a) { : if (checkPrintable(*a) == 0) { : bad = UnprintableArg; : break; : } : a++; : } : if (bad) : break; : } : if (!bad) { : /* Check each envp[] */ : for (i = 0; envp[i]; i++) { : : /* Check for bad environment variables and values */ :#if REMOVE_ENV_LD : while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) { :#ifdef ENVDEBUG : ErrorF("CheckUserParameters: removing %s from the " : "environment\n", strtok(envp[i], "=")); :#endif : for (j = i; envp[j]; j++) { : envp[j] = envp[j+1]; : } : } :#endif : if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) { :#if REMOVE_LONG_ENV :#ifdef ENVDEBUG : ErrorF("CheckUserParameters: removing %s from the " : "environment\n", strtok(envp[i], "=")); :#endif : for (j = i; envp[j]; j++) { : envp[j] = envp[j+1]; : } : i--; :#else : char *eq; : int len; : : eq = strchr(envp[i], '='); : if (!eq) : continue; : len = eq - envp[i]; : e = malloc(len + 1); : if (!e) { : bad = InternalError; : break; : } : strncpy(e, envp[i], len); : e[len] = 0; : if (len >= 4 && : (strcmp(e + len - 4, "PATH") == 0 || : strcmp(e, "TERMCAP") == 0)) { : if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) { : bad = EnvTooLong; : break; : } else { : free(e); : } : } else { : bad = EnvTooLong; : break; : } :#endif : } : } : } :#if NO_OUTPUT_PIPES : if (!bad) { : struct stat buf; : : if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode)) : bad = OutputIsPipe; : if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode)) : bad = OutputIsPipe; : } :#endif : } : switch (bad) { : case NotBad: : return; : case UnsafeArg: : ErrorF("Command line argument number %d is unsafe\n", i); : ErrorF(ARGMSG, BUGADDRESS); : break; : case ArgTooLong: : ErrorF("Command line argument number %d is too long\n", i); : ErrorF(ARGMSG, BUGADDRESS); : break; : case UnprintableArg: : ErrorF("Command line argument number %d contains unprintable" : " characters\n", i); : ErrorF(ARGMSG, BUGADDRESS); : break; : case EnvTooLong: : ErrorF("Environment variable `%s' is too long\n", e); : ErrorF(ENVMSG, BUGADDRESS); : break; : case OutputIsPipe: : ErrorF("Stdout and/or stderr is a pipe\n"); : break; : case InternalError: : ErrorF("Internal Error\n"); : break; : default: : ErrorF("Unknown error\n"); : ErrorF(ARGMSG, BUGADDRESS); : ErrorF(ENVMSG, BUGADDRESS); : break; : } : FatalError("X server aborted because of unsafe environment\n"); :} : :/* : * CheckUserAuthorization: check if the user is allowed to start the : * X server. This usually means some sort of PAM checking, and it is : * usually only done for setuid servers (uid != euid). : */ : :#ifdef USE_PAM :#include :#include :#include :#endif /* USE_PAM */ : :void :CheckUserAuthorization(void) :{ :#ifdef USE_PAM : static struct pam_conv conv = { : misc_conv, : NULL : }; : : pam_handle_t *pamh = NULL; : struct passwd *pw; : int retval; : : if (getuid() != geteuid()) { : pw = getpwuid(getuid()); : if (pw == NULL) : FatalError("getpwuid() failed for uid %d\n", getuid()); : : retval = pam_start("xserver", pw->pw_name, &conv, &pamh); : if (retval != PAM_SUCCESS) : FatalError("pam_start() failed.\n" : "\tMissing or mangled PAM config file or module?\n"); : : retval = pam_authenticate(pamh, 0); : if (retval != PAM_SUCCESS) { : pam_end(pamh, retval); : FatalError("PAM authentication failed, cannot start X server.\n" : "\tPerhaps you do not have console ownership?\n"); : } : : retval = pam_acct_mgmt(pamh, 0); : if (retval != PAM_SUCCESS) { : pam_end(pamh, retval); : FatalError("PAM authentication failed, cannot start X server.\n" : "\tPerhaps you do not have console ownership?\n"); : } : : /* this is not a session, so do not do session management */ : pam_end(pamh, PAM_SUCCESS); : } :#endif :} : :#ifdef __SCO__ :#include : :static void :lockit (int fd, short what) :{ : struct flock lck; : : lck.l_whence = 0; : lck.l_start = 0; : lck.l_len = 1; : lck.l_type = what; : : (void)fcntl (fd, F_SETLKW, &lck); :} : :/* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */ :ssize_t :pread (int fd, void *buf, size_t nbytes, off_t offset) :{ : off_t saved; : ssize_t ret; : : lockit (fd, F_RDLCK); : saved = lseek (fd, 0, SEEK_CUR); : lseek (fd, offset, SEEK_SET); : ret = read (fd, buf, nbytes); : lseek (fd, saved, SEEK_SET); : lockit (fd, F_UNLCK); : : return ret; :} : :ssize_t :pwrite (int fd, const void *buf, size_t nbytes, off_t offset) :{ : off_t saved; : ssize_t ret; : : lockit (fd, F_WRLCK); : saved = lseek (fd, 0, SEEK_CUR); : lseek (fd, offset, SEEK_SET); : ret = write (fd, buf, nbytes); : lseek (fd, saved, SEEK_SET); : lockit (fd, F_UNLCK); : : return ret; :} :#endif /* __SCO__ */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbpixmap.c" * * 21 0.0229 */ :/* : * Copyright © 1998 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include : :#include "fb.h" : :PixmapPtr :fbCreatePixmapBpp (ScreenPtr pScreen, int width, int height, int depth, int bpp) :{ /* fbCreatePixmapBpp total: 10 0.0109 */ : PixmapPtr pPixmap; : size_t datasize; : size_t paddedWidth; : int adjust; : int base; : 1 0.0011 : paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits); : if (paddedWidth / 4 > 32767 || height > 32767) : return NullPixmap; : datasize = height * paddedWidth; 1 0.0011 : base = pScreen->totalPixmapSize; : adjust = 0; 1 0.0011 : if (base & 7) : adjust = 8 - (base & 7); : datasize += adjust; :#ifdef FB_DEBUG : datasize += 2 * paddedWidth; :#endif 1 0.0011 : pPixmap = AllocatePixmap(pScreen, datasize); : if (!pPixmap) : return NullPixmap; : pPixmap->drawable.type = DRAWABLE_PIXMAP; : pPixmap->drawable.class = 0; : pPixmap->drawable.pScreen = pScreen; : pPixmap->drawable.depth = depth; : pPixmap->drawable.bitsPerPixel = bpp; : pPixmap->drawable.id = 0; 2 0.0022 : pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; : pPixmap->drawable.x = 0; : pPixmap->drawable.y = 0; : pPixmap->drawable.width = width; 1 0.0011 : pPixmap->drawable.height = height; : pPixmap->devKind = paddedWidth; : pPixmap->refcnt = 1; 2 0.0022 : pPixmap->devPrivate.ptr = (pointer) ((char *)pPixmap + base + adjust); :#ifdef FB_DEBUG : pPixmap->devPrivate.ptr = (void *) ((char *) pPixmap->devPrivate.ptr + paddedWidth); : fbInitializeDrawable (&pPixmap->drawable); :#endif : :#ifdef COMPOSITE : pPixmap->screen_x = 0; : pPixmap->screen_y = 0; :#endif : : return pPixmap; 1 0.0011 :} : :PixmapPtr :fbCreatePixmap (ScreenPtr pScreen, int width, int height, int depth) 2 0.0022 :{ /* fbCreatePixmap total: 10 0.0109 */ : int bpp; 4 0.0044 : bpp = BitsPerPixel (depth); :#ifdef FB_SCREEN_PRIVATE 1 0.0011 : if (bpp == 32 && depth <= 24) : bpp = fbGetScreenPrivate(pScreen)->pix32bpp; :#endif 2 0.0022 : return fbCreatePixmapBpp (pScreen, width, height, depth, bpp); 1 0.0011 :} : :Bool :fbDestroyPixmap (PixmapPtr pPixmap) 1 0.0011 :{ /* fbDestroyPixmap total: 1 0.0011 */ : if(--pPixmap->refcnt) : return TRUE; : xfree(pPixmap); : return TRUE; :} : :#define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \ :if (((rx1) < (rx2)) && ((ry1) < (ry2)) && \ : (!((reg)->data->numRects && \ : ((r-1)->y1 == (ry1)) && \ : ((r-1)->y2 == (ry2)) && \ : ((r-1)->x1 <= (rx1)) && \ : ((r-1)->x2 >= (rx2))))) \ :{ \ : if ((reg)->data->numRects == (reg)->data->size) \ : { \ : miRectAlloc(reg, 1); \ : fr = REGION_BOXPTR(reg); \ : r = fr + (reg)->data->numRects; \ : } \ : r->x1 = (rx1); \ : r->y1 = (ry1); \ : r->x2 = (rx2); \ : r->y2 = (ry2); \ : (reg)->data->numRects++; \ : if(r->x1 < (reg)->extents.x1) \ : (reg)->extents.x1 = r->x1; \ : if(r->x2 > (reg)->extents.x2) \ : (reg)->extents.x2 = r->x2; \ : r++; \ :} : :/* Convert bitmap clip mask into clipping region. : * First, goes through each line and makes boxes by noting the transitions : * from 0 to 1 and 1 to 0. : * Then it coalesces the current line with the previous if they have boxes : * at the same X coordinates. : */ :RegionPtr :fbPixmapToRegion(PixmapPtr pPix) :{ : register RegionPtr pReg; : FbBits *pw, w; : register int ib; : int width, h, base, rx1 = 0, crects; : FbBits *pwLineEnd; : int irectPrevStart, irectLineStart; : register BoxPtr prectO, prectN; : BoxPtr FirstRect, rects, prectLineStart; : Bool fInBox, fSame; : register FbBits mask0 = FB_ALLONES & ~FbScrRight(FB_ALLONES, 1); : FbBits *pwLine; : int nWidth; : : pReg = REGION_CREATE(pPix->drawable.pScreen, NULL, 1); : if(!pReg) : return NullRegion; : FirstRect = REGION_BOXPTR(pReg); : rects = FirstRect; : : fbPrepareAccess(&pPix->drawable); : : pwLine = (FbBits *) pPix->devPrivate.ptr; : nWidth = pPix->devKind >> (FB_SHIFT-3); : : width = pPix->drawable.width; : pReg->extents.x1 = width - 1; : pReg->extents.x2 = 0; : irectPrevStart = -1; : for(h = 0; h < pPix->drawable.height; h++) : { : pw = pwLine; : pwLine += nWidth; : irectLineStart = rects - FirstRect; : /* If the Screen left most bit of the word is set, we're starting in : * a box */ : if(READ(pw) & mask0) : { : fInBox = TRUE; : rx1 = 0; : } : else : fInBox = FALSE; : /* Process all words which are fully in the pixmap */ : pwLineEnd = pw + (width >> FB_SHIFT); : for (base = 0; pw < pwLineEnd; base += FB_UNIT) : { : w = READ(pw++); : if (fInBox) : { : if (!~w) : continue; : } : else : { : if (!w) : continue; : } : for(ib = 0; ib < FB_UNIT; ib++) : { : /* If the Screen left most bit of the word is set, we're : * starting a box */ : if(w & mask0) : { : if(!fInBox) : { : rx1 = base + ib; : /* start new box */ : fInBox = TRUE; : } : } : else : { : if(fInBox) : { : /* end box */ : ADDRECT(pReg, rects, FirstRect, : rx1, h, base + ib, h + 1); : fInBox = FALSE; : } : } : /* Shift the word VISUALLY left one. */ : w = FbScrLeft(w, 1); : } : } : if(width & FB_MASK) : { : /* Process final partial word on line */ : w = READ(pw++); : for(ib = 0; ib < (width & FB_MASK); ib++) : { : /* If the Screen left most bit of the word is set, we're : * starting a box */ : if(w & mask0) : { : if(!fInBox) : { : rx1 = base + ib; : /* start new box */ : fInBox = TRUE; : } : } : else : { : if(fInBox) : { : /* end box */ : ADDRECT(pReg, rects, FirstRect, : rx1, h, base + ib, h + 1); : fInBox = FALSE; : } : } : /* Shift the word VISUALLY left one. */ : w = FbScrLeft(w, 1); : } : } : /* If scanline ended with last bit set, end the box */ : if(fInBox) : { : ADDRECT(pReg, rects, FirstRect, : rx1, h, base + (width & FB_MASK), h + 1); : } : /* if all rectangles on this line have the same x-coords as : * those on the previous line, then add 1 to all the previous y2s and : * throw away all the rectangles from this line : */ : fSame = FALSE; : if(irectPrevStart != -1) : { : crects = irectLineStart - irectPrevStart; : if(crects == ((rects - FirstRect) - irectLineStart)) : { : prectO = FirstRect + irectPrevStart; : prectN = prectLineStart = FirstRect + irectLineStart; : fSame = TRUE; : while(prectO < prectLineStart) : { : if((prectO->x1 != prectN->x1) || (prectO->x2 != prectN->x2)) : { : fSame = FALSE; : break; : } : prectO++; : prectN++; : } : if (fSame) : { : prectO = FirstRect + irectPrevStart; : while(prectO < prectLineStart) : { : prectO->y2 += 1; : prectO++; : } : rects -= crects; : pReg->data->numRects -= crects; : } : } : } : if(!fSame) : irectPrevStart = irectLineStart; : } : if (!pReg->data->numRects) : pReg->extents.x1 = pReg->extents.x2 = 0; : else : { : pReg->extents.y1 = REGION_BOXPTR(pReg)->y1; : pReg->extents.y2 = REGION_END(pReg)->y2; : if (pReg->data->numRects == 1) : { : xfree(pReg->data); : pReg->data = (RegDataPtr)NULL; : } : } : : fbFinishAccess(&pPix->drawable); :#ifdef DEBUG : if (!miValidRegion(pReg)) : FatalError("Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); :#endif : return(pReg); :} : :#ifdef FB_DEBUG : :#ifndef WIN32 :#include :#else :#include :#endif : :static Bool :fbValidateBits (FbStip *bits, int stride, FbStip data) :{ : while (stride--) : { : if (*bits != data) : { :#ifdef WIN32 : NCD_DEBUG ((DEBUG_FAILURE, "fdValidateBits failed at 0x%x (is 0x%x want 0x%x)", : bits, *bits, data)); :#else : fprintf (stderr, "fbValidateBits failed\n"); :#endif : return FALSE; : } : bits++; : } :} : :void :fbValidateDrawable (DrawablePtr pDrawable) :{ : FbStip *bits, *first, *last; : int stride, bpp; : int xoff, yoff; : int height; : Bool failed; : : if (pDrawable->type != DRAWABLE_PIXMAP) : pDrawable = (DrawablePtr) fbGetWindowPixmap(pDrawable); : fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff); : first = bits - stride; : last = bits + stride * pDrawable->height; : if (!fbValidateBits (first, stride, FB_HEAD_BITS) || : !fbValidateBits (last, stride, FB_TAIL_BITS)) : fbInitializeDrawable(pDrawable); : fbFinishAccess (pDrawable); :} : :void :fbSetBits (FbStip *bits, int stride, FbStip data) :{ : while (stride--) : *bits++ = data; :} : :void :fbInitializeDrawable (DrawablePtr pDrawable) :{ : FbStip *bits, *first, *last; : int stride, bpp; : int xoff, yoff; : : fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff); : first = bits - stride; : last = bits + stride * pDrawable->height; : fbSetBits (first, stride, FB_HEAD_BITS); : fbSetBits (last, stride, FB_TAIL_BITS); : fbFinishAccess (pDrawable); :} :#endif /* FB_DEBUG */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/render/miglyph.c" * * 16 0.0174 */ :/* : * : * Copyright © 2000 SuSE, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of SuSE not be used in advertising or : * publicity pertaining to distribution of the software without specific, : * written prior permission. SuSE makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : * : * Author: Keith Packard, SuSE, Inc. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "scrnintstr.h" :#include "gcstruct.h" :#include "pixmapstr.h" :#include "windowstr.h" :#include "mi.h" :#include "picturestr.h" :#include "mipict.h" : :Bool :miRealizeGlyph (ScreenPtr pScreen, : GlyphPtr glyph) :{ : return TRUE; :} : :void :miUnrealizeGlyph (ScreenPtr pScreen, : GlyphPtr glyph) :{ :} : :_X_EXPORT void :miGlyphExtents (int nlist, : GlyphListPtr list, : GlyphPtr *glyphs, : BoxPtr extents) 2 0.0022 :{ /* miGlyphExtents total: 16 0.0174 */ : int x1, x2, y1, y2; : int n; : GlyphPtr glyph; : int x, y; : : x = 0; : y = 0; : extents->x1 = MAXSHORT; : extents->x2 = MINSHORT; : extents->y1 = MAXSHORT; : extents->y2 = MINSHORT; : while (nlist--) : { : x += list->xOff; : y += list->yOff; : n = list->len; : list++; : while (n--) : { : glyph = *glyphs++; 1 0.0011 : x1 = x - glyph->info.x; : if (x1 < MINSHORT) : x1 = MINSHORT; 5 0.0054 : y1 = y - glyph->info.y; : if (y1 < MINSHORT) : y1 = MINSHORT; 2 0.0022 : x2 = x1 + glyph->info.width; : if (x2 > MAXSHORT) : x2 = MAXSHORT; : y2 = y1 + glyph->info.height; : if (y2 > MAXSHORT) : y2 = MAXSHORT; : if (x1 < extents->x1) : extents->x1 = x1; : if (x2 > extents->x2) : extents->x2 = x2; 4 0.0044 : if (y1 < extents->y1) : extents->y1 = y1; 1 0.0011 : if (y2 > extents->y2) : extents->y2 = y2; : x += glyph->info.xOff; 1 0.0011 : y += glyph->info.yOff; : } : } :} : :#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) : :_X_EXPORT void :miGlyphs (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int nlist, : GlyphListPtr list, : GlyphPtr *glyphs) :{ : PixmapPtr pPixmap = 0; : PicturePtr pPicture; : PixmapPtr pMaskPixmap = 0; : PicturePtr pMask; : ScreenPtr pScreen = pDst->pDrawable->pScreen; : int width = 0, height = 0; : int x, y; : int xDst = list->xOff, yDst = list->yOff; : int n; : GlyphPtr glyph; : int error; : BoxRec extents; : CARD32 component_alpha; : : if (maskFormat) : { : GCPtr pGC; : xRectangle rect; : : miGlyphExtents (nlist, list, glyphs, &extents); : : if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) : return; : width = extents.x2 - extents.x1; : height = extents.y2 - extents.y1; : pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth); : if (!pMaskPixmap) : return; : component_alpha = NeedsComponent(maskFormat->format); : pMask = CreatePicture (0, &pMaskPixmap->drawable, : maskFormat, CPComponentAlpha, &component_alpha, : serverClient, &error); : if (!pMask) : { : (*pScreen->DestroyPixmap) (pMaskPixmap); : return; : } : pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); : ValidateGC (&pMaskPixmap->drawable, pGC); : rect.x = 0; : rect.y = 0; : rect.width = width; : rect.height = height; : (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); : FreeScratchGC (pGC); : x = -extents.x1; : y = -extents.y1; : } : else : { : pMask = pDst; : x = 0; : y = 0; : } : pPicture = 0; : while (nlist--) : { : x += list->xOff; : y += list->yOff; : n = list->len; : while (n--) : { : glyph = *glyphs++; : if (!pPicture) : { : pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, : list->format->depth, : list->format->depth, : 0, (pointer) (glyph + 1)); : if (!pPixmap) : return; : component_alpha = NeedsComponent(list->format->format); : pPicture = CreatePicture (0, &pPixmap->drawable, list->format, : CPComponentAlpha, &component_alpha, : serverClient, &error); : if (!pPicture) : { : FreeScratchPixmapHeader (pPixmap); : return; : } : } : (*pScreen->ModifyPixmapHeader) (pPixmap, : glyph->info.width, glyph->info.height, : 0, 0, -1, (pointer) (glyph + 1)); : pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; : if (maskFormat) : { : CompositePicture (PictOpAdd, : pPicture, : None, : pMask, : 0, 0, : 0, 0, : x - glyph->info.x, : y - glyph->info.y, : glyph->info.width, : glyph->info.height); : } : else : { : CompositePicture (op, : pSrc, : pPicture, : pDst, : xSrc + (x - glyph->info.x) - xDst, : ySrc + (y - glyph->info.y) - yDst, : 0, 0, : x - glyph->info.x, : y - glyph->info.y, : glyph->info.width, : glyph->info.height); : } : x += glyph->info.xOff; : y += glyph->info.yOff; : } : list++; : if (pPicture) : { : FreeScratchPixmapHeader (pPixmap); : FreePicture ((pointer) pPicture, 0); : pPicture = 0; : pPixmap = 0; : } : } : if (maskFormat) : { : x = extents.x1; : y = extents.y1; : CompositePicture (op, : pSrc, : pMask, : pDst, : xSrc + x - xDst, : ySrc + y - yDst, : 0, 0, : x, y, : width, height); : FreePicture ((pointer) pMask, (XID) 0); : (*pScreen->DestroyPixmap) (pMaskPixmap); : } :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/dix/pixmap.c" * * 16 0.0174 */ :/* : :Copyright 1993, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included :in all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR :OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall :not be used in advertising or otherwise to promote the sale, use or :other dealings in this Software without prior written authorization :from The Open Group. : :*/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include "scrnintstr.h" :#include "misc.h" :#include "os.h" :#include "windowstr.h" :#include "resource.h" :#include "dixstruct.h" :#include "gcstruct.h" :#include "servermd.h" :#include "site.h" : : :/* : * Scratch pixmap management and device independent pixmap allocation : * function. : */ : : :/* callable by ddx */ :_X_EXPORT PixmapPtr :GetScratchPixmapHeader(ScreenPtr pScreen, int width, int height, int depth, : int bitsPerPixel, int devKind, pointer pPixData) 1 0.0011 :{ /* GetScratchPixmapHeader total: 1 0.0011 */ : PixmapPtr pPixmap = pScreen->pScratchPixmap; : : if (pPixmap) : pScreen->pScratchPixmap = NULL; : else : /* width and height of 0 means don't allocate any pixmap data */ : pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth); : : if (pPixmap) { : if ((*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, : bitsPerPixel, devKind, pPixData)) : return pPixmap; : (*pScreen->DestroyPixmap)(pPixmap); : } : return NullPixmap; :} : : :/* callable by ddx */ :_X_EXPORT void :FreeScratchPixmapHeader(PixmapPtr pPixmap) 1 0.0011 :{ /* FreeScratchPixmapHeader total: 2 0.0022 */ : if (pPixmap) : { : ScreenPtr pScreen = pPixmap->drawable.pScreen; : : pPixmap->devPrivate.ptr = NULL; /* lest ddx chases bad ptr */ : if (pScreen->pScratchPixmap) : (*pScreen->DestroyPixmap)(pPixmap); : else : pScreen->pScratchPixmap = pPixmap; : } 1 0.0011 :} : : :Bool :CreateScratchPixmapsForScreen(int scrnum) :{ : /* let it be created on first use */ : screenInfo.screens[scrnum]->pScratchPixmap = NULL; : return TRUE; :} : : :void :FreeScratchPixmapsForScreen(int scrnum) :{ : FreeScratchPixmapHeader(screenInfo.screens[scrnum]->pScratchPixmap); :} : : :/* callable by ddx */ :_X_EXPORT PixmapPtr :AllocatePixmap(ScreenPtr pScreen, int pixDataSize) 3 0.0033 :{ /* AllocatePixmap total: 13 0.0142 */ : PixmapPtr pPixmap; : char *ptr; : DevUnion *ppriv; : unsigned *sizes; : unsigned size; : int i; : : if (pScreen->totalPixmapSize > ((size_t)-1) - pixDataSize) : return NullPixmap; : : pPixmap = (PixmapPtr)xalloc(pScreen->totalPixmapSize + pixDataSize); : if (!pPixmap) : return NullPixmap; : ppriv = (DevUnion *)(pPixmap + 1); : pPixmap->devPrivates = ppriv; : sizes = pScreen->PixmapPrivateSizes; 1 0.0011 : ptr = (char *)(ppriv + pScreen->PixmapPrivateLen); 1 0.0011 : for (i = pScreen->PixmapPrivateLen; --i >= 0; ppriv++, sizes++) : { 2 0.0022 : if ((size = *sizes) != 0) : { 1 0.0011 : ppriv->ptr = (pointer)ptr; 1 0.0011 : ptr += size; : } : else 2 0.0022 : ppriv->ptr = (pointer)NULL; : } : :#ifdef _XSERVER64 : if (pPixmap) { : pPixmap->drawable.pad0 = 0; : pPixmap->drawable.pad1 = 0; : } :#endif : : return pPixmap; 2 0.0022 :} /* * Total samples for file : "fbpseudocolor.c" * * 14 0.0153 */ 14 0.0153 : /* __i686.get_pc_thunk.cx total: 2 0.0022 */ /* __i686.get_pc_thunk.bx total: 12 0.0131 */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/render/mitrap.c" * * 12 0.0131 */ :/* : * : * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "scrnintstr.h" :#include "gcstruct.h" :#include "pixmapstr.h" :#include "windowstr.h" :#include "servermd.h" :#include "mi.h" :#include "picturestr.h" :#include "mipict.h" : :PicturePtr :miCreateAlphaPicture (ScreenPtr pScreen, : PicturePtr pDst, : PictFormatPtr pPictFormat, : CARD16 width, : CARD16 height) :{ : PixmapPtr pPixmap; : PicturePtr pPicture; : GCPtr pGC; : int error; : xRectangle rect; : : if (width > 32767 || height > 32767) : return 0; : : if (!pPictFormat) : { : if (pDst->polyEdge == PolyEdgeSharp) : pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); : else : pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); : if (!pPictFormat) : return 0; : } : : pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, : pPictFormat->depth); : if (!pPixmap) : return 0; : pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); : if (!pGC) : { : (*pScreen->DestroyPixmap) (pPixmap); : return 0; : } : ValidateGC (&pPixmap->drawable, pGC); : rect.x = 0; : rect.y = 0; : rect.width = width; : rect.height = height; : (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); : FreeScratchGC (pGC); : pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, : 0, 0, serverClient, &error); : (*pScreen->DestroyPixmap) (pPixmap); : return pPicture; :} : :static xFixed :miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) :{ /* miLineFixedX total: 8 0.0087 */ : xFixed dx = l->p2.x - l->p1.x; 1 0.0011 : xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; 1 0.0011 : xFixed dy = l->p2.y - l->p1.y; : if (ceil) 4 0.0044 : ex += (dy - 1); : return l->p1.x + (xFixed) (ex / dy); 2 0.0022 :} : :void :miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) :{ /* miTrapezoidBounds total: 3 0.0033 */ : box->y1 = MAXSHORT; : box->y2 = MINSHORT; : box->x1 = MAXSHORT; : box->x2 = MINSHORT; : for (; ntrap; ntrap--, traps++) : { : INT16 x1, y1, x2, y2; : : if (!xTrapezoidValid(traps)) : continue; : y1 = xFixedToInt (traps->top); : if (y1 < box->y1) : box->y1 = y1; : : y2 = xFixedToInt (xFixedCeil (traps->bottom)); : if (y2 > box->y2) : box->y2 = y2; : : x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), : miLineFixedX (&traps->left, traps->bottom, FALSE))); : if (x1 < box->x1) : box->x1 = x1; : 3 0.0033 : x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), : miLineFixedX (&traps->right, traps->bottom, TRUE)))); : if (x2 > box->x2) : box->x2 = x2; : } :} : :void :miTrapezoids (CARD8 op, : PicturePtr pSrc, : PicturePtr pDst, : PictFormatPtr maskFormat, : INT16 xSrc, : INT16 ySrc, : int ntrap, : xTrapezoid *traps) :{ /* miTrapezoids total: 1 0.0011 */ : ScreenPtr pScreen = pDst->pDrawable->pScreen; : PictureScreenPtr ps = GetPictureScreen(pScreen); : : /* : * Check for solid alpha add : */ : if (op == PictOpAdd && miIsSolidAlpha (pSrc)) : { : for (; ntrap; ntrap--, traps++) : (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); : } : else if (maskFormat) : { : PicturePtr pPicture; : BoxRec bounds; : INT16 xDst, yDst; : INT16 xRel, yRel; : : xDst = traps[0].left.p1.x >> 16; : yDst = traps[0].left.p1.y >> 16; : : miTrapezoidBounds (ntrap, traps, &bounds); : if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) : return; : pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, : bounds.x2 - bounds.x1, : bounds.y2 - bounds.y1); : if (!pPicture) : return; 1 0.0011 : for (; ntrap; ntrap--, traps++) : (*ps->RasterizeTrapezoid) (pPicture, traps, : -bounds.x1, -bounds.y1); : xRel = bounds.x1 + xSrc - xDst; : yRel = bounds.y1 + ySrc - yDst; : CompositePicture (op, pSrc, pPicture, pDst, : xRel, yRel, 0, 0, bounds.x1, bounds.y1, : bounds.x2 - bounds.x1, : bounds.y2 - bounds.y1); : FreePicture (pPicture, 0); : } : else : { : if (pDst->polyEdge == PolyEdgeSharp) : maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); : else : maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); : for (; ntrap; ntrap--, traps++) : miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); : } :} /* * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-image.c" * * 10 0.0109 */ :/* : * Copyright © 2000 SuSE, Inc. : * Copyright © 2007 Red Hat, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of SuSE not be used in advertising or : * publicity pertaining to distribution of the software without specific, : * written prior permission. SuSE makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : */ : :#include : :#include :#include :#include : :#include "pixman.h" :#include "pixman-private.h" : :static void :init_source_image (source_image_t *image) :{ : image->class = SOURCE_IMAGE_CLASS_UNKNOWN; :} : :static pixman_bool_t :init_gradient (gradient_t *gradient, : const pixman_gradient_stop_t *stops, : int n_stops) :{ : return_val_if_fail (n_stops > 0, FALSE); : : init_source_image (&gradient->common); : : gradient->stops = malloc (n_stops * sizeof (pixman_gradient_stop_t)); : if (!gradient->stops) : return FALSE; : : memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t)); : : gradient->n_stops = n_stops; : : gradient->stop_range = 0xffff; : gradient->color_table = NULL; : gradient->color_table_size = 0; : : return TRUE; :} : :static uint32_t :color_to_uint32 (const pixman_color_t *color) :{ : return : (color->alpha >> 8 << 24) | : (color->red >> 8 << 16) | : (color->green & 0xff00) | : (color->blue >> 8); :} : :static pixman_image_t *image_cache; : :static pixman_image_t * :new_image (void) :{ : pixman_image_t *image; : : if (image_cache) : { : image = image_cache; : image_cache = image->next; : } : else : { : image = malloc (sizeof (pixman_image_t)); : } : : return image; :} : :static void :delete_image (pixman_image_t *image) :{ : image->next = image_cache; : image_cache = image; :} : :static pixman_image_t * :allocate_image (void) :{ /* allocate_image total: 7 0.0076 */ : pixman_image_t *image = new_image(); : : if (image) : { : image_common_t *common = &image->common; : : pixman_region_init (&common->full_region); 1 0.0011 : pixman_region_init (&common->clip_region); : common->src_clip = &common->full_region; : common->has_client_clip = FALSE; : common->transform = NULL; : common->repeat = PIXMAN_REPEAT_NONE; : common->filter = PIXMAN_FILTER_NEAREST; : common->filter_params = NULL; 1 0.0011 : common->n_filter_params = 0; 1 0.0011 : common->alpha_map = NULL; : common->component_alpha = FALSE; 1 0.0011 : common->ref_count = 1; : common->read_func = NULL; 1 0.0011 : common->write_func = NULL; : } : : return image; 2 0.0022 :} : :/* Ref Counting */ :pixman_image_t * :pixman_image_ref (pixman_image_t *image) :{ : image->common.ref_count++; : : return image; :} : :void :pixman_image_unref (pixman_image_t *image) 1 0.0011 :{ /* pixman_image_unref total: 2 0.0022 */ : image_common_t *common = (image_common_t *)image; : : common->ref_count--; : : if (common->ref_count == 0) : { : pixman_region_fini (&common->clip_region); : pixman_region_fini (&common->full_region); : : if (common->transform) : free (common->transform); : : if (common->filter_params) : free (common->filter_params); : : if (common->alpha_map) : pixman_image_unref ((pixman_image_t *)common->alpha_map); : :#if 0 : if (image->type == BITS && image->bits.indexed) : free (image->bits.indexed); :#endif : :#if 0 : memset (image, 0xaa, sizeof (pixman_image_t)); :#endif : if (image->type == LINEAR || image->type == RADIAL || image->type == CONICAL) : { : if (image->gradient.stops) : free (image->gradient.stops); : } : : : if (image->type == BITS && image->bits.free_me) : free (image->bits.free_me); : : delete_image (image); : } :} : :/* Constructors */ :pixman_image_t * :pixman_image_create_solid_fill (pixman_color_t *color) :{ : pixman_image_t *img = allocate_image(); : if (!img) : return NULL; : : init_source_image (&img->solid.common); : : img->type = SOLID; : img->solid.color = color_to_uint32 (color); : : return img; :} : :pixman_image_t * :pixman_image_create_linear_gradient (pixman_point_fixed_t *p1, : pixman_point_fixed_t *p2, : const pixman_gradient_stop_t *stops, : int n_stops) :{ : pixman_image_t *image; : linear_gradient_t *linear; : : return_val_if_fail (n_stops >= 2, NULL); : : image = allocate_image(); : : if (!image) : return NULL; : : linear = &image->linear; : : if (!init_gradient (&linear->common, stops, n_stops)) : { : free (image); : return NULL; : } : : linear->p1 = *p1; : linear->p2 = *p2; : : image->type = LINEAR; : : return image; :} : : :pixman_image_t * :pixman_image_create_radial_gradient (pixman_point_fixed_t *inner, : pixman_point_fixed_t *outer, : pixman_fixed_t inner_radius, : pixman_fixed_t outer_radius, : const pixman_gradient_stop_t *stops, : int n_stops) :{ : pixman_image_t *image; : radial_gradient_t *radial; : : return_val_if_fail (n_stops >= 2, NULL); : : image = allocate_image(); : : if (!image) : return NULL; : : radial = &image->radial; : : if (!init_gradient (&radial->common, stops, n_stops)) : { : free (image); : return NULL; : } : : image->type = RADIAL; : : radial->c1.x = inner->x; : radial->c1.y = inner->y; : radial->c1.radius = inner_radius; : radial->c2.x = outer->x; : radial->c2.y = outer->y; : radial->c2.radius = outer_radius; : radial->cdx = pixman_fixed_to_double (radial->c2.x - radial->c1.x); : radial->cdy = pixman_fixed_to_double (radial->c2.y - radial->c1.y); : radial->dr = pixman_fixed_to_double (radial->c2.radius - radial->c1.radius); : radial->A = (radial->cdx * radial->cdx : + radial->cdy * radial->cdy : - radial->dr * radial->dr); : : return image; :} : :pixman_image_t * :pixman_image_create_conical_gradient (pixman_point_fixed_t *center, : pixman_fixed_t angle, : const pixman_gradient_stop_t *stops, : int n_stops) :{ : pixman_image_t *image = allocate_image(); : conical_gradient_t *conical; : : if (!image) : return NULL; : : conical = &image->conical; : : if (!init_gradient (&conical->common, stops, n_stops)) : { : free (image); : return NULL; : } : : image->type = CONICAL; : conical->center = *center; : conical->angle = angle; : : return image; :} : :static uint32_t * :create_bits (pixman_format_code_t format, : int width, : int height, : int *rowstride_bytes) :{ : int stride; : int buf_size; : int bpp; : : bpp = PIXMAN_FORMAT_BPP (format); : stride = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (uint32_t); : buf_size = height * stride; : : if (rowstride_bytes) : *rowstride_bytes = stride; : : return calloc (buf_size, 1); :} : :static void :reset_clip_region (pixman_image_t *image) :{ : pixman_region_fini (&image->common.clip_region); : : if (image->type == BITS) : { : pixman_region_init_rect (&image->common.clip_region, 0, 0, : image->bits.width, image->bits.height); : } : else : { : pixman_region_init (&image->common.clip_region); : } :} : :pixman_image_t * :pixman_image_create_bits (pixman_format_code_t format, : int width, : int height, : uint32_t *bits, : int rowstride_bytes) 1 0.0011 :{ /* pixman_image_create_bits total: 1 0.0011 */ : pixman_image_t *image; : uint32_t *free_me = NULL; : : /* must be a whole number of uint32_t's : */ : return_val_if_fail (bits == NULL || : (rowstride_bytes % sizeof (uint32_t)) == 0, NULL); : : if (!bits) : { : free_me = bits = create_bits (format, width, height, &rowstride_bytes); : if (!bits) : return NULL; : } : : image = allocate_image(); : : if (!image) : return NULL; : : image->type = BITS; : image->bits.format = format; : image->bits.width = width; : image->bits.height = height; : image->bits.bits = bits; : image->bits.free_me = free_me; : : image->bits.rowstride = rowstride_bytes / sizeof (uint32_t); /* we store it in number : * of uint32_t's : */ : image->bits.indexed = NULL; : : pixman_region_fini (&image->common.full_region); : pixman_region_init_rect (&image->common.full_region, 0, 0, : image->bits.width, image->bits.height); : : reset_clip_region (image); : return image; :} : :pixman_bool_t :pixman_image_set_clip_region (pixman_image_t *image, : pixman_region16_t *region) :{ : image_common_t *common = (image_common_t *)image; : : if (region) : { : return pixman_region_copy (&common->clip_region, region); : } : else : { : reset_clip_region (image); : : return TRUE; : } :} : :/* Sets whether the clip region includes a clip region set by the client : */ :void :pixman_image_set_has_client_clip (pixman_image_t *image, : pixman_bool_t client_clip) :{ : image->common.has_client_clip = client_clip; :} : :pixman_bool_t :pixman_image_set_transform (pixman_image_t *image, : const pixman_transform_t *transform) :{ : static const pixman_transform_t id = : { : { { pixman_fixed_1, 0, 0 }, : { 0, pixman_fixed_1, 0 }, : { 0, 0, pixman_fixed_1 } : } : }; : : image_common_t *common = (image_common_t *)image; : : if (common->transform == transform) : return TRUE; : : if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0) : { : transform = NULL; : return TRUE; : } : : if (common->transform) : free (common->transform); : : if (transform) : { : common->transform = malloc (sizeof (pixman_transform_t)); : if (!common->transform) : return FALSE; : : *common->transform = *transform; : } : else : { : common->transform = NULL; : } : : return TRUE; :} : :void :pixman_image_set_repeat (pixman_image_t *image, : pixman_repeat_t repeat) 1 0.0011 :{ /* pixman_image_set_repeat total: 1 0.0011 */ : image->common.repeat = repeat; :} : :pixman_bool_t :pixman_image_set_filter (pixman_image_t *image, : pixman_filter_t filter, : const pixman_fixed_t *params, : int n_params) :{ : image_common_t *common = (image_common_t *)image; : pixman_fixed_t *new_params; : : if (params == common->filter_params && filter == common->filter) : return TRUE; : : new_params = NULL; : if (params) : { : new_params = malloc (n_params * sizeof (pixman_fixed_t)); : if (!new_params) : return FALSE; : : memcpy (new_params, : params, n_params * sizeof (pixman_fixed_t)); : } : : common->filter = filter; : : if (common->filter_params) : free (common->filter_params); : : common->filter_params = new_params; : common->n_filter_params = n_params; : return TRUE; :} : :/* Unlike all the other property setters, this function does not : * copy the content of indexed. Doing this copying is simply : * way, way too expensive. : */ :void :pixman_image_set_indexed (pixman_image_t *image, : const pixman_indexed_t *indexed) :{ : bits_image_t *bits = (bits_image_t *)image; : : bits->indexed = indexed; :} : :void :pixman_image_set_alpha_map (pixman_image_t *image, : pixman_image_t *alpha_map, : int16_t x, : int16_t y) :{ : image_common_t *common = (image_common_t *)image; : : return_if_fail (!alpha_map || alpha_map->type == BITS); : : if (common->alpha_map != (bits_image_t *)alpha_map) : { : if (common->alpha_map) : pixman_image_unref ((pixman_image_t *)common->alpha_map); : : if (alpha_map) : common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map); : else : common->alpha_map = NULL; : } : : common->alpha_origin.x = x; : common->alpha_origin.y = y; :} : :void :pixman_image_set_component_alpha (pixman_image_t *image, : pixman_bool_t component_alpha) :{ : image->common.component_alpha = component_alpha; :} : : :void :pixman_image_set_accessors (pixman_image_t *image, : pixman_read_memory_func_t read_func, : pixman_write_memory_func_t write_func) :{ : return_if_fail (image != NULL); : : image->common.read_func = read_func; : image->common.write_func = write_func; :} : :uint32_t * :pixman_image_get_data (pixman_image_t *image) :{ : if (image->type == BITS) : return image->bits.bits; : : return NULL; :} : :int :pixman_image_get_width (pixman_image_t *image) :{ : if (image->type == BITS) : return image->bits.width; : : return 0; :} : :int :pixman_image_get_height (pixman_image_t *image) :{ : if (image->type == BITS) : return image->bits.height; : : return 0; :} : :int :pixman_image_get_stride (pixman_image_t *image) :{ : if (image->type == BITS) : return image->bits.rowstride * sizeof (uint32_t); : : return 0; :} : :int :pixman_image_get_depth (pixman_image_t *image) :{ : if (image->type == BITS) : return PIXMAN_FORMAT_DEPTH (image->bits.format); : : return 0; :} : :pixman_bool_t :color_to_pixel (pixman_color_t *color, : uint32_t *pixel, : pixman_format_code_t format) :{ : uint32_t c = color_to_uint32 (color); : : if (!(format == PIXMAN_a8r8g8b8 || : format == PIXMAN_x8r8g8b8 || : format == PIXMAN_a8b8g8r8 || : format == PIXMAN_x8b8g8r8 || : format == PIXMAN_r5g6b5 || : format == PIXMAN_b5g6r5 || : format == PIXMAN_a8)) : { : return FALSE; : } : : if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) : { : c = ((c & 0xff000000) >> 0) | : ((c & 0x00ff0000) >> 16) | : ((c & 0x0000ff00) >> 0) | : ((c & 0x000000ff) << 16); : } : : if (format == PIXMAN_a8) : c = c >> 24; : else if (format == PIXMAN_r5g6b5 || : format == PIXMAN_b5g6r5) : c = cvt8888to0565 (c); : :#if 0 : printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue); : printf ("pixel: %x\n", c); :#endif : : *pixel = c; : return TRUE; :} : :pixman_bool_t :pixman_image_fill_rectangles (pixman_op_t op, : pixman_image_t *dest, : pixman_color_t *color, : int n_rects, : const pixman_rectangle16_t *rects) :{ : pixman_image_t *solid; : pixman_color_t c; : int i; : : if (color->alpha == 0xffff) : { : if (op == PIXMAN_OP_OVER) : op = PIXMAN_OP_SRC; : } : : if (op == PIXMAN_OP_CLEAR) : { : c.red = 0; : c.green = 0; : c.blue = 0; : c.alpha = 0; : : color = &c; : : op = PIXMAN_OP_SRC; : } : : if (op == PIXMAN_OP_SRC) : { : uint32_t pixel; : : if (color_to_pixel (color, &pixel, dest->bits.format)) : { : for (i = 0; i < n_rects; ++i) : { : pixman_region16_t fill_region; : int n_boxes, j; : pixman_box16_t *boxes; : : pixman_region_init_rect (&fill_region, rects[i].x, rects[i].y, rects[i].width, rects[i].height); : pixman_region_intersect (&fill_region, &fill_region, &dest->common.clip_region); : : boxes = pixman_region_rectangles (&fill_region, &n_boxes); : for (j = 0; j < n_boxes; ++j) : { : const pixman_box16_t *box = &(boxes[j]); : pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format), : box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1, : pixel); : } : : pixman_region_fini (&fill_region); : } : return TRUE; : } : } : : solid = pixman_image_create_solid_fill (color); : if (!solid) : return FALSE; : : for (i = 0; i < n_rects; ++i) : { : const pixman_rectangle16_t *rect = &(rects[i]); : : pixman_image_composite (op, solid, NULL, dest, : 0, 0, 0, 0, : rect->x, rect->y, : rect->width, rect->height); : } : : pixman_image_unref (solid); : : return TRUE; :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/mi/mibstore.c" * * 9 0.0098 */ :/*********************************************************** : :Copyright 1987, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987 by the Regents of the University of California : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, provided :that the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation, and that the name The Open Group not be used in advertising or publicity :pertaining to distribution of the software without specific, written prior :permission. : :The University of California makes no representations about the suitability :of this software for any purpose. It is provided "as is" without express or :implied warranty. : :******************************************************************/ : : :#define NEED_EVENTS :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include :#include :#include "misc.h" :#include "regionstr.h" :#include "scrnintstr.h" :#include "gcstruct.h" :#include "windowstr.h" :#include "pixmapstr.h" :#include :#include "dixfontstr.h" :#include "dixstruct.h" /* For requestingClient */ :#include "mi.h" :#include "mibstorest.h" : :/* : * When the server fails to allocate a backing store pixmap, if you want : * it to dynamically retry to allocate backing store on every subsequent : * graphics op, you can enable BSEAGER; otherwise, backing store will be : * disabled on the window until it is unmapped and then remapped. : */ :/* #define BSEAGER */ : :/*- : * NOTES ON USAGE: : * : * The functions in this file implement a machine-independent backing-store : * scheme. To use it, the output library must do the following: : * - Provide a SaveAreas function that takes a destination pixmap, a : * region of the areas to save (in the pixmap's coordinate system) : * and the screen origin of the region. It should copy the areas from : * the screen into the pixmap. : * - Provide a RestoreAreas function that takes a source pixmap, a region : * of the areas to restore (in the screen's coordinate system) and the : * origin of the pixmap on the screen. It should copy the areas from : * the pixmap into the screen. : * - Provide a SetClipmaskRgn function that takes a gc and a region : * and merges the region into any CT_PIXMAP client clip that : * is specified in the GC. This routine is only needed if : * miValidateBackingStore will see CT_PIXMAP clip lists; not : * true for any of the sample servers (which convert the PIXMAP : * clip lists into CT_REGION clip lists; an expensive but simple : * to code option). : * - The function placed in a window's ClearToBackground vector must call : * pScreen->ClearBackingStore with the window, followed by : * the window-relative x and y coordinates, followed by the width and : * height of the area to be cleared, followed by the generateExposures : * flag. This has been taken care of in miClearToBackground. : * - Whatever determines GraphicsExpose events for the CopyArea and : * CopyPlane requests should call pWin->backStorage->ExposeCopy : * with the source and destination drawables, the GC used, a source- : * window-relative region of exposed areas, the source and destination : * coordinates and the bitplane copied, if CopyPlane, or 0, if : * CopyArea. : * : * JUSTIFICATION : * This is a cross between saving everything and just saving the : * obscued areas (as in Pike's layers.) This method has the advantage : * of only doing each output operation once per pixel, visible or : * invisible, and avoids having to do all the crufty storage : * management of keeping several separate rectangles. Since the : * ddx layer ouput primitives are required to draw through clipping : * rectangles anyway, sending multiple drawing requests for each of : * several rectangles isn't necessary. (Of course, it could be argued : * that the ddx routines should just take one rectangle each and : * get called multiple times, but that would make taking advantage of : * smart hardware harder, and probably be slower as well.) : */ : :#define SETUP_BACKING_TERSE(pGC) \ : miBSGCPtr pGCPrivate = (miBSGCPtr)(pGC)->devPrivates[miBSGCIndex].ptr; \ : GCFuncs *oldFuncs = pGC->funcs; : :#define SETUP_BACKING(pDrawable,pGC) \ : miBSWindowPtr pBackingStore = \ : (miBSWindowPtr)((WindowPtr)(pDrawable))->backStorage; \ : DrawablePtr pBackingDrawable = (DrawablePtr) \ : pBackingStore->pBackingPixmap; \ : SETUP_BACKING_TERSE(pGC) \ : GCPtr pBackingGC = pGCPrivate->pBackingGC; : :#define PROLOGUE(pGC) { \ : pGC->ops = pGCPrivate->wrapOps;\ : pGC->funcs = pGCPrivate->wrapFuncs; \ : } : :#define EPILOGUE(pGC) { \ : pGCPrivate->wrapOps = (pGC)->ops; \ : (pGC)->ops = &miBSGCOps; \ : (pGC)->funcs = oldFuncs; \ : } : :static void miCreateBSPixmap(WindowPtr pWin, BoxPtr pExtents); :static void miDestroyBSPixmap(WindowPtr pWin); :static void miTileVirtualBS(WindowPtr pWin); :static void miBSAllocate(WindowPtr pWin), miBSFree(WindowPtr pWin); :static Bool miBSCreateGCPrivate(GCPtr pGC); :static void miBSClearBackingRegion(WindowPtr pWin, RegionPtr pRgn); : :#define MoreCopy0 ; :#define MoreCopy2 *dstCopy++ = *srcCopy++; *dstCopy++ = *srcCopy++; :#define MoreCopy4 MoreCopy2 MoreCopy2 : :#define copyData(src,dst,n,morecopy) \ :{ \ : short *srcCopy = (short *)(src); \ : short *dstCopy = (short *)(dst); \ : int i; \ : int bsx = pBackingStore->x; \ : int bsy = pBackingStore->y; \ : for (i = n; --i >= 0; ) \ : { \ : *dstCopy++ = *srcCopy++ - bsx; \ : *dstCopy++ = *srcCopy++ - bsy; \ : morecopy \ : } \ :} : :#define copyPoints(src,dst,n,mode) \ :if (mode == CoordModeOrigin) \ :{ \ : copyData(src,dst,n,MoreCopy0); \ :} \ :else \ :{ \ : memmove((char *)(dst), (char *)(src), (n) << 2); \ : *((short *)(dst)) -= pBackingStore->x; \ : *((short *)(dst) + 1) -= pBackingStore->y; \ :} : :/* : * wrappers for screen funcs : */ : :static int miBSScreenIndex; :static unsigned long miBSGeneration = 0; : :static Bool miBSCloseScreen(int i, ScreenPtr pScreen); :static void miBSGetImage(DrawablePtr pDrawable, int sx, int sy, : int w, int h, unsigned int format, : unsigned long planemask, char *pdstLine); :static void miBSGetSpans(DrawablePtr pDrawable, int wMax, : DDXPointPtr ppt, int *pwidth, int nspans, : char *pdstStart); :static Bool miBSChangeWindowAttributes(WindowPtr pWin, : unsigned long mask); :static Bool miBSCreateGC(GCPtr pGC); :static Bool miBSDestroyWindow(WindowPtr pWin); : :/* : * backing store screen functions : */ : :static void miBSSaveDoomedAreas(WindowPtr pWin, RegionPtr pObscured, : int dx, int dy); :static RegionPtr miBSRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed); :static void miBSExposeCopy(WindowPtr pSrc, DrawablePtr pDst, : GCPtr pGC, RegionPtr prgnExposed, : int srcx, int srcy, int dstx, int dsty, : unsigned long plane); :static RegionPtr miBSTranslateBackingStore(WindowPtr pWin, int windx, : int windy, RegionPtr oldClip, : int oldx, int oldy); :static RegionPtr miBSClearBackingStore(WindowPtr pWin, int x, int y, : int w, int h, Bool generateExposures); :static void miBSDrawGuarantee(WindowPtr pWin, GCPtr pGC, : int guarantee); : :/* : * wrapper vectors for GC funcs and ops : */ : :static int miBSGCIndex; : :static void miBSValidateGC(GCPtr pGC, unsigned long stateChanges, : DrawablePtr pDrawable); :static void miBSCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); :static void miBSDestroyGC(GCPtr pGC); :static void miBSChangeGC(GCPtr pGC, unsigned long mask); :static void miBSChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects); :static void miBSDestroyClip(GCPtr pGC); :static void miBSCopyClip(GCPtr pgcDst, GCPtr pgcSrc); : :static GCFuncs miBSGCFuncs = { : miBSValidateGC, : miBSChangeGC, : miBSCopyGC, : miBSDestroyGC, : miBSChangeClip, : miBSDestroyClip, : miBSCopyClip, :}; : :static void miBSFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, : DDXPointPtr pptInit, int *pwidthInit, : int fSorted); :static void miBSSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, : DDXPointPtr ppt, int *pwidth, int nspans, : int fSorted); :static void miBSPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, : int x, int y, int w, int h, int leftPad, : int format, char *pBits); :static RegionPtr miBSCopyArea(DrawablePtr pSrc, DrawablePtr pDst, : GCPtr pGC, int srcx, int srcy, int w, int h, : int dstx, int dsty); :static RegionPtr miBSCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, : GCPtr pGC, int srcx, int srcy, int w, int h, : int dstx, int dsty, unsigned long plane); :static void miBSPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, : int npt, xPoint *pptInit); :static void miBSPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, : int npt, DDXPointPtr pptInit); :static void miBSPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, : xSegment *pSegs); :static void miBSPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, : int nrects, xRectangle *pRects); :static void miBSPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, : xArc *parcs); :static void miBSFillPolygon(DrawablePtr pDrawable, GCPtr pGC, : int shape, int mode, int count, : DDXPointPtr pPts); :static void miBSPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, : int nrectFill, xRectangle *prectInit); :static void miBSPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, : int narcs, xArc *parcs); :static int miBSPolyText8(DrawablePtr pDrawable, GCPtr pGC, : int x, int y, int count, char *chars); :static int miBSPolyText16(DrawablePtr pDrawable, GCPtr pGC, : int x, int y, int count, : unsigned short *chars); :static void miBSImageText8(DrawablePtr pDrawable, GCPtr pGC, : int x, int y, int count, char *chars); :static void miBSImageText16(DrawablePtr pDrawable, GCPtr pGC, : int x, int y, int count, : unsigned short *chars); :static void miBSImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, : int x, int y, unsigned int nglyph, : CharInfoPtr *ppci, pointer pglyphBase); :static void miBSPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, : int x, int y, unsigned int nglyph, : CharInfoPtr *ppci, pointer pglyphBase); :static void miBSPushPixels(GCPtr pGC, PixmapPtr pBitMap, : DrawablePtr pDst, int w, int h, : int x, int y); : :static GCOps miBSGCOps = { : miBSFillSpans, miBSSetSpans, miBSPutImage, : miBSCopyArea, miBSCopyPlane, miBSPolyPoint, : miBSPolylines, miBSPolySegment, miBSPolyRectangle, : miBSPolyArc, miBSFillPolygon, miBSPolyFillRect, : miBSPolyFillArc, miBSPolyText8, miBSPolyText16, : miBSImageText8, miBSImageText16, miBSImageGlyphBlt, : miBSPolyGlyphBlt, miBSPushPixels :}; : :#define FUNC_PROLOGUE(pGC, pPriv) \ : ((pGC)->funcs = pPriv->wrapFuncs),\ : ((pGC)->ops = pPriv->wrapOps) : :#define FUNC_EPILOGUE(pGC, pPriv) \ : ((pGC)->funcs = &miBSGCFuncs),\ : ((pGC)->ops = &miBSGCOps) : :/* : * every GC in the server is initially wrapped with these : * "cheap" functions. This allocates no memory and is used : * to discover GCs used with windows which have backing : * store enabled : */ : :static void miBSCheapValidateGC(GCPtr pGC, unsigned long stateChanges, : DrawablePtr pDrawable); :static void miBSCheapCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); :static void miBSCheapDestroyGC(GCPtr pGC); :static void miBSCheapChangeGC(GCPtr pGC, unsigned long mask); :static void miBSCheapChangeClip(GCPtr pGC, int type, pointer pvalue, : int nrects); :static void miBSCheapDestroyClip(GCPtr pGC); :static void miBSCheapCopyClip(GCPtr pgcDst, GCPtr pgcSrc); : :static GCFuncs miBSCheapGCFuncs = { : miBSCheapValidateGC, : miBSCheapChangeGC, : miBSCheapCopyGC, : miBSCheapDestroyGC, : miBSCheapChangeClip, : miBSCheapDestroyClip, : miBSCheapCopyClip, :}; : :#define CHEAP_FUNC_PROLOGUE(pGC) \ : ((pGC)->funcs = (GCFuncs *) (pGC)->devPrivates[miBSGCIndex].ptr) : :#define CHEAP_FUNC_EPILOGUE(pGC) \ : ((pGC)->funcs = &miBSCheapGCFuncs) : :/* : * called from device screen initialization proc. Gets a GCPrivateIndex : * and wraps appropriate per-screen functions. pScreen->BackingStoreFuncs : * must be previously initialized. : */ : :_X_EXPORT void :miInitializeBackingStore (pScreen) : ScreenPtr pScreen; :{ : miBSScreenPtr pScreenPriv; : : if (miBSGeneration != serverGeneration) : { : miBSScreenIndex = AllocateScreenPrivateIndex (); : if (miBSScreenIndex < 0) : return; : miBSGCIndex = AllocateGCPrivateIndex (); : miBSGeneration = serverGeneration; : } : if (!AllocateGCPrivate(pScreen, miBSGCIndex, 0)) : return; : pScreenPriv = (miBSScreenPtr) xalloc (sizeof (miBSScreenRec)); : if (!pScreenPriv) : return; : : pScreenPriv->CloseScreen = pScreen->CloseScreen; : pScreenPriv->GetImage = pScreen->GetImage; : pScreenPriv->GetSpans = pScreen->GetSpans; : pScreenPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; : pScreenPriv->CreateGC = pScreen->CreateGC; : pScreenPriv->DestroyWindow = pScreen->DestroyWindow; : : pScreen->CloseScreen = miBSCloseScreen; : pScreen->GetImage = miBSGetImage; : pScreen->GetSpans = miBSGetSpans; : pScreen->ChangeWindowAttributes = miBSChangeWindowAttributes; : pScreen->CreateGC = miBSCreateGC; : pScreen->DestroyWindow = miBSDestroyWindow; : : pScreen->SaveDoomedAreas = miBSSaveDoomedAreas; : pScreen->RestoreAreas = miBSRestoreAreas; : pScreen->ExposeCopy = miBSExposeCopy; : pScreen->TranslateBackingStore = miBSTranslateBackingStore; : pScreen->ClearBackingStore = miBSClearBackingStore; : pScreen->DrawGuarantee = miBSDrawGuarantee; : : pScreen->devPrivates[miBSScreenIndex].ptr = (pointer) pScreenPriv; :} : :/* : * Screen function wrappers : */ : :#define SCREEN_PROLOGUE(pScreen, field)\ : ((pScreen)->field = \ : ((miBSScreenPtr) \ : (pScreen)->devPrivates[miBSScreenIndex].ptr)->field) : :#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ : ((pScreen)->field = wrapper) : :/* : * CloseScreen wrapper -- unwrap everything, free the private data : * and call the wrapped function : */ : :static Bool :miBSCloseScreen (i, pScreen) : int i; : ScreenPtr pScreen; :{ : miBSScreenPtr pScreenPriv; : : pScreenPriv = (miBSScreenPtr) pScreen->devPrivates[miBSScreenIndex].ptr; : : pScreen->CloseScreen = pScreenPriv->CloseScreen; : pScreen->GetImage = pScreenPriv->GetImage; : pScreen->GetSpans = pScreenPriv->GetSpans; : pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes; : pScreen->CreateGC = pScreenPriv->CreateGC; : : xfree ((pointer) pScreenPriv); : : return (*pScreen->CloseScreen) (i, pScreen); :} : :static void miBSFillVirtualBits(DrawablePtr pDrawable, GCPtr pGC, : RegionPtr pRgn, int x, int y, int state, : PixUnion pixunion, unsigned long planemask); : :static void :miBSGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) : DrawablePtr pDrawable; : int sx, sy, w, h; : unsigned int format; : unsigned long planemask; : char *pdstLine; :{ : ScreenPtr pScreen = pDrawable->pScreen; : BoxRec bounds; : unsigned char depth; : : SCREEN_PROLOGUE (pScreen, GetImage); : : if (pDrawable->type != DRAWABLE_PIXMAP && : ((WindowPtr) pDrawable)->visibility != VisibilityUnobscured) : { : PixmapPtr pPixmap; : miBSWindowPtr pWindowPriv; : GCPtr pGC = NULL; : WindowPtr pWin, pSrcWin; : int xoff, yoff; : RegionRec Remaining; : RegionRec Border; : RegionRec Inside; : BoxPtr pBox; : int n; : : pWin = (WindowPtr) pDrawable; : pPixmap = 0; : depth = pDrawable->depth; : bounds.x1 = sx + pDrawable->x; : bounds.y1 = sy + pDrawable->y; : bounds.x2 = bounds.x1 + w; : bounds.y2 = bounds.y1 + h; : REGION_INIT(pScreen, &Remaining, &bounds, 0); : for (;;) : { : bounds.x1 = sx + pDrawable->x - pWin->drawable.x; : bounds.y1 = sy + pDrawable->y - pWin->drawable.y; : bounds.x2 = bounds.x1 + w; : bounds.y2 = bounds.y1 + h; : if (pWin->viewable && pWin->backStorage && : pWin->drawable.depth == depth && : (RECT_IN_REGION(pScreen, &(pWindowPriv = : (miBSWindowPtr) pWin->backStorage)->SavedRegion, : &bounds) != rgnOUT || : RECT_IN_REGION(pScreen, &Remaining, : REGION_EXTENTS(pScreen, &pWin->borderSize)) != rgnOUT)) : { : if (!pPixmap) : { : XID subWindowMode = IncludeInferiors; : int x, y; : : pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, depth); : if (!pPixmap) : goto punt; : pGC = GetScratchGC (depth, pScreen); : if (!pGC) : { : (*pScreen->DestroyPixmap) (pPixmap); : goto punt; : } : ChangeGC (pGC, GCSubwindowMode, &subWindowMode); : ValidateGC ((DrawablePtr)pPixmap, pGC); : REGION_NULL(pScreen, &Border); : REGION_NULL(pScreen, &Inside); : pSrcWin = (WindowPtr) pDrawable; : x = sx; : y = sy; : if (pSrcWin->parent) : { : x += pSrcWin->origin.x; : y += pSrcWin->origin.y; : pSrcWin = pSrcWin->parent; : } : (*pGC->ops->CopyArea) ((DrawablePtr)pSrcWin, : (DrawablePtr)pPixmap, pGC, : x, y, w, h, : 0, 0); : REGION_SUBTRACT(pScreen, &Remaining, &Remaining, : &((WindowPtr) pDrawable)->borderClip); : } : : REGION_INTERSECT(pScreen, &Inside, &Remaining, &pWin->winSize); : REGION_TRANSLATE(pScreen, &Inside, : -pWin->drawable.x, : -pWin->drawable.y); : REGION_INTERSECT(pScreen, &Inside, &Inside, : &pWindowPriv->SavedRegion); : : /* offset of sub-window in GetImage pixmap */ : xoff = pWin->drawable.x - pDrawable->x - sx; : yoff = pWin->drawable.y - pDrawable->y - sy; : : if (REGION_NUM_RECTS(&Inside) > 0) : { : switch (pWindowPriv->status) : { : case StatusContents: : pBox = REGION_RECTS(&Inside); : for (n = REGION_NUM_RECTS(&Inside); --n >= 0;) : { : (*pGC->ops->CopyArea) ( : (DrawablePtr)pWindowPriv->pBackingPixmap, : (DrawablePtr)pPixmap, pGC, : pBox->x1 - pWindowPriv->x, : pBox->y1 - pWindowPriv->y, : pBox->x2 - pBox->x1, : pBox->y2 - pBox->y1, : pBox->x1 + xoff, : pBox->y1 + yoff); : ++pBox; : } : break; : case StatusVirtual: : case StatusVDirty: : if (pWindowPriv->backgroundState == BackgroundPixmap || : pWindowPriv->backgroundState == BackgroundPixel) : miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Inside, : xoff, yoff, : (int) pWindowPriv->backgroundState, : pWindowPriv->background, ~0L); : break; : } : } : REGION_SUBTRACT(pScreen, &Border, &pWin->borderSize, : &pWin->winSize); : REGION_INTERSECT(pScreen, &Border, &Border, &Remaining); : if (REGION_NUM_RECTS(&Border) > 0) : { : REGION_TRANSLATE(pScreen, &Border, -pWin->drawable.x, : -pWin->drawable.y); : miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Border, : xoff, yoff, : pWin->borderIsPixel ? (int)BackgroundPixel : (int)BackgroundPixmap, : pWin->border, ~0L); : } : } : : if (pWin->viewable && pWin->firstChild) : pWin = pWin->firstChild; : else : { : while (!pWin->nextSib && pWin != (WindowPtr) pDrawable) : pWin = pWin->parent; : if (pWin == (WindowPtr) pDrawable) : break; : pWin = pWin->nextSib; : } : } : : REGION_UNINIT(pScreen, &Remaining); : : if (pPixmap) : { : REGION_UNINIT(pScreen, &Border); : REGION_UNINIT(pScreen, &Inside); : (*pScreen->GetImage) ((DrawablePtr) pPixmap, : 0, 0, w, h, format, planemask, pdstLine); : (*pScreen->DestroyPixmap) (pPixmap); : FreeScratchGC (pGC); : } : else : { : goto punt; : } : } : else : { :punt: ; : (*pScreen->GetImage) (pDrawable, sx, sy, w, h, : format, planemask, pdstLine); : } : : SCREEN_EPILOGUE (pScreen, GetImage, miBSGetImage); :} : :static void :miBSGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) : DrawablePtr pDrawable; : int wMax; : DDXPointPtr ppt; : int *pwidth; : int nspans; : char *pdstStart; :{ : ScreenPtr pScreen = pDrawable->pScreen; : BoxRec bounds; : int i; : WindowPtr pWin; : int dx, dy; : : SCREEN_PROLOGUE (pScreen, GetSpans); : : if (pDrawable->type != DRAWABLE_PIXMAP && ((WindowPtr) pDrawable)->backStorage) : { : PixmapPtr pPixmap; : miBSWindowPtr pWindowPriv; : GCPtr pGC; : : pWin = (WindowPtr) pDrawable; : pWindowPriv = (miBSWindowPtr) pWin->backStorage; : pPixmap = pWindowPriv->pBackingPixmap; : : bounds.x1 = ppt->x; : bounds.y1 = ppt->y; : bounds.x2 = bounds.x1 + *pwidth; : bounds.y2 = ppt->y; : for (i = 0; i < nspans; i++) : { : if (ppt[i].x < bounds.x1) : bounds.x1 = ppt[i].x; : if (ppt[i].x + pwidth[i] > bounds.x2) : bounds.x2 = ppt[i].x + pwidth[i]; : if (ppt[i].y < bounds.y1) : bounds.y1 = ppt[i].y; : else if (ppt[i].y > bounds.y2) : bounds.y2 = ppt[i].y; : } : : switch (RECT_IN_REGION(pScreen, &pWindowPriv->SavedRegion, &bounds)) : { : case rgnPART: : if (!pPixmap) : { : miCreateBSPixmap (pWin, NullBox); : if (!(pPixmap = pWindowPriv->pBackingPixmap)) : break; : } : pWindowPriv->status = StatusNoPixmap; : pGC = GetScratchGC(pPixmap->drawable.depth, : pPixmap->drawable.pScreen); : if (pGC) : { : ValidateGC ((DrawablePtr) pPixmap, pGC); : (*pGC->ops->CopyArea) : (pDrawable, (DrawablePtr) pPixmap, pGC, : bounds.x1, bounds.y1, : bounds.x2 - bounds.x1, bounds.y2 - bounds.y1, : bounds.x1 + pPixmap->drawable.x - pWin->drawable.x - : pWindowPriv->x, : bounds.y1 + pPixmap->drawable.y - pWin->drawable.y - : pWindowPriv->y); : FreeScratchGC(pGC); : } : pWindowPriv->status = StatusContents; : /* fall through */ : case rgnIN: : if (!pPixmap) : { : miCreateBSPixmap (pWin, NullBox); : if (!(pPixmap = pWindowPriv->pBackingPixmap)) : break; : } : dx = pPixmap->drawable.x - pWin->drawable.x - pWindowPriv->x; : dy = pPixmap->drawable.y - pWin->drawable.y - pWindowPriv->y; : for (i = 0; i < nspans; i++) : { : ppt[i].x += dx; : ppt[i].y += dy; : } : (*pScreen->GetSpans) ((DrawablePtr) pPixmap, wMax, ppt, pwidth, : nspans, pdstStart); : break; : case rgnOUT: : (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, : pdstStart); : break; : } : } : else : { : (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); : } : : SCREEN_EPILOGUE (pScreen, GetSpans, miBSGetSpans); :} : :static Bool :miBSChangeWindowAttributes (pWin, mask) : WindowPtr pWin; : unsigned long mask; :{ : ScreenPtr pScreen; : Bool ret; : : pScreen = pWin->drawable.pScreen; : : SCREEN_PROLOGUE (pScreen, ChangeWindowAttributes); : : ret = (*pScreen->ChangeWindowAttributes) (pWin, mask); : : if (ret && (mask & CWBackingStore)) : { : if (pWin->backingStore != NotUseful || pWin->DIXsaveUnder) : miBSAllocate (pWin); : else : miBSFree (pWin); : } : : SCREEN_EPILOGUE (pScreen, ChangeWindowAttributes, miBSChangeWindowAttributes); : : return ret; :} : :/* : * GC Create wrapper. Set up the cheap GC func wrappers to track : * GC validation on BackingStore windows : */ : :static Bool :miBSCreateGC (pGC) : GCPtr pGC; :{ : ScreenPtr pScreen = pGC->pScreen; : Bool ret; : : SCREEN_PROLOGUE (pScreen, CreateGC); : : if ( (ret = (*pScreen->CreateGC) (pGC)) ) : { : pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs; : pGC->funcs = &miBSCheapGCFuncs; : } : : SCREEN_EPILOGUE (pScreen, CreateGC, miBSCreateGC); : : return ret; :} : :static Bool :miBSDestroyWindow (pWin) : WindowPtr pWin; :{ : ScreenPtr pScreen = pWin->drawable.pScreen; : Bool ret; : : SCREEN_PROLOGUE (pScreen, DestroyWindow); : : ret = (*pScreen->DestroyWindow) (pWin); : : miBSFree (pWin); : : SCREEN_EPILOGUE (pScreen, DestroyWindow, miBSDestroyWindow); : : return ret; :} : :/* : * cheap GC func wrappers. Simply track validation on windows : * with backing store to enable the real func/op wrappers : */ : :static void :miBSCheapValidateGC (pGC, stateChanges, pDrawable) : GCPtr pGC; : unsigned long stateChanges; : DrawablePtr pDrawable; 1 0.0011 :{ /* miBSCheapValidateGC total: 5 0.0054 */ : CHEAP_FUNC_PROLOGUE (pGC); : 1 0.0011 : if (pDrawable->type != DRAWABLE_PIXMAP && : ((WindowPtr) pDrawable)->backStorage != NULL && : miBSCreateGCPrivate (pGC)) : { : (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable); : } : else : { : (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable); : : /* rewrap funcs as Validate may have changed them */ : pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs; : 1 0.0011 : CHEAP_FUNC_EPILOGUE (pGC); : } 2 0.0022 :} : :static void :miBSCheapChangeGC (pGC, mask) : GCPtr pGC; : unsigned long mask; 1 0.0011 :{ /* miBSCheapChangeGC total: 1 0.0011 */ : CHEAP_FUNC_PROLOGUE (pGC); : : (*pGC->funcs->ChangeGC) (pGC, mask); : : CHEAP_FUNC_EPILOGUE (pGC); :} : :static void :miBSCheapCopyGC (pGCSrc, mask, pGCDst) : GCPtr pGCSrc, pGCDst; : unsigned long mask; :{ : CHEAP_FUNC_PROLOGUE (pGCDst); : : (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); : : CHEAP_FUNC_EPILOGUE (pGCDst); :} : :static void :miBSCheapDestroyGC (pGC) : GCPtr pGC; :{ : CHEAP_FUNC_PROLOGUE (pGC); : : (*pGC->funcs->DestroyGC) (pGC); : : /* leave it unwrapped */ :} : :static void :miBSCheapChangeClip (pGC, type, pvalue, nrects) : GCPtr pGC; : int type; : pointer pvalue; : int nrects; 1 0.0011 :{ /* miBSCheapChangeClip total: 3 0.0033 */ : CHEAP_FUNC_PROLOGUE (pGC); : : (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); : : CHEAP_FUNC_EPILOGUE (pGC); 2 0.0022 :} : :static void :miBSCheapCopyClip(pgcDst, pgcSrc) : GCPtr pgcDst, pgcSrc; :{ : CHEAP_FUNC_PROLOGUE (pgcDst); : : (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); : : CHEAP_FUNC_EPILOGUE (pgcDst); :} : :static void :miBSCheapDestroyClip(pGC) : GCPtr pGC; :{ : CHEAP_FUNC_PROLOGUE (pGC); : : (* pGC->funcs->DestroyClip)(pGC); : : CHEAP_FUNC_EPILOGUE (pGC); :} : :/* : * create the full func/op wrappers for a GC : */ : :static Bool :miBSCreateGCPrivate (pGC) : GCPtr pGC; :{ : miBSGCRec *pPriv; : : pPriv = (miBSGCRec *) xalloc (sizeof (miBSGCRec)); : if (!pPriv) : return FALSE; : pPriv->pBackingGC = NULL; : pPriv->guarantee = GuaranteeNothing; : pPriv->serialNumber = 0; : pPriv->stateChanges = (1 << (GCLastBit + 1)) - 1; : pPriv->wrapOps = pGC->ops; : pPriv->wrapFuncs = pGC->funcs; : pGC->funcs = &miBSGCFuncs; : pGC->ops = &miBSGCOps; : pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv; : return TRUE; :} : :static void :miBSDestroyGCPrivate (GCPtr pGC) :{ : miBSGCRec *pPriv; : : pPriv = (miBSGCRec *) pGC->devPrivates[miBSGCIndex].ptr; : if (pPriv) : { : pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv->wrapFuncs; : pGC->funcs = &miBSCheapGCFuncs; : pGC->ops = pPriv->wrapOps; : if (pPriv->pBackingGC) : FreeGC (pPriv->pBackingGC, (GContext) 0); : xfree ((pointer) pPriv); : } :} : :/* : * GC ops -- wrap each GC operation with our own function : */ : :/*- : *----------------------------------------------------------------------- : * miBSFillSpans -- : * Perform a FillSpans, routing output to backing-store as needed. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted) : DrawablePtr pDrawable; : GCPtr pGC; : int nInit; /* number of spans to fill */ : DDXPointPtr pptInit; /* pointer to list of start points */ : int *pwidthInit; /* pointer to list of n widths */ : int fSorted; :{ : DDXPointPtr pptCopy, pptReset; : int *pwidthCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nInit*sizeof(DDXPointRec)); : pwidthCopy=(int *)ALLOCATE_LOCAL(nInit*sizeof(int)); : if (pptCopy && pwidthCopy) : { : copyData(pptInit, pptCopy, nInit, MoreCopy0); : memmove((char *)pwidthCopy,(char *)pwidthInit,nInit*sizeof(int)); : : (* pGC->ops->FillSpans)(pDrawable, pGC, nInit, pptInit, : pwidthInit, fSorted); : if (pGC->miTranslate) : { : int dx, dy; : int nReset; : : pptReset = pptCopy; : dx = pDrawable->x - pBackingDrawable->x; : dy = pDrawable->y - pBackingDrawable->y; : nReset = nInit; : while (nReset--) : { : pptReset->x -= dx; : pptReset->y -= dy; : ++pptReset; : } : } : (* pBackingGC->ops->FillSpans)(pBackingDrawable, : pBackingGC, nInit, pptCopy, pwidthCopy, : fSorted); : } : if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy); : if (pptCopy) DEALLOCATE_LOCAL(pptCopy); : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSSetSpans -- : * Perform a SetSpans, routing output to backing-store as needed. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted) : DrawablePtr pDrawable; : GCPtr pGC; : char *psrc; : DDXPointPtr ppt; : int *pwidth; : int nspans; : int fSorted; :{ : DDXPointPtr pptCopy, pptReset; : int *pwidthCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nspans*sizeof(DDXPointRec)); : pwidthCopy=(int *)ALLOCATE_LOCAL(nspans*sizeof(int)); : if (pptCopy && pwidthCopy) : { : copyData(ppt, pptCopy, nspans, MoreCopy0); : memmove((char *)pwidthCopy,(char *)pwidth,nspans*sizeof(int)); : : (* pGC->ops->SetSpans)(pDrawable, pGC, psrc, ppt, pwidth, : nspans, fSorted); : if (pGC->miTranslate) : { : int dx, dy; : int nReset; : : pptReset = pptCopy; : dx = pDrawable->x - pBackingDrawable->x; : dy = pDrawable->y - pBackingDrawable->y; : nReset = nspans; : while (nReset--) : { : pptReset->x -= dx; : pptReset->y -= dy; : ++pptReset; : } : } : (* pBackingGC->ops->SetSpans)(pBackingDrawable, pBackingGC, : psrc, pptCopy, pwidthCopy, nspans, fSorted); : } : if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy); : if (pptCopy) DEALLOCATE_LOCAL(pptCopy); : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPutImage -- : * Perform a PutImage, routing output to backing-store as needed. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits) : DrawablePtr pDrawable; : GCPtr pGC; : int depth; : int x; : int y; : int w; : int h; : int leftPad; : int format; : char *pBits; :{ : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : (*pGC->ops->PutImage)(pDrawable, pGC, : depth, x, y, w, h, leftPad, format, pBits); : (*pBackingGC->ops->PutImage)(pBackingDrawable, pBackingGC, : depth, x - pBackingStore->x, y - pBackingStore->y, : w, h, leftPad, format, pBits); : : EPILOGUE (pGC); :} : :typedef RegionPtr (* CopyAreaProcPtr)(DrawablePtr, DrawablePtr, GCPtr, : int, int, int, int, int, int); :typedef RegionPtr (* CopyPlaneProcPtr)(DrawablePtr, DrawablePtr, GCPtr, : int, int, int, int, int, int, : unsigned long bitPlane); :/*- : *----------------------------------------------------------------------- : * miBSDoCopy -- : * Perform a CopyArea or CopyPlane within a window that has backing : * store enabled. : * : * Results: : * TRUE if the copy was performed or FALSE if a regular one should : * be done. : * : * Side Effects: : * Things are copied (no s***!) : * : * Notes: : * The idea here is to form two regions that cover the source box. : * One contains the exposed rectangles while the other contains : * the obscured ones. An array of pairs is then : * formed where the indicates the area to be copied and the : * indicates from where it is to be copied (exposed regions : * come from the screen while obscured ones come from the backing : * pixmap). The array 'sequence' is then filled with the indices of : * the pairs in the order in which they should be copied to prevent : * things from getting screwed up. A call is also made through the : * backingGC to take care of any copying into the backing pixmap. : * : *----------------------------------------------------------------------- : */ :static Bool :miBSDoCopy( : WindowPtr pWin, /* Window being scrolled */ : GCPtr pGC, /* GC we're called through */ : int srcx, /* X of source rectangle */ : int srcy, /* Y of source rectangle */ : int w, /* Width of source rectangle */ : int h, /* Height of source rectangle */ : int dstx, /* X of destination rectangle */ : int dsty, /* Y of destination rectangle */ : unsigned long plane, /* Plane to copy (0 for CopyArea) */ : CopyPlaneProcPtr copyProc, /* Procedure to call to perform the copy */ : RegionPtr *ppRgn) /* resultant Graphics Expose region */ :{ : RegionPtr pRgnExp; /* Exposed region */ : RegionPtr pRgnObs; /* Obscured region */ : BoxRec box; /* Source box (screen coord) */ : struct BoxDraw { : BoxPtr pBox; /* Source box */ : enum { : win, pix : } source; /* Place from which to copy */ : } *boxes; /* Array of box/drawable pairs covering : * source box. */ : int *sequence; /* Sequence of boxes to move */ : int i, j, k, l, y; : BoxPtr pBox; : int dx, dy, nrects; : Bool graphicsExposures; : CopyPlaneProcPtr pixCopyProc; : int numRectsExp, numRectsObs; : BoxPtr pBoxExp, pBoxObs; : : SETUP_BACKING (pWin, pGC); : (void)oldFuncs; : : /* : * Create a region of exposed boxes in pRgnExp. : */ : box.x1 = srcx + pWin->drawable.x; : box.x2 = box.x1 + w; : box.y1 = srcy + pWin->drawable.y; : box.y2 = box.y1 + h; : : pRgnExp = REGION_CREATE(pGC->pScreen, &box, 1); : REGION_INTERSECT(pGC->pScreen, pRgnExp, pRgnExp, &pWin->clipList); : pRgnObs = REGION_CREATE(pGC->pScreen, NULL, 1); : REGION_INVERSE( pGC->pScreen, pRgnObs, pRgnExp, &box); : : /* : * Translate regions into window coordinates for proper calls : * to the copyProc, then make sure none of the obscured region sticks : * into invalid areas of the backing pixmap. : */ : REGION_TRANSLATE(pGC->pScreen, pRgnExp, : -pWin->drawable.x, : -pWin->drawable.y); : REGION_TRANSLATE(pGC->pScreen, pRgnObs, : -pWin->drawable.x, : -pWin->drawable.y); : REGION_INTERSECT(pGC->pScreen, pRgnObs, pRgnObs, &pBackingStore->SavedRegion); : : /* : * If the obscured region is empty, there's no point being fancy. : */ : if (!REGION_NOTEMPTY(pGC->pScreen, pRgnObs)) : { : REGION_DESTROY(pGC->pScreen, pRgnExp); : REGION_DESTROY(pGC->pScreen, pRgnObs); : : return (FALSE); : } : : numRectsExp = REGION_NUM_RECTS(pRgnExp); : pBoxExp = REGION_RECTS(pRgnExp); : pBoxObs = REGION_RECTS(pRgnObs); : numRectsObs = REGION_NUM_RECTS(pRgnObs); : nrects = numRectsExp + numRectsObs; : : boxes = (struct BoxDraw *)ALLOCATE_LOCAL(nrects * sizeof(struct BoxDraw)); : sequence = (int *) ALLOCATE_LOCAL(nrects * sizeof(int)); : *ppRgn = NULL; : : if (!boxes || !sequence) : { : if (sequence) DEALLOCATE_LOCAL(sequence); : if (boxes) DEALLOCATE_LOCAL(boxes); : REGION_DESTROY(pGC->pScreen, pRgnExp); : REGION_DESTROY(pGC->pScreen, pRgnObs); : : return(TRUE); : } : : /* : * Order the boxes in the two regions so we know from which drawable : * to copy which box, storing the result in the boxes array : */ : for (i = 0, j = 0, k = 0; : (i < numRectsExp) && (j < numRectsObs); : k++) : { : if (pBoxExp[i].y1 < pBoxObs[j].y1) : { : boxes[k].pBox = &pBoxExp[i]; : boxes[k].source = win; : i++; : } : else if ((pBoxObs[j].y1 < pBoxExp[i].y1) || : (pBoxObs[j].x1 < pBoxExp[i].x1)) : { : boxes[k].pBox = &pBoxObs[j]; : boxes[k].source = pix; : j++; : } : else : { : boxes[k].pBox = &pBoxExp[i]; : boxes[k].source = win; : i++; : } : } : : /* : * Catch any leftover boxes from either region (note that only : * one can have leftover boxes...) : */ : if (i != numRectsExp) : { : do : { : boxes[k].pBox = &pBoxExp[i]; : boxes[k].source = win; : i++; : k++; : } while (i < numRectsExp); : : } : else : { : do : { : boxes[k].pBox = &pBoxObs[j]; : boxes[k].source = pix; : j++; : k++; : } while (j < numRectsObs); : } : : if (dsty <= srcy) : { : /* : * Scroll up or vertically stationary, so vertical order is ok. : */ : if (dstx <= srcx) : { : /* : * Scroll left or horizontally stationary, so horizontal order : * is ok as well. : */ : for (i = 0; i < nrects; i++) : { : sequence[i] = i; : } : } : else : { : /* : * Scroll right. Need to reverse the rectangles within each : * band. : */ : for (i = 0, j = 1, k = 0; : i < nrects; : j = i + 1, k = i) : { : y = boxes[i].pBox->y1; : while ((j < nrects) && (boxes[j].pBox->y1 == y)) : { : j++; : } : for (j--; j >= k; j--, i++) : { : sequence[i] = j; : } : } : } : } : else : { : /* : * Scroll down. Must reverse vertical banding, at least. : */ : if (dstx < srcx) : { : /* : * Scroll left. Horizontal order is ok. : */ : for (i = nrects - 1, j = i - 1, k = i, l = 0; : i >= 0; : j = i - 1, k = i) : { : /* : * Find extent of current horizontal band, then reverse : * the order of the whole band. : */ : y = boxes[i].pBox->y1; : while ((j >= 0) && (boxes[j].pBox->y1 == y)) : { : j--; : } : for (j++; j <= k; j++, i--, l++) : { : sequence[l] = j; : } : } : } : else : { : /* : * Scroll right or horizontal stationary. : * Reverse horizontal order as well (if stationary, horizontal : * order can be swapped without penalty and this is faster : * to compute). : */ : for (i = 0, j = nrects - 1; i < nrects; i++, j--) : { : sequence[i] = j; : } : } : } : : /* : * XXX: To avoid getting multiple NoExpose events from this operation, : * we turn OFF graphicsExposures in the gc and deal with any uncopied : * areas later, if there's something not in backing-store. : */ : : graphicsExposures = pGC->graphicsExposures; : pGC->graphicsExposures = FALSE; : : dx = dstx - srcx; : dy = dsty - srcy; : : /* : * Figure out which copy procedure to use from the backing GC. Note we : * must do this because some implementations (sun's, e.g.) have : * pBackingGC a fake GC with the real one below it, thus the devPriv for : * pBackingGC won't be what the output library expects. : */ : if (plane != 0) : { : pixCopyProc = pBackingGC->ops->CopyPlane; : } : else : { : pixCopyProc = (CopyPlaneProcPtr)pBackingGC->ops->CopyArea; : } : : for (i = 0; i < nrects; i++) : { : pBox = boxes[sequence[i]].pBox; : : /* : * If we're copying from the pixmap, we need to place its contents : * onto the screen before scrolling the pixmap itself. If we're copying : * from the window, we need to copy its contents into the pixmap before : * we scroll the window itself. : */ : if (boxes[sequence[i]].source == pix) : { : (void) (* copyProc) (pBackingDrawable, &(pWin->drawable), pGC, : pBox->x1 - pBackingStore->x, : pBox->y1 - pBackingStore->y, : pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, : pBox->x1 + dx, pBox->y1 + dy, plane); : (void) (* pixCopyProc) (pBackingDrawable, pBackingDrawable, pBackingGC, : pBox->x1 - pBackingStore->x, : pBox->y1 - pBackingStore->y, : pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, : pBox->x1 + dx - pBackingStore->x, : pBox->y1 + dy - pBackingStore->y, plane); : } : else : { : (void) (* pixCopyProc) (&(pWin->drawable), pBackingDrawable, pBackingGC, : pBox->x1, pBox->y1, : pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, : pBox->x1 + dx - pBackingStore->x, : pBox->y1 + dy - pBackingStore->y, plane); : (void) (* copyProc) (&(pWin->drawable), &(pWin->drawable), pGC, : pBox->x1, pBox->y1, : pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, : pBox->x1 + dx, pBox->y1 + dy, plane); : } : } : DEALLOCATE_LOCAL(sequence); : DEALLOCATE_LOCAL(boxes); : : pGC->graphicsExposures = graphicsExposures; : /* : * Form union of rgnExp and rgnObs and see if covers entire area : * to be copied. Store the resultant region for miBSCopyArea : * to return to dispatch which will send the appropriate expose : * events. : */ : REGION_UNION(pGC->pScreen, pRgnExp, pRgnExp, pRgnObs); : box.x1 = srcx; : box.x2 = srcx + w; : box.y1 = srcy; : box.y2 = srcy + h; : if (RECT_IN_REGION(pGC->pScreen, pRgnExp, &box) == rgnIN) : { : REGION_EMPTY(pGC->pScreen, pRgnExp); : } : else : { : REGION_INVERSE( pGC->pScreen, pRgnExp, pRgnExp, &box); : REGION_TRANSLATE( pGC->pScreen, pRgnExp, : dx + pWin->drawable.x, : dy + pWin->drawable.y); : REGION_INTERSECT( pGC->pScreen, pRgnObs, pRgnExp, &pWin->clipList); : (*pWin->drawable.pScreen->PaintWindowBackground) (pWin, : pRgnObs, PW_BACKGROUND); : REGION_TRANSLATE( pGC->pScreen, pRgnExp, : -pWin->drawable.x, : -pWin->drawable.y); : miBSClearBackingRegion (pWin, pRgnExp); : } : if (graphicsExposures) : *ppRgn = pRgnExp; : else : REGION_DESTROY(pGC->pScreen, pRgnExp); : REGION_DESTROY(pGC->pScreen, pRgnObs); : : return (TRUE); :} : :/*- : *----------------------------------------------------------------------- : * miBSCopyArea -- : * Perform a CopyArea from the source to the destination, extracting : * from the source's backing-store and storing into the destination's : * backing-store without messing anything up. If the source and : * destination are different, there's not too much to worry about: : * we can just issue several calls to the regular CopyArea function. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static RegionPtr :miBSCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty) : DrawablePtr pSrc; : DrawablePtr pDst; : GCPtr pGC; : int srcx; : int srcy; : int w; : int h; : int dstx; : int dsty; :{ : BoxPtr pExtents; : long dx, dy; : int bsrcx, bsrcy, bw, bh, bdstx, bdsty; : RegionPtr pixExposed = 0, winExposed = 0; : : SETUP_BACKING(pDst, pGC); : : PROLOGUE(pGC); : : if ((pSrc != pDst) || : (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty, : (unsigned long) 0, (CopyPlaneProcPtr)pGC->ops->CopyArea, : &winExposed))) : { : /* : * always copy to the backing store first, miBSDoCopy : * returns FALSE if the *source* region is disjoint : * from the backing store saved region. So, copying : * *to* the backing store is always safe : */ : if (pGC->clientClipType != CT_PIXMAP) : { : /* : * adjust srcx, srcy, w, h, dstx, dsty to be clipped to : * the backing store. An unnecessary optimisation, : * but a useful one when GetSpans is slow. : */ : pExtents = REGION_EXTENTS(pDst->pScreen, : (RegionPtr)pBackingGC->clientClip); : bsrcx = srcx; : bsrcy = srcy; : bw = w; : bh = h; : bdstx = dstx; : bdsty = dsty; : dx = pExtents->x1 - bdstx; : if (dx > 0) : { : bsrcx += dx; : bdstx += dx; : bw -= dx; : } : dy = pExtents->y1 - bdsty; : if (dy > 0) : { : bsrcy += dy; : bdsty += dy; : bh -= dy; : } : dx = (bdstx + bw) - pExtents->x2; : if (dx > 0) : bw -= dx; : dy = (bdsty + bh) - pExtents->y2; : if (dy > 0) : bh -= dy; : if (bw > 0 && bh > 0) : pixExposed = (* pBackingGC->ops->CopyArea) (pSrc, : pBackingDrawable, pBackingGC, : bsrcx, bsrcy, bw, bh, bdstx - pBackingStore->x, : bdsty - pBackingStore->y); : } : else : pixExposed = (* pBackingGC->ops->CopyArea) (pSrc, : pBackingDrawable, pBackingGC, : srcx, srcy, w, h, : dstx - pBackingStore->x, dsty - pBackingStore->y); : : winExposed = (* pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); : } : : /* : * compute the composite graphics exposure region : */ : if (winExposed) : { : if (pixExposed){ : REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed); : REGION_DESTROY(pDst->pScreen, pixExposed); : } : } else : winExposed = pixExposed; : : EPILOGUE (pGC); : : return winExposed; :} : :/*- : *----------------------------------------------------------------------- : * miBSCopyPlane -- : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static RegionPtr :miBSCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane) : DrawablePtr pSrc; : DrawablePtr pDst; : GC *pGC; : int srcx, : srcy; : int w, : h; : int dstx, : dsty; : unsigned long plane; :{ : BoxPtr pExtents; : long dx, dy; : int bsrcx, bsrcy, bw, bh, bdstx, bdsty; : RegionPtr winExposed = 0, pixExposed = 0; : SETUP_BACKING(pDst, pGC); : : PROLOGUE(pGC); : : if ((pSrc != pDst) || : (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty, : plane, pGC->ops->CopyPlane, &winExposed))) : { : /* : * always copy to the backing store first, miBSDoCopy : * returns FALSE if the *source* region is disjoint : * from the backing store saved region. So, copying : * *to* the backing store is always safe : */ : if (pGC->clientClipType != CT_PIXMAP) : { : /* : * adjust srcx, srcy, w, h, dstx, dsty to be clipped to : * the backing store. An unnecessary optimisation, : * but a useful one when GetSpans is slow. : */ : pExtents = REGION_EXTENTS(pDst->pScreen, : (RegionPtr)pBackingGC->clientClip); : bsrcx = srcx; : bsrcy = srcy; : bw = w; : bh = h; : bdstx = dstx; : bdsty = dsty; : dx = pExtents->x1 - bdstx; : if (dx > 0) : { : bsrcx += dx; : bdstx += dx; : bw -= dx; : } : dy = pExtents->y1 - bdsty; : if (dy > 0) : { : bsrcy += dy; : bdsty += dy; : bh -= dy; : } : dx = (bdstx + bw) - pExtents->x2; : if (dx > 0) : bw -= dx; : dy = (bdsty + bh) - pExtents->y2; : if (dy > 0) : bh -= dy; : if (bw > 0 && bh > 0) : pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc, : pBackingDrawable, : pBackingGC, bsrcx, bsrcy, bw, bh, : bdstx - pBackingStore->x, : bdsty - pBackingStore->y, plane); : } : else : pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc, : pBackingDrawable, : pBackingGC, srcx, srcy, w, h, : dstx - pBackingStore->x, : dsty - pBackingStore->y, plane); : : winExposed = (* pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, : dstx, dsty, plane); : : } : : /* : * compute the composite graphics exposure region : */ : if (winExposed) : { : if (pixExposed) : { : REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed); : REGION_DESTROY(pDst->pScreen, pixExposed); : } : } else : winExposed = pixExposed; : : EPILOGUE (pGC); : : return winExposed; :} : :/*- : *----------------------------------------------------------------------- : * miBSPolyPoint -- : * Perform a PolyPoint, routing output to backing-store as needed. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPolyPoint (pDrawable, pGC, mode, npt, pptInit) : DrawablePtr pDrawable; : GCPtr pGC; : int mode; /* Origin or Previous */ : int npt; : xPoint *pptInit; :{ : xPoint *pptCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pptCopy = (xPoint *)ALLOCATE_LOCAL(npt*sizeof(xPoint)); : if (pptCopy) : { : copyPoints(pptInit, pptCopy, npt, mode); : : (* pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit); : : (* pBackingGC->ops->PolyPoint) (pBackingDrawable, : pBackingGC, mode, npt, pptCopy); : : DEALLOCATE_LOCAL(pptCopy); : } : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPolyLines -- : * Perform a Polylines, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPolylines (pDrawable, pGC, mode, npt, pptInit) : DrawablePtr pDrawable; : GCPtr pGC; : int mode; : int npt; : DDXPointPtr pptInit; :{ : DDXPointPtr pptCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(npt*sizeof(DDXPointRec)); : if (pptCopy) : { : copyPoints(pptInit, pptCopy, npt, mode); : : (* pGC->ops->Polylines)(pDrawable, pGC, mode, npt, pptInit); : (* pBackingGC->ops->Polylines)(pBackingDrawable, : pBackingGC, mode, npt, pptCopy); : DEALLOCATE_LOCAL(pptCopy); : } : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPolySegment -- : * Perform a PolySegment, routing output to backing-store as needed. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPolySegment(pDrawable, pGC, nseg, pSegs) : DrawablePtr pDrawable; : GCPtr pGC; : int nseg; : xSegment *pSegs; :{ : xSegment *pSegsCopy; : : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pSegsCopy = (xSegment *)ALLOCATE_LOCAL(nseg*sizeof(xSegment)); : if (pSegsCopy) : { : copyData(pSegs, pSegsCopy, nseg << 1, MoreCopy0); : : (* pGC->ops->PolySegment)(pDrawable, pGC, nseg, pSegs); : (* pBackingGC->ops->PolySegment)(pBackingDrawable, : pBackingGC, nseg, pSegsCopy); : : DEALLOCATE_LOCAL(pSegsCopy); : } : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPolyRectangle -- : * Perform a PolyRectangle, routing output to backing-store as needed. : * : * Results: : * None : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPolyRectangle(pDrawable, pGC, nrects, pRects) : DrawablePtr pDrawable; : GCPtr pGC; : int nrects; : xRectangle *pRects; :{ : xRectangle *pRectsCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pRectsCopy =(xRectangle *)ALLOCATE_LOCAL(nrects*sizeof(xRectangle)); : if (pRectsCopy) : { : copyData(pRects, pRectsCopy, nrects, MoreCopy2); : : (* pGC->ops->PolyRectangle)(pDrawable, pGC, nrects, pRects); : (* pBackingGC->ops->PolyRectangle)(pBackingDrawable, : pBackingGC, nrects, pRectsCopy); : : DEALLOCATE_LOCAL(pRectsCopy); : } : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPolyArc -- : * Perform a PolyArc, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPolyArc(pDrawable, pGC, narcs, parcs) : DrawablePtr pDrawable; : GCPtr pGC; : int narcs; : xArc *parcs; :{ : xArc *pArcsCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc)); : if (pArcsCopy) : { : copyData(parcs, pArcsCopy, narcs, MoreCopy4); : : (* pGC->ops->PolyArc)(pDrawable, pGC, narcs, parcs); : (* pBackingGC->ops->PolyArc)(pBackingDrawable, pBackingGC, : narcs, pArcsCopy); : : DEALLOCATE_LOCAL(pArcsCopy); : } : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSFillPolygon -- : * Perform a FillPolygon, routing output to backing-store as needed. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSFillPolygon(pDrawable, pGC, shape, mode, count, pPts) : DrawablePtr pDrawable; : GCPtr pGC; : int shape, mode; : int count; : DDXPointPtr pPts; :{ : DDXPointPtr pPtsCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pPtsCopy = (DDXPointPtr)ALLOCATE_LOCAL(count*sizeof(DDXPointRec)); : if (pPtsCopy) : { : copyPoints(pPts, pPtsCopy, count, mode); : (* pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, count, pPts); : (* pBackingGC->ops->FillPolygon)(pBackingDrawable, : pBackingGC, shape, mode, : count, pPtsCopy); : : DEALLOCATE_LOCAL(pPtsCopy); : } : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPolyFillRect -- : * Perform a PolyFillRect, routing output to backing-store as needed. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPolyFillRect(pDrawable, pGC, nrectFill, prectInit) : DrawablePtr pDrawable; : GCPtr pGC; : int nrectFill; /* number of rectangles to fill */ : xRectangle *prectInit; /* Pointer to first rectangle to fill */ :{ : xRectangle *pRectCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pRectCopy = : (xRectangle *)ALLOCATE_LOCAL(nrectFill*sizeof(xRectangle)); : if (pRectCopy) : { : copyData(prectInit, pRectCopy, nrectFill, MoreCopy2); : : (* pGC->ops->PolyFillRect)(pDrawable, pGC, nrectFill, prectInit); : (* pBackingGC->ops->PolyFillRect)(pBackingDrawable, : pBackingGC, nrectFill, pRectCopy); : : DEALLOCATE_LOCAL(pRectCopy); : } : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPolyFillArc -- : * Perform a PolyFillArc, routing output to backing-store as needed. : * : * Results: : * None. : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPolyFillArc(pDrawable, pGC, narcs, parcs) : DrawablePtr pDrawable; : GCPtr pGC; : int narcs; : xArc *parcs; :{ : xArc *pArcsCopy; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc)); : if (pArcsCopy) : { : copyData(parcs, pArcsCopy, narcs, MoreCopy4); : (* pGC->ops->PolyFillArc)(pDrawable, pGC, narcs, parcs); : (* pBackingGC->ops->PolyFillArc)(pBackingDrawable, : pBackingGC, narcs, pArcsCopy); : DEALLOCATE_LOCAL(pArcsCopy); : } : : EPILOGUE (pGC); :} : : :/*- : *----------------------------------------------------------------------- : * miBSPolyText8 -- : * Perform a PolyText8, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static int :miBSPolyText8(pDrawable, pGC, x, y, count, chars) : DrawablePtr pDrawable; : GCPtr pGC; : int x, y; : int count; : char *chars; :{ : int result; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : result = (* pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); : (* pBackingGC->ops->PolyText8)(pBackingDrawable, pBackingGC, : x - pBackingStore->x, y - pBackingStore->y, : count, chars); : : EPILOGUE (pGC); : return result; :} : :/*- : *----------------------------------------------------------------------- : * miBSPolyText16 -- : * Perform a PolyText16, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static int :miBSPolyText16(pDrawable, pGC, x, y, count, chars) : DrawablePtr pDrawable; : GCPtr pGC; : int x, y; : int count; : unsigned short *chars; :{ : int result; : SETUP_BACKING (pDrawable, pGC); : : PROLOGUE(pGC); : : result = (* pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); : (* pBackingGC->ops->PolyText16)(pBackingDrawable, pBackingGC, : x - pBackingStore->x, y - pBackingStore->y, : count, chars); : : EPILOGUE (pGC); : : return result; :} : :/*- : *----------------------------------------------------------------------- : * miBSImageText8 -- : * Perform a ImageText8, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSImageText8(pDrawable, pGC, x, y, count, chars) : DrawablePtr pDrawable; : GCPtr pGC; : int x, y; : int count; : char *chars; :{ : SETUP_BACKING (pDrawable, pGC); : PROLOGUE(pGC); : : (* pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); : (* pBackingGC->ops->ImageText8)(pBackingDrawable, pBackingGC, : x - pBackingStore->x, y - pBackingStore->y, : count, chars); : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSImageText16 -- : * Perform a ImageText16, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSImageText16(pDrawable, pGC, x, y, count, chars) : DrawablePtr pDrawable; : GCPtr pGC; : int x, y; : int count; : unsigned short *chars; :{ : SETUP_BACKING (pDrawable, pGC); : PROLOGUE(pGC); : : (* pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); : (* pBackingGC->ops->ImageText16)(pBackingDrawable, pBackingGC, : x - pBackingStore->x, y - pBackingStore->y, : count, chars); : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSImageGlyphBlt -- : * Perform a ImageGlyphBlt, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) : DrawablePtr pDrawable; : GCPtr pGC; : int x, y; : unsigned int nglyph; : CharInfoPtr *ppci; /* array of character info */ : pointer pglyphBase; /* start of array of glyphs */ :{ : SETUP_BACKING (pDrawable, pGC); : PROLOGUE(pGC); : : (* pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci, : pglyphBase); : (* pBackingGC->ops->ImageGlyphBlt)(pBackingDrawable, pBackingGC, : x - pBackingStore->x, y - pBackingStore->y, : nglyph, ppci, pglyphBase); : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPolyGlyphBlt -- : * Perform a PolyGlyphBlt, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) : DrawablePtr pDrawable; : GCPtr pGC; : int x, y; : unsigned int nglyph; : CharInfoPtr *ppci; /* array of character info */ : pointer pglyphBase; /* start of array of glyphs */ :{ : SETUP_BACKING (pDrawable, pGC); : PROLOGUE(pGC); : : (* pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, : ppci, pglyphBase); : (* pBackingGC->ops->PolyGlyphBlt)(pBackingDrawable, pBackingGC, : x - pBackingStore->x, y - pBackingStore->y, : nglyph, ppci, pglyphBase); : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSPushPixels -- : * Perform a PushPixels, routing output to backing-store as needed. : * : * Results: : * : * Side Effects: : * : *----------------------------------------------------------------------- : */ :static void :miBSPushPixels(pGC, pBitMap, pDst, w, h, x, y) : GCPtr pGC; : PixmapPtr pBitMap; : DrawablePtr pDst; : int w, h, x, y; :{ : SETUP_BACKING (pDst, pGC); : PROLOGUE(pGC); : : (* pGC->ops->PushPixels)(pGC, pBitMap, pDst, w, h, x, y); : if (pGC->miTranslate) { : x -= pDst->x; : y -= pDst->y; : } : (* pBackingGC->ops->PushPixels)(pBackingGC, pBitMap, : pBackingDrawable, w, h, : x - pBackingStore->x, y - pBackingStore->y); : : EPILOGUE (pGC); :} : :/*- : *----------------------------------------------------------------------- : * miBSClearBackingStore -- : * Clear the given area of the backing pixmap with the background of : * the window, whatever it is. If generateExposures is TRUE, generate : * exposure events for the area. Note that if the area has any : * part outside the saved portions of the window, we do not allow the : * count in the expose events to be 0, since there will be more : * expose events to come. : * : * Results: : * None. : * : * Side Effects: : * Areas of pixmap are cleared and Expose events are generated. : * : *----------------------------------------------------------------------- : */ :static RegionPtr :miBSClearBackingStore(pWin, x, y, w, h, generateExposures) : WindowPtr pWin; : int x; : int y; : int w; : int h; : Bool generateExposures; :{ : RegionPtr pRgn; : int i; : miBSWindowPtr pBackingStore; : ScreenPtr pScreen; : GCPtr pGC; : int ts_x_origin, : ts_y_origin; : pointer gcvalues[4]; : unsigned long gcmask; : xRectangle *rects; : BoxPtr pBox; : BoxRec box; : PixUnion background; : char backgroundState; : int numRects; : : pBackingStore = (miBSWindowPtr)pWin->backStorage; : pScreen = pWin->drawable.pScreen; : : if ((pBackingStore->status == StatusNoPixmap) || : (pBackingStore->status == StatusBadAlloc)) : return NullRegion; : : if (w == 0) : w = (int) pWin->drawable.width - x; : if (h == 0) : h = (int) pWin->drawable.height - y; : : box.x1 = x; : box.y1 = y; : box.x2 = x + w; : box.y2 = y + h; : pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); : if (!pRgn) : return NullRegion; : REGION_INTERSECT( pScreen, pRgn, pRgn, &pBackingStore->SavedRegion); : : if (REGION_NOTEMPTY( pScreen, pRgn)) : { : /* : * if clearing entire window, simply make new virtual : * tile. For the root window, we also destroy the pixmap : * to save a pile of memory : */ : if (x == 0 && y == 0 && : w == pWin->drawable.width && : h == pWin->drawable.height) : { : if (!pWin->parent) : miDestroyBSPixmap (pWin); : if (pBackingStore->status != StatusContents) : miTileVirtualBS (pWin); : } : : ts_x_origin = ts_y_origin = 0; : : backgroundState = pWin->backgroundState; : background = pWin->background; : if (backgroundState == ParentRelative) { : WindowPtr pParent; : : pParent = pWin; : while (pParent->backgroundState == ParentRelative) { : ts_x_origin -= pParent->origin.x; : ts_y_origin -= pParent->origin.y; : pParent = pParent->parent; : } : backgroundState = pParent->backgroundState; : background = pParent->background; : } : : if ((backgroundState != None) && : ((pBackingStore->status == StatusContents) || : !SameBackground (pBackingStore->backgroundState, : pBackingStore->background, : backgroundState, : background))) : { : if (!pBackingStore->pBackingPixmap) : miCreateBSPixmap(pWin, NullBox); : : pGC = GetScratchGC(pWin->drawable.depth, pScreen); : if (pGC && pBackingStore->pBackingPixmap) : { : /* : * First take care of any ParentRelative stuff by altering the : * tile/stipple origin to match the coordinates of the upper-left : * corner of the first ancestor without a ParentRelative background. : * This coordinate is, of course, negative. : */ : : if (backgroundState == BackgroundPixel) : { : gcvalues[0] = (pointer) background.pixel; : gcvalues[1] = (pointer)FillSolid; : gcmask = GCForeground|GCFillStyle; : } : else : { : gcvalues[0] = (pointer)FillTiled; : gcvalues[1] = (pointer) background.pixmap; : gcmask = GCFillStyle|GCTile; : } : gcvalues[2] = (pointer)(long)(ts_x_origin - pBackingStore->x); : gcvalues[3] = (pointer)(long)(ts_y_origin - pBackingStore->y); : gcmask |= GCTileStipXOrigin|GCTileStipYOrigin; : DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE); : ValidateGC((DrawablePtr)pBackingStore->pBackingPixmap, pGC); : : /* : * Figure out the array of rectangles to fill and fill them with : * PolyFillRect in the proper mode, as set in the GC above. : */ : numRects = REGION_NUM_RECTS(pRgn); : rects = (xRectangle *)ALLOCATE_LOCAL(numRects*sizeof(xRectangle)); : : if (rects) : { : for (i = 0, pBox = REGION_RECTS(pRgn); : i < numRects; : i++, pBox++) : { : rects[i].x = pBox->x1 - pBackingStore->x; : rects[i].y = pBox->y1 - pBackingStore->y; : rects[i].width = pBox->x2 - pBox->x1; : rects[i].height = pBox->y2 - pBox->y1; : } : (* pGC->ops->PolyFillRect) ( : (DrawablePtr)pBackingStore->pBackingPixmap, : pGC, numRects, rects); : DEALLOCATE_LOCAL(rects); : } : FreeScratchGC(pGC); : } : } : : if (!generateExposures) : { : REGION_DESTROY(pScreen, pRgn); : pRgn = NULL; : } : else : { : /* : * result must be screen relative, but is currently : * drawable relative. : */ : REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, : pWin->drawable.y); : } : } : else : { : REGION_DESTROY( pScreen, pRgn); : pRgn = NULL; : } : return pRgn; :} : :static void :miBSClearBackingRegion (pWin, pRgn) : WindowPtr pWin; : RegionPtr pRgn; :{ : BoxPtr pBox; : int i; : : i = REGION_NUM_RECTS(pRgn); : pBox = REGION_RECTS(pRgn); : while (i--) : { : (void) miBSClearBackingStore(pWin, pBox->x1, pBox->y1, : pBox->x2 - pBox->x1, : pBox->y2 - pBox->y1, : FALSE); : pBox++; : } :} : :/* : * fill a region of the destination with virtual bits : * : * pRgn is to be translated by (x,y) : */ : :static void :miBSFillVirtualBits (pDrawable, pGC, pRgn, x, y, state, pixunion, planeMask) : DrawablePtr pDrawable; : GCPtr pGC; : RegionPtr pRgn; : int x, y; : int state; : PixUnion pixunion; : unsigned long planeMask; :{ : int i; : BITS32 gcmask; : pointer gcval[5]; : xRectangle *pRect; : BoxPtr pBox; : WindowPtr pWin; : int numRects; : : if (state == None) : return; : numRects = REGION_NUM_RECTS(pRgn); : pRect = (xRectangle *)ALLOCATE_LOCAL(numRects * sizeof(xRectangle)); : if (!pRect) : return; : pWin = 0; : if (pDrawable->type != DRAWABLE_PIXMAP) : { : pWin = (WindowPtr) pDrawable; : if (!pWin->backStorage) : pWin = 0; : } : i = 0; : gcmask = 0; : gcval[i++] = (pointer)planeMask; : gcmask |= GCPlaneMask; : if (state == BackgroundPixel) : { : if (pGC->fgPixel != pixunion.pixel) : { : gcval[i++] = (pointer)pixunion.pixel; : gcmask |= GCForeground; : } : if (pGC->fillStyle != FillSolid) : { : gcval[i++] = (pointer)FillSolid; : gcmask |= GCFillStyle; : } : } : else : { : if (pGC->fillStyle != FillTiled) : { : gcval[i++] = (pointer)FillTiled; : gcmask |= GCFillStyle; : } : if (pGC->tileIsPixel || pGC->tile.pixmap != pixunion.pixmap) : { : gcval[i++] = (pointer)pixunion.pixmap; : gcmask |= GCTile; : } : if (pGC->patOrg.x != x) : { : gcval[i++] = (pointer)(long)x; : gcmask |= GCTileStipXOrigin; : } : if (pGC->patOrg.y != y) : { : gcval[i++] = (pointer)(long)y; : gcmask |= GCTileStipYOrigin; : } : } : if (gcmask) : DoChangeGC (pGC, gcmask, (XID *)gcval, 1); : : if (pWin) : (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); : : if (pDrawable->serialNumber != pGC->serialNumber) : ValidateGC (pDrawable, pGC); : : pBox = REGION_RECTS(pRgn); : for (i = numRects; --i >= 0; pBox++, pRect++) : { : pRect->x = pBox->x1 + x; : pRect->y = pBox->y1 + y; : pRect->width = pBox->x2 - pBox->x1; : pRect->height = pBox->y2 - pBox->y1; : } : pRect -= numRects; : (*pGC->ops->PolyFillRect) (pDrawable, pGC, numRects, pRect); : if (pWin) : (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); : DEALLOCATE_LOCAL (pRect); :} : :/*- : *----------------------------------------------------------------------- : * miBSAllocate -- : * Create and install backing store info for a window : * : *----------------------------------------------------------------------- : */ : :static void :miBSAllocate(pWin) : WindowPtr pWin; :{ : miBSWindowPtr pBackingStore; : ScreenPtr pScreen; : : if (pWin->drawable.pScreen->backingStoreSupport == NotUseful) : return; : pScreen = pWin->drawable.pScreen; : if (!(pBackingStore = (miBSWindowPtr)pWin->backStorage)) : { : : pBackingStore = (miBSWindowPtr)xalloc(sizeof(miBSWindowRec)); : if (!pBackingStore) : return; : : pBackingStore->pBackingPixmap = NullPixmap; : pBackingStore->x = 0; : pBackingStore->y = 0; : REGION_NULL( pScreen, &pBackingStore->SavedRegion); : pBackingStore->viewable = (char)pWin->viewable; : pBackingStore->status = StatusNoPixmap; : pBackingStore->backgroundState = None; : pWin->backStorage = (pointer) pBackingStore; : } : : /* : * Now want to initialize the backing pixmap and SavedRegion if : * necessary. The initialization consists of finding all the : * currently-obscured regions, by taking the inverse of the window's : * clip list, storing the result in SavedRegion, and exposing those : * areas of the window. : */ : : if (pBackingStore->status == StatusNoPixmap && : ((pWin->backingStore == WhenMapped && pWin->viewable) || : (pWin->backingStore == Always))) : { : BoxRec box; : RegionPtr pSavedRegion; : : pSavedRegion = &pBackingStore->SavedRegion; : : box.x1 = pWin->drawable.x; : box.x2 = box.x1 + (int) pWin->drawable.width; : box.y1 = pWin->drawable.y; : box.y2 = pWin->drawable.y + (int) pWin->drawable.height; : : REGION_INVERSE( pScreen, pSavedRegion, &pWin->clipList, &box); : REGION_TRANSLATE( pScreen, pSavedRegion, : -pWin->drawable.x, : -pWin->drawable.y); :#ifdef SHAPE : if (wBoundingShape (pWin)) : REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion, : wBoundingShape (pWin)); : if (wClipShape (pWin)) : REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion, : wClipShape (pWin)); :#endif : /* if window is already on-screen, assume it has been drawn to */ : if (pWin->viewable) : pBackingStore->status = StatusVDirty; : miTileVirtualBS (pWin); : : /* : * deliver all the newly available regions : * as exposure events to the window : */ : : miSendExposures(pWin, pSavedRegion, 0, 0); : } : else if (!pWin->viewable) : { : /* : * Turn off backing store when we're not supposed to : * be saving anything : */ : if (pBackingStore->status != StatusNoPixmap) : { : REGION_EMPTY( pScreen, &pBackingStore->SavedRegion); : miDestroyBSPixmap (pWin); : } : } :} : :/*- : *----------------------------------------------------------------------- : * miBSFree -- : * Destroy and free all the stuff associated with the backing-store : * for the given window. : * : * Results: : * None. : * : * Side Effects: : * The backing pixmap and all the regions and GC's are destroyed. : * : *----------------------------------------------------------------------- : */ :static void :miBSFree(pWin) : WindowPtr pWin; :{ : miBSWindowPtr pBackingStore; : ScreenPtr pScreen; : : pScreen = pWin->drawable.pScreen; : : pBackingStore = (miBSWindowPtr)pWin->backStorage; : if (pBackingStore) : { : miDestroyBSPixmap (pWin); : : REGION_UNINIT( pScreen, &pBackingStore->SavedRegion); : : xfree(pBackingStore); : pWin->backStorage = NULL; : } :} : :/*- : *----------------------------------------------------------------------- : * miResizeBackingStore -- : * Alter the size of the backing pixmap as necessary when the : * SavedRegion changes size. The contents of the old pixmap are : * copied/shifted into the new/same pixmap. : * : * Results: : * The new Pixmap is created as necessary. : * : * Side Effects: : * The old pixmap is destroyed. : * : *----------------------------------------------------------------------- : */ :static void :miResizeBackingStore( : WindowPtr pWin, : int dx, /* bits are moving this far */ : int dy, /* bits are moving this far */ : Bool saveBits) /* bits are useful */ :{ : miBSWindowPtr pBackingStore; : PixmapPtr pBackingPixmap; : ScreenPtr pScreen; : GC *pGC; : BoxPtr extents; : PixmapPtr pNewPixmap; : int nx, ny; : int nw, nh; : : pBackingStore = (miBSWindowPtr)(pWin->backStorage); : pBackingPixmap = pBackingStore->pBackingPixmap; : if (!pBackingPixmap) : return; : pScreen = pWin->drawable.pScreen; : extents = REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion); : pNewPixmap = pBackingPixmap; : : nw = extents->x2 - extents->x1; : nh = extents->y2 - extents->y1; : : /* the policy here could be more sophisticated */ : if (nw != pBackingPixmap->drawable.width || : nh != pBackingPixmap->drawable.height) : { : if (!saveBits || !nw || !nh) : { : pNewPixmap = NullPixmap; : pBackingStore->status = StatusNoPixmap; : } : else : { : pNewPixmap = (PixmapPtr)(*pScreen->CreatePixmap) : (pScreen, : nw, nh, : pWin->drawable.depth); : if (!pNewPixmap) : { :#ifdef BSEAGER : pBackingStore->status = StatusNoPixmap; :#else : pBackingStore->status = StatusBadAlloc; :#endif : } : } : } : if (!pNewPixmap) : { : pBackingStore->x = 0; : pBackingStore->y = 0; : } : else : { : nx = pBackingStore->x - extents->x1 + dx; : ny = pBackingStore->y - extents->y1 + dy; : pBackingStore->x = extents->x1; : pBackingStore->y = extents->y1; : : if (saveBits && (pNewPixmap != pBackingPixmap || nx != 0 || ny != 0)) : { : pGC = GetScratchGC(pNewPixmap->drawable.depth, pScreen); : if (pGC) : { : ValidateGC((DrawablePtr)pNewPixmap, pGC); : /* if we implement a policy where the pixmap can be larger than : * the region extents, we might want to optimize this copyarea : * by only copying the old extents, rather than the entire : * pixmap : */ : (*pGC->ops->CopyArea)((DrawablePtr)pBackingPixmap, : (DrawablePtr)pNewPixmap, pGC, : 0, 0, : pBackingPixmap->drawable.width, : pBackingPixmap->drawable.height, : nx, ny); : FreeScratchGC(pGC); : } : } : } : /* SavedRegion is used in the backingGC clip; force an update */ : pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; : if (pNewPixmap != pBackingPixmap) : { : (* pScreen->DestroyPixmap)(pBackingPixmap); : pBackingStore->pBackingPixmap = pNewPixmap; : } :} : :/*- : *----------------------------------------------------------------------- : * miBSSaveDoomedAreas -- : * Saved the areas of the given window that are about to be : * obscured. If the window has moved, pObscured is expected to : * be at the new screen location and (dx,dy) is expected to be the offset : * to the window's previous location. : * : * Results: : * None. : * : * Side Effects: : * The region is copied from the screen into pBackingPixmap and : * SavedRegion is updated. : * : *----------------------------------------------------------------------- : */ :static void :miBSSaveDoomedAreas(pWin, pObscured, dx, dy) : WindowPtr pWin; : RegionPtr pObscured; : int dx, dy; :{ : miBSWindowPtr pBackingStore; : ScreenPtr pScreen; : int x, y; : : pBackingStore = (miBSWindowPtr)pWin->backStorage; : pScreen = pWin->drawable.pScreen; : : /* : * If the window isn't realized, it's being unmapped, thus we don't : * want to save anything if backingStore isn't Always. : */ : if (!pWin->realized) : { : pBackingStore->viewable = (char)pWin->viewable; : if (pWin->backingStore != Always) : { : REGION_EMPTY( pScreen, &pBackingStore->SavedRegion); : miDestroyBSPixmap (pWin); : return; : } : if (pBackingStore->status == StatusBadAlloc) : pBackingStore->status = StatusNoPixmap; : } : : /* Don't even pretend to save anything for a virtual background None */ : if ((pBackingStore->status == StatusVirtual) && : (pBackingStore->backgroundState == None)) : return; : : if (REGION_NOTEMPTY(pScreen, pObscured)) : { : BoxRec oldExtents; : x = pWin->drawable.x; : y = pWin->drawable.y; : REGION_TRANSLATE(pScreen, pObscured, -x, -y); : oldExtents = *REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion); : REGION_UNION( pScreen, &pBackingStore->SavedRegion, : &pBackingStore->SavedRegion, : pObscured); : /* : * only save the bits if we've actually : * started using backing store : */ : if (pBackingStore->status != StatusVirtual) : { : if (!pBackingStore->pBackingPixmap) : miCreateBSPixmap (pWin, &oldExtents); : else : miResizeBackingStore(pWin, 0, 0, TRUE); : : if (pBackingStore->pBackingPixmap) { : if (pBackingStore->x | pBackingStore->y) : { : REGION_TRANSLATE( pScreen, pObscured, : -pBackingStore->x, : -pBackingStore->y); : x += pBackingStore->x; : y += pBackingStore->y; : } : (* pScreen->BackingStoreFuncs.SaveAreas) : (pBackingStore->pBackingPixmap, pObscured, : x - dx, y - dy, pWin); : } : } : REGION_TRANSLATE(pScreen, pObscured, x, y); : } : else : { : if (REGION_BROKEN (pScreen, pObscured)) : { : REGION_EMPTY( pScreen, &pBackingStore->SavedRegion); : miDestroyBSPixmap (pWin); : return; : } : } :} : :/*- : *----------------------------------------------------------------------- : * miBSRestoreAreas -- : * Restore areas from backing-store that are no longer obscured. : * expects prgnExposed to contain a screen-relative area. : * : * Results: : * The region to generate exposure events on (which may be : * different from the region to paint). : * : * Side Effects: : * Areas are copied from pBackingPixmap to the screen. prgnExposed : * is altered to contain the region that could not be restored from : * backing-store. : * : * Notes: : * This is called before sending any exposure events to the client, : * and so might be called if the window has grown. Changing the backing : * pixmap doesn't require revalidating the backingGC because the : * client's next output request will result in a call to ValidateGC, : * since the window clip region has changed, which will in turn call : * miValidateBackingStore. : *----------------------------------------------------------------------- : */ :static RegionPtr :miBSRestoreAreas(pWin, prgnExposed) : WindowPtr pWin; : RegionPtr prgnExposed; :{ : PixmapPtr pBackingPixmap; : miBSWindowPtr pBackingStore; : RegionPtr prgnSaved; : RegionPtr prgnRestored; : ScreenPtr pScreen; : RegionPtr exposures = prgnExposed; : : pScreen = pWin->drawable.pScreen; : pBackingStore = (miBSWindowPtr)pWin->backStorage; : pBackingPixmap = pBackingStore->pBackingPixmap; : : prgnSaved = &pBackingStore->SavedRegion; : : if (pBackingStore->status == StatusContents) : { : REGION_TRANSLATE(pScreen, prgnSaved, pWin->drawable.x, : pWin->drawable.y); : : prgnRestored = REGION_CREATE( pScreen, (BoxPtr)NULL, 1); : REGION_INTERSECT( pScreen, prgnRestored, prgnExposed, prgnSaved); : : /* : * Since prgnExposed is no longer obscured, we no longer : * will have a valid copy of it in backing-store, but there is a valid : * copy of it on screen, so subtract the area we just restored from : * from the area to be exposed. : */ : : if (REGION_NOTEMPTY( pScreen, prgnRestored)) : { : REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed); : REGION_SUBTRACT( pScreen, prgnExposed, prgnExposed, prgnRestored); : : /* : * Do the actual restoration : */ : (* pScreen->BackingStoreFuncs.RestoreAreas) (pBackingPixmap, : prgnRestored, : pWin->drawable.x + pBackingStore->x, : pWin->drawable.y + pBackingStore->y, : pWin); : /* : * if the saved region is completely empty, dispose of the : * backing pixmap, otherwise, retranslate the saved : * region to window relative : */ : : if (REGION_NOTEMPTY(pScreen, prgnSaved)) : { : REGION_TRANSLATE(pScreen, prgnSaved, : -pWin->drawable.x, : -pWin->drawable.y); : miResizeBackingStore(pWin, 0, 0, TRUE); : } : else : miDestroyBSPixmap (pWin); : } : else : REGION_TRANSLATE(pScreen, prgnSaved, : -pWin->drawable.x, -pWin->drawable.y); : REGION_DESTROY( pScreen, prgnRestored); : : } : else if ((pBackingStore->status == StatusVirtual) || : (pBackingStore->status == StatusVDirty)) : { : REGION_TRANSLATE(pScreen, prgnSaved, : pWin->drawable.x, pWin->drawable.y); : exposures = REGION_CREATE( pScreen, NullBox, 1); : if (SameBackground (pBackingStore->backgroundState, : pBackingStore->background, : pWin->backgroundState, : pWin->background)) : { : REGION_SUBTRACT( pScreen, exposures, prgnExposed, prgnSaved); : } : else : { : miTileVirtualBS(pWin); : : /* we need to expose all we have (virtually) retiled */ : REGION_UNION( pScreen, exposures, prgnExposed, prgnSaved); : } : REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed); : REGION_TRANSLATE(pScreen, prgnSaved, : -pWin->drawable.x, -pWin->drawable.y); : } : else if (pWin->viewable && !pBackingStore->viewable && : pWin->backingStore != Always) : { : /* : * The window was just mapped and nothing has been saved in : * backing-store from the last time it was mapped. We want to capture : * any output to regions that are already obscured but there are no : * bits to snag off the screen, so we initialize things just as we did : * in miBSAllocate, above. : */ : BoxRec box; : : prgnSaved = &pBackingStore->SavedRegion; : : box.x1 = pWin->drawable.x; : box.x2 = box.x1 + (int) pWin->drawable.width; : box.y1 = pWin->drawable.y; : box.y2 = box.y1 + (int) pWin->drawable.height; : : REGION_INVERSE( pScreen, prgnSaved, &pWin->clipList, &box); : REGION_TRANSLATE( pScreen, prgnSaved, : -pWin->drawable.x, : -pWin->drawable.y); :#ifdef SHAPE : if (wBoundingShape (pWin)) : REGION_INTERSECT(pScreen, prgnSaved, prgnSaved, : wBoundingShape (pWin)); : if (wClipShape (pWin)) : REGION_INTERSECT(pScreen, prgnSaved, prgnSaved, : wClipShape (pWin)); :#endif : miTileVirtualBS(pWin); : : exposures = REGION_CREATE( pScreen, &box, 1); : } : pBackingStore->viewable = (char)pWin->viewable; : return exposures; :} : : :/*- : *----------------------------------------------------------------------- : * miBSTranslateBackingStore -- : * Shift the backing-store in the given direction. Called when bit : * gravity is shifting things around. : * : * Results: : * An occluded region of the window which should be sent exposure events. : * This region should be in absolute coordinates (i.e. include : * new window position). : * : * Side Effects: : * If the window changed size as well as position, the backing pixmap : * is resized. The contents of the backing pixmap are shifted : * : * Warning: : * Bob and I have rewritten this routine quite a few times, each : * time it gets a few more cases correct, and introducing some : * interesting bugs. Naturally, I think the code is correct this : * time. : * : * Let me try to explain what this routine is for: : * : * It's called from SlideAndSizeWindow whenever a window : * with backing store is resized. There are two separate : * possibilities: : * : * a) The window has ForgetGravity : * : * In this case, windx, windy will be 0 and oldClip will : * be NULL. This indicates that all of the window contents : * currently saved offscreen should be discarded, and the : * entire window exposed. TranslateBackingStore, then, should : * prepare a completely new backing store region based on the : * new window clipList and return that region for exposure. : * : * b) The window has some other gravity : * : * In this case, windx, windy will be set to the distance : * that the bits should move within the window. oldClip : * will be set to the old visible portion of the window. : * TranslateBackingStore, then, should adjust the backing : * store to accommodate the portion of the existing backing : * store bits which coorespond to backing store bits which : * will still be occluded in the new configuration. oldx,oldy : * are set to the old position of the window on the screen. : * : * Furthermore, in this case any contents of the screen which : * are about to become occluded should be fetched from the screen : * and placed in backing store. This is to avoid the eventual : * occlusion by the win gravity shifting the child window bits around : * on top of this window, and potentially losing information : * : * It's also called from SetShape, but I think (he says not : * really knowing for sure) that this code will even work : * in that case. : *----------------------------------------------------------------------- : */ : :static RegionPtr :miBSTranslateBackingStore(pWin, windx, windy, oldClip, oldx, oldy) : WindowPtr pWin; : int windx; /* bit translation distance in window */ : int windy; : RegionPtr oldClip; /* Region being copied */ : int oldx; /* old window position */ : int oldy; :{ : miBSWindowPtr pBackingStore; : RegionPtr pSavedRegion; : RegionPtr newSaved, doomed; : ScreenPtr pScreen; : BoxRec extents; : int scrdx; /* bit translation distance on screen */ : int scrdy; : int dx; /* distance window moved on screen */ : int dy; : : pScreen = pWin->drawable.pScreen; : pBackingStore = (miBSWindowPtr)(pWin->backStorage); : if ((pBackingStore->status == StatusNoPixmap) || : (pBackingStore->status == StatusBadAlloc)) : return NullRegion; : : /* : * Compute the new saved region : */ : : newSaved = REGION_CREATE( pScreen, NullBox, 1); : extents.x1 = pWin->drawable.x; : extents.x2 = pWin->drawable.x + (int) pWin->drawable.width; : extents.y1 = pWin->drawable.y; : extents.y2 = pWin->drawable.y + (int) pWin->drawable.height; : REGION_INVERSE( pScreen, newSaved, &pWin->clipList, &extents); : : REGION_TRANSLATE( pScreen, newSaved, : -pWin->drawable.x, -pWin->drawable.y); :#ifdef SHAPE : if (wBoundingShape (pWin) || wClipShape (pWin)) { : if (wBoundingShape (pWin)) : REGION_INTERSECT( pScreen, newSaved, newSaved, : wBoundingShape (pWin)); : if (wClipShape (pWin)) : REGION_INTERSECT( pScreen, newSaved, newSaved, wClipShape (pWin)); : } :#endif : : pSavedRegion = &pBackingStore->SavedRegion; : : /* now find any visible areas we can save from the screen */ : /* and then translate newSaved to old local coordinates */ : if (oldClip) : { : /* bit gravity makes things virtually too hard, punt */ : if (((windx != 0) || (windy != 0)) && : (pBackingStore->status != StatusContents)) : miCreateBSPixmap(pWin, NullBox); : : /* : * The window is moving this far on the screen : */ : dx = pWin->drawable.x - oldx; : dy = pWin->drawable.y - oldy; : /* : * The bits will be moving on the screen by the : * amount the window is moving + the amount the : * bits are moving within the window : */ : scrdx = windx + dx; : scrdy = windy + dy; : : /* : * intersect at old bit position to discover the : * bits on the screen which can be put into the : * new backing store : */ : REGION_TRANSLATE( pScreen, oldClip, windx - oldx, windy - oldy); : doomed = REGION_CREATE( pScreen, NullBox, 1); : REGION_INTERSECT( pScreen, doomed, oldClip, newSaved); : REGION_TRANSLATE( pScreen, oldClip, oldx - windx, oldy - windy); : : /* : * Translate the old saved region to the position in the : * window where it will appear to be : */ : REGION_TRANSLATE( pScreen, pSavedRegion, windx, windy); : : /* : * Add the old saved region to the new saved region, so : * that calls to RestoreAreas will be able to fetch those : * bits back : */ : REGION_UNION( pScreen, newSaved, newSaved, pSavedRegion); : : /* : * Swap the new saved region into the window : */ : { : RegionRec tmp; : : tmp = *pSavedRegion; : *pSavedRegion = *newSaved; : *newSaved = tmp; : } : miResizeBackingStore (pWin, windx, windy, TRUE); : : /* : * Compute the newly enabled region : * of backing store. This region will be : * set to background in the backing pixmap and : * sent as exposure events to the client. : */ : REGION_SUBTRACT( pScreen, newSaved, pSavedRegion, newSaved); : : /* : * Fetch bits which will be obscured from : * the screen : */ : if (REGION_NOTEMPTY( pScreen, doomed)) : { : /* : * Don't clear regions which have bits on the : * screen : */ : REGION_SUBTRACT( pScreen, newSaved, newSaved, doomed); : : /* : * Make the region to SaveDoomedAreas absolute, instead : * of window relative. : */ : REGION_TRANSLATE( pScreen, doomed, : pWin->drawable.x, pWin->drawable.y); : (* pScreen->SaveDoomedAreas) (pWin, doomed, scrdx, scrdy); : } : : REGION_DESTROY(pScreen, doomed); : : /* : * and clear whatever there is that's new : */ : if (REGION_NOTEMPTY( pScreen, newSaved)) : { : miBSClearBackingRegion (pWin, newSaved); : /* : * Make the exposed region absolute : */ : REGION_TRANSLATE(pScreen, newSaved, : pWin->drawable.x, : pWin->drawable.y); : } : else : { : REGION_DESTROY(pScreen, newSaved); : newSaved = NullRegion; : } : } : else : { : /* : * ForgetGravity: just reset backing store and : * expose the whole mess : */ : REGION_COPY( pScreen, pSavedRegion, newSaved); : REGION_TRANSLATE( pScreen, newSaved, : pWin->drawable.x, pWin->drawable.y); : : miResizeBackingStore (pWin, 0, 0, FALSE); : (void) miBSClearBackingStore (pWin, 0, 0, 0, 0, FALSE); : } : : return newSaved; :} : :/* : * Inform the backing store layer that you are about to validate : * a gc with a window, and that subsequent output to the window : * is (or is not) guaranteed to be already clipped to the visible : * regions of the window. : */ : :static void :miBSDrawGuarantee (pWin, pGC, guarantee) : WindowPtr pWin; : GCPtr pGC; : int guarantee; :{ : miBSGCPtr pPriv; : : if (pWin->backStorage) : { : pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr; : if (!pPriv) : (void) miBSCreateGCPrivate (pGC); : pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr; : if (pPriv) : { : /* : * XXX KLUDGE ALERT : * : * when the GC is Cheap pPriv will point : * at some device's gc func structure. guarantee : * will point at the ChangeGC entry of that struct : * and will never match a valid guarantee value. : */ : switch (pPriv->guarantee) : { : case GuaranteeNothing: : case GuaranteeVisBack: : pPriv->guarantee = guarantee; : break; : } : } : } :} : :#define noBackingCopy (GCGraphicsExposures|GCClipXOrigin|GCClipYOrigin| \ : GCClipMask|GCSubwindowMode| \ : GCTileStipXOrigin|GCTileStipYOrigin) : :/*- : *----------------------------------------------------------------------- : * miBSValidateGC -- : * Wrapper around output-library's ValidateGC routine : * : * Results: : * None. : * : * Side Effects: : * : * Notes: : * The idea here is to perform several functions: : * - All the output calls must be intercepted and routed to : * backing-store as necessary. : * - pGC in the window's devBackingStore must be set up with the : * clip list appropriate for writing to pBackingPixmap (i.e. : * the inverse of the window's clipList intersected with the : * clientClip of the GC). Since the destination for this GC is : * a pixmap, it is sufficient to set the clip list as its : * clientClip. : *----------------------------------------------------------------------- : */ : :static void :miBSValidateGC (pGC, stateChanges, pDrawable) : GCPtr pGC; : unsigned long stateChanges; : DrawablePtr pDrawable; :{ : GCPtr pBackingGC; : miBSWindowPtr pWindowPriv = NULL; : miBSGCPtr pPriv; : WindowPtr pWin; : int lift_functions; : RegionPtr backingCompositeClip = NULL; : : if (pDrawable->type != DRAWABLE_PIXMAP) : { : pWin = (WindowPtr) pDrawable; : pWindowPriv = (miBSWindowPtr) pWin->backStorage; : lift_functions = (pWindowPriv == (miBSWindowPtr) NULL); : } : else : { : pWin = (WindowPtr) NULL; : lift_functions = TRUE; : } : : pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr; : : FUNC_PROLOGUE (pGC, pPriv); : : (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable); : : /* : * rewrap funcs and ops as Validate may have changed them : */ : : pPriv->wrapFuncs = pGC->funcs; : pPriv->wrapOps = pGC->ops; : : if (!lift_functions && ((pPriv->guarantee == GuaranteeVisBack) || : (pWindowPriv->status == StatusNoPixmap) || : (pWindowPriv->status == StatusBadAlloc))) : lift_functions = TRUE; : : /* : * check to see if a new backingCompositeClip region must : * be generated : */ : : if (!lift_functions && : ((pDrawable->serialNumber != pPriv->serialNumber) || : (stateChanges&(GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)))) : { : if (REGION_NOTEMPTY(pGC->pScreen, &pWindowPriv->SavedRegion)) : { : backingCompositeClip = REGION_CREATE(pGC->pScreen, NULL, 1); : if ((pGC->clientClipType == CT_NONE) || : (pGC->clientClipType == CT_PIXMAP)) : { : REGION_COPY(pGC->pScreen, backingCompositeClip, : &pWindowPriv->SavedRegion); : } : else : { : /* : * Make a new copy of the client clip, translated to : * its proper origin. : */ : : REGION_COPY(pGC->pScreen, backingCompositeClip, : pGC->clientClip); : REGION_TRANSLATE(pGC->pScreen, backingCompositeClip, : pGC->clipOrg.x, : pGC->clipOrg.y); : REGION_INTERSECT(pGC->pScreen, backingCompositeClip, : backingCompositeClip, : &pWindowPriv->SavedRegion); : } : if (pGC->subWindowMode == IncludeInferiors) : { : RegionPtr translatedClip; : : /* XXX : * any output in IncludeInferiors mode will not : * be redirected to Inferiors backing store. This : * can be fixed only at great cost to the shadow routines. : */ : translatedClip = NotClippedByChildren (pWin); : REGION_TRANSLATE(pGC->pScreen, translatedClip, : -pDrawable->x, : -pDrawable->y); : REGION_SUBTRACT(pGC->pScreen, backingCompositeClip, : backingCompositeClip, translatedClip); : REGION_DESTROY(pGC->pScreen, translatedClip); : } : if (!REGION_NOTEMPTY(pGC->pScreen, backingCompositeClip)) : lift_functions = TRUE; : } : else : { : lift_functions = TRUE; : } : : /* Reset the status when drawing to an unoccluded window so that : * future SaveAreas will actually copy bits from the screen. Note that : * output to root window in IncludeInferiors mode will not cause this : * to change. This causes all transient graphics by the window : * manager to the root window to not enable backing store. : */ : if (lift_functions && (pWindowPriv->status == StatusVirtual) && : (pWin->parent || pGC->subWindowMode != IncludeInferiors)) : pWindowPriv->status = StatusVDirty; : } : : /* : * if no backing store has been allocated, and it's needed, : * create it now. : */ : : if (!lift_functions && !pWindowPriv->pBackingPixmap) : { : miCreateBSPixmap (pWin, NullBox); : if (!pWindowPriv->pBackingPixmap) : lift_functions = TRUE; : } : : /* : * create the backing GC if needed, lift functions : * if the creation fails : */ : : if (!lift_functions && !pPriv->pBackingGC) : { : int status; : XID noexpose = xFalse; : : /* We never want ops with the backingGC to generate GraphicsExpose */ : pBackingGC = CreateGC ((DrawablePtr)pWindowPriv->pBackingPixmap, : GCGraphicsExposures, &noexpose, &status); : if (status != Success) : lift_functions = TRUE; : else : pPriv->pBackingGC = pBackingGC; : } : : pBackingGC = pPriv->pBackingGC; : : pPriv->stateChanges |= stateChanges; : : if (lift_functions) : { : if (backingCompositeClip) : REGION_DESTROY( pGC->pScreen, backingCompositeClip); : : /* unwrap the GC again */ : miBSDestroyGCPrivate (pGC); : : return; : } : : /* : * the rest of this function gets the pBackingGC : * into shape for possible draws : */ : : pPriv->stateChanges &= ~noBackingCopy; : if (pPriv->stateChanges) : CopyGC(pGC, pBackingGC, pPriv->stateChanges); : if ((pGC->patOrg.x - pWindowPriv->x) != pBackingGC->patOrg.x || : (pGC->patOrg.y - pWindowPriv->y) != pBackingGC->patOrg.y) : { : XID vals[2]; : vals[0] = pGC->patOrg.x - pWindowPriv->x; : vals[1] = pGC->patOrg.y - pWindowPriv->y; : DoChangeGC(pBackingGC, GCTileStipXOrigin|GCTileStipYOrigin, vals, 0); : } : pPriv->stateChanges = 0; : : if (backingCompositeClip) : { : XID vals[2]; : : if (pGC->clientClipType == CT_PIXMAP) : { : (*pBackingGC->funcs->CopyClip)(pBackingGC, pGC); : REGION_TRANSLATE(pGC->pScreen, backingCompositeClip, : -pGC->clipOrg.x, -pGC->clipOrg.y); : vals[0] = pGC->clipOrg.x - pWindowPriv->x; : vals[1] = pGC->clipOrg.y - pWindowPriv->y; : DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0); : (* pGC->pScreen->BackingStoreFuncs.SetClipmaskRgn) : (pBackingGC, backingCompositeClip); : REGION_DESTROY( pGC->pScreen, backingCompositeClip); : } : else : { : vals[0] = -pWindowPriv->x; : vals[1] = -pWindowPriv->y; : DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0); : (*pBackingGC->funcs->ChangeClip) (pBackingGC, CT_REGION, backingCompositeClip, 0); : } : pPriv->serialNumber = pDrawable->serialNumber; : } : : if (pWindowPriv->pBackingPixmap->drawable.serialNumber : != pBackingGC->serialNumber) : { : ValidateGC((DrawablePtr)pWindowPriv->pBackingPixmap, pBackingGC); : } : : if (pBackingGC->clientClip == 0) : ErrorF ("backing store clip list nil"); : : FUNC_EPILOGUE (pGC, pPriv); :} : :static void :miBSChangeGC (pGC, mask) : GCPtr pGC; : unsigned long mask; :{ : miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr; : : FUNC_PROLOGUE (pGC, pPriv); : : (*pGC->funcs->ChangeGC) (pGC, mask); : : FUNC_EPILOGUE (pGC, pPriv); :} : :static void :miBSCopyGC (pGCSrc, mask, pGCDst) : GCPtr pGCSrc, pGCDst; : unsigned long mask; :{ : miBSGCPtr pPriv = (miBSGCPtr) (pGCDst)->devPrivates[miBSGCIndex].ptr; : : FUNC_PROLOGUE (pGCDst, pPriv); : : (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); : : FUNC_EPILOGUE (pGCDst, pPriv); :} : :static void :miBSDestroyGC (pGC) : GCPtr pGC; :{ : miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr; : : FUNC_PROLOGUE (pGC, pPriv); : : if (pPriv->pBackingGC) : FreeGC(pPriv->pBackingGC, (GContext)0); : : (*pGC->funcs->DestroyGC) (pGC); : : FUNC_EPILOGUE (pGC, pPriv); : : xfree(pPriv); :} : :static void :miBSChangeClip(pGC, type, pvalue, nrects) : GCPtr pGC; : int type; : pointer pvalue; : int nrects; :{ : miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr; : : FUNC_PROLOGUE (pGC, pPriv); : : (* pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects); : : FUNC_EPILOGUE (pGC, pPriv); :} : :static void :miBSCopyClip(pgcDst, pgcSrc) : GCPtr pgcDst, pgcSrc; :{ : miBSGCPtr pPriv = (miBSGCPtr) (pgcDst)->devPrivates[miBSGCIndex].ptr; : : FUNC_PROLOGUE (pgcDst, pPriv); : : (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); : : FUNC_EPILOGUE (pgcDst, pPriv); :} : :static void :miBSDestroyClip(pGC) : GCPtr pGC; :{ : miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr; : : FUNC_PROLOGUE (pGC, pPriv); : : (* pGC->funcs->DestroyClip)(pGC); : : FUNC_EPILOGUE (pGC, pPriv); :} : :static void :miDestroyBSPixmap (pWin) : WindowPtr pWin; :{ : miBSWindowPtr pBackingStore; : ScreenPtr pScreen; : : pScreen = pWin->drawable.pScreen; : pBackingStore = (miBSWindowPtr) pWin->backStorage; : if (pBackingStore->pBackingPixmap) : (* pScreen->DestroyPixmap)(pBackingStore->pBackingPixmap); : pBackingStore->pBackingPixmap = NullPixmap; : pBackingStore->x = 0; : pBackingStore->y = 0; : if (pBackingStore->backgroundState == BackgroundPixmap) : (* pScreen->DestroyPixmap)(pBackingStore->background.pixmap); : pBackingStore->backgroundState = None; : pBackingStore->status = StatusNoPixmap; : pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; :} : :static void :miTileVirtualBS (pWin) : WindowPtr pWin; :{ : miBSWindowPtr pBackingStore; : : pBackingStore = (miBSWindowPtr) pWin->backStorage; : if (pBackingStore->backgroundState == BackgroundPixmap) : (* pWin->drawable.pScreen->DestroyPixmap) : (pBackingStore->background.pixmap); : pBackingStore->backgroundState = pWin->backgroundState; : pBackingStore->background = pWin->background; : if (pBackingStore->backgroundState == BackgroundPixmap) : pBackingStore->background.pixmap->refcnt++; : : if (pBackingStore->status != StatusVDirty) : pBackingStore->status = StatusVirtual; : : /* : * punt parent relative tiles and do it now : */ : if (pBackingStore->backgroundState == ParentRelative) : miCreateBSPixmap (pWin, NullBox); :} : :#ifdef DEBUG :static int BSAllocationsFailed = 0; :#define FAILEDSIZE 32 :static struct { int w, h; } failedRecord[FAILEDSIZE]; :static int failedIndex; :#endif : :static void :miCreateBSPixmap (pWin, pExtents) : WindowPtr pWin; : BoxPtr pExtents; :{ : miBSWindowPtr pBackingStore; : ScreenPtr pScreen; : PixUnion background; : char backgroundState = 0; : BoxPtr extents; : Bool backSet; : : pScreen = pWin->drawable.pScreen; : pBackingStore = (miBSWindowPtr) pWin->backStorage; : if (pBackingStore->status == StatusBadAlloc) : return; : backSet = ((pBackingStore->status == StatusVirtual) || : (pBackingStore->status == StatusVDirty)); : : extents = REGION_EXTENTS( pScreen, &pBackingStore->SavedRegion); : : if (!pBackingStore->pBackingPixmap && : extents->x2 != extents->x1 && : extents->y2 != extents->y1) : { : /* the policy here could be more sophisticated */ : pBackingStore->x = extents->x1; : pBackingStore->y = extents->y1; : pBackingStore->pBackingPixmap = : (PixmapPtr)(* pScreen->CreatePixmap) : (pScreen, : extents->x2 - extents->x1, : extents->y2 - extents->y1, : pWin->drawable.depth); : } : if (!pBackingStore->pBackingPixmap) : { :#ifdef DEBUG : BSAllocationsFailed++; : /* : * record failed allocations : */ : failedRecord[failedIndex].w = pWin->drawable.width; : failedRecord[failedIndex].h = pWin->drawable.height; : failedIndex++; : if (failedIndex == FAILEDSIZE) : failedIndex = 0; :#endif :#ifdef BSEAGER : pBackingStore->status = StatusNoPixmap; :#else : pBackingStore->status = StatusBadAlloc; :#endif : return; : } : : pBackingStore->status = StatusContents; : : if (backSet) : { : backgroundState = pWin->backgroundState; : background = pWin->background; : : pWin->backgroundState = pBackingStore->backgroundState; : pWin->background = pBackingStore->background; : if (pWin->backgroundState == BackgroundPixmap) : pWin->background.pixmap->refcnt++; : } : : if (!pExtents) : pExtents = extents; : : if (pExtents->y1 != pExtents->y2) : { : RegionPtr exposed; : : exposed = miBSClearBackingStore(pWin, : pExtents->x1, pExtents->y1, : pExtents->x2 - pExtents->x1, : pExtents->y2 - pExtents->y1, : !backSet); : if (exposed) : { : miSendExposures(pWin, exposed, pWin->drawable.x, pWin->drawable.y); : REGION_DESTROY( pScreen, exposed); : } : } : : if (backSet) : { : if (pWin->backgroundState == BackgroundPixmap) : (* pScreen->DestroyPixmap) (pWin->background.pixmap); : pWin->backgroundState = backgroundState; : pWin->background = background; : if (pBackingStore->backgroundState == BackgroundPixmap) : (* pScreen->DestroyPixmap) (pBackingStore->background.pixmap); : pBackingStore->backgroundState = None; : } :} : :/*- : *----------------------------------------------------------------------- : * miBSExposeCopy -- : * Handle the restoration of areas exposed by graphics operations. : * : * Results: : * None. : * : * Side Effects: : * prgnExposed has the areas exposed from backing-store removed : * from it. : * : *----------------------------------------------------------------------- : */ :static void :miBSExposeCopy (pSrc, pDst, pGC, prgnExposed, srcx, srcy, dstx, dsty, plane) : WindowPtr pSrc; : DrawablePtr pDst; : GCPtr pGC; : RegionPtr prgnExposed; : int srcx, srcy; : int dstx, dsty; : unsigned long plane; :{ : RegionRec tempRgn; : miBSWindowPtr pBackingStore; : CopyPlaneProcPtr copyProc; : GCPtr pScratchGC; : BoxPtr pBox; : int i; : int dx, dy; : BITS32 gcMask; : : if (!REGION_NOTEMPTY(pGC->pScreen, prgnExposed)) : return; : pBackingStore = (miBSWindowPtr)pSrc->backStorage; : : if ((pBackingStore->status == StatusNoPixmap) || : (pBackingStore->status == StatusBadAlloc)) : return; : : REGION_NULL( pGC->pScreen, &tempRgn); : REGION_INTERSECT( pGC->pScreen, &tempRgn, prgnExposed, : &pBackingStore->SavedRegion); : REGION_SUBTRACT( pGC->pScreen, prgnExposed, prgnExposed, &tempRgn); : : if (plane != 0) { : copyProc = pGC->ops->CopyPlane; : } else { : copyProc = (CopyPlaneProcPtr)pGC->ops->CopyArea; : } : : dx = dstx - srcx; : dy = dsty - srcy; : : switch (pBackingStore->status) { : case StatusVirtual: : case StatusVDirty: : pScratchGC = GetScratchGC (pDst->depth, pDst->pScreen); : if (pScratchGC) : { : gcMask = 0; : if (pGC->alu != pScratchGC->alu) : gcMask = GCFunction; : if (pGC->planemask != pScratchGC->planemask) : gcMask |= GCPlaneMask; : if (gcMask) : CopyGC (pGC, pScratchGC, gcMask); : miBSFillVirtualBits (pDst, pScratchGC, &tempRgn, dx, dy, : (int) pBackingStore->backgroundState, : pBackingStore->background, : ~0L); : FreeScratchGC (pScratchGC); : } : break; : case StatusContents: : for (i = REGION_NUM_RECTS(&tempRgn), pBox = REGION_RECTS(&tempRgn); : --i >= 0; : pBox++) : { : (* copyProc) (&(pBackingStore->pBackingPixmap->drawable), pDst, pGC, : pBox->x1 - pBackingStore->x, : pBox->y1 - pBackingStore->y, : pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, : pBox->x1 + dx, pBox->y1 + dy, plane); : } : break; : } : REGION_UNINIT( pGC->pScreen, &tempRgn); :} /* * Total samples for file : "/home/cworth/src/xorg/xserver/dix/devices.c" * * 9 0.0098 */ :/************************************************************ : :Copyright 1987, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :********************************************************/ : : : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#include "misc.h" :#include "resource.h" :#define NEED_EVENTS :#define NEED_REPLIES :#include :#include "windowstr.h" :#include "inputstr.h" :#include "scrnintstr.h" :#include "cursorstr.h" :#include "dixstruct.h" :#include "site.h" :#ifndef XKB_IN_SERVER :#define XKB_IN_SERVER :#endif :#ifdef XKB :#include :#endif :#include "xace.h" : :#include "dispatch.h" :#include "swaprep.h" :#include "dixevents.h" : :#include :#include :#include "exglobals.h" :#include "exevents.h" : :/** @file : * This file handles input device-related stuff. : */ : :int CoreDevicePrivatesIndex = 0; :static int CoreDevicePrivatesGeneration = -1; : :/** : * Create a new input device and init it to sane values. The device is added : * to the server's off_devices list. : * : * @param deviceProc Callback for device control function (switch dev on/off). : * @return The newly created device. : */ :DeviceIntPtr :AddInputDevice(DeviceProc deviceProc, Bool autoStart) :{ : DeviceIntPtr dev, *prev; /* not a typo */ : DeviceIntPtr devtmp; : int devid; : char devind[MAX_DEVICES]; : : /* Find next available id */ : memset(devind, 0, sizeof(char)*MAX_DEVICES); : for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next) : devind[devtmp->id]++; : for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next) : devind[devtmp->id]++; : for (devid = 0; devid < MAX_DEVICES && devind[devid]; devid++) : ; : : if (devid >= MAX_DEVICES) : return (DeviceIntPtr)NULL; : dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec), 1); : if (!dev) : return (DeviceIntPtr)NULL; : dev->name = (char *)NULL; : dev->type = 0; : dev->id = devid; : inputInfo.numDevices++; : dev->public.on = FALSE; : dev->public.processInputProc = (ProcessInputProc)NoopDDA; : dev->public.realInputProc = (ProcessInputProc)NoopDDA; : dev->public.enqueueInputProc = EnqueueEvent; : dev->deviceProc = deviceProc; : dev->startup = autoStart; : dev->sync.frozen = FALSE; : dev->sync.other = NullGrab; : dev->sync.state = NOT_GRABBED; : dev->sync.event = (xEvent *) NULL; : dev->sync.evcount = 0; : dev->grab = NullGrab; : dev->grabTime = currentTime; : dev->fromPassiveGrab = FALSE; : dev->key = (KeyClassPtr)NULL; : dev->valuator = (ValuatorClassPtr)NULL; : dev->button = (ButtonClassPtr)NULL; : dev->focus = (FocusClassPtr)NULL; : dev->proximity = (ProximityClassPtr)NULL; : dev->absolute = (AbsoluteClassPtr)NULL; : dev->kbdfeed = (KbdFeedbackPtr)NULL; : dev->ptrfeed = (PtrFeedbackPtr)NULL; : dev->intfeed = (IntegerFeedbackPtr)NULL; : dev->stringfeed = (StringFeedbackPtr)NULL; : dev->bell = (BellFeedbackPtr)NULL; : dev->leds = (LedFeedbackPtr)NULL; :#ifdef XKB : dev->xkb_interest = NULL; :#endif : dev->nPrivates = 0; : dev->devPrivates = NULL; : dev->unwrapProc = NULL; : dev->coreEvents = TRUE; : dev->inited = FALSE; : dev->enabled = FALSE; : : for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next) : ; : *prev = dev; : dev->next = NULL; : : return dev; :} : :/** : * Switch device ON through the driver and push it onto the global device : * list. All clients are notified about the device being enabled. : * : * A device will send events once enabled. : * : * @param The device to be enabled. : * @return TRUE on success or FALSE otherwise. : */ :Bool :EnableDevice(DeviceIntPtr dev) :{ : DeviceIntPtr *prev; : int ret; : DeviceIntRec dummyDev; : devicePresenceNotify ev; : : for (prev = &inputInfo.off_devices; : *prev && (*prev != dev); : prev = &(*prev)->next) : ; : if ((*prev != dev) || !dev->inited || : ((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) { : ErrorF("couldn't enable device %d\n", dev->id); : return FALSE; : } : dev->enabled = TRUE; : *prev = dev->next; : : for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next) : ; : *prev = dev; : dev->next = NULL; : : ev.type = DevicePresenceNotify; : ev.time = currentTime.milliseconds; : ev.devchange = DeviceEnabled; : ev.deviceid = dev->id; : dummyDev.id = 0; : SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, : (xEvent *) &ev, 1); : : return TRUE; :} : :/** : * Switch a device off through the driver and push it onto the off_devices : * list. A device will not send events while disabled. All clients are : * notified about the device being disabled. : * : * @return TRUE on success or FALSE otherwise. : */ :Bool :DisableDevice(DeviceIntPtr dev) :{ : DeviceIntPtr *prev; : DeviceIntRec dummyDev; : devicePresenceNotify ev; : : for (prev = &inputInfo.devices; : *prev && (*prev != dev); : prev = &(*prev)->next) : ; : if (*prev != dev) : return FALSE; : (void)(*dev->deviceProc)(dev, DEVICE_OFF); : dev->enabled = FALSE; : *prev = dev->next; : dev->next = inputInfo.off_devices; : inputInfo.off_devices = dev; : : ev.type = DevicePresenceNotify; : ev.time = currentTime.milliseconds; : ev.devchange = DeviceDisabled; : ev.deviceid = dev->id; : dummyDev.id = 0; : SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, : (xEvent *) &ev, 1); : : return TRUE; :} : :/** : * Initialise a new device through the driver and tell all clients about the : * new device. : * : * The device will NOT send events until it is enabled! : * : * @return Success or an error code on failure. : */ :int :ActivateDevice(DeviceIntPtr dev) :{ : int ret = Success; : devicePresenceNotify ev; : DeviceIntRec dummyDev; : : if (!dev || !dev->deviceProc) : return BadImplementation; : : ret = (*dev->deviceProc) (dev, DEVICE_INIT); : dev->inited = (ret == Success); : : ev.type = DevicePresenceNotify; : ev.time = currentTime.milliseconds; : ev.devchange = DeviceAdded; : ev.deviceid = dev->id; : dummyDev.id = 0; : SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, : (xEvent *) &ev, 1); : : return ret; :} : :/** : * Ring the bell. : * The actual task of ringing the bell is the job of the DDX. : */ :static void :CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something) :{ : KeybdCtrl *ctrl = arg; : : DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration); :} : :static void :CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl) :{ : return; :} : :/** : * Device control function for the Virtual Core Keyboard. : */ :static int :CoreKeyboardProc(DeviceIntPtr pDev, int what) :{ : CARD8 *modMap; : KeySymsRec keySyms; :#ifdef XKB : XkbComponentNamesRec names; :#endif : : switch (what) { : case DEVICE_INIT: : keySyms.minKeyCode = 8; : keySyms.maxKeyCode = 255; : keySyms.mapWidth = 4; : keySyms.map = (KeySym *)xcalloc(sizeof(KeySym), : (keySyms.maxKeyCode - : keySyms.minKeyCode + 1) * : keySyms.mapWidth); : if (!keySyms.map) { : ErrorF("Couldn't allocate core keymap\n"); : return BadAlloc; : } : : modMap = (CARD8 *)xalloc(MAP_LENGTH); : if (!modMap) { : ErrorF("Couldn't allocate core modifier map\n"); : return BadAlloc; : } : bzero((char *)modMap, MAP_LENGTH); : :#ifdef XKB : if (!noXkbExtension) { : bzero(&names, sizeof(names)); : XkbSetRulesDflts("base", "pc105", "us", NULL, NULL); : XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, modMap, : CoreKeyboardBell, CoreKeyboardCtl); : } : else :#endif : { : /* FIXME Our keymap here isn't exactly useful. */ : InitKeyboardDeviceStruct((DevicePtr)pDev, &keySyms, modMap, : CoreKeyboardBell, CoreKeyboardCtl); : } : : xfree(keySyms.map); : xfree(modMap); : : break; : : case DEVICE_CLOSE: : pDev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL; : break; : : default: : break; : } : return Success; :} : :/** : * Device control function for the Virtual Core Pointer. : */ :static int :CorePointerProc(DeviceIntPtr pDev, int what) :{ : BYTE map[33]; : int i = 0; : : switch (what) { : case DEVICE_INIT: : for (i = 1; i <= 32; i++) : map[i] = i; : InitPointerDeviceStruct((DevicePtr)pDev, map, 32, : GetMotionHistory, (PtrCtrlProcPtr)NoopDDA, : GetMotionHistorySize(), 2); : pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; : pDev->valuator->lastx = pDev->valuator->axisVal[0]; : pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; : pDev->valuator->lasty = pDev->valuator->axisVal[1]; : break; : : case DEVICE_CLOSE: : pDev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL; : break; : : default: : break; : } : : return Success; :} : :/** : * Initialise the two core devices, VCP and VCK (see events.c). : * The devices are activated but not enabled. : * Note that the server MUST have two core devices at all times, even if there : * is no physical device connected. : */ :void :InitCoreDevices(void) :{ : DeviceIntPtr dev; : : if (CoreDevicePrivatesGeneration != serverGeneration) { : CoreDevicePrivatesIndex = AllocateDevicePrivateIndex(); : CoreDevicePrivatesGeneration = serverGeneration; : } : : if (!inputInfo.keyboard) { : dev = AddInputDevice(CoreKeyboardProc, TRUE); : if (!dev) : FatalError("Failed to allocate core keyboard"); : dev->name = strdup("Virtual core keyboard"); :#ifdef XKB : dev->public.processInputProc = CoreProcessKeyboardEvent; : dev->public.realInputProc = CoreProcessKeyboardEvent; : if (!noXkbExtension) : XkbSetExtension(dev, ProcessKeyboardEvent); :#else : dev->public.processInputProc = ProcessKeyboardEvent; : dev->public.realInputProc = ProcessKeyboardEvent; :#endif : dev->ActivateGrab = ActivateKeyboardGrab; : dev->DeactivateGrab = DeactivateKeyboardGrab; : dev->coreEvents = FALSE; : if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex)) : FatalError("Couldn't allocate keyboard devPrivates\n"); : dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL; : (void)ActivateDevice(dev); : inputInfo.keyboard = dev; : } : : if (!inputInfo.pointer) { : dev = AddInputDevice(CorePointerProc, TRUE); : if (!dev) : FatalError("Failed to allocate core pointer"); : dev->name = strdup("Virtual core pointer"); :#ifdef XKB : dev->public.processInputProc = CoreProcessPointerEvent; : dev->public.realInputProc = CoreProcessPointerEvent; : if (!noXkbExtension) : XkbSetExtension(dev, ProcessPointerEvent); :#else : dev->public.processInputProc = ProcessPointerEvent; : dev->public.realInputProc = ProcessPointerEvent; :#endif : dev->ActivateGrab = ActivatePointerGrab; : dev->DeactivateGrab = DeactivatePointerGrab; : dev->coreEvents = FALSE; : if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex)) : FatalError("Couldn't allocate pointer devPrivates\n"); : dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL; : (void)ActivateDevice(dev); : inputInfo.pointer = dev; : } :} : :/** : * Activate all switched-off devices and then enable all those devices. : * : * Will return an error if no core keyboard or core pointer is present. : * In theory this should never happen if you call InitCoreDevices() first. : * : * @return Success or error code on failure. : */ :int :InitAndStartDevices(void) :{ : DeviceIntPtr dev, next; : : for (dev = inputInfo.off_devices; dev; dev = dev->next) { : DebugF("(dix) initialising device %d\n", dev->id); : ActivateDevice(dev); : } : for (dev = inputInfo.off_devices; dev; dev = next) : { : DebugF("(dix) enabling device %d\n", dev->id); : next = dev->next; : if (dev->inited && dev->startup) : (void)EnableDevice(dev); : } : for (dev = inputInfo.devices; : dev && (dev != inputInfo.keyboard); : dev = dev->next) : ; : if (!dev || (dev != inputInfo.keyboard)) { : ErrorF("No core keyboard\n"); : return BadImplementation; : } : for (dev = inputInfo.devices; : dev && (dev != inputInfo.pointer); : dev = dev->next) : ; : if (!dev || (dev != inputInfo.pointer)) { : ErrorF("No core pointer\n"); : return BadImplementation; : } : return Success; :} : :/** : * Close down a device and free all resources. : * Once closed down, the driver will probably not expect you that you'll ever : * enable it again and free associated structs. If you want the device to just : * be disabled, DisableDevice(). : * Don't call this function directly, use RemoveDevice() instead. : */ :static void :CloseDevice(DeviceIntPtr dev) :{ : KbdFeedbackPtr k, knext; : PtrFeedbackPtr p, pnext; : IntegerFeedbackPtr i, inext; : StringFeedbackPtr s, snext; : BellFeedbackPtr b, bnext; : LedFeedbackPtr l, lnext; : : if (dev->inited) : (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); : : xfree(dev->name); : : if (dev->key) { :#ifdef XKB : if (dev->key->xkbInfo) : XkbFreeInfo(dev->key->xkbInfo); :#endif : xfree(dev->key->curKeySyms.map); : xfree(dev->key->modifierKeyMap); : xfree(dev->key); : } : : if (dev->valuator) { : /* Counterpart to 'biggest hack ever' in init. */ : if (dev->valuator->motion && : dev->valuator->GetMotionProc == GetMotionHistory) : xfree(dev->valuator->motion); : xfree(dev->valuator); : } : : if (dev->button) { :#ifdef XKB : if (dev->button->xkb_acts) : xfree(dev->button->xkb_acts); :#endif : xfree(dev->button); : } : : if (dev->focus) { : xfree(dev->focus->trace); : xfree(dev->focus); : } : : if (dev->proximity) : xfree(dev->proximity); : : for (k = dev->kbdfeed; k; k = knext) { : knext = k->next; :#ifdef XKB : if (k->xkb_sli) : XkbFreeSrvLedInfo(k->xkb_sli); :#endif : xfree(k); : } : : for (p = dev->ptrfeed; p; p = pnext) { : pnext = p->next; : xfree(p); : } : : for (i = dev->intfeed; i; i = inext) { : inext = i->next; : xfree(i); : } : : for (s = dev->stringfeed; s; s = snext) { : snext = s->next; : xfree(s->ctrl.symbols_supported); : xfree(s->ctrl.symbols_displayed); : xfree(s); : } : : for (b = dev->bell; b; b = bnext) { : bnext = b->next; : xfree(b); : } : : for (l = dev->leds; l; l = lnext) { : lnext = l->next; :#ifdef XKB : if (l->xkb_sli) : XkbFreeSrvLedInfo(l->xkb_sli); :#endif : xfree(l); : } : :#ifdef XKB : while (dev->xkb_interest) : XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); :#endif : : if (dev->devPrivates) : xfree(dev->devPrivates); : : xfree(dev->sync.event); : xfree(dev); :} : :/** : * Shut down all devices, free all resources, etc. : * Only useful if you're shutting down the server! : */ :void :CloseDownDevices(void) :{ : DeviceIntPtr dev, next; : : for (dev = inputInfo.devices; dev; dev = next) : { : next = dev->next; : CloseDevice(dev); : } : for (dev = inputInfo.off_devices; dev; dev = next) : { : next = dev->next; : CloseDevice(dev); : } : inputInfo.devices = NULL; : inputInfo.off_devices = NULL; : inputInfo.keyboard = NULL; : inputInfo.pointer = NULL; :} : :/** : * Remove a device from the device list, closes it and thus frees all : * resources. : * Removes both enabled and disabled devices and notifies all devices about : * the removal of the device. : */ :int :RemoveDevice(DeviceIntPtr dev) :{ : DeviceIntPtr prev,tmp,next; : int ret = BadMatch; : devicePresenceNotify ev; : DeviceIntRec dummyDev; : int deviceid; : : DebugF("(dix) removing device %d\n", dev->id); : : if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer) : return BadImplementation; : : deviceid = dev->id; : DisableDevice(dev); : : prev = NULL; : for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { : next = tmp->next; : if (tmp == dev) { : CloseDevice(tmp); : : if (prev==NULL) : inputInfo.devices = next; : else : prev->next = next; : : ret = Success; : } : } : : prev = NULL; : for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) { : next = tmp->next; : if (tmp == dev) { : CloseDevice(tmp); : : if (prev == NULL) : inputInfo.off_devices = next; : else : prev->next = next; : : ret = Success; : } : } : : if (ret == Success) { : inputInfo.numDevices--; : ev.type = DevicePresenceNotify; : ev.time = currentTime.milliseconds; : ev.devchange = DeviceRemoved; : ev.deviceid = deviceid; : dummyDev.id = 0; : SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, : (xEvent *) &ev, 1); : } : : return ret; :} : :int :NumMotionEvents(void) :{ : return inputInfo.pointer->valuator->numMotionEvents; :} : :void :RegisterPointerDevice(DeviceIntPtr device) :{ : RegisterOtherDevice(device); :} : :void :RegisterKeyboardDevice(DeviceIntPtr device) :{ : RegisterOtherDevice(device); :} : :_X_EXPORT DevicePtr :LookupKeyboardDevice(void) :{ : return inputInfo.keyboard ? &inputInfo.keyboard->public : NULL; :} : :_X_EXPORT DevicePtr :LookupPointerDevice(void) :{ : return inputInfo.pointer ? &inputInfo.pointer->public : NULL; :} : :DevicePtr :LookupDevice(int id) :{ : DeviceIntPtr dev; : : for (dev=inputInfo.devices; dev; dev=dev->next) { : if (dev->id == (CARD8)id) : return (DevicePtr)dev; : } : for (dev=inputInfo.off_devices; dev; dev=dev->next) { : if (dev->id == (CARD8)id) : return (DevicePtr)dev; : } : return NULL; :} : :void :QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode) :{ : if (inputInfo.keyboard) { : *minCode = inputInfo.keyboard->key->curKeySyms.minKeyCode; : *maxCode = inputInfo.keyboard->key->curKeySyms.maxKeyCode; : } :} : :Bool :SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) :{ : int i, j; : int rowDif = src->minKeyCode - dst->minKeyCode; : : /* if keysym map size changes, grow map first */ : if (src->mapWidth < dst->mapWidth) : { : for (i = src->minKeyCode; i <= src->maxKeyCode; i++) : { :#define SI(r, c) (((r-src->minKeyCode)*src->mapWidth) + (c)) :#define DI(r, c) (((r - dst->minKeyCode)*dst->mapWidth) + (c)) : for (j = 0; j < src->mapWidth; j++) : dst->map[DI(i, j)] = src->map[SI(i, j)]; : for (j = src->mapWidth; j < dst->mapWidth; j++) : dst->map[DI(i, j)] = NoSymbol; :#undef SI :#undef DI : } : return TRUE; : } : else if (src->mapWidth > dst->mapWidth) : { : KeySym *map; : int bytes = sizeof(KeySym) * src->mapWidth * : (dst->maxKeyCode - dst->minKeyCode + 1); : map = (KeySym *)xalloc(bytes); : if (!map) : return FALSE; : bzero((char *)map, bytes); : if (dst->map) : { : for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) : memmove((char *)&map[i*src->mapWidth], : (char *)&dst->map[i*dst->mapWidth], : dst->mapWidth * sizeof(KeySym)); : xfree(dst->map); : } : dst->mapWidth = src->mapWidth; : dst->map = map; : } : memmove((char *)&dst->map[rowDif * dst->mapWidth], : (char *)src->map, : (int)(src->maxKeyCode - src->minKeyCode + 1) * : dst->mapWidth * sizeof(KeySym)); : return TRUE; :} : :static Bool :InitModMap(KeyClassPtr keyc) :{ : int i, j; : CARD8 keysPerModifier[8]; : CARD8 mask; : : keyc->maxKeysPerModifier = 0; : for (i = 0; i < 8; i++) : keysPerModifier[i] = 0; : for (i = 8; i < MAP_LENGTH; i++) : { : for (j = 0, mask = 1; j < 8; j++, mask <<= 1) : { : if (mask & keyc->modifierMap[i]) : { : if (++keysPerModifier[j] > keyc->maxKeysPerModifier) : keyc->maxKeysPerModifier = keysPerModifier[j]; : } : } : } : keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier); : if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier) : return (FALSE); : bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier); : for (i = 0; i < 8; i++) : keysPerModifier[i] = 0; : for (i = 8; i < MAP_LENGTH; i++) : { : for (j = 0, mask = 1; j < 8; j++, mask <<= 1) : { : if (mask & keyc->modifierMap[i]) : { : keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) + : keysPerModifier[j]] = i; : keysPerModifier[j]++; : } : } : } : return TRUE; :} : :_X_EXPORT Bool :InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers[]) :{ : int i; : KeyClassPtr keyc; : : keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec)); : if (!keyc) : return FALSE; : keyc->curKeySyms.map = (KeySym *)NULL; : keyc->curKeySyms.mapWidth = 0; : keyc->curKeySyms.minKeyCode = pKeySyms->minKeyCode; : keyc->curKeySyms.maxKeyCode = pKeySyms->maxKeyCode; : keyc->modifierKeyMap = (KeyCode *)NULL; : keyc->state = 0; : keyc->prev_state = 0; : if (pModifiers) : memmove((char *)keyc->modifierMap, (char *)pModifiers, MAP_LENGTH); : else : bzero((char *)keyc->modifierMap, MAP_LENGTH); : bzero((char *)keyc->down, DOWN_LENGTH); : for (i = 0; i < 8; i++) : keyc->modifierKeyCount[i] = 0; : if (!SetKeySymsMap(&keyc->curKeySyms, pKeySyms) || !InitModMap(keyc)) : { : xfree(keyc->curKeySyms.map); : xfree(keyc->modifierKeyMap); : xfree(keyc); : return FALSE; : } : dev->key = keyc; :#ifdef XKB : dev->key->xkbInfo= NULL; : if (!noXkbExtension) XkbInitDevice(dev); :#endif : return TRUE; :} : :_X_EXPORT Bool :InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, : CARD8 *map) :{ : ButtonClassPtr butc; : int i; : : butc = (ButtonClassPtr)xalloc(sizeof(ButtonClassRec)); : if (!butc) : return FALSE; : butc->numButtons = numButtons; : for (i = 1; i <= numButtons; i++) : butc->map[i] = map[i]; : butc->buttonsDown = 0; : butc->state = 0; : butc->motionMask = 0; : bzero((char *)butc->down, DOWN_LENGTH); :#ifdef XKB : butc->xkb_acts= NULL; :#endif : dev->button = butc; : return TRUE; :} : :_X_EXPORT Bool :InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, : ValuatorMotionProcPtr motionProc, : int numMotionEvents, int mode) :{ : int i; : ValuatorClassPtr valc; : : if (!dev) : return FALSE; : : valc = (ValuatorClassPtr)xalloc(sizeof(ValuatorClassRec) + : numAxes * sizeof(AxisInfo) + : numAxes * sizeof(unsigned int)); : if (!valc) : return FALSE; : : valc->motion = NULL; : valc->first_motion = 0; : valc->last_motion = 0; : valc->GetMotionProc = motionProc; : : valc->numMotionEvents = numMotionEvents; : valc->motionHintWindow = NullWindow; : valc->numAxes = numAxes; : valc->mode = mode; : valc->axes = (AxisInfoPtr)(valc + 1); : valc->axisVal = (int *)(valc->axes + numAxes); : valc->lastx = 0; : valc->lasty = 0; : valc->dxremaind = 0; : valc->dyremaind = 0; : dev->valuator = valc; : : /* biggest hack ever. */ : if (motionProc == GetMotionHistory) : AllocateMotionHistory(dev); : : for (i=0; iaxisVal[i]=0; : } : return TRUE; :} : :_X_EXPORT Bool :InitAbsoluteClassDeviceStruct(DeviceIntPtr dev) :{ : AbsoluteClassPtr abs; : : abs = (AbsoluteClassPtr)xalloc(sizeof(AbsoluteClassRec)); : if (!abs) : return FALSE; : : /* we don't do anything sensible with these, but should */ : abs->min_x = -1; : abs->min_y = -1; : abs->max_x = -1; : abs->max_y = -1; : abs->flip_x = 0; : abs->flip_y = 0; : abs->rotation = 0; : abs->button_threshold = 0; : : abs->offset_x = 0; : abs->offset_y = 0; : abs->width = -1; : abs->height = -1; : abs->following = 0; : abs->screen = 0; : : dev->absolute = abs; : : return TRUE; :} : :_X_EXPORT Bool :InitFocusClassDeviceStruct(DeviceIntPtr dev) :{ : FocusClassPtr focc; : : focc = (FocusClassPtr)xalloc(sizeof(FocusClassRec)); : if (!focc) : return FALSE; : focc->win = PointerRootWin; : focc->revert = None; : focc->time = currentTime; : focc->trace = (WindowPtr *)NULL; : focc->traceSize = 0; : focc->traceGood = 0; : dev->focus = focc; : return TRUE; :} : :_X_EXPORT Bool :InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, : KbdCtrlProcPtr controlProc) :{ : KbdFeedbackPtr feedc; : : feedc = (KbdFeedbackPtr)xalloc(sizeof(KbdFeedbackClassRec)); : if (!feedc) : return FALSE; : feedc->BellProc = bellProc; : feedc->CtrlProc = controlProc; :#ifdef XKB : defaultKeyboardControl.autoRepeat = TRUE; :#endif : feedc->ctrl = defaultKeyboardControl; : feedc->ctrl.id = 0; : if ((feedc->next = dev->kbdfeed) != 0) : feedc->ctrl.id = dev->kbdfeed->ctrl.id + 1; : dev->kbdfeed = feedc; :#ifdef XKB : feedc->xkb_sli= NULL; : if (!noXkbExtension) : XkbFinishDeviceInit(dev); :#endif : (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); : return TRUE; :} : :_X_EXPORT Bool :InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc) :{ : PtrFeedbackPtr feedc; : : feedc = (PtrFeedbackPtr)xalloc(sizeof(PtrFeedbackClassRec)); : if (!feedc) : return FALSE; : feedc->CtrlProc = controlProc; : feedc->ctrl = defaultPointerControl; : feedc->ctrl.id = 0; : if ( (feedc->next = dev->ptrfeed) ) : feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1; : dev->ptrfeed = feedc; : (*controlProc)(dev, &feedc->ctrl); : return TRUE; :} : : :static LedCtrl defaultLedControl = { : DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0}; : :static BellCtrl defaultBellControl = { : DEFAULT_BELL, : DEFAULT_BELL_PITCH, : DEFAULT_BELL_DURATION, : 0}; : :static IntegerCtrl defaultIntegerControl = { : DEFAULT_INT_RESOLUTION, : DEFAULT_INT_MIN_VALUE, : DEFAULT_INT_MAX_VALUE, : DEFAULT_INT_DISPLAYED, : 0}; : :_X_EXPORT Bool :InitStringFeedbackClassDeviceStruct ( : DeviceIntPtr dev, StringCtrlProcPtr controlProc, : int max_symbols, int num_symbols_supported, KeySym *symbols) :{ : int i; : StringFeedbackPtr feedc; : : feedc = (StringFeedbackPtr)xalloc(sizeof(StringFeedbackClassRec)); : if (!feedc) : return FALSE; : feedc->CtrlProc = controlProc; : feedc->ctrl.num_symbols_supported = num_symbols_supported; : feedc->ctrl.num_symbols_displayed = 0; : feedc->ctrl.max_symbols = max_symbols; : feedc->ctrl.symbols_supported = (KeySym *) : xalloc (sizeof (KeySym) * num_symbols_supported); : feedc->ctrl.symbols_displayed = (KeySym *) : xalloc (sizeof (KeySym) * max_symbols); : if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) : { : if (feedc->ctrl.symbols_supported) : xfree(feedc->ctrl.symbols_supported); : if (feedc->ctrl.symbols_displayed) : xfree(feedc->ctrl.symbols_displayed); : xfree(feedc); : return FALSE; : } : for (i=0; ictrl.symbols_supported+i) = *symbols++; : for (i=0; ictrl.symbols_displayed+i) = (KeySym) NULL; : feedc->ctrl.id = 0; : if ( (feedc->next = dev->stringfeed) ) : feedc->ctrl.id = dev->stringfeed->ctrl.id + 1; : dev->stringfeed = feedc; : (*controlProc)(dev, &feedc->ctrl); : return TRUE; :} : :_X_EXPORT Bool :InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, : BellCtrlProcPtr controlProc) :{ : BellFeedbackPtr feedc; : : feedc = (BellFeedbackPtr)xalloc(sizeof(BellFeedbackClassRec)); : if (!feedc) : return FALSE; : feedc->CtrlProc = controlProc; : feedc->BellProc = bellProc; : feedc->ctrl = defaultBellControl; : feedc->ctrl.id = 0; : if ( (feedc->next = dev->bell) ) : feedc->ctrl.id = dev->bell->ctrl.id + 1; : dev->bell = feedc; : (*controlProc)(dev, &feedc->ctrl); : return TRUE; :} : :_X_EXPORT Bool :InitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc) :{ : LedFeedbackPtr feedc; : : feedc = (LedFeedbackPtr)xalloc(sizeof(LedFeedbackClassRec)); : if (!feedc) : return FALSE; : feedc->CtrlProc = controlProc; : feedc->ctrl = defaultLedControl; : feedc->ctrl.id = 0; : if ( (feedc->next = dev->leds) ) : feedc->ctrl.id = dev->leds->ctrl.id + 1; :#ifdef XKB : feedc->xkb_sli= NULL; :#endif : dev->leds = feedc; : (*controlProc)(dev, &feedc->ctrl); : return TRUE; :} : :_X_EXPORT Bool :InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc) :{ : IntegerFeedbackPtr feedc; : : feedc = (IntegerFeedbackPtr)xalloc(sizeof(IntegerFeedbackClassRec)); : if (!feedc) : return FALSE; : feedc->CtrlProc = controlProc; : feedc->ctrl = defaultIntegerControl; : feedc->ctrl.id = 0; : if ( (feedc->next = dev->intfeed) ) : feedc->ctrl.id = dev->intfeed->ctrl.id + 1; : dev->intfeed = feedc; : (*controlProc)(dev, &feedc->ctrl); : return TRUE; :} : :_X_EXPORT Bool :InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, : ValuatorMotionProcPtr motionProc, : PtrCtrlProcPtr controlProc, int numMotionEvents, : int numAxes) :{ : DeviceIntPtr dev = (DeviceIntPtr)device; : : return(InitButtonClassDeviceStruct(dev, numButtons, map) && : InitValuatorClassDeviceStruct(dev, numAxes, motionProc, : numMotionEvents, 0) && : InitPtrFeedbackClassDeviceStruct(dev, controlProc)); :} : :_X_EXPORT Bool :InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, : CARD8 pModifiers[], BellProcPtr bellProc, : KbdCtrlProcPtr controlProc) :{ : DeviceIntPtr dev = (DeviceIntPtr)device; : : return(InitKeyClassDeviceStruct(dev, pKeySyms, pModifiers) && : InitFocusClassDeviceStruct(dev) && : InitKbdFeedbackClassDeviceStruct(dev, bellProc, controlProc)); :} : :_X_EXPORT void :SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, : ClientPtr client) :{ : int i; : xEvent event; : : event.u.u.type = MappingNotify; : event.u.mappingNotify.request = request; : if (request == MappingKeyboard) : { : event.u.mappingNotify.firstKeyCode = firstKeyCode; : event.u.mappingNotify.count = count; : } :#ifdef XKB : if (!noXkbExtension && : ((request == MappingKeyboard) || (request == MappingModifier))) { : XkbApplyMappingChange(inputInfo.keyboard,request,firstKeyCode,count, : client); : } :#endif : : /* 0 is the server client */ : for (i=1; iclientState == ClientStateRunning) : { :#ifdef XKB : if (!noXkbExtension && : (request == MappingKeyboard) && : (clients[i]->xkbClientFlags != 0) && : (clients[i]->mapNotifyMask&XkbKeySymsMask)) : continue; :#endif : event.u.u.sequenceNumber = clients[i]->sequence; : WriteEventsToClient(clients[i], 1, &event); : } : } :} : :/* : * n-squared algorithm. n < 255 and don't want to copy the whole thing and : * sort it to do the checking. How often is it called? Just being lazy? : */ :Bool :BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval) :{ : int i, j; : : for (i = 0; i < length; i++) : if (buff[i]) /* only check non-zero elements */ : { : if ((low > buff[i]) || (high < buff[i])) : { : *errval = buff[i]; : return TRUE; : } : for (j = i + 1; j < length; j++) : if (buff[i] == buff[j]) : { : *errval = buff[i]; : return TRUE; : } : } : return FALSE; :} : :Bool :AllModifierKeysAreUp(dev, map1, per1, map2, per2) : DeviceIntPtr dev; : CARD8 *map1, *map2; : int per1, per2; :{ : int i, j, k; : CARD8 *down = dev->key->down; : : for (i = 8; --i >= 0; map2 += per2) : { : for (j = per1; --j >= 0; map1++) : { : if (*map1 && BitIsOn(down, *map1)) : { : for (k = per2; (--k >= 0) && (*map1 != map2[k]);) : ; : if (k < 0) : return FALSE; : } : } : } : return TRUE; :} : :static int :DoSetModifierMapping(ClientPtr client, KeyCode *inputMap, : int numKeyPerModifier) :{ : DeviceIntPtr pDev = NULL; : int i = 0, inputMapLen = numKeyPerModifier * 8; : : for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { : if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { : for (i = 0; i < inputMapLen; i++) { : /* Check that all the new modifiers fall within the advertised : * keycode range, and are okay with the DDX. */ : if (inputMap[i] && ((inputMap[i] < pDev->key->curKeySyms.minKeyCode || : inputMap[i] > pDev->key->curKeySyms.maxKeyCode) || : !LegalModifier(inputMap[i], pDev))) { : client->errorValue = inputMap[i]; : return BadValue; : } : } : : if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE)) : return BadAccess; : : /* None of the modifiers (old or new) may be down while we change : * the map. */ : if (!AllModifierKeysAreUp(pDev, pDev->key->modifierKeyMap, : pDev->key->maxKeysPerModifier, : inputMap, numKeyPerModifier) || : !AllModifierKeysAreUp(pDev, inputMap, numKeyPerModifier, : pDev->key->modifierKeyMap, : pDev->key->maxKeysPerModifier)) { : return MappingBusy; : } : } : } : : for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { : : if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { : bzero(pDev->key->modifierMap, MAP_LENGTH); : : /* Annoyingly, we lack a modifierKeyMap size, so we have to just free : * and re-alloc it every time. */ : if (pDev->key->modifierKeyMap) : xfree(pDev->key->modifierKeyMap); : : if (inputMapLen) { : pDev->key->modifierKeyMap = (KeyCode *) xalloc(inputMapLen); : if (!pDev->key->modifierKeyMap) : return BadAlloc; : : memcpy(pDev->key->modifierKeyMap, inputMap, inputMapLen); : pDev->key->maxKeysPerModifier = numKeyPerModifier; : : for (i = 0; i < inputMapLen; i++) { : if (inputMap[i]) { : pDev->key->modifierMap[inputMap[i]] |= : (1 << (((unsigned int)i) / numKeyPerModifier)); : } : } : } : else { : pDev->key->modifierKeyMap = NULL; : pDev->key->maxKeysPerModifier = 0; : } : } : } : : return Success; :} : :int :ProcSetModifierMapping(ClientPtr client) :{ : xSetModifierMappingReply rep; : REQUEST(xSetModifierMappingReq); : : REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq); : : if (client->req_len != ((stuff->numKeyPerModifier << 1) + : (sizeof (xSetModifierMappingReq) >> 2))) : return BadLength; : : rep.type = X_Reply; : rep.length = 0; : rep.sequenceNumber = client->sequence; : : rep.success = DoSetModifierMapping(client, (KeyCode *)&stuff[1], : stuff->numKeyPerModifier); : : /* FIXME: Send mapping notifies for all the extended devices as well. */ : SendMappingNotify(MappingModifier, 0, 0, client); : WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); : return client->noClientException; :} : :int :ProcGetModifierMapping(ClientPtr client) :{ : xGetModifierMappingReply rep; : KeyClassPtr keyc = inputInfo.keyboard->key; : : REQUEST_SIZE_MATCH(xReq); : rep.type = X_Reply; : rep.numKeyPerModifier = keyc->maxKeysPerModifier; : rep.sequenceNumber = client->sequence; : /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ : rep.length = keyc->maxKeysPerModifier << 1; : : WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); : : /* Use the (modified by DDX) map that SetModifierMapping passed in */ : (void)WriteToClient(client, (int)(keyc->maxKeysPerModifier << 3), : (char *)keyc->modifierKeyMap); : return client->noClientException; :} : :int :ProcChangeKeyboardMapping(ClientPtr client) :{ : REQUEST(xChangeKeyboardMappingReq); : unsigned len; : KeySymsRec keysyms; : KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; : DeviceIntPtr pDev = NULL; : REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); : : len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2); : if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) : return BadLength; : : if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || : (stuff->firstKeyCode > curKeySyms->maxKeyCode)) { : client->errorValue = stuff->firstKeyCode; : return BadValue; : : } : if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) > : curKeySyms->maxKeyCode) || (stuff->keySymsPerKeyCode == 0)) { : client->errorValue = stuff->keySymsPerKeyCode; : return BadValue; : } : : for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { : if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { : if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE)) : return BadAccess; : } : } : : keysyms.minKeyCode = stuff->firstKeyCode; : keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1; : keysyms.mapWidth = stuff->keySymsPerKeyCode; : keysyms.map = (KeySym *)&stuff[1]; : for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { : if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { : if (!SetKeySymsMap(&pDev->key->curKeySyms, &keysyms)) : return BadAlloc; : } : } : : /* FIXME: Send mapping notifies for all the extended devices as well. */ : SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes, : client); : return client->noClientException; :} : :static int :DoSetPointerMapping(DeviceIntPtr device, BYTE *map, int n) :{ : int i = 0; : DeviceIntPtr dev = NULL; : : if (!device || !device->button) : return BadDevice; : : for (dev = inputInfo.devices; dev; dev = dev->next) { : if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { : for (i = 0; i < n; i++) { : if ((device->button->map[i + 1] != map[i]) && : BitIsOn(device->button->down, i + 1)) { : return MappingBusy; : } : } : } : } : : for (dev = inputInfo.devices; dev; dev = dev->next) { : if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { : for (i = 0; i < n; i++) : dev->button->map[i + 1] = map[i]; : } : } : : return Success; :} : :int :ProcSetPointerMapping(ClientPtr client) :{ : REQUEST(xSetPointerMappingReq); : BYTE *map; : int ret; : xSetPointerMappingReply rep; : : REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); : if (client->req_len != (sizeof(xSetPointerMappingReq)+stuff->nElts+3) >> 2) : return BadLength; : rep.type = X_Reply; : rep.length = 0; : rep.sequenceNumber = client->sequence; : rep.success = MappingSuccess; : map = (BYTE *)&stuff[1]; : : /* So we're bounded here by the number of core buttons. This check : * probably wants disabling through XFixes. */ : if (stuff->nElts != inputInfo.pointer->button->numButtons) { : client->errorValue = stuff->nElts; : return BadValue; : } : if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue)) : return BadValue; : : ret = DoSetPointerMapping(inputInfo.pointer, map, stuff->nElts); : if (ret != Success) { : rep.success = ret; : WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); : return Success; : } : : /* FIXME: Send mapping notifies for all the extended devices as well. */ : SendMappingNotify(MappingPointer, 0, 0, client); : WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); : return Success; :} : :int :ProcGetKeyboardMapping(ClientPtr client) :{ : xGetKeyboardMappingReply rep; : REQUEST(xGetKeyboardMappingReq); : KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; : : REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); : : if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || : (stuff->firstKeyCode > curKeySyms->maxKeyCode)) { : client->errorValue = stuff->firstKeyCode; : return BadValue; : } : if (stuff->firstKeyCode + stuff->count > : (unsigned)(curKeySyms->maxKeyCode + 1)) { : client->errorValue = stuff->count; : return BadValue; : } : : rep.type = X_Reply; : rep.sequenceNumber = client->sequence; : rep.keySymsPerKeyCode = curKeySyms->mapWidth; : /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ : rep.length = (curKeySyms->mapWidth * stuff->count); : WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep); : client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; : WriteSwappedDataToClient( : client, : curKeySyms->mapWidth * stuff->count * sizeof(KeySym), : &curKeySyms->map[(stuff->firstKeyCode - curKeySyms->minKeyCode) * : curKeySyms->mapWidth]); : : return client->noClientException; :} : :int :ProcGetPointerMapping(ClientPtr client) :{ : xGetPointerMappingReply rep; : ButtonClassPtr butc = inputInfo.pointer->button; : : REQUEST_SIZE_MATCH(xReq); : rep.type = X_Reply; : rep.sequenceNumber = client->sequence; : rep.nElts = butc->numButtons; : rep.length = ((unsigned)rep.nElts + (4-1))/4; : WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); : (void)WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]); : return Success; :} : :void :NoteLedState(DeviceIntPtr keybd, int led, Bool on) :{ : KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl; : if (on) : ctrl->leds |= ((Leds)1 << (led - 1)); : else : ctrl->leds &= ~((Leds)1 << (led - 1)); :} : :_X_EXPORT int :Ones(unsigned long mask) /* HACKMEM 169 */ 3 0.0033 :{ /* Ones total: 9 0.0098 */ : unsigned long y; : : y = (mask >> 1) &033333333333; 4 0.0044 : y = mask - y - ((y >>1) & 033333333333); : return (((y + (y >> 3)) & 030707070707) % 077); 2 0.0022 :} : :static int :DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, : BITS32 vmask) :{ :#define DO_ALL (-1) : KeybdCtrl ctrl; : int t; : int led = DO_ALL; : int key = DO_ALL; : BITS32 index2; : int mask = vmask, i; : : ctrl = keybd->kbdfeed->ctrl; : while (vmask) { : index2 = (BITS32) lowbit (vmask); : vmask &= ~index2; : switch (index2) { : case KBKeyClickPercent: : t = (INT8)*vlist; : vlist++; : if (t == -1) { : t = defaultKeyboardControl.click; : } : else if (t < 0 || t > 100) { : client->errorValue = t; : return BadValue; : } : ctrl.click = t; : break; : case KBBellPercent: : t = (INT8)*vlist; : vlist++; : if (t == -1) { : t = defaultKeyboardControl.bell; : } : else if (t < 0 || t > 100) { : client->errorValue = t; : return BadValue; : } : ctrl.bell = t; : break; : case KBBellPitch: : t = (INT16)*vlist; : vlist++; : if (t == -1) { : t = defaultKeyboardControl.bell_pitch; : } : else if (t < 0) { : client->errorValue = t; : return BadValue; : } : ctrl.bell_pitch = t; : break; : case KBBellDuration: : t = (INT16)*vlist; : vlist++; : if (t == -1) : t = defaultKeyboardControl.bell_duration; : else if (t < 0) { : client->errorValue = t; : return BadValue; : } : ctrl.bell_duration = t; : break; : case KBLed: : led = (CARD8)*vlist; : vlist++; : if (led < 1 || led > 32) { : client->errorValue = led; : return BadValue; : } : if (!(mask & KBLedMode)) : return BadMatch; : break; : case KBLedMode: : t = (CARD8)*vlist; : vlist++; : if (t == LedModeOff) { : if (led == DO_ALL) : ctrl.leds = 0x0; : else : ctrl.leds &= ~(((Leds)(1)) << (led - 1)); : } : else if (t == LedModeOn) { : if (led == DO_ALL) : ctrl.leds = ~0L; : else : ctrl.leds |= (((Leds)(1)) << (led - 1)); : } : else { : client->errorValue = t; : return BadValue; : } :#ifdef XKB : if (!noXkbExtension) { : XkbEventCauseRec cause; : XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client); : XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))), : ctrl.leds, &cause); : ctrl.leds = keybd->kbdfeed->ctrl.leds; : } :#endif : break; : case KBKey: : key = (KeyCode)*vlist; : vlist++; : if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode || : (KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) { : client->errorValue = key; : return BadValue; : } : if (!(mask & KBAutoRepeatMode)) : return BadMatch; : break; : case KBAutoRepeatMode: : i = (key >> 3); : mask = (1 << (key & 7)); : t = (CARD8)*vlist; : vlist++; :#ifdef XKB : if (!noXkbExtension && key != DO_ALL) : XkbDisableComputedAutoRepeats(keybd,key); :#endif : if (t == AutoRepeatModeOff) { : if (key == DO_ALL) : ctrl.autoRepeat = FALSE; : else : ctrl.autoRepeats[i] &= ~mask; : } : else if (t == AutoRepeatModeOn) { : if (key == DO_ALL) : ctrl.autoRepeat = TRUE; : else : ctrl.autoRepeats[i] |= mask; : } : else if (t == AutoRepeatModeDefault) { : if (key == DO_ALL) : ctrl.autoRepeat = defaultKeyboardControl.autoRepeat; : else : ctrl.autoRepeats[i] = : (ctrl.autoRepeats[i] & ~mask) | : (defaultKeyboardControl.autoRepeats[i] & mask); : } : else { : client->errorValue = t; : return BadValue; : } : break; : default: : client->errorValue = mask; : return BadValue; : } : } : keybd->kbdfeed->ctrl = ctrl; : :#ifdef XKB : /* The XKB RepeatKeys control and core protocol global autorepeat */ : /* value are linked */ : if (!noXkbExtension) : XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat); : else :#endif : (*keybd->kbdfeed->CtrlProc)(keybd, &keybd->kbdfeed->ctrl); : : return Success; : :#undef DO_ALL :} : :int :ProcChangeKeyboardControl (ClientPtr client) :{ : XID *vlist; : BITS32 vmask; : int ret = Success, error = Success; : DeviceIntPtr pDev = NULL; : REQUEST(xChangeKeyboardControlReq); : : REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); : : vmask = stuff->mask; : vlist = (XID *)&stuff[1]; : : if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask)) : return BadLength; : : for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { : if ((pDev->coreEvents || pDev == inputInfo.keyboard) && : pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { : if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE)) : return BadAccess; : } : } : : for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { : if ((pDev->coreEvents || pDev == inputInfo.keyboard) && : pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { : ret = DoChangeKeyboardControl(client, pDev, vlist, vmask); : if (ret != Success) : error = ret; : } : } : : return error; :} : :int :ProcGetKeyboardControl (ClientPtr client) :{ : int i; : KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl; : xGetKeyboardControlReply rep; : : REQUEST_SIZE_MATCH(xReq); : rep.type = X_Reply; : rep.length = 5; : rep.sequenceNumber = client->sequence; : rep.globalAutoRepeat = ctrl->autoRepeat; : rep.keyClickPercent = ctrl->click; : rep.bellPercent = ctrl->bell; : rep.bellPitch = ctrl->bell_pitch; : rep.bellDuration = ctrl->bell_duration; : rep.ledMask = ctrl->leds; : for (i = 0; i < 32; i++) : rep.map[i] = ctrl->autoRepeats[i]; : WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); : return Success; :} : :int :ProcBell(ClientPtr client) :{ : DeviceIntPtr keybd = inputInfo.keyboard; : int base = keybd->kbdfeed->ctrl.bell; : int newpercent; : REQUEST(xBellReq); : REQUEST_SIZE_MATCH(xBellReq); : : if (!keybd->kbdfeed->BellProc) : return BadDevice; : : if (stuff->percent < -100 || stuff->percent > 100) { : client->errorValue = stuff->percent; : return BadValue; : } : : newpercent = (base * stuff->percent) / 100; : if (stuff->percent < 0) : newpercent = base + newpercent; : else : newpercent = base - newpercent + stuff->percent; : : for (keybd = inputInfo.devices; keybd; keybd = keybd->next) { : if ((keybd->coreEvents || keybd == inputInfo.keyboard) && : keybd->kbdfeed && keybd->kbdfeed->BellProc) { :#ifdef XKB : if (!noXkbExtension) : XkbHandleBell(FALSE, FALSE, keybd, newpercent, : &keybd->kbdfeed->ctrl, 0, None, NULL, client); : else :#endif : (*keybd->kbdfeed->BellProc)(newpercent, keybd, : &keybd->kbdfeed->ctrl, 0); : } : } : : return Success; :} : :int :ProcChangePointerControl(ClientPtr client) :{ : DeviceIntPtr mouse = inputInfo.pointer; : PtrCtrl ctrl; /* might get BadValue part way through */ : REQUEST(xChangePointerControlReq); : : REQUEST_SIZE_MATCH(xChangePointerControlReq); : : if (!mouse->ptrfeed->CtrlProc) : return BadDevice; : : ctrl = mouse->ptrfeed->ctrl; : if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) { : client->errorValue = stuff->doAccel; : return(BadValue); : } : if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) { : client->errorValue = stuff->doThresh; : return(BadValue); : } : if (stuff->doAccel) { : if (stuff->accelNum == -1) { : ctrl.num = defaultPointerControl.num; : } : else if (stuff->accelNum < 0) { : client->errorValue = stuff->accelNum; : return BadValue; : } : else { : ctrl.num = stuff->accelNum; : } : : if (stuff->accelDenum == -1) { : ctrl.den = defaultPointerControl.den; : } : else if (stuff->accelDenum <= 0) { : client->errorValue = stuff->accelDenum; : return BadValue; : } : else { : ctrl.den = stuff->accelDenum; : } : } : if (stuff->doThresh) { : if (stuff->threshold == -1) { : ctrl.threshold = defaultPointerControl.threshold; : } : else if (stuff->threshold < 0) { : client->errorValue = stuff->threshold; : return BadValue; : } : else { : ctrl.threshold = stuff->threshold; : } : } : : : for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { : if ((mouse->coreEvents || mouse == inputInfo.pointer) && : mouse->ptrfeed && mouse->ptrfeed->CtrlProc) { : mouse->ptrfeed->ctrl = ctrl; : (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl); : } : } : : return Success; :} : :int :ProcGetPointerControl(ClientPtr client) :{ : PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl; : xGetPointerControlReply rep; : : REQUEST_SIZE_MATCH(xReq); : rep.type = X_Reply; : rep.length = 0; : rep.sequenceNumber = client->sequence; : rep.threshold = ctrl->threshold; : rep.accelNumerator = ctrl->num; : rep.accelDenominator = ctrl->den; : WriteReplyToClient(client, sizeof(xGenericReply), &rep); : return Success; :} : :void :MaybeStopHint(DeviceIntPtr dev, ClientPtr client) :{ : GrabPtr grab = dev->grab; : : if ((grab && SameClient(grab, client) && : ((grab->eventMask & PointerMotionHintMask) || : (grab->ownerEvents && : (EventMaskForClient(dev->valuator->motionHintWindow, client) & : PointerMotionHintMask)))) || : (!grab && : (EventMaskForClient(dev->valuator->motionHintWindow, client) & : PointerMotionHintMask))) : dev->valuator->motionHintWindow = NullWindow; :} : :int :ProcGetMotionEvents(ClientPtr client) :{ : WindowPtr pWin; : xTimecoord * coords = (xTimecoord *) NULL; : xGetMotionEventsReply rep; : int i, count, xmin, xmax, ymin, ymax, rc; : unsigned long nEvents; : DeviceIntPtr mouse = inputInfo.pointer; : TimeStamp start, stop; : REQUEST(xGetMotionEventsReq); : : REQUEST_SIZE_MATCH(xGetMotionEventsReq); : rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess); : if (rc != Success) : return rc; : if (mouse->valuator->motionHintWindow) : MaybeStopHint(mouse, client); : rep.type = X_Reply; : rep.sequenceNumber = client->sequence; : nEvents = 0; : start = ClientTimeToServerTime(stuff->start); : stop = ClientTimeToServerTime(stuff->stop); : if ((CompareTimeStamps(start, stop) != LATER) && : (CompareTimeStamps(start, currentTime) != LATER) && : mouse->valuator->numMotionEvents) : { : if (CompareTimeStamps(stop, currentTime) == LATER) : stop = currentTime; : coords = (xTimecoord *)ALLOCATE_LOCAL(mouse->valuator->numMotionEvents : * sizeof(xTimecoord)); : if (!coords) : return BadAlloc; : count = (*mouse->valuator->GetMotionProc) (mouse, coords, : start.milliseconds, : stop.milliseconds, : pWin->drawable.pScreen); : xmin = pWin->drawable.x - wBorderWidth (pWin); : xmax = pWin->drawable.x + (int)pWin->drawable.width + : wBorderWidth (pWin); : ymin = pWin->drawable.y - wBorderWidth (pWin); : ymax = pWin->drawable.y + (int)pWin->drawable.height + : wBorderWidth (pWin); : for (i = 0; i < count; i++) : if ((xmin <= coords[i].x) && (coords[i].x < xmax) && : (ymin <= coords[i].y) && (coords[i].y < ymax)) : { : coords[nEvents].time = coords[i].time; : coords[nEvents].x = coords[i].x - pWin->drawable.x; : coords[nEvents].y = coords[i].y - pWin->drawable.y; : nEvents++; : } : } : rep.length = nEvents * (sizeof(xTimecoord) >> 2); : rep.nEvents = nEvents; : WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep); : if (nEvents) : { : client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite; : WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord), : (char *)coords); : } : if (coords) : DEALLOCATE_LOCAL(coords); : return Success; :} : :int :ProcQueryKeymap(ClientPtr client) :{ : xQueryKeymapReply rep; : int i; : CARD8 *down = inputInfo.keyboard->key->down; : : REQUEST_SIZE_MATCH(xReq); : rep.type = X_Reply; : rep.sequenceNumber = client->sequence; : rep.length = 2; : : if (XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE)) : for (i = 0; i<32; i++) : rep.map[i] = down[i]; : else : bzero((char *)&rep.map[0], 32); : : WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); : return Success; :} /* * Total samples for file : "xf86dri.c" * * 8 0.0087 */ 8 0.0087 : /* __i686.get_pc_thunk.cx total: 8 0.0087 */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/dix/extension.c" * * 5 0.0054 */ :/*********************************************************** : :Copyright 1987, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :******************************************************************/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include :#define NEED_EVENTS :#define NEED_REPLIES :#include :#include "misc.h" :#include "dixstruct.h" :#include "extnsionst.h" :#include "gcstruct.h" :#include "scrnintstr.h" :#include "dispatch.h" :#include "xace.h" : :#define EXTENSION_BASE 128 :#define EXTENSION_EVENT_BASE 64 :#define LAST_EVENT 128 :#define LAST_ERROR 255 : :static ExtensionEntry **extensions = (ExtensionEntry **)NULL; : :int lastEvent = EXTENSION_EVENT_BASE; :static int lastError = FirstExtensionError; :static unsigned int NumExtensions = 0; : :extern int extensionPrivateLen; :extern unsigned *extensionPrivateSizes; :extern unsigned totalExtensionSize; : :static void :InitExtensionPrivates(ExtensionEntry *ext) :{ : char *ptr; : DevUnion *ppriv; : unsigned *sizes; : unsigned size; : int i; : : if (totalExtensionSize == sizeof(ExtensionEntry)) : ppriv = (DevUnion *)NULL; : else : ppriv = (DevUnion *)(ext + 1); : : ext->devPrivates = ppriv; : sizes = extensionPrivateSizes; : ptr = (char *)(ppriv + extensionPrivateLen); : for (i = extensionPrivateLen; --i >= 0; ppriv++, sizes++) : { : if ( (size = *sizes) ) : { : ppriv->ptr = (pointer)ptr; : ptr += size; : } : else : ppriv->ptr = (pointer)NULL; : } :} : :_X_EXPORT ExtensionEntry * :AddExtension(char *name, int NumEvents, int NumErrors, : int (*MainProc)(ClientPtr c1), : int (*SwappedMainProc)(ClientPtr c2), : void (*CloseDownProc)(ExtensionEntry *e), : unsigned short (*MinorOpcodeProc)(ClientPtr c3)) :{ : int i; : ExtensionEntry *ext, **newexts; : : if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) : return((ExtensionEntry *) NULL); : if ((lastEvent + NumEvents > LAST_EVENT) || : (unsigned)(lastError + NumErrors > LAST_ERROR)) : return((ExtensionEntry *) NULL); : : ext = (ExtensionEntry *) xalloc(totalExtensionSize); : if (!ext) : return((ExtensionEntry *) NULL); : bzero(ext, totalExtensionSize); : InitExtensionPrivates(ext); : ext->name = (char *)xalloc(strlen(name) + 1); : ext->num_aliases = 0; : ext->aliases = (char **)NULL; : if (!ext->name) : { : xfree(ext); : return((ExtensionEntry *) NULL); : } : strcpy(ext->name, name); : i = NumExtensions; : newexts = (ExtensionEntry **) xrealloc(extensions, : (i + 1) * sizeof(ExtensionEntry *)); : if (!newexts) : { : xfree(ext->name); : xfree(ext); : return((ExtensionEntry *) NULL); : } : NumExtensions++; : extensions = newexts; : extensions[i] = ext; : ext->index = i; : ext->base = i + EXTENSION_BASE; : ext->CloseDown = CloseDownProc; : ext->MinorOpcode = MinorOpcodeProc; : ProcVector[i + EXTENSION_BASE] = MainProc; : SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; : if (NumEvents) : { : ext->eventBase = lastEvent; : ext->eventLast = lastEvent + NumEvents; : lastEvent += NumEvents; : } : else : { : ext->eventBase = 0; : ext->eventLast = 0; : } : if (NumErrors) : { : ext->errorBase = lastError; : ext->errorLast = lastError + NumErrors; : lastError += NumErrors; : } : else : { : ext->errorBase = 0; : ext->errorLast = 0; : } : : return(ext); :} : :_X_EXPORT Bool AddExtensionAlias(char *alias, ExtensionEntry *ext) :{ : char *name; : char **aliases; : : aliases = (char **)xrealloc(ext->aliases, : (ext->num_aliases + 1) * sizeof(char *)); : if (!aliases) : return FALSE; : ext->aliases = aliases; : name = (char *)xalloc(strlen(alias) + 1); : if (!name) : return FALSE; : strcpy(name, alias); : ext->aliases[ext->num_aliases] = name; : ext->num_aliases++; : return TRUE; :} : :static int :FindExtension(char *extname, int len) :{ : int i, j; : : for (i=0; iname) == len) && : !strncmp(extname, extensions[i]->name, len)) : break; : for (j = extensions[i]->num_aliases; --j >= 0;) : { : if ((strlen(extensions[i]->aliases[j]) == len) && : !strncmp(extname, extensions[i]->aliases[j], len)) : break; : } : if (j >= 0) break; : } : return ((i == NumExtensions) ? -1 : i); :} : :/* : * CheckExtension returns the extensions[] entry for the requested : * extension name. Maybe this could just return a Bool instead? : */ :_X_EXPORT ExtensionEntry * :CheckExtension(const char *extname) :{ : int n; : : n = FindExtension((char*)extname, strlen(extname)); : if (n != -1) : return extensions[n]; : else : return NULL; :} : :/* : * Added as part of Xace. : */ :ExtensionEntry * :GetExtensionEntry(int major) 5 0.0054 :{ /* GetExtensionEntry total: 5 0.0054 */ : if (major < EXTENSION_BASE) : return NULL; : major -= EXTENSION_BASE; : if (major >= NumExtensions) : return NULL; : return extensions[major]; :} : :_X_EXPORT void :DeclareExtensionSecurity(char *extname, Bool secure) :{ : int i = FindExtension(extname, strlen(extname)); : if (i >= 0) : XaceHook(XACE_DECLARE_EXT_SECURE, extensions[i], secure); :} : :_X_EXPORT unsigned short :StandardMinorOpcode(ClientPtr client) :{ : return ((xReq *)client->requestBuffer)->data; :} : :_X_EXPORT unsigned short :MinorOpcodeOfRequest(ClientPtr client) :{ : unsigned char major; : : major = ((xReq *)client->requestBuffer)->reqType; : if (major < EXTENSION_BASE) : return 0; : major -= EXTENSION_BASE; : if (major >= NumExtensions) : return 0; : return (*extensions[major]->MinorOpcode)(client); :} : :void :CloseDownExtensions(void) :{ : int i,j; : : for (i = NumExtensions - 1; i >= 0; i--) : { : (* extensions[i]->CloseDown)(extensions[i]); : NumExtensions = i; : xfree(extensions[i]->name); : for (j = extensions[i]->num_aliases; --j >= 0;) : xfree(extensions[i]->aliases[j]); : xfree(extensions[i]->aliases); : xfree(extensions[i]); : } : xfree(extensions); : extensions = (ExtensionEntry **)NULL; : lastEvent = EXTENSION_EVENT_BASE; : lastError = FirstExtensionError; :} : :int :ProcQueryExtension(ClientPtr client) :{ : xQueryExtensionReply reply; : int i; : REQUEST(xQueryExtensionReq); : : REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); : : reply.type = X_Reply; : reply.length = 0; : reply.major_opcode = 0; : reply.sequenceNumber = client->sequence; : : if ( ! NumExtensions ) : reply.present = xFalse; : else : { : i = FindExtension((char *)&stuff[1], stuff->nbytes); : if (i < 0 || !XaceHook(XACE_EXT_ACCESS, client, extensions[i])) : reply.present = xFalse; : else : { : reply.present = xTrue; : reply.major_opcode = extensions[i]->base; : reply.first_event = extensions[i]->eventBase; : reply.first_error = extensions[i]->errorBase; : } : } : WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); : return(client->noClientException); :} : :int :ProcListExtensions(ClientPtr client) :{ : xListExtensionsReply reply; : char *bufptr, *buffer; : int total_length = 0; : : REQUEST_SIZE_MATCH(xReq); : : reply.type = X_Reply; : reply.nExtensions = 0; : reply.length = 0; : reply.sequenceNumber = client->sequence; : buffer = NULL; : : if ( NumExtensions ) : { : int i, j; : : for (i=0; iname) + 1; : reply.nExtensions += 1 + extensions[i]->num_aliases; : for (j = extensions[i]->num_aliases; --j >= 0;) : total_length += strlen(extensions[i]->aliases[j]) + 1; : } : reply.length = (total_length + 3) >> 2; : buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); : if (!buffer) : return(BadAlloc); : for (i=0; iname); : memmove(bufptr, extensions[i]->name, len); : bufptr += len; : for (j = extensions[i]->num_aliases; --j >= 0;) : { : *bufptr++ = len = strlen(extensions[i]->aliases[j]); : memmove(bufptr, extensions[i]->aliases[j], len); : bufptr += len; : } : } : } : WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); : if (reply.length) : { : WriteToClient(client, total_length, buffer); : DEALLOCATE_LOCAL(buffer); : } : return(client->noClientException); :} : :#ifdef XSERVER_DTRACE :void LoadExtensionNames(char **RequestNames) { : int i; : : for (i=0; ibase; : : if (RequestNames[r] == NULL) { : RequestNames[r] = strdup(extensions[i]->name); : } : } :} :#endif /* * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-trap.c" * * 5 0.0054 */ :/* : * $Id$ : * : * Copyright © 2004 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#include :#include :#include "pixman-private.h" : :typedef uint32_t FbBits; : :void :pixman_add_traps (pixman_image_t * image, : int16_t x_off, : int16_t y_off, : int ntrap, : pixman_trap_t *traps) :{ : int bpp; : int width; : int height; : : pixman_fixed_t x_off_fixed; : pixman_fixed_t y_off_fixed; : pixman_edge_t l, r; : pixman_fixed_t t, b; : : width = image->bits.width; : height = image->bits.height; : bpp = PIXMAN_FORMAT_BPP (image->bits.format); : : x_off_fixed = pixman_int_to_fixed(y_off); : y_off_fixed = pixman_int_to_fixed(y_off); : : while (ntrap--) : { : t = traps->top.y + y_off_fixed; : if (t < 0) : t = 0; : t = pixman_sample_ceil_y (t, bpp); : : b = traps->bot.y + y_off_fixed; : if (pixman_fixed_to_int (b) >= height) : b = pixman_int_to_fixed (height) - 1; : b = pixman_sample_floor_y (b, bpp); : : if (b >= t) : { : /* initialize edge walkers */ : pixman_edge_init (&l, bpp, t, : traps->top.l + x_off_fixed, : traps->top.y + y_off_fixed, : traps->bot.l + x_off_fixed, : traps->bot.y + y_off_fixed); : : pixman_edge_init (&r, bpp, t, : traps->top.r + x_off_fixed, : traps->top.y + y_off_fixed, : traps->bot.r + x_off_fixed, : traps->bot.y + y_off_fixed); : : pixman_rasterize_edges (image, &l, &r, t, b); : } : traps++; : } : : fbFinishAccess (pPicture->pDrawable); :} : :static void :dump_image (pixman_image_t *image, : const char *title) :{ : int i, j; : : if (!image->type == BITS) : { : printf ("%s is not a regular image\n", title); : } : : if (!image->bits.format == PIXMAN_a8) : { : printf ("%s is not an alpha mask\n", title); : } : : printf ("\n\n\n%s: \n", title); : : for (i = 0; i < image->bits.height; ++i) : { : uint8_t *line = : (uint8_t *)&(image->bits.bits[i * image->bits.rowstride]); : : for (j = 0; j < image->bits.width; ++j) : printf ("%c", line[j]? '#' : ' '); : : printf ("\n"); : } :} : :void :pixman_add_trapezoids (pixman_image_t *image, : int16_t x_off, : int y_off, : int ntraps, : const pixman_trapezoid_t *traps) :{ : int i; : :#if 0 : dump_image (image, "before"); :#endif : : for (i = 0; i < ntraps; ++i) : { : const pixman_trapezoid_t *trap = &(traps[i]); : : if (!pixman_trapezoid_valid (trap)) : continue; : : pixman_rasterize_trapezoid (image, trap, x_off, y_off); : } : :#if 0 : dump_image (image, "after"); :#endif :} : :void :pixman_rasterize_trapezoid (pixman_image_t * image, : const pixman_trapezoid_t *trap, : int x_off, : int y_off) :{ /* pixman_rasterize_trapezoid total: 5 0.0054 */ : int bpp; : int width; : int height; : : pixman_fixed_t x_off_fixed; : pixman_fixed_t y_off_fixed; : pixman_edge_t l, r; : pixman_fixed_t t, b; : : return_if_fail (image->type == BITS); : 2 0.0022 : if (!pixman_trapezoid_valid (trap)) : return; : : width = image->bits.width; : height = image->bits.height; : bpp = PIXMAN_FORMAT_BPP (image->bits.format); : : x_off_fixed = pixman_int_to_fixed(x_off); : y_off_fixed = pixman_int_to_fixed(y_off); : t = trap->top + y_off_fixed; : if (t < 0) : t = 0; : t = pixman_sample_ceil_y (t, bpp); : : b = trap->bottom + y_off_fixed; : if (pixman_fixed_to_int (b) >= height) : b = pixman_int_to_fixed (height) - 1; : b = pixman_sample_floor_y (b, bpp); : : if (b >= t) : { : /* initialize edge walkers */ : pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off); 3 0.0033 : pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off); : : pixman_rasterize_edges (image, &l, &r, t, b); : } :} : :#if 0 :static int :_GreaterY (pixman_point_fixed_t *a, pixman_point_fixed_t *b) :{ : if (a->y == b->y) : return a->x > b->x; : return a->y > b->y; :} : :/* : * Note that the definition of this function is a bit odd because : * of the X coordinate space (y increasing downwards). : */ :static int :_Clockwise (pixman_point_fixed_t *ref, pixman_point_fixed_t *a, pixman_point_fixed_t *b) :{ : pixman_point_fixed_t ad, bd; : : ad.x = a->x - ref->x; : ad.y = a->y - ref->y; : bd.x = b->x - ref->x; : bd.y = b->y - ref->y; : : return ((pixman_fixed_32_32_t) bd.y * ad.x - (pixman_fixed_32_32_t) ad.y * bd.x) < 0; :} : :/* FIXME -- this could be made more efficient */ :void :fbAddTriangles (pixman_image_t * pPicture, : int16_t x_off, : int16_t y_off, : int ntri, : xTriangle *tris) :{ : pixman_point_fixed_t *top, *left, *right, *tmp; : xTrapezoid trap; : : for (; ntri; ntri--, tris++) : { : top = &tris->p1; : left = &tris->p2; : right = &tris->p3; : if (_GreaterY (top, left)) { : tmp = left; left = top; top = tmp; : } : if (_GreaterY (top, right)) { : tmp = right; right = top; top = tmp; : } : if (_Clockwise (top, right, left)) { : tmp = right; right = left; left = tmp; : } : : /* : * Two cases: : * : * + + : * / \ / \ : * / \ / \ : * / + + \ : * / -- -- \ : * / -- -- \ : * / --- --- \ : * +-- --+ : */ : : trap.top = top->y; : trap.left.p1 = *top; : trap.left.p2 = *left; : trap.right.p1 = *top; : trap.right.p2 = *right; : if (right->y < left->y) : trap.bottom = right->y; : else : trap.bottom = left->y; : fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); : if (right->y < left->y) : { : trap.top = right->y; : trap.bottom = left->y; : trap.right.p1 = *right; : trap.right.p2 = *left; : } : else : { : trap.top = left->y; : trap.bottom = right->y; : trap.left.p1 = *left; : trap.left.p2 = *right; : } : fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); : } :} :#endif /* * Total samples for file : "memcpy.c" * * 4 0.0044 */ 4 0.0044 : /* _dl_load_cache_lookup total: 1 0.0011 */ /* _dl_lookup_symbol_x total: 1 0.0011 */ /* _dl_relocate_object total: 1 0.0011 */ /* strcmp total: 2 0.0022 */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbpict.c" * * 3 0.0033 */ :/* : * : * Copyright © 2000 SuSE, Inc. : * Copyright © 2007 Red Hat, Inc. : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of SuSE not be used in advertising or : * publicity pertaining to distribution of the software without specific, : * written prior permission. SuSE makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE : * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION : * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : * : * Author: Keith Packard, SuSE, Inc. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include : :#include "fb.h" : :#ifdef RENDER : :#include "picturestr.h" :#include "mipict.h" :#include "fbpict.h" : :#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) : :void :fbWalkCompositeRegion (CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height, : Bool srcRepeat, : Bool maskRepeat, : CompositeFunc compositeRect) :{ : RegionRec region; : int n; : BoxPtr pbox; : int w, h, w_this, h_this; : int x_msk, y_msk, x_src, y_src, x_dst, y_dst; : : xDst += pDst->pDrawable->x; : yDst += pDst->pDrawable->y; : if (pSrc->pDrawable) : { : xSrc += pSrc->pDrawable->x; : ySrc += pSrc->pDrawable->y; : } : if (pMask && pMask->pDrawable) : { : xMask += pMask->pDrawable->x; : yMask += pMask->pDrawable->y; : } : : if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, : xMask, yMask, xDst, yDst, width, height)) : return; : : n = REGION_NUM_RECTS (®ion); : pbox = REGION_RECTS (®ion); : while (n--) : { : h = pbox->y2 - pbox->y1; : y_src = pbox->y1 - yDst + ySrc; : y_msk = pbox->y1 - yDst + yMask; : y_dst = pbox->y1; : while (h) : { : h_this = h; : w = pbox->x2 - pbox->x1; : x_src = pbox->x1 - xDst + xSrc; : x_msk = pbox->x1 - xDst + xMask; : x_dst = pbox->x1; : if (maskRepeat) : { : y_msk = mod (y_msk - pMask->pDrawable->y, pMask->pDrawable->height); : if (h_this > pMask->pDrawable->height - y_msk) : h_this = pMask->pDrawable->height - y_msk; : y_msk += pMask->pDrawable->y; : } : if (srcRepeat) : { : y_src = mod (y_src - pSrc->pDrawable->y, pSrc->pDrawable->height); : if (h_this > pSrc->pDrawable->height - y_src) : h_this = pSrc->pDrawable->height - y_src; : y_src += pSrc->pDrawable->y; : } : while (w) : { : w_this = w; : if (maskRepeat) : { : x_msk = mod (x_msk - pMask->pDrawable->x, pMask->pDrawable->width); : if (w_this > pMask->pDrawable->width - x_msk) : w_this = pMask->pDrawable->width - x_msk; : x_msk += pMask->pDrawable->x; : } : if (srcRepeat) : { : x_src = mod (x_src - pSrc->pDrawable->x, pSrc->pDrawable->width); : if (w_this > pSrc->pDrawable->width - x_src) : w_this = pSrc->pDrawable->width - x_src; : x_src += pSrc->pDrawable->x; : } : (*compositeRect) (op, pSrc, pMask, pDst, : x_src, y_src, x_msk, y_msk, x_dst, y_dst, : w_this, h_this); : w -= w_this; : x_src += w_this; : x_msk += w_this; : x_dst += w_this; : } : h -= h_this; : y_src += h_this; : y_msk += h_this; : y_dst += h_this; : } : pbox++; : } : REGION_UNINIT (pDst->pDrawable->pScreen, ®ion); :} : :void :fbComposite (CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) :{ : pixman_image_t *src, *mask, *dest; : : xDst += pDst->pDrawable->x; : yDst += pDst->pDrawable->y; : if (pSrc->pDrawable) : { : xSrc += pSrc->pDrawable->x; : ySrc += pSrc->pDrawable->y; : } : if (pMask && pMask->pDrawable) : { : xMask += pMask->pDrawable->x; : yMask += pMask->pDrawable->y; : } : : miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height); : if (pMask) : miCompositeSourceValidate (pMask, xMask, yMask, width, height); : : src = image_from_pict (pSrc, TRUE); : mask = image_from_pict (pMask, TRUE); : dest = image_from_pict (pDst, TRUE); : : if (src && dest && !(pMask && !mask)) : { : pixman_image_composite (op, src, mask, dest, : xSrc, ySrc, xMask, yMask, xDst, yDst, : width, height); : : } : : if (src) : pixman_image_unref (src); : if (mask) : pixman_image_unref (mask); : if (dest) : pixman_image_unref (dest); :} : :void :fbCompositeGeneral (CARD8 op, : PicturePtr pSrc, : PicturePtr pMask, : PicturePtr pDst, : INT16 xSrc, : INT16 ySrc, : INT16 xMask, : INT16 yMask, : INT16 xDst, : INT16 yDst, : CARD16 width, : CARD16 height) :{ : return fbComposite (op, pSrc, pMask, pDst, : xSrc, ySrc, xMask, yMask, xDst, yDst, : width, height); :} : :#endif /* RENDER */ : :static pixman_image_t * :create_solid_fill_image (PicturePtr pict) :{ : PictSolidFill *solid = &pict->pSourcePict->solidFill; : pixman_color_t color; : CARD32 a, r, g, b; : : a = (solid->color & 0xff000000) >> 24; : r = (solid->color & 0x00ff0000) >> 16; : g = (solid->color & 0x0000ff00) >> 8; : b = (solid->color & 0x000000ff) >> 0; : : color.alpha = (a << 8) | a; : color.red = (r << 8) | r; : color.green = (g << 8) | g; : color.blue = (b << 8) | b; : : return pixman_image_create_solid_fill (&color); :} : :static pixman_image_t * :create_linear_gradient_image (PictGradient *gradient) :{ : PictLinearGradient *linear = (PictLinearGradient *)gradient; : pixman_point_fixed_t p1; : pixman_point_fixed_t p2; : : p1.x = linear->p1.x; : p1.y = linear->p1.y; : p2.x = linear->p2.x; : p2.y = linear->p2.y; : : return pixman_image_create_linear_gradient ( : &p1, &p2, (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); :} : :static pixman_image_t * :create_radial_gradient_image (PictGradient *gradient) :{ : PictRadialGradient *radial = (PictRadialGradient *)gradient; : pixman_point_fixed_t c1; : pixman_point_fixed_t c2; : : c1.x = radial->c1.x; : c1.y = radial->c1.y; : c2.x = radial->c2.x; : c2.y = radial->c2.y; : : return pixman_image_create_radial_gradient ( : &c1, &c2, radial->c1.radius, : radial->c2.radius, : (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); :} : :static pixman_image_t * :create_conical_gradient_image (PictGradient *gradient) :{ : PictConicalGradient *conical = (PictConicalGradient *)gradient; : pixman_point_fixed_t center; : : center.x = conical->center.x; : center.y = conical->center.y; : : return pixman_image_create_conical_gradient ( : ¢er, conical->angle, (pixman_gradient_stop_t *)gradient->stops, : gradient->nstops); :} : :static pixman_image_t * :create_bits_picture (PicturePtr pict, : Bool has_clip) :{ : FbBits *bits; : FbStride stride; : int bpp, xoff, yoff; : pixman_image_t *image; : : fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff); : : bits += yoff * stride + xoff; : : image = pixman_image_create_bits ( : pict->format, : pict->pDrawable->width, pict->pDrawable->height, : (uint32_t *)bits, stride * sizeof (FbStride)); : : :#ifdef FB_ACCESS_WRAPPER :#if FB_SHIFT==5 : : pixman_image_set_accessors (image, : (pixman_read_memory_func_t)wfbReadMemory, : (pixman_write_memory_func_t)wfbWriteMemory); : :#else : :#error The pixman library only works when FbBits is 32 bits wide : :#endif :#endif : : /* pCompositeClip is undefined for source pictures, so : * only set the clip region for pictures with drawables : */ : if (has_clip) : { : if (pict->clientClipType != CT_NONE) : pixman_image_set_has_client_clip (image, TRUE); : : pixman_image_set_clip_region (image, pict->pCompositeClip); : } : : /* Indexed table */ : if (pict->pFormat->index.devPrivate) : pixman_image_set_indexed (image, pict->pFormat->index.devPrivate); : : fbFinishAccess (pict->pDrawable); : : return image; :} : :static void :set_image_properties (pixman_image_t *image, PicturePtr pict) :{ : pixman_repeat_t repeat; : pixman_filter_t filter; : : if (pict->transform) : { : pixman_image_set_transform ( : image, (pixman_transform_t *)pict->transform); : } : : switch (pict->repeatType) : { : default: : case RepeatNone: : repeat = PIXMAN_REPEAT_NONE; : break; : : case RepeatPad: : repeat = PIXMAN_REPEAT_PAD; : break; : : case RepeatNormal: : repeat = PIXMAN_REPEAT_NORMAL; : break; : : case RepeatReflect: : repeat = PIXMAN_REPEAT_REFLECT; : break; : } : : pixman_image_set_repeat (image, repeat); : : if (pict->alphaMap) : { : pixman_image_t *alpha_map = image_from_pict (pict->alphaMap, TRUE); : : pixman_image_set_alpha_map ( : image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y); : : pixman_image_unref (alpha_map); : } : : pixman_image_set_component_alpha (image, pict->componentAlpha); : : switch (pict->filter) : { : default: : case PictFilterNearest: : case PictFilterFast: : filter = PIXMAN_FILTER_NEAREST; : break; : : case PictFilterBilinear: : case PictFilterGood: : filter = PIXMAN_FILTER_BILINEAR; : break; : : case PictFilterConvolution: : filter = PIXMAN_FILTER_CONVOLUTION; : break; : } : : pixman_image_set_filter (image, filter, (pixman_fixed_t *)pict->filter_params, pict->filter_nparams); :} : :pixman_image_t * :image_from_pict (PicturePtr pict, : Bool has_clip) 3 0.0033 :{ /* image_from_pict total: 4 0.0044 */ : pixman_image_t *image = NULL; : : if (!pict) : return NULL; : : if (pict->pDrawable) : { : image = create_bits_picture (pict, has_clip); : } : else if (pict->pSourcePict) : { : SourcePict *sp = pict->pSourcePict; : : if (sp->type == SourcePictTypeSolidFill) : { : image = create_solid_fill_image (pict); : } : else : { : PictGradient *gradient = &pict->pSourcePict->gradient; : : if (sp->type == SourcePictTypeLinear) : image = create_linear_gradient_image (gradient); : else if (sp->type == SourcePictTypeRadial) : image = create_radial_gradient_image (gradient); : else if (sp->type == SourcePictTypeConical) : image = create_conical_gradient_image (gradient); : } : } : : if (image) : set_image_properties (image, pict); : : return image; :} : :Bool :fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) :{ : :#ifdef RENDER : : PictureScreenPtr ps; : : if (!miPictureInit (pScreen, formats, nformats)) : return FALSE; : ps = GetPictureScreen(pScreen); : ps->Composite = fbComposite; : ps->Glyphs = miGlyphs; : ps->CompositeRects = miCompositeRects; : ps->RasterizeTrapezoid = fbRasterizeTrapezoid; : ps->AddTraps = fbAddTraps; : ps->AddTriangles = fbAddTriangles; : :#endif /* RENDER */ : : return TRUE; :} /* * Total samples for file : "/home/cworth/src/xorg/driver/xf86-video-intel/src/i830_render.c" * * 3 0.0033 */ :/* : * Copyright © 2006 Intel Corporation : * : * Permission is hereby granted, free of charge, to any person obtaining a : * copy of this software and associated documentation files (the "Software"), : * to deal in the Software without restriction, including without limitation : * the rights to use, copy, modify, merge, publish, distribute, sublicense, : * and/or sell copies of the Software, and to permit persons to whom the : * Software is furnished to do so, subject to the following conditions: : * : * The above copyright notice and this permission notice (including the next : * paragraph) shall be included in all copies or substantial portions of the : * Software. : * : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE : * SOFTWARE. : * : * Authors: : * Wang Zhenyu : * Eric Anholt : * : */ : :#ifdef HAVE_CONFIG_H :#include "config.h" :#endif : :#include "xf86.h" :#include "i830.h" :#include "i830_reg.h" : :#ifdef I830DEBUG :#define DEBUG_I830FALLBACK 1 :#endif : :#ifdef DEBUG_I830FALLBACK :#define I830FALLBACK(s, arg...) \ :do { \ : DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \ : return FALSE; \ :} while(0) :#else :#define I830FALLBACK(s, arg...) \ :do { \ : return FALSE; \ :} while(0) :#endif : :struct blendinfo { : Bool dst_alpha; : Bool src_alpha; : CARD32 src_blend; : CARD32 dst_blend; :}; : :struct formatinfo { : int fmt; : CARD32 card_fmt; :}; : :#define TB0C_LAST_STAGE (1 << 31) :#define TB0C_RESULT_SCALE_1X (0 << 29) :#define TB0C_RESULT_SCALE_2X (1 << 29) :#define TB0C_RESULT_SCALE_4X (2 << 29) :#define TB0C_OP_MODULE (3 << 25) :#define TB0C_OUTPUT_WRITE_CURRENT (0 << 24) :#define TB0C_OUTPUT_WRITE_ACCUM (1 << 24) :#define TB0C_ARG3_REPLICATE_ALPHA (1<<23) :#define TB0C_ARG3_INVERT (1<<22) :#define TB0C_ARG3_SEL_XXX :#define TB0C_ARG2_REPLICATE_ALPHA (1<<17) :#define TB0C_ARG2_INVERT (1<<16) :#define TB0C_ARG2_SEL_ONE (0 << 12) :#define TB0C_ARG2_SEL_FACTOR (1 << 12) :#define TB0C_ARG2_SEL_TEXEL0 (6 << 12) :#define TB0C_ARG2_SEL_TEXEL1 (7 << 12) :#define TB0C_ARG2_SEL_TEXEL2 (8 << 12) :#define TB0C_ARG2_SEL_TEXEL3 (9 << 12) :#define TB0C_ARG1_REPLICATE_ALPHA (1<<11) :#define TB0C_ARG1_INVERT (1<<10) :#define TB0C_ARG1_SEL_ONE (0 << 6) :#define TB0C_ARG1_SEL_TEXEL0 (6 << 6) :#define TB0C_ARG1_SEL_TEXEL1 (7 << 6) :#define TB0C_ARG1_SEL_TEXEL2 (8 << 6) :#define TB0C_ARG1_SEL_TEXEL3 (9 << 6) :#define TB0C_ARG0_REPLICATE_ALPHA (1<<5) :#define TB0C_ARG0_SEL_XXX : :#define TB0A_CTR_STAGE_ENABLE (1<<31) :#define TB0A_RESULT_SCALE_1X (0 << 29) :#define TB0A_RESULT_SCALE_2X (1 << 29) :#define TB0A_RESULT_SCALE_4X (2 << 29) :#define TB0A_OP_MODULE (3 << 25) :#define TB0A_OUTPUT_WRITE_CURRENT (0<<24) :#define TB0A_OUTPUT_WRITE_ACCUM (1<<24) :#define TB0A_CTR_STAGE_SEL_BITS_XXX :#define TB0A_ARG3_SEL_XXX :#define TB0A_ARG3_INVERT (1<<17) :#define TB0A_ARG2_INVERT (1<<16) :#define TB0A_ARG2_SEL_ONE (0 << 12) :#define TB0A_ARG2_SEL_TEXEL0 (6 << 12) :#define TB0A_ARG2_SEL_TEXEL1 (7 << 12) :#define TB0A_ARG2_SEL_TEXEL2 (8 << 12) :#define TB0A_ARG2_SEL_TEXEL3 (9 << 12) :#define TB0A_ARG1_INVERT (1<<10) :#define TB0A_ARG1_SEL_ONE (0 << 6) :#define TB0A_ARG1_SEL_TEXEL0 (6 << 6) :#define TB0A_ARG1_SEL_TEXEL1 (7 << 6) :#define TB0A_ARG1_SEL_TEXEL2 (8 << 6) :#define TB0A_ARG1_SEL_TEXEL3 (9 << 6) : :static struct blendinfo i830_blend_op[] = { : /* Clear */ : {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO}, : /* Src */ : {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO}, : /* Dst */ : {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE}, : /* Over */ : {0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA}, : /* OverReverse */ : {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE}, : /* In */ : {1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO}, : /* InReverse */ : {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA}, : /* Out */ : {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO}, : /* OutReverse */ : {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA}, : /* Atop */ : {1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, : /* AtopReverse */ : {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA}, : /* Xor */ : {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, : /* Add */ : {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE}, :}; : :static struct formatinfo i830_tex_formats[] = { : {PICT_a8r8g8b8, MT_32BIT_ARGB8888 }, : {PICT_x8r8g8b8, MT_32BIT_XRGB8888 }, : {PICT_a8b8g8r8, MT_32BIT_ABGR8888 }, : {PICT_x8b8g8r8, MT_32BIT_XBGR8888 }, : {PICT_r5g6b5, MT_16BIT_RGB565 }, : {PICT_a1r5g5b5, MT_16BIT_ARGB1555 }, : {PICT_x1r5g5b5, MT_16BIT_ARGB1555 }, : {PICT_a8, MT_8BIT_A8 }, :}; : :static Bool i830_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format) :{ : switch (pDstPicture->format) { : case PICT_a8r8g8b8: : case PICT_x8r8g8b8: : *dst_format = COLR_BUF_ARGB8888; : break; : case PICT_r5g6b5: : *dst_format = COLR_BUF_RGB565; : break; : case PICT_a1r5g5b5: : case PICT_x1r5g5b5: : *dst_format = COLR_BUF_ARGB1555; : break; : /* : case PICT_a8: : *dst_format = COLR_BUF_8BIT; : break; : */ : case PICT_a4r4g4b4: : case PICT_x4r4g4b4: : *dst_format = COLR_BUF_ARGB4444; : break; : default: : I830FALLBACK("Unsupported dest format 0x%x\n", : (int)pDstPicture->format); : } : : return TRUE; :} : : :static CARD32 i830_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format) :{ : CARD32 sblend, dblend; : : sblend = i830_blend_op[op].src_blend; : dblend = i830_blend_op[op].dst_blend; : : /* If there's no dst alpha channel, adjust the blend op so that we'll treat : * it as always 1. : */ : if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) { : if (sblend == BLENDFACTOR_DST_ALPHA) : sblend = BLENDFACTOR_ONE; : else if (sblend == BLENDFACTOR_INV_DST_ALPHA) : sblend = BLENDFACTOR_ZERO; : } : : /* If the source alpha is being used, then we should only be in a case : * where the source blend factor is 0, and the source blend value is the : * mask channels multiplied by the source picture's alpha. : */ : if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) : && i830_blend_op[op].src_alpha) { : if (dblend == BLENDFACTOR_SRC_ALPHA) { : dblend = BLENDFACTOR_SRC_COLR; : } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) { : dblend = BLENDFACTOR_INV_SRC_COLR; : } : } : : return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | : (dblend << S8_DST_BLEND_FACTOR_SHIFT); :} : :static Bool i830_check_composite_texture(PicturePtr pPict, int unit) :{ : ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : int w = pPict->pDrawable->width; : int h = pPict->pDrawable->height; : int i; : : if ((w > 0x7ff) || (h > 0x7ff)) : I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h); : : for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]); : i++) : { : if (i830_tex_formats[i].fmt == pPict->format) : break; : } : if (i == sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0])) : I830FALLBACK("Unsupported picture format 0x%x\n", : (int)pPict->format); : : if (IS_I830(pI830) || IS_845G(pI830)) { : if (pPict->format == PICT_x8r8g8b8 || : pPict->format == PICT_x8b8g8r8 || : pPict->format == PICT_a8) : I830FALLBACK("830/845G don't support a8, x8r8g8b8, x8b8g8r8\n"); : } : : if (pPict->repeat && pPict->repeatType != RepeatNormal) : I830FALLBACK("unsupport repeat type\n"); : : if (pPict->filter != PictFilterNearest && : pPict->filter != PictFilterBilinear) : { : I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter); : } : : return TRUE; :} : :static CARD32 :i8xx_get_card_format(PicturePtr pPict) :{ : int i; : for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]); : i++) : { : if (i830_tex_formats[i].fmt == pPict->format) : break; : } : return i830_tex_formats[i].card_fmt; :} : :static Bool :i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit) :{ : : ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : CARD32 format, offset, pitch, filter; : CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER; : : offset = intel_get_pixmap_offset(pPix); : pitch = intel_get_pixmap_pitch(pPix); : pI830->scale_units[unit][0] = pPix->drawable.width; : pI830->scale_units[unit][1] = pPix->drawable.height; : pI830->transform[unit] = pPict->transform; : : format = i8xx_get_card_format(pPict); : : if (pPict->repeat) : wrap_mode = TEXCOORDMODE_WRAP; : : switch (pPict->filter) { : case PictFilterNearest: : filter = ((FILTER_NEAREST<filter); : } : filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); : : { : if (pPix->drawable.bitsPerPixel == 8) : format |= MAPSURF_8BIT; : else if (pPix->drawable.bitsPerPixel == 16) : format |= MAPSURF_16BIT; : else : format |= MAPSURF_32BIT; : : BEGIN_LP_RING(10); : OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4); : OUT_RING((offset & TM0S0_ADDRESS_MASK) | TM0S0_USE_FENCE); : OUT_RING(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) | : ((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format); : OUT_RING((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D); : OUT_RING(filter); : OUT_RING(0); /* default color */ : OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | : ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | : TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | : TEXCOORD_ADDR_V_MODE(wrap_mode) | : ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode)); : /* map texel stream */ : OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD); : if (unit == 0) : OUT_RING(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | : TEXBIND_SET1(TEXCOORDSRC_KEEP) | : TEXBIND_SET2(TEXCOORDSRC_KEEP) | : TEXBIND_SET3(TEXCOORDSRC_KEEP)); : else : OUT_RING(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | : TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | : TEXBIND_SET2(TEXCOORDSRC_KEEP) | : TEXBIND_SET3(TEXCOORDSRC_KEEP)); : OUT_RING(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) | : DISABLE_TEX_STREAM_BUMP | : ENABLE_TEX_STREAM_COORD_SET | : TEX_STREAM_COORD_SET(unit) | : ENABLE_TEX_STREAM_MAP_IDX | : TEX_STREAM_MAP_IDX(unit)); : ADVANCE_LP_RING(); : } : :#ifdef I830DEBUG : ErrorF("try to sync to show any errors..."); : I830Sync(pScrn); :#endif : : return TRUE; :} : :Bool :i830_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, : PicturePtr pDstPicture) :{ : CARD32 tmp1; : : /* Check for unsupported compositing operations. */ : if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0])) : I830FALLBACK("Unsupported Composite op 0x%x\n", op); : : if (pMaskPicture != NULL && pMaskPicture->componentAlpha && : PICT_FORMAT_RGB(pMaskPicture->format)) { : /* Check if it's component alpha that relies on a source alpha and on : * the source value. We can only get one of those into the single : * source value that we get to blend with. : */ : if (i830_blend_op[op].src_alpha && : (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) : I830FALLBACK("Component alpha not supported with source " : "alpha and source value blending.\n"); : } : : if (!i830_check_composite_texture(pSrcPicture, 0)) : I830FALLBACK("Check Src picture texture\n"); : if (pMaskPicture != NULL && !i830_check_composite_texture(pMaskPicture, 1)) : I830FALLBACK("Check Mask picture texture\n"); : : if (!i830_get_dest_format(pDstPicture, &tmp1)) : I830FALLBACK("Get Color buffer format\n"); : : return TRUE; :} : :Bool :i830_prepare_composite(int op, PicturePtr pSrcPicture, : PicturePtr pMaskPicture, PicturePtr pDstPicture, : PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) :{ : ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : CARD32 dst_format, dst_offset, dst_pitch; : : IntelEmitInvarientState(pScrn); : *pI830->last_3d = LAST_3D_RENDER; : : i830_get_dest_format(pDstPicture, &dst_format); : dst_offset = intel_get_pixmap_offset(pDst); : dst_pitch = intel_get_pixmap_pitch(pDst); : : if (!i830_texture_setup(pSrcPicture, pSrc, 0)) : I830FALLBACK("fail to setup src texture\n"); : if (pMask != NULL) { : if (!i830_texture_setup(pMaskPicture, pMask, 1)) : I830FALLBACK("fail to setup mask texture\n"); : } else { : pI830->transform[1] = NULL; : pI830->scale_units[1][0] = -1; : pI830->scale_units[1][1] = -1; : } : : { : CARD32 cblend, ablend, blendctl, vf2; : : BEGIN_LP_RING(30); : : /* color buffer */ : OUT_RING(_3DSTATE_BUF_INFO_CMD); : OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch)); : OUT_RING(BUF_3D_ADDR(dst_offset)); : OUT_RING(MI_NOOP); : : OUT_RING(_3DSTATE_DST_BUF_VARS_CMD); : OUT_RING(dst_format); : : /* defaults */ : OUT_RING(_3DSTATE_DFLT_Z_CMD); : OUT_RING(0); : : OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD); : OUT_RING(0); : : OUT_RING(_3DSTATE_DFLT_SPEC_CMD); : OUT_RING(0); : : OUT_RING(_3DSTATE_DRAW_RECT_CMD); : OUT_RING(0); : OUT_RING(0); /* ymin, xmin */ : OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) | : DRAW_XMAX(pDst->drawable.width - 1)); : OUT_RING(0); /* yorig, xorig */ : : OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | : I1_LOAD_S(3) | 1); : if (pMask) : vf2 = 2 << 12; /* 2 texture coord sets */ : else : vf2 = 1 << 12; : OUT_RING(vf2); /* TEXCOORDFMT_2D */ : OUT_RING(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); : : /* We use two pipes for color and alpha, and do (src In mask) : in one stage. Arg1 is from src pict, and arg2 is from mask pict. : Be sure to force 1.0 when src or mask pict has no alpha channel. : */ : cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE | : TB0C_OUTPUT_WRITE_CURRENT; : ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | : TB0A_OUTPUT_WRITE_CURRENT; : : if (PICT_FORMAT_A(pSrcPicture->format) != 0) { : ablend |= TB0A_ARG1_SEL_TEXEL0; : cblend |= TB0C_ARG1_SEL_TEXEL0; : } else { : ablend |= TB0A_ARG1_SEL_ONE; : if (pMask && pMaskPicture->componentAlpha : && PICT_FORMAT_RGB(pMaskPicture->format) : && i830_blend_op[op].src_alpha) : cblend |= TB0C_ARG1_SEL_ONE; : else : cblend |= TB0C_ARG1_SEL_TEXEL0; : } : : if (pMask) { : if (pMaskPicture->componentAlpha && : PICT_FORMAT_RGB(pMaskPicture->format)) { : if (i830_blend_op[op].src_alpha) : cblend |= (TB0C_ARG2_SEL_TEXEL1 | : TB0C_ARG1_REPLICATE_ALPHA); : else : cblend |= TB0C_ARG2_SEL_TEXEL1; : } else { : if (PICT_FORMAT_A(pMaskPicture->format) != 0) : cblend |= (TB0C_ARG2_SEL_TEXEL1 | : TB0C_ARG2_REPLICATE_ALPHA); : else : cblend |= TB0C_ARG2_SEL_ONE; : } : if (PICT_FORMAT_A(pMaskPicture->format) != 0) : ablend |= TB0A_ARG2_SEL_TEXEL1; : else : ablend |= TB0A_ARG2_SEL_ONE; : } else { : cblend |= TB0C_ARG2_SEL_ONE; : ablend |= TB0A_ARG2_SEL_ONE; : } : : OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | : LOAD_TEXTURE_BLEND_STAGE(0)|1); : OUT_RING(cblend); : OUT_RING(ablend); : OUT_RING(0); : : blendctl = i830_get_blend_cntl(op, pMaskPicture, pDstPicture->format); : OUT_RING(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND); : OUT_RING(MI_NOOP); : OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0); : OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | blendctl | : S8_ENABLE_COLOR_BUFFER_WRITE); : : OUT_RING(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP | : DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS | : DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST | : ENABLE_COLOR_BLEND | DISABLE_DEPTH_TEST); : /* We have to explicitly say we don't want write disabled */ : OUT_RING(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK | : DISABLE_STENCIL_WRITE | ENABLE_TEX_CACHE | : DISABLE_DITHER | ENABLE_COLOR_WRITE | : DISABLE_DEPTH_WRITE); : ADVANCE_LP_RING(); : } : :#ifdef I830DEBUG : Error("try to sync to show any errors..."); : I830Sync(pScrn); :#endif : : return TRUE; :} : : :/** : * Do a single rectangle composite operation. : * : * This function is shared between i830 and i915 generation code. : */ :void :i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, : int dstX, int dstY, int w, int h) :{ : ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; : I830Ptr pI830 = I830PTR(pScrn); : Bool has_mask; : float src_x[3], src_y[3], mask_x[3], mask_y[3]; : : i830_get_transformed_coordinates(srcX, srcY, : pI830->transform[0], : &src_x[0], &src_y[0]); : i830_get_transformed_coordinates(srcX, srcY + h, : pI830->transform[0], : &src_x[1], &src_y[1]); : i830_get_transformed_coordinates(srcX + w, srcY + h, : pI830->transform[0], : &src_x[2], &src_y[2]); : : if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) { : has_mask = FALSE; : } else { : has_mask = TRUE; : i830_get_transformed_coordinates(maskX, maskY, : pI830->transform[1], : &mask_x[0], &mask_y[0]); : i830_get_transformed_coordinates(maskX, maskY + h, : pI830->transform[1], : &mask_x[1], &mask_y[1]); : i830_get_transformed_coordinates(maskX + w, maskY + h, : pI830->transform[1], : &mask_x[2], &mask_y[2]); : } : : { : int vertex_count; : : if (has_mask) : vertex_count = 3*6; : else : vertex_count = 3*4; : : BEGIN_LP_RING(6+vertex_count); : : OUT_RING(MI_NOOP); : OUT_RING(MI_NOOP); : OUT_RING(MI_NOOP); : OUT_RING(MI_NOOP); : OUT_RING(MI_NOOP); : : OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (vertex_count-1)); : : OUT_RING_F(-0.125 + dstX + w); : OUT_RING_F(-0.125 + dstY + h); : OUT_RING_F(src_x[2] / pI830->scale_units[0][0]); : OUT_RING_F(src_y[2] / pI830->scale_units[0][1]); : if (has_mask) { : OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]); : OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]); : } : : OUT_RING_F(-0.125 + dstX); : OUT_RING_F(-0.125 + dstY + h); : OUT_RING_F(src_x[1] / pI830->scale_units[0][0]); : OUT_RING_F(src_y[1] / pI830->scale_units[0][1]); : if (has_mask) { : OUT_RING_F(mask_x[1] / pI830->scale_units[1][0]); : OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]); : } : : OUT_RING_F(-0.125 + dstX); : OUT_RING_F(-0.125 + dstY); : OUT_RING_F(src_x[0] / pI830->scale_units[0][0]); : OUT_RING_F(src_y[0] / pI830->scale_units[0][1]); : if (has_mask) { : OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]); : OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]); : } : ADVANCE_LP_RING(); : } :} : :/** : * Do any cleanup from the Composite operation. : * : * This is shared between i830 through i965. : */ :void :i830_done_composite(PixmapPtr pDst) 2 0.0022 :{ /* i830_done_composite total: 3 0.0033 */ : /* NO-OP */ 1 0.0011 :} /* * Total samples for file : "/home/cworth/src/pixman/pixman/pixman-edge.c" * * 3 0.0033 */ :/* : * $Id$ : * : * Copyright © 2004 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ :#include :#include :#include "pixman.h" :#include "pixman-private.h" : :#ifdef PIXMAN_FB_ACCESSORS :#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors :#else :#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors :#endif : :/* : * 4 bit alpha : */ : :#define N_BITS 4 :#define rasterizeEdges fbRasterizeEdges4 : :#if BITMAP_BIT_ORDER == LSBFirst :#define Shift4(o) ((o) << 2) :#else :#define Shift4(o) ((1-(o)) << 2) :#endif : :#define Get4(x,o) (((x) >> Shift4(o)) & 0xf) :#define Put4(x,o,v) (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o))) : :#define DefineAlpha(line,x) \ : uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \ : int __ao = (x) & 1 : :#define StepAlpha ((__ap += __ao), (__ao ^= 1)) : :#define AddAlpha(a) { \ : uint8_t __o = READ(__ap); \ : uint8_t __a = (a) + Get4(__o, __ao); \ : WRITE(__ap, Put4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \ : } : :#include "pixman-edge-imp.h" : :#undef AddAlpha :#undef StepAlpha :#undef DefineAlpha :#undef rasterizeEdges :#undef N_BITS : : :/* : * 1 bit alpha : */ : :#define N_BITS 1 :#define rasterizeEdges fbRasterizeEdges1 : :#include "pixman-edge-imp.h" : :#undef rasterizeEdges :#undef N_BITS : :/* : * 8 bit alpha : */ : :static inline uint8_t :clip255 (int x) :{ : if (x > 255) return 255; : return x; :} : :#define add_saturate_8(buf,val,length) \ : do { \ : int i__ = (length); \ : uint8_t *buf__ = (buf); \ : int val__ = (val); \ : \ : while (i__--) \ : { \ : WRITE((buf__), clip255 (READ((buf__)) + (val__))); \ : (buf__)++; \ : } \ : } while (0) : :/* : * We want to detect the case where we add the same value to a long : * span of pixels. The triangles on the end are filled in while we : * count how many sub-pixel scanlines contribute to the middle section. : * : * +--------------------------+ : * fill_height =| \ / : * +------------------+ : * |================| : * fill_start fill_end : */ :static void :fbRasterizeEdges8 (pixman_image_t *image, : pixman_edge_t *l, : pixman_edge_t *r, : pixman_fixed_t t, : pixman_fixed_t b) :{ : pixman_fixed_t y = t; : uint32_t *line; : int fill_start = -1, fill_end = -1; : int fill_size = 0; : uint32_t *buf = (image)->bits.bits; : uint32_t stride = (image)->bits.rowstride; : uint32_t width = (image)->bits.width; : : line = buf + pixman_fixed_to_int (y) * stride; : : for (;;) : { : uint8_t *ap = (uint8_t *) line; : pixman_fixed_t lx, rx; : int lxi, rxi; : : /* clip X */ : lx = l->x; : if (lx < 0) : lx = 0; : rx = r->x; : if (pixman_fixed_to_int (rx) >= width) : rx = pixman_int_to_fixed (width); : : /* Skip empty (or backwards) sections */ : if (rx > lx) : { : int lxs, rxs; : : /* Find pixel bounds for span. */ : lxi = pixman_fixed_to_int (lx); : rxi = pixman_fixed_to_int (rx); : : /* Sample coverage for edge pixels */ : lxs = RenderSamplesX (lx, 8); : rxs = RenderSamplesX (rx, 8); : : /* Add coverage across row */ : if (lxi == rxi) : { : WRITE(ap +lxi, clip255 (READ(ap + lxi) + rxs - lxs)); : } : else : { : WRITE(ap + lxi, clip255 (READ(ap + lxi) + N_X_FRAC(8) - lxs)); : : /* Move forward so that lxi/rxi is the pixel span */ : lxi++; : : /* Don't bother trying to optimize the fill unless : * the span is longer than 4 pixels. */ : if (rxi - lxi > 4) : { : if (fill_start < 0) : { : fill_start = lxi; : fill_end = rxi; : fill_size++; : } : else : { : if (lxi >= fill_end || rxi < fill_start) : { : /* We're beyond what we saved, just fill it */ : add_saturate_8 (ap + fill_start, : fill_size * N_X_FRAC(8), : fill_end - fill_start); : fill_start = lxi; : fill_end = rxi; : fill_size = 1; : } : else : { : /* Update fill_start */ : if (lxi > fill_start) : { : add_saturate_8 (ap + fill_start, : fill_size * N_X_FRAC(8), : lxi - fill_start); : fill_start = lxi; : } : else if (lxi < fill_start) : { : add_saturate_8 (ap + lxi, N_X_FRAC(8), : fill_start - lxi); : } : : /* Update fill_end */ : if (rxi < fill_end) : { : add_saturate_8 (ap + rxi, : fill_size * N_X_FRAC(8), : fill_end - rxi); : fill_end = rxi; : } : else if (fill_end < rxi) : { : add_saturate_8 (ap + fill_end, : N_X_FRAC(8), : rxi - fill_end); : } : fill_size++; : } : } : } : else : { : add_saturate_8 (ap + lxi, N_X_FRAC(8), rxi - lxi); : } : : /* Do not add in a 0 alpha here. This check is : * necessary to avoid a buffer overrun, (when rx : * is exactly on a pixel boundary). */ : if (rxs) : WRITE(ap + rxi, clip255 (READ(ap + rxi) + rxs)); : } : } : : if (y == b) { : /* We're done, make sure we clean up any remaining fill. */ : if (fill_start != fill_end) { : if (fill_size == N_Y_FRAC(8)) : { : MEMSET_WRAPPED (ap + fill_start, 0xff, fill_end - fill_start); : } : else : { : add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8), : fill_end - fill_start); : } : } : break; : } : : if (pixman_fixed_frac (y) != Y_FRAC_LAST(8)) : { : RenderEdgeStepSmall (l); : RenderEdgeStepSmall (r); : y += STEP_Y_SMALL(8); : } : else : { : RenderEdgeStepBig (l); : RenderEdgeStepBig (r); : y += STEP_Y_BIG(8); : if (fill_start != fill_end) : { : if (fill_size == N_Y_FRAC(8)) : { : MEMSET_WRAPPED (ap + fill_start, 0xff, fill_end - fill_start); : } : else : { : add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8), : fill_end - fill_start); : } : fill_start = fill_end = -1; : fill_size = 0; : } : line += stride; : } : } :} : :#ifndef PIXMAN_FB_ACCESSORS :static :#endif :void :PIXMAN_RASTERIZE_EDGES (pixman_image_t *image, : pixman_edge_t *l, : pixman_edge_t *r, : pixman_fixed_t t, : pixman_fixed_t b) :{ : switch (PIXMAN_FORMAT_BPP (image->bits.format)) : { : case 1: : fbRasterizeEdges1 (image, l, r, t, b); : break; : case 4: : fbRasterizeEdges4 (image, l, r, t, b); : break; : case 8: : fbRasterizeEdges8 (image, l, r, t, b); : break; : } :} : :#ifndef PIXMAN_FB_ACCESSORS : :void :pixman_rasterize_edges (pixman_image_t *image, : pixman_edge_t *l, : pixman_edge_t *r, : pixman_fixed_t t, : pixman_fixed_t b) :{ /* pixman_rasterize_edges total: 5402 5.8849 */ 2 0.0022 : if (image->common.read_func || image->common.write_func) : { : return pixman_rasterize_edges_accessors (image, l, r, t, b); : } : else : { : return pixman_rasterize_edges_no_accessors (image, l, r, t, b); : } 1 0.0011 :} : :#endif /* * Total samples for file : "/home/cworth/src/xorg/xserver/os/WaitFor.c" * * 2 0.0022 */ :/*********************************************************** : :Copyright 1987, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included in :all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR :IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, :FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE :OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN :AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN :CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall not be :used in advertising or otherwise to promote the sale, use or other dealings :in this Software without prior written authorization from The Open Group. : : :Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. : : All Rights Reserved : :Permission to use, copy, modify, and distribute this software and its :documentation for any purpose and without fee is hereby granted, :provided that the above copyright notice appear in all copies and that :both that copyright notice and this permission notice appear in :supporting documentation, and that the name of Digital not be :used in advertising or publicity pertaining to distribution of the :software without specific, written prior permission. : :DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING :ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL :DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR :ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, :WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, :ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS :SOFTWARE. : :******************************************************************/ : : :/***************************************************************** : * OS Dependent input routines: : * : * WaitForSomething : * TimerForce, TimerSet, TimerCheck, TimerFree : * : *****************************************************************/ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#ifdef WIN32 :#include :#endif :#include /* for strings, fcntl, time */ :#include :#include :#include :#include "misc.h" : :#include "osdep.h" :#include :#include "dixstruct.h" :#include "opaque.h" :#ifdef DPMSExtension :#include "dpmsproc.h" :#endif : :#ifdef WIN32 :/* Error codes from windows sockets differ from fileio error codes */ :#undef EINTR :#define EINTR WSAEINTR :#undef EINVAL :#define EINVAL WSAEINVAL :#undef EBADF :#define EBADF WSAENOTSOCK :/* Windows select does not set errno. Use GetErrno as wrapper for : WSAGetLastError */ :#define GetErrno WSAGetLastError :#else :/* This is just a fallback to errno to hide the differences between unix and : Windows in the code */ :#define GetErrno() errno :#endif : :/* modifications by raphael */ :int :mffs(fd_mask mask) :{ : int i; : : if (!mask) return 0; : i = 1; : while (!(mask & 1)) : { : i++; : mask >>= 1; : } : return i; :} : :#ifdef DPMSExtension :#define DPMS_SERVER :#include :#endif : :struct _OsTimerRec { : OsTimerPtr next; : CARD32 expires; : CARD32 delta; : OsTimerCallback callback; : pointer arg; :}; : :static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev); :static void CheckAllTimers(void); :static OsTimerPtr timers = NULL; : :/***************** : * WaitForSomething: : * Make the server suspend until there is : * 1. data from clients or : * 2. input events available or : * 3. ddx notices something of interest (graphics : * queue ready, etc.) or : * 4. clients that have buffered replies/events are ready : * : * If the time between INPUT events is : * greater than ScreenSaverTime, the display is turned off (or : * saved, depending on the hardware). So, WaitForSomething() : * has to handle this also (that's why the select() has a timeout. : * For more info on ClientsWithInput, see ReadRequestFromClient(). : * pClientsReady is an array to store ready client->index values into. : *****************/ : :int :WaitForSomething(int *pClientsReady) :{ /* WaitForSomething total: 2 0.0022 */ : int i; : struct timeval waittime, *wt; : INT32 timeout = 0; : fd_set clientsReadable; : fd_set clientsWritable; : int curclient; : int selecterr; : int nready; : fd_set devicesReadable; : CARD32 now = 0; :#ifdef SMART_SCHEDULE : Bool someReady = FALSE; :#endif : : FD_ZERO(&clientsReadable); : : /* We need a while loop here to handle : crashed connections and the screen saver timeout */ : while (1) : { : /* deal with any blocked jobs */ : if (workQueue) : ProcessWorkQueue(); : if (XFD_ANYSET (&ClientsWithInput)) : { :#ifdef SMART_SCHEDULE : if (!SmartScheduleDisable) : { : someReady = TRUE; : waittime.tv_sec = 0; : waittime.tv_usec = 0; : wt = &waittime; : } : else :#endif : { : XFD_COPYSET (&ClientsWithInput, &clientsReadable); : break; : } : } :#ifdef SMART_SCHEDULE : if (someReady) : { : XFD_COPYSET(&AllSockets, &LastSelectMask); : XFD_UNSET(&LastSelectMask, &ClientsWithInput); : } : else : { :#endif : wt = NULL; : if (timers) : { : now = GetTimeInMillis(); : timeout = timers->expires - now; : if (timeout > 0 && timeout > timers->delta + 250) { : /* time has rewound. reset the timers. */ : CheckAllTimers(); : } : : if (timers) { : timeout = timers->expires - now; : if (timeout < 0) : timeout = 0; : waittime.tv_sec = timeout / MILLI_PER_SECOND; : waittime.tv_usec = (timeout % MILLI_PER_SECOND) * : (1000000 / MILLI_PER_SECOND); : wt = &waittime; : } : } : XFD_COPYSET(&AllSockets, &LastSelectMask); :#ifdef SMART_SCHEDULE : } : SmartScheduleIdle = TRUE; :#endif : BlockHandler((pointer)&wt, (pointer)&LastSelectMask); : if (NewOutputPending) : FlushAllOutput(); : /* keep this check close to select() call to minimize race */ : if (dispatchException) : i = -1; : else if (AnyClientsWriteBlocked) : { : XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable); : i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt); : } : else : { 1 0.0011 : i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt); : } : selecterr = GetErrno(); : WakeupHandler(i, (pointer)&LastSelectMask); :#ifdef SMART_SCHEDULE : if (i >= 0) : { : SmartScheduleIdle = FALSE; : SmartScheduleIdleCount = 0; : if (SmartScheduleTimerStopped) : (void) SmartScheduleStartTimer (); : } :#endif : if (i <= 0) /* An error or timeout occurred */ : { : if (dispatchException) : return 0; : if (i < 0) : { : if (selecterr == EBADF) /* Some client disconnected */ : { : CheckConnections (); : if (! XFD_ANYSET (&AllClients)) : return 0; : } : else if (selecterr == EINVAL) : { : FatalError("WaitForSomething(): select: errno=%d\n", : selecterr); : } : else if (selecterr != EINTR) : { : ErrorF("WaitForSomething(): select: errno=%d\n", : selecterr); : } : } :#ifdef SMART_SCHEDULE : else if (someReady) : { : /* : * If no-one else is home, bail quickly : */ : XFD_COPYSET(&ClientsWithInput, &LastSelectMask); : XFD_COPYSET(&ClientsWithInput, &clientsReadable); : break; : } :#endif : if (*checkForInput[0] != *checkForInput[1]) : return 0; : : if (timers) : { : int expired = 0; : now = GetTimeInMillis(); : if ((int) (timers->expires - now) <= 0) : expired = 1; : : while (timers && (int) (timers->expires - now) <= 0) : DoTimer(timers, now, &timers); : : if (expired) : return 0; : } : } : else : { : fd_set tmp_set; : : if (*checkForInput[0] == *checkForInput[1]) { : if (timers) : { : int expired = 0; : now = GetTimeInMillis(); : if ((int) (timers->expires - now) <= 0) : expired = 1; : : while (timers && (int) (timers->expires - now) <= 0) : DoTimer(timers, now, &timers); : : if (expired) : return 0; : } : } :#ifdef SMART_SCHEDULE : if (someReady) : XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask); :#endif : if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable)) : { : NewOutputPending = TRUE; : XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending); : XFD_UNSET(&ClientsWriteBlocked, &clientsWritable); : if (! XFD_ANYSET(&ClientsWriteBlocked)) : AnyClientsWriteBlocked = FALSE; : } : : XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices); : XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); : XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections); : if (XFD_ANYSET(&tmp_set)) : QueueWorkProc(EstablishNewConnections, NULL, : (pointer)&LastSelectMask); : : if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable)) : break; :#ifdef WIN32 : /* Windows keyboard and mouse events are added to the input queue : in Block- and WakupHandlers. There is no device to check if : data is ready. So check here if new input is available */ : if (*checkForInput[0] != *checkForInput[1]) : return 0; :#endif : } : } : : nready = 0; : if (XFD_ANYSET (&clientsReadable)) : { :#ifndef WIN32 : for (i=0; ipriority; : if (nready == 0 || client_priority > highest_priority) : { : /* Either we found the first client, or we found : * a client whose priority is greater than all others : * that have been found so far. Either way, we want : * to initialize the list of clients to contain just : * this client. : */ : pClientsReady[0] = client_index; : highest_priority = client_priority; : nready = 1; : } : /* the following if makes sure that multiple same-priority : * clients get batched together : */ : else if (client_priority == highest_priority) :#endif : { : pClientsReady[nready++] = client_index; : } :#ifndef WIN32 : clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient); : } :#else : FD_CLR(curclient, &clientsReadable); :#endif : } : } : return nready; :} : :#if 0 :/* : * This is not always a macro. : */ :ANYSET(FdMask *src) :{ : int i; : : for (i=0; inext) { : if (timer->expires - now > timer->delta + 250) { : TimerForce(timer); : goto start; : } : } :} : :static void :DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev) :{ : CARD32 newTime; : : *prev = timer->next; : timer->next = NULL; : newTime = (*timer->callback)(timer, now, timer->arg); : if (newTime) : TimerSet(timer, 0, newTime, timer->callback, timer->arg); :} : :_X_EXPORT OsTimerPtr :TimerSet(OsTimerPtr timer, int flags, CARD32 millis, : OsTimerCallback func, pointer arg) :{ : register OsTimerPtr *prev; : CARD32 now = GetTimeInMillis(); : : if (!timer) : { : timer = (OsTimerPtr)xalloc(sizeof(struct _OsTimerRec)); : if (!timer) : return NULL; : } : else : { : for (prev = &timers; *prev; prev = &(*prev)->next) : { : if (*prev == timer) : { : *prev = timer->next; : if (flags & TimerForceOld) : (void)(*timer->callback)(timer, now, timer->arg); : break; : } : } : } : if (!millis) : return timer; : if (flags & TimerAbsolute) { : timer->delta = millis - now; : } : else { : timer->delta = millis; : millis += now; : } : timer->expires = millis; : timer->callback = func; : timer->arg = arg; : if ((int) (millis - now) <= 0) : { : timer->next = NULL; : millis = (*timer->callback)(timer, now, timer->arg); : if (!millis) : return timer; : } : for (prev = &timers; : *prev && (int) ((*prev)->expires - millis) <= 0; : prev = &(*prev)->next) : ; : timer->next = *prev; : *prev = timer; : return timer; :} : :Bool :TimerForce(OsTimerPtr timer) :{ : OsTimerPtr *prev; : : for (prev = &timers; *prev; prev = &(*prev)->next) : { : if (*prev == timer) : { : DoTimer(timer, GetTimeInMillis(), prev); : return TRUE; : } : } : return FALSE; :} : : :_X_EXPORT void :TimerCancel(OsTimerPtr timer) :{ : OsTimerPtr *prev; : : if (!timer) : return; : for (prev = &timers; *prev; prev = &(*prev)->next) : { : if (*prev == timer) : { : *prev = timer->next; : break; : } : } :} : :_X_EXPORT void :TimerFree(OsTimerPtr timer) :{ : if (!timer) : return; : TimerCancel(timer); : xfree(timer); :} : :void :TimerCheck(void) :{ : CARD32 now = GetTimeInMillis(); : : while (timers && (int) (timers->expires - now) <= 0) : DoTimer(timers, now, &timers); :} : :void :TimerInit(void) :{ : OsTimerPtr timer; : : while ((timer = timers)) : { : timers = timer->next; : xfree(timer); : } :} : :#ifdef DPMSExtension : :#define DPMS_CHECK_MODE(mode,time)\ : if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\ : DPMSSet(mode); : :#define DPMS_CHECK_TIMEOUT(time)\ : if (time > 0 && (time - timeout) > 0)\ : return time - timeout; : :static CARD32 :NextDPMSTimeout(INT32 timeout) :{ : /* : * Return the amount of time remaining until we should set : * the next power level. Fallthroughs are intentional. : */ : switch (DPMSPowerLevel) : { : case DPMSModeOn: : DPMS_CHECK_TIMEOUT(DPMSStandbyTime) : : case DPMSModeStandby: : DPMS_CHECK_TIMEOUT(DPMSSuspendTime) : : case DPMSModeSuspend: : DPMS_CHECK_TIMEOUT(DPMSOffTime) : : default: /* DPMSModeOff */ : return 0; : } :} :#endif /* DPMSExtension */ : :static CARD32 :ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) :{ : INT32 timeout = now - lastDeviceEventTime.milliseconds; : CARD32 nextTimeout = 0; : :#ifdef DPMSExtension : /* : * Check each mode lowest to highest, since a lower mode can : * have the same timeout as a higher one. : */ : if (DPMSEnabled) : { : DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime) : DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime) : DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime) : : nextTimeout = NextDPMSTimeout(timeout); : } : : /* : * Only do the screensaver checks if we're not in a DPMS : * power saving mode : */ : if (DPMSPowerLevel != DPMSModeOn) : return nextTimeout; :#endif /* DPMSExtension */ : : if (!ScreenSaverTime) : return nextTimeout; : : if (timeout < ScreenSaverTime) : { : return nextTimeout > 0 ? : min(ScreenSaverTime - timeout, nextTimeout) : : ScreenSaverTime - timeout; : } : : ResetOsBuffers(); /* not ideal, but better than nothing */ : SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive); : : if (ScreenSaverInterval > 0) : { : nextTimeout = nextTimeout > 0 ? : min(ScreenSaverInterval, nextTimeout) : : ScreenSaverInterval; : } : : return nextTimeout; :} : :static OsTimerPtr ScreenSaverTimer = NULL; : :void :FreeScreenSaverTimer(void) :{ : if (ScreenSaverTimer) { : TimerFree(ScreenSaverTimer); : ScreenSaverTimer = NULL; : } :} : :void :SetScreenSaverTimer(void) :{ : CARD32 timeout = 0; : :#ifdef DPMSExtension : if (DPMSEnabled) : { : /* : * A higher DPMS level has a timeout that's either less : * than or equal to that of a lower DPMS level. : */ : if (DPMSStandbyTime > 0) : timeout = DPMSStandbyTime; : : else if (DPMSSuspendTime > 0) : timeout = DPMSSuspendTime; : : else if (DPMSOffTime > 0) : timeout = DPMSOffTime; : } :#endif : : if (ScreenSaverTime > 0) : { : timeout = timeout > 0 ? : min(ScreenSaverTime, timeout) : : ScreenSaverTime; : } : :#ifdef SCREENSAVER : if (timeout && !screenSaverSuspended) { :#else : if (timeout) { :#endif : ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout, : ScreenSaverTimeoutExpire, NULL); : } : else if (ScreenSaverTimer) { : FreeScreenSaverTimer(); : } :} : /* * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fballpriv.c" * * 2 0.0022 */ :/* : * Copyright © 1998 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "fb.h" : :#ifdef FB_SCREEN_PRIVATE :int fbScreenPrivateIndex; :int fbGetScreenPrivateIndex(void) :{ : return fbScreenPrivateIndex; :} :#endif :int fbGCPrivateIndex; :int fbGetGCPrivateIndex(void) 2 0.0022 :{ /* fbGetGCPrivateIndex total: 2 0.0022 */ : return fbGCPrivateIndex; :} :#ifndef FB_NO_WINDOW_PIXMAPS :int fbWinPrivateIndex; :int fbGetWinPrivateIndex(void) :{ : return fbWinPrivateIndex; :} :#endif :int fbGeneration; : :#ifdef FB_OLD_SCREEN :#define miAllocateGCPrivateIndex() AllocateGCPrivateIndex() :#endif : :Bool :fbAllocatePrivates(ScreenPtr pScreen, int *pGCIndex) :{ : if (fbGeneration != serverGeneration) : { : fbGCPrivateIndex = miAllocateGCPrivateIndex (); :#ifndef FB_NO_WINDOW_PIXMAPS : fbWinPrivateIndex = AllocateWindowPrivateIndex(); :#endif :#ifdef FB_SCREEN_PRIVATE : fbScreenPrivateIndex = AllocateScreenPrivateIndex (); : if (fbScreenPrivateIndex == -1) : return FALSE; :#endif : : fbGeneration = serverGeneration; : } : if (pGCIndex) : *pGCIndex = fbGCPrivateIndex; : if (!AllocateGCPrivate(pScreen, fbGCPrivateIndex, sizeof(FbGCPrivRec))) : return FALSE; :#ifndef FB_NO_WINDOW_PIXMAPS : if (!AllocateWindowPrivate(pScreen, fbWinPrivateIndex, 0)) : return FALSE; :#endif :#ifdef FB_SCREEN_PRIVATE : { : FbScreenPrivPtr pScreenPriv; : : pScreenPriv = (FbScreenPrivPtr) xalloc (sizeof (FbScreenPrivRec)); : if (!pScreenPriv) : return FALSE; : pScreen->devPrivates[fbScreenPrivateIndex].ptr = (pointer) pScreenPriv; : } :#endif : return TRUE; :} : :#ifdef FB_ACCESS_WRAPPER :ReadMemoryProcPtr wfbReadMemory; :WriteMemoryProcPtr wfbWriteMemory; :#endif /* * Total samples for file : "/home/cworth/opt/xorg//include/X11/Xtrans/Xtranssock.c" * * 2 0.0022 */ :/* $XdotOrg: lib/xtrans/Xtranssock.c,v 1.11 2005/11/08 06:33:26 jkj Exp $ */ :/* $Xorg: Xtranssock.c,v 1.11 2001/02/09 02:04:06 xorgcvs Exp $ */ :/* : :Copyright 1993, 1994, 1998 The Open Group :Copyright 2002 Sun Microsystems, Inc. All rights reserved. : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included :in all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR :OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of the copyright holders shall :not be used in advertising or otherwise to promote the sale, use or :other dealings in this Software without prior written authorization :from the copyright holders. : :*/ :/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.68 2004/01/07 04:28:02 dawes Exp $ */ : :/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA : * : * All Rights Reserved : * : * Permission to use, copy, modify, and distribute this software and its : * documentation for any purpose and without fee is hereby granted, provided : * that the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name NCR not be used in advertising : * or publicity pertaining to distribution of the software without specific, : * written prior permission. NCR makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN : * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS : * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : */ : :#include :#ifdef XTHREADS :#include :#endif : :#ifndef WIN32 : :#if defined(TCPCONN) || defined(UNIXCONN) :#include :#include :#include :#endif : :#if defined(TCPCONN) || defined(UNIXCONN) :#define X_INCLUDE_NETDB_H :#define XOS_USE_NO_LOCKING :#include :#endif : :#ifdef UNIXCONN :#ifndef X_NO_SYS_UN :#ifndef Lynx :#include :#else :#include :#endif :#endif :#include :#endif : :#if defined(hpux) || (defined(MOTOROLA) && defined(SYSV)) :#define NO_TCP_H :#endif : :#ifndef NO_TCP_H :#if defined(__osf__) || defined(linux) || defined(__GLIBC__) || defined(AIXV5) :#include :#endif /* osf */ :#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) :#include :#include :#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */ :#include :#endif /* !NO_TCP_H */ : :#include :#if defined(SVR4) && !defined(DGUX) && !defined(_SEQUENT_) :#include :#endif : :#if (defined(i386) && defined(SYSV)) && !defined(SCO325) && !defined(sun) :#include :#endif : :#if (defined(i386) && defined(SYSV)) && (!defined(ISC) || !defined(I_NREAD) || defined(SCO325)) || defined(_SEQUENT_) :#include :#endif : :#else /* !WIN32 */ : :#include :#include :#include :#undef close :#define close closesocket :#define ECONNREFUSED WSAECONNREFUSED :#define EADDRINUSE WSAEADDRINUSE :#define EPROTOTYPE WSAEPROTOTYPE :#undef EWOULDBLOCK :#define EWOULDBLOCK WSAEWOULDBLOCK :#define EINPROGRESS WSAEINPROGRESS :#undef EINTR :#define EINTR WSAEINTR :#define X_INCLUDE_NETDB_H :#define XOS_USE_MTSAFE_NETDBAPI :#include :#endif /* WIN32 */ : :#if defined(SO_DONTLINGER) && defined(SO_LINGER) :#undef SO_DONTLINGER :#endif : :#if defined(__UNIXOS2__) :#if defined(NOT_EMX09A) :static int IBMsockInit = 0; :#define SocketInitOnce()\ : if (!IBMsockInit) {\ : sock_init();\ : IBMsockInit = 1;\ : } :#undef EINTR :#define EINTR SOCEINTR :#undef EINVAL :#define EINVAL SOCEINVAL :#undef errno :#define errno sock_errno() :#undef close :#define close soclose :#undef ioctl :#define ioctl sockioctl :#else :#define SocketInitOnce() /**/ :#endif :/* this is still not there */ :#define SOCKET int :#else :/* others don't need this */ :#define SocketInitOnce() /**/ :#endif : :#define MIN_BACKLOG 128 :#ifdef SOMAXCONN :#if SOMAXCONN > MIN_BACKLOG :#define BACKLOG SOMAXCONN :#endif :#endif :#ifndef BACKLOG :#define BACKLOG MIN_BACKLOG :#endif :/* : * This is the Socket implementation of the X Transport service layer : * : * This file contains the implementation for both the UNIX and INET domains, : * and can be built for either one, or both. : * : */ : :typedef struct _Sockettrans2dev { : char *transname; : int family; : int devcotsname; : int devcltsname; : int protocol; :} Sockettrans2dev; : :static Sockettrans2dev Sockettrans2devtab[] = { :#ifdef TCPCONN : {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, :#if !defined(IPv6) || !defined(AF_INET6) : {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, :#else /* IPv6 */ : {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, : {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */ : {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, :#endif :#endif /* TCPCONN */ :#ifdef UNIXCONN : {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, :#if !defined(LOCALCONN) : {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, :#endif /* !LOCALCONN */ :#endif /* UNIXCONN */ :}; : :#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev)) : :#ifdef TCPCONN :static int TRANS(SocketINETClose) (XtransConnInfo ciptr); :#endif : :#ifdef UNIXCONN : :#ifdef hpux : :#if defined(X11_t) :#define UNIX_PATH "/usr/spool/sockets/X11/" :#define UNIX_DIR "/usr/spool/sockets/X11" :#define OLD_UNIX_PATH "/tmp/.X11-unix/X" :#endif /* X11_t */ :#if defined(XIM_t) :#define UNIX_PATH "/usr/spool/sockets/XIM/" :#define UNIX_DIR "/usr/spool/sockets/XIM" :#define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM" :#endif /* XIM_t */ :#if defined(FS_t) || defined(FONT_t) :#define UNIX_PATH "/usr/spool/sockets/fontserv/" :#define UNIX_DIR "/usr/spool/sockets/fontserv" :#endif /* FS_t || FONT_t */ :#if defined(ICE_t) :#define UNIX_PATH "/usr/spool/sockets/ICE/" :#define UNIX_DIR "/usr/spool/sockets/ICE" :#endif /* ICE_t */ :#if defined(TEST_t) :#define UNIX_PATH "/usr/spool/sockets/xtrans_test/" :#define UNIX_DIR "/usr/spool/sockets/xtrans_test" :#endif :#if defined(LBXPROXY_t) :#define UNIX_PATH "/usr/spool/sockets/X11/" :#define UNIX_DIR "/usr/spool/sockets/X11" :#endif : :#else /* !hpux */ : :#if defined(X11_t) :#define UNIX_PATH "/tmp/.X11-unix/X" :#define UNIX_DIR "/tmp/.X11-unix" :#endif /* X11_t */ :#if defined(XIM_t) :#define UNIX_PATH "/tmp/.XIM-unix/XIM" :#define UNIX_DIR "/tmp/.XIM-unix" :#endif /* XIM_t */ :#if defined(FS_t) || defined(FONT_t) :#define UNIX_PATH "/tmp/.font-unix/fs" :#define UNIX_DIR "/tmp/.font-unix" :#endif /* FS_t || FONT_t */ :#if defined(ICE_t) :#define UNIX_PATH "/tmp/.ICE-unix/" :#define UNIX_DIR "/tmp/.ICE-unix" :#endif /* ICE_t */ :#if defined(TEST_t) :#define UNIX_PATH "/tmp/.Test-unix/test" :#define UNIX_DIR "/tmp/.Test-unix" :#endif :#if defined(LBXPROXY_t) :#define UNIX_PATH "/tmp/.X11-unix/X" :#define UNIX_DIR "/tmp/.X11-unix" :#endif : :#endif /* hpux */ : :#endif /* UNIXCONN */ : :#define PORTBUFSIZE 32 : :#ifndef MAXHOSTNAMELEN :#define MAXHOSTNAMELEN 255 :#endif : :/* : * This provides compatibility for apps linked against system libraries : * that don't have IPv6 support. : */ :#if defined(IPv6) && defined(AF_INET6) :static const struct in6_addr local_in6addr_any = IN6ADDR_ANY_INIT; :#pragma weak in6addr_any = local_in6addr_any :#ifndef __USLC__ :#pragma weak getaddrinfo :#endif :static int haveIPv6 = 1; :#endif : :/* : * These are some utility function used by the real interface function below. : */ : :static int :TRANS(SocketSelectFamily) (int first, char *family) : :{ : int i; : : PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0); : : for (i = first + 1; i < NUMSOCKETFAMILIES;i++) : { : if (!strcmp (family, Sockettrans2devtab[i].transname)) : return i; : } : : return (first == -1 ? -2 : -1); :} : : :/* : * This function gets the local address of the socket and stores it in the : * XtransConnInfo structure for the connection. : */ : :static int :TRANS(SocketINETGetAddr) (XtransConnInfo ciptr) : :{ :#if defined(IPv6) && defined(AF_INET6) : struct sockaddr_storage socknamev6; :#endif : struct sockaddr_in socknamev4; : void *socknamePtr; :#if defined(SVR4) || defined(__SCO__) : size_t namelen; :#else : int namelen; :#endif : : PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0); : :#if defined(IPv6) && defined(AF_INET6) : if (haveIPv6) : { : namelen = sizeof(socknamev6); : socknamePtr = &socknamev6; : } : else :#endif : { : namelen = sizeof(socknamev4); : socknamePtr = &socknamev4; : } : : bzero(socknamePtr, namelen); : : if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr, : (void *)&namelen) < 0) : { :#ifdef WIN32 : errno = WSAGetLastError(); :#endif : PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n", : EGET(),0, 0); : return -1; : } : : /* : * Everything looks good: fill in the XtransConnInfo structure. : */ : : if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) : { : PRMSG (1, : "SocketINETGetAddr: Can't allocate space for the addr\n", : 0, 0, 0); : return -1; : } : :#if defined(IPv6) && defined(AF_INET6) : if (haveIPv6) : { : ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family; : } : else :#endif : { : ciptr->family = socknamev4.sin_family; : } : ciptr->addrlen = namelen; : memcpy (ciptr->addr, socknamePtr, ciptr->addrlen); : : return 0; :} : : :/* : * This function gets the remote address of the socket and stores it in the : * XtransConnInfo structure for the connection. : */ : :static int :TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr) : :{ :#if defined(IPv6) && defined(AF_INET6) : struct sockaddr_storage socknamev6; :#endif : struct sockaddr_in socknamev4; : void *socknamePtr; :#if defined(SVR4) || defined(__SCO__) : size_t namelen; :#else : int namelen; :#endif : :#if defined(IPv6) && defined(AF_INET6) : if (haveIPv6 && ciptr->family == AF_INET6) : { : namelen = sizeof(socknamev6); : socknamePtr = &socknamev6; : } : else :#endif : { : namelen = sizeof(socknamev4); : socknamePtr = &socknamev4; : } : : bzero(socknamePtr, namelen); : : PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0); : : if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr, : (void *)&namelen) < 0) : { :#ifdef WIN32 : errno = WSAGetLastError(); :#endif : PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n", : EGET(), 0, 0); : return -1; : } : : /* : * Everything looks good: fill in the XtransConnInfo structure. : */ : : if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL) : { : PRMSG (1, : "SocketINETGetPeerAddr: Can't allocate space for the addr\n", : 0, 0, 0); : return -1; : } : : ciptr->peeraddrlen = namelen; : memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen); : : return 0; :} : : :static XtransConnInfo :TRANS(SocketOpen) (int i, int type) : :{ : XtransConnInfo ciptr; : : PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0); : :#if defined(IPv6) && defined(AF_INET6) : if (getaddrinfo == NULL) : haveIPv6 = 0; : : if (!haveIPv6 && Sockettrans2devtab[i].family == AF_INET6) : return NULL; :#endif : : if ((ciptr = (XtransConnInfo) xcalloc ( : 1, sizeof(struct _XtransConnInfo))) == NULL) : { : PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0); : return NULL; : } : : if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type, : Sockettrans2devtab[i].protocol)) < 0 :#ifndef WIN32 :#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t) : || ciptr->fd >= TRANS_OPEN_MAX :#endif :#endif : ) { :#ifdef WIN32 : errno = WSAGetLastError(); :#endif : PRMSG (2, "SocketOpen: socket() failed for %s\n", : Sockettrans2devtab[i].transname, 0, 0); : : xfree ((char *) ciptr); : return NULL; : } : :#ifdef TCP_NODELAY : if (Sockettrans2devtab[i].family == AF_INET :#if defined(IPv6) && defined(AF_INET6) : || Sockettrans2devtab[i].family == AF_INET6 :#endif : ) : { : /* : * turn off TCP coalescence for INET sockets : */ : : int tmp = 1; : setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY, : (char *) &tmp, sizeof (int)); : } :#endif : : return ciptr; :} : : :#ifdef TRANS_REOPEN : :static XtransConnInfo :TRANS(SocketReopen) (int i, int type, int fd, char *port) : :{ : XtransConnInfo ciptr; : : PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port); : : if ((ciptr = (XtransConnInfo) xcalloc ( : 1, sizeof(struct _XtransConnInfo))) == NULL) : { : PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0); : return NULL; : } : : ciptr->fd = fd; : : return ciptr; :} : :#endif /* TRANS_REOPEN */ : : :/* : * These functions are the interface supplied in the Xtransport structure : */ : :#ifdef TRANS_CLIENT : :static XtransConnInfo :TRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol, : char *host, char *port, int previndex) :{ : XtransConnInfo ciptr; : int i = previndex; : : PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n", : protocol, host, port); : : SocketInitOnce(); : : while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) { : if ((ciptr = TRANS(SocketOpen) ( : i, Sockettrans2devtab[i].devcotsname)) != NULL) : break; : } : if (i < 0) { : if (i == -1) : PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n", : transname, 0, 0); : else : PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n", : transname, 0, 0); : return NULL; : } : : /* Save the index for later use */ : : ciptr->index = i; : : return ciptr; :} : :static XtransConnInfo :TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol, : char *host, char *port) :{ : return TRANS(SocketOpenCOTSClientBase)( : thistrans->TransName, protocol, host, port, -1); :} : : :#endif /* TRANS_CLIENT */ : : :#ifdef TRANS_SERVER : :static XtransConnInfo :TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol, : char *host, char *port) : :{ : XtransConnInfo ciptr; : int i = -1; : : PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port); : : SocketInitOnce(); : : while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { : if ((ciptr = TRANS(SocketOpen) ( : i, Sockettrans2devtab[i].devcotsname)) != NULL) : break; : } : if (i < 0) { : if (i == -1) : PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n", : thistrans->TransName, 0, 0); : else : PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n", : thistrans->TransName, 0, 0); : return NULL; : } : : /* : * Using this prevents the bind() check for an existing server listening : * on the same port, but it is required for other reasons. : */ :#ifdef SO_REUSEADDR : : /* : * SO_REUSEADDR only applied to AF_INET && AF_INET6 : */ : : if (Sockettrans2devtab[i].family == AF_INET :#if defined(IPv6) && defined(AF_INET6) : || Sockettrans2devtab[i].family == AF_INET6 :#endif : ) : { : int one = 1; : setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR, : (char *) &one, sizeof (int)); : } :#endif :#ifdef IPV6_V6ONLY : if (Sockettrans2devtab[i].family == AF_INET6) : { : int one = 1; : setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); : } :#endif : /* Save the index for later use */ : : ciptr->index = i; : : return ciptr; :} : :#endif /* TRANS_SERVER */ : : :#ifdef TRANS_CLIENT : :static XtransConnInfo :TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol, : char *host, char *port) : :{ : XtransConnInfo ciptr; : int i = -1; : : PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port); : : SocketInitOnce(); : : while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { : if ((ciptr = TRANS(SocketOpen) ( : i, Sockettrans2devtab[i].devcotsname)) != NULL) : break; : } : if (i < 0) { : if (i == -1) : PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n", : thistrans->TransName, 0, 0); : else : PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n", : thistrans->TransName, 0, 0); : return NULL; : } : : /* Save the index for later use */ : : ciptr->index = i; : : return ciptr; :} : :#endif /* TRANS_CLIENT */ : : :#ifdef TRANS_SERVER : :static XtransConnInfo :TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol, : char *host, char *port) : :{ : XtransConnInfo ciptr; : int i = -1; : : PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port); : : SocketInitOnce(); : : while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { : if ((ciptr = TRANS(SocketOpen) ( : i, Sockettrans2devtab[i].devcotsname)) != NULL) : break; : } : if (i < 0) { : if (i == -1) : PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n", : thistrans->TransName, 0, 0); : else : PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n", : thistrans->TransName, 0, 0); : return NULL; : } : :#ifdef IPV6_V6ONLY : if (Sockettrans2devtab[i].family == AF_INET6) : { : int one = 1; : setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); : } :#endif : /* Save the index for later use */ : : ciptr->index = i; : : return ciptr; :} : :#endif /* TRANS_SERVER */ : : :#ifdef TRANS_REOPEN : :static XtransConnInfo :TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port) : :{ : XtransConnInfo ciptr; : int i = -1; : : PRMSG (2, : "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0); : : SocketInitOnce(); : : while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { : if ((ciptr = TRANS(SocketReopen) ( : i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) : break; : } : if (i < 0) { : if (i == -1) : PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n", : thistrans->TransName, 0, 0); : else : PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n", : thistrans->TransName, 0, 0); : return NULL; : } : : /* Save the index for later use */ : : ciptr->index = i; : : return ciptr; :} : :static XtransConnInfo :TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port) : :{ : XtransConnInfo ciptr; : int i = -1; : : PRMSG (2, : "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0); : : SocketInitOnce(); : : while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { : if ((ciptr = TRANS(SocketReopen) ( : i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) : break; : } : if (i < 0) { : if (i == -1) : PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n", : thistrans->TransName, 0, 0); : else : PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n", : thistrans->TransName, 0, 0); : return NULL; : } : : /* Save the index for later use */ : : ciptr->index = i; : : return ciptr; :} : :#endif /* TRANS_REOPEN */ : : :static int :TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg) : :{ : PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg); : : return -1; :} : :#ifdef UNIXCONN :static int :set_sun_path(const char *port, const char *upath, char *path) :{ : struct sockaddr_un s; : int maxlen = sizeof(s.sun_path) - 1; : : if (!port || !*port || !path) : return -1; : : if (*port == '/') { /* a full pathname */ : if (strlen(port) > maxlen) : return -1; : sprintf(path, "%s", port); : } else { : if (strlen(port) + strlen(upath) > maxlen) : return -1; : sprintf(path, "%s%s", upath, port); : } : return 0; :} :#endif : :#ifdef TRANS_SERVER : :static int :TRANS(SocketCreateListener) (XtransConnInfo ciptr, : struct sockaddr *sockname, : int socknamelen, unsigned int flags) : :{ : int namelen = socknamelen; : int fd = ciptr->fd; : int retry; : : PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0); : : if (Sockettrans2devtab[ciptr->index].family == AF_INET :#if defined(IPv6) && defined(AF_INET6) : || Sockettrans2devtab[ciptr->index].family == AF_INET6 :#endif : ) : retry = 20; : else : retry = 0; : : while (bind (fd, (struct sockaddr *) sockname, namelen) < 0) : { : if (errno == EADDRINUSE) { : if (flags & ADDR_IN_USE_ALLOWED) : break; : else : return TRANS_ADDR_IN_USE; : } : : if (retry-- == 0) { : PRMSG (1, "SocketCreateListener: failed to bind listener\n", : 0, 0, 0); : close (fd); : return TRANS_CREATE_LISTENER_FAILED; : } :#ifdef SO_REUSEADDR : sleep (1); :#else : sleep (10); :#endif /* SO_REUSEDADDR */ : } : : if (Sockettrans2devtab[ciptr->index].family == AF_INET :#if defined(IPv6) && defined(AF_INET6) : || Sockettrans2devtab[ciptr->index].family == AF_INET6 :#endif : ) { :#ifdef SO_DONTLINGER : setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0); :#else :#ifdef SO_LINGER : { : static int linger[2] = { 0, 0 }; : setsockopt (fd, SOL_SOCKET, SO_LINGER, : (char *) linger, sizeof (linger)); : } :#endif :#endif :} : : if (listen (fd, BACKLOG) < 0) : { : PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0); : close (fd); : return TRANS_CREATE_LISTENER_FAILED; : } : : /* Set a flag to indicate that this connection is a listener */ : : ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); : : return 0; :} : :#ifdef TCPCONN :static int :TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags) : :{ :#if defined(IPv6) && defined(AF_INET6) : struct sockaddr_storage sockname; :#else : struct sockaddr_in sockname; :#endif : unsigned short sport; : int namelen = sizeof(sockname); : int status; : long tmpport; :#ifdef XTHREADS_NEEDS_BYNAMEPARAMS : _Xgetservbynameparams sparams; :#endif : struct servent *servp; : :#ifdef X11_t : char portbuf[PORTBUFSIZE]; :#endif : : PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0); : :#ifdef X11_t : /* : * X has a well known port, that is transport dependent. It is easier : * to handle it here, than try and come up with a transport independent : * representation that can be passed in and resolved the usual way. : * : * The port that is passed here is really a string containing the idisplay : * from ConnectDisplay(). : */ : : if (is_numeric (port)) : { : /* fixup the server port address */ : tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); : sprintf (portbuf,"%lu", tmpport); : port = portbuf; : } :#endif : : if (port && *port) : { : /* Check to see if the port string is just a number (handles X11) */ : : if (!is_numeric (port)) : { : if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) : { : PRMSG (1, : "SocketINETCreateListener: Unable to get service for %s\n", : port, 0, 0); : return TRANS_CREATE_LISTENER_FAILED; : } : /* we trust getservbyname to return a valid number */ : sport = servp->s_port; : } : else : { : tmpport = strtol (port, (char**)NULL, 10); : /* : * check that somehow the port address isn't negative or in : * the range of reserved port addresses. This can happen and : * be very bad if the server is suid-root and the user does : * something (dumb) like `X :60049`. : */ : if (tmpport < 1024 || tmpport > USHRT_MAX) : return TRANS_CREATE_LISTENER_FAILED; : : sport = (unsigned short) tmpport; : } : } : else : sport = 0; : : bzero(&sockname, sizeof(sockname)); :#if defined(IPv6) && defined(AF_INET6) : if (Sockettrans2devtab[ciptr->index].family == AF_INET) { : namelen = sizeof (struct sockaddr_in); :#ifdef BSD44SOCKETS : ((struct sockaddr_in *)&sockname)->sin_len = namelen; :#endif : ((struct sockaddr_in *)&sockname)->sin_family = AF_INET; : ((struct sockaddr_in *)&sockname)->sin_port = htons(sport); : ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY); : } else { : namelen = sizeof (struct sockaddr_in6); :#ifdef SIN6_LEN : ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname); :#endif : ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6; : ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport); : ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any; : } :#else :#ifdef BSD44SOCKETS : sockname.sin_len = sizeof (sockname); :#endif : sockname.sin_family = AF_INET; : sockname.sin_port = htons (sport); : sockname.sin_addr.s_addr = htonl (INADDR_ANY); :#endif : : if ((status = TRANS(SocketCreateListener) (ciptr, : (struct sockaddr *) &sockname, namelen, flags)) < 0) : { : PRMSG (1, : "SocketINETCreateListener: ...SocketCreateListener() failed\n", : 0, 0, 0); : return status; : } : : if (TRANS(SocketINETGetAddr) (ciptr) < 0) : { : PRMSG (1, : "SocketINETCreateListener: ...SocketINETGetAddr() failed\n", : 0, 0, 0); : return TRANS_CREATE_LISTENER_FAILED; : } : : return 0; :} : :#endif /* TCPCONN */ : : :#ifdef UNIXCONN : :static int :TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port, : unsigned int flags) : :{ : struct sockaddr_un sockname; : int namelen; : int oldUmask; : int status; : unsigned int mode; : : PRMSG (2, "SocketUNIXCreateListener(%s)\n", : port ? port : "NULL", 0, 0); : : /* Make sure the directory is created */ : : oldUmask = umask (0); : :#ifdef UNIX_DIR :#ifdef HAS_STICKY_DIR_BIT : mode = 01777; :#else : mode = 0777; :#endif : if (trans_mkdir(UNIX_DIR, mode) == -1) { : PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n", : UNIX_DIR, errno, 0); : (void) umask (oldUmask); : return TRANS_CREATE_LISTENER_FAILED; : } :#endif : : sockname.sun_family = AF_UNIX; : : if (port && *port) { : if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) { : PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0); : return TRANS_CREATE_LISTENER_FAILED; : } : } else { : snprintf (sockname.sun_path, sizeof(sockname.sun_path), : "%s%ld", UNIX_PATH, (long)getpid()); : } : :#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx) : sockname.sun_len = strlen(sockname.sun_path); :#endif : :#if defined(BSD44SOCKETS) || defined(SUN_LEN) : namelen = SUN_LEN(&sockname); :#else : namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); :#endif : : unlink (sockname.sun_path); : : if ((status = TRANS(SocketCreateListener) (ciptr, : (struct sockaddr *) &sockname, namelen, flags)) < 0) : { : PRMSG (1, : "SocketUNIXCreateListener: ...SocketCreateListener() failed\n", : 0, 0, 0); : (void) umask (oldUmask); : return status; : } : : /* : * Now that the listener is esablished, create the addr info for : * this connection. getpeername() doesn't work for UNIX Domain Sockets : * on some systems (hpux at least), so we will just do it manually, instead : * of calling something like TRANS(SocketUNIXGetAddr). : */ : : namelen = sizeof (sockname); /* this will always make it the same size */ : : if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) : { : PRMSG (1, : "SocketUNIXCreateListener: Can't allocate space for the addr\n", : 0, 0, 0); : (void) umask (oldUmask); : return TRANS_CREATE_LISTENER_FAILED; : } : : ciptr->family = sockname.sun_family; : ciptr->addrlen = namelen; : memcpy (ciptr->addr, &sockname, ciptr->addrlen); : : (void) umask (oldUmask); : : return 0; :} : : :static int :TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr) : :{ : /* : * See if the unix domain socket has disappeared. If it has, recreate it. : */ : : struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr; : struct stat statb; : int status = TRANS_RESET_NOOP; : unsigned int mode; : : PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0); : : if (stat (unsock->sun_path, &statb) == -1 || : ((statb.st_mode & S_IFMT) != :#if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO325) || !defined(S_IFSOCK) : S_IFIFO)) :#else : S_IFSOCK)) :#endif : { : int oldUmask = umask (0); : :#ifdef UNIX_DIR :#ifdef HAS_STICKY_DIR_BIT : mode = 01777; :#else : mode = 0777; :#endif : if (trans_mkdir(UNIX_DIR, mode) == -1) { : PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n", : UNIX_DIR, errno, 0); : (void) umask (oldUmask); : return TRANS_RESET_FAILURE; : } :#endif : : close (ciptr->fd); : unlink (unsock->sun_path); : : if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) : { : TRANS(FreeConnInfo) (ciptr); : (void) umask (oldUmask); : return TRANS_RESET_FAILURE; : } : : if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0) : { : close (ciptr->fd); : TRANS(FreeConnInfo) (ciptr); : return TRANS_RESET_FAILURE; : } : : if (listen (ciptr->fd, BACKLOG) < 0) : { : close (ciptr->fd); : TRANS(FreeConnInfo) (ciptr); : (void) umask (oldUmask); : return TRANS_RESET_FAILURE; : } : : umask (oldUmask); : : status = TRANS_RESET_NEW_FD; : } : : return status; :} : :#endif /* UNIXCONN */ : : :#ifdef TCPCONN : :static XtransConnInfo :TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status) : :{ : XtransConnInfo newciptr; : struct sockaddr_in sockname; : int namelen = sizeof(sockname); : : PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0); : : if ((newciptr = (XtransConnInfo) xcalloc ( : 1, sizeof(struct _XtransConnInfo))) == NULL) : { : PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0); : *status = TRANS_ACCEPT_BAD_MALLOC; : return NULL; : } : : if ((newciptr->fd = accept (ciptr->fd, : (struct sockaddr *) &sockname, (void *)&namelen)) < 0) : { :#ifdef WIN32 : errno = WSAGetLastError(); :#endif : PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0); : xfree (newciptr); : *status = TRANS_ACCEPT_FAILED; : return NULL; : } : :#ifdef TCP_NODELAY : { : /* : * turn off TCP coalescence for INET sockets : */ : : int tmp = 1; : setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY, : (char *) &tmp, sizeof (int)); : } :#endif : : /* : * Get this address again because the transport may give a more : * specific address now that a connection is established. : */ : : if (TRANS(SocketINETGetAddr) (newciptr) < 0) : { : PRMSG (1, : "SocketINETAccept: ...SocketINETGetAddr() failed:\n", : 0, 0, 0); : close (newciptr->fd); : xfree (newciptr); : *status = TRANS_ACCEPT_MISC_ERROR; : return NULL; : } : : if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0) : { : PRMSG (1, : "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n", : 0, 0, 0); : close (newciptr->fd); : if (newciptr->addr) xfree (newciptr->addr); : xfree (newciptr); : *status = TRANS_ACCEPT_MISC_ERROR; : return NULL; : } : : *status = 0; : : return newciptr; :} : :#endif /* TCPCONN */ : : :#ifdef UNIXCONN :static XtransConnInfo :TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) : :{ : XtransConnInfo newciptr; : struct sockaddr_un sockname; :#if defined(SVR4) || defined(__SCO__) : size_t namelen = sizeof sockname; :#else : int namelen = sizeof sockname; :#endif : : PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0); : : if ((newciptr = (XtransConnInfo) xcalloc ( : 1, sizeof(struct _XtransConnInfo))) == NULL) : { : PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0); : *status = TRANS_ACCEPT_BAD_MALLOC; : return NULL; : } : : if ((newciptr->fd = accept (ciptr->fd, : (struct sockaddr *) &sockname, (void *)&namelen)) < 0) : { : PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0); : xfree (newciptr); : *status = TRANS_ACCEPT_FAILED; : return NULL; : } : : /* : * Get the socket name and the peer name from the listener socket, : * since this is unix domain. : */ : : if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL) : { : PRMSG (1, : "SocketUNIXAccept: Can't allocate space for the addr\n", : 0, 0, 0); : close (newciptr->fd); : xfree (newciptr); : *status = TRANS_ACCEPT_BAD_MALLOC; : return NULL; : } : : : newciptr->addrlen = ciptr->addrlen; : memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen); : : if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL) : { : PRMSG (1, : "SocketUNIXAccept: Can't allocate space for the addr\n", : 0, 0, 0); : close (newciptr->fd); : if (newciptr->addr) xfree (newciptr->addr); : xfree (newciptr); : *status = TRANS_ACCEPT_BAD_MALLOC; : return NULL; : } : : newciptr->peeraddrlen = ciptr->addrlen; : memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen); : : newciptr->family = AF_UNIX; : : *status = 0; : : return newciptr; :} : :#endif /* UNIXCONN */ : :#endif /* TRANS_SERVER */ : : :#ifdef TRANS_CLIENT : :#ifdef TCPCONN : :#if defined(IPv6) && defined(AF_INET6) :struct addrlist { : struct addrinfo * addr; : struct addrinfo * firstaddr; : char port[PORTBUFSIZE]; : char host[MAXHOSTNAMELEN]; :}; :static struct addrlist *addrlist = NULL; :#endif : : :static int :TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port) : :{ : struct sockaddr * socketaddr = NULL; : int socketaddrlen = 0; : int res; :#if defined(IPv6) && defined(AF_INET6) : struct addrinfo hints; : char ntopbuf[INET6_ADDRSTRLEN]; : int resetonce = 0; :#endif : struct sockaddr_in sockname; :#ifdef XTHREADS_NEEDS_BYNAMEPARAMS : _Xgethostbynameparams hparams; : _Xgetservbynameparams sparams; :#endif : struct hostent *hostp; : struct servent *servp; : unsigned long tmpaddr; :#ifdef X11_t : char portbuf[PORTBUFSIZE]; :#endif : : long tmpport; : char hostnamebuf[256]; /* tmp space */ : : PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port); : : if (!host) : { : hostnamebuf[0] = '\0'; : (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf); : host = hostnamebuf; : } : :#ifdef X11_t : /* : * X has a well known port, that is transport dependent. It is easier : * to handle it here, than try and come up with a transport independent : * representation that can be passed in and resolved the usual way. : * : * The port that is passed here is really a string containing the idisplay : * from ConnectDisplay(). : */ : : if (is_numeric (port)) : { : tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); : sprintf (portbuf, "%lu", tmpport); : port = portbuf; : } :#endif : :#if defined(IPv6) && defined(AF_INET6) : if (haveIPv6) { : if (addrlist != NULL) { : if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) { : if (addrlist->firstaddr) : freeaddrinfo(addrlist->firstaddr); : addrlist->firstaddr = NULL; : } : } else { : addrlist = malloc(sizeof(struct addrlist)); : addrlist->firstaddr = NULL; : } : : if (addrlist->firstaddr == NULL) { : strncpy(addrlist->port, port, sizeof(addrlist->port)); : addrlist->port[sizeof(addrlist->port) - 1] = '\0'; : strncpy(addrlist->host, host, sizeof(addrlist->host)); : addrlist->host[sizeof(addrlist->host) - 1] = '\0'; : : bzero(&hints,sizeof(hints)); : hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname; : : res = getaddrinfo(host,port,&hints,&addrlist->firstaddr); : if (res != 0) { : PRMSG (1, "SocketINETConnect() can't get address " : "for %s:%s: %s\n", host, port, gai_strerror(res)); : ESET(EINVAL); : return TRANS_CONNECT_FAILED; : } : for (res = 0, addrlist->addr = addrlist->firstaddr; : addrlist->addr ; res++) { : addrlist->addr = addrlist->addr->ai_next; : } : PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0); : res = 0; : addrlist->addr = NULL; : } : : while (socketaddr == NULL) { : if (addrlist->addr == NULL) { : if (resetonce) { : /* Already checked entire list - no usable addresses */ : PRMSG (1, "SocketINETConnect() no usable address " : "for %s:%s\n", host, port, 0); : return TRANS_CONNECT_FAILED; : } else { : /* Go back to beginning of list */ : resetonce = 1; : addrlist->addr = addrlist->firstaddr; : } : } : : socketaddr = addrlist->addr->ai_addr; : socketaddrlen = addrlist->addr->ai_addrlen; : : if (addrlist->addr->ai_family == AF_INET) { : struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr; : : PRMSG (4,"SocketINETConnect() sockname.sin_addr = %s\n", : inet_ntop(addrlist->addr->ai_family,&sin->sin_addr, : ntopbuf,sizeof(ntopbuf)), 0, 0); : : PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n", : ntohs(sin->sin_port), 0, 0); : : if (Sockettrans2devtab[ciptr->index].family == AF_INET6) { : if (strcmp(Sockettrans2devtab[ciptr->index].transname, : "tcp") == 0) { : XtransConnInfo newciptr; : : /* : * Our socket is an IPv6 socket, but the address is : * IPv4. Close it and get an IPv4 socket. This is : * needed for IPv4 connections to work on platforms : * that don't allow IPv4 over IPv6 sockets. : */ : TRANS(SocketINETClose)(ciptr); : newciptr = TRANS(SocketOpenCOTSClientBase)( : "tcp", "tcp", host, port, ciptr->index); : if (newciptr) : ciptr->fd = newciptr->fd; : if (!newciptr || : Sockettrans2devtab[newciptr->index].family != : AF_INET) { : socketaddr = NULL; : PRMSG (4,"SocketINETConnect() Cannot get IPv4 " : " socketfor IPv4 address\n", 0,0,0); : } : if (newciptr) : xfree(newciptr); : } else { : socketaddr = NULL; : PRMSG (4,"SocketINETConnect Skipping IPv4 address\n", : 0,0,0); : } : } : } else if (addrlist->addr->ai_family == AF_INET6) { : struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr; : : PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n", : inet_ntop(addrlist->addr->ai_family, : &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)), : 0, 0); : PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n", : ntohs(sin6->sin6_port), 0, 0); : : if (Sockettrans2devtab[ciptr->index].family == AF_INET) { : if (strcmp(Sockettrans2devtab[ciptr->index].transname, : "tcp") == 0) { : XtransConnInfo newciptr; : : /* : * Close the IPv4 socket and try to open an IPv6 socket. : */ : TRANS(SocketINETClose)(ciptr); : newciptr = TRANS(SocketOpenCOTSClientBase)( : "tcp", "tcp", host, port, -1); : if (newciptr) : ciptr->fd = newciptr->fd; : if (!newciptr || : Sockettrans2devtab[newciptr->index].family != : AF_INET6) { : socketaddr = NULL; : PRMSG (4,"SocketINETConnect() Cannot get IPv6 " : "socket for IPv6 address\n", 0,0,0); : } : if (newciptr) : xfree(newciptr); : } : else : { : socketaddr = NULL; : PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n", : 0,0,0); : } : } : } else { : socketaddr = NULL; /* Unsupported address type */ : } : if (socketaddr == NULL) { : addrlist->addr = addrlist->addr->ai_next; : } : } : } else :#endif : { : /* : * Build the socket name. : */ : :#ifdef BSD44SOCKETS : sockname.sin_len = sizeof (struct sockaddr_in); :#endif : sockname.sin_family = AF_INET; : : /* : * fill in sin_addr : */ : :#ifndef INADDR_NONE :#define INADDR_NONE ((in_addr_t) 0xffffffff) :#endif : : /* check for ww.xx.yy.zz host string */ : : if (isascii (host[0]) && isdigit (host[0])) { : tmpaddr = inet_addr (host); /* returns network byte order */ : } else { : tmpaddr = INADDR_NONE; : } : : PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0); : : if (tmpaddr == INADDR_NONE) { : if ((hostp = _XGethostbyname(host,hparams)) == NULL) { : PRMSG (1,"SocketINETConnect: Can't get address for %s\n", : host, 0, 0); : ESET(EINVAL); : return TRANS_CONNECT_FAILED; : } : if (hostp->h_addrtype != AF_INET) { /* is IP host? */ : PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0); : ESET(EPROTOTYPE); : return TRANS_CONNECT_FAILED; : } : :#if defined(CRAY) && defined(OLDTCP) : /* Only Cray UNICOS3 and UNICOS4 will define this */ : { : long t; : memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t)); : sockname.sin_addr = t; : } :#else : memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr, : sizeof (sockname.sin_addr)); :#endif /* CRAY and OLDTCP */ : : } else { :#if defined(CRAY) && defined(OLDTCP) : /* Only Cray UNICOS3 and UNICOS4 will define this */ : sockname.sin_addr = tmpaddr; :#else : sockname.sin_addr.s_addr = tmpaddr; :#endif /* CRAY and OLDTCP */ : } : : /* : * fill in sin_port : */ : : /* Check for number in the port string */ : : if (!is_numeric (port)) { : if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) { : PRMSG (1,"SocketINETConnect: can't get service for %s\n", : port, 0, 0); : return TRANS_CONNECT_FAILED; : } : sockname.sin_port = htons (servp->s_port); : } else { : tmpport = strtol (port, (char**)NULL, 10); : if (tmpport < 1024 || tmpport > USHRT_MAX) : return TRANS_CONNECT_FAILED; : sockname.sin_port = htons (((unsigned short) tmpport)); : } : : PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n", : ntohs(sockname.sin_port), 0, 0); : socketaddr = (struct sockaddr *) &sockname; : socketaddrlen = sizeof(sockname); : } : : /* : * Turn on socket keepalive so the client process will eventually : * be notified with a SIGPIPE signal if the display server fails : * to respond to a periodic transmission of messages : * on the connected socket. : * This is useful to avoid hung application processes when the : * processes are not spawned from the xdm session and : * the display server terminates abnormally. : * (Someone turned off the power switch.) : */ : : { : int tmp = 1; : setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE, : (char *) &tmp, sizeof (int)); : } : : /* : * Do the connect() : */ : : if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0) : { :#ifdef WIN32 : int olderrno = WSAGetLastError(); :#else : int olderrno = errno; :#endif : : /* : * If the error was ECONNREFUSED, the server may be overloaded : * and we should try again. : * : * If the error was EWOULDBLOCK or EINPROGRESS then the socket : * was non-blocking and we should poll using select : * : * If the error was EINTR, the connect was interrupted and we : * should try again. : * : * If multiple addresses are found for a host then we should : * try to connect again with a different address for a larger : * number of errors that made us quit before, since those : * could be caused by trying to use an IPv6 address to contact : * a machine with an IPv4-only server or other reasons that : * only affect one of a set of addresses. : */ : : if (olderrno == ECONNREFUSED || olderrno == EINTR :#if defined(IPv6) && defined(AF_INET6) : || (haveIPv6 && ((addrlist->addr->ai_next != NULL) || : (addrlist->addr != addrlist->firstaddr)) && : (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT || : olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT :#if defined(EHOSTDOWN) : || olderrno == EHOSTDOWN :#endif : )) :#endif : ) : res = TRANS_TRY_CONNECT_AGAIN; : else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) : res = TRANS_IN_PROGRESS; : else : { : PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n", : olderrno,0, 0); : : res = TRANS_CONNECT_FAILED; : } : } else { : res = 0; : : : /* : * Sync up the address fields of ciptr. : */ : : if (TRANS(SocketINETGetAddr) (ciptr) < 0) : { : PRMSG (1, : "SocketINETConnect: ...SocketINETGetAddr() failed:\n", : 0, 0, 0); : res = TRANS_CONNECT_FAILED; : } : : else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) : { : PRMSG (1, : "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n", : 0, 0, 0); : res = TRANS_CONNECT_FAILED; : } : } : :#if defined(IPv6) && defined(AF_INET6) : if (haveIPv6 && res != 0) { : addrlist->addr = addrlist->addr->ai_next; : } :#endif : : return res; :} : :#endif /* TCPCONN */ : : : :#ifdef UNIXCONN : :/* : * Make sure 'host' is really local. : */ : :static int :UnixHostReallyLocal (char *host) : :{ : char hostnamebuf[256]; : :#if defined(IPv6) && defined(AF_INET6) : if (getaddrinfo == NULL) : haveIPv6 = 0; :#endif : : TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); : : if (strcmp (hostnamebuf, host) == 0) : { : return (1); : } :#if defined(IPv6) && defined(AF_INET6) : else if (haveIPv6) : { : struct addrinfo *localhostaddr; : struct addrinfo *otherhostaddr; : struct addrinfo *i, *j; : int equiv = 0; : : if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0) : return 0; : if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) { : freeaddrinfo(localhostaddr); : return 0; : } : : for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) { : for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) { : if (i->ai_family == j->ai_family) { : if (i->ai_family == AF_INET) { : struct sockaddr_in *sinA : = (struct sockaddr_in *) i->ai_addr; : struct sockaddr_in *sinB : = (struct sockaddr_in *) j->ai_addr; : struct in_addr *A = &sinA->sin_addr; : struct in_addr *B = &sinB->sin_addr; : : if (memcmp(A,B,sizeof(struct in_addr)) == 0) { : equiv = 1; : } : } else if (i->ai_family == AF_INET6) { : struct sockaddr_in6 *sinA : = (struct sockaddr_in6 *) i->ai_addr; : struct sockaddr_in6 *sinB : = (struct sockaddr_in6 *) j->ai_addr; : struct in6_addr *A = &sinA->sin6_addr; : struct in6_addr *B = &sinB->sin6_addr; : : if (memcmp(A,B,sizeof(struct in6_addr)) == 0) { : equiv = 1; : } : } : } : } : } : : freeaddrinfo(localhostaddr); : freeaddrinfo(otherhostaddr); : return equiv; : } :#endif : else : { : /* : * A host may have more than one network address. If any of the : * network addresses of 'host' (specified to the connect call) : * match any of the network addresses of 'hostname' (determined : * by TRANS(GetHostname)), then the two hostnames are equivalent, : * and we know that 'host' is really a local host. : */ : char specified_local_addr_list[10][4]; : int scount, equiv, i, j; :#ifdef XTHREADS_NEEDS_BYNAMEPARAMS : _Xgethostbynameparams hparams; :#endif : struct hostent *hostp; : : if ((hostp = _XGethostbyname (host,hparams)) == NULL) : return (0); : : scount = 0; : while (hostp->h_addr_list[scount] && scount <= 8) : { : /* : * The 2nd call to gethostname() overrides the data : * from the 1st call, so we must save the address list. : */ : : specified_local_addr_list[scount][0] = : hostp->h_addr_list[scount][0]; : specified_local_addr_list[scount][1] = : hostp->h_addr_list[scount][1]; : specified_local_addr_list[scount][2] = : hostp->h_addr_list[scount][2]; : specified_local_addr_list[scount][3] = : hostp->h_addr_list[scount][3]; : scount++; : } : if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL) : return (0); : : equiv = 0; : i = 0; : : while (i < scount && !equiv) : { : j = 0; : : while (hostp->h_addr_list[j]) : { : if ((specified_local_addr_list[i][0] == : hostp->h_addr_list[j][0]) && : (specified_local_addr_list[i][1] == : hostp->h_addr_list[j][1]) && : (specified_local_addr_list[i][2] == : hostp->h_addr_list[j][2]) && : (specified_local_addr_list[i][3] == : hostp->h_addr_list[j][3])) : { : /* They're equal, so we're done */ : : equiv = 1; : break; : } : : j++; : } : : i++; : } : return (equiv); : } :} : :static int :TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port) : :{ : struct sockaddr_un sockname; : int namelen; : :#if defined(hpux) && defined(X11_t) : struct sockaddr_un old_sockname; : int old_namelen; :#endif : : : PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port); : : /* : * Make sure 'host' is really local. If not, we return failure. : * The reason we make this check is because a process may advertise : * a "local" network ID for which it can accept connections, but if : * a process on a remote machine tries to connect to this network ID, : * we know for sure it will fail. : */ : : if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) : { : PRMSG (1, : "SocketUNIXConnect: Cannot connect to non-local host %s\n", : host, 0, 0); : return TRANS_CONNECT_FAILED; : } : : : /* : * Check the port. : */ : : if (!port || !*port) : { : PRMSG (1,"SocketUNIXConnect: Missing port specification\n", : 0, 0, 0); : return TRANS_CONNECT_FAILED; : } : : /* : * Build the socket name. : */ : : sockname.sun_family = AF_UNIX; : : if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) { : PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0); : return TRANS_CONNECT_FAILED; : } : :#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx) : sockname.sun_len = strlen (sockname.sun_path); :#endif : :#if defined(BSD44SOCKETS) || defined(SUN_LEN) : namelen = SUN_LEN (&sockname); :#else : namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); :#endif : : :#if defined(hpux) && defined(X11_t) : /* : * This is gross, but it was in Xlib : */ : old_sockname.sun_family = AF_UNIX; : if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) { : PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0); : return TRANS_CONNECT_FAILED; : } : old_namelen = strlen (old_sockname.sun_path) + : offsetof(struct sockaddr_un, sun_path); :#endif : : : /* : * Do the connect() : */ : : if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0) : { : int olderrno = errno; : int connected = 0; : :#if defined(hpux) && defined(X11_t) : if (olderrno == ENOENT) : { : if (connect (ciptr->fd, : (struct sockaddr *) &old_sockname, old_namelen) >= 0) : { : connected = 1; : } : else : olderrno = errno; : } :#endif : if (!connected) : { : errno = olderrno; : : /* : * If the error was ENOENT, the server may be starting up : * and we should try again. : * : * If the error was EWOULDBLOCK or EINPROGRESS then the socket : * was non-blocking and we should poll using select : * : * If the error was EINTR, the connect was interrupted and we : * should try again. : */ : : if (olderrno == ENOENT || olderrno == EINTR) : return TRANS_TRY_CONNECT_AGAIN; : else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) : return TRANS_IN_PROGRESS; : else : { : PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n", : EGET(),0, 0); : : return TRANS_CONNECT_FAILED; : } : } : } : : /* : * Get the socket name and the peer name from the connect socket, : * since this is unix domain. : */ : : if ((ciptr->addr = (char *) xalloc(namelen)) == NULL || : (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL) : { : PRMSG (1, : "SocketUNIXCreateListener: Can't allocate space for the addr\n", : 0, 0, 0); : return TRANS_CONNECT_FAILED; : } : : ciptr->family = AF_UNIX; : ciptr->addrlen = namelen; : ciptr->peeraddrlen = namelen; : memcpy (ciptr->addr, &sockname, ciptr->addrlen); : memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); : : return 0; :} : :#endif /* UNIXCONN */ : :#endif /* TRANS_CLIENT */ : : :static int :TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) : :{ : PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n", : ciptr, ciptr->fd, pend); :#if defined(QNX4) : *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */ :#endif :#ifdef WIN32 : { : int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend); : errno = WSAGetLastError(); : return ret; : } :#else :#if (defined(i386) && defined(SYSV) && !defined(SCO325)) || (defined(_SEQUENT_) && _SOCKET_VERSION == 1) : return ioctl (ciptr->fd, I_NREAD, (char *) pend); :#else :#if defined(__UNIXOS2__) : return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int)); :#else : return ioctl (ciptr->fd, FIONREAD, (char *) pend); :#endif /* __UNIXOS2__ */ :#endif /* i386 && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */ :#endif /* WIN32 */ :} : : :static int :TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) : 1 0.0011 :{ /* _XSERVTransSocketRead total: 2 0.0022 */ : PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); : :#if defined(WIN32) || defined(__UNIXOS2__) : { : int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); :#ifdef WIN32 : errno = WSAGetLastError(); :#endif : return ret; : } :#else 1 0.0011 : return read (ciptr->fd, buf, size); :#endif /* WIN32 */ :} : : :static int :TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) : :{ : PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); : :#if defined(WIN32) || defined(__UNIXOS2__) : { : int ret = send ((SOCKET)ciptr->fd, buf, size, 0); :#ifdef WIN32 : errno = WSAGetLastError(); :#endif : return ret; : } :#else : return write (ciptr->fd, buf, size); :#endif /* WIN32 */ :} : : :static int :TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) : :{ : PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); : : return READV (ciptr, buf, size); :} : : :static int :TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) : :{ : PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); : : return WRITEV (ciptr, buf, size); :} : : :static int :TRANS(SocketDisconnect) (XtransConnInfo ciptr) : :{ : PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0); : :#ifdef WIN32 : { : int ret = shutdown (ciptr->fd, 2); : errno = WSAGetLastError(); : return ret; : } :#else : return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ :#endif :} : : :#ifdef TCPCONN :static int :TRANS(SocketINETClose) (XtransConnInfo ciptr) : :{ : PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0); : :#ifdef WIN32 : { : int ret = close (ciptr->fd); : errno = WSAGetLastError(); : return ret; : } :#else : return close (ciptr->fd); :#endif :} : :#endif /* TCPCONN */ : : :#ifdef UNIXCONN :static int :TRANS(SocketUNIXClose) (XtransConnInfo ciptr) : :{ : /* : * If this is the server side, then once the socket is closed, : * it must be unlinked to completely close it : */ : : struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr; : int ret; : : PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0); : : ret = close(ciptr->fd); : : if (ciptr->flags : && sockname : && sockname->sun_family == AF_UNIX : && sockname->sun_path[0]) : { : if (!(ciptr->flags & TRANS_NOUNLINK)) : unlink (sockname->sun_path); : } : : return ret; :} : :static int :TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) : :{ : /* : * Don't unlink path. : */ : : int ret; : : PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n", : ciptr, ciptr->fd, 0); : : ret = close(ciptr->fd); : : return ret; :} : :#endif /* UNIXCONN */ : : :#ifdef TCPCONN :# ifdef TRANS_SERVER :static char* tcp_nolisten[] = { : "inet", :#if defined(IPv6) && defined(AF_INET6) : "inet6", :#endif : NULL :}; :# endif : :Xtransport TRANS(SocketTCPFuncs) = { : /* Socket Interface */ : "tcp", : TRANS_ALIAS, :#ifdef TRANS_CLIENT : TRANS(SocketOpenCOTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : tcp_nolisten, : TRANS(SocketOpenCOTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketOpenCLTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : TRANS(SocketOpenCLTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_REOPEN : TRANS(SocketReopenCOTSServer), : TRANS(SocketReopenCLTSServer), :#endif : TRANS(SocketSetOption), :#ifdef TRANS_SERVER : TRANS(SocketINETCreateListener), : NULL, /* ResetListener */ : TRANS(SocketINETAccept), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketINETConnect), :#endif /* TRANS_CLIENT */ : TRANS(SocketBytesReadable), : TRANS(SocketRead), : TRANS(SocketWrite), : TRANS(SocketReadv), : TRANS(SocketWritev), : TRANS(SocketDisconnect), : TRANS(SocketINETClose), : TRANS(SocketINETClose), : }; : :Xtransport TRANS(SocketINETFuncs) = { : /* Socket Interface */ : "inet", : 0, :#ifdef TRANS_CLIENT : TRANS(SocketOpenCOTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : NULL, : TRANS(SocketOpenCOTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketOpenCLTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : TRANS(SocketOpenCLTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_REOPEN : TRANS(SocketReopenCOTSServer), : TRANS(SocketReopenCLTSServer), :#endif : TRANS(SocketSetOption), :#ifdef TRANS_SERVER : TRANS(SocketINETCreateListener), : NULL, /* ResetListener */ : TRANS(SocketINETAccept), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketINETConnect), :#endif /* TRANS_CLIENT */ : TRANS(SocketBytesReadable), : TRANS(SocketRead), : TRANS(SocketWrite), : TRANS(SocketReadv), : TRANS(SocketWritev), : TRANS(SocketDisconnect), : TRANS(SocketINETClose), : TRANS(SocketINETClose), : }; : :#if defined(IPv6) && defined(AF_INET6) :Xtransport TRANS(SocketINET6Funcs) = { : /* Socket Interface */ : "inet6", : 0, :#ifdef TRANS_CLIENT : TRANS(SocketOpenCOTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : NULL, : TRANS(SocketOpenCOTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketOpenCLTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : TRANS(SocketOpenCLTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_REOPEN : TRANS(SocketReopenCOTSServer), : TRANS(SocketReopenCLTSServer), :#endif : TRANS(SocketSetOption), :#ifdef TRANS_SERVER : TRANS(SocketINETCreateListener), : NULL, /* ResetListener */ : TRANS(SocketINETAccept), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketINETConnect), :#endif /* TRANS_CLIENT */ : TRANS(SocketBytesReadable), : TRANS(SocketRead), : TRANS(SocketWrite), : TRANS(SocketReadv), : TRANS(SocketWritev), : TRANS(SocketDisconnect), : TRANS(SocketINETClose), : TRANS(SocketINETClose), : }; :#endif /* IPv6 */ :#endif /* TCPCONN */ : :#ifdef UNIXCONN :#if !defined(LOCALCONN) :Xtransport TRANS(SocketLocalFuncs) = { : /* Socket Interface */ : "local", : 0, :#ifdef TRANS_CLIENT : TRANS(SocketOpenCOTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : NULL, : TRANS(SocketOpenCOTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketOpenCLTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : TRANS(SocketOpenCLTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_REOPEN : TRANS(SocketReopenCOTSServer), : TRANS(SocketReopenCLTSServer), :#endif : TRANS(SocketSetOption), :#ifdef TRANS_SERVER : TRANS(SocketUNIXCreateListener), : TRANS(SocketUNIXResetListener), : TRANS(SocketUNIXAccept), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketUNIXConnect), :#endif /* TRANS_CLIENT */ : TRANS(SocketBytesReadable), : TRANS(SocketRead), : TRANS(SocketWrite), : TRANS(SocketReadv), : TRANS(SocketWritev), : TRANS(SocketDisconnect), : TRANS(SocketUNIXClose), : TRANS(SocketUNIXCloseForCloning), : }; :#endif /* !LOCALCONN */ :# ifdef TRANS_SERVER :# if !defined(LOCALCONN) :static char* unix_nolisten[] = { "local" , NULL }; :# endif :# endif : :Xtransport TRANS(SocketUNIXFuncs) = { : /* Socket Interface */ : "unix", :#if !defined(LOCALCONN) : TRANS_ALIAS, :#else : 0, :#endif :#ifdef TRANS_CLIENT : TRANS(SocketOpenCOTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER :#if !defined(LOCALCONN) : unix_nolisten, :#else : NULL, :#endif : TRANS(SocketOpenCOTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketOpenCLTSClient), :#endif /* TRANS_CLIENT */ :#ifdef TRANS_SERVER : TRANS(SocketOpenCLTSServer), :#endif /* TRANS_SERVER */ :#ifdef TRANS_REOPEN : TRANS(SocketReopenCOTSServer), : TRANS(SocketReopenCLTSServer), :#endif : TRANS(SocketSetOption), :#ifdef TRANS_SERVER : TRANS(SocketUNIXCreateListener), : TRANS(SocketUNIXResetListener), : TRANS(SocketUNIXAccept), :#endif /* TRANS_SERVER */ :#ifdef TRANS_CLIENT : TRANS(SocketUNIXConnect), :#endif /* TRANS_CLIENT */ : TRANS(SocketBytesReadable), : TRANS(SocketRead), : TRANS(SocketWrite), : TRANS(SocketReadv), : TRANS(SocketWritev), : TRANS(SocketDisconnect), : TRANS(SocketUNIXClose), : TRANS(SocketUNIXCloseForCloning), : }; : :#endif /* UNIXCONN */ /* * Total samples for file : "/home/cworth/src/xorg/xserver/fb/fbtrap.c" * * 1 0.0011 */ :/* : * Copyright © 2004 Keith Packard : * : * Permission to use, copy, modify, distribute, and sell this software and its : * documentation for any purpose is hereby granted without fee, provided that : * the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name of Keith Packard not be used in : * advertising or publicity pertaining to distribution of the software without : * specific, written prior permission. Keith Packard makes no : * representations about the suitability of this software for any purpose. It : * is provided "as is" without express or implied warranty. : * : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR : * PERFORMANCE OF THIS SOFTWARE. : */ : :#ifdef HAVE_DIX_CONFIG_H :#include :#endif : :#include "fb.h" : :#ifdef RENDER : :#include "picturestr.h" :#include "mipict.h" :#include "renderedge.h" :#include "fbpict.h" : :void :fbAddTraps (PicturePtr pPicture, : INT16 x_off, : INT16 y_off, : int ntrap, : xTrap *traps) :{ : pixman_image_t *image = image_from_pict (pPicture, FALSE); : : if (!image) : return; : : pixman_add_traps (image, x_off, y_off, ntrap, (pixman_trap_t *)traps); : : fbFinishAccess (pPicture->pDrawable); : : pixman_image_unref (image); :} : :void :fbRasterizeTrapezoid (PicturePtr pPicture, : xTrapezoid *trap, : int x_off, : int y_off) :{ /* fbRasterizeTrapezoid total: 1 0.0011 */ : pixman_image_t *image = image_from_pict (pPicture, FALSE); : : if (!image) : return; : : pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *)trap, x_off, y_off); : : fbFinishAccess (pPicture->pDrawable); : 1 0.0011 : pixman_image_unref (image); :} : :static int :_GreaterY (xPointFixed *a, xPointFixed *b) :{ : if (a->y == b->y) : return a->x > b->x; : return a->y > b->y; :} : :/* : * Note that the definition of this function is a bit odd because : * of the X coordinate space (y increasing downwards). : */ :static int :_Clockwise (xPointFixed *ref, xPointFixed *a, xPointFixed *b) :{ : xPointFixed ad, bd; : : ad.x = a->x - ref->x; : ad.y = a->y - ref->y; : bd.x = b->x - ref->x; : bd.y = b->y - ref->y; : : return ((xFixed_32_32) bd.y * ad.x - (xFixed_32_32) ad.y * bd.x) < 0; :} : :/* FIXME -- this could be made more efficient */ :void :fbAddTriangles (PicturePtr pPicture, : INT16 x_off, : INT16 y_off, : int ntri, : xTriangle *tris) :{ : xPointFixed *top, *left, *right, *tmp; : xTrapezoid trap; : : for (; ntri; ntri--, tris++) : { : top = &tris->p1; : left = &tris->p2; : right = &tris->p3; : if (_GreaterY (top, left)) { : tmp = left; left = top; top = tmp; : } : if (_GreaterY (top, right)) { : tmp = right; right = top; top = tmp; : } : if (_Clockwise (top, right, left)) { : tmp = right; right = left; left = tmp; : } : : /* : * Two cases: : * : * + + : * / \ / \ : * / \ / \ : * / + + \ : * / -- -- \ : * / -- -- \ : * / --- --- \ : * +-- --+ : */ : : trap.top = top->y; : trap.left.p1 = *top; : trap.left.p2 = *left; : trap.right.p1 = *top; : trap.right.p2 = *right; : if (right->y < left->y) : trap.bottom = right->y; : else : trap.bottom = left->y; : fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); : if (right->y < left->y) : { : trap.top = right->y; : trap.bottom = left->y; : trap.right.p1 = *right; : trap.right.p2 = *left; : } : else : { : trap.top = left->y; : trap.bottom = right->y; : trap.left.p1 = *left; : trap.left.p2 = *right; : } : fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); : } :} : :#endif /* RENDER */ /* * Total samples for file : "/home/cworth/opt/xorg//include/X11/Xtrans/Xtrans.c" * * 1 0.0011 */ :/* $XdotOrg: xc/lib/xtrans/Xtrans.c,v 1.4 2004/11/15 15:06:56 ago Exp $ */ :/* $Xorg: Xtrans.c,v 1.4 2001/02/09 02:04:06 xorgcvs Exp $ */ :/* : :Copyright 1993, 1994, 1998 The Open Group : :Permission to use, copy, modify, distribute, and sell this software and its :documentation for any purpose is hereby granted without fee, provided that :the above copyright notice appear in all copies and that both that :copyright notice and this permission notice appear in supporting :documentation. : :The above copyright notice and this permission notice shall be included :in all copies or substantial portions of the Software. : :THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS :OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF :MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. :IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR :OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, :ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR :OTHER DEALINGS IN THE SOFTWARE. : :Except as contained in this notice, the name of The Open Group shall :not be used in advertising or otherwise to promote the sale, use or :other dealings in this Software without prior written authorization :from The Open Group. : :*/ :/* $XFree86: xc/lib/xtrans/Xtrans.c,v 3.33 2003/08/11 17:41:29 eich Exp $ */ : :/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA : * : * All Rights Reserved : * : * Permission to use, copy, modify, and distribute this software and its : * documentation for any purpose and without fee is hereby granted, provided : * that the above copyright notice appear in all copies and that both that : * copyright notice and this permission notice appear in supporting : * documentation, and that the name NCR not be used in advertising : * or publicity pertaining to distribution of the software without specific, : * written prior permission. NCR makes no representations about the : * suitability of this software for any purpose. It is provided "as is" : * without express or implied warranty. : * : * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN : * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS : * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. : */ : :#include : :/* : * The transport table contains a definition for every transport (protocol) : * family. All operations that can be made on the transport go through this : * table. : * : * Each transport is assigned a unique transport id. : * : * New transports can be added by adding an entry in this table. : * For compatiblity, the transport ids should never be renumbered. : * Always add to the end of the list. : */ : :#define TRANS_TLI_INET_INDEX 1 :#define TRANS_TLI_TCP_INDEX 2 :#define TRANS_TLI_TLI_INDEX 3 :#define TRANS_SOCKET_UNIX_INDEX 4 :#define TRANS_SOCKET_LOCAL_INDEX 5 :#define TRANS_SOCKET_INET_INDEX 6 :#define TRANS_SOCKET_TCP_INDEX 7 :#define TRANS_DNET_INDEX 8 :#define TRANS_LOCAL_LOCAL_INDEX 9 :#define TRANS_LOCAL_PTS_INDEX 10 :#define TRANS_LOCAL_NAMED_INDEX 11 :#define TRANS_LOCAL_ISC_INDEX 12 :#define TRANS_LOCAL_SCO_INDEX 13 :#define TRANS_SOCKET_INET6_INDEX 14 :#define TRANS_LOCAL_PIPE_INDEX 15 : : :static :Xtransport_table Xtransports[] = { :#if defined(STREAMSCONN) : { &TRANS(TLITCPFuncs), TRANS_TLI_TCP_INDEX }, : { &TRANS(TLIINETFuncs), TRANS_TLI_INET_INDEX }, : { &TRANS(TLITLIFuncs), TRANS_TLI_TLI_INDEX }, :#endif /* STREAMSCONN */ :#if defined(TCPCONN) : { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX }, :#if defined(IPv6) && defined(AF_INET6) : { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX }, :#endif /* IPv6 */ : { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX }, :#endif /* TCPCONN */ :#if defined(DNETCONN) : { &TRANS(DNETFuncs), TRANS_DNET_INDEX }, :#endif /* DNETCONN */ :#if defined(UNIXCONN) :#if !defined(LOCALCONN) : { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX }, :#endif /* !LOCALCONN */ : { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX }, :#endif /* UNIXCONN */ :#if defined(OS2PIPECONN) : { &TRANS(OS2LocalFuncs), TRANS_LOCAL_LOCAL_INDEX }, :#endif /* OS2PIPECONN */ :#if defined(LOCALCONN) : { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX }, :#ifndef sun : { &TRANS(PTSFuncs), TRANS_LOCAL_PTS_INDEX }, :#endif /* sun */ :#ifdef SVR4 : { &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX }, :#endif :#ifdef sun : { &TRANS(PIPEFuncs), TRANS_LOCAL_PIPE_INDEX }, :#else /* !sun */ :#if !defined(__SCO__) && !defined(__UNIXWARE__) : { &TRANS(ISCFuncs), TRANS_LOCAL_ISC_INDEX }, :#endif : { &TRANS(SCOFuncs), TRANS_LOCAL_SCO_INDEX }, :#endif /* sun */ :#endif /* LOCALCONN */ :}; : :#define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table)) : : :#ifdef WIN32 :#define ioctl ioctlsocket :#endif : : : :/* : * These are a few utility function used by the public interface functions. : */ : :void :TRANS(FreeConnInfo) (XtransConnInfo ciptr) : :{ : PRMSG (3,"FreeConnInfo(%p)\n", ciptr, 0, 0); : : if (ciptr->addr) : xfree (ciptr->addr); : : if (ciptr->peeraddr) : xfree (ciptr->peeraddr); : : if (ciptr->port) : xfree (ciptr->port); : : xfree ((char *) ciptr); :} : : :#define PROTOBUFSIZE 20 : :static Xtransport * :TRANS(SelectTransport) (char *protocol) : :{ : char protobuf[PROTOBUFSIZE]; : int i; : : PRMSG (3,"SelectTransport(%s)\n", protocol, 0, 0); : : /* : * Force Protocol to be lowercase as a way of doing : * a case insensitive match. : */ : : strncpy (protobuf, protocol, PROTOBUFSIZE - 1); : protobuf[PROTOBUFSIZE-1] = '\0'; : : for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++) : if (isupper (protobuf[i])) : protobuf[i] = tolower (protobuf[i]); : : /* Look at all of the configured protocols */ : : for (i = 0; i < NUMTRANS; i++) : { : if (!strcmp (protobuf, Xtransports[i].transport->TransName)) : return Xtransports[i].transport; : } : : return NULL; :} : :#ifndef TEST_t :static :#endif /* TEST_t */ :int :TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) : :{ : /* : * For the font library, the address is a string formatted : * as "protocol/host:port[/catalogue]". Note that the catologue : * is optional. At this time, the catologue info is ignored, but : * we have to parse it anyways. : * : * Other than fontlib, the address is a string formatted : * as "protocol/host:port". : * : * If the protocol part is missing, then assume TCP. : * If the protocol part and host part are missing, then assume local. : * If a "::" is found then assume DNET. : */ : : char *mybuf, *tmpptr; : char *_protocol, *_host, *_port; : char hostnamebuf[256]; : int _host_len; : : PRMSG (3,"ParseAddress(%s)\n", address, 0, 0); : : /* Copy the string so it can be changed */ : : tmpptr = mybuf = (char *) xalloc (strlen (address) + 1); : strcpy (mybuf, address); : : /* Parse the string to get each component */ : : /* Get the protocol part */ : : _protocol = mybuf; : : : if ( ((mybuf = strchr (mybuf,'/')) == NULL) && : ((mybuf = strrchr (tmpptr,':')) == NULL) ) : { : /* address is in a bad format */ : *protocol = NULL; : *host = NULL; : *port = NULL; : xfree (tmpptr); : return 0; : } : : if (*mybuf == ':') : { : /* : * If there is a hostname, then assume tcp, otherwise : * it must be local. : */ : if (mybuf == tmpptr) : { : /* There is neither a protocol or host specified */ : _protocol = "local"; : } : else : { : /* There is a hostname specified */ : _protocol = "tcp"; : mybuf = tmpptr; /* reset to the begining of the host ptr */ : } : } : else : { : /* *mybuf == '/' */ : : *mybuf ++= '\0'; /* put a null at the end of the protocol */ : : if (strlen(_protocol) == 0) : { : /* : * If there is a hostname, then assume tcp, otherwise : * it must be local. : */ : if (*mybuf != ':') : _protocol = "tcp"; : else : _protocol = "local"; : } : } : : /* Get the host part */ : : _host = mybuf; : : if ((mybuf = strrchr (mybuf,':')) == NULL) : { : *protocol = NULL; : *host = NULL; : *port = NULL; : xfree (tmpptr); : return 0; : } : : /* Check for DECnet */ : : if ((mybuf != _host) && (*(mybuf - 1) == ':') :#if defined(IPv6) && defined(AF_INET6) : /* An IPv6 address can end in :: so three : in a row is assumed to be : an IPv6 host and not a DECnet node with a : in it's name, unless : DECnet is specifically requested */ : && ( ((mybuf - 1) == _host) || (*(mybuf - 2) != ':') || : ((_protocol != NULL) && (strcmp(_protocol, "dnet") == 0)) ) :#endif : ) : { : _protocol = "dnet"; : *(mybuf - 1) = '\0'; : } : : *mybuf ++= '\0'; : : _host_len = strlen(_host); : if (_host_len == 0) : { : TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); : _host = hostnamebuf; : } :#if defined(IPv6) && defined(AF_INET6) : /* hostname in IPv6 [numeric_addr]:0 form? */ : else if ( (_host_len > 3) && : ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0)) : && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) { : struct sockaddr_in6 sin6; : : *(_host + _host_len - 1) = '\0'; : : /* Verify address is valid IPv6 numeric form */ : if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) { : /* It is. Use it as such. */ : _host++; : _protocol = "inet6"; : } else { : /* It's not, restore it just in case some other code can use it. */ : *(_host + _host_len - 1) = ']'; : } : } :#endif : : : /* Get the port */ : : _port = mybuf; : :#if defined(FONT_t) || defined(FS_t) : /* : * Is there an optional catalogue list? : */ : : if ((mybuf = strchr (mybuf,'/')) != NULL) : *mybuf ++= '\0'; : : /* : * The rest, if any, is the (currently unused) catalogue list. : * : * _catalogue = mybuf; : */ :#endif : : /* : * Now that we have all of the components, allocate new : * string space for them. : */ : : if ((*protocol = (char *) xalloc(strlen (_protocol) + 1)) == NULL) : { : /* Malloc failed */ : *port = NULL; : *host = NULL; : *protocol = NULL; : xfree (tmpptr); : return 0; : } : else : strcpy (*protocol, _protocol); : : if ((*host = (char *) xalloc (strlen (_host) + 1)) == NULL) : { : /* Malloc failed */ : *port = NULL; : *host = NULL; : xfree (*protocol); : *protocol = NULL; : xfree (tmpptr); : return 0; : } : else : strcpy (*host, _host); : : if ((*port = (char *) xalloc (strlen (_port) + 1)) == NULL) : { : /* Malloc failed */ : *port = NULL; : xfree (*host); : *host = NULL; : xfree (*protocol); : *protocol = NULL; : xfree (tmpptr); : return 0; : } : else : strcpy (*port, _port); : : xfree (tmpptr); : : return 1; :} : : :/* : * TRANS(Open) does all of the real work opening a connection. The only : * funny part about this is the type parameter which is used to decide which : * type of open to perform. : */ : :static XtransConnInfo :TRANS(Open) (int type, char *address) : :{ : char *protocol = NULL, *host = NULL, *port = NULL; : XtransConnInfo ciptr = NULL; : Xtransport *thistrans; : : PRMSG (2,"Open(%d,%s)\n", type, address, 0); : :#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN)) : if (TRANS(WSAStartup)()) : { : PRMSG (1,"Open: WSAStartup failed\n", 0, 0, 0); : return NULL; : } :#endif : : /* Parse the Address */ : : if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) : { : PRMSG (1,"Open: Unable to Parse address %s\n", address, 0, 0); : return NULL; : } : : /* Determine the transport type */ : : if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL) : { : PRMSG (1,"Open: Unable to find transport for %s\n", : protocol, 0, 0); : : xfree (protocol); : xfree (host); : xfree (port); : return NULL; : } : : /* Open the transport */ : : switch (type) : { : case XTRANS_OPEN_COTS_CLIENT: :#ifdef TRANS_CLIENT : ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port); :#endif /* TRANS_CLIENT */ : break; : case XTRANS_OPEN_COTS_SERVER: :#ifdef TRANS_SERVER : ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port); :#endif /* TRANS_SERVER */ : break; : case XTRANS_OPEN_CLTS_CLIENT: :#ifdef TRANS_CLIENT : ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port); :#endif /* TRANS_CLIENT */ : break; : case XTRANS_OPEN_CLTS_SERVER: :#ifdef TRANS_SERVER : ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port); :#endif /* TRANS_SERVER */ : break; : default: : PRMSG (1,"Open: Unknown Open type %d\n", type, 0, 0); : } : : if (ciptr == NULL) : { : if (!(thistrans->flags & TRANS_DISABLED)) : { : PRMSG (1,"Open: transport open failed for %s/%s:%s\n", : protocol, host, port); : } : xfree (protocol); : xfree (host); : xfree (port); : return NULL; : } : : ciptr->transptr = thistrans; : ciptr->port = port; /* We need this for TRANS(Reopen) */ : : xfree (protocol); : xfree (host); : : return ciptr; :} : : :#ifdef TRANS_REOPEN : :/* : * We might want to create an XtransConnInfo object based on a previously : * opened connection. For example, the font server may clone itself and : * pass file descriptors to the parent. : */ : :static XtransConnInfo :TRANS(Reopen) (int type, int trans_id, int fd, char *port) : :{ : XtransConnInfo ciptr = NULL; : Xtransport *thistrans = NULL; : char *save_port; : int i; : : PRMSG (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port); : : /* Determine the transport type */ : : for (i = 0; i < NUMTRANS; i++) : if (Xtransports[i].transport_id == trans_id) : { : thistrans = Xtransports[i].transport; : break; : } : : if (thistrans == NULL) : { : PRMSG (1,"Reopen: Unable to find transport id %d\n", : trans_id, 0, 0); : : return NULL; : } : : if ((save_port = (char *) xalloc (strlen (port) + 1)) == NULL) : { : PRMSG (1,"Reopen: Unable to malloc port string\n", 0, 0, 0); : : return NULL; : } : : strcpy (save_port, port); : : /* Get a new XtransConnInfo object */ : : switch (type) : { : case XTRANS_OPEN_COTS_SERVER: : ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port); : break; : case XTRANS_OPEN_CLTS_SERVER: : ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port); : break; : default: : PRMSG (1,"Reopen: Bad Open type %d\n", type, 0, 0); : } : : if (ciptr == NULL) : { : PRMSG (1,"Reopen: transport open failed\n", 0, 0, 0); : return NULL; : } : : ciptr->transptr = thistrans; : ciptr->port = save_port; : : return ciptr; :} : :#endif /* TRANS_REOPEN */ : : : :/* : * These are the public interfaces to this Transport interface. : * These are the only functions that should have knowledge of the transport : * table. : */ : :#ifdef TRANS_CLIENT : :XtransConnInfo :TRANS(OpenCOTSClient) (char *address) : :{ : PRMSG (2,"OpenCOTSClient(%s)\n", address, 0, 0); : return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address); :} : :#endif /* TRANS_CLIENT */ : : :#ifdef TRANS_SERVER : :XtransConnInfo :TRANS(OpenCOTSServer) (char *address) : :{ : PRMSG (2,"OpenCOTSServer(%s)\n", address, 0, 0); : return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address); :} : :#endif /* TRANS_SERVER */ : : :#ifdef TRANS_CLIENT : :XtransConnInfo :TRANS(OpenCLTSClient) (char *address) : :{ : PRMSG (2,"OpenCLTSClient(%s)\n", address, 0, 0); : return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address); :} : :#endif /* TRANS_CLIENT */ : : :#ifdef TRANS_SERVER : :XtransConnInfo :TRANS(OpenCLTSServer) (char *address) : :{ : PRMSG (2,"OpenCLTSServer(%s)\n", address, 0, 0); : return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address); :} : :#endif /* TRANS_SERVER */ : : :#ifdef TRANS_REOPEN : :XtransConnInfo :TRANS(ReopenCOTSServer) (int trans_id, int fd, char *port) : :{ : PRMSG (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port); : return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port); :} : :XtransConnInfo :TRANS(ReopenCLTSServer) (int trans_id, int fd, char *port) : :{ : PRMSG (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port); : return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port); :} : : :int :TRANS(GetReopenInfo) (XtransConnInfo ciptr, : int *trans_id, int *fd, char **port) : :{ : int i; : : for (i = 0; i < NUMTRANS; i++) : if (Xtransports[i].transport == ciptr->transptr) : { : *trans_id = Xtransports[i].transport_id; : *fd = ciptr->fd; : : if ((*port = (char *) xalloc (strlen (ciptr->port) + 1)) == NULL) : return 0; : else : { : strcpy (*port, ciptr->port); : return 1; : } : } : : return 0; :} : :#endif /* TRANS_REOPEN */ : : :int :TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg) : :{ : int fd = ciptr->fd; : int ret = 0; : : PRMSG (2,"SetOption(%d,%d,%d)\n", fd, option, arg); : : /* : * For now, all transport type use the same stuff for setting options. : * As long as this is true, we can put the common code here. Once a more : * complicated transport such as shared memory or an OSI implementation : * that uses the session and application libraries is implemented, this : * code may have to move to a transport dependent function. : * : * ret = ciptr->transptr->SetOption (ciptr, option, arg); : */ : : switch (option) : { : case TRANS_NONBLOCKING: : switch (arg) : { : case 0: : /* Set to blocking mode */ : break; : case 1: /* Set to non-blocking mode */ : :#if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux) && !defined(AIXV3) && !defined(uniosu) && !defined(__UNIXOS2__) && !defined(SCO325)) && !defined(__QNX__) : ret = fcntl (fd, F_GETFL, 0); : if (ret != -1) : ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK); :#else :#ifdef FIOSNBIO : { : int arg; : arg = 1; : ret = ioctl (fd, FIOSNBIO, &arg); : } :#else :#if (defined(AIXV3) || defined(uniosu) || defined(WIN32) || defined(__UNIXOS2__) || defined(__QNX__)) && defined(FIONBIO) : { :#ifdef WIN32 : u_long arg; :#else : int arg; :#endif : arg = 1; :/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail : * eventually with EWOULDBLOCK */ :#ifndef __UNIXOS2__ : ret = ioctl (fd, FIONBIO, &arg); :#else :/* ret = ioctl(fd, FIONBIO, &arg, sizeof(int));*/ :#endif : } :#else : ret = fcntl (fd, F_GETFL, 0); :#ifdef FNDELAY : ret = fcntl (fd, F_SETFL, ret | FNDELAY); :#else : ret = fcntl (fd, F_SETFL, ret | O_NDELAY); :#endif :#endif /* AIXV3 || uniosu */ :#endif /* FIOSNBIO */ :#endif /* O_NONBLOCK */ : break; : default: : /* Unknown option */ : break; : } : break; : case TRANS_CLOSEONEXEC: :#ifdef F_SETFD :#ifdef FD_CLOEXEC : ret = fcntl (fd, F_SETFD, FD_CLOEXEC); :#else : ret = fcntl (fd, F_SETFD, 1); :#endif /* FD_CLOEXEC */ :#endif /* F_SETFD */ : break; : } : : return ret; :} : :#ifdef TRANS_SERVER : :int :TRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags) : :{ : return ciptr->transptr->CreateListener (ciptr, port, flags); :} : :int :TRANS(NoListen) (char * protocol) : :{ : Xtransport *trans; : int i = 0, ret = 0; : : if ((trans = TRANS(SelectTransport)(protocol)) == NULL) : { : PRMSG (1,"TransNoListen: unable to find transport: %s\n", : protocol, 0, 0); : : return -1; : } : if (trans->flags & TRANS_ALIAS) { : if (trans->nolisten) : while (trans->nolisten[i]) { : ret |= TRANS(NoListen)(trans->nolisten[i]); : i++; : } : } : : trans->flags |= TRANS_NOLISTEN; : return ret; :} : :int :TRANS(ResetListener) (XtransConnInfo ciptr) : :{ : if (ciptr->transptr->ResetListener) : return ciptr->transptr->ResetListener (ciptr); : else : return TRANS_RESET_NOOP; :} : : :XtransConnInfo :TRANS(Accept) (XtransConnInfo ciptr, int *status) : :{ : XtransConnInfo newciptr; : : PRMSG (2,"Accept(%d)\n", ciptr->fd, 0, 0); : : newciptr = ciptr->transptr->Accept (ciptr, status); : : if (newciptr) : newciptr->transptr = ciptr->transptr; : : return newciptr; :} : :#endif /* TRANS_SERVER */ : : :#ifdef TRANS_CLIENT : :int :TRANS(Connect) (XtransConnInfo ciptr, char *address) : :{ : char *protocol; : char *host; : char *port; : int ret; : : PRMSG (2,"Connect(%d,%s)\n", ciptr->fd, address, 0); : : if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) : { : PRMSG (1,"Connect: Unable to Parse address %s\n", : address, 0, 0); : return -1; : } : : if (!port || !*port) : { : PRMSG (1,"Connect: Missing port specification in %s\n", : address, 0, 0); : if (protocol) xfree (protocol); : if (host) xfree (host); : return -1; : } : : ret = ciptr->transptr->Connect (ciptr, host, port); : : if (protocol) xfree (protocol); : if (host) xfree (host); : if (port) xfree (port); : : return ret; :} : :#endif /* TRANS_CLIENT */ : : :int :TRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) : :{ : return ciptr->transptr->BytesReadable (ciptr, pend); :} : :int :TRANS(Read) (XtransConnInfo ciptr, char *buf, int size) : :{ /* _XSERVTransRead total: 1 0.0011 */ 1 0.0011 : return ciptr->transptr->Read (ciptr, buf, size); :} : :int :TRANS(Write) (XtransConnInfo ciptr, char *buf, int size) : :{ : return ciptr->transptr->Write (ciptr, buf, size); :} : :int :TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size) : :{ : return ciptr->transptr->Readv (ciptr, buf, size); :} : :int :TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) : :{ : return ciptr->transptr->Writev (ciptr, buf, size); :} : :int :TRANS(Disconnect) (XtransConnInfo ciptr) : :{ : return ciptr->transptr->Disconnect (ciptr); :} : :int :TRANS(Close) (XtransConnInfo ciptr) : :{ : int ret; : : PRMSG (2,"Close(%d)\n", ciptr->fd, 0, 0); : : ret = ciptr->transptr->Close (ciptr); : : TRANS(FreeConnInfo) (ciptr); : : return ret; :} : :int :TRANS(CloseForCloning) (XtransConnInfo ciptr) : :{ : int ret; : : PRMSG (2,"CloseForCloning(%d)\n", ciptr->fd, 0, 0); : : ret = ciptr->transptr->CloseForCloning (ciptr); : : TRANS(FreeConnInfo) (ciptr); : : return ret; :} : :int :TRANS(IsLocal) (XtransConnInfo ciptr) : :{ : return (ciptr->family == AF_UNIX); :} : : :int :TRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, : Xtransaddr **addrp) : :{ : PRMSG (2,"GetMyAddr(%d)\n", ciptr->fd, 0, 0); : : *familyp = ciptr->family; : *addrlenp = ciptr->addrlen; : : if ((*addrp = (Xtransaddr *) xalloc (ciptr->addrlen)) == NULL) : { : PRMSG (1,"GetMyAddr: malloc failed\n", 0, 0, 0); : return -1; : } : memcpy(*addrp, ciptr->addr, ciptr->addrlen); : : return 0; :} : :int :TRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, : Xtransaddr **addrp) : :{ : PRMSG (2,"GetPeerAddr(%d)\n", ciptr->fd, 0, 0); : : *familyp = ciptr->family; : *addrlenp = ciptr->peeraddrlen; : : if ((*addrp = (Xtransaddr *) xalloc (ciptr->peeraddrlen)) == NULL) : { : PRMSG (1,"GetPeerAddr: malloc failed\n", 0, 0, 0); : return -1; : } : memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen); : : return 0; :} : : :int :TRANS(GetConnectionNumber) (XtransConnInfo ciptr) : :{ : return ciptr->fd; :} : : :/* : * These functions are really utility functions, but they require knowledge : * of the internal data structures, so they have to be part of the Transport : * Independant API. : */ : :#ifdef TRANS_SERVER : :static int :complete_network_count (void) : :{ : int count = 0; : int found_local = 0; : int i; : : /* : * For a complete network, we only need one LOCALCONN transport to work : */ : : for (i = 0; i < NUMTRANS; i++) : { : if (Xtransports[i].transport->flags & TRANS_ALIAS : || Xtransports[i].transport->flags & TRANS_NOLISTEN) : continue; : : if (Xtransports[i].transport->flags & TRANS_LOCAL) : found_local = 1; : else : count++; : } : : return (count + found_local); :} : : : :int :TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, : XtransConnInfo **ciptrs_ret) : :{ : char buffer[256]; /* ??? What size ?? */ : XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; : int status, i, j; :#if defined(IPv6) && defined(AF_INET6) : int ipv6_succ = 0; :#endif : : PRMSG (2,"MakeAllCOTSServerListeners(%s,%p)\n", : port ? port : "NULL", ciptrs_ret, 0); : : *count_ret = 0; : : for (i = 0; i < NUMTRANS; i++) : { : Xtransport *trans = Xtransports[i].transport; : unsigned int flags = 0; : : if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN) : continue; : : snprintf(buffer, sizeof(buffer), "%s/:%s", : trans->TransName, port ? port : ""); : : PRMSG (5,"MakeAllCOTSServerListeners: opening %s\n", : buffer, 0, 0); : : if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL) : { : if (trans->flags & TRANS_DISABLED) : continue; : : PRMSG (1, : "MakeAllCOTSServerListeners: failed to open listener for %s\n", : trans->TransName, 0, 0); : continue; : } :#if defined(IPv6) && defined(AF_INET6) : if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX : && ipv6_succ)) : flags |= ADDR_IN_USE_ALLOWED; :#endif : : if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0) : { : if (status == TRANS_ADDR_IN_USE) : { : /* : * We failed to bind to the specified address because the : * address is in use. It must be that a server is already : * running at this address, and this function should fail. : */ : : PRMSG (1, : "MakeAllCOTSServerListeners: server already running\n", : 0, 0, 0); : : for (j = 0; j < *count_ret; j++) : TRANS(Close) (temp_ciptrs[j]); : : *count_ret = 0; : *ciptrs_ret = NULL; : *partial = 0; : return -1; : } : else : { : PRMSG (1, : "MakeAllCOTSServerListeners: failed to create listener for %s\n", : trans->TransName, 0, 0); : : continue; : } : } : :#if defined(IPv6) && defined(AF_INET6) : if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX) : ipv6_succ = 1; :#endif : : PRMSG (5, : "MakeAllCOTSServerListeners: opened listener for %s, %d\n", : trans->TransName, ciptr->fd, 0); : : temp_ciptrs[*count_ret] = ciptr; : (*count_ret)++; : } : : *partial = (*count_ret < complete_network_count()); : : PRMSG (5, : "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n", : *partial, *count_ret, complete_network_count()); : : if (*count_ret > 0) : { : if ((*ciptrs_ret = (XtransConnInfo *) xalloc ( : *count_ret * sizeof (XtransConnInfo))) == NULL) : { : return -1; : } : : for (i = 0; i < *count_ret; i++) : { : (*ciptrs_ret)[i] = temp_ciptrs[i]; : } : } : else : *ciptrs_ret = NULL; : : return 0; :} : :int :TRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret, : XtransConnInfo **ciptrs_ret) : :{ : char buffer[256]; /* ??? What size ?? */ : XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; : int status, i, j; : : PRMSG (2,"MakeAllCLTSServerListeners(%s,%p)\n", : port ? port : "NULL", ciptrs_ret, 0); : : *count_ret = 0; : : for (i = 0; i < NUMTRANS; i++) : { : Xtransport *trans = Xtransports[i].transport; : : if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN) : continue; : : snprintf(buffer, sizeof(buffer), "%s/:%s", : trans->TransName, port ? port : ""); : : PRMSG (5,"MakeAllCLTSServerListeners: opening %s\n", : buffer, 0, 0); : : if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL) : { : PRMSG (1, : "MakeAllCLTSServerListeners: failed to open listener for %s\n", : trans->TransName, 0, 0); : continue; : } : : if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0) : { : if (status == TRANS_ADDR_IN_USE) : { : /* : * We failed to bind to the specified address because the : * address is in use. It must be that a server is already : * running at this address, and this function should fail. : */ : : PRMSG (1, : "MakeAllCLTSServerListeners: server already running\n", : 0, 0, 0); : : for (j = 0; j < *count_ret; j++) : TRANS(Close) (temp_ciptrs[j]); : : *count_ret = 0; : *ciptrs_ret = NULL; : *partial = 0; : return -1; : } : else : { : PRMSG (1, : "MakeAllCLTSServerListeners: failed to create listener for %s\n", : trans->TransName, 0, 0); : : continue; : } : } : : PRMSG (5, : "MakeAllCLTSServerListeners: opened listener for %s, %d\n", : trans->TransName, ciptr->fd, 0); : temp_ciptrs[*count_ret] = ciptr; : (*count_ret)++; : } : : *partial = (*count_ret < complete_network_count()); : : PRMSG (5, : "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n", : *partial, *count_ret, complete_network_count()); : : if (*count_ret > 0) : { : if ((*ciptrs_ret = (XtransConnInfo *) xalloc ( : *count_ret * sizeof (XtransConnInfo))) == NULL) : { : return -1; : } : : for (i = 0; i < *count_ret; i++) : { : (*ciptrs_ret)[i] = temp_ciptrs[i]; : } : } : else : *ciptrs_ret = NULL; : : return 0; :} : :#endif /* TRANS_SERVER */ : : : :/* : * These routines are not part of the X Transport Interface, but they : * may be used by it. : */ : :#ifdef CRAY : :/* : * Cray UniCOS does not have readv and writev so we emulate : */ : :static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) : :{ : struct msghdr hdr; : : hdr.msg_iov = iov; : hdr.msg_iovlen = iovcnt; : hdr.msg_accrights = 0; : hdr.msg_accrightslen = 0; : hdr.msg_name = 0; : hdr.msg_namelen = 0; : : return (recvmsg (ciptr->fd, &hdr, 0)); :} : :static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) : :{ : struct msghdr hdr; : : hdr.msg_iov = iov; : hdr.msg_iovlen = iovcnt; : hdr.msg_accrights = 0; : hdr.msg_accrightslen = 0; : hdr.msg_name = 0; : hdr.msg_namelen = 0; : : return (sendmsg (ciptr->fd, &hdr, 0)); :} : :#endif /* CRAY */ : :#if (defined(SYSV) && defined(i386) && !defined(__SCO__) && !defined(sun)) || defined(WIN32) || defined(__sxg__) || defined(__UNIXOS2__) : :/* : * emulate readv : */ : :static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) : :{ : int i, len, total; : char *base; : : ESET(0); : for (i = 0, total = 0; i < iovcnt; i++, iov++) { : len = iov->iov_len; : base = iov->iov_base; : while (len > 0) { : register int nbytes; : nbytes = TRANS(Read) (ciptr, base, len); : if (nbytes < 0 && total == 0) return -1; : if (nbytes <= 0) return total; : ESET(0); : len -= nbytes; : total += nbytes; : base += nbytes; : } : } : return total; :} : :#endif /* SYSV && i386 || WIN32 || __sxg__ */ : :#if (defined(SYSV) && defined(i386) && !defined(__SCO__) && !defined(sun)) || defined(WIN32) || defined(__sxg__) || defined(__UNIXOS2__) : :/* : * emulate writev : */ : :static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) : :{ : int i, len, total; : char *base; : : ESET(0); : for (i = 0, total = 0; i < iovcnt; i++, iov++) { : len = iov->iov_len; : base = iov->iov_base; : while (len > 0) { : register int nbytes; : nbytes = TRANS(Write) (ciptr, base, len); : if (nbytes < 0 && total == 0) return -1; : if (nbytes <= 0) return total; : ESET(0); : len -= nbytes; : total += nbytes; : base += nbytes; : } : } : return total; :} : :#endif /* SYSV && i386 || WIN32 || __sxg__ */ : : :#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) || defined(__SCO__) :#ifndef NEED_UTSNAME :#define NEED_UTSNAME :#endif :#include :#endif : :/* : * TRANS(GetHostname) - similar to gethostname but allows special processing. : */ : :int TRANS(GetHostname) (char *buf, int maxlen) : :{ : int len; : :#ifdef NEED_UTSNAME : struct utsname name; : : uname (&name); : len = strlen (name.nodename); : if (len >= maxlen) len = maxlen - 1; : strncpy (buf, name.nodename, len); : buf[len] = '\0'; :#else : buf[0] = '\0'; : (void) gethostname (buf, maxlen); : buf [maxlen - 1] = '\0'; : len = strlen(buf); :#endif /* NEED_UTSNAME */ : return len; :}