Fix Pending property API, adding RRPostPendingProperty.

Pending Properties take effect when the driver says they do, so provide an
API to tell DIX when a property effect is made. Also, allow driver
to reject property values in RRChangeOutputProperty.
(cherry picked from commit 8eb288fbd69e2ffd02521d2c6a964c8180d08ec8)
This commit is contained in:
Keith Packard 2007-03-23 01:05:55 -07:00
parent 86d76390eb
commit 7093367c39
3 changed files with 99 additions and 59 deletions

View File

@ -1923,7 +1923,7 @@ xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
if (data_len != 0) { if (data_len != 0) {
RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
PropModeReplace, data_len, data, FALSE); PropModeReplace, data_len, data, FALSE, TRUE);
} else { } else {
RRDeleteOutputProperty(output->randr_output, edid_atom); RRDeleteOutputProperty(output->randr_output, edid_atom);
} }

View File

@ -761,10 +761,13 @@ RRQueryOutputProperty (RROutputPtr output, Atom property);
void void
RRDeleteOutputProperty (RROutputPtr output, Atom property); RRDeleteOutputProperty (RROutputPtr output, Atom property);
Bool
RRPostPendingProperty (RROutputPtr output, Atom property);
int int
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
int format, int mode, unsigned long len, int format, int mode, unsigned long len,
pointer value, Bool sendevent); pointer value, Bool sendevent, Bool pending);
int int
RRConfigureOutputProperty (RROutputPtr output, Atom property, RRConfigureOutputProperty (RROutputPtr output, Atom property,

View File

@ -121,19 +121,19 @@ RRDeleteOutputProperty (RROutputPtr output, Atom property)
int int
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
int format, int mode, unsigned long len, int format, int mode, unsigned long len,
pointer value, Bool sendevent) pointer value, Bool sendevent, Bool pending)
{ {
RRPropertyPtr prop; RRPropertyPtr prop;
xRROutputPropertyNotifyEvent event; xRROutputPropertyNotifyEvent event;
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen); rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
int sizeInBytes; int size_in_bytes;
int totalSize; int total_size;
pointer data; unsigned long total_len;
RRPropertyValuePtr prop_value; RRPropertyValuePtr prop_value;
RRPropertyValueRec new_value;
Bool add = FALSE; Bool add = FALSE;
sizeInBytes = format >> 3; size_in_bytes = format >> 3;
totalSize = len * sizeInBytes;
/* first see if property already exists */ /* first see if property already exists */
prop = RRQueryOutputProperty (output, property); prop = RRQueryOutputProperty (output, property);
@ -145,7 +145,7 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
add = TRUE; add = TRUE;
mode = PropModeReplace; mode = PropModeReplace;
} }
if (prop->is_pending) if (pending && prop->is_pending)
prop_value = &prop->pending; prop_value = &prop->pending;
else else
prop_value = &prop->current; prop_value = &prop->current;
@ -159,68 +159,75 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
return(BadMatch); return(BadMatch);
if ((prop_value->type != type) && (mode != PropModeReplace)) if ((prop_value->type != type) && (mode != PropModeReplace))
return(BadMatch); return(BadMatch);
new_value = *prop_value;
if (mode == PropModeReplace) if (mode == PropModeReplace)
{ total_len = len;
if (totalSize != prop_value->size * (prop_value->format >> 3))
{
if (prop_value->data)
data = (pointer)xrealloc(prop_value->data, totalSize);
else else
data = (pointer)xalloc (totalSize); total_len = prop_value->size + len;
if (!data && len)
if (mode == PropModeReplace || len > 0)
{
pointer new_data, old_data;
total_size = total_len * size_in_bytes;
new_value.data = (pointer)xalloc (total_size);
if (!new_value.data && total_size)
{ {
if (add) if (add)
RRDestroyOutputProperty (prop); RRDestroyOutputProperty (prop);
return(BadAlloc); return BadAlloc;
}
prop_value->data = data;
} }
if (len) if (len)
memmove((char *)prop_value->data, (char *)value, totalSize); memmove((char *)new_value.data, (char *)value, total_size);
prop_value->size = len; new_value.size = len;
prop_value->type = type; new_value.type = type;
prop_value->format = format; new_value.format = format;
switch (mode) {
case PropModeReplace:
new_data = new_value.data;
old_data = NULL;
break;
case PropModeAppend:
new_data = (pointer) (((char *) new_value.data) +
(prop_value->size * size_in_bytes));
old_data = new_value.data;
break;
case PropModePrepend:
new_data = new_value.data;
old_data = (pointer) (((char *) new_value.data) +
(prop_value->size * size_in_bytes));
break;
} }
memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
if (old_data)
memcpy ((char *) old_data, (char *) prop_value->data,
prop_value->size * size_in_bytes);
if (pending && pScrPriv->rrOutputSetProperty &&
!pScrPriv->rrOutputSetProperty(output->pScreen, output,
prop->propertyName, &new_value))
{
if (new_value.data)
xfree (new_value.data);
return (BadValue);
}
if (prop_value->data)
xfree (prop_value->data);
*prop_value = new_value;
}
else if (len == 0) else if (len == 0)
{ {
/* do nothing */ /* do nothing */
} }
else if (mode == PropModeAppend)
{
data = (pointer)xrealloc(prop_value->data,
sizeInBytes * (len + prop_value->size));
if (!data)
return(BadAlloc);
prop_value->data = data;
memmove(&((char *)data)[prop_value->size * sizeInBytes],
(char *)value,
totalSize);
prop_value->size += len;
}
else if (mode == PropModePrepend)
{
data = (pointer)xalloc(sizeInBytes * (len + prop_value->size));
if (!data)
return(BadAlloc);
memmove(&((char *)data)[totalSize], (char *)prop_value->data,
(int)(prop_value->size * sizeInBytes));
memmove((char *)data, (char *)value, totalSize);
xfree(prop_value->data);
prop_value->data = data;
prop_value->size += len;
}
if (add) if (add)
{ {
prop->next = output->properties; prop->next = output->properties;
output->properties = prop; output->properties = prop;
} }
if (!prop->is_pending) {
/* What should we do in case of failure? */
pScrPriv->rrOutputSetProperty(output->pScreen, output,
prop->propertyName, prop_value);
}
if (sendevent) if (sendevent)
{ {
event.type = RREventBase + RRNotify; event.type = RREventBase + RRNotify;
@ -234,6 +241,33 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
return(Success); return(Success);
} }
Bool
RRPostPendingProperty (RROutputPtr output, Atom property)
{
RRPropertyPtr prop = RRQueryOutputProperty (output, property);
RRPropertyValuePtr pending_value;
RRPropertyValuePtr current_value;
if (!prop)
return FALSE;
if (!prop->is_pending)
return FALSE;
pending_value = &prop->pending;
current_value = &prop->current;
if (pending_value->type == current_value->type &&
pending_value->format == current_value->format &&
pending_value->size == current_value->size &&
!memcmp (pending_value->data, current_value->data, pending_value->size))
return TRUE;
if (RRChangeOutputProperty (output, property,
pending_value->type, pending_value->format, PropModeReplace,
pending_value->size, pending_value->data, TRUE, FALSE) != Success)
return FALSE;
return TRUE;
}
RRPropertyPtr RRPropertyPtr
RRQueryOutputProperty (RROutputPtr output, Atom property) RRQueryOutputProperty (RROutputPtr output, Atom property)
{ {
@ -474,7 +508,7 @@ ProcRRChangeOutputProperty (ClientPtr client)
err = RRChangeOutputProperty(output, stuff->property, err = RRChangeOutputProperty(output, stuff->property,
stuff->type, (int)format, stuff->type, (int)format,
(int)mode, len, (pointer)&stuff[1], TRUE); (int)mode, len, (pointer)&stuff[1], TRUE, TRUE);
if (err != Success) if (err != Success)
return err; return err;
else else
@ -600,7 +634,10 @@ ProcRRGetOutputProperty (ClientPtr client)
reply.bytesAfter = n - (ind + len); reply.bytesAfter = n - (ind + len);
reply.format = prop_value->format; reply.format = prop_value->format;
reply.length = (len + 3) >> 2; reply.length = (len + 3) >> 2;
reply.nItems = len / (prop_value->format / 8 ); if (prop_value->format)
reply.nItems = len / (prop_value->format / 8);
else
reply.nItems = 0;
reply.propertyType = prop_value->type; reply.propertyType = prop_value->type;
if (stuff->delete && (reply.bytesAfter == 0)) if (stuff->delete && (reply.bytesAfter == 0))