[Nouveau] [PATCH 1/3] kms: Don't hardcode the output properties
Francisco Jerez
currojerez at riseup.net
Tue Aug 11 17:18:26 PDT 2009
Replicate any properties the kernel exposes. Mostly taken from the
intel DDX.
---
src/drmmode_display.c | 303 ++++++++++++++++++++++++-------------------------
1 files changed, 151 insertions(+), 152 deletions(-)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3f04be1..805dc5b 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -58,11 +58,22 @@ typedef struct {
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {
+ drmModePropertyPtr mode_prop;
+ int index; /* Index within the kernel-side property arrays for
+ * this connector. */
+ int num_atoms; /* if range prop, num_atoms == 1; if enum prop,
+ * num_atoms == num_enums + 1 */
+ Atom *atoms;
+} drmmode_prop_rec, *drmmode_prop_ptr;
+
+typedef struct {
drmmode_ptr drmmode;
int output_id;
drmModeConnectorPtr mode_output;
drmModeEncoderPtr mode_encoder;
drmModePropertyBlobPtr edid_blob;
+ int num_props;
+ drmmode_prop_ptr props;
} drmmode_output_private_rec, *drmmode_output_private_ptr;
static void drmmode_output_dpms(xf86OutputPtr output, int mode);
@@ -613,9 +624,14 @@ static void
drmmode_output_destroy(xf86OutputPtr output)
{
drmmode_output_private_ptr drmmode_output = output->driver_private;
+ int i;
if (drmmode_output->edid_blob)
drmModeFreePropertyBlob(drmmode_output->edid_blob);
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmModeFreeProperty(drmmode_output->props[i].mode_prop);
+ xfree(drmmode_output->props[i].atoms);
+ }
drmModeFreeConnector(drmmode_output->mode_output);
xfree(drmmode_output);
output->driver_private = NULL;
@@ -652,140 +668,110 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
mode_id, mode);
}
-/*
- * Several scaling modes exist, let the user choose.
- */
-struct drmmode_enum {
- char *name;
- int value;
-};
-
-static struct drmmode_enum scaling_mode[] = {
- { "non-gpu", DRM_MODE_SCALE_NON_GPU },
- { "fullscreen", DRM_MODE_SCALE_FULLSCREEN },
- { "aspect", DRM_MODE_SCALE_ASPECT },
- { "noscale", DRM_MODE_SCALE_NO_SCALE },
- { NULL, -1 /* invalid */ }
-};
-static Atom scaling_mode_atom;
-
-static struct drmmode_enum dithering_mode[] = {
- { "off", DRM_MODE_DITHERING_OFF },
- { "on", DRM_MODE_DITHERING_ON },
- { NULL, -1 /* invalid */ }
-};
-static Atom dithering_atom;
-
-static int
-drmmode_enum_lookup_value(struct drmmode_enum *ptr, char *name, int size) {
- if (size == 0)
- size = strlen(name);
-
- while (ptr->name) {
- if (!strcmp(name, ptr->name))
- return ptr->value;
- ptr++;
- }
-
- return -1;
-}
-
-static char *
-drmmode_enum_lookup_name(struct drmmode_enum *ptr, int value)
+static Bool
+drmmode_property_ignore(drmModePropertyPtr prop)
{
- while (ptr->name) {
- if (ptr->value == value)
- return ptr->name;
- ptr++;
- }
+ if (!prop)
+ return TRUE;
+ /* ignore blob prop */
+ if (prop->flags & DRM_MODE_PROP_BLOB)
+ return TRUE;
+ /* ignore standard property */
+ if (!strcmp(prop->name, "EDID") ||
+ !strcmp(prop->name, "DPMS"))
+ return TRUE;
- return NULL;
+ return FALSE;
}
-drmModePropertyPtr
-drmmode_output_property_find(xf86OutputPtr output, uint32_t type,
- const char *name)
+static void
+drmmode_output_create_resources(xf86OutputPtr output)
{
drmmode_output_private_ptr drmmode_output = output->driver_private;
- drmModeConnectorPtr koutput = drmmode_output->mode_output;
+ drmModeConnectorPtr mode_output = drmmode_output->mode_output;
drmmode_ptr drmmode = drmmode_output->drmmode;
- drmModePropertyPtr props;
- int i;
+ drmModePropertyPtr drmmode_prop;
+ uint32_t value;
+ int i, j, err;
- for (i = 0; i < koutput->count_props; i++) {
- props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ drmmode_output->props = xcalloc(mode_output->count_props, sizeof(drmmode_prop_rec));
+ if (!drmmode_output->props)
+ return;
- if (!props || !(props->flags & type))
+ drmmode_output->num_props = 0;
+ for (i = 0, j = 0; i < mode_output->count_props; i++) {
+ drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
+ if (drmmode_property_ignore(drmmode_prop)) {
+ drmModeFreeProperty(drmmode_prop);
continue;
-
- if (!strcmp(props->name, name))
- return props;
- }
-
- return NULL;
-}
-
-static const char *
-drmmode_output_property_string(xf86OutputPtr output, struct drmmode_enum *ptr,
- const char *prop)
-{
- drmmode_output_private_ptr drmmode_output = output->driver_private;
- drmModeConnectorPtr koutput = drmmode_output->mode_output;
- drmModePropertyPtr props;
- const char *name;
- int i;
-
- props = drmmode_output_property_find(output, DRM_MODE_PROP_ENUM, prop);
- if (!props)
- return "unknown_prop";
-
- for (i = 0; i < koutput->count_props; i++) {
- if (koutput->props[i] == props->prop_id)
- break;
- }
-
- if (koutput->props[i] != props->prop_id)
- return "unknown_output_prop";
-
- name = drmmode_enum_lookup_name(ptr, koutput->prop_values[i]);
- return name ? name : "unknown_enum";
-}
-
-static void
-drmmode_output_create_resources(xf86OutputPtr output)
-{
- ScrnInfoPtr pScrn = output->scrn;
- const char *name;
- int ret;
-
- scaling_mode_atom = MakeAtom("SCALING_MODE", 12, TRUE);
- dithering_atom = MakeAtom("DITHERING", 9, TRUE);
-
- ret = RRConfigureOutputProperty(output->randr_output, scaling_mode_atom,
- FALSE, FALSE, FALSE, 0, NULL);
- if (ret) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Error creating SCALING_MODE property: %d\n", ret);
+ }
+ drmmode_output->props[j].mode_prop = drmmode_prop;
+ drmmode_output->props[j].index = i;
+ drmmode_output->num_props++;
+ j++;
}
- name = drmmode_output_property_string(output, scaling_mode,
- "scaling mode");
- RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
- XA_STRING, 8, PropModeReplace, strlen(name),
- (char *)name, FALSE, FALSE);
-
- ret = RRConfigureOutputProperty(output->randr_output, dithering_atom,
- FALSE, FALSE, FALSE, 0, NULL);
- if (ret) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Error creating DITHERING property: %d\n", ret);
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
+ drmmode_prop = p->mode_prop;
+
+ value = drmmode_output->mode_output->prop_values[p->index];
+
+ if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
+ INT32 range[2];
+
+ p->num_atoms = 1;
+ p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+ if (!p->atoms)
+ continue;
+ p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
+ range[0] = drmmode_prop->values[0];
+ range[1] = drmmode_prop->values[1];
+ err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+ FALSE, TRUE,
+ drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+ 2, range);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+ err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+ XA_INTEGER, 32, PropModeReplace, 1,
+ &value, FALSE, FALSE);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+ } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
+ p->num_atoms = drmmode_prop->count_enums + 1;
+ p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+ if (!p->atoms)
+ continue;
+ p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
+ for (j = 1; j <= drmmode_prop->count_enums; j++) {
+ struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
+ p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
+ }
+ err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+ FALSE, FALSE,
+ drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+ p->num_atoms - 1, (INT32 *)&p->atoms[1]);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+ for (j = 0; j < drmmode_prop->count_enums; j++)
+ if (drmmode_prop->enums[j].value == value)
+ break;
+ /* there's always a matching value */
+ err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+ XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, FALSE);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+ }
}
-
- name = drmmode_output_property_string(output, dithering_mode,
- "dithering");
- RRChangeOutputProperty(output->randr_output, dithering_atom,
- XA_STRING, 8, PropModeReplace, strlen(name),
- (char *)name, FALSE, FALSE);
}
static Bool
@@ -794,47 +780,60 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property,
{
drmmode_output_private_ptr drmmode_output = output->driver_private;
drmmode_ptr drmmode = drmmode_output->drmmode;
- drmModePropertyPtr props;
- int mode, ret = 0;
+ int i, ret;
- if (property == scaling_mode_atom) {
- if (value->type != XA_STRING || value->format != 8)
- return FALSE;
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
- mode = drmmode_enum_lookup_value(scaling_mode, value->data,
- value->size);
- if (mode == -1)
- return FALSE;
+ if (p->atoms[0] != property)
+ continue;
- props = drmmode_output_property_find(output, DRM_MODE_PROP_ENUM,
- "scaling mode");
- if (!props)
- return FALSE;
+ if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
+ uint32_t val;
- ret = drmModeConnectorSetProperty(drmmode->fd,
- drmmode_output->output_id,
- props->prop_id, mode);
- } else
- if (property == dithering_atom) {
- if (value->type != XA_STRING || value->format != 8)
- return FALSE;
+ if (value->type != XA_INTEGER || value->format != 32 ||
+ value->size != 1)
+ return FALSE;
+ val = *(uint32_t *)value->data;
- mode = drmmode_enum_lookup_value(dithering_mode, value->data,
- value->size);
- if (mode == -1)
- return FALSE;
+ ret = drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
+ p->mode_prop->prop_id, (uint64_t)val);
- props = drmmode_output_property_find(output, DRM_MODE_PROP_ENUM,
- "dithering");
- if (!props)
- return FALSE;
+ if (ret)
+ return FALSE;
+
+ return TRUE;
- ret = drmModeConnectorSetProperty(drmmode->fd,
- drmmode_output->output_id,
- props->prop_id, mode);
+ } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
+ Atom atom;
+ const char *name;
+ int j;
+
+ if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
+ return FALSE;
+ memcpy(&atom, value->data, 4);
+ name = NameForAtom(atom);
+
+ /* search for matching name string, then set its value down */
+ for (j = 0; j < p->mode_prop->count_enums; j++) {
+ if (!strcmp(p->mode_prop->enums[j].name, name)) {
+ ret = drmModeConnectorSetProperty(drmmode->fd,
+ drmmode_output->output_id,
+ p->mode_prop->prop_id,
+ p->mode_prop->enums[j].value);
+
+ if (ret)
+ return FALSE;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
}
- return ret == 0;
+ return TRUE;
}
static const xf86OutputFuncsRec drmmode_output_funcs = {
--
1.6.3.3
More information about the Nouveau
mailing list