[PATCH] Handle RandR transform matrices in floating point.
Keith Packard
keithp at keithp.com
Fri Nov 14 14:12:48 PST 2008
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.
---
hw/xfree86/modes/xf86Crtc.c | 3 +-
hw/xfree86/modes/xf86Crtc.h | 3 +-
hw/xfree86/modes/xf86Cursors.c | 16 +-
hw/xfree86/modes/xf86Rotate.c | 167 +++++++--------------
randr/randrstr.h | 27 ++--
randr/rrcrtc.c | 136 ++++++++++++------
render/matrix.c | 324 +++++++++++++++++++++++++++++++---------
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 f977152..f33a228 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 d093b1a..026ec78 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 7bf9265..4065789 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 7b49afa..efbacec 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 792c3d6..5ac983d 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 e0fafce..d7ea6f2 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 0d5d962..a4cde4f 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 658e221..b18f316 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_ */
--
1.5.6.5
More information about the xorg
mailing list