diff options
author | Keith Packard <keithp@keithp.com> | 2008-03-19 00:46:35 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2008-11-24 13:24:40 -0800 |
commit | 49db14e4ac26070ed86088419483888dda18b603 (patch) | |
tree | 24f45d2c6117e204cf489633ac29eedccce9688f /randr/rrcrtc.c | |
parent | 6f734aecaec4f5c6152c3ebca197ef65bb4523da (diff) |
Handle RandR transform matrices in floating point.
RandR matrix computations lose too much precision in fixed point;
computations using the inverted matrix can be as much as 10 pixels off.
Convert them to double precision values and pass those around. These API
changes are fairly heavyweight; the official Render interface remains fixed
point, so the fixed point matrix comes along for the ride everywhere.
Diffstat (limited to 'randr/rrcrtc.c')
-rw-r--r-- | randr/rrcrtc.c | 136 |
1 files changed, 93 insertions, 43 deletions
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index e0fafce7a..d7ea6f22b 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -52,7 +52,8 @@ static void RRTransformInit (RRTransformPtr transform) { PictureTransformInitIdentity (&transform->transform); - PictureTransformInitIdentity (&transform->inverse); + pict_f_transform_init_identity (&transform->f_transform); + pict_f_transform_init_identity (&transform->f_inverse); transform->filter = NULL; transform->params = NULL; transform->nparams = 0; @@ -94,7 +95,8 @@ RRTransformCopy (RRTransformPtr dst, RRTransformPtr src) src->params, src->nparams, src->width, src->height)) return FALSE; dst->transform = src->transform; - dst->inverse = src->inverse; + dst->f_transform = src->f_transform; + dst->f_inverse = src->f_inverse; return TRUE; } @@ -142,7 +144,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) RRTransformInit (&crtc->client_pending_transform); RRTransformInit (&crtc->client_current_transform); PictureTransformInitIdentity (&crtc->transform); - PictureTransformInitIdentity (&crtc->inverse); + pict_f_transform_init_identity (&crtc->f_transform); + pict_f_transform_init_identity (&crtc->f_inverse); if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) return NULL; @@ -441,13 +444,19 @@ RRCrtcGetTransform (RRCrtcPtr crtc) void RRCrtcPostPendingTransform (RRCrtcPtr crtc) { + if (!crtc->mode) + return; + RRTransformCopy (&crtc->client_current_transform, &crtc->client_pending_transform); - RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y, - &crtc->client_current_transform.transform, - &crtc->client_current_transform.inverse, + RRComputeTransform (crtc->x, crtc->y, + crtc->mode->mode.width, + crtc->mode->mode.height, + crtc->rotation, + &crtc->client_current_transform, &crtc->transform, - &crtc->inverse); + &crtc->f_transform, + &crtc->f_inverse); } /* @@ -608,7 +617,8 @@ RRCrtcGammaSetSize (RRCrtcPtr crtc, int RRCrtcTransformSet (RRCrtcPtr crtc, PictTransformPtr transform, - PictTransformPtr inverse, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse, char *filter_name, int filter_len, xFixed *params, @@ -648,7 +658,8 @@ RRCrtcTransformSet (RRCrtcPtr crtc, return BadAlloc; crtc->client_pending_transform.transform = *transform; - crtc->client_pending_transform.inverse = *inverse; + crtc->client_pending_transform.f_transform = *f_transform; + crtc->client_pending_transform.f_inverse = *f_inverse; return Success; } @@ -662,78 +673,110 @@ RRCrtcTransformSet (RRCrtcPtr crtc, * Return TRUE if the resulting transform is not a simple translation. */ Bool -RRComputeTransform (RRModePtr mode, - Rotation rotation, - int x, - int y, - PictTransformPtr client_transform, - PictTransformPtr client_inverse, - PictTransformPtr transform, - PictTransformPtr inverse) +RRComputeTransform (int x, + int y, + int width, + int height, + Rotation rotation, + RRTransformPtr rr_transform, + + PictTransformPtr transform, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse) { + PictTransform inverse; + PictureTransformInitIdentity (transform); - PictureTransformInitIdentity (inverse); + PictureTransformInitIdentity (&inverse); + pict_f_transform_init_identity (f_transform); + pict_f_transform_init_identity (f_inverse); if (rotation != RR_Rotate_0) { + double f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy; + double f_scale_x, f_scale_y, f_scale_dx, f_scale_dy; xFixed rot_cos, rot_sin, rot_dx, rot_dy; xFixed scale_x, scale_y, scale_dx, scale_dy; - int mode_w = mode->mode.width; - int mode_h = mode->mode.height; - + /* rotation */ switch (rotation & 0xf) { default: case RR_Rotate_0: + f_rot_cos = 1; f_rot_sin = 0; + f_rot_dx = 0; f_rot_dy = 0; rot_cos = F ( 1); rot_sin = F ( 0); rot_dx = F ( 0); rot_dy = F ( 0); break; case RR_Rotate_90: + f_rot_cos = 0; f_rot_sin = 1; + f_rot_dx = height; f_rot_dy = 0; rot_cos = F ( 0); rot_sin = F ( 1); - rot_dx = F ( mode_h); rot_dy = F (0); + rot_dx = F ( height); rot_dy = F (0); break; case RR_Rotate_180: + f_rot_cos = -1; f_rot_sin = 0; + f_rot_dx = width; f_rot_dy = height; rot_cos = F (-1); rot_sin = F ( 0); - rot_dx = F (mode_w); rot_dy = F ( mode_h); + rot_dx = F (width); rot_dy = F ( height); break; case RR_Rotate_270: + f_rot_cos = 0; f_rot_sin = -1; + f_rot_dx = 0; f_rot_dy = width; rot_cos = F ( 0); rot_sin = F (-1); - rot_dx = F ( 0); rot_dy = F ( mode_w); + rot_dx = F ( 0); rot_dy = F ( width); break; } - PictureTransformRotate (inverse, transform, rot_cos, rot_sin); - PictureTransformTranslate (inverse, transform, rot_dx, rot_dy); + PictureTransformRotate (&inverse, transform, rot_cos, rot_sin); + PictureTransformTranslate (&inverse, transform, rot_dx, rot_dy); + pict_f_transform_rotate (f_inverse, f_transform, f_rot_cos, f_rot_sin); + pict_f_transform_translate (f_inverse, f_transform, f_rot_dx, f_rot_dy); /* reflection */ + f_scale_x = 1; + f_scale_dx = 0; + f_scale_y = 1; + f_scale_dy = 0; scale_x = F (1); scale_dx = 0; scale_y = F (1); scale_dy = 0; if (rotation & RR_Reflect_X) { + f_scale_x = -1; scale_x = F(-1); - if (rotation & (RR_Rotate_0|RR_Rotate_180)) - scale_dx = F(mode_w); - else - scale_dx = F(mode_h); + if (rotation & (RR_Rotate_0|RR_Rotate_180)) { + f_scale_dx = width; + scale_dx = F(width); + } else { + f_scale_dx = height; + scale_dx = F(height); + } } if (rotation & RR_Reflect_Y) { + f_scale_y = -1; scale_y = F(-1); - if (rotation & (RR_Rotate_0|RR_Rotate_180)) - scale_dy = F(mode_h); - else - scale_dy = F(mode_w); + if (rotation & (RR_Rotate_0|RR_Rotate_180)) { + f_scale_dy = height; + scale_dy = F(height); + } else { + f_scale_dy = width; + scale_dy = F(width); + } } - PictureTransformScale (inverse, transform, scale_x, scale_y); - PictureTransformTranslate (inverse, transform, scale_dx, scale_dy); + PictureTransformScale (&inverse, transform, scale_x, scale_y); + pict_f_transform_scale (f_inverse, f_transform, f_scale_x, f_scale_y); + PictureTransformTranslate (&inverse, transform, scale_dx, scale_dy); + pict_f_transform_translate (f_inverse, f_transform, f_scale_dx, f_scale_dy); } #ifdef RANDR_12_INTERFACE + if (rr_transform) { - PictureTransformMultiply (inverse, client_inverse, inverse); - PictureTransformMultiply (transform, transform, client_transform); + PictureTransformMultiply (transform, transform, &rr_transform->transform); + pict_f_transform_multiply (f_transform, f_transform, &rr_transform->f_transform); + pict_f_transform_multiply (f_inverse, &rr_transform->f_inverse, f_inverse); } #endif /* @@ -741,13 +784,16 @@ RRComputeTransform (RRModePtr mode, */ if (PictureTransformIsIdentity (transform)) { - PictureTransformInitTranslate (inverse, F (-x), F (-y)); PictureTransformInitTranslate (transform, F ( x), F ( y)); + + pict_f_transform_init_translate (f_transform, F( x), F( y)); + pict_f_transform_init_translate (f_inverse, F(-x), F(-y)); return FALSE; } else { - PictureTransformTranslate (inverse, transform, x, y); + PictureTransformTranslate (&inverse, transform, x, y); + pict_f_transform_translate (f_inverse, f_transform, x, y); return TRUE; } } @@ -1045,6 +1091,7 @@ ProcRRSetCrtcConfig (ClientPtr client) } #ifdef RANDR_12_INTERFACE +#if 0 /* * Check screen size bounds if the DDX provides a 1.2 interface * for setting screen size. Else, assume the CrtcSet sets @@ -1080,6 +1127,7 @@ ProcRRSetCrtcConfig (ClientPtr client) } } #endif +#endif } /* @@ -1227,7 +1275,8 @@ ProcRRSetCrtcTransform (ClientPtr client) { REQUEST(xRRSetCrtcTransformReq); RRCrtcPtr crtc; - PictTransform transform, inverse; + PictTransform transform; + struct pict_f_transform f_transform, f_inverse; char *filter; int nbytes; xFixed *params; @@ -1239,7 +1288,8 @@ ProcRRSetCrtcTransform (ClientPtr client) return RRErrorBase + BadRRCrtc; PictTransform_from_xRenderTransform (&transform, &stuff->transform); - if (!PictureTransformInvert (&inverse, &transform)) + pict_f_transform_from_pixman_transform (&f_transform, &transform); + if (!pict_f_transform_invert (&f_inverse, &f_transform)) return BadMatch; filter = (char *) (stuff + 1); @@ -1249,7 +1299,7 @@ ProcRRSetCrtcTransform (ClientPtr client) if (nparams < 0) return BadLength; - return RRCrtcTransformSet (crtc, &transform, &inverse, + return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse, filter, nbytes, params, nparams); } |