diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h index ef8589ed1..a5bb11b12 100644 --- a/hw/xfree86/modes/xf86Crtc.h +++ b/hw/xfree86/modes/xf86Crtc.h @@ -306,6 +306,9 @@ struct _xf86Crtc { */ PictTransform crtc_to_framebuffer; PictTransform framebuffer_to_crtc; + PictFilterPtr filter; + xFixed *params; + int nparams; Bool transform_in_use; /** * Bounding box in screen space diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c index 7967e5b28..f201ae3be 100644 --- a/hw/xfree86/modes/xf86Rotate.c +++ b/hw/xfree86/modes/xf86Rotate.c @@ -109,6 +109,9 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) error = SetPictureTransform (src, &crtc->crtc_to_framebuffer); if (error) return; + if (crtc->transform_in_use && crtc->filter) + SetPicturePictFilter (src, crtc->filter, + crtc->params, crtc->nparams); while (n--) { @@ -380,13 +383,33 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) } #ifdef RANDR_12_INTERFACE + if (crtc->randr_crtc) { - PictTransform user_forward, user_reverse; - if (crtc->randr_crtc && RRCrtcGetTransform (crtc->randr_crtc, &user_forward, &user_reverse)) + xFixed *new_params = NULL; + int new_nparams = 0; + PictFilterPtr new_filter = NULL; + + RRTransformPtr transform = RRCrtcGetTransform (crtc->randr_crtc); + if (transform) { - PictureTransformMultiply (&crtc_to_fb, &user_forward, &crtc_to_fb); - PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &user_reverse); + 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; + PictureTransformMultiply (&crtc_to_fb, &transform->transform, &crtc_to_fb); + PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &transform->inverse); } + if (crtc->params) + xfree (crtc->params); + crtc->params = new_params; + crtc->nparams = new_nparams; + crtc->filter = new_filter; } #endif /* diff --git a/randr/randrstr.h b/randr/randrstr.h index 320e9f742..cdaebe9bb 100644 --- a/randr/randrstr.h +++ b/randr/randrstr.h @@ -78,6 +78,7 @@ typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr; typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; typedef struct _rrOutput RROutputRec, *RROutputPtr; +typedef struct _rrTransform RRTransformRec, *RRTransformPtr; struct _rrMode { int refcnt; @@ -104,6 +105,14 @@ struct _rrProperty { RRPropertyValueRec current, pending; }; +struct _rrTransform { + PictTransform transform; + PictTransform inverse; + PictFilterPtr filter; + xFixed *params; + int nparams; +}; + struct _rrCrtc { RRCrtc id; ScreenPtr pScreen; @@ -119,10 +128,8 @@ struct _rrCrtc { CARD16 *gammaBlue; CARD16 *gammaGreen; void *devPrivate; - PictTransform client_pending_transform; - PictTransform client_pending_inverse; - PictTransform client_current_transform; - PictTransform client_current_inverse; + RRTransformRec client_pending_transform; + RRTransformRec client_current_transform; PictTransform transform; PictTransform inverse; }; @@ -612,10 +619,8 @@ RRComputeTransform (RRModePtr mode, /* * Return crtc transform */ -Bool -RRCrtcGetTransform (RRCrtcPtr crtc, - PictTransformPtr crtc_to_fb, - PictTransformPtr fb_to_crtc); +RRTransformPtr +RRCrtcGetTransform (RRCrtcPtr crtc); /* * Mark the pending transform as current @@ -643,7 +648,11 @@ RRCrtcDestroy (RRCrtcPtr crtc); int RRCrtcTransformSet (RRCrtcPtr crtc, PictTransformPtr transform, - PictTransformPtr inverse); + PictTransformPtr inverse, + char *filter, + int filter_len, + xFixed *params, + int nparams); /* * Initialize crtc type diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index 0cb863849..e3ba4f821 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -48,6 +48,52 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) } } +static void +RRTransformInit (RRTransformPtr transform) +{ + PictureTransformInitIdentity (&transform->transform); + PictureTransformInitIdentity (&transform->inverse); + transform->filter = NULL; + transform->params = NULL; + transform->nparams = 0; +} + +static Bool +RRTransformSetFilter (RRTransformPtr dst, + PictFilterPtr filter, + xFixed *params, + int nparams) +{ + xFixed *new_params; + + if (nparams) + { + new_params = xalloc (nparams * sizeof (xFixed)); + if (!new_params) + return FALSE; + memcpy (new_params, params, nparams * sizeof (xFixed)); + } + else + new_params = NULL; + if (dst->params) + xfree (dst->params); + dst->filter = filter; + dst->params = new_params; + dst->nparams = nparams; + return TRUE; +} + +static Bool +RRTransformCopy (RRTransformPtr dst, RRTransformPtr src) +{ + if (!RRTransformSetFilter (dst, src->filter, + src->params, src->nparams)) + return FALSE; + dst->transform = src->transform; + dst->inverse = src->inverse; + return TRUE; +} + /* * Create a CRTC */ @@ -89,10 +135,8 @@ 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); + RRTransformInit (&crtc->client_pending_transform); + RRTransformInit (&crtc->client_current_transform); PictureTransformInitIdentity (&crtc->transform); PictureTransformInitIdentity (&crtc->inverse); @@ -368,14 +412,14 @@ RRCrtcSet (RRCrtcPtr crtc, /* * Return crtc transform */ -Bool -RRCrtcGetTransform (RRCrtcPtr crtc, - PictTransformPtr crtc_to_fb, - PictTransformPtr fb_to_crtc) +RRTransformPtr +RRCrtcGetTransform (RRCrtcPtr crtc) { - *crtc_to_fb = crtc->client_pending_transform; - *fb_to_crtc = crtc->client_pending_inverse; - return !PictureTransformIsIdentity (crtc_to_fb); + RRTransformPtr transform = &crtc->client_pending_transform; + + if (PictureTransformIsIdentity (&transform->transform)) + return NULL; + return transform; } /* @@ -384,11 +428,11 @@ RRCrtcGetTransform (RRCrtcPtr crtc, void RRCrtcPostPendingTransform (RRCrtcPtr crtc) { - crtc->client_current_transform = crtc->client_pending_transform; - crtc->client_current_inverse = crtc->client_pending_inverse; + RRTransformCopy (&crtc->client_current_transform, + &crtc->client_pending_transform); RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y, - &crtc->client_current_transform, - &crtc->client_current_inverse, + &crtc->client_current_transform.transform, + &crtc->client_current_transform.inverse, &crtc->transform, &crtc->inverse); } @@ -399,8 +443,8 @@ RRCrtcPostPendingTransform (RRCrtcPtr crtc) Bool RRCrtcPendingTransform (RRCrtcPtr crtc) { - return memcmp (&crtc->client_current_transform, - &crtc->client_pending_transform, + return memcmp (&crtc->client_current_transform.transform, + &crtc->client_pending_transform.transform, sizeof (PictTransform)) != 0; } @@ -546,12 +590,41 @@ RRCrtcGammaSetSize (RRCrtcPtr crtc, int RRCrtcTransformSet (RRCrtcPtr crtc, PictTransformPtr transform, - PictTransformPtr inverse) + PictTransformPtr inverse, + char *filter_name, + int filter_len, + xFixed *params, + int nparams) { + PictFilterPtr filter = NULL; + if (!PictureTransformIsInverse (transform, inverse)) return BadMatch; - crtc->client_pending_transform = *transform; - crtc->client_pending_inverse = *inverse; + if (filter_len) + { + filter = PictureFindFilter (crtc->pScreen, + filter_name, + filter_len); + if (!filter) + return BadName; + if (filter->ValidateParams) + { + if (!filter->ValidateParams (crtc->pScreen, filter->id, + params, nparams)) + return BadMatch; + } + } + else + { + if (nparams) + return BadMatch; + } + if (!RRTransformSetFilter (&crtc->client_pending_transform, + filter, params, nparams)) + return BadAlloc; + + crtc->client_pending_transform.transform = *transform; + crtc->client_pending_transform.inverse = *inverse; return Success; } @@ -1128,8 +1201,12 @@ ProcRRSetCrtcTransform (ClientPtr client) REQUEST(xRRSetCrtcTransformReq); RRCrtcPtr crtc; PictTransform transform, inverse; + char *filter; + int nbytes; + xFixed *params; + int nparams; - REQUEST_SIZE_MATCH (xRRSetCrtcTransformReq); + REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess); if (!crtc) return RRErrorBase + BadRRCrtc; @@ -1137,42 +1214,124 @@ ProcRRSetCrtcTransform (ClientPtr client) PictTransform_from_xRenderTransform (&transform, &stuff->transform); PictTransform_from_xRenderTransform (&inverse, &stuff->inverse); - return RRCrtcTransformSet (crtc, &transform, &inverse); + filter = (char *) (stuff + 1); + nbytes = stuff->nbytesFilter; + params = (xFixed *) (filter + ((nbytes + 3) & ~3)); + nparams = ((xFixed *) stuff + client->req_len) - params; + if (nparams < 0) + return BadLength; + + return RRCrtcTransformSet (crtc, &transform, &inverse, + filter, nbytes, params, nparams); } #define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) +static int +transform_filter_length (RRTransformPtr transform) +{ + int nbytes, nparams; + + if (transform->filter == NULL) + return 0; + nbytes = strlen (transform->filter->name); + nparams = transform->nparams; + return ((nbytes + 3) & ~3) + (nparams * sizeof (xFixed)); +} + +static int +transform_filter_encode (ClientPtr client, char *output, + CARD16 *nbytesFilter, + CARD16 *nparamsFilter, + RRTransformPtr transform) +{ + char *output_orig = output; + int nbytes, nparams; + int n; + + if (transform->filter == NULL) { + *nbytesFilter = 0; + *nparamsFilter = 0; + return 0; + } + nbytes = strlen (transform->filter->name); + nparams = transform->nparams; + *nbytesFilter = nbytes; + *nparamsFilter = nparams; + memcpy (output, transform->filter->name, nbytes); + output += nbytes; + while ((nbytes & 3) != 0) + *output++ = 0; + memcpy (output, transform->params, nparams * sizeof (xFixed)); + if (client->swapped) { + swaps (nbytesFilter, n); + swaps (nparamsFilter, n); + SwapLongs ((CARD32 *) output, nparams * sizeof (xFixed)); + } + output += nparams * sizeof (xFixed); + return output - output_orig; +} + +static void +transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict) +{ + xRenderTransform_from_PictTransform (wire, pict); + if (client->swapped) + SwapLongs ((CARD32 *) wire, sizeof (xRenderTransform)); +} + int ProcRRGetCrtcTransform (ClientPtr client) { REQUEST(xRRGetCrtcTransformReq); - xRRGetCrtcTransformReply reply; + xRRGetCrtcTransformReply *reply; RRCrtcPtr crtc; - int n; + int n, nextra; + RRTransformPtr current, pending; + char *extra; 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); + pending = &crtc->client_pending_transform; + current = &crtc->client_current_transform; + + nextra = (transform_filter_length (pending) + + transform_filter_length (current)); + + reply = xalloc (sizeof (xRRGetCrtcTransformReply) + nextra); + if (!reply) + return BadAlloc; + + extra = (char *) (reply + 1); + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (CrtcTransformExtra + nextra) >> 2; + + /* XXX deal with DDXen that can't do transforms */ + reply->hasTransforms = xTrue; + + transform_encode (client, &reply->pendingTransform, &pending->transform); + transform_encode (client, &reply->pendingInverse, &pending->inverse); + extra += transform_filter_encode (client, extra, + &reply->pendingNbytesFilter, + &reply->pendingNparamsFilter, + pending); + + transform_encode (client, &reply->currentTransform, ¤t->transform); + transform_encode (client, &reply->currentInverse, ¤t->inverse); + extra += transform_filter_encode (client, extra, + &reply->currentNbytesFilter, + &reply->currentNparamsFilter, + current); + if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - SwapLongs ((CARD32 *) &reply.pendingTransform, 40); + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); } - WriteToClient (client, sizeof (xRRGetCrtcTransformReply), (char *) &reply); + WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply); return client->noClientException; }