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) {
RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
PropModeReplace, data_len, data, FALSE);
PropModeReplace, data_len, data, FALSE, TRUE);
} else {
RRDeleteOutputProperty(output->randr_output, edid_atom);
}

View File

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

View File

@ -121,19 +121,19 @@ RRDeleteOutputProperty (RROutputPtr output, Atom property)
int
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
int format, int mode, unsigned long len,
pointer value, Bool sendevent)
pointer value, Bool sendevent, Bool pending)
{
RRPropertyPtr prop;
xRROutputPropertyNotifyEvent event;
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
int sizeInBytes;
int totalSize;
pointer data;
int size_in_bytes;
int total_size;
unsigned long total_len;
RRPropertyValuePtr prop_value;
RRPropertyValueRec new_value;
Bool add = FALSE;
sizeInBytes = format >> 3;
totalSize = len * sizeInBytes;
size_in_bytes = format >> 3;
/* first see if property already exists */
prop = RRQueryOutputProperty (output, property);
@ -145,7 +145,7 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
add = TRUE;
mode = PropModeReplace;
}
if (prop->is_pending)
if (pending && prop->is_pending)
prop_value = &prop->pending;
else
prop_value = &prop->current;
@ -159,68 +159,75 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
return(BadMatch);
if ((prop_value->type != type) && (mode != PropModeReplace))
return(BadMatch);
new_value = *prop_value;
if (mode == PropModeReplace)
total_len = len;
else
total_len = prop_value->size + len;
if (mode == PropModeReplace || len > 0)
{
if (totalSize != prop_value->size * (prop_value->format >> 3))
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 (prop_value->data)
data = (pointer)xrealloc(prop_value->data, totalSize);
else
data = (pointer)xalloc (totalSize);
if (!data && len)
{
if (add)
RRDestroyOutputProperty (prop);
return(BadAlloc);
}
prop_value->data = data;
if (add)
RRDestroyOutputProperty (prop);
return BadAlloc;
}
if (len)
memmove((char *)prop_value->data, (char *)value, totalSize);
prop_value->size = len;
prop_value->type = type;
prop_value->format = format;
memmove((char *)new_value.data, (char *)value, total_size);
new_value.size = len;
new_value.type = type;
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)
{
/* 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)
{
prop->next = output->properties;
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)
{
event.type = RREventBase + RRNotify;
@ -234,6 +241,33 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
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
RRQueryOutputProperty (RROutputPtr output, Atom property)
{
@ -474,7 +508,7 @@ ProcRRChangeOutputProperty (ClientPtr client)
err = RRChangeOutputProperty(output, stuff->property,
stuff->type, (int)format,
(int)mode, len, (pointer)&stuff[1], TRUE);
(int)mode, len, (pointer)&stuff[1], TRUE, TRUE);
if (err != Success)
return err;
else
@ -508,8 +542,8 @@ int
ProcRRGetOutputProperty (ClientPtr client)
{
REQUEST(xRRGetOutputPropertyReq);
RRPropertyPtr prop, *prev;
RRPropertyValuePtr prop_value;
RRPropertyPtr prop, *prev;
RRPropertyValuePtr prop_value;
unsigned long n, len, ind;
RROutputPtr output;
xRRGetOutputPropertyReply reply;
@ -600,7 +634,10 @@ ProcRRGetOutputProperty (ClientPtr client)
reply.bytesAfter = n - (ind + len);
reply.format = prop_value->format;
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;
if (stuff->delete && (reply.bytesAfter == 0))