Commit 5d2edde0 authored by Dave Airlie's avatar Dave Airlie

libXrandr: add support for provider objects.

This adds the client side libXrandr support for randr 1.4,
and provider objects.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent a9457b44
......@@ -39,6 +39,7 @@ _XFUNCPROTOBEGIN
typedef XID RROutput;
typedef XID RRCrtc;
typedef XID RRMode;
typedef XID RRProvider;
typedef struct {
int width, height;
......@@ -118,6 +119,41 @@ typedef struct {
int state; /* NewValue, Deleted */
} XRROutputPropertyNotifyEvent;
typedef struct {
int type; /* event base */
unsigned long serial; /* # of last request processed by server */
Bool send_event; /* true if this came from a SendEvent request */
Display *display; /* Display the event was read from */
Window window; /* window which selected for this event */
int subtype; /* RRNotify_ProviderChange */
RRProvider provider; /* current provider (or None) */
Time timestamp; /* time of change */
unsigned int current_role;
} XRRProviderChangeNotifyEvent;
typedef struct {
int type; /* event base */
unsigned long serial; /* # of last request processed by server */
Bool send_event; /* true if this came from a SendEvent request */
Display *display; /* Display the event was read from */
Window window; /* window which selected for this event */
int subtype; /* RRNotify_ProviderProperty */
RRProvider provider; /* related provider */
Atom property; /* changed property */
Time timestamp; /* time of change */
int state; /* NewValue, Deleted */
} XRRProviderPropertyNotifyEvent;
typedef struct {
int type; /* event base */
unsigned long serial; /* # of last request processed by server */
Bool send_event; /* true if this came from a SendEvent request */
Display *display; /* Display the event was read from */
Window window; /* window which selected for this event */
int subtype; /* RRNotify_ResourceChange */
Time timestamp; /* time of change */
} XRRResourceChangeNotifyEvent;
/* internal representation is private to the library */
typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
......@@ -451,6 +487,71 @@ RROutput
XRRGetOutputPrimary(Display *dpy,
Window window);
typedef struct _XRRProviderResources {
Time timestamp;
int nproviders;
RRProvider *providers;
} XRRProviderResources;
XRRProviderResources *
XRRGetProviderResources(Display *dpy, Window window);
void
XRRFreeProviderResources(XRRProviderResources *resources);
typedef struct _XRRProviderInfo {
unsigned int capabilities;
int ncrtcs;
RRCrtc *crtcs;
int noutputs;
RROutput *outputs;
char *name;
int nassociatedproviders;
RRProvider *associated_providers;
unsigned int *associated_capability;
int nameLen;
} XRRProviderInfo;
XRRProviderInfo *
XRRGetProviderInfo(Display *dpy, XRRScreenResources *resources, RRProvider provider);
void
XRRFreeProviderInfo(XRRProviderInfo *provider);
int
XRRSetProviderOutputSource(Display *dpy, XID provider, XID source_provider);
int
XRRSetProviderOffloadSink(Display *dpy, XID provider, XID sink_provider);
Atom *
XRRListProviderProperties (Display *dpy, RRProvider provider, int *nprop);
XRRPropertyInfo *
XRRQueryProviderProperty (Display *dpy, RRProvider provider, Atom property);
void
XRRConfigureProviderProperty (Display *dpy, RRProvider provider, Atom property,
Bool pending, Bool range, int num_values,
long *values);
void
XRRChangeProviderProperty (Display *dpy, RRProvider provider,
Atom property, Atom type,
int format, int mode,
_Xconst unsigned char *data, int nelements);
void
XRRDeleteProviderProperty (Display *dpy, RRProvider provider, Atom property);
int
XRRGetProviderProperty (Display *dpy, RRProvider provider,
Atom property, long offset, long length,
Bool _delete, Bool pending, Atom req_type,
Atom *actual_type, int *actual_format,
unsigned long *nitems, unsigned long *bytes_after,
unsigned char **prop);
_XFUNCPROTOEND
#endif /* _XRANDR_H_ */
......@@ -8,7 +8,9 @@ libXrandr_la_SOURCES = \
XrrMode.c \
XrrOutput.c \
XrrProperty.c \
XrrScreen.c
XrrScreen.c \
XrrProvider.c \
XrrProviderProperty.c
libXrandr_la_LIBADD = @RANDR_LIBS@
......
......@@ -137,7 +137,46 @@ static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
aevent->state = awire->state;
return True;
}
case RRNotify_ProviderChange: {
XRRProviderChangeNotifyEvent *aevent = (XRRProviderChangeNotifyEvent *) event;
xRRProviderChangeNotifyEvent *awire = (xRRProviderChangeNotifyEvent *) wire;
aevent->type = awire->type & 0x7F;
aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
aevent->send_event = (awire->type & 0x80) != 0;
aevent->display = dpy;
aevent->window = awire->window;
aevent->subtype = awire->subCode;
aevent->provider = awire->provider;
aevent->timestamp = awire->timestamp;
return True;
}
case RRNotify_ProviderProperty: {
XRRProviderPropertyNotifyEvent *aevent = (XRRProviderPropertyNotifyEvent *) event;
xRRProviderPropertyNotifyEvent *awire = (xRRProviderPropertyNotifyEvent *) wire;
aevent->type = awire->type & 0x7F;
aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
aevent->send_event = (awire->type & 0x80) != 0;
aevent->display = dpy;
aevent->window = awire->window;
aevent->subtype = awire->subCode;
aevent->provider = awire->provider;
aevent->property = awire->atom;
aevent->timestamp = awire->timestamp;
aevent->state = awire->state;
return True;
}
case RRNotify_ResourceChange: {
XRRResourceChangeNotifyEvent *aevent = (XRRResourceChangeNotifyEvent *) event;
xRRResourceChangeNotifyEvent *awire = (xRRResourceChangeNotifyEvent *) wire;
aevent->type = awire->type & 0x7F;
aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
aevent->send_event = (awire->type & 0x80) != 0;
aevent->display = dpy;
aevent->window = awire->window;
aevent->subtype = awire->subCode;
aevent->timestamp = awire->timestamp;
return True;
}
break;
}
}
......@@ -214,6 +253,30 @@ static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire)
awire->state = aevent->state;
return True;
}
case RRNotify_ProviderChange: {
xRRProviderChangeNotifyEvent *awire = (xRRProviderChangeNotifyEvent *) wire;
XRRProviderChangeNotifyEvent *aevent = (XRRProviderChangeNotifyEvent *) event;
awire->window = aevent->window;
awire->provider = aevent->provider;
return True;
}
case RRNotify_ProviderProperty: {
xRRProviderPropertyNotifyEvent *awire = (xRRProviderPropertyNotifyEvent *) wire;
XRRProviderPropertyNotifyEvent *aevent = (XRRProviderPropertyNotifyEvent *) event;
awire->window = aevent->window;
awire->provider = aevent->provider;
awire->atom = aevent->property;
awire->timestamp = aevent->timestamp;
awire->state = aevent->state;
return True;
}
case RRNotify_ResourceChange: {
xRRResourceChangeNotifyEvent *awire = (xRRResourceChangeNotifyEvent *) wire;
XRRResourceChangeNotifyEvent *aevent = (XRRResourceChangeNotifyEvent *) event;
awire->window = aevent->window;
awire->timestamp = aevent->timestamp;
return True;
}
}
}
}
......
/*
* Copyright © 2011 Dave Airlie
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <X11/Xlib.h>
/* we need to be able to manipulate the Display structure on events */
#include <X11/Xlibint.h>
#include <X11/extensions/render.h>
#include <X11/extensions/Xrender.h>
#include "Xrandrint.h"
XRRProviderResources *
XRRGetProviderResources(Display *dpy, Window window)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRGetProvidersReply rep;
xRRGetProvidersReq *req;
XRRProviderResources *xrpr;
long nbytes, nbytesRead;
int rbytes;
RRCheckExtension (dpy, info, NULL);
LockDisplay (dpy);
GetReq(RRGetProviders, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRGetProviders;
req->window = window;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
{
UnlockDisplay (dpy);
SyncHandle ();
return NULL;
}
nbytes = (long) rep.length << 2;
nbytesRead = (long) (rep.nProviders * 4);
rbytes = (sizeof(XRRProviderResources) + rep.nProviders * sizeof(RRProvider));
xrpr = (XRRProviderResources *) Xmalloc(rbytes);
if (xrpr == NULL) {
_XEatData (dpy, (unsigned long) nbytes);
UnlockDisplay (dpy);
SyncHandle ();
return NULL;
}
xrpr->timestamp = rep.timestamp;
xrpr->nproviders = rep.nProviders;
xrpr->providers = (RRProvider *)(xrpr + 1);
_XRead32(dpy, xrpr->providers, rep.nProviders << 2);
if (nbytes > nbytesRead)
_XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
UnlockDisplay (dpy);
SyncHandle();
return (XRRProviderResources *) xrpr;
}
void
XRRFreeProviderResources(XRRProviderResources *provider_resources)
{
free(provider_resources);
}
#define ProviderInfoExtra (SIZEOF(xRRGetProviderInfoReply) - 32)
XRRProviderInfo *
XRRGetProviderInfo(Display *dpy, XRRScreenResources *resources, RRProvider provider)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRGetProviderInfoReply rep;
xRRGetProviderInfoReq *req;
int nbytes, nbytesRead, rbytes;
XRRProviderInfo *xpi;
RRCheckExtension (dpy, info, NULL);
LockDisplay (dpy);
GetReq (RRGetProviderInfo, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRGetProviderInfo;
req->provider = provider;
req->configTimestamp = resources->configTimestamp;
if (!_XReply (dpy, (xReply *) &rep, ProviderInfoExtra >> 2, xFalse))
{
UnlockDisplay (dpy);
SyncHandle ();
return NULL;
}
nbytes = ((long) rep.length << 2) - ProviderInfoExtra;
nbytesRead = (long)(rep.nCrtcs * 4 +
rep.nOutputs * 4 +
rep.nAssociatedProviders * 8 +
((rep.nameLength + 3) & ~3));
rbytes = (sizeof(XRRProviderInfo) +
rep.nCrtcs * sizeof(RRCrtc) +
rep.nOutputs * sizeof(RROutput) +
rep.nAssociatedProviders * (sizeof(RRProvider) + sizeof(unsigned int))+
rep.nameLength + 1);
xpi = (XRRProviderInfo *)Xmalloc(rbytes);
if (xpi == NULL) {
_XEatData (dpy, (unsigned long) nbytes);
UnlockDisplay (dpy);
SyncHandle ();
return NULL;
}
xpi->capabilities = rep.capabilities;
xpi->ncrtcs = rep.nCrtcs;
xpi->noutputs = rep.nOutputs;
xpi->nassociatedproviders = rep.nAssociatedProviders;
xpi->crtcs = (RRCrtc *)(xpi + 1);
xpi->outputs = (RROutput *)(xpi->crtcs + rep.nCrtcs);
xpi->associated_providers = (RRProvider *)(xpi->outputs + rep.nOutputs);
xpi->associated_capability = (unsigned int *)(xpi->associated_providers + rep.nAssociatedProviders);
xpi->name = (char *)(xpi->associated_capability + rep.nAssociatedProviders);
_XRead32(dpy, xpi->crtcs, rep.nCrtcs << 2);
_XRead32(dpy, xpi->outputs, rep.nOutputs << 2);
_XRead32(dpy, xpi->associated_providers, rep.nAssociatedProviders << 2);
_XRead32(dpy, xpi->associated_capability, rep.nAssociatedProviders << 2);
_XReadPad(dpy, xpi->name, rep.nameLength);
xpi->name[rep.nameLength] = '\0';
/*
* Skip any extra data
*/
if (nbytes > nbytesRead)
_XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
UnlockDisplay (dpy);
SyncHandle ();
return (XRRProviderInfo *) xpi;
}
void
XRRFreeProviderInfo(XRRProviderInfo *provider)
{
free(provider);
}
int
XRRSetProviderOutputSource(Display *dpy, XID provider,
XID source_provider)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRSetProviderOutputSourceReq *req;
RRCheckExtension (dpy, info, 0);
LockDisplay (dpy);
GetReq (RRSetProviderOutputSource, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRSetProviderOutputSource;
req->provider = provider;
req->source_provider = source_provider;
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
int
XRRSetProviderOffloadSink(Display *dpy, XID provider,
XID sink_provider)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRSetProviderOffloadSinkReq *req;
RRCheckExtension (dpy, info, 0);
LockDisplay (dpy);
GetReq (RRSetProviderOffloadSink, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRSetProviderOffloadSink;
req->provider = provider;
req->sink_provider = sink_provider;
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
/*
* Copyright © 2006 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <X11/Xlib.h>
/* we need to be able to manipulate the Display structure on events */
#include <X11/Xlibint.h>
#include <X11/extensions/render.h>
#include <X11/extensions/Xrender.h>
#include "Xrandrint.h"
Atom *
XRRListProviderProperties (Display *dpy, RRProvider provider, int *nprop)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRListProviderPropertiesReply rep;
xRRListProviderPropertiesReq *req;
int nbytes, rbytes;
Atom *props = NULL;
RRCheckExtension (dpy, info, NULL);
LockDisplay (dpy);
GetReq (RRListProviderProperties, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRListProviderProperties;
req->provider = provider;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
UnlockDisplay (dpy);
SyncHandle ();
*nprop = 0;
return NULL;
}
if (rep.nAtoms) {
rbytes = rep.nAtoms * sizeof (Atom);
nbytes = rep.nAtoms << 2;
props = (Atom *) Xmalloc (rbytes);
if (props == NULL) {
_XEatData (dpy, nbytes);
UnlockDisplay (dpy);
SyncHandle ();
*nprop = 0;
return NULL;
}
_XRead32 (dpy, props, nbytes);
}
*nprop = rep.nAtoms;
UnlockDisplay (dpy);
SyncHandle ();
return props;
}
XRRPropertyInfo *
XRRQueryProviderProperty (Display *dpy, RRProvider provider, Atom property)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRQueryProviderPropertyReply rep;
xRRQueryProviderPropertyReq *req;
int rbytes, nbytes;
XRRPropertyInfo *prop_info;
RRCheckExtension (dpy, info, NULL);
LockDisplay (dpy);
GetReq (RRQueryProviderProperty, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRQueryProviderProperty;
req->provider = provider;
req->property = property;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
UnlockDisplay (dpy);
SyncHandle ();
return NULL;
}
rbytes = sizeof (XRRPropertyInfo) + rep.length * sizeof (long);
nbytes = rep.length << 2;
prop_info = (XRRPropertyInfo *) Xmalloc (rbytes);
if (prop_info == NULL) {
_XEatData (dpy, nbytes);
UnlockDisplay (dpy);
SyncHandle ();
return NULL;
}
prop_info->pending = rep.pending;
prop_info->range = rep.range;
prop_info->immutable = rep.immutable;
prop_info->num_values = rep.length;
if (rep.length != 0) {
prop_info->values = (long *) (prop_info + 1);
_XRead32 (dpy, prop_info->values, nbytes);
} else {
prop_info->values = NULL;
}
UnlockDisplay (dpy);
SyncHandle ();
return prop_info;
}
void
XRRConfigureProviderProperty (Display *dpy, RRProvider provider, Atom property,
Bool pending, Bool range, int num_values,
long *values)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRConfigureProviderPropertyReq *req;
long len;
RRSimpleCheckExtension (dpy, info);
LockDisplay(dpy);
GetReq (RRConfigureProviderProperty, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRConfigureProviderProperty;
req->provider = provider;
req->property = property;
req->pending = pending;
req->range = range;
len = num_values;
if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
SetReqLen(req, len, len);
len = (long)num_values << 2;
Data32 (dpy, values, len);
} /* else force BadLength */
UnlockDisplay(dpy);
SyncHandle();
}
void
XRRChangeProviderProperty (Display *dpy, RRProvider provider,
Atom property, Atom type,
int format, int mode,
_Xconst unsigned char *data, int nelements)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRChangeProviderPropertyReq *req;
long len;
RRSimpleCheckExtension (dpy, info);
LockDisplay(dpy);
GetReq (RRChangeProviderProperty, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRChangeProviderProperty;
req->provider = provider;
req->property = property;
req->type = type;
req->mode = mode;
if (nelements < 0) {
req->nUnits = 0;
req->format = 0; /* ask for garbage, get garbage */
} else {
req->nUnits = nelements;
req->format = format;
}
switch (req->format) {
case 8:
len = ((long)nelements + 3) >> 2;
if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
SetReqLen(req, len, len);
Data (dpy, (char *)data, nelements);
} /* else force BadLength */
break;
case 16:
len = ((long)nelements + 1) >> 1;
if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
SetReqLen(req, len, len);
len = (long)nelements << 1;
Data16 (dpy, (short *) data, len);
} /* else force BadLength */
break;
case 32:
len = nelements;
if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
SetReqLen(req, len, len);
len = (long)nelements << 2;
Data32 (dpy, (long *) data, len);
} /* else force BadLength */
break;
default:
/* BadValue will be generated */ ;
}
UnlockDisplay(dpy);
SyncHandle();
}
void
XRRDeleteProviderProperty (Display *dpy, RRProvider provider, Atom property)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRDeleteProviderPropertyReq *req;
RRSimpleCheckExtension (dpy, info);
LockDisplay(dpy);
GetReq(RRDeleteProviderProperty, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRDeleteProviderProperty;
req->provider = provider;
req->property = property;
UnlockDisplay(dpy);
SyncHandle();
}
int
XRRGetProviderProperty (Display *dpy, RRProvider provider,
Atom property, long offset, long length,
Bool delete, Bool pending, Atom req_type,
Atom *actual_type, int *actual_format,
unsigned long *nitems, unsigned long *bytes_after,
unsigned char **prop)
{
XExtDisplayInfo *info = XRRFindDisplay(dpy);
xRRGetProviderPropertyReply rep;
xRRGetProviderPropertyReq *req;
long nbytes, rbytes;
RRCheckExtension (dpy, info, 1);
LockDisplay (dpy);
GetReq (RRGetProviderProperty, req);
req->reqType = info->codes->major_opcode;
req->randrReqType = X_RRGetProviderProperty;
req->provider = provider;
req->property = property;
req->type = req_type;
req->longOffset = offset;
req->longLength = length;
req->delete = delete;
req->pending = pending;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
{
UnlockDisplay (dpy);
SyncHandle ();
return ((xError *)&rep)->errorCode;
}
*prop = (unsigned char *) NULL;
if (rep.propertyType != None) {
/*
* One extra byte is malloced than is needed to contain the property
* data, but this last byte is null terminated and convenient for
* returning string properties, so the client doesn't then have to
* recopy the string to make it null terminated.
*/
switch (rep.format) {
case 8:
nbytes = rep.nItems;
rbytes = rep.nItems + 1;
if (rbytes > 0 &&
(*prop = (unsigned char *) Xmalloc ((unsigned)rbytes)))
_XReadPad (dpy, (char *) *prop, nbytes);
break;
case 16:
nbytes = rep.nItems << 1;
rbytes = rep.nItems * sizeof (short) + 1;
if (rbytes > 0 &&
(*prop = (unsigned char *) Xmalloc ((unsigned)rbytes)))
_XRead16Pad (dpy, (short *) *prop, nbytes);
break;
case 32: