788 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			788 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright © 2004 David Reveman
 | 
						|
 *
 | 
						|
 * 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
 | 
						|
 * David Reveman not be used in advertising or publicity pertaining to
 | 
						|
 * distribution of the software without specific, written prior permission.
 | 
						|
 * David Reveman makes no representations about the suitability of this
 | 
						|
 * software for any purpose. It is provided "as is" without express or
 | 
						|
 * implied warranty.
 | 
						|
 *
 | 
						|
 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
 | 
						|
 * NO EVENT SHALL DAVID REVEMAN 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: David Reveman <davidr@novell.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include "xgl.h"
 | 
						|
#include "fb.h"
 | 
						|
 | 
						|
#ifdef RENDER
 | 
						|
 | 
						|
#include "fbpict.h"
 | 
						|
 | 
						|
#define XGL_PICTURE_FALLBACK_PROLOGUE(pPicture, func) \
 | 
						|
    xglSyncDamageBoxBits (pPicture->pDrawable);	      \
 | 
						|
    XGL_PICTURE_SCREEN_UNWRAP (func)
 | 
						|
 | 
						|
#define XGL_PICTURE_FALLBACK_EPILOGUE(pPicture, func, xglfunc) \
 | 
						|
    XGL_PICTURE_SCREEN_WRAP (func, xglfunc);		       \
 | 
						|
    xglAddCurrentSurfaceDamage (pPicture->pDrawable)
 | 
						|
 | 
						|
void
 | 
						|
xglComposite (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 pPictureScreen;
 | 
						|
    ScreenPtr	     pScreen = pDst->pDrawable->pScreen;
 | 
						|
 | 
						|
    XGL_SCREEN_PRIV (pScreen);
 | 
						|
 | 
						|
    if (xglCompositeGeneral (op,
 | 
						|
			     pSrc, pMask, pDst, NULL,
 | 
						|
			     xSrc, ySrc,
 | 
						|
			     xMask, yMask,
 | 
						|
			     xDst + pDst->pDrawable->x,
 | 
						|
			     yDst + pDst->pDrawable->y,
 | 
						|
			     width, height))
 | 
						|
    {
 | 
						|
	xglAddCurrentBitDamage (pDst->pDrawable);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
 | 
						|
    pPictureScreen = GetPictureScreen (pScreen);
 | 
						|
 | 
						|
    if (pSrc->pDrawable)
 | 
						|
    {
 | 
						|
	if (!xglSyncBits (pSrc->pDrawable, NullBox))
 | 
						|
	    FatalError (XGL_SW_FAILURE_STRING);
 | 
						|
    }
 | 
						|
 | 
						|
    if (pMask && pMask->pDrawable)
 | 
						|
    {
 | 
						|
	if (!xglSyncBits (pMask->pDrawable, NullBox))
 | 
						|
	    FatalError (XGL_SW_FAILURE_STRING);
 | 
						|
    }
 | 
						|
 | 
						|
    if (op == PictOpSrc)
 | 
						|
    {
 | 
						|
	XGL_DRAWABLE_PIXMAP (pDst->pDrawable);
 | 
						|
 | 
						|
	if (!xglMapPixmapBits (pPixmap))
 | 
						|
	    FatalError (XGL_SW_FAILURE_STRING);
 | 
						|
    } else
 | 
						|
	xglSyncDamageBoxBits (pDst->pDrawable);
 | 
						|
 | 
						|
    XGL_PICTURE_SCREEN_UNWRAP (Composite);
 | 
						|
    (*pPictureScreen->Composite) (op, pSrc, pMask, pDst,
 | 
						|
				  xSrc, ySrc, xMask, yMask, xDst, yDst,
 | 
						|
				  width, height);
 | 
						|
    XGL_PICTURE_SCREEN_WRAP (Composite, xglComposite);
 | 
						|
 | 
						|
    if (op == PictOpSrc)
 | 
						|
    {
 | 
						|
	RegionRec region;
 | 
						|
 | 
						|
	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;
 | 
						|
 | 
						|
	xglAddSurfaceDamage (pDst->pDrawable, ®ion);
 | 
						|
	REGION_UNINIT (pDst->pDrawable->pScreen, ®ion);
 | 
						|
    } else
 | 
						|
	xglAddCurrentSurfaceDamage (pDst->pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xglAddTriangles (PicturePtr pDst,
 | 
						|
		 INT16	    xOff,
 | 
						|
		 INT16	    yOff,
 | 
						|
		 int	    ntri,
 | 
						|
		 xTriangle  *tris)
 | 
						|
{
 | 
						|
    PictureScreenPtr pPictureScreen;
 | 
						|
    ScreenPtr	     pScreen = pDst->pDrawable->pScreen;
 | 
						|
 | 
						|
    XGL_SCREEN_PRIV (pScreen);
 | 
						|
    XGL_DRAWABLE_PIXMAP_PRIV (pDst->pDrawable);
 | 
						|
 | 
						|
    pPictureScreen = GetPictureScreen (pScreen);
 | 
						|
 | 
						|
    pPixmapPriv->damageBox.x1 = 0;
 | 
						|
    pPixmapPriv->damageBox.y1 = 0;
 | 
						|
    pPixmapPriv->damageBox.x2 = pDst->pDrawable->width;
 | 
						|
    pPixmapPriv->damageBox.y2 = pDst->pDrawable->height;
 | 
						|
 | 
						|
    XGL_PICTURE_FALLBACK_PROLOGUE (pDst, AddTriangles);
 | 
						|
    (*pPictureScreen->AddTriangles) (pDst, xOff, yOff, ntri, tris);
 | 
						|
    XGL_PICTURE_FALLBACK_EPILOGUE (pDst, AddTriangles, xglAddTriangles);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
xglChangePicture (PicturePtr pPicture,
 | 
						|
		  Mask	     mask)
 | 
						|
{
 | 
						|
    PictureScreenPtr pPictureScreen;
 | 
						|
    ScreenPtr	     pScreen = pPicture->pDrawable->pScreen;
 | 
						|
 | 
						|
    XGL_SCREEN_PRIV (pScreen);
 | 
						|
    XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable);
 | 
						|
 | 
						|
    pPictureScreen = GetPictureScreen (pScreen);
 | 
						|
 | 
						|
    if (pPicture->stateChanges & CPRepeat)
 | 
						|
	pPixmapPriv->pictureMask |= xglPCFillMask;
 | 
						|
 | 
						|
    if (pPicture->stateChanges & CPComponentAlpha)
 | 
						|
	pPixmapPriv->pictureMask |= xglPCComponentAlphaMask;
 | 
						|
 | 
						|
    if (pPicture->stateChanges & CPDither)
 | 
						|
	pPixmapPriv->pictureMask |= xglPCDitherMask;
 | 
						|
 | 
						|
    XGL_PICTURE_SCREEN_UNWRAP (ChangePicture);
 | 
						|
    (*pPictureScreen->ChangePicture) (pPicture, mask);
 | 
						|
    XGL_PICTURE_SCREEN_WRAP (ChangePicture, xglChangePicture);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
xglChangePictureTransform (PicturePtr    pPicture,
 | 
						|
			   PictTransform *transform)
 | 
						|
{
 | 
						|
    PictureScreenPtr pPictureScreen;
 | 
						|
    ScreenPtr	     pScreen = pPicture->pDrawable->pScreen;
 | 
						|
    int		     ret;
 | 
						|
 | 
						|
    XGL_SCREEN_PRIV (pScreen);
 | 
						|
    XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable);
 | 
						|
 | 
						|
    pPictureScreen = GetPictureScreen (pScreen);
 | 
						|
 | 
						|
    if (transform != pPicture->transform ||
 | 
						|
	(transform && memcmp (transform, &pPicture->transform,
 | 
						|
			      sizeof (PictTransform))))
 | 
						|
	pPixmapPriv->pictureMask |= xglPCTransformMask;
 | 
						|
 | 
						|
    XGL_PICTURE_SCREEN_UNWRAP (ChangePictureTransform);
 | 
						|
    ret = (*pPictureScreen->ChangePictureTransform) (pPicture, transform);
 | 
						|
    XGL_PICTURE_SCREEN_WRAP (ChangePictureTransform,
 | 
						|
			     xglChangePictureTransform);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
xglChangePictureFilter (PicturePtr pPicture,
 | 
						|
			int	   filter,
 | 
						|
			xFixed	   *params,
 | 
						|
			int	   nparams)
 | 
						|
{
 | 
						|
    PictureScreenPtr pPictureScreen;
 | 
						|
    ScreenPtr	     pScreen = pPicture->pDrawable->pScreen;
 | 
						|
    int		     ret;
 | 
						|
 | 
						|
    XGL_SCREEN_PRIV (pScreen);
 | 
						|
    XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable);
 | 
						|
 | 
						|
    pPictureScreen = GetPictureScreen (pScreen);
 | 
						|
 | 
						|
    pPixmapPriv->pictureMask |= xglPCFilterMask;
 | 
						|
 | 
						|
    XGL_PICTURE_SCREEN_UNWRAP (ChangePictureFilter);
 | 
						|
    ret = (*pPictureScreen->ChangePictureFilter) (pPicture, filter,
 | 
						|
						  params, nparams);
 | 
						|
    XGL_PICTURE_SCREEN_WRAP (ChangePictureFilter, xglChangePictureFilter);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
xglDestroyDevicePicture (PicturePtr pPicture)
 | 
						|
{
 | 
						|
    if (pPicture->pSourcePict->source.devPrivate.ptr)
 | 
						|
	glitz_surface_destroy (pPicture->pSourcePict->source.devPrivate.ptr);
 | 
						|
}
 | 
						|
 | 
						|
PicturePtr
 | 
						|
xglCreateDevicePicture (pointer data)
 | 
						|
{
 | 
						|
    PicturePtr pPicture;
 | 
						|
    int	       error;
 | 
						|
 | 
						|
    pPicture = CreateDevicePicture (0, &error);
 | 
						|
    if (!pPicture)
 | 
						|
	return 0;
 | 
						|
 | 
						|
    pPicture->pSourcePict->source.devPrivate.ptr = data;
 | 
						|
    pPicture->pSourcePict->source.Destroy	 = xglDestroyDevicePicture;
 | 
						|
 | 
						|
    return pPicture;
 | 
						|
}
 | 
						|
 | 
						|
static int fillMode[] = {
 | 
						|
    GLITZ_FILL_TRANSPARENT, /* RepeatNone    */
 | 
						|
    GLITZ_FILL_REPEAT,      /* RepeatNormal  */
 | 
						|
    GLITZ_FILL_NEAREST,     /* RepeatPad     */
 | 
						|
    GLITZ_FILL_REFLECT      /* RepeatReflect */
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
xglUpdatePicture (PicturePtr pPicture)
 | 
						|
{
 | 
						|
    glitz_surface_t *surface;
 | 
						|
 | 
						|
    XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable);
 | 
						|
 | 
						|
    surface = pPixmapPriv->surface;
 | 
						|
 | 
						|
    if (pPixmapPriv->pictureMask & xglPCFillMask)
 | 
						|
    {
 | 
						|
	glitz_surface_set_fill (surface, fillMode[pPicture->repeat]);
 | 
						|
    }
 | 
						|
 | 
						|
    if (pPixmapPriv->pictureMask & xglPCFilterMask)
 | 
						|
    {
 | 
						|
	switch (pPicture->filter) {
 | 
						|
	case PictFilterNearest:
 | 
						|
	case PictFilterFast:
 | 
						|
	    glitz_surface_set_filter (surface, GLITZ_FILTER_NEAREST, NULL, 0);
 | 
						|
	    break;
 | 
						|
	case PictFilterGood:
 | 
						|
	case PictFilterBest:
 | 
						|
	case PictFilterBilinear:
 | 
						|
	    glitz_surface_set_filter (surface, GLITZ_FILTER_BILINEAR, NULL, 0);
 | 
						|
	    break;
 | 
						|
	case PictFilterConvolution:
 | 
						|
	    glitz_surface_set_filter (surface, GLITZ_FILTER_CONVOLUTION,
 | 
						|
				      (glitz_fixed16_16_t *)
 | 
						|
				      pPicture->filter_params,
 | 
						|
				      pPicture->filter_nparams);
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (pPixmapPriv->pictureMask & xglPCTransformMask)
 | 
						|
    {
 | 
						|
	glitz_surface_set_transform (surface, (glitz_transform_t *)
 | 
						|
				     pPicture->transform);
 | 
						|
    }
 | 
						|
 | 
						|
    if (pPixmapPriv->pictureMask & xglPCComponentAlphaMask)
 | 
						|
    {
 | 
						|
	glitz_surface_set_component_alpha (surface, pPicture->componentAlpha);
 | 
						|
    }
 | 
						|
 | 
						|
    if (pPixmapPriv->pictureMask & xglPCDitherMask)
 | 
						|
    {
 | 
						|
	glitz_surface_set_dither (surface, pPicture->dither);
 | 
						|
    }
 | 
						|
 | 
						|
    pPixmapPriv->pictureMask &= ~XGL_PICTURE_CHANGES (~0);
 | 
						|
}
 | 
						|
 | 
						|
#define N_STACK_PARAM 256
 | 
						|
 | 
						|
static int gradientNParam[] = {
 | 
						|
    0, /* SourcePictTypeSolidFill */
 | 
						|
    4, /* SourcePictTypeLinear    */
 | 
						|
    6, /* SourcePictTypeRadial    */
 | 
						|
    4, /* SourcePictTypeConical   */
 | 
						|
};
 | 
						|
 | 
						|
Bool
 | 
						|
xglSyncPicture (ScreenPtr  pScreen,
 | 
						|
		PicturePtr pPicture,
 | 
						|
		INT16	   x,
 | 
						|
		INT16	   y,
 | 
						|
		CARD16	   width,
 | 
						|
		CARD16	   height,
 | 
						|
		INT16	   *xOff,
 | 
						|
		INT16	   *yOff)
 | 
						|
{
 | 
						|
    xglPixmapPtr pPixmapPriv;
 | 
						|
 | 
						|
    XGL_SCREEN_PRIV (pScreen);
 | 
						|
 | 
						|
    *xOff = *yOff = 0;
 | 
						|
 | 
						|
    if (pPicture->pSourcePict)
 | 
						|
    {
 | 
						|
	if (pPicture->pSourcePict->source.devPrivate.ptr)
 | 
						|
	    return TRUE;
 | 
						|
 | 
						|
	if (pPicture->pDrawable)
 | 
						|
	{
 | 
						|
	    (*pScreen->DestroyPixmap) ((PixmapPtr) pPicture->pDrawable);
 | 
						|
	    pPicture->pDrawable = (DrawablePtr) 0;
 | 
						|
	}
 | 
						|
 | 
						|
	switch (pPicture->pSourcePict->source.type) {
 | 
						|
	case SourcePictTypeSolidFill:
 | 
						|
	    x = y = 0;
 | 
						|
	    width = height = 1;
 | 
						|
	    break;
 | 
						|
	case SourcePictTypeLinear:
 | 
						|
	case SourcePictTypeRadial: {
 | 
						|
	    glitz_fixed16_16_t		stackParam[N_STACK_PARAM];
 | 
						|
	    glitz_fixed16_16_t		*param;
 | 
						|
	    int				nParam, nStop, size, i;
 | 
						|
	    CARD32			*pixel;
 | 
						|
	    PictGradientStopPtr		pStop;
 | 
						|
	    glitz_buffer_t		*buffer;
 | 
						|
	    glitz_format_t		*format;
 | 
						|
	    glitz_surface_t		*surface;
 | 
						|
	    static glitz_pixel_format_t pixelFormat = {
 | 
						|
		GLITZ_FOURCC_RGB,
 | 
						|
		{
 | 
						|
		    32,
 | 
						|
		    0xff000000,
 | 
						|
		    0x00ff0000,
 | 
						|
		    0x0000ff00,
 | 
						|
		    0x000000ff
 | 
						|
		},
 | 
						|
		0, 0, 0,
 | 
						|
		GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
 | 
						|
	    };
 | 
						|
 | 
						|
	    if (!(pScreenPriv->features & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK))
 | 
						|
		break;
 | 
						|
 | 
						|
	    format = glitz_find_standard_format (pScreenPriv->drawable,
 | 
						|
						 GLITZ_STANDARD_ARGB32);
 | 
						|
	    if (!format)
 | 
						|
		break;
 | 
						|
 | 
						|
	    nParam = gradientNParam[pPicture->pSourcePict->gradient.type];
 | 
						|
	    pStop  = pPicture->pSourcePict->gradient.stops;
 | 
						|
	    nStop  = pPicture->pSourcePict->gradient.nstops;
 | 
						|
 | 
						|
	    size = nParam + nStop * 4;
 | 
						|
	    if (size > N_STACK_PARAM)
 | 
						|
	    {
 | 
						|
		param = malloc (sizeof (xFixed) * size);
 | 
						|
		if (!param)
 | 
						|
		    break;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		param = stackParam;
 | 
						|
	    }
 | 
						|
 | 
						|
	    pixel = (CARD32 *) (param + nParam + nStop * 3);
 | 
						|
 | 
						|
	    buffer = glitz_buffer_create_for_data (pixel);
 | 
						|
	    if (!buffer)
 | 
						|
	    {
 | 
						|
		if (size > N_STACK_PARAM)
 | 
						|
		    free (param);
 | 
						|
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
 | 
						|
	    surface = glitz_surface_create (pScreenPriv->drawable,
 | 
						|
					    format, nStop, 1, 0, NULL);
 | 
						|
	    if (!surface)
 | 
						|
	    {
 | 
						|
		glitz_buffer_destroy (buffer);
 | 
						|
		if (size > N_STACK_PARAM)
 | 
						|
		    free (param);
 | 
						|
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
 | 
						|
	    for (i = 0; i < nStop; i++)
 | 
						|
	    {
 | 
						|
		pixel[i] = pStop[i].color;
 | 
						|
 | 
						|
		param[nParam + 3 * i + 0] = pStop[i].x;
 | 
						|
		param[nParam + 3 * i + 1] = i << 16;
 | 
						|
		param[nParam + 3 * i + 2] = 0;
 | 
						|
	    }
 | 
						|
 | 
						|
	    glitz_set_pixels (surface, 0, 0, nStop, 1, &pixelFormat, buffer);
 | 
						|
 | 
						|
	    glitz_buffer_destroy (buffer);
 | 
						|
 | 
						|
	    switch (pPicture->pSourcePict->source.type) {
 | 
						|
	    case SourcePictTypeLinear:
 | 
						|
		param[0] = pPicture->pSourcePict->linear.p1.x;
 | 
						|
		param[1] = pPicture->pSourcePict->linear.p1.y;
 | 
						|
		param[2] = pPicture->pSourcePict->linear.p2.x;
 | 
						|
		param[3] = pPicture->pSourcePict->linear.p2.y;
 | 
						|
 | 
						|
		glitz_surface_set_filter (surface,
 | 
						|
					  GLITZ_FILTER_LINEAR_GRADIENT,
 | 
						|
					  param, nParam + nStop * 3);
 | 
						|
		break;
 | 
						|
	    case SourcePictTypeRadial:
 | 
						|
		param[0] = pPicture->pSourcePict->radial.inner.x;
 | 
						|
		param[1] = pPicture->pSourcePict->radial.inner.y;
 | 
						|
		param[2] = pPicture->pSourcePict->radial.inner_radius;
 | 
						|
		param[3] = pPicture->pSourcePict->radial.outer.x;
 | 
						|
		param[4] = pPicture->pSourcePict->radial.outer.y;
 | 
						|
		param[5] = pPicture->pSourcePict->radial.outer_radius;
 | 
						|
 | 
						|
		glitz_surface_set_filter (surface,
 | 
						|
					  GLITZ_FILTER_RADIAL_GRADIENT,
 | 
						|
					  param, nParam + nStop * 3);
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
 | 
						|
	    glitz_surface_set_fill (surface, fillMode[pPicture->repeat]);
 | 
						|
	    glitz_surface_set_transform (surface, (glitz_transform_t *)
 | 
						|
					 pPicture->transform);
 | 
						|
 | 
						|
	    pPicture->pSourcePict->gradient.devPrivate.ptr = surface;
 | 
						|
	    pPicture->pSourcePict->gradient.Destroy = xglDestroyDevicePicture;
 | 
						|
 | 
						|
	    if (size > N_STACK_PARAM)
 | 
						|
		free (param);
 | 
						|
 | 
						|
	    return TRUE;
 | 
						|
	} break;
 | 
						|
	case SourcePictTypeConical:
 | 
						|
	default:
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pPicture->pDrawable)
 | 
						|
	{
 | 
						|
	    PictFormatPtr pFormat;
 | 
						|
	    PixmapPtr	  pPixmap;
 | 
						|
	    PicturePtr	  pTmp;
 | 
						|
	    RegionRec	  region;
 | 
						|
	    BoxRec	  box;
 | 
						|
	    int		  error;
 | 
						|
 | 
						|
	    pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
 | 
						|
	    if (!pFormat)
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
 | 
						|
						pFormat->depth);
 | 
						|
	    if (!pPixmap)
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	    pTmp = CreatePicture (0, &pPixmap->drawable, pFormat, 0, NULL,
 | 
						|
				  serverClient, &error);
 | 
						|
	    if (!pTmp)
 | 
						|
	    {
 | 
						|
		(*pScreen->DestroyPixmap) (pPixmap);
 | 
						|
		return FALSE;
 | 
						|
	    }
 | 
						|
 | 
						|
	    ValidatePicture (pTmp);
 | 
						|
 | 
						|
	    if (!xglSyncBits (pTmp->pDrawable, NullBox))
 | 
						|
		FatalError (XGL_SW_FAILURE_STRING);
 | 
						|
 | 
						|
	    fbCompositeGeneral (PictOpSrc,
 | 
						|
				pPicture, 0, pTmp,
 | 
						|
				x, y, 0, 0, 0, 0,
 | 
						|
				width, height);
 | 
						|
 | 
						|
	    FreePicture ((pointer) pTmp, (XID) 0);
 | 
						|
 | 
						|
	    box.x1 = 0;
 | 
						|
	    box.y1 = 0;
 | 
						|
	    box.x2 = width;
 | 
						|
	    box.y2 = height;
 | 
						|
 | 
						|
	    REGION_INIT (pScreen, ®ion, &box, 1);
 | 
						|
	    xglAddSurfaceDamage (&pPixmap->drawable, ®ion);
 | 
						|
	    REGION_UNINIT (pDrawable->pScreen, ®ion);
 | 
						|
 | 
						|
	    pPicture->pDrawable = &pPixmap->drawable;
 | 
						|
 | 
						|
	    *xOff = x;
 | 
						|
	    *yOff = y;
 | 
						|
 | 
						|
	    XGL_GET_PIXMAP_PRIV (pPixmap)->pictureMask &=
 | 
						|
		~(xglPCFillMask | xglPCFilterMask | xglPCTransformMask);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef XV
 | 
						|
    switch (pPicture->format) {
 | 
						|
    case PICT_yuy2:
 | 
						|
	xglSetPixmapVisual ((PixmapPtr) pPicture->pDrawable,
 | 
						|
			    &pScreenPriv->pXvVisual[XGL_XV_FORMAT_YUY2]);
 | 
						|
	break;
 | 
						|
    case PICT_yv12:
 | 
						|
	xglSetPixmapVisual ((PixmapPtr) pPicture->pDrawable,
 | 
						|
			    &pScreenPriv->pXvVisual[XGL_XV_FORMAT_YV12]);
 | 
						|
    default:
 | 
						|
	break;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    if (!xglSyncSurface (pPicture->pDrawable))
 | 
						|
	return FALSE;
 | 
						|
 | 
						|
    pPixmapPriv = XGL_GET_PIXMAP_PRIV ((PixmapPtr) pPicture->pDrawable);
 | 
						|
    if (XGL_PICTURE_CHANGES (pPixmapPriv->pictureMask))
 | 
						|
	xglUpdatePicture (pPicture);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
xglVisualDepth (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;
 | 
						|
}
 | 
						|
 | 
						|
typedef struct _xglformatInit {
 | 
						|
    CARD32 format;
 | 
						|
    CARD8  depth;
 | 
						|
} xglFormatInitRec, *xglFormatInitPtr;
 | 
						|
 | 
						|
static int
 | 
						|
xglAddFormat (xglFormatInitPtr formats,
 | 
						|
	      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))
 | 
						|
 | 
						|
Bool
 | 
						|
xglPictureInit (ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    int		     f, nformats = 0;
 | 
						|
    PictFormatPtr    pFormats;
 | 
						|
    xglFormatInitRec formats[64];
 | 
						|
    CARD32	     format;
 | 
						|
    CARD8	     depth;
 | 
						|
    VisualPtr	     pVisual;
 | 
						|
    int		     v;
 | 
						|
    int		     bpp;
 | 
						|
    int		     r, g, b;
 | 
						|
    int		     d;
 | 
						|
    DepthPtr	     pDepth;
 | 
						|
 | 
						|
    /* formats required by protocol */
 | 
						|
    formats[nformats].format = PICT_a1;
 | 
						|
    formats[nformats].depth = 1;
 | 
						|
    nformats++;
 | 
						|
    formats[nformats].format = PICT_a4;
 | 
						|
    formats[nformats].depth = 4;
 | 
						|
    nformats++;
 | 
						|
    formats[nformats].format = PICT_a8;
 | 
						|
    formats[nformats].depth = 8;
 | 
						|
    nformats++;
 | 
						|
    formats[nformats].format = PICT_a8r8g8b8;
 | 
						|
    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 = xglVisualDepth (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);
 | 
						|
	    if (pVisual->offsetBlue == 0 &&
 | 
						|
		pVisual->offsetGreen == b &&
 | 
						|
		pVisual->offsetRed == b + g)
 | 
						|
	    {
 | 
						|
		format = PICT_FORMAT (bpp, PICT_TYPE_ARGB, 0, r, g, b);
 | 
						|
		nformats = xglAddFormat (formats, nformats, format, depth);
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	case StaticColor:
 | 
						|
	case PseudoColor:
 | 
						|
	case StaticGray:
 | 
						|
	case GrayScale:
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /* walk supported depths and add missing Direct formats */
 | 
						|
    for (d = 0; d < pScreen->numDepths; d++)
 | 
						|
    {
 | 
						|
	pDepth = &pScreen->allowedDepths[d];
 | 
						|
	bpp = BitsPerPixel (pDepth->depth);
 | 
						|
	format = 0;
 | 
						|
	switch (bpp) {
 | 
						|
	case 16:
 | 
						|
	    if (pDepth->depth == 15)
 | 
						|
		nformats = xglAddFormat (formats, nformats,
 | 
						|
					 PICT_x1r5g5b5, pDepth->depth);
 | 
						|
	    if (pDepth->depth == 16)
 | 
						|
		nformats = xglAddFormat (formats, nformats,
 | 
						|
					 PICT_r5g6b5, pDepth->depth);
 | 
						|
	    break;
 | 
						|
	case 24:
 | 
						|
	    if (pDepth->depth == 24)
 | 
						|
		nformats = xglAddFormat (formats, nformats,
 | 
						|
					 PICT_r8g8b8, pDepth->depth);
 | 
						|
	    break;
 | 
						|
	case 32:
 | 
						|
	    if (pDepth->depth == 24)
 | 
						|
		nformats = xglAddFormat (formats, nformats,
 | 
						|
					 PICT_x8r8g8b8, pDepth->depth);
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /* add YUV formats */
 | 
						|
    nformats = xglAddFormat (formats, nformats, PICT_yuy2, 16);
 | 
						|
    nformats = xglAddFormat (formats, nformats, PICT_yv12, 12);
 | 
						|
 | 
						|
    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_A:
 | 
						|
	    pFormats[f].type = PictTypeDirect;
 | 
						|
	    pFormats[f].direct.alpha = 0;
 | 
						|
	    pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A (format));
 | 
						|
	    break;
 | 
						|
	case PICT_TYPE_COLOR:
 | 
						|
	case PICT_TYPE_GRAY:
 | 
						|
	    pFormats[f].type = PictTypeDirect;
 | 
						|
	    break;
 | 
						|
	case PICT_TYPE_YUY2:
 | 
						|
	case PICT_TYPE_YV12:
 | 
						|
	    pFormats[f].type = PictTypeOther;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (!fbPictureInit (pScreen, pFormats, nformats))
 | 
						|
	return FALSE;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xglPictureClipExtents (PicturePtr pPicture,
 | 
						|
		       BoxPtr     extents)
 | 
						|
{
 | 
						|
    if (pPicture->clientClipType != CT_NONE)
 | 
						|
    {
 | 
						|
	BoxPtr clip = REGION_EXTENTS (pPicture->pDrawable->pScreen,
 | 
						|
				      (RegionPtr) pPicture->clientClip);
 | 
						|
 | 
						|
	if (extents->x1 < pPicture->clipOrigin.x + clip->x1)
 | 
						|
	    extents->x1 = pPicture->clipOrigin.x + clip->x1;
 | 
						|
 | 
						|
	if (extents->y1 < pPicture->clipOrigin.y + clip->y1)
 | 
						|
	    extents->y1 = pPicture->clipOrigin.y + clip->y1;
 | 
						|
 | 
						|
	if (extents->x2 > pPicture->clipOrigin.x + clip->x2)
 | 
						|
	    extents->x2 = pPicture->clipOrigin.x + clip->x2;
 | 
						|
 | 
						|
	if (extents->y2 > pPicture->clipOrigin.y + clip->y2)
 | 
						|
	    extents->y2 = pPicture->clipOrigin.y + clip->y2;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	if (extents->x1 < 0)
 | 
						|
	    extents->x1 = 0;
 | 
						|
 | 
						|
	if (extents->y1 < 0)
 | 
						|
	    extents->y1 = 0;
 | 
						|
 | 
						|
	if (extents->x2 > pPicture->pDrawable->width)
 | 
						|
	    extents->x2 = pPicture->pDrawable->width;
 | 
						|
 | 
						|
	if (extents->y2 > pPicture->pDrawable->height)
 | 
						|
	    extents->y2 = pPicture->pDrawable->height;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |