/*
 * 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 (&region, pSrc, pMask, pDst,
				       xSrc, ySrc, xMask, yMask, xDst, yDst,
				       width, height))
	    return;

	xglAddSurfaceDamage (pDst->pDrawable, &region);
	REGION_UNINIT (pDst->pDrawable->pScreen, &region);
    } 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->repeatType]);
    }

    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->repeatType]);
	    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, &region, &box, 1);
	    xglAddSurfaceDamage (&pPixmap->drawable, &region);
	    REGION_UNINIT (pDrawable->pScreen, &region);

	    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
