XrrProvider.c revision a5bbb2f1
1/*
2 * Copyright © 2011 Dave Airlie
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  The copyright holders make no representations
11 * about the suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <limits.h>
29#include <stdio.h>
30#include <X11/Xlib.h>
31/* we need to be able to manipulate the Display structure on events */
32#include <X11/Xlibint.h>
33#include <X11/extensions/render.h>
34#include <X11/extensions/Xrender.h>
35#include "Xrandrint.h"
36
37XRRProviderResources *
38XRRGetProviderResources(Display *dpy, Window window)
39{
40    XExtDisplayInfo		*info = XRRFindDisplay(dpy);
41    xRRGetProvidersReply rep;
42    xRRGetProvidersReq *req;
43    XRRProviderResources *xrpr;
44    long nbytes, nbytesRead;
45    int rbytes;
46
47    RRCheckExtension (dpy, info, NULL);
48
49    LockDisplay (dpy);
50
51    GetReq(RRGetProviders, req);
52    req->reqType = info->codes->major_opcode;
53    req->randrReqType = X_RRGetProviders;
54    req->window = window;
55
56    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
57    {
58      UnlockDisplay (dpy);
59      SyncHandle ();
60      return NULL;
61    }
62
63    if (rep.length < (INT_MAX >> 2)) {
64	nbytes = (long) rep.length << 2;
65
66	nbytesRead = (long) (rep.nProviders * 4);
67
68	rbytes = (sizeof(XRRProviderResources) + rep.nProviders *
69		  sizeof(RRProvider));
70	xrpr = Xmalloc(rbytes);
71    } else {
72	nbytes = 0;
73	nbytesRead = 0;
74	rbytes = 0;
75	xrpr = NULL;
76    }
77
78    if (xrpr == NULL) {
79       _XEatDataWords (dpy, rep.length);
80       UnlockDisplay (dpy);
81       SyncHandle ();
82       return NULL;
83    }
84
85    xrpr->timestamp = rep.timestamp;
86    xrpr->nproviders = rep.nProviders;
87    xrpr->providers = (RRProvider *)(xrpr + 1);
88
89    _XRead32(dpy, (long *) xrpr->providers, rep.nProviders << 2);
90
91    if (nbytes > nbytesRead)
92      _XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
93
94
95    UnlockDisplay (dpy);
96    SyncHandle();
97
98    return (XRRProviderResources *) xrpr;
99}
100
101void
102XRRFreeProviderResources(XRRProviderResources *provider_resources)
103{
104    free(provider_resources);
105}
106
107XRRProviderInfo *
108XRRGetProviderInfo(Display *dpy, XRRScreenResources *resources, RRProvider provider)
109{
110    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
111    xRRGetProviderInfoReply rep;
112    xRRGetProviderInfoReq *req;
113    int nbytes, nbytesRead, rbytes;
114    XRRProviderInfo *xpi;
115
116    RRCheckExtension (dpy, info, NULL);
117
118    LockDisplay (dpy);
119    GetReq (RRGetProviderInfo, req);
120    req->reqType = info->codes->major_opcode;
121    req->randrReqType = X_RRGetProviderInfo;
122    req->provider = provider;
123    req->configTimestamp = resources->configTimestamp;
124
125    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
126    {
127	UnlockDisplay (dpy);
128	SyncHandle ();
129	return NULL;
130    }
131
132    if (rep.length > (INT_MAX >> 2))
133    {
134	_XEatDataWords (dpy, rep.length);
135	UnlockDisplay (dpy);
136	SyncHandle ();
137	return NULL;
138    }
139
140    nbytes = ((long) rep.length << 2);
141
142    nbytesRead = (long)(rep.nCrtcs * 4 +
143			rep.nOutputs * 4 +
144			rep.nAssociatedProviders * 8 +
145			((rep.nameLength + 3) & ~3));
146
147    rbytes = (sizeof(XRRProviderInfo) +
148	      rep.nCrtcs * sizeof(RRCrtc) +
149	      rep.nOutputs * sizeof(RROutput) +
150	      rep.nAssociatedProviders * (sizeof(RRProvider) + sizeof(unsigned int))+
151	      rep.nameLength + 1);
152
153    xpi = Xmalloc(rbytes);
154    if (xpi == NULL) {
155	_XEatDataWords (dpy, rep.length);
156	UnlockDisplay (dpy);
157	SyncHandle ();
158	return NULL;
159    }
160
161    xpi->capabilities = rep.capabilities;
162    xpi->ncrtcs = rep.nCrtcs;
163    xpi->noutputs = rep.nOutputs;
164    xpi->nassociatedproviders = rep.nAssociatedProviders;
165    xpi->crtcs = (RRCrtc *)(xpi + 1);
166    xpi->outputs = (RROutput *)(xpi->crtcs + rep.nCrtcs);
167    xpi->associated_providers = (RRProvider *)(xpi->outputs + rep.nOutputs);
168    xpi->associated_capability = (unsigned int *)(xpi->associated_providers + rep.nAssociatedProviders);
169    xpi->name = (char *)(xpi->associated_capability + rep.nAssociatedProviders);
170
171    _XRead32(dpy, (long *) xpi->crtcs, rep.nCrtcs << 2);
172    _XRead32(dpy, (long *) xpi->outputs, rep.nOutputs << 2);
173
174    _XRead32(dpy, (long *) xpi->associated_providers, rep.nAssociatedProviders << 2);
175
176    /*
177     * _XRead32 reads a series of 32-bit values from the protocol and writes
178     * them out as a series of "long int" values, but associated_capability
179     * is defined as unsigned int *, so that won't work for this array.
180     * Instead we assume for now that "unsigned int" is also 32-bits, so
181     * the values can be read without any conversion.
182     */
183    _XRead(dpy, (char *) xpi->associated_capability,
184           rep.nAssociatedProviders << 2);
185
186    _XReadPad(dpy, xpi->name, rep.nameLength);
187    xpi->name[rep.nameLength] = '\0';
188
189    /*
190     * Skip any extra data
191     */
192    if (nbytes > nbytesRead)
193	_XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
194
195    UnlockDisplay (dpy);
196    SyncHandle ();
197    return (XRRProviderInfo *) xpi;
198}
199
200void
201XRRFreeProviderInfo(XRRProviderInfo *provider)
202{
203    free(provider);
204}
205
206int
207XRRSetProviderOutputSource(Display *dpy, XID provider,
208			   XID source_provider)
209{
210    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
211    xRRSetProviderOutputSourceReq *req;
212
213    RRCheckExtension (dpy, info, 0);
214    LockDisplay (dpy);
215    GetReq (RRSetProviderOutputSource, req);
216    req->reqType = info->codes->major_opcode;
217    req->randrReqType = X_RRSetProviderOutputSource;
218    req->provider = provider;
219    req->source_provider = source_provider;
220    UnlockDisplay (dpy);
221    SyncHandle ();
222    return 0;
223}
224
225int
226XRRSetProviderOffloadSink(Display *dpy, XID provider,
227			  XID sink_provider)
228{
229    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
230    xRRSetProviderOffloadSinkReq *req;
231
232    RRCheckExtension (dpy, info, 0);
233    LockDisplay (dpy);
234    GetReq (RRSetProviderOffloadSink, req);
235    req->reqType = info->codes->major_opcode;
236    req->randrReqType = X_RRSetProviderOffloadSink;
237    req->provider = provider;
238    req->sink_provider = sink_provider;
239    UnlockDisplay (dpy);
240    SyncHandle ();
241    return 0;
242}
243