1706f2543Smrg/* 2706f2543Smrg * Copyright © 2006 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that copyright 7706f2543Smrg * notice and this permission notice appear in supporting documentation, and 8706f2543Smrg * that the name of the copyright holders not be used in advertising or 9706f2543Smrg * publicity pertaining to distribution of the software without specific, 10706f2543Smrg * written prior permission. The copyright holders make no representations 11706f2543Smrg * about the suitability of this software for any purpose. It is provided "as 12706f2543Smrg * is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20706f2543Smrg * OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 24706f2543Smrg#include <xorg-config.h> 25706f2543Smrg#else 26706f2543Smrg#ifdef HAVE_CONFIG_H 27706f2543Smrg#include <config.h> 28706f2543Smrg#endif 29706f2543Smrg#endif 30706f2543Smrg 31706f2543Smrg#include <stddef.h> 32706f2543Smrg#include <string.h> 33706f2543Smrg#include <stdio.h> 34706f2543Smrg 35706f2543Smrg#include "xf86.h" 36706f2543Smrg#include "xf86DDC.h" 37706f2543Smrg#include "fb.h" 38706f2543Smrg#include "windowstr.h" 39706f2543Smrg#include "xf86Crtc.h" 40706f2543Smrg#include "xf86Modes.h" 41706f2543Smrg#include "xf86RandR12.h" 42706f2543Smrg#include "X11/extensions/render.h" 43706f2543Smrg#include "X11/extensions/dpmsconst.h" 44706f2543Smrg#include "X11/Xatom.h" 45706f2543Smrg 46706f2543Smrg/* borrowed from composite extension, move to Render and publish? */ 47706f2543Smrg 48706f2543Smrgstatic VisualPtr 49706f2543SmrgcompGetWindowVisual (WindowPtr pWin) 50706f2543Smrg{ 51706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 52706f2543Smrg VisualID vid = wVisual (pWin); 53706f2543Smrg int i; 54706f2543Smrg 55706f2543Smrg for (i = 0; i < pScreen->numVisuals; i++) 56706f2543Smrg if (pScreen->visuals[i].vid == vid) 57706f2543Smrg return &pScreen->visuals[i]; 58706f2543Smrg return 0; 59706f2543Smrg} 60706f2543Smrg 61706f2543Smrgstatic PictFormatPtr 62706f2543SmrgcompWindowFormat (WindowPtr pWin) 63706f2543Smrg{ 64706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 65706f2543Smrg 66706f2543Smrg return PictureMatchVisual (pScreen, pWin->drawable.depth, 67706f2543Smrg compGetWindowVisual (pWin)); 68706f2543Smrg} 69706f2543Smrg 70706f2543Smrg#define F(x) IntToxFixed(x) 71706f2543Smrg 72706f2543Smrg#define toF(x) ((float) (x) / 65536.0f) 73706f2543Smrg 74706f2543Smrgstatic void 75706f2543Smrgxf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) 76706f2543Smrg{ 77706f2543Smrg ScrnInfoPtr scrn = crtc->scrn; 78706f2543Smrg ScreenPtr screen = scrn->pScreen; 79706f2543Smrg WindowPtr root = screen->root; 80706f2543Smrg PixmapPtr dst_pixmap = crtc->rotatedPixmap; 81706f2543Smrg PictFormatPtr format = compWindowFormat (screen->root); 82706f2543Smrg int error; 83706f2543Smrg PicturePtr src, dst; 84706f2543Smrg int n = RegionNumRects(region); 85706f2543Smrg BoxPtr b = RegionRects(region); 86706f2543Smrg XID include_inferiors = IncludeInferiors; 87706f2543Smrg 88706f2543Smrg src = CreatePicture (None, 89706f2543Smrg &root->drawable, 90706f2543Smrg format, 91706f2543Smrg CPSubwindowMode, 92706f2543Smrg &include_inferiors, 93706f2543Smrg serverClient, 94706f2543Smrg &error); 95706f2543Smrg if (!src) 96706f2543Smrg return; 97706f2543Smrg 98706f2543Smrg dst = CreatePicture (None, 99706f2543Smrg &dst_pixmap->drawable, 100706f2543Smrg format, 101706f2543Smrg 0L, 102706f2543Smrg NULL, 103706f2543Smrg serverClient, 104706f2543Smrg &error); 105706f2543Smrg if (!dst) 106706f2543Smrg return; 107706f2543Smrg 108706f2543Smrg error = SetPictureTransform (src, &crtc->crtc_to_framebuffer); 109706f2543Smrg if (error) 110706f2543Smrg return; 111706f2543Smrg if (crtc->transform_in_use && crtc->filter) 112706f2543Smrg SetPicturePictFilter (src, crtc->filter, 113706f2543Smrg crtc->params, crtc->nparams); 114706f2543Smrg 115706f2543Smrg if (crtc->shadowClear) 116706f2543Smrg { 117706f2543Smrg CompositePicture (PictOpSrc, 118706f2543Smrg src, NULL, dst, 119706f2543Smrg 0, 0, 0, 0, 0, 0, 120706f2543Smrg crtc->mode.HDisplay, crtc->mode.VDisplay); 121706f2543Smrg crtc->shadowClear = FALSE; 122706f2543Smrg } 123706f2543Smrg else 124706f2543Smrg { 125706f2543Smrg while (n--) 126706f2543Smrg { 127706f2543Smrg BoxRec dst_box; 128706f2543Smrg 129706f2543Smrg dst_box = *b; 130706f2543Smrg dst_box.x1 -= crtc->filter_width >> 1; 131706f2543Smrg dst_box.x2 += crtc->filter_width >> 1; 132706f2543Smrg dst_box.y1 -= crtc->filter_height >> 1; 133706f2543Smrg dst_box.y2 += crtc->filter_height >> 1; 134706f2543Smrg pixman_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box); 135706f2543Smrg CompositePicture (PictOpSrc, 136706f2543Smrg src, NULL, dst, 137706f2543Smrg dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1, 138706f2543Smrg dst_box.x2 - dst_box.x1, 139706f2543Smrg dst_box.y2 - dst_box.y1); 140706f2543Smrg b++; 141706f2543Smrg } 142706f2543Smrg } 143706f2543Smrg FreePicture (src, None); 144706f2543Smrg FreePicture (dst, None); 145706f2543Smrg} 146706f2543Smrg 147706f2543Smrgstatic void 148706f2543Smrgxf86CrtcDamageShadow (xf86CrtcPtr crtc) 149706f2543Smrg{ 150706f2543Smrg ScrnInfoPtr pScrn = crtc->scrn; 151706f2543Smrg BoxRec damage_box; 152706f2543Smrg RegionRec damage_region; 153706f2543Smrg ScreenPtr pScreen = pScrn->pScreen; 154706f2543Smrg 155706f2543Smrg damage_box.x1 = 0; 156706f2543Smrg damage_box.x2 = crtc->mode.HDisplay; 157706f2543Smrg damage_box.y1 = 0; 158706f2543Smrg damage_box.y2 = crtc->mode.VDisplay; 159706f2543Smrg if (!pixman_transform_bounds (&crtc->crtc_to_framebuffer, &damage_box)) 160706f2543Smrg { 161706f2543Smrg damage_box.x1 = 0; 162706f2543Smrg damage_box.y1 = 0; 163706f2543Smrg damage_box.x2 = pScreen->width; 164706f2543Smrg damage_box.y2 = pScreen->height; 165706f2543Smrg } 166706f2543Smrg if (damage_box.x1 < 0) damage_box.x1 = 0; 167706f2543Smrg if (damage_box.y1 < 0) damage_box.y1 = 0; 168706f2543Smrg if (damage_box.x2 > pScreen->width) damage_box.x2 = pScreen->width; 169706f2543Smrg if (damage_box.y2 > pScreen->height) damage_box.y2 = pScreen->height; 170706f2543Smrg RegionInit(&damage_region, &damage_box, 1); 171706f2543Smrg DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, 172706f2543Smrg &damage_region); 173706f2543Smrg RegionUninit(&damage_region); 174706f2543Smrg crtc->shadowClear = TRUE; 175706f2543Smrg} 176706f2543Smrg 177706f2543Smrgstatic void 178706f2543Smrgxf86RotatePrepare (ScreenPtr pScreen) 179706f2543Smrg{ 180706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 181706f2543Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 182706f2543Smrg int c; 183706f2543Smrg 184706f2543Smrg for (c = 0; c < xf86_config->num_crtc; c++) 185706f2543Smrg { 186706f2543Smrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 187706f2543Smrg 188706f2543Smrg if (crtc->rotatedData && !crtc->rotatedPixmap) 189706f2543Smrg { 190706f2543Smrg crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc, 191706f2543Smrg crtc->rotatedData, 192706f2543Smrg crtc->mode.HDisplay, 193706f2543Smrg crtc->mode.VDisplay); 194706f2543Smrg if (!xf86_config->rotation_damage_registered) 195706f2543Smrg { 196706f2543Smrg /* Hook damage to screen pixmap */ 197706f2543Smrg DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, 198706f2543Smrg xf86_config->rotation_damage); 199706f2543Smrg xf86_config->rotation_damage_registered = TRUE; 200706f2543Smrg EnableLimitedSchedulingLatency(); 201706f2543Smrg } 202706f2543Smrg 203706f2543Smrg xf86CrtcDamageShadow (crtc); 204706f2543Smrg } 205706f2543Smrg } 206706f2543Smrg} 207706f2543Smrg 208706f2543Smrgstatic Bool 209706f2543Smrgxf86RotateRedisplay(ScreenPtr pScreen) 210706f2543Smrg{ 211706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 212706f2543Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 213706f2543Smrg DamagePtr damage = xf86_config->rotation_damage; 214706f2543Smrg RegionPtr region; 215706f2543Smrg 216706f2543Smrg if (!damage) 217706f2543Smrg return FALSE; 218706f2543Smrg xf86RotatePrepare (pScreen); 219706f2543Smrg region = DamageRegion(damage); 220706f2543Smrg if (RegionNotEmpty(region)) 221706f2543Smrg { 222706f2543Smrg int c; 223706f2543Smrg SourceValidateProcPtr SourceValidate; 224706f2543Smrg 225706f2543Smrg /* 226706f2543Smrg * SourceValidate is used by the software cursor code 227706f2543Smrg * to pull the cursor off of the screen when reading 228706f2543Smrg * bits from the frame buffer. Bypassing this function 229706f2543Smrg * leaves the software cursor in place 230706f2543Smrg */ 231706f2543Smrg SourceValidate = pScreen->SourceValidate; 232706f2543Smrg pScreen->SourceValidate = NULL; 233706f2543Smrg 234706f2543Smrg for (c = 0; c < xf86_config->num_crtc; c++) 235706f2543Smrg { 236706f2543Smrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 237706f2543Smrg 238706f2543Smrg if (crtc->transform_in_use && crtc->enabled) 239706f2543Smrg { 240706f2543Smrg RegionRec crtc_damage; 241706f2543Smrg 242706f2543Smrg /* compute portion of damage that overlaps crtc */ 243706f2543Smrg RegionInit(&crtc_damage, &crtc->bounds, 1); 244706f2543Smrg RegionIntersect(&crtc_damage, &crtc_damage, region); 245706f2543Smrg 246706f2543Smrg /* update damaged region */ 247706f2543Smrg if (RegionNotEmpty(&crtc_damage)) 248706f2543Smrg xf86RotateCrtcRedisplay (crtc, &crtc_damage); 249706f2543Smrg 250706f2543Smrg RegionUninit(&crtc_damage); 251706f2543Smrg } 252706f2543Smrg } 253706f2543Smrg pScreen->SourceValidate = SourceValidate; 254706f2543Smrg DamageEmpty(damage); 255706f2543Smrg } 256706f2543Smrg return TRUE; 257706f2543Smrg} 258706f2543Smrg 259706f2543Smrgstatic void 260706f2543Smrgxf86RotateBlockHandler(int screenNum, pointer blockData, 261706f2543Smrg pointer pTimeout, pointer pReadmask) 262706f2543Smrg{ 263706f2543Smrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 264706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[screenNum]; 265706f2543Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 266706f2543Smrg Bool rotation_active; 267706f2543Smrg 268706f2543Smrg rotation_active = xf86RotateRedisplay(pScreen); 269706f2543Smrg pScreen->BlockHandler = xf86_config->BlockHandler; 270706f2543Smrg (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); 271706f2543Smrg /* cannot avoid re-wrapping until all wrapping is audited */ 272706f2543Smrg xf86_config->BlockHandler = pScreen->BlockHandler; 273706f2543Smrg pScreen->BlockHandler = xf86RotateBlockHandler; 274706f2543Smrg} 275706f2543Smrg 276706f2543Smrgvoid 277706f2543Smrgxf86RotateDestroy (xf86CrtcPtr crtc) 278706f2543Smrg{ 279706f2543Smrg ScrnInfoPtr pScrn = crtc->scrn; 280706f2543Smrg ScreenPtr pScreen = pScrn->pScreen; 281706f2543Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 282706f2543Smrg int c; 283706f2543Smrg 284706f2543Smrg /* Free memory from rotation */ 285706f2543Smrg if (crtc->rotatedPixmap || crtc->rotatedData) 286706f2543Smrg { 287706f2543Smrg crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData); 288706f2543Smrg crtc->rotatedPixmap = NULL; 289706f2543Smrg crtc->rotatedData = NULL; 290706f2543Smrg } 291706f2543Smrg 292706f2543Smrg for (c = 0; c < xf86_config->num_crtc; c++) 293706f2543Smrg if (xf86_config->crtc[c]->transform_in_use) 294706f2543Smrg return; 295706f2543Smrg 296706f2543Smrg /* 297706f2543Smrg * Clean up damage structures when no crtcs are rotated 298706f2543Smrg */ 299706f2543Smrg if (xf86_config->rotation_damage) 300706f2543Smrg { 301706f2543Smrg /* Free damage structure */ 302706f2543Smrg if (xf86_config->rotation_damage_registered) 303706f2543Smrg { 304706f2543Smrg DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, 305706f2543Smrg xf86_config->rotation_damage); 306706f2543Smrg xf86_config->rotation_damage_registered = FALSE; 307706f2543Smrg DisableLimitedSchedulingLatency(); 308706f2543Smrg } 309706f2543Smrg DamageDestroy (xf86_config->rotation_damage); 310706f2543Smrg xf86_config->rotation_damage = NULL; 311706f2543Smrg } 312706f2543Smrg} 313706f2543Smrg 314706f2543Smrgvoid 315706f2543Smrgxf86RotateFreeShadow(ScrnInfoPtr pScrn) 316706f2543Smrg{ 317706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 318706f2543Smrg int c; 319706f2543Smrg 320706f2543Smrg for (c = 0; c < config->num_crtc; c++) { 321706f2543Smrg xf86CrtcPtr crtc = config->crtc[c]; 322706f2543Smrg 323706f2543Smrg if (crtc->rotatedPixmap || crtc->rotatedData) { 324706f2543Smrg crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap, 325706f2543Smrg crtc->rotatedData); 326706f2543Smrg crtc->rotatedPixmap = NULL; 327706f2543Smrg crtc->rotatedData = NULL; 328706f2543Smrg } 329706f2543Smrg } 330706f2543Smrg} 331706f2543Smrg 332706f2543Smrgvoid 333706f2543Smrgxf86RotateCloseScreen (ScreenPtr screen) 334706f2543Smrg{ 335706f2543Smrg ScrnInfoPtr scrn = xf86Screens[screen->myNum]; 336706f2543Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 337706f2543Smrg int c; 338706f2543Smrg 339706f2543Smrg for (c = 0; c < xf86_config->num_crtc; c++) 340706f2543Smrg xf86RotateDestroy (xf86_config->crtc[c]); 341706f2543Smrg} 342706f2543Smrg 343706f2543Smrgstatic Bool 344706f2543Smrgxf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb) 345706f2543Smrg{ 346706f2543Smrg ScrnInfoPtr pScrn = crtc->scrn; 347706f2543Smrg BoxRec b; 348706f2543Smrg 349706f2543Smrg /* When called before PreInit, the driver is 350706f2543Smrg * presumably doing load detect 351706f2543Smrg */ 352706f2543Smrg if (pScrn->virtualX == 0 || pScrn->virtualY == 0) 353706f2543Smrg return TRUE; 354706f2543Smrg 355706f2543Smrg b.x1 = 0; 356706f2543Smrg b.y1 = 0; 357706f2543Smrg b.x2 = crtc->mode.HDisplay; 358706f2543Smrg b.y2 = crtc->mode.VDisplay; 359706f2543Smrg if (crtc_to_fb) 360706f2543Smrg pixman_f_transform_bounds (crtc_to_fb, &b); 361706f2543Smrg else { 362706f2543Smrg b.x1 += crtc->x; 363706f2543Smrg b.y1 += crtc->y; 364706f2543Smrg b.x2 += crtc->x; 365706f2543Smrg b.y2 += crtc->y; 366706f2543Smrg } 367706f2543Smrg 368706f2543Smrg return (0 <= b.x1 && b.x2 <= pScrn->virtualX && 369706f2543Smrg 0 <= b.y1 && b.y2 <= pScrn->virtualY); 370706f2543Smrg} 371706f2543Smrg 372706f2543SmrgBool 373706f2543Smrgxf86CrtcRotate (xf86CrtcPtr crtc) 374706f2543Smrg{ 375706f2543Smrg ScrnInfoPtr pScrn = crtc->scrn; 376706f2543Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 377706f2543Smrg /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ 378706f2543Smrg ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; 379706f2543Smrg PictTransform crtc_to_fb; 380706f2543Smrg struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc; 381706f2543Smrg xFixed *new_params = NULL; 382706f2543Smrg int new_nparams = 0; 383706f2543Smrg PictFilterPtr new_filter = NULL; 384706f2543Smrg int new_width = 0; 385706f2543Smrg int new_height = 0; 386706f2543Smrg RRTransformPtr transform = NULL; 387706f2543Smrg Bool damage = FALSE; 388706f2543Smrg 389706f2543Smrg if (crtc->transformPresent) 390706f2543Smrg transform = &crtc->transform; 391706f2543Smrg 392706f2543Smrg if (!RRTransformCompute (crtc->x, crtc->y, 393706f2543Smrg crtc->mode.HDisplay, crtc->mode.VDisplay, 394706f2543Smrg crtc->rotation, 395706f2543Smrg transform, 396706f2543Smrg 397706f2543Smrg &crtc_to_fb, 398706f2543Smrg &f_crtc_to_fb, 399706f2543Smrg &f_fb_to_crtc) && 400706f2543Smrg xf86CrtcFitsScreen (crtc, &f_crtc_to_fb)) 401706f2543Smrg { 402706f2543Smrg /* 403706f2543Smrg * If the untranslated transformation is the identity, 404706f2543Smrg * disable the shadow buffer 405706f2543Smrg */ 406706f2543Smrg xf86RotateDestroy (crtc); 407706f2543Smrg crtc->transform_in_use = FALSE; 408706f2543Smrg free(new_params); 409706f2543Smrg new_params = NULL; 410706f2543Smrg new_nparams = 0; 411706f2543Smrg new_filter = NULL; 412706f2543Smrg new_width = 0; 413706f2543Smrg new_height = 0; 414706f2543Smrg } 415706f2543Smrg else 416706f2543Smrg { 417706f2543Smrg /* 418706f2543Smrg * these are the size of the shadow pixmap, which 419706f2543Smrg * matches the mode, not the pre-rotated copy in the 420706f2543Smrg * frame buffer 421706f2543Smrg */ 422706f2543Smrg int width = crtc->mode.HDisplay; 423706f2543Smrg int height = crtc->mode.VDisplay; 424706f2543Smrg void *shadowData = crtc->rotatedData; 425706f2543Smrg PixmapPtr shadow = crtc->rotatedPixmap; 426706f2543Smrg int old_width = shadow ? shadow->drawable.width : 0; 427706f2543Smrg int old_height = shadow ? shadow->drawable.height : 0; 428706f2543Smrg 429706f2543Smrg /* Allocate memory for rotation */ 430706f2543Smrg if (old_width != width || old_height != height) 431706f2543Smrg { 432706f2543Smrg if (shadow || shadowData) 433706f2543Smrg { 434706f2543Smrg crtc->funcs->shadow_destroy (crtc, shadow, shadowData); 435706f2543Smrg crtc->rotatedPixmap = NULL; 436706f2543Smrg crtc->rotatedData = NULL; 437706f2543Smrg } 438706f2543Smrg shadowData = crtc->funcs->shadow_allocate (crtc, width, height); 439706f2543Smrg if (!shadowData) 440706f2543Smrg goto bail1; 441706f2543Smrg crtc->rotatedData = shadowData; 442706f2543Smrg /* shadow will be damaged in xf86RotatePrepare */ 443706f2543Smrg } 444706f2543Smrg else 445706f2543Smrg { 446706f2543Smrg /* mark shadowed area as damaged so it will be repainted */ 447706f2543Smrg damage = TRUE; 448706f2543Smrg } 449706f2543Smrg 450706f2543Smrg if (!xf86_config->rotation_damage) 451706f2543Smrg { 452706f2543Smrg /* Create damage structure */ 453706f2543Smrg xf86_config->rotation_damage = DamageCreate (NULL, NULL, 454706f2543Smrg DamageReportNone, 455706f2543Smrg TRUE, pScreen, pScreen); 456706f2543Smrg if (!xf86_config->rotation_damage) 457706f2543Smrg goto bail2; 458706f2543Smrg 459706f2543Smrg /* Wrap block handler */ 460706f2543Smrg if (!xf86_config->BlockHandler) { 461706f2543Smrg xf86_config->BlockHandler = pScreen->BlockHandler; 462706f2543Smrg pScreen->BlockHandler = xf86RotateBlockHandler; 463706f2543Smrg } 464706f2543Smrg } 465706f2543Smrg#ifdef RANDR_12_INTERFACE 466706f2543Smrg if (transform) 467706f2543Smrg { 468706f2543Smrg if (transform->nparams) { 469706f2543Smrg new_params = malloc(transform->nparams * sizeof (xFixed)); 470706f2543Smrg if (new_params) { 471706f2543Smrg memcpy (new_params, transform->params, 472706f2543Smrg transform->nparams * sizeof (xFixed)); 473706f2543Smrg new_nparams = transform->nparams; 474706f2543Smrg new_filter = transform->filter; 475706f2543Smrg } 476706f2543Smrg } else 477706f2543Smrg new_filter = transform->filter; 478706f2543Smrg if (new_filter) 479706f2543Smrg { 480706f2543Smrg new_width = new_filter->width; 481706f2543Smrg new_height = new_filter->height; 482706f2543Smrg } 483706f2543Smrg } 484706f2543Smrg#endif 485706f2543Smrg 486706f2543Smrg if (0) 487706f2543Smrg { 488706f2543Smrg bail2: 489706f2543Smrg if (shadow || shadowData) 490706f2543Smrg { 491706f2543Smrg crtc->funcs->shadow_destroy (crtc, shadow, shadowData); 492706f2543Smrg crtc->rotatedPixmap = NULL; 493706f2543Smrg crtc->rotatedData = NULL; 494706f2543Smrg } 495706f2543Smrg bail1: 496706f2543Smrg if (old_width && old_height) 497706f2543Smrg crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc, 498706f2543Smrg NULL, 499706f2543Smrg old_width, 500706f2543Smrg old_height); 501706f2543Smrg return FALSE; 502706f2543Smrg } 503706f2543Smrg crtc->transform_in_use = TRUE; 504706f2543Smrg } 505706f2543Smrg crtc->crtc_to_framebuffer = crtc_to_fb; 506706f2543Smrg crtc->f_crtc_to_framebuffer = f_crtc_to_fb; 507706f2543Smrg crtc->f_framebuffer_to_crtc = f_fb_to_crtc; 508706f2543Smrg free(crtc->params); 509706f2543Smrg crtc->params = new_params; 510706f2543Smrg crtc->nparams = new_nparams; 511706f2543Smrg crtc->filter = new_filter; 512706f2543Smrg crtc->filter_width = new_width; 513706f2543Smrg crtc->filter_height = new_height; 514706f2543Smrg crtc->bounds.x1 = 0; 515706f2543Smrg crtc->bounds.x2 = crtc->mode.HDisplay; 516706f2543Smrg crtc->bounds.y1 = 0; 517706f2543Smrg crtc->bounds.y2 = crtc->mode.VDisplay; 518706f2543Smrg pixman_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds); 519706f2543Smrg 520706f2543Smrg if (damage) 521706f2543Smrg xf86CrtcDamageShadow (crtc); 522706f2543Smrg 523706f2543Smrg /* All done */ 524706f2543Smrg return TRUE; 525706f2543Smrg} 526