summaryrefslogtreecommitdiff
path: root/randr/rrcrtc.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-03-13 21:31:12 -0700
committerKeith Packard <keithp@keithp.com>2008-11-24 13:24:36 -0800
commite3d6f279d5c305dfb81ca109fbfb665870712d2f (patch)
treebc08da754654f5858bd212a99f085a735e49c6fe /randr/rrcrtc.c
parentff9d1cd843a9b0aba69a3d788b21d5f6af702590 (diff)
Wire up RandR CRTC transform protocol, bump server to RandR 1.3
This involved removing a pile of matrix code from the DDX, as well as moving a bit of transform logic from DDX to DIX.
Diffstat (limited to 'randr/rrcrtc.c')
-rw-r--r--randr/rrcrtc.c203
1 files changed, 201 insertions, 2 deletions
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 38b34525c..0cb863849 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -89,6 +89,12 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
crtc->changed = FALSE;
crtc->devPrivate = devPrivate;
+ PictureTransformInitIdentity (&crtc->client_pending_transform);
+ PictureTransformInitIdentity (&crtc->client_pending_inverse);
+ PictureTransformInitIdentity (&crtc->client_current_transform);
+ PictureTransformInitIdentity (&crtc->client_current_inverse);
+ PictureTransformInitIdentity (&crtc->transform);
+ PictureTransformInitIdentity (&crtc->inverse);
if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
return NULL;
@@ -290,7 +296,8 @@ RRCrtcSet (RRCrtcPtr crtc,
crtc->rotation == rotation &&
crtc->numOutputs == numOutputs &&
!memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
- !RRCrtcPendingProperties (crtc))
+ !RRCrtcPendingProperties (crtc) &&
+ !RRCrtcPendingTransform (crtc))
{
ret = TRUE;
}
@@ -366,7 +373,9 @@ RRCrtcGetTransform (RRCrtcPtr crtc,
PictTransformPtr crtc_to_fb,
PictTransformPtr fb_to_crtc)
{
- return FALSE;
+ *crtc_to_fb = crtc->client_pending_transform;
+ *fb_to_crtc = crtc->client_pending_inverse;
+ return !PictureTransformIsIdentity (crtc_to_fb);
}
/*
@@ -375,6 +384,24 @@ RRCrtcGetTransform (RRCrtcPtr crtc,
void
RRCrtcPostPendingTransform (RRCrtcPtr crtc)
{
+ crtc->client_current_transform = crtc->client_pending_transform;
+ crtc->client_current_inverse = crtc->client_pending_inverse;
+ RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y,
+ &crtc->client_current_transform,
+ &crtc->client_current_inverse,
+ &crtc->transform,
+ &crtc->inverse);
+}
+
+/*
+ * Check whether the pending and current transforms are the same
+ */
+Bool
+RRCrtcPendingTransform (RRCrtcPtr crtc)
+{
+ return memcmp (&crtc->client_current_transform,
+ &crtc->client_pending_transform,
+ sizeof (PictTransform)) != 0;
}
/*
@@ -513,6 +540,122 @@ RRCrtcGammaSetSize (RRCrtcPtr crtc,
}
/*
+ * Set the pending CRTC transformation
+ */
+
+int
+RRCrtcTransformSet (RRCrtcPtr crtc,
+ PictTransformPtr transform,
+ PictTransformPtr inverse)
+{
+ if (!PictureTransformIsInverse (transform, inverse))
+ return BadMatch;
+ crtc->client_pending_transform = *transform;
+ crtc->client_pending_inverse = *inverse;
+ return Success;
+}
+
+#define F(x) IntToxFixed(x)
+
+/*
+ * Compute the complete transformation matrix including
+ * client-specified transform, rotation/reflection values and the crtc
+ * offset.
+ *
+ * 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)
+{
+ PictureTransformInitIdentity (transform);
+ PictureTransformInitIdentity (inverse);
+ 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 = mode->mode.width;
+ int mode_h = mode->mode.height;
+
+ /* 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 (inverse, transform, rot_cos, rot_sin);
+ PictureTransformTranslate (inverse, transform, 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 (inverse, transform, scale_x, scale_y);
+ PictureTransformTranslate (inverse, transform, scale_dx, scale_dy);
+ }
+
+#ifdef RANDR_12_INTERFACE
+ {
+ PictureTransformMultiply (inverse, client_inverse, inverse);
+ PictureTransformMultiply (transform, transform, client_transform);
+ }
+#endif
+ /*
+ * Compute the class of the resulting transform
+ */
+ if (PictureTransformIsIdentity (transform))
+ {
+ PictureTransformInitTranslate (inverse, F (-x), F (-y));
+ PictureTransformInitTranslate (transform, F ( x), F ( y));
+ return FALSE;
+ }
+ else
+ {
+ PictureTransformTranslate (inverse, transform, x, y);
+ return TRUE;
+ }
+}
+
+/*
* Initialize crtc type
*/
Bool
@@ -977,3 +1120,59 @@ ProcRRSetCrtcGamma (ClientPtr client)
return Success;
}
+/* Version 1.3 additions */
+
+int
+ProcRRSetCrtcTransform (ClientPtr client)
+{
+ REQUEST(xRRSetCrtcTransformReq);
+ RRCrtcPtr crtc;
+ PictTransform transform, inverse;
+
+ REQUEST_SIZE_MATCH (xRRSetCrtcTransformReq);
+ crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
+ if (!crtc)
+ return RRErrorBase + BadRRCrtc;
+
+ PictTransform_from_xRenderTransform (&transform, &stuff->transform);
+ PictTransform_from_xRenderTransform (&inverse, &stuff->inverse);
+
+ return RRCrtcTransformSet (crtc, &transform, &inverse);
+}
+
+
+#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32)
+
+int
+ProcRRGetCrtcTransform (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcTransformReq);
+ xRRGetCrtcTransformReply reply;
+ RRCrtcPtr crtc;
+ int n;
+
+ REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq);
+ crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
+ if (!crtc)
+ return RRErrorBase + BadRRCrtc;
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = CrtcTransformExtra >> 2;
+
+ xRenderTransform_from_PictTransform (&reply.pendingTransform,
+ &crtc->client_pending_transform);
+ xRenderTransform_from_PictTransform (&reply.pendingInverse,
+ &crtc->client_pending_inverse);
+ xRenderTransform_from_PictTransform (&reply.currentTransform,
+ &crtc->client_current_transform);
+ xRenderTransform_from_PictTransform (&reply.currentInverse,
+ &crtc->client_current_inverse);
+ if (client->swapped) {
+ swaps (&reply.sequenceNumber, n);
+ swapl (&reply.length, n);
+ SwapLongs ((CARD32 *) &reply.pendingTransform, 40);
+ }
+ WriteToClient (client, sizeof (xRRGetCrtcTransformReply), (char *) &reply);
+ return client->noClientException;
+}