528 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			528 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright © 2006 Keith Packard
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that copyright
 | |
|  * notice and this permission notice appear in supporting documentation, and
 | |
|  * that the name of the copyright holders not be used in advertising or
 | |
|  * publicity pertaining to distribution of the software without specific,
 | |
|  * written prior permission.  The copyright holders make no representations
 | |
|  * about the suitability of this software for any purpose.  It is provided "as
 | |
|  * is" without express or implied warranty.
 | |
|  *
 | |
|  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | |
|  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | |
|  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | |
|  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | |
|  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | |
|  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 | |
|  * OF THIS SOFTWARE.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_XORG_CONFIG_H
 | |
| #include <xorg-config.h>
 | |
| #else
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include <config.h>
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #include <stddef.h>
 | |
| #include <string.h>
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include "xf86.h"
 | |
| #include "xf86DDC.h"
 | |
| #include "fb.h"
 | |
| #include "windowstr.h"
 | |
| #include "xf86Crtc.h"
 | |
| #include "xf86Modes.h"
 | |
| #include "xf86RandR12.h"
 | |
| #include "X11/extensions/render.h"
 | |
| #include "X11/extensions/dpmsconst.h"
 | |
| #include "X11/Xatom.h"
 | |
| 
 | |
| /* borrowed from composite extension, move to Render and publish? */
 | |
| 
 | |
| static VisualPtr
 | |
| compGetWindowVisual (WindowPtr pWin)
 | |
| {
 | |
|     ScreenPtr	    pScreen = pWin->drawable.pScreen;
 | |
|     VisualID	    vid = wVisual (pWin);
 | |
|     int		    i;
 | |
| 
 | |
|     for (i = 0; i < pScreen->numVisuals; i++)
 | |
| 	if (pScreen->visuals[i].vid == vid)
 | |
| 	    return &pScreen->visuals[i];
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static PictFormatPtr
 | |
| compWindowFormat (WindowPtr pWin)
 | |
| {
 | |
|     ScreenPtr	pScreen = pWin->drawable.pScreen;
 | |
|     
 | |
|     return PictureMatchVisual (pScreen, pWin->drawable.depth,
 | |
| 			       compGetWindowVisual (pWin));
 | |
| }
 | |
| 
 | |
| #define F(x)	IntToxFixed(x)
 | |
| 
 | |
| #define toF(x)	((float) (x) / 65536.0f)
 | |
| 
 | |
| static void
 | |
| xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 | |
| {
 | |
|     ScrnInfoPtr		scrn = crtc->scrn;
 | |
|     ScreenPtr		screen = scrn->pScreen;
 | |
|     WindowPtr		root = WindowTable[screen->myNum];
 | |
|     PixmapPtr		dst_pixmap = crtc->rotatedPixmap;
 | |
|     PictFormatPtr	format = compWindowFormat (WindowTable[screen->myNum]);
 | |
|     int			error;
 | |
|     PicturePtr		src, dst;
 | |
|     int			n = REGION_NUM_RECTS(region);
 | |
|     BoxPtr		b = REGION_RECTS(region);
 | |
|     XID			include_inferiors = IncludeInferiors;
 | |
|     
 | |
|     src = CreatePicture (None,
 | |
| 			 &root->drawable,
 | |
| 			 format,
 | |
| 			 CPSubwindowMode,
 | |
| 			 &include_inferiors,
 | |
| 			 serverClient,
 | |
| 			 &error);
 | |
|     if (!src)
 | |
| 	return;
 | |
| 
 | |
|     dst = CreatePicture (None,
 | |
| 			 &dst_pixmap->drawable,
 | |
| 			 format,
 | |
| 			 0L,
 | |
| 			 NULL,
 | |
| 			 serverClient,
 | |
| 			 &error);
 | |
|     if (!dst)
 | |
| 	return;
 | |
| 
 | |
|     error = SetPictureTransform (src, &crtc->crtc_to_framebuffer);
 | |
|     if (error)
 | |
| 	return;
 | |
|     if (crtc->transform_in_use && crtc->filter)
 | |
| 	SetPicturePictFilter (src, crtc->filter,
 | |
| 			      crtc->params, crtc->nparams);
 | |
| 
 | |
|     if (crtc->shadowClear)
 | |
|     {
 | |
| 	CompositePicture (PictOpSrc,
 | |
| 			  src, NULL, dst,
 | |
| 			  0, 0, 0, 0, 0, 0,
 | |
| 			  crtc->mode.HDisplay, crtc->mode.VDisplay);
 | |
| 	crtc->shadowClear = FALSE;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    BoxRec	dst_box;
 | |
| 
 | |
| 	    dst_box = *b;
 | |
| 	    dst_box.x1 -= crtc->filter_width >> 1;
 | |
| 	    dst_box.x2 += crtc->filter_width >> 1;
 | |
| 	    dst_box.y1 -= crtc->filter_height >> 1;
 | |
| 	    dst_box.y2 += crtc->filter_height >> 1;
 | |
| 	    pixman_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box);
 | |
| 	    CompositePicture (PictOpSrc,
 | |
| 			      src, NULL, dst,
 | |
| 			      dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
 | |
| 			      dst_box.x2 - dst_box.x1,
 | |
| 			      dst_box.y2 - dst_box.y1);
 | |
| 	    b++;
 | |
| 	}
 | |
|     }
 | |
|     FreePicture (src, None);
 | |
|     FreePicture (dst, None);
 | |
| }
 | |
| 
 | |
| static void
 | |
| xf86CrtcDamageShadow (xf86CrtcPtr crtc)
 | |
| {
 | |
|     ScrnInfoPtr	pScrn = crtc->scrn;
 | |
|     BoxRec	damage_box;
 | |
|     RegionRec   damage_region;
 | |
|     ScreenPtr	pScreen = pScrn->pScreen;
 | |
| 
 | |
|     damage_box.x1 = 0;
 | |
|     damage_box.x2 = crtc->mode.HDisplay;
 | |
|     damage_box.y1 = 0;
 | |
|     damage_box.y2 = crtc->mode.VDisplay;
 | |
|     if (!pixman_transform_bounds (&crtc->crtc_to_framebuffer, &damage_box))
 | |
|     {
 | |
| 	damage_box.x1 = 0;
 | |
| 	damage_box.y1 = 0;
 | |
| 	damage_box.x2 = pScreen->width;
 | |
| 	damage_box.y2 = pScreen->height;
 | |
|     }
 | |
|     if (damage_box.x1 < 0) damage_box.x1 = 0;
 | |
|     if (damage_box.y1 < 0) damage_box.y1 = 0;
 | |
|     if (damage_box.x2 > pScreen->width) damage_box.x2 = pScreen->width;
 | |
|     if (damage_box.y2 > pScreen->height) damage_box.y2 = pScreen->height;
 | |
|     REGION_INIT (pScreen, &damage_region, &damage_box, 1);
 | |
|     DamageRegionAppend (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
 | |
| 			&damage_region);
 | |
|     REGION_UNINIT (pScreen, &damage_region);
 | |
|     crtc->shadowClear = TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| xf86RotatePrepare (ScreenPtr pScreen)
 | |
| {
 | |
|     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
 | |
|     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 | |
|     int			c;
 | |
| 
 | |
|     for (c = 0; c < xf86_config->num_crtc; c++)
 | |
|     {
 | |
| 	xf86CrtcPtr crtc = xf86_config->crtc[c];
 | |
| 	
 | |
| 	if (crtc->rotatedData && !crtc->rotatedPixmap)
 | |
| 	{
 | |
| 	    crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
 | |
| 							     crtc->rotatedData,
 | |
| 							     crtc->mode.HDisplay,
 | |
| 							     crtc->mode.VDisplay);
 | |
| 	    if (!xf86_config->rotation_damage_registered)
 | |
| 	    {
 | |
| 		/* Hook damage to screen pixmap */
 | |
| 		DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
 | |
| 				xf86_config->rotation_damage);
 | |
| 		xf86_config->rotation_damage_registered = TRUE;
 | |
| 		EnableLimitedSchedulingLatency();
 | |
| 	    }
 | |
| 	    
 | |
| 	    xf86CrtcDamageShadow (crtc);
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| xf86RotateRedisplay(ScreenPtr pScreen)
 | |
| {
 | |
|     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
 | |
|     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 | |
|     DamagePtr		damage = xf86_config->rotation_damage;
 | |
|     RegionPtr		region;
 | |
| 
 | |
|     if (!damage)
 | |
| 	return FALSE;
 | |
|     xf86RotatePrepare (pScreen);
 | |
|     region = DamageRegion(damage);
 | |
|     if (REGION_NOTEMPTY(pScreen, region)) 
 | |
|     {
 | |
| 	int			c;
 | |
| 	SourceValidateProcPtr	SourceValidate;
 | |
| 
 | |
| 	/*
 | |
| 	 * SourceValidate is used by the software cursor code
 | |
| 	 * to pull the cursor off of the screen when reading
 | |
| 	 * bits from the frame buffer. Bypassing this function
 | |
| 	 * leaves the software cursor in place
 | |
| 	 */
 | |
| 	SourceValidate = pScreen->SourceValidate;
 | |
| 	pScreen->SourceValidate = NULL;
 | |
| 
 | |
| 	for (c = 0; c < xf86_config->num_crtc; c++)
 | |
| 	{
 | |
| 	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];
 | |
| 
 | |
| 	    if (crtc->transform_in_use && crtc->enabled)
 | |
| 	    {
 | |
| 		RegionRec   crtc_damage;
 | |
| 
 | |
| 		/* compute portion of damage that overlaps crtc */
 | |
| 		REGION_INIT(pScreen, &crtc_damage, &crtc->bounds, 1);
 | |
| 		REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
 | |
| 		
 | |
| 		/* update damaged region */
 | |
| 		if (REGION_NOTEMPTY(pScreen, &crtc_damage))
 | |
|     		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
 | |
| 		
 | |
| 		REGION_UNINIT (pScreen, &crtc_damage);
 | |
| 	    }
 | |
| 	}
 | |
| 	pScreen->SourceValidate = SourceValidate;
 | |
| 	DamageEmpty(damage);
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| xf86RotateBlockHandler(int screenNum, pointer blockData,
 | |
| 		       pointer pTimeout, pointer pReadmask)
 | |
| {
 | |
|     ScreenPtr		pScreen = screenInfo.screens[screenNum];
 | |
|     ScrnInfoPtr		pScrn = xf86Screens[screenNum];
 | |
|     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 | |
|     Bool		rotation_active;
 | |
| 
 | |
|     rotation_active = xf86RotateRedisplay(pScreen);
 | |
|     pScreen->BlockHandler = xf86_config->BlockHandler;
 | |
|     (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
 | |
|     /* cannot avoid re-wrapping until all wrapping is audited */
 | |
|     xf86_config->BlockHandler = pScreen->BlockHandler;
 | |
|     pScreen->BlockHandler = xf86RotateBlockHandler;
 | |
| }
 | |
| 
 | |
| void
 | |
| xf86RotateDestroy (xf86CrtcPtr crtc)
 | |
| {
 | |
|     ScrnInfoPtr		pScrn = crtc->scrn;
 | |
|     ScreenPtr		pScreen = pScrn->pScreen;
 | |
|     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 | |
|     int			c;
 | |
|     
 | |
|     /* Free memory from rotation */
 | |
|     if (crtc->rotatedPixmap || crtc->rotatedData)
 | |
|     {
 | |
| 	crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData);
 | |
| 	crtc->rotatedPixmap = NULL;
 | |
| 	crtc->rotatedData = NULL;
 | |
|     }
 | |
| 
 | |
|     for (c = 0; c < xf86_config->num_crtc; c++)
 | |
| 	if (xf86_config->crtc[c]->transform_in_use)
 | |
| 	    return;
 | |
| 
 | |
|     /*
 | |
|      * Clean up damage structures when no crtcs are rotated
 | |
|      */
 | |
|     if (xf86_config->rotation_damage)
 | |
|     {
 | |
| 	/* Free damage structure */
 | |
| 	if (xf86_config->rotation_damage_registered)
 | |
| 	{
 | |
| 	    DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
 | |
| 			      xf86_config->rotation_damage);
 | |
| 	    xf86_config->rotation_damage_registered = FALSE;
 | |
| 	    DisableLimitedSchedulingLatency();
 | |
| 	}
 | |
| 	DamageDestroy (xf86_config->rotation_damage);
 | |
| 	xf86_config->rotation_damage = NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| xf86RotateFreeShadow(ScrnInfoPtr pScrn)
 | |
| {
 | |
|     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
 | |
|     int c;
 | |
| 
 | |
|    for (c = 0; c < config->num_crtc; c++) {
 | |
|        xf86CrtcPtr crtc = config->crtc[c];
 | |
| 
 | |
|        if (crtc->rotatedPixmap || crtc->rotatedData) {
 | |
| 	   crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
 | |
| 				crtc->rotatedData);
 | |
| 	   crtc->rotatedPixmap = NULL;
 | |
| 	   crtc->rotatedData = NULL;
 | |
|        }
 | |
|    }
 | |
| }
 | |
| 
 | |
| void
 | |
| xf86RotateCloseScreen (ScreenPtr screen)
 | |
| {
 | |
|     ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
 | |
|     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
 | |
|     int			c;
 | |
| 
 | |
|     for (c = 0; c < xf86_config->num_crtc; c++)
 | |
| 	xf86RotateDestroy (xf86_config->crtc[c]);
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb)
 | |
| {
 | |
|     ScrnInfoPtr		pScrn = crtc->scrn;
 | |
|     BoxRec		b;
 | |
| 
 | |
|     /* When called before PreInit, the driver is
 | |
|      * presumably doing load detect
 | |
|      */
 | |
|     if (pScrn->virtualX == 0 || pScrn->virtualY == 0)
 | |
| 	return TRUE;
 | |
| 
 | |
|     b.x1 = 0;
 | |
|     b.y1 = 0;
 | |
|     b.x2 = crtc->mode.HDisplay;
 | |
|     b.y2 = crtc->mode.VDisplay;
 | |
|     if (crtc_to_fb)
 | |
| 	pixman_f_transform_bounds (crtc_to_fb, &b);
 | |
|     else {
 | |
| 	b.x1 += crtc->x;
 | |
| 	b.y1 += crtc->y;
 | |
| 	b.x2 += crtc->x;
 | |
| 	b.y2 += crtc->y;
 | |
|     }
 | |
| 
 | |
|     return (0 <= b.x1 && b.x2 <= pScrn->virtualX &&
 | |
| 	    0 <= b.y1 && b.y2 <= pScrn->virtualY);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| xf86CrtcRotate (xf86CrtcPtr crtc)
 | |
| {
 | |
|     ScrnInfoPtr		pScrn = crtc->scrn;
 | |
|     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 | |
|     /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
 | |
|     ScreenPtr		pScreen = screenInfo.screens[pScrn->scrnIndex];
 | |
|     PictTransform	crtc_to_fb;
 | |
|     struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
 | |
|     xFixed		*new_params = NULL;
 | |
|     int			new_nparams = 0;
 | |
|     PictFilterPtr	new_filter = NULL;
 | |
|     int			new_width = 0;
 | |
|     int			new_height = 0;
 | |
|     RRTransformPtr	transform = NULL;
 | |
|     Bool		damage = FALSE;
 | |
| 
 | |
|     if (crtc->transformPresent)
 | |
| 	transform = &crtc->transform;
 | |
| 
 | |
|     if (!RRTransformCompute (crtc->x, crtc->y,
 | |
| 			     crtc->mode.HDisplay, crtc->mode.VDisplay,
 | |
| 			     crtc->rotation,
 | |
| 			     transform,
 | |
| 
 | |
| 			     &crtc_to_fb,
 | |
| 			     &f_crtc_to_fb,
 | |
| 			     &f_fb_to_crtc) &&
 | |
| 	xf86CrtcFitsScreen (crtc, &f_crtc_to_fb))
 | |
|     {
 | |
| 	/*
 | |
| 	 * If the untranslated transformation is the identity,
 | |
| 	 * disable the shadow buffer
 | |
| 	 */
 | |
| 	xf86RotateDestroy (crtc);
 | |
| 	crtc->transform_in_use = FALSE;
 | |
| 	if (new_params)
 | |
| 	    xfree (new_params);
 | |
| 	new_params = NULL;
 | |
| 	new_nparams = 0;
 | |
| 	new_filter = NULL;
 | |
| 	new_width = 0;
 | |
| 	new_height = 0;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	/*
 | |
| 	 * these are the size of the shadow pixmap, which
 | |
| 	 * matches the mode, not the pre-rotated copy in the
 | |
| 	 * frame buffer
 | |
| 	 */
 | |
| 	int	    width = crtc->mode.HDisplay;
 | |
| 	int	    height = crtc->mode.VDisplay;
 | |
| 	void	    *shadowData = crtc->rotatedData;
 | |
| 	PixmapPtr   shadow = crtc->rotatedPixmap;
 | |
| 	int	    old_width = shadow ? shadow->drawable.width : 0;
 | |
| 	int	    old_height = shadow ? shadow->drawable.height : 0;
 | |
| 
 | |
| 	/* Allocate memory for rotation */
 | |
| 	if (old_width != width || old_height != height)
 | |
| 	{
 | |
| 	    if (shadow || shadowData)
 | |
| 	    {
 | |
| 		crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
 | |
| 		crtc->rotatedPixmap = NULL;
 | |
| 		crtc->rotatedData = NULL;
 | |
| 	    }
 | |
| 	    shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
 | |
| 	    if (!shadowData)
 | |
| 		goto bail1;
 | |
| 	    crtc->rotatedData = shadowData;
 | |
| 	    /* shadow will be damaged in xf86RotatePrepare */
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    /* mark shadowed area as damaged so it will be repainted */
 | |
| 	    damage = TRUE;
 | |
| 	}
 | |
| 
 | |
| 	if (!xf86_config->rotation_damage)
 | |
| 	{
 | |
| 	    /* Create damage structure */
 | |
| 	    xf86_config->rotation_damage = DamageCreate (NULL, NULL,
 | |
| 						DamageReportNone,
 | |
| 						TRUE, pScreen, pScreen);
 | |
| 	    if (!xf86_config->rotation_damage)
 | |
| 		goto bail2;
 | |
| 	    
 | |
| 	    /* Wrap block handler */
 | |
| 	    if (!xf86_config->BlockHandler) {
 | |
| 		xf86_config->BlockHandler = pScreen->BlockHandler;
 | |
| 		pScreen->BlockHandler = xf86RotateBlockHandler;
 | |
| 	    }
 | |
| 	}
 | |
| #ifdef RANDR_12_INTERFACE
 | |
| 	if (transform)
 | |
| 	{
 | |
| 	    if (transform->nparams) {
 | |
| 		new_params = xalloc (transform->nparams * sizeof (xFixed));
 | |
| 		if (new_params) {
 | |
| 		    memcpy (new_params, transform->params,
 | |
| 			    transform->nparams * sizeof (xFixed));
 | |
| 		    new_nparams = transform->nparams;
 | |
| 		    new_filter = transform->filter;
 | |
| 		}
 | |
| 	    } else
 | |
| 		new_filter = transform->filter;
 | |
| 	    if (new_filter)
 | |
| 	    {
 | |
| 		new_width = new_filter->width;
 | |
| 		new_height = new_filter->height;
 | |
| 	    }
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	if (0)
 | |
| 	{
 | |
|     bail2:
 | |
| 	    if (shadow || shadowData)
 | |
| 	    {
 | |
| 		crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
 | |
| 		crtc->rotatedPixmap = NULL;
 | |
| 		crtc->rotatedData = NULL;
 | |
| 	    }
 | |
|     bail1:
 | |
| 	    if (old_width && old_height)
 | |
| 		crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
 | |
| 								  NULL,
 | |
| 								  old_width,
 | |
| 								  old_height);
 | |
| 	    return FALSE;
 | |
| 	}
 | |
| 	crtc->transform_in_use = TRUE;
 | |
|     }
 | |
|     crtc->crtc_to_framebuffer = crtc_to_fb;
 | |
|     crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
 | |
|     crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
 | |
|     if (crtc->params)
 | |
| 	xfree (crtc->params);
 | |
|     crtc->params = new_params;
 | |
|     crtc->nparams = new_nparams;
 | |
|     crtc->filter = new_filter;
 | |
|     crtc->filter_width = new_width;
 | |
|     crtc->filter_height = new_height;
 | |
|     crtc->bounds.x1 = 0;
 | |
|     crtc->bounds.x2 = crtc->mode.HDisplay;
 | |
|     crtc->bounds.y1 = 0;
 | |
|     crtc->bounds.y2 = crtc->mode.VDisplay;
 | |
|     pixman_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds);
 | |
| 
 | |
|     if (damage)
 | |
|         xf86CrtcDamageShadow (crtc);
 | |
| 
 | |
|     /* All done */
 | |
|     return TRUE;
 | |
| }
 |