1846 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1846 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  *
 | |
|  * 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 <dix-config.h>
 | |
| #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 "xace.h"
 | |
| #include "registry.h"
 | |
| 
 | |
| _X_EXPORT DevPrivateKey PictureScreenPrivateKey = &PictureScreenPrivateKey;
 | |
| DevPrivateKey	PictureWindowPrivateKey = &PictureWindowPrivateKey;
 | |
| static int	PictureGeneration;
 | |
| RESTYPE		PictureType;
 | |
| RESTYPE		PictFormatType;
 | |
| RESTYPE		GlyphSetType;
 | |
| int		PictureCmapPolicy = PictureCmapPolicyDefault;
 | |
| 
 | |
| 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);
 | |
|     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
 | |
| PictureInitIndexedFormat(ScreenPtr pScreen, PictFormatPtr format)
 | |
| {
 | |
|     PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
 | |
| 
 | |
|     if (format->type != PictTypeIndexed || format->index.pColormap)
 | |
| 	return TRUE;
 | |
| 
 | |
|     if (format->index.vid == pScreen->rootVisual) {
 | |
| 	format->index.pColormap =
 | |
| 	    (ColormapPtr) LookupIDByType(pScreen->defColormap, RT_COLORMAP);
 | |
|     } else {
 | |
| 	VisualPtr 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;
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static 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 (!PictureInitIndexedFormat(pScreen, format++))
 | |
| 	    return FALSE;
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| PictureFinishInit (void)
 | |
| {
 | |
|     int	    s;
 | |
| 
 | |
|     for (s = 0; s < screenInfo.numScreens; s++)
 | |
|     {
 | |
| 	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;
 | |
| 	PictureGeneration = serverGeneration;
 | |
| 	RegisterResourceName (PictureType, "PICTURE");
 | |
| 	RegisterResourceName (PictFormatType, "PICTFORMAT");
 | |
| 	RegisterResourceName (GlyphSetType, "GLYPHSET");
 | |
|     }
 | |
|     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);
 | |
| 
 | |
|     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)
 | |
| {
 | |
|     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;
 | |
|     pPicture->clipOrigin.y = 0;
 | |
|     pPicture->clientClip = 0;
 | |
| 
 | |
|     pPicture->transform = 0;
 | |
| 
 | |
|     pPicture->dither = None;
 | |
|     pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE);
 | |
|     pPicture->filter_params = 0;
 | |
|     pPicture->filter_nparams = 0;
 | |
| 
 | |
|     pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
 | |
|     pPicture->stateChanges = (1 << (CPLastBit+1)) - 1;
 | |
|     pPicture->pSourcePict = 0;
 | |
| }
 | |
| 
 | |
| PicturePtr
 | |
| CreatePicture (Picture		pid,
 | |
| 	       DrawablePtr	pDrawable,
 | |
| 	       PictFormatPtr	pFormat,
 | |
| 	       Mask		vmask,
 | |
| 	       XID		*vlist,
 | |
| 	       ClientPtr	client,
 | |
| 	       int		*error)
 | |
| {
 | |
|     PicturePtr		pPicture;
 | |
|     PictureScreenPtr	ps = GetPictureScreen(pDrawable->pScreen);
 | |
| 
 | |
|     pPicture = (PicturePtr)xalloc(sizeof(PictureRec));
 | |
|     if (!pPicture)
 | |
|     {
 | |
| 	*error = BadAlloc;
 | |
| 	return 0;
 | |
|     }
 | |
| 
 | |
|     pPicture->id = pid;
 | |
|     pPicture->pDrawable = pDrawable;
 | |
|     pPicture->pFormat = pFormat;
 | |
|     pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
 | |
|     pPicture->devPrivates = NULL;
 | |
| 
 | |
|     /* security creation/labeling check */
 | |
|     *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture,
 | |
| 		      RT_PIXMAP, pDrawable, DixCreateAccess|DixSetAttrAccess);
 | |
|     if (*error != Success)
 | |
| 	goto out;
 | |
| 
 | |
|     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)
 | |
| 	*error = (*ps->CreatePicture) (pPicture);
 | |
| out:
 | |
|     if (*error != Success)
 | |
|     {
 | |
| 	FreePicture (pPicture, (XID) 0);
 | |
| 	pPicture = 0;
 | |
|     }
 | |
|     return pPicture;
 | |
| }
 | |
| 
 | |
| 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)
 | |
| {
 | |
|     ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
 | |
|     PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
 | |
|     BITS32		index2;
 | |
|     int			error = 0;
 | |
|     BITS32		maskQ;
 | |
|     
 | |
|     pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
 | |
|     maskQ = vmask;
 | |
|     while (vmask && !error)
 | |
|     {
 | |
| 	index2 = (BITS32) lowbit (vmask);
 | |
| 	vmask &= ~index2;
 | |
| 	pPicture->stateChanges |= index2;
 | |
| 	switch (index2)
 | |
| 	{
 | |
| 	case CPRepeat:
 | |
| 	    {
 | |
| 		unsigned int	newr;
 | |
| 		newr = NEXT_VAL(unsigned int);
 | |
| 		if (newr <= RepeatReflect)
 | |
| 		{
 | |
| 		    pPicture->repeat = (newr != RepeatNone);
 | |
| 		    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
 | |
| 		    {
 | |
| 			error = dixLookupResource((pointer *)&pAlpha, pid,
 | |
| 						  PictureType, client,
 | |
| 						  DixReadAccess);
 | |
| 			if (error != Success)
 | |
| 			{
 | |
| 			    client->errorValue = pid;
 | |
| 			    error = (error == BadValue) ? BadPixmap : error;
 | |
| 			    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;
 | |
| 			error = dixLookupResource((pointer *)&pPixmap, pid,
 | |
| 						  RT_PIXMAP, client,
 | |
| 						  DixReadAccess);
 | |
| 			if (error != Success)
 | |
| 			{
 | |
| 			    client->errorValue = pid;
 | |
| 			    error = (error == BadValue) ? BadPixmap : error;
 | |
| 			    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;
 | |
| 
 | |
| 		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;
 | |
| }
 | |
| 
 | |
| 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)
 | |
| {
 | |
|     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;
 | |
| 
 | |
|     if (pPicture->pDrawable != NULL) {
 | |
| 	int result;
 | |
| 	PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
 | |
| 
 | |
| 	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)
 | |
| {
 | |
|     if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber)
 | |
|     {
 | |
| 	PictureScreenPtr    ps = GetPictureScreen(pPicture->pDrawable->pScreen);
 | |
| 
 | |
| 	(*ps->ValidatePicture) (pPicture, pPicture->stateChanges);
 | |
| 	pPicture->stateChanges = 0;
 | |
| 	pPicture->serialNumber = pPicture->pDrawable->serialNumber;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| ValidatePicture(PicturePtr pPicture)
 | |
| {
 | |
|     ValidateOnePicture (pPicture);
 | |
|     if (pPicture->alphaMap)
 | |
| 	ValidateOnePicture (pPicture->alphaMap);
 | |
| }
 | |
| 
 | |
| int
 | |
| FreePicture (pointer	value,
 | |
| 	     XID	pid)
 | |
| {
 | |
|     PicturePtr	pPicture = (PicturePtr) value;
 | |
| 
 | |
|     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;
 | |
|             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 *)dixLookupPrivateAddr
 | |
| 			 (&pWindow->devPrivates, PictureWindowPrivateKey);
 | |
|                      *pPrev;
 | |
|                      pPrev = &(*pPrev)->pNext)
 | |
|                 {
 | |
|                     if (*pPrev == pPicture)
 | |
|                     {
 | |
|                         *pPrev = pPicture->pNext;
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
 | |
|             {
 | |
|                 (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
 | |
|             }
 | |
|         }
 | |
| 	dixFreePrivates(pPicture->devPrivates);
 | |
| 	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 CARD8
 | |
| ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
 | |
| 		   INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height)
 | |
| {
 | |
|     Bool no_src_alpha, no_dst_alpha;
 | |
| 
 | |
|     /* Sampling off the edge of a RepeatNone picture introduces alpha
 | |
|      * even if the picture itself doesn't have alpha. We don't try to
 | |
|      * detect every case where we don't sample off the edge, just the
 | |
|      * simplest case where there is no transform on the source
 | |
|      * picture.
 | |
|      */
 | |
|     no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) &&
 | |
|                    PICT_FORMAT_A(pSrc->format) == 0 &&
 | |
|                    (pSrc->repeatType != RepeatNone ||
 | |
| 		    (!pSrc->transform &&
 | |
| 		     xSrc >= 0 && ySrc >= 0 &&
 | |
| 		     xSrc + width <= pSrc->pDrawable->width &&
 | |
| 		     ySrc + height <= pSrc->pDrawable->height)) &&
 | |
|                    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)
 | |
| {
 | |
|     PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
 | |
|     
 | |
|     ValidatePicture (pSrc);
 | |
|     if (pMask)
 | |
| 	ValidatePicture (pMask);
 | |
|     ValidatePicture (pDst);
 | |
| 
 | |
|     op = ReduceCompositeOp (op, pSrc, pMask, pDst, xSrc, ySrc, width, height);
 | |
|     if (op == PictOpDst)
 | |
| 	return;
 | |
| 
 | |
|     (*ps->Composite) (op,
 | |
| 		       pSrc,
 | |
| 		       pMask,
 | |
| 		       pDst,
 | |
| 		       xSrc,
 | |
| 		       ySrc,
 | |
| 		       xMask,
 | |
| 		       yMask,
 | |
| 		       xDst,
 | |
| 		       yDst,
 | |
| 		       width,
 | |
| 		       height);
 | |
| }
 | |
| 
 | |
| void
 | |
| CompositeRects (CARD8		op,
 | |
| 		PicturePtr	pDst,
 | |
| 		xRenderColor	*color,
 | |
| 		int		nRect,
 | |
| 		xRectangle      *rects)
 | |
| {
 | |
|     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;
 | |
| }
 |