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 | |
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.
-rw-r--r-- | hw/xfree86/modes/xf86Crtc.c | 3 | ||||
-rw-r--r-- | hw/xfree86/modes/xf86Crtc.h | 3 | ||||
-rw-r--r-- | hw/xfree86/modes/xf86Cursors.c | 16 | ||||
-rw-r--r-- | hw/xfree86/modes/xf86Rotate.c | 167 | ||||
-rw-r--r-- | randr/randrstr.h | 27 | ||||
-rw-r--r-- | randr/rrcrtc.c | 136 | ||||
-rw-r--r-- | render/matrix.c | 324 | ||||
-rw-r--r-- | render/picturestr.h | 63 |
8 files changed, 488 insertions, 251 deletions
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 65c003057..9f11037b7 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -104,7 +104,8 @@ xf86CrtcCreate (ScrnInfoPtr scrn, crtc->rotation = RR_Rotate_0; crtc->desiredRotation = RR_Rotate_0; PictureTransformInitIdentity (&crtc->crtc_to_framebuffer); - PictureTransformInitIdentity (&crtc->framebuffer_to_crtc); + pict_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); + pict_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); crtc->filter = NULL; crtc->params = NULL; crtc->nparams = 0; diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h index d093b1a55..026ec7803 100644 --- a/hw/xfree86/modes/xf86Crtc.h +++ b/hw/xfree86/modes/xf86Crtc.h @@ -305,7 +305,8 @@ struct _xf86Crtc { * Current transformation matrix */ PictTransform crtc_to_framebuffer; - PictTransform framebuffer_to_crtc; + struct pict_f_transform f_crtc_to_framebuffer; + struct pict_f_transform f_framebuffer_to_crtc; PictFilterPtr filter; xFixed *params; int nparams; diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c index 7bf92651f..40657897d 100644 --- a/hw/xfree86/modes/xf86Cursors.c +++ b/hw/xfree86/modes/xf86Cursors.c @@ -326,15 +326,13 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates, xf86CursorScreenKey); - PictVector v; - x += ScreenPriv->HotX; - y += ScreenPriv->HotY; - v.vector[0] = IntToxFixed (x); v.vector[1] = IntToxFixed (y); v.vector[2] = IntToxFixed(1); - PictureTransformPoint (&crtc->framebuffer_to_crtc, &v); - x = xFixedToInt (v.vector[0]); y = xFixedToInt (v.vector[1]); - x -= ScreenPriv->HotX; - y -= ScreenPriv->HotY; - } + struct pict_f_vector v; + + v.v[0] = x + ScreenPriv->HotX; v.v[1] = y + ScreenPriv->HotY; v.v[2] = 1; + pict_f_transform_point (&crtc->f_framebuffer_to_crtc, &v); + x = floor (v.v[0] + 0.5) - ScreenPriv->HotX; + y = floor (v.v[1] + 0.5) - ScreenPriv->HotY; + } else { x -= crtc->x; diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c index 7b49afa4b..efbacec8e 100644 --- a/hw/xfree86/modes/xf86Rotate.c +++ b/hw/xfree86/modes/xf86Rotate.c @@ -122,7 +122,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) dst_box.x2 += crtc->filter_width >> 1; dst_box.y1 -= crtc->filter_height >> 1; dst_box.y2 += crtc->filter_height >> 1; - PictureTransformBounds (&dst_box, &crtc->framebuffer_to_crtc); + pict_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, @@ -165,6 +165,8 @@ xf86CrtcShadowClear (xf86CrtcPtr crtc) xRectangle rect; int error; + if (!dst_pixmap) + return; dst = CreatePicture (None, &dst_pixmap->drawable, format, @@ -199,7 +201,6 @@ xf86RotatePrepare (ScreenPtr pScreen) crtc->rotatedData, crtc->mode.HDisplay, crtc->mode.VDisplay); - xf86CrtcShadowClear (crtc); if (!xf86_config->rotation_damage_registered) { /* Hook damage to screen pixmap */ @@ -355,109 +356,33 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) 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, fb_to_crtc; + 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; - - PictureTransformInitIdentity (&crtc_to_fb); - PictureTransformInitIdentity (&fb_to_crtc); - if (rotation != RR_Rotate_0) - { - xFixed rot_cos, rot_sin, rot_dx, rot_dy; - xFixed scale_x, scale_y, scale_dx, scale_dy; - int mode_w = crtc->mode.HDisplay; - int mode_h = crtc->mode.VDisplay; - - /* rotation */ - switch (rotation & 0xf) { - default: - case RR_Rotate_0: - rot_cos = F ( 1); rot_sin = F ( 0); - rot_dx = F ( 0); rot_dy = F ( 0); - break; - case RR_Rotate_90: - rot_cos = F ( 0); rot_sin = F ( 1); - rot_dx = F ( mode_h); rot_dy = F (0); - break; - case RR_Rotate_180: - rot_cos = F (-1); rot_sin = F ( 0); - rot_dx = F (mode_w); rot_dy = F ( mode_h); - break; - case RR_Rotate_270: - rot_cos = F ( 0); rot_sin = F (-1); - rot_dx = F ( 0); rot_dy = F ( mode_w); - break; - } - - PictureTransformRotate (&crtc_to_fb, &fb_to_crtc, rot_cos, rot_sin); - PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, rot_dx, rot_dy); - - /* reflection */ - scale_x = F (1); - scale_dx = 0; - scale_y = F (1); - scale_dy = 0; - if (rotation & RR_Reflect_X) - { - 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_Reflect_Y) - { - scale_y = F(-1); - if (rotation & (RR_Rotate_0|RR_Rotate_180)) - scale_dy = F(mode_h); - else - scale_dy = F(mode_w); - } - - PictureTransformScale (&crtc_to_fb, &fb_to_crtc, scale_x, scale_y); - PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, scale_dx, scale_dy); - } + RRTransformPtr transform = NULL; #ifdef RANDR_12_INTERFACE if (crtc->randr_crtc) - { - - RRTransformPtr transform = RRCrtcGetTransform (crtc->randr_crtc); - 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; - } - PictureTransformMultiply (&crtc_to_fb, &transform->transform, &crtc_to_fb); - PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &transform->inverse); - } - } + transform = RRCrtcGetTransform (crtc->randr_crtc); #endif - /* - * If the untranslated transformation is the identity, - * disable the shadow buffer - */ - if (PictureTransformIsIdentity (&crtc_to_fb)) + if (!transform || + !RRComputeTransform (crtc->x, crtc->y, + crtc->mode.HDisplay, crtc->mode.VDisplay, + rotation, + transform, + + &crtc_to_fb, + &f_crtc_to_fb, + &f_fb_to_crtc)) { - PictureTransformInitTranslate (&crtc_to_fb, - F (-crtc->x), F (-crtc->y)); - PictureTransformInitTranslate (&fb_to_crtc, - F ( crtc->x), F ( crtc->y)); + /* + * If the untranslated transformation is the identity, + * disable the shadow buffer + */ xf86RotateDestroy (crtc); crtc->transform_in_use = FALSE; if (new_params) @@ -470,24 +395,18 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) } else { - int width, height, old_width, old_height; - void *shadowData; - PixmapPtr shadow; - - PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, F(crtc->x), F(crtc->y)); - - /* + /* * these are the size of the shadow pixmap, which * matches the mode, not the pre-rotated copy in the * frame buffer */ - width = mode->HDisplay; - height = mode->VDisplay; - shadowData = crtc->rotatedData; - shadow = crtc->rotatedPixmap; - old_width = shadow ? shadow->drawable.width : 0; - old_height = shadow ? shadow->drawable.height : 0; - + int width = mode->HDisplay; + int height = 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) { @@ -522,6 +441,27 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) 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: @@ -537,14 +477,13 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) NULL, old_width, old_height); - if (new_params) - xfree (new_params); return FALSE; } crtc->transform_in_use = TRUE; } crtc->crtc_to_framebuffer = crtc_to_fb; - crtc->framebuffer_to_crtc = fb_to_crtc; + 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; @@ -556,8 +495,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) crtc->bounds.x2 = crtc->mode.HDisplay; crtc->bounds.y1 = 0; crtc->bounds.y2 = crtc->mode.VDisplay; - PictureTransformBounds (&crtc->bounds, &crtc_to_fb); - + pict_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds); + /* All done */ return TRUE; } diff --git a/randr/randrstr.h b/randr/randrstr.h index 792c3d654..5ac983d90 100644 --- a/randr/randrstr.h +++ b/randr/randrstr.h @@ -107,7 +107,8 @@ struct _rrProperty { struct _rrTransform { PictTransform transform; - PictTransform inverse; + struct pict_f_transform f_transform; + struct pict_f_transform f_inverse; PictFilterPtr filter; xFixed *params; int nparams; @@ -134,7 +135,8 @@ struct _rrCrtc { RRTransformRec client_pending_transform; RRTransformRec client_current_transform; PictTransform transform; - PictTransform inverse; + struct pict_f_transform f_transform; + struct pict_f_transform f_inverse; }; struct _rrOutput { @@ -616,14 +618,16 @@ RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height); * 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); /* * Return crtc transform @@ -657,7 +661,8 @@ RRCrtcDestroy (RRCrtcPtr crtc); int RRCrtcTransformSet (RRCrtcPtr crtc, PictTransformPtr transform, - PictTransformPtr inverse, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse, char *filter, int filter_len, xFixed *params, 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); } diff --git a/render/matrix.c b/render/matrix.c index 0d5d96267..a4cde4f18 100644 --- a/render/matrix.c +++ b/render/matrix.c @@ -262,83 +262,15 @@ PictureTransformBounds (BoxPtr b, PictTransformPtr matrix) } } -static const int a[3] = { 3, 3, 2 }; -static const int b[3] = { 2, 1, 1 }; - -static void -to_doubles (double m[3][3], const PictTransformPtr t) -{ - int i, j; - - for (j = 0; j < 3; j++) - for (i = 0; i < 3; i++) - m[j][i] = pixman_fixed_to_double (t->matrix[j][i]); -} - -static Bool -from_doubles (PictTransformPtr t, double m[3][3]) -{ - int i, j; - - for (j = 0; j < 3; j++) - for (i = 0; i < 3; i++) - { - double d = m[j][i]; - if (d < -32767.0 || d > 32767.0) - return FALSE; - d = d * 65536.0 + 0.5; - t->matrix[j][i] = (xFixed) floor (d); - } - return TRUE; -} - -static Bool -invert (double r[3][3], double m[3][3]) -{ - double det; - int i, j; - static int a[3] = { 2, 2, 1 }; - static int b[3] = { 1, 0, 0 }; - - det = 0; - for (i = 0; i < 3; i++) { - double p; - int ai = a[i]; - int bi = b[i]; - p = m[i][0] * (m[ai][2] * m[bi][1] - m[ai][1] * m[bi][2]); - if (i == 1) - p = -p; - det += p; - } - if (det == 0) - return FALSE; - det = 1/det; - for (j = 0; j < 3; j++) { - for (i = 0; i < 3; i++) { - double p; - int ai = a[i]; - int aj = a[j]; - int bi = b[i]; - int bj = b[j]; - - p = m[ai][aj] * m[bi][bj] - m[ai][bj] * m[bi][aj]; - if (((i + j) & 1) != 0) - p = -p; - r[j][i] = det * p; - } - } - return TRUE; -} - _X_EXPORT Bool PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src) { - double m[3][3], r[3][3]; + struct pict_f_transform m, r; - to_doubles (m, src); - if (!invert (r, m)) + pict_f_transform_from_pixman_transform (&m, src); + if (!pict_f_transform_invert (&r, &m)) return FALSE; - if (!from_doubles (dst, r)) + if (!pixman_transform_from_pict_f_transform (dst, &r)) return FALSE; return TRUE; } @@ -464,3 +396,251 @@ xRenderTransform_from_PictTransform (xRenderTransform *render, render->matrix33 = pict->matrix[2][2]; } +/* + * Floating point matrix interfaces + */ + +_X_EXPORT void +pict_f_transform_from_pixman_transform (struct pict_f_transform *ft, + struct pixman_transform *t) +{ + int i, j; + + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]); +} + +_X_EXPORT Bool +pixman_transform_from_pict_f_transform (struct pixman_transform *t, + struct pict_f_transform *ft) +{ + int i, j; + + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + { + double d = ft->m[j][i]; + if (d < -32767.0 || d > 32767.0) + return FALSE; + d = d * 65536.0 + 0.5; + t->matrix[j][i] = (xFixed) floor (d); + } + return TRUE; +} + +static const int a[3] = { 3, 3, 2 }; +static const int b[3] = { 2, 1, 1 }; + +_X_EXPORT Bool +pict_f_transform_invert (struct pict_f_transform *r, + struct pict_f_transform *m) +{ + double det; + int i, j; + static int a[3] = { 2, 2, 1 }; + static int b[3] = { 1, 0, 0 }; + + det = 0; + for (i = 0; i < 3; i++) { + double p; + int ai = a[i]; + int bi = b[i]; + p = m->m[i][0] * (m->m[ai][2] * m->m[bi][1] - m->m[ai][1] * m->m[bi][2]); + if (i == 1) + p = -p; + det += p; + } + if (det == 0) + return FALSE; + det = 1/det; + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) { + double p; + int ai = a[i]; + int aj = a[j]; + int bi = b[i]; + int bj = b[j]; + + p = m->m[ai][aj] * m->m[bi][bj] - m->m[ai][bj] * m->m[bi][aj]; + if (((i + j) & 1) != 0) + p = -p; + r->m[j][i] = det * p; + } + } + return TRUE; +} + +_X_EXPORT Bool +pict_f_transform_point (struct pict_f_transform *t, + struct pict_f_vector *v) +{ + struct pict_f_vector result; + int i, j; + double a; + + for (j = 0; j < 3; j++) + { + a = 0; + for (i = 0; i < 3; i++) + a += t->m[j][i] * v->v[i]; + result.v[j] = a; + } + if (!result.v[2]) + return FALSE; + for (j = 0; j < 2; j++) + v->v[j] = result.v[j] / result.v[2]; + v->v[2] = 1; + return TRUE; +} + +_X_EXPORT void +pict_f_transform_point_3d (struct pict_f_transform *t, + struct pict_f_vector *v) +{ + struct pict_f_vector result; + int i, j; + double a; + + for (j = 0; j < 3; j++) + { + a = 0; + for (i = 0; i < 3; i++) + a += t->m[j][i] * v->v[i]; + result.v[j] = a; + } + *v = result; +} + +_X_EXPORT void +pict_f_transform_multiply (struct pict_f_transform *dst, + struct pict_f_transform *l, struct pict_f_transform *r) +{ + struct pict_f_transform d; + int dx, dy; + int o; + + for (dy = 0; dy < 3; dy++) + for (dx = 0; dx < 3; dx++) + { + double v = 0; + for (o = 0; o < 3; o++) + v += l->m[dy][o] * r->m[o][dx]; + d.m[dy][dx] = v; + } + *dst = d; +} + +_X_EXPORT void +pict_f_transform_init_scale (struct pict_f_transform *t, double sx, double sy) +{ + t->m[0][0] = sx; t->m[0][1] = 0; t->m[0][2] = 0; + t->m[1][0] = 0; t->m[1][1] = sy; t->m[1][2] = 0; + t->m[2][0] = 0; t->m[2][1] = 0; t->m[2][2] = 1; +} + +_X_EXPORT Bool +pict_f_transform_scale (struct pict_f_transform *forward, + struct pict_f_transform *reverse, + double sx, double sy) +{ + struct pict_f_transform t; + + if (sx == 0 || sy == 0) + return FALSE; + + pict_f_transform_init_scale (&t, sx, sy); + pict_f_transform_multiply (forward, &t, forward); + pict_f_transform_init_scale (&t, 1/sx, 1/sy); + pict_f_transform_multiply (reverse, reverse, &t); + return TRUE; +} + +_X_EXPORT void +pict_f_transform_init_rotate (struct pict_f_transform *t, double c, double s) +{ + t->m[0][0] = c; t->m[0][1] = -s; t->m[0][2] = 0; + t->m[1][0] = s; t->m[1][1] = c; t->m[1][2] = 0; + t->m[2][0] = 0; t->m[2][1] = 0; t->m[2][2] = 1; +} + +_X_EXPORT Bool +pict_f_transform_rotate (struct pict_f_transform *forward, + struct pict_f_transform *reverse, + double c, double s) +{ + struct pict_f_transform t; + + pict_f_transform_init_rotate (&t, c, s); + pict_f_transform_multiply (forward, &t, forward); + pict_f_transform_init_rotate (&t, c, -s); + pict_f_transform_multiply (reverse, reverse, &t); + return TRUE; +} + +_X_EXPORT void +pict_f_transform_init_translate (struct pict_f_transform *t, double tx, double ty) +{ + t->m[0][0] = 1; t->m[0][1] = 0; t->m[0][2] = tx; + t->m[1][0] = 0; t->m[1][1] = 1; t->m[1][2] = ty; + t->m[2][0] = 0; t->m[2][1] = 0; t->m[2][2] = 1; +} + +_X_EXPORT Bool +pict_f_transform_translate (struct pict_f_transform *forward, + struct pict_f_transform *reverse, + double tx, double ty) +{ + struct pict_f_transform t; + + pict_f_transform_init_translate (&t, tx, ty); + pict_f_transform_multiply (forward, &t, forward); + pict_f_transform_init_translate (&t, -tx, -ty); + pict_f_transform_multiply (reverse, reverse, &t); + return TRUE; +} + +_X_EXPORT Bool +pict_f_transform_bounds (struct pict_f_transform *t, BoxPtr b) +{ + struct pict_f_vector v[4]; + int i; + int x1, y1, x2, y2; + + v[0].v[0] = b->x1; v[0].v[1] = b->y1; v[0].v[2] = 1; + v[1].v[0] = b->x2; v[1].v[1] = b->y1; v[1].v[2] = 1; + v[2].v[0] = b->x2; v[2].v[1] = b->y2; v[2].v[2] = 1; + v[3].v[0] = b->x1; v[3].v[1] = b->y2; v[3].v[2] = 1; + for (i = 0; i < 4; i++) + { + if (!pict_f_transform_point (t, &v[i])) + return FALSE; + x1 = floor (v[i].v[0]); + y1 = floor (v[i].v[1]); + x2 = ceil (v[i].v[0]); + y2 = ceil (v[i].v[1]); + if (i == 0) + { + b->x1 = x1; b->y1 = y1; + b->x2 = x2; b->y2 = y2; + } + else + { + if (x1 < b->x1) b->x1 = x1; + if (y1 < b->y1) b->y1 = y1; + if (x2 > b->x2) b->x2 = x2; + if (y2 > b->y2) b->y2 = y2; + } + } + return TRUE; +} + +_X_EXPORT void +pict_f_transform_init_identity (struct pict_f_transform *t) +{ + int i, j; + + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + t->m[j][i] = i == j ? 1 : 0; +} diff --git a/render/picturestr.h b/render/picturestr.h index 658e221b4..b18f3168c 100644 --- a/render/picturestr.h +++ b/render/picturestr.h @@ -56,6 +56,14 @@ typedef struct _PictFormat { typedef struct pixman_vector PictVector, *PictVectorPtr; typedef struct pixman_transform PictTransform, *PictTransformPtr; +struct pict_f_vector { + double v[3]; +}; + +struct pict_f_transform { + double m[3][3]; +}; + #define PICT_GRADIENT_STOPTABLE_SIZE 1024 #define SourcePictTypeSolidFill 0 #define SourcePictTypeLinear 1 @@ -745,4 +753,59 @@ void xRenderTransform_from_PictTransform (xRenderTransform *render, PictTransformPtr pict); +void +pict_f_transform_from_pixman_transform (struct pict_f_transform *ft, + struct pixman_transform *t); + +Bool +pixman_transform_from_pict_f_transform (struct pixman_transform *t, + struct pict_f_transform *ft); + +Bool +pict_f_transform_invert (struct pict_f_transform *r, + struct pict_f_transform *m); + + +Bool +pict_f_transform_point (struct pict_f_transform *t, + struct pict_f_vector *v); + +void +pict_f_transform_point_3d (struct pict_f_transform *t, + struct pict_f_vector *v); + +void +pict_f_transform_multiply (struct pict_f_transform *dst, + struct pict_f_transform *l, struct pict_f_transform *r); + +void +pict_f_transform_init_scale (struct pict_f_transform *t, double sx, double sy); + +Bool +pict_f_transform_scale (struct pict_f_transform *forward, + struct pict_f_transform *reverse, + double sx, double sy); + +void +pict_f_transform_init_rotate (struct pict_f_transform *t, double c, double s); + +Bool +pict_f_transform_rotate (struct pict_f_transform *forward, + struct pict_f_transform *reverse, + double c, double s); + +void +pict_f_transform_init_translate (struct pict_f_transform *t, double tx, double ty); + +Bool +pict_f_transform_translate (struct pict_f_transform *forward, + struct pict_f_transform *reverse, + double tx, double ty); + +Bool +pict_f_transform_bounds (struct pict_f_transform *t, BoxPtr b); + +void +pict_f_transform_init_identity (struct pict_f_transform *t); + #endif /* _PICTURESTR_H_ */ |