XrrProvider.c revision f1c62215
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 = (XRRProviderResources *) 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
107#define ProviderInfoExtra	(SIZEOF(xRRGetProviderInfoReply) - 32)
108XRRProviderInfo *
109XRRGetProviderInfo(Display *dpy, XRRScreenResources *resources, RRProvider provider)
110{
111    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
112    xRRGetProviderInfoReply rep;
113    xRRGetProviderInfoReq *req;
114    int nbytes, nbytesRead, rbytes;
115    XRRProviderInfo *xpi;
116
117    RRCheckExtension (dpy, info, NULL);
118
119    LockDisplay (dpy);
120    GetReq (RRGetProviderInfo, req);
121    req->reqType = info->codes->major_opcode;
122    req->randrReqType = X_RRGetProviderInfo;
123    req->provider = provider;
124    req->configTimestamp = resources->configTimestamp;
125
126    if (!_XReply (dpy, (xReply *) &rep, ProviderInfoExtra >> 2, xFalse))
127    {
128	UnlockDisplay (dpy);
129	SyncHandle ();
130	return NULL;
131    }
132
133    if (rep.length > INT_MAX >> 2 || rep.length < ProviderInfoExtra >> 2)
134    {
135	if (rep.length < ProviderInfoExtra >> 2)
136	    _XEatDataWords (dpy, rep.length);
137	else
138	    _XEatDataWords (dpy, rep.length - (ProviderInfoExtra >> 2));
139	UnlockDisplay (dpy);
140	SyncHandle ();
141	return NULL;
142    }
143
144    nbytes = ((long) rep.length << 2) - ProviderInfoExtra;
145
146    nbytesRead = (long)(rep.nCrtcs * 4 +
147			rep.nOutputs * 4 +
148			rep.nAssociatedProviders * 8 +
149			((rep.nameLength + 3) & ~3));
150
151    rbytes = (sizeof(XRRProviderInfo) +
152	      rep.nCrtcs * sizeof(RRCrtc) +
153	      rep.nOutputs * sizeof(RROutput) +
154	      rep.nAssociatedProviders * (sizeof(RRProvider) + sizeof(unsigned int))+
155	      rep.nameLength + 1);
156
157    xpi = (XRRProviderInfo *)Xmalloc(rbytes);
158    if (xpi == NULL) {
159	_XEatDataWords (dpy, rep.length - (ProviderInfoExtra >> 2));
160	UnlockDisplay (dpy);
161	SyncHandle ();
162	return NULL;
163    }
164
165    xpi->capabilities = rep.capabilities;
166    xpi->ncrtcs = rep.nCrtcs;
167    xpi->noutputs = rep.nOutputs;
168    xpi->nassociatedproviders = rep.nAssociatedProviders;
169    xpi->crtcs = (RRCrtc *)(xpi + 1);
170    xpi->outputs = (RROutput *)(xpi->crtcs + rep.nCrtcs);
171    xpi->associated_providers = (RRProvider *)(xpi->outputs + rep.nOutputs);
172    xpi->associated_capability = (unsigned int *)(xpi->associated_providers + rep.nAssociatedProviders);
173    xpi->name = (char *)(xpi->associated_capability + rep.nAssociatedProviders);
174
175    _XRead32(dpy, (long *) xpi->crtcs, rep.nCrtcs << 2);
176    _XRead32(dpy, (long *) xpi->outputs, rep.nOutputs << 2);
177
178    _XRead32(dpy, (long *) xpi->associated_providers, rep.nAssociatedProviders << 2);
179
180    /*
181     * _XRead32 reads a series of 32-bit values from the protocol and writes
182     * them out as a series of "long int" values, but associated_capability
183     * is defined as unsigned int *, so that won't work for this array.
184     * Instead we assume for now that "unsigned int" is also 32-bits, so
185     * the values can be read without any conversion.
186     */
187    _XRead(dpy, (char *) xpi->associated_capability,
188           rep.nAssociatedProviders << 2);
189
190    _XReadPad(dpy, xpi->name, rep.nameLength);
191    xpi->name[rep.nameLength] = '\0';
192
193    /*
194     * Skip any extra data
195     */
196    if (nbytes > nbytesRead)
197	_XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
198
199    UnlockDisplay (dpy);
200    SyncHandle ();
201    return (XRRProviderInfo *) xpi;
202}
203
204void
205XRRFreeProviderInfo(XRRProviderInfo *provider)
206{
207    free(provider);
208}
209
210int
211XRRSetProviderOutputSource(Display *dpy, XID provider,
212			   XID source_provider)
213{
214    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
215    xRRSetProviderOutputSourceReq *req;
216
217    RRCheckExtension (dpy, info, 0);
218    LockDisplay (dpy);
219    GetReq (RRSetProviderOutputSource, req);
220    req->reqType = info->codes->major_opcode;
221    req->randrReqType = X_RRSetProviderOutputSource;
222    req->provider = provider;
223    req->source_provider = source_provider;
224    UnlockDisplay (dpy);
225    SyncHandle ();
226    return 0;
227}
228
229int
230XRRSetProviderOffloadSink(Display *dpy, XID provider,
231			  XID sink_provider)
232{
233    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
234    xRRSetProviderOffloadSinkReq *req;
235
236    RRCheckExtension (dpy, info, 0);
237    LockDisplay (dpy);
238    GetReq (RRSetProviderOffloadSink, req);
239    req->reqType = info->codes->major_opcode;
240    req->randrReqType = X_RRSetProviderOffloadSink;
241    req->provider = provider;
242    req->sink_provider = sink_provider;
243    UnlockDisplay (dpy);
244    SyncHandle ();
245    return 0;
246}
247