[RANDR] Support filters in CRTC transforms.

Create new RRTransform datatype to hold all of the transform related
information, use that in lots of places to pass filters around.
This commit is contained in:
Keith Packard 2008-03-15 00:36:45 -07:00
parent acda790e43
commit f50349e193
4 changed files with 247 additions and 53 deletions

View File

@ -306,6 +306,9 @@ struct _xf86Crtc {
*/ */
PictTransform crtc_to_framebuffer; PictTransform crtc_to_framebuffer;
PictTransform framebuffer_to_crtc; PictTransform framebuffer_to_crtc;
PictFilterPtr filter;
xFixed *params;
int nparams;
Bool transform_in_use; Bool transform_in_use;
/** /**
* Bounding box in screen space * Bounding box in screen space

View File

@ -109,6 +109,9 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
error = SetPictureTransform (src, &crtc->crtc_to_framebuffer); error = SetPictureTransform (src, &crtc->crtc_to_framebuffer);
if (error) if (error)
return; return;
if (crtc->transform_in_use && crtc->filter)
SetPicturePictFilter (src, crtc->filter,
crtc->params, crtc->nparams);
while (n--) while (n--)
{ {
@ -380,13 +383,33 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
} }
#ifdef RANDR_12_INTERFACE #ifdef RANDR_12_INTERFACE
if (crtc->randr_crtc)
{ {
PictTransform user_forward, user_reverse; xFixed *new_params = NULL;
if (crtc->randr_crtc && RRCrtcGetTransform (crtc->randr_crtc, &user_forward, &user_reverse)) 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); if (transform->nparams) {
PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &user_reverse); 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 #endif
/* /*

View File

@ -78,6 +78,7 @@ typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr;
typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr;
typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
typedef struct _rrOutput RROutputRec, *RROutputPtr; typedef struct _rrOutput RROutputRec, *RROutputPtr;
typedef struct _rrTransform RRTransformRec, *RRTransformPtr;
struct _rrMode { struct _rrMode {
int refcnt; int refcnt;
@ -104,6 +105,14 @@ struct _rrProperty {
RRPropertyValueRec current, pending; RRPropertyValueRec current, pending;
}; };
struct _rrTransform {
PictTransform transform;
PictTransform inverse;
PictFilterPtr filter;
xFixed *params;
int nparams;
};
struct _rrCrtc { struct _rrCrtc {
RRCrtc id; RRCrtc id;
ScreenPtr pScreen; ScreenPtr pScreen;
@ -119,10 +128,8 @@ struct _rrCrtc {
CARD16 *gammaBlue; CARD16 *gammaBlue;
CARD16 *gammaGreen; CARD16 *gammaGreen;
void *devPrivate; void *devPrivate;
PictTransform client_pending_transform; RRTransformRec client_pending_transform;
PictTransform client_pending_inverse; RRTransformRec client_current_transform;
PictTransform client_current_transform;
PictTransform client_current_inverse;
PictTransform transform; PictTransform transform;
PictTransform inverse; PictTransform inverse;
}; };
@ -612,10 +619,8 @@ RRComputeTransform (RRModePtr mode,
/* /*
* Return crtc transform * Return crtc transform
*/ */
Bool RRTransformPtr
RRCrtcGetTransform (RRCrtcPtr crtc, RRCrtcGetTransform (RRCrtcPtr crtc);
PictTransformPtr crtc_to_fb,
PictTransformPtr fb_to_crtc);
/* /*
* Mark the pending transform as current * Mark the pending transform as current
@ -643,7 +648,11 @@ RRCrtcDestroy (RRCrtcPtr crtc);
int int
RRCrtcTransformSet (RRCrtcPtr crtc, RRCrtcTransformSet (RRCrtcPtr crtc,
PictTransformPtr transform, PictTransformPtr transform,
PictTransformPtr inverse); PictTransformPtr inverse,
char *filter,
int filter_len,
xFixed *params,
int nparams);
/* /*
* Initialize crtc type * Initialize crtc type

View File

@ -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 * Create a CRTC
*/ */
@ -89,10 +135,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
crtc->changed = FALSE; crtc->changed = FALSE;
crtc->devPrivate = devPrivate; crtc->devPrivate = devPrivate;
PictureTransformInitIdentity (&crtc->client_pending_transform); RRTransformInit (&crtc->client_pending_transform);
PictureTransformInitIdentity (&crtc->client_pending_inverse); RRTransformInit (&crtc->client_current_transform);
PictureTransformInitIdentity (&crtc->client_current_transform);
PictureTransformInitIdentity (&crtc->client_current_inverse);
PictureTransformInitIdentity (&crtc->transform); PictureTransformInitIdentity (&crtc->transform);
PictureTransformInitIdentity (&crtc->inverse); PictureTransformInitIdentity (&crtc->inverse);
@ -368,14 +412,14 @@ RRCrtcSet (RRCrtcPtr crtc,
/* /*
* Return crtc transform * Return crtc transform
*/ */
Bool RRTransformPtr
RRCrtcGetTransform (RRCrtcPtr crtc, RRCrtcGetTransform (RRCrtcPtr crtc)
PictTransformPtr crtc_to_fb,
PictTransformPtr fb_to_crtc)
{ {
*crtc_to_fb = crtc->client_pending_transform; RRTransformPtr transform = &crtc->client_pending_transform;
*fb_to_crtc = crtc->client_pending_inverse;
return !PictureTransformIsIdentity (crtc_to_fb); if (PictureTransformIsIdentity (&transform->transform))
return NULL;
return transform;
} }
/* /*
@ -384,11 +428,11 @@ RRCrtcGetTransform (RRCrtcPtr crtc,
void void
RRCrtcPostPendingTransform (RRCrtcPtr crtc) RRCrtcPostPendingTransform (RRCrtcPtr crtc)
{ {
crtc->client_current_transform = crtc->client_pending_transform; RRTransformCopy (&crtc->client_current_transform,
crtc->client_current_inverse = crtc->client_pending_inverse; &crtc->client_pending_transform);
RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y, RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y,
&crtc->client_current_transform, &crtc->client_current_transform.transform,
&crtc->client_current_inverse, &crtc->client_current_transform.inverse,
&crtc->transform, &crtc->transform,
&crtc->inverse); &crtc->inverse);
} }
@ -399,8 +443,8 @@ RRCrtcPostPendingTransform (RRCrtcPtr crtc)
Bool Bool
RRCrtcPendingTransform (RRCrtcPtr crtc) RRCrtcPendingTransform (RRCrtcPtr crtc)
{ {
return memcmp (&crtc->client_current_transform, return memcmp (&crtc->client_current_transform.transform,
&crtc->client_pending_transform, &crtc->client_pending_transform.transform,
sizeof (PictTransform)) != 0; sizeof (PictTransform)) != 0;
} }
@ -546,12 +590,41 @@ RRCrtcGammaSetSize (RRCrtcPtr crtc,
int int
RRCrtcTransformSet (RRCrtcPtr crtc, RRCrtcTransformSet (RRCrtcPtr crtc,
PictTransformPtr transform, PictTransformPtr transform,
PictTransformPtr inverse) PictTransformPtr inverse,
char *filter_name,
int filter_len,
xFixed *params,
int nparams)
{ {
PictFilterPtr filter = NULL;
if (!PictureTransformIsInverse (transform, inverse)) if (!PictureTransformIsInverse (transform, inverse))
return BadMatch; return BadMatch;
crtc->client_pending_transform = *transform; if (filter_len)
crtc->client_pending_inverse = *inverse; {
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; return Success;
} }
@ -1128,8 +1201,12 @@ ProcRRSetCrtcTransform (ClientPtr client)
REQUEST(xRRSetCrtcTransformReq); REQUEST(xRRSetCrtcTransformReq);
RRCrtcPtr crtc; RRCrtcPtr crtc;
PictTransform transform, inverse; 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); crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
if (!crtc) if (!crtc)
return RRErrorBase + BadRRCrtc; return RRErrorBase + BadRRCrtc;
@ -1137,42 +1214,124 @@ ProcRRSetCrtcTransform (ClientPtr client)
PictTransform_from_xRenderTransform (&transform, &stuff->transform); PictTransform_from_xRenderTransform (&transform, &stuff->transform);
PictTransform_from_xRenderTransform (&inverse, &stuff->inverse); 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) #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 int
ProcRRGetCrtcTransform (ClientPtr client) ProcRRGetCrtcTransform (ClientPtr client)
{ {
REQUEST(xRRGetCrtcTransformReq); REQUEST(xRRGetCrtcTransformReq);
xRRGetCrtcTransformReply reply; xRRGetCrtcTransformReply *reply;
RRCrtcPtr crtc; RRCrtcPtr crtc;
int n; int n, nextra;
RRTransformPtr current, pending;
char *extra;
REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq); REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq);
crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess); crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
if (!crtc) if (!crtc)
return RRErrorBase + BadRRCrtc; return RRErrorBase + BadRRCrtc;
reply.type = X_Reply; pending = &crtc->client_pending_transform;
reply.sequenceNumber = client->sequence; current = &crtc->client_current_transform;
reply.length = CrtcTransformExtra >> 2;
nextra = (transform_filter_length (pending) +
xRenderTransform_from_PictTransform (&reply.pendingTransform, transform_filter_length (current));
&crtc->client_pending_transform);
xRenderTransform_from_PictTransform (&reply.pendingInverse, reply = xalloc (sizeof (xRRGetCrtcTransformReply) + nextra);
&crtc->client_pending_inverse); if (!reply)
xRenderTransform_from_PictTransform (&reply.currentTransform, return BadAlloc;
&crtc->client_current_transform);
xRenderTransform_from_PictTransform (&reply.currentInverse, extra = (char *) (reply + 1);
&crtc->client_current_inverse); 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, &current->transform);
transform_encode (client, &reply->currentInverse, &current->inverse);
extra += transform_filter_encode (client, extra,
&reply->currentNbytesFilter,
&reply->currentNparamsFilter,
current);
if (client->swapped) { if (client->swapped) {
swaps (&reply.sequenceNumber, n); swaps (&reply->sequenceNumber, n);
swapl (&reply.length, n); swapl (&reply->length, n);
SwapLongs ((CARD32 *) &reply.pendingTransform, 40);
} }
WriteToClient (client, sizeof (xRRGetCrtcTransformReply), (char *) &reply); WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply);
return client->noClientException; return client->noClientException;
} }