summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@guitar.keithp.com>2007-03-23 01:05:55 -0700
committerKeith Packard <keithp@guitar.keithp.com>2007-03-23 01:05:55 -0700
commit8eb288fbd69e2ffd02521d2c6a964c8180d08ec8 (patch)
tree44f9341a67ec176d97dee9c26d8cbfa1aabf4e5b
parent9ca7ba5d6012295a77ed773c656e786440da973d (diff)
downloadxserver-8eb288fbd69e2ffd02521d2c6a964c8180d08ec8.tar.gz
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.
-rw-r--r--hw/xfree86/modes/xf86Crtc.c2
-rw-r--r--randr/randrstr.h5
-rw-r--r--randr/rrproperty.c151
3 files changed, 99 insertions, 59 deletions
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index fad0752eb..2341715e7 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -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);
}
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 396810332..40d3eec8d 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -759,10 +759,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,
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index e020d5bc7..a57bd74bd 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -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 && pScrPriv->rrOutputSetProperty) {
- /* 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))