summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-03-15 00:35:08 -0700
committerKeith Packard <keithp@keithp.com>2008-03-15 00:35:08 -0700
commitbed3da4feaa505a5b50a4c94b0e6661bdac1fcbd (patch)
tree9a73bdbd610514216b4f9a725faade69cc11b79d
parentba35bb5d306f4edf9a47b92f249132a0814f5db1 (diff)
Manage transform filters. Use bilinear for non-identity scale.
This involved creating a compound transform datatype to hold all of the relevant transform and filter information. Adding arbitrary transforms should be fairly easy at this point.
-rw-r--r--xrandr.c159
1 files changed, 113 insertions, 46 deletions
diff --git a/xrandr.c b/xrandr.c
index 8e2be59..9bb7f2d 100644
--- a/xrandr.c
+++ b/xrandr.c
@@ -238,9 +238,18 @@ typedef struct {
typedef struct _crtc crtc_t;
typedef struct _output output_t;
+typedef struct _transform transform_t;
typedef struct _umode umode_t;
typedef struct _output_prop output_prop_t;
+struct _transform {
+ XTransform transform;
+ XTransform inverse;
+ char *filter;
+ int nparams;
+ XFixed *params;
+};
+
struct _crtc {
name_t crtc;
Bool changing;
@@ -252,8 +261,7 @@ struct _crtc {
Rotation rotation;
output_t **outputs;
int noutput;
- XTransform current_transform, current_inverse;
- XTransform pending_transform, pending_inverse;
+ transform_t current_transform, pending_transform;
};
struct _output_prop {
@@ -289,7 +297,7 @@ struct _output {
Rotation rotation;
Bool automatic;
- XTransform transform, inverse;
+ transform_t transform;
};
typedef enum _umode_action {
@@ -456,6 +464,58 @@ set_name (name_t *name, char *string, name_kind_t valid)
usage ();
}
+static void
+init_transform (transform_t *transform)
+{
+ int x;
+ memset (&transform->transform, '\0', sizeof (transform->transform));
+ memset (&transform->inverse, '\0', sizeof (transform->inverse));
+ for (x = 0; x < 3; x++)
+ transform->transform.matrix[x][x] = transform->inverse.matrix[x][x] = XDoubleToFixed (1.0);
+ transform->filter = "";
+ transform->nparams = 0;
+ transform->params = NULL;
+}
+
+static void
+set_transform (transform_t *dest,
+ XTransform *transform,
+ XTransform *inverse,
+ char *filter,
+ XFixed *params,
+ int nparams)
+{
+ dest->transform = *transform;
+ dest->inverse = *inverse;
+ dest->filter = strdup (filter);
+ dest->nparams = nparams;
+ dest->params = malloc (nparams * sizeof (XFixed));
+ memcpy (dest->params, params, nparams * sizeof (XFixed));
+}
+
+static void
+copy_transform (transform_t *dest, transform_t *src)
+{
+ set_transform (dest, &src->transform, &src->inverse,
+ src->filter, src->params, src->nparams);
+}
+
+static Bool
+equal_transform (transform_t *a, transform_t *b)
+{
+ if (memcmp (&a->transform, &b->transform, sizeof (XTransform)) != 0)
+ return False;
+ if (memcmp (&a->inverse, &b->inverse, sizeof (XTransform)) != 0)
+ return False;
+ if (strcmp (a->filter, b->filter) != 0)
+ return False;
+ if (a->nparams != b->nparams)
+ return False;
+ if (memcmp (a->params, b->params, a->nparams * sizeof (XFixed)) != 0)
+ return False;
+ return True;
+}
+
static output_t *
add_output (void)
{
@@ -874,18 +934,9 @@ set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
if (!(output->changes & changes_transform))
{
if (output->crtc_info)
- {
- output->transform = output->crtc_info->current_transform;
- output->inverse = output->crtc_info->current_inverse;
- }
+ copy_transform (&output->transform, &output->crtc_info->current_transform);
else
- {
- int x;
- memset (&output->transform, '\0', sizeof (output->transform));
- memset (&output->inverse, '\0', sizeof (output->inverse));
- for (x = 0; x < 3; x++)
- output->transform.matrix[x][x] = output->inverse.matrix[x][x] = XDoubleToFixed (1.0);
- }
+ init_transform (&output->transform);
}
}
@@ -914,6 +965,9 @@ get_crtcs (void)
for (c = 0; c < res->ncrtc; c++)
{
XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]);
+#if RANDR_MAJOR > 1 || RANDR_MINOR >= 3
+ XRRCrtcTransformAttributes *attr;
+#endif
int x;
set_name_xid (&crtcs[c].crtc, res->crtcs[c]);
set_name_index (&crtcs[c].crtc, c);
@@ -927,19 +981,23 @@ get_crtcs (void)
crtcs[c].rotation = RR_Rotate_0;
}
#if RANDR_MAJOR > 1 || RANDR_MINOR >= 3
- XRRGetCrtcTransform (dpy, res->crtcs[c],
- NULL, NULL,
- &crtcs[c].current_transform,
- &crtcs[c].current_inverse);
-#else
- memset (&crtcs[c].current_transform, '\0', sizeof (crtcs[c].current_transform));
- memset (&crtcs[c].current_inverse, '\0', sizeof (crtcs[c].current_inverse));
- for (x = 0; x < 3; x++)
- crtcs[c].current_transform.matrix[x][x] = crtcs[c].current_inverse.matrix[x][x] = XDoubleToFixed (1.0);
+ XRRGetCrtcTransform (dpy, res->crtcs[c], &attr);
+ if (attr) {
+ set_transform (&crtcs[c].current_transform,
+ &attr->currentTransform,
+ &attr->currentInverse,
+ attr->currentFilter,
+ attr->currentParams,
+ attr->currentNparams);
+ XFree (attr);
+ }
+ else
#endif
- crtcs[c].pending_transform = crtcs[c].current_transform;
- crtcs[c].pending_inverse = crtcs[c].current_inverse;
- }
+ {
+ init_transform (&crtcs[c].current_transform);
+ }
+ copy_transform (&crtcs[c].pending_transform, &crtcs[c].current_transform);
+ }
}
static void
@@ -954,9 +1012,8 @@ crtc_add_output (crtc_t *crtc, output_t *output)
crtc->y = output->y;
crtc->rotation = output->rotation;
crtc->mode_info = output->mode_info;
- crtc->pending_transform = output->transform;
- crtc->pending_inverse = output->inverse;
- }
+ copy_transform (&crtc->pending_transform, &output->transform);
+ }
if (!crtc->outputs) fatal ("out of memory");
crtc->outputs[crtc->noutput++] = output;
}
@@ -986,13 +1043,18 @@ crtc_disable (crtc_t *crtc)
}
static void
-crtc_set_transform (crtc_t *crtc, XTransform *transform, XTransform *inverse)
+crtc_set_transform (crtc_t *crtc, transform_t *transform)
{
int major, minor;
XRRQueryVersion (dpy, &major, &minor);
if (major > 1 || (major == 1 && minor >= 3))
- XRRSetCrtcTransform (dpy, crtc->crtc.xid, transform, inverse);
+ XRRSetCrtcTransform (dpy, crtc->crtc.xid,
+ &transform->transform,
+ &transform->inverse,
+ transform->filter,
+ transform->params,
+ transform->nparams);
}
static Status
@@ -1006,7 +1068,7 @@ crtc_revert (crtc_t *crtc)
if (dryrun)
return RRSetConfigSuccess;
- crtc_set_transform (crtc, &crtc->current_transform, &crtc->current_inverse);
+ crtc_set_transform (crtc, &crtc->current_transform);
return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
crtc_info->x, crtc_info->y,
crtc_info->mode, crtc_info->rotation,
@@ -1043,7 +1105,7 @@ crtc_apply (crtc_t *crtc)
s = RRSetConfigSuccess;
else
{
- crtc_set_transform (crtc, &crtc->pending_transform, &crtc->pending_inverse);
+ crtc_set_transform (crtc, &crtc->pending_transform);
s = XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
crtc->x, crtc->y, mode, crtc->rotation,
rr_outputs, crtc->noutput);
@@ -1361,9 +1423,7 @@ check_crtc_for_output (crtc_t *crtc, output_t *output, Bool ignore_state)
return False;
if (crtc->rotation != output->rotation)
return False;
- if (memcmp (&crtc->current_transform, &output->transform, sizeof (XTransform)) != 0)
- return False;
- if (memcmp (&crtc->current_inverse, &output->inverse, sizeof (XTransform)) != 0)
+ if (!equal_transform (&crtc->current_transform, &output->transform))
return False;
}
else if (crtc->crtc_info->noutput)
@@ -1940,14 +2000,19 @@ main (int argc, char **argv)
if (++i>=argc) usage();
if (sscanf (argv[i], "%lfx%lf", &sx, &sy) != 2)
usage ();
- memset (&output->transform, '\0', sizeof (output->transform));
- memset (&output->inverse, '\0', sizeof (output->inverse));
- output->transform.matrix[0][0] = XDoubleToFixed (1/sx);
- output->transform.matrix[1][1] = XDoubleToFixed (1/sy);
- output->transform.matrix[2][2] = XDoubleToFixed (1.0);
- output->inverse.matrix[0][0] = XDoubleToFixed (sx);
- output->inverse.matrix[1][1] = XDoubleToFixed (sy);
- output->inverse.matrix[2][2] = XDoubleToFixed (1.0);
+ init_transform (&output->transform);
+ output->transform.transform.matrix[0][0] = XDoubleToFixed (1/sx);
+ output->transform.transform.matrix[1][1] = XDoubleToFixed (1/sy);
+ output->transform.transform.matrix[2][2] = XDoubleToFixed (1.0);
+ output->transform.inverse.matrix[0][0] = XDoubleToFixed (sx);
+ output->transform.inverse.matrix[1][1] = XDoubleToFixed (sy);
+ output->transform.inverse.matrix[2][2] = XDoubleToFixed (1.0);
+ if (sx != 1 || sy != 1)
+ output->transform.filter = "bilinear";
+ else
+ output->transform.filter = "nearest";
+ output->transform.nparams = 0;
+ output->transform.params = NULL;
output->changes |= changes_transform;
continue;
}
@@ -2442,7 +2507,7 @@ main (int argc, char **argv)
for (y = 0; y < 3; y++)
{
for (x = 0; x < 3; x++)
- printf (" %f", XFixedToDouble (output->transform.matrix[y][x]));
+ printf (" %f", XFixedToDouble (output->transform.transform.matrix[y][x]));
if (y < 2)
printf ("\n\t ");
}
@@ -2450,10 +2515,12 @@ main (int argc, char **argv)
for (y = 0; y < 3; y++)
{
for (x = 0; x < 3; x++)
- printf (" %f", XFixedToDouble (output->inverse.matrix[y][x]));
+ printf (" %f", XFixedToDouble (output->transform.inverse.matrix[y][x]));
if (y < 2)
printf ("\n\t ");
}
+ if (output->transform.filter)
+ printf ("\n\t filter: %s", output->transform.filter);
printf ("\n");
}
if (verbose || properties)