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
 |