XF86VMode.c revision d9dcd5ae
1191cded7Smrg/*
2191cded7Smrg
3191cded7SmrgCopyright (c) 1995  Kaleb S. KEITHLEY
4191cded7Smrg
5191cded7SmrgPermission is hereby granted, free of charge, to any person obtaining
6191cded7Smrga copy of this software and associated documentation files (the
7191cded7Smrg"Software"), to deal in the Software without restriction, including
8191cded7Smrgwithout limitation the rights to use, copy, modify, merge, publish,
9191cded7Smrgdistribute, sublicense, and/or sell copies of the Software, and to
10191cded7Smrgpermit persons to whom the Software is furnished to do so, subject to
11191cded7Smrgthe following conditions:
12191cded7Smrg
13191cded7SmrgThe above copyright notice and this permission notice shall be
14191cded7Smrgincluded in all copies or substantial portions of the Software.
15191cded7Smrg
16191cded7SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17191cded7SmrgEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18191cded7SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19d9dcd5aeSmrgIN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES
20191cded7SmrgOR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21191cded7SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22191cded7SmrgOTHER DEALINGS IN THE SOFTWARE.
23191cded7Smrg
24d9dcd5aeSmrgExcept as contained in this notice, the name of Kaleb S. KEITHLEY
25d9dcd5aeSmrgshall not be used in advertising or otherwise to promote the sale, use
26191cded7Smrgor other dealings in this Software without prior written authorization
27191cded7Smrgfrom Kaleb S. KEITHLEY.
28191cded7Smrg
29191cded7Smrg*/
30191cded7Smrg
31191cded7Smrg/* THIS IS NOT AN X CONSORTIUM STANDARD */
32191cded7Smrg
33d9dcd5aeSmrg#ifdef HAVE_CONFIG_H
34d9dcd5aeSmrg#include <config.h>
35d9dcd5aeSmrg#endif
36d9dcd5aeSmrg
37191cded7Smrg#include <X11/Xlibint.h>
38b290cf36Smrg#include <X11/extensions/xf86vmproto.h>
39b290cf36Smrg#include <X11/extensions/xf86vmode.h>
40191cded7Smrg#include <X11/extensions/Xext.h>
41191cded7Smrg#include <X11/extensions/extutil.h>
42d9dcd5aeSmrg#include <limits.h>
43d9dcd5aeSmrg
44d9dcd5aeSmrg#ifndef HAVE__XEATDATAWORDS
45d9dcd5aeSmrgstatic inline void _XEatDataWords(Display *dpy, unsigned long n)
46d9dcd5aeSmrg{
47d9dcd5aeSmrg# ifndef LONG64
48d9dcd5aeSmrg    if (n >= (ULONG_MAX >> 2))
49d9dcd5aeSmrg        _XIOError(dpy);
50d9dcd5aeSmrg# endif
51d9dcd5aeSmrg    _XEatData (dpy, n << 2);
52d9dcd5aeSmrg}
53d9dcd5aeSmrg#endif
54191cded7Smrg
55191cded7Smrg#ifdef DEBUG
56191cded7Smrg#include <stdio.h>
57191cded7Smrg#endif
58191cded7Smrg
59191cded7Smrg#ifndef MODE_BAD
60191cded7Smrg#define MODE_BAD 255
61191cded7Smrg#endif
62191cded7Smrg
63191cded7Smrgstatic XExtensionInfo _xf86vidmode_info_data;
64191cded7Smrgstatic XExtensionInfo *xf86vidmode_info = &_xf86vidmode_info_data;
65d9dcd5aeSmrgstatic const char *xf86vidmode_extension_name = XF86VIDMODENAME;
66191cded7Smrg
67191cded7Smrg#define XF86VidModeCheckExtension(dpy,i,val) \
68191cded7Smrg  XextCheckExtension (dpy, i, xf86vidmode_extension_name, val)
69191cded7Smrg
70191cded7Smrg/*****************************************************************************
71191cded7Smrg *                                                                           *
72191cded7Smrg *			   private utility routines                          *
73191cded7Smrg *                                                                           *
74191cded7Smrg *****************************************************************************/
75191cded7Smrg
76191cded7Smrgstatic XEXT_CLOSE_DISPLAY_PROTO(close_display);
77191cded7Smrgstatic /* const */ XExtensionHooks xf86vidmode_extension_hooks = {
78191cded7Smrg    NULL,				/* create_gc */
79191cded7Smrg    NULL,				/* copy_gc */
80191cded7Smrg    NULL,				/* flush_gc */
81191cded7Smrg    NULL,				/* free_gc */
82191cded7Smrg    NULL,				/* create_font */
83191cded7Smrg    NULL,				/* free_font */
84191cded7Smrg    close_display,			/* close_display */
85191cded7Smrg    NULL,				/* wire_to_event */
86191cded7Smrg    NULL,				/* event_to_wire */
87191cded7Smrg    NULL,				/* error */
88191cded7Smrg    NULL,				/* error_string */
89191cded7Smrg};
90191cded7Smrg
91d9dcd5aeSmrgstatic XEXT_GENERATE_FIND_DISPLAY (find_display, xf86vidmode_info,
92d9dcd5aeSmrg				   xf86vidmode_extension_name,
93d9dcd5aeSmrg				   &xf86vidmode_extension_hooks,
94191cded7Smrg				   0, NULL)
95191cded7Smrg
96191cded7Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86vidmode_info)
97191cded7Smrg
98191cded7Smrg
99191cded7Smrg/*****************************************************************************
100191cded7Smrg *                                                                           *
101191cded7Smrg *		    public XFree86-VidMode Extension routines                *
102191cded7Smrg *                                                                           *
103191cded7Smrg *****************************************************************************/
104191cded7Smrg
105191cded7SmrgBool
106b290cf36SmrgXF86VidModeQueryExtension(Display *dpy, int *event_basep, int *error_basep)
107191cded7Smrg{
108191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
109191cded7Smrg
110191cded7Smrg    if (XextHasExtension(info)) {
111191cded7Smrg	*event_basep = info->codes->first_event;
112191cded7Smrg	*error_basep = info->codes->first_error;
113191cded7Smrg	return True;
114191cded7Smrg    } else {
115191cded7Smrg	return False;
116191cded7Smrg    }
117191cded7Smrg}
118191cded7Smrg
119191cded7SmrgBool
120b290cf36SmrgXF86VidModeQueryVersion(Display* dpy, int* majorVersion, int* minorVersion)
121191cded7Smrg{
122191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
123191cded7Smrg    xXF86VidModeQueryVersionReply rep;
124191cded7Smrg    xXF86VidModeQueryVersionReq *req;
125191cded7Smrg
126191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
127191cded7Smrg
128191cded7Smrg    LockDisplay(dpy);
129191cded7Smrg    GetReq(XF86VidModeQueryVersion, req);
130191cded7Smrg    req->reqType = info->codes->major_opcode;
131191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeQueryVersion;
132191cded7Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
133191cded7Smrg	UnlockDisplay(dpy);
134191cded7Smrg	SyncHandle();
135191cded7Smrg	return False;
136191cded7Smrg    }
137191cded7Smrg    *majorVersion = rep.majorVersion;
138191cded7Smrg    *minorVersion = rep.minorVersion;
139191cded7Smrg    UnlockDisplay(dpy);
140191cded7Smrg    SyncHandle();
141191cded7Smrg    if (*majorVersion >= 2)
142191cded7Smrg	XF86VidModeSetClientVersion(dpy);
143191cded7Smrg    return True;
144191cded7Smrg}
145191cded7Smrg
146191cded7SmrgBool
147191cded7SmrgXF86VidModeSetClientVersion(Display *dpy)
148191cded7Smrg{
149191cded7Smrg    XExtDisplayInfo *info = find_display(dpy);
150191cded7Smrg    xXF86VidModeSetClientVersionReq *req;
151191cded7Smrg
152191cded7Smrg    XF86VidModeCheckExtension(dpy, info, False);
153191cded7Smrg
154191cded7Smrg    LockDisplay(dpy);
155191cded7Smrg    GetReq(XF86VidModeSetClientVersion, req);
156191cded7Smrg    req->reqType = info->codes->major_opcode;
157191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSetClientVersion;
158191cded7Smrg    req->major = XF86VIDMODE_MAJOR_VERSION;
159191cded7Smrg    req->minor = XF86VIDMODE_MINOR_VERSION;
160191cded7Smrg    UnlockDisplay(dpy);
161191cded7Smrg    SyncHandle();
162191cded7Smrg    return True;
163191cded7Smrg}
164191cded7Smrg
165191cded7SmrgBool
166191cded7SmrgXF86VidModeSetGamma(Display *dpy, int screen, XF86VidModeGamma *Gamma)
167191cded7Smrg{
168191cded7Smrg    XExtDisplayInfo *info = find_display(dpy);
169191cded7Smrg    xXF86VidModeSetGammaReq *req;
170191cded7Smrg
171191cded7Smrg    XF86VidModeCheckExtension(dpy, info, False);
172191cded7Smrg
173191cded7Smrg    LockDisplay(dpy);
174191cded7Smrg    GetReq(XF86VidModeSetGamma, req);
175191cded7Smrg    req->reqType = info->codes->major_opcode;
176191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSetGamma;
177191cded7Smrg    req->screen = screen;
178191cded7Smrg    req->red = (CARD32)(Gamma->red * 10000.);
179191cded7Smrg    req->green = (CARD32)(Gamma->green * 10000.);
180191cded7Smrg    req->blue = (CARD32)(Gamma->blue * 10000.);
181191cded7Smrg    UnlockDisplay(dpy);
182191cded7Smrg    SyncHandle();
183191cded7Smrg    return True;
184191cded7Smrg}
185191cded7Smrg
186191cded7SmrgBool
187191cded7SmrgXF86VidModeGetGamma(Display *dpy, int screen, XF86VidModeGamma *Gamma)
188191cded7Smrg{
189191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
190191cded7Smrg    xXF86VidModeGetGammaReply rep;
191191cded7Smrg    xXF86VidModeGetGammaReq *req;
192191cded7Smrg
193191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
194191cded7Smrg
195191cded7Smrg    LockDisplay(dpy);
196191cded7Smrg    GetReq(XF86VidModeGetGamma, req);
197191cded7Smrg    req->reqType = info->codes->major_opcode;
198191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetGamma;
199191cded7Smrg    req->screen = screen;
200191cded7Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
201191cded7Smrg	UnlockDisplay(dpy);
202191cded7Smrg	SyncHandle();
203191cded7Smrg	return False;
204191cded7Smrg    }
205191cded7Smrg    Gamma->red = ((float)rep.red) / 10000.;
206191cded7Smrg    Gamma->green = ((float)rep.green) / 10000.;
207191cded7Smrg    Gamma->blue = ((float)rep.blue) / 10000.;
208191cded7Smrg    UnlockDisplay(dpy);
209191cded7Smrg    SyncHandle();
210191cded7Smrg    return True;
211191cded7Smrg}
212191cded7Smrg
213191cded7SmrgBool
214b290cf36SmrgXF86VidModeGetModeLine(Display* dpy, int screen, int* dotclock,
215b290cf36Smrg		       XF86VidModeModeLine* modeline)
216191cded7Smrg{
217191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
218191cded7Smrg    xXF86VidModeGetModeLineReply rep;
219191cded7Smrg    xXF86OldVidModeGetModeLineReply oldrep;
220191cded7Smrg    xXF86VidModeGetModeLineReq *req;
221191cded7Smrg    int majorVersion, minorVersion;
222d9dcd5aeSmrg    Bool result = True;
223191cded7Smrg
224191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
225191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
226191cded7Smrg
227191cded7Smrg    LockDisplay(dpy);
228191cded7Smrg    GetReq(XF86VidModeGetModeLine, req);
229191cded7Smrg    req->reqType = info->codes->major_opcode;
230191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetModeLine;
231191cded7Smrg    req->screen = screen;
232d9dcd5aeSmrg
233191cded7Smrg    if (majorVersion < 2) {
234d9dcd5aeSmrg	if (!_XReply(dpy, (xReply *)&oldrep,
235191cded7Smrg            (SIZEOF(xXF86OldVidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) {
236191cded7Smrg	    UnlockDisplay(dpy);
237191cded7Smrg	    SyncHandle();
238191cded7Smrg	    return False;
239191cded7Smrg	}
240191cded7Smrg	*dotclock = oldrep.dotclock;
241191cded7Smrg	modeline->hdisplay   = oldrep.hdisplay;
242191cded7Smrg	modeline->hsyncstart = oldrep.hsyncstart;
243191cded7Smrg	modeline->hsyncend   = oldrep.hsyncend;
244191cded7Smrg	modeline->htotal     = oldrep.htotal;
245191cded7Smrg	modeline->hskew      = 0;
246191cded7Smrg	modeline->vdisplay   = oldrep.vdisplay;
247191cded7Smrg	modeline->vsyncstart = oldrep.vsyncstart;
248191cded7Smrg	modeline->vsyncend   = oldrep.vsyncend;
249191cded7Smrg	modeline->vtotal     = oldrep.vtotal;
250191cded7Smrg	modeline->flags      = oldrep.flags;
251191cded7Smrg	modeline->privsize   = oldrep.privsize;
252191cded7Smrg    } else {
253d9dcd5aeSmrg	if (!_XReply(dpy, (xReply *)&rep,
254191cded7Smrg            (SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) {
255191cded7Smrg	    UnlockDisplay(dpy);
256191cded7Smrg	    SyncHandle();
257191cded7Smrg	    return False;
258191cded7Smrg	}
259191cded7Smrg	*dotclock = rep.dotclock;
260191cded7Smrg	modeline->hdisplay   = rep.hdisplay;
261191cded7Smrg	modeline->hsyncstart = rep.hsyncstart;
262191cded7Smrg	modeline->hsyncend   = rep.hsyncend;
263191cded7Smrg	modeline->htotal     = rep.htotal;
264191cded7Smrg	modeline->hskew      = rep.hskew;
265191cded7Smrg	modeline->vdisplay   = rep.vdisplay;
266191cded7Smrg	modeline->vsyncstart = rep.vsyncstart;
267191cded7Smrg	modeline->vsyncend   = rep.vsyncend;
268191cded7Smrg	modeline->vtotal     = rep.vtotal;
269191cded7Smrg	modeline->flags      = rep.flags;
270191cded7Smrg	modeline->privsize   = rep.privsize;
271191cded7Smrg    }
272d9dcd5aeSmrg
273191cded7Smrg    if (modeline->privsize > 0) {
274d9dcd5aeSmrg	if (modeline->privsize < (INT_MAX / sizeof(INT32)))
275d9dcd5aeSmrg	    modeline->private = Xcalloc(modeline->privsize, sizeof(INT32));
276d9dcd5aeSmrg	else
277d9dcd5aeSmrg	    modeline->private = NULL;
278d9dcd5aeSmrg	if (modeline->private == NULL) {
279d9dcd5aeSmrg	    _XEatDataWords(dpy, rep.length -
280d9dcd5aeSmrg		((SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2));
281d9dcd5aeSmrg	    result = False;
282d9dcd5aeSmrg	} else
283d9dcd5aeSmrg	    _XRead(dpy, (char*)modeline->private, modeline->privsize * sizeof(INT32));
284191cded7Smrg    } else {
285191cded7Smrg	modeline->private = NULL;
286191cded7Smrg    }
287191cded7Smrg    UnlockDisplay(dpy);
288191cded7Smrg    SyncHandle();
289d9dcd5aeSmrg    return result;
290191cded7Smrg}
291191cded7Smrg
292191cded7SmrgBool
293b290cf36SmrgXF86VidModeGetAllModeLines(Display* dpy, int screen, int* modecount,
294b290cf36Smrg			   XF86VidModeModeInfo ***modelinesPtr)
295191cded7Smrg{
296191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
297191cded7Smrg    xXF86VidModeGetAllModeLinesReply rep;
298191cded7Smrg    xXF86VidModeGetAllModeLinesReq *req;
299191cded7Smrg    XF86VidModeModeInfo *mdinfptr, **modelines;
300191cded7Smrg    xXF86VidModeModeInfo xmdline;
301191cded7Smrg    xXF86OldVidModeModeInfo oldxmdline;
302191cded7Smrg    int i;
303191cded7Smrg    int majorVersion, minorVersion;
304191cded7Smrg    Bool protocolBug = False;
305191cded7Smrg
306191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
307191cded7Smrg
308191cded7Smrg    /*
309191cded7Smrg     * Note: There was a bug in the protocol implementation in versions
310191cded7Smrg     * 0.x with x < 8 (the .private field wasn't being passed over the wire).
311191cded7Smrg     * Check the server's version, and accept the old format if appropriate.
312191cded7Smrg     */
313191cded7Smrg
314191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
315191cded7Smrg    if (majorVersion == 0 && minorVersion < 8) {
316191cded7Smrg	protocolBug = True;
317191cded7Smrg#ifdef DEBUG
318191cded7Smrg	fprintf(stderr, "XF86VidModeGetAllModeLines: Warning: Xserver is"
319191cded7Smrg		"running an old version (%d.%d)\n", majorVersion,
320191cded7Smrg		minorVersion);
321191cded7Smrg#endif
322191cded7Smrg    }
323d9dcd5aeSmrg
324191cded7Smrg    LockDisplay(dpy);
325191cded7Smrg    GetReq(XF86VidModeGetAllModeLines, req);
326191cded7Smrg    req->reqType = info->codes->major_opcode;
327191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetAllModeLines;
328191cded7Smrg    req->screen = screen;
329d9dcd5aeSmrg    if (!_XReply(dpy, (xReply *)&rep,
330191cded7Smrg        (SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2, xFalse)) {
331191cded7Smrg        UnlockDisplay(dpy);
332191cded7Smrg	SyncHandle();
333191cded7Smrg	return False;
334191cded7Smrg    }
335191cded7Smrg
336191cded7Smrg    *modecount = rep.modecount;
337191cded7Smrg
338191cded7Smrg    if (!(modelines = (XF86VidModeModeInfo **) Xcalloc(rep.modecount,
339191cded7Smrg                                          sizeof(XF86VidModeModeInfo *)
340191cded7Smrg                                          +sizeof(XF86VidModeModeInfo)))) {
341d9dcd5aeSmrg	_XEatDataWords(dpy, rep.length -
342d9dcd5aeSmrg	    ((SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2));
343d9dcd5aeSmrg	UnlockDisplay(dpy);
344d9dcd5aeSmrg	SyncHandle();
345191cded7Smrg        return False;
346191cded7Smrg    }
347191cded7Smrg    mdinfptr = (XF86VidModeModeInfo *) (
348191cded7Smrg			    (char *) modelines
349191cded7Smrg			    + rep.modecount*sizeof(XF86VidModeModeInfo *)
350191cded7Smrg		    );
351191cded7Smrg
352191cded7Smrg    for (i = 0; i < rep.modecount; i++) {
353191cded7Smrg        modelines[i] = mdinfptr++;
354191cded7Smrg	if (majorVersion < 2) {
355191cded7Smrg            _XRead(dpy, (char*)&oldxmdline, sizeof(xXF86OldVidModeModeInfo));
356191cded7Smrg	    modelines[i]->dotclock   = oldxmdline.dotclock;
357191cded7Smrg	    modelines[i]->hdisplay   = oldxmdline.hdisplay;
358191cded7Smrg	    modelines[i]->hsyncstart = oldxmdline.hsyncstart;
359191cded7Smrg	    modelines[i]->hsyncend   = oldxmdline.hsyncend;
360191cded7Smrg	    modelines[i]->htotal     = oldxmdline.htotal;
361191cded7Smrg	    modelines[i]->hskew      = 0;
362191cded7Smrg	    modelines[i]->vdisplay   = oldxmdline.vdisplay;
363191cded7Smrg	    modelines[i]->vsyncstart = oldxmdline.vsyncstart;
364191cded7Smrg	    modelines[i]->vsyncend   = oldxmdline.vsyncend;
365191cded7Smrg	    modelines[i]->vtotal     = oldxmdline.vtotal;
366191cded7Smrg	    modelines[i]->flags      = oldxmdline.flags;
367191cded7Smrg	    if (protocolBug) {
368191cded7Smrg		modelines[i]->privsize = 0;
369191cded7Smrg		modelines[i]->private = NULL;
370191cded7Smrg	    } else {
371191cded7Smrg		modelines[i]->privsize   = oldxmdline.privsize;
372191cded7Smrg		if (oldxmdline.privsize > 0) {
373191cded7Smrg	            if (!(modelines[i]->private =
374191cded7Smrg			    Xcalloc(oldxmdline.privsize, sizeof(INT32)))) {
375d9dcd5aeSmrg			_XEatDataWords(dpy, oldxmdline.privsize);
376191cded7Smrg		    } else {
377191cded7Smrg			_XRead(dpy, (char*)modelines[i]->private,
378191cded7Smrg			     oldxmdline.privsize * sizeof(INT32));
379191cded7Smrg		    }
380191cded7Smrg		} else {
381191cded7Smrg		  modelines[i]->private = NULL;
382191cded7Smrg		}
383191cded7Smrg	    }
384191cded7Smrg	} else {
385191cded7Smrg            _XRead(dpy, (char*)&xmdline, sizeof(xXF86VidModeModeInfo));
386191cded7Smrg	    modelines[i]->dotclock   = xmdline.dotclock;
387191cded7Smrg	    modelines[i]->hdisplay   = xmdline.hdisplay;
388191cded7Smrg	    modelines[i]->hsyncstart = xmdline.hsyncstart;
389191cded7Smrg	    modelines[i]->hsyncend   = xmdline.hsyncend;
390191cded7Smrg	    modelines[i]->htotal     = xmdline.htotal;
391191cded7Smrg	    modelines[i]->hskew      = xmdline.hskew;
392191cded7Smrg	    modelines[i]->vdisplay   = xmdline.vdisplay;
393191cded7Smrg	    modelines[i]->vsyncstart = xmdline.vsyncstart;
394191cded7Smrg	    modelines[i]->vsyncend   = xmdline.vsyncend;
395191cded7Smrg	    modelines[i]->vtotal     = xmdline.vtotal;
396191cded7Smrg	    modelines[i]->flags      = xmdline.flags;
397191cded7Smrg	    if (protocolBug) {
398191cded7Smrg		modelines[i]->privsize = 0;
399191cded7Smrg		modelines[i]->private = NULL;
400191cded7Smrg	    } else {
401191cded7Smrg		modelines[i]->privsize   = xmdline.privsize;
402191cded7Smrg		if (xmdline.privsize > 0) {
403191cded7Smrg		    if (!(modelines[i]->private =
404191cded7Smrg			    Xcalloc(xmdline.privsize, sizeof(INT32)))) {
405d9dcd5aeSmrg			_XEatDataWords(dpy, xmdline.privsize);
406191cded7Smrg		    } else {
407191cded7Smrg			_XRead(dpy, (char*)modelines[i]->private,
408191cded7Smrg			     xmdline.privsize * sizeof(INT32));
409191cded7Smrg		    }
410191cded7Smrg		} else {
411191cded7Smrg		    modelines[i]->private = NULL;
412191cded7Smrg		}
413191cded7Smrg	    }
414191cded7Smrg	}
415191cded7Smrg    }
416191cded7Smrg    *modelinesPtr = modelines;
417191cded7Smrg    UnlockDisplay(dpy);
418191cded7Smrg    SyncHandle();
419191cded7Smrg    return True;
420191cded7Smrg}
421191cded7Smrg
422191cded7Smrg/*
423191cded7Smrg * GetReq replacement for use with VidMode protocols earlier than 2.0
424191cded7Smrg */
425191cded7Smrg#if !defined(UNIXCPP) || defined(ANSICPP)
426191cded7Smrg#define GetOldReq(name, oldname, req) \
427191cded7Smrg        WORD64ALIGN\
428191cded7Smrg	if ((dpy->bufptr + SIZEOF(x##oldname##Req)) > dpy->bufmax)\
429191cded7Smrg		_XFlush(dpy);\
430191cded7Smrg	req = (x##oldname##Req *)(dpy->last_req = dpy->bufptr);\
431191cded7Smrg	req->reqType = X_##name;\
432191cded7Smrg	req->length = (SIZEOF(x##oldname##Req))>>2;\
433191cded7Smrg	dpy->bufptr += SIZEOF(x##oldname##Req);\
434191cded7Smrg	dpy->request++
435191cded7Smrg
436191cded7Smrg#else  /* non-ANSI C uses empty comment instead of "##" for token concatenation */
437191cded7Smrg#define GetOldReq(name, oldname, req) \
438191cded7Smrg        WORD64ALIGN\
439191cded7Smrg	if ((dpy->bufptr + SIZEOF(x/**/oldname/**/Req)) > dpy->bufmax)\
440191cded7Smrg		_XFlush(dpy);\
441191cded7Smrg	req = (x/**/oldname/**/Req *)(dpy->last_req = dpy->bufptr);\
442191cded7Smrg	req->reqType = X_/**/name;\
443191cded7Smrg	req->length = (SIZEOF(x/**/oldname/**/Req))>>2;\
444191cded7Smrg	dpy->bufptr += SIZEOF(x/**/oldname/**/Req);\
445191cded7Smrg	dpy->request++
446191cded7Smrg#endif
447191cded7Smrg
448191cded7SmrgBool
449b290cf36SmrgXF86VidModeAddModeLine(Display *dpy, int screen,
450b290cf36Smrg		       XF86VidModeModeInfo* newmodeline,
451b290cf36Smrg		       XF86VidModeModeInfo* aftermodeline)
452191cded7Smrg{
453191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
454191cded7Smrg    xXF86VidModeAddModeLineReq *req;
455191cded7Smrg    xXF86OldVidModeAddModeLineReq *oldreq;
456191cded7Smrg    int majorVersion, minorVersion;
457191cded7Smrg
458191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
459191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
460191cded7Smrg
461191cded7Smrg    LockDisplay(dpy);
462191cded7Smrg    if (majorVersion < 2) {
463191cded7Smrg	GetOldReq(XF86VidModeAddModeLine, XF86OldVidModeAddModeLine, oldreq);
464191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
465191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeAddModeLine;
466191cded7Smrg	oldreq->screen = screen;
467191cded7Smrg	oldreq->dotclock =	newmodeline->dotclock;
468191cded7Smrg	oldreq->hdisplay =	newmodeline->hdisplay;
469191cded7Smrg	oldreq->hsyncstart =	newmodeline->hsyncstart;
470191cded7Smrg	oldreq->hsyncend =	newmodeline->hsyncend;
471191cded7Smrg	oldreq->htotal =	newmodeline->htotal;
472191cded7Smrg	oldreq->vdisplay =	newmodeline->vdisplay;
473191cded7Smrg	oldreq->vsyncstart =	newmodeline->vsyncstart;
474191cded7Smrg	oldreq->vsyncend =	newmodeline->vsyncend;
475191cded7Smrg	oldreq->vtotal =	newmodeline->vtotal;
476191cded7Smrg	oldreq->flags =		newmodeline->flags;
477191cded7Smrg	oldreq->privsize =	newmodeline->privsize;
478191cded7Smrg	if (aftermodeline != NULL) {
479191cded7Smrg	    oldreq->after_dotclock =	aftermodeline->dotclock;
480191cded7Smrg	    oldreq->after_hdisplay =	aftermodeline->hdisplay;
481191cded7Smrg	    oldreq->after_hsyncstart =	aftermodeline->hsyncstart;
482191cded7Smrg	    oldreq->after_hsyncend =	aftermodeline->hsyncend;
483191cded7Smrg	    oldreq->after_htotal =	aftermodeline->htotal;
484191cded7Smrg	    oldreq->after_vdisplay =	aftermodeline->vdisplay;
485191cded7Smrg	    oldreq->after_vsyncstart =	aftermodeline->vsyncstart;
486191cded7Smrg	    oldreq->after_vsyncend =	aftermodeline->vsyncend;
487191cded7Smrg	    oldreq->after_vtotal =	aftermodeline->vtotal;
488191cded7Smrg	    oldreq->after_flags =	aftermodeline->flags;
489191cded7Smrg	} else {
490191cded7Smrg	    oldreq->after_dotclock =	0;
491191cded7Smrg	    oldreq->after_hdisplay =	0;
492191cded7Smrg	    oldreq->after_hsyncstart =	0;
493191cded7Smrg	    oldreq->after_hsyncend =	0;
494191cded7Smrg	    oldreq->after_htotal =	0;
495191cded7Smrg	    oldreq->after_vdisplay =	0;
496191cded7Smrg	    oldreq->after_vsyncstart =	0;
497191cded7Smrg	    oldreq->after_vsyncend =	0;
498191cded7Smrg	    oldreq->after_vtotal =	0;
499191cded7Smrg	    oldreq->after_flags =	0;
500191cded7Smrg	}
501191cded7Smrg	if (newmodeline->privsize) {
502191cded7Smrg	    oldreq->length += newmodeline->privsize;
503191cded7Smrg	    Data32(dpy, (long *) newmodeline->private,
504191cded7Smrg	       newmodeline->privsize * sizeof(INT32));
505191cded7Smrg	}
506191cded7Smrg    } else {
507191cded7Smrg	GetReq(XF86VidModeAddModeLine, req);
508191cded7Smrg	req->reqType = info->codes->major_opcode;
509191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeAddModeLine;
510191cded7Smrg	req->screen = screen;
511191cded7Smrg	req->dotclock =		newmodeline->dotclock;
512191cded7Smrg	req->hdisplay =		newmodeline->hdisplay;
513191cded7Smrg	req->hsyncstart =	newmodeline->hsyncstart;
514191cded7Smrg	req->hsyncend =		newmodeline->hsyncend;
515191cded7Smrg	req->htotal =		newmodeline->htotal;
516191cded7Smrg	req->hskew =		newmodeline->hskew;
517191cded7Smrg	req->vdisplay =		newmodeline->vdisplay;
518191cded7Smrg	req->vsyncstart =	newmodeline->vsyncstart;
519191cded7Smrg	req->vsyncend =		newmodeline->vsyncend;
520191cded7Smrg	req->vtotal =		newmodeline->vtotal;
521191cded7Smrg	req->flags =		newmodeline->flags;
522191cded7Smrg	req->privsize =		newmodeline->privsize;
523191cded7Smrg	if (aftermodeline != NULL) {
524191cded7Smrg	    req->after_dotclock =	aftermodeline->dotclock;
525191cded7Smrg	    req->after_hdisplay =	aftermodeline->hdisplay;
526191cded7Smrg	    req->after_hsyncstart =	aftermodeline->hsyncstart;
527191cded7Smrg	    req->after_hsyncend =	aftermodeline->hsyncend;
528191cded7Smrg	    req->after_htotal =		aftermodeline->htotal;
529191cded7Smrg	    req->after_hskew =		aftermodeline->hskew;
530191cded7Smrg	    req->after_vdisplay =	aftermodeline->vdisplay;
531191cded7Smrg	    req->after_vsyncstart =	aftermodeline->vsyncstart;
532191cded7Smrg	    req->after_vsyncend =	aftermodeline->vsyncend;
533191cded7Smrg	    req->after_vtotal =		aftermodeline->vtotal;
534191cded7Smrg	    req->after_flags =		aftermodeline->flags;
535191cded7Smrg	} else {
536191cded7Smrg	    req->after_dotclock =	0;
537191cded7Smrg	    req->after_hdisplay =	0;
538191cded7Smrg	    req->after_hsyncstart =	0;
539191cded7Smrg	    req->after_hsyncend =	0;
540191cded7Smrg	    req->after_htotal =		0;
541191cded7Smrg	    req->after_hskew =		0;
542191cded7Smrg	    req->after_vdisplay =	0;
543191cded7Smrg	    req->after_vsyncstart =	0;
544191cded7Smrg	    req->after_vsyncend =	0;
545191cded7Smrg	    req->after_vtotal =		0;
546191cded7Smrg	    req->after_flags =		0;
547191cded7Smrg	}
548191cded7Smrg	if (newmodeline->privsize) {
549191cded7Smrg	    req->length += newmodeline->privsize;
550191cded7Smrg	    Data32(dpy, (long *) newmodeline->private,
551191cded7Smrg	       newmodeline->privsize * sizeof(INT32));
552191cded7Smrg	}
553191cded7Smrg    }
554191cded7Smrg    UnlockDisplay(dpy);
555191cded7Smrg    SyncHandle();
556191cded7Smrg    return True;
557191cded7Smrg}
558191cded7Smrg
559191cded7SmrgBool
560b290cf36SmrgXF86VidModeDeleteModeLine(Display *dpy, int screen,
561b290cf36Smrg			  XF86VidModeModeInfo* modeline)
562191cded7Smrg{
563191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
564191cded7Smrg    xXF86VidModeDeleteModeLineReq *req;
565191cded7Smrg    xXF86OldVidModeDeleteModeLineReq *oldreq;
566191cded7Smrg    int majorVersion, minorVersion;
567191cded7Smrg
568191cded7Smrg    XF86VidModeCheckExtension (dpy, info, 0);
569191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
570191cded7Smrg
571191cded7Smrg    LockDisplay(dpy);
572191cded7Smrg    if (majorVersion < 2) {
573191cded7Smrg	GetOldReq(XF86VidModeDeleteModeLine, XF86OldVidModeDeleteModeLine, oldreq);
574191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
575191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine;
576191cded7Smrg	oldreq->screen = screen;
577191cded7Smrg	oldreq->dotclock =	modeline->dotclock;
578191cded7Smrg	oldreq->hdisplay =	modeline->hdisplay;
579191cded7Smrg	oldreq->hsyncstart =	modeline->hsyncstart;
580191cded7Smrg	oldreq->hsyncend =	modeline->hsyncend;
581191cded7Smrg	oldreq->htotal =	modeline->htotal;
582191cded7Smrg	oldreq->vdisplay =	modeline->vdisplay;
583191cded7Smrg	oldreq->vsyncstart =	modeline->vsyncstart;
584191cded7Smrg	oldreq->vsyncend =	modeline->vsyncend;
585191cded7Smrg	oldreq->vtotal =	modeline->vtotal;
586191cded7Smrg	oldreq->flags =		modeline->flags;
587191cded7Smrg	oldreq->privsize =	modeline->privsize;
588191cded7Smrg	if (modeline->privsize) {
589191cded7Smrg	    oldreq->length += modeline->privsize;
590191cded7Smrg	    Data32(dpy, (long *) modeline->private,
591191cded7Smrg	       modeline->privsize * sizeof(INT32));
592191cded7Smrg	}
593191cded7Smrg    } else {
594191cded7Smrg	GetReq(XF86VidModeDeleteModeLine, req);
595191cded7Smrg	req->reqType = info->codes->major_opcode;
596191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine;
597191cded7Smrg	req->screen = screen;
598191cded7Smrg	req->dotclock =		modeline->dotclock;
599191cded7Smrg	req->hdisplay =		modeline->hdisplay;
600191cded7Smrg	req->hsyncstart =	modeline->hsyncstart;
601191cded7Smrg	req->hsyncend =		modeline->hsyncend;
602191cded7Smrg	req->htotal =		modeline->htotal;
603191cded7Smrg	req->hskew =		modeline->hskew;
604191cded7Smrg	req->vdisplay =		modeline->vdisplay;
605191cded7Smrg	req->vsyncstart =	modeline->vsyncstart;
606191cded7Smrg	req->vsyncend =		modeline->vsyncend;
607191cded7Smrg	req->vtotal =		modeline->vtotal;
608191cded7Smrg	req->flags =		modeline->flags;
609191cded7Smrg	req->privsize =		modeline->privsize;
610191cded7Smrg	if (modeline->privsize) {
611191cded7Smrg	    req->length += modeline->privsize;
612191cded7Smrg	    Data32(dpy, (long *) modeline->private,
613191cded7Smrg	       modeline->privsize * sizeof(INT32));
614191cded7Smrg	}
615191cded7Smrg    }
616191cded7Smrg    UnlockDisplay(dpy);
617191cded7Smrg    SyncHandle();
618191cded7Smrg    return True;
619191cded7Smrg}
620191cded7Smrg
621191cded7SmrgBool
622b290cf36SmrgXF86VidModeModModeLine(Display *dpy, int screen, XF86VidModeModeLine* modeline)
623191cded7Smrg{
624191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
625191cded7Smrg    xXF86VidModeModModeLineReq *req;
626191cded7Smrg    xXF86OldVidModeModModeLineReq *oldreq;
627191cded7Smrg    int majorVersion, minorVersion;
628191cded7Smrg
629191cded7Smrg    XF86VidModeCheckExtension (dpy, info, 0);
630191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
631191cded7Smrg
632191cded7Smrg    LockDisplay(dpy);
633191cded7Smrg    if (majorVersion < 2) {
634191cded7Smrg	GetOldReq(XF86VidModeModModeLine, XF86OldVidModeModModeLine, oldreq);
635191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
636191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeModModeLine;
637191cded7Smrg	oldreq->screen = screen;
638191cded7Smrg	oldreq->hdisplay =	modeline->hdisplay;
639191cded7Smrg	oldreq->hsyncstart =	modeline->hsyncstart;
640191cded7Smrg	oldreq->hsyncend =	modeline->hsyncend;
641191cded7Smrg	oldreq->htotal =	modeline->htotal;
642191cded7Smrg	oldreq->vdisplay =	modeline->vdisplay;
643191cded7Smrg	oldreq->vsyncstart =	modeline->vsyncstart;
644191cded7Smrg	oldreq->vsyncend =	modeline->vsyncend;
645191cded7Smrg	oldreq->vtotal =	modeline->vtotal;
646191cded7Smrg	oldreq->flags =		modeline->flags;
647191cded7Smrg	oldreq->privsize =	modeline->privsize;
648191cded7Smrg	if (modeline->privsize) {
649191cded7Smrg	    oldreq->length += modeline->privsize;
650191cded7Smrg	    Data32(dpy, (long *) modeline->private,
651191cded7Smrg	       modeline->privsize * sizeof(INT32));
652191cded7Smrg	}
653191cded7Smrg    } else {
654191cded7Smrg	GetReq(XF86VidModeModModeLine, req);
655191cded7Smrg	req->reqType = info->codes->major_opcode;
656191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeModModeLine;
657191cded7Smrg	req->screen = screen;
658191cded7Smrg	req->hdisplay =		modeline->hdisplay;
659191cded7Smrg	req->hsyncstart =	modeline->hsyncstart;
660191cded7Smrg	req->hsyncend =		modeline->hsyncend;
661191cded7Smrg	req->htotal =		modeline->htotal;
662191cded7Smrg	req->hskew =		modeline->hskew;
663191cded7Smrg	req->vdisplay =		modeline->vdisplay;
664191cded7Smrg	req->vsyncstart =	modeline->vsyncstart;
665191cded7Smrg	req->vsyncend =		modeline->vsyncend;
666191cded7Smrg	req->vtotal =		modeline->vtotal;
667191cded7Smrg	req->flags =		modeline->flags;
668191cded7Smrg	req->privsize =		modeline->privsize;
669191cded7Smrg	if (modeline->privsize) {
670191cded7Smrg	    req->length += modeline->privsize;
671191cded7Smrg	    Data32(dpy, (long *) modeline->private,
672191cded7Smrg	       modeline->privsize * sizeof(INT32));
673191cded7Smrg	}
674191cded7Smrg    }
675191cded7Smrg    UnlockDisplay(dpy);
676191cded7Smrg    SyncHandle();
677191cded7Smrg    return True;
678191cded7Smrg}
679191cded7Smrg
680191cded7SmrgStatus
681b290cf36SmrgXF86VidModeValidateModeLine(Display *dpy, int screen,
682b290cf36Smrg			    XF86VidModeModeInfo* modeline)
683191cded7Smrg{
684191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
685191cded7Smrg    xXF86VidModeValidateModeLineReq *req;
686191cded7Smrg    xXF86OldVidModeValidateModeLineReq *oldreq;
687191cded7Smrg    xXF86VidModeValidateModeLineReply rep;
688191cded7Smrg    int majorVersion, minorVersion;
689191cded7Smrg
690191cded7Smrg    XF86VidModeCheckExtension (dpy, info, 0);
691191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
692191cded7Smrg
693191cded7Smrg    LockDisplay(dpy);
694191cded7Smrg
695191cded7Smrg    if (majorVersion < 2) {
696191cded7Smrg	GetOldReq(XF86VidModeValidateModeLine, XF86OldVidModeValidateModeLine, oldreq);
697191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
698191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeValidateModeLine;
699191cded7Smrg	oldreq->screen = screen;
700191cded7Smrg	oldreq->dotclock =	modeline->dotclock;
701191cded7Smrg	oldreq->hdisplay =	modeline->hdisplay;
702191cded7Smrg	oldreq->hsyncstart =	modeline->hsyncstart;
703191cded7Smrg	oldreq->hsyncend =	modeline->hsyncend;
704191cded7Smrg	oldreq->htotal =	modeline->htotal;
705191cded7Smrg	oldreq->vdisplay =	modeline->vdisplay;
706191cded7Smrg	oldreq->vsyncstart =	modeline->vsyncstart;
707191cded7Smrg	oldreq->vsyncend =	modeline->vsyncend;
708191cded7Smrg	oldreq->vtotal =	modeline->vtotal;
709191cded7Smrg	oldreq->flags =		modeline->flags;
710191cded7Smrg	oldreq->privsize =	modeline->privsize;
711191cded7Smrg	if (modeline->privsize) {
712191cded7Smrg	    oldreq->length += modeline->privsize;
713191cded7Smrg	    Data32(dpy, (long *) modeline->private,
714191cded7Smrg	       modeline->privsize * sizeof(INT32));
715191cded7Smrg	}
716191cded7Smrg    } else {
717191cded7Smrg	GetReq(XF86VidModeValidateModeLine, req);
718191cded7Smrg	req->reqType = info->codes->major_opcode;
719191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeValidateModeLine;
720191cded7Smrg	req->screen = screen;
721191cded7Smrg	req->dotclock =		modeline->dotclock;
722191cded7Smrg	req->hdisplay =		modeline->hdisplay;
723191cded7Smrg	req->hsyncstart =	modeline->hsyncstart;
724191cded7Smrg	req->hsyncend =		modeline->hsyncend;
725191cded7Smrg	req->htotal =		modeline->htotal;
726191cded7Smrg	req->hskew =		modeline->hskew;
727191cded7Smrg	req->vdisplay =		modeline->vdisplay;
728191cded7Smrg	req->vsyncstart =	modeline->vsyncstart;
729191cded7Smrg	req->vsyncend =		modeline->vsyncend;
730191cded7Smrg	req->vtotal =		modeline->vtotal;
731191cded7Smrg	req->flags =		modeline->flags;
732191cded7Smrg	req->privsize =		modeline->privsize;
733191cded7Smrg	if (modeline->privsize) {
734191cded7Smrg	    req->length += modeline->privsize;
735191cded7Smrg	    Data32(dpy, (long *) modeline->private,
736191cded7Smrg	       modeline->privsize * sizeof(INT32));
737191cded7Smrg	}
738191cded7Smrg    }
739191cded7Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
740191cded7Smrg	UnlockDisplay(dpy);
741191cded7Smrg	SyncHandle();
742191cded7Smrg	return MODE_BAD;
743191cded7Smrg    }
744191cded7Smrg    UnlockDisplay(dpy);
745191cded7Smrg    SyncHandle();
746191cded7Smrg    return rep.status;
747191cded7Smrg}
748191cded7Smrg
749191cded7SmrgBool
750b290cf36SmrgXF86VidModeSwitchMode(Display* dpy, int screen, int zoom)
751191cded7Smrg{
752191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
753191cded7Smrg    xXF86VidModeSwitchModeReq *req;
754191cded7Smrg
755191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
756191cded7Smrg
757191cded7Smrg    LockDisplay(dpy);
758191cded7Smrg    GetReq(XF86VidModeSwitchMode, req);
759191cded7Smrg    req->reqType = info->codes->major_opcode;
760191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSwitchMode;
761191cded7Smrg    req->screen = screen;
762191cded7Smrg    req->zoom = zoom;
763191cded7Smrg    UnlockDisplay(dpy);
764191cded7Smrg    SyncHandle();
765191cded7Smrg    return True;
766191cded7Smrg}
767d9dcd5aeSmrg
768191cded7SmrgBool
769b290cf36SmrgXF86VidModeSwitchToMode(Display* dpy, int screen, XF86VidModeModeInfo* modeline)
770191cded7Smrg{
771191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
772191cded7Smrg    xXF86VidModeSwitchToModeReq *req;
773191cded7Smrg    xXF86OldVidModeSwitchToModeReq *oldreq;
774191cded7Smrg    int majorVersion, minorVersion;
775191cded7Smrg    Bool protocolBug = False;
776191cded7Smrg
777191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
778191cded7Smrg
779191cded7Smrg    /*
780191cded7Smrg     * Note: There was a bug in the protocol implementation in versions
781191cded7Smrg     * 0.x with x < 8 (the .private field wasn't expected to be sent over
782191cded7Smrg     * the wire).  Check the server's version, and accept the old format
783191cded7Smrg     * if appropriate.
784191cded7Smrg     */
785191cded7Smrg
786191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
787191cded7Smrg    if (majorVersion == 0 && minorVersion < 8) {
788191cded7Smrg	protocolBug = True;
789191cded7Smrg#ifdef DEBUG
790191cded7Smrg	fprintf(stderr, "XF86VidModeSwitchToMode: Warning: Xserver is"
791191cded7Smrg		"running an old version (%d.%d)\n", majorVersion,
792191cded7Smrg		minorVersion);
793191cded7Smrg#endif
794191cded7Smrg    }
795d9dcd5aeSmrg
796191cded7Smrg    LockDisplay(dpy);
797191cded7Smrg    if (majorVersion < 2) {
798191cded7Smrg	GetOldReq(XF86VidModeSwitchToMode, XF86OldVidModeSwitchToMode, oldreq);
799191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
800191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeSwitchToMode;
801191cded7Smrg	oldreq->screen = screen;
802191cded7Smrg	oldreq->dotclock =	modeline->dotclock;
803191cded7Smrg	oldreq->hdisplay =	modeline->hdisplay;
804191cded7Smrg	oldreq->hsyncstart =	modeline->hsyncstart;
805191cded7Smrg	oldreq->hsyncend =	modeline->hsyncend;
806191cded7Smrg	oldreq->htotal =	modeline->htotal;
807191cded7Smrg	oldreq->vdisplay =	modeline->vdisplay;
808191cded7Smrg	oldreq->vsyncstart =	modeline->vsyncstart;
809191cded7Smrg	oldreq->vsyncend =	modeline->vsyncend;
810191cded7Smrg	oldreq->vtotal =	modeline->vtotal;
811191cded7Smrg	oldreq->flags =	modeline->flags;
812191cded7Smrg	if (protocolBug) {
813191cded7Smrg	    oldreq->privsize = 0;
814191cded7Smrg	} else {
815191cded7Smrg	    oldreq->privsize =	modeline->privsize;
816191cded7Smrg	    if (modeline->privsize) {
817191cded7Smrg		oldreq->length += modeline->privsize;
818191cded7Smrg		Data32(dpy, (long *) modeline->private,
819191cded7Smrg	           modeline->privsize * sizeof(INT32));
820191cded7Smrg	    }
821191cded7Smrg	}
822191cded7Smrg    } else {
823191cded7Smrg	GetReq(XF86VidModeSwitchToMode, req);
824191cded7Smrg	req->reqType = info->codes->major_opcode;
825191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeSwitchToMode;
826191cded7Smrg	req->screen = screen;
827191cded7Smrg	req->dotclock =	modeline->dotclock;
828191cded7Smrg	req->hdisplay =	modeline->hdisplay;
829191cded7Smrg	req->hsyncstart =	modeline->hsyncstart;
830191cded7Smrg	req->hsyncend =	modeline->hsyncend;
831191cded7Smrg	req->htotal =	modeline->htotal;
832191cded7Smrg	req->hskew =	modeline->hskew;
833191cded7Smrg	req->vdisplay =	modeline->vdisplay;
834191cded7Smrg	req->vsyncstart =	modeline->vsyncstart;
835191cded7Smrg	req->vsyncend =	modeline->vsyncend;
836191cded7Smrg	req->vtotal =	modeline->vtotal;
837191cded7Smrg	req->flags =	modeline->flags;
838191cded7Smrg	if (protocolBug) {
839191cded7Smrg	    req->privsize = 0;
840191cded7Smrg	} else {
841191cded7Smrg	    req->privsize =	modeline->privsize;
842191cded7Smrg	    if (modeline->privsize) {
843191cded7Smrg		req->length += modeline->privsize;
844191cded7Smrg		Data32(dpy, (long *) modeline->private,
845191cded7Smrg	           modeline->privsize * sizeof(INT32));
846191cded7Smrg	    }
847191cded7Smrg	}
848191cded7Smrg    }
849191cded7Smrg    UnlockDisplay(dpy);
850191cded7Smrg    SyncHandle();
851191cded7Smrg    return True;
852191cded7Smrg}
853d9dcd5aeSmrg
854191cded7SmrgBool
855b290cf36SmrgXF86VidModeLockModeSwitch(Display* dpy, int screen, int lock)
856191cded7Smrg{
857191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
858191cded7Smrg    xXF86VidModeLockModeSwitchReq *req;
859191cded7Smrg
860191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
861191cded7Smrg
862191cded7Smrg    LockDisplay(dpy);
863191cded7Smrg    GetReq(XF86VidModeLockModeSwitch, req);
864191cded7Smrg    req->reqType = info->codes->major_opcode;
865191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeLockModeSwitch;
866191cded7Smrg    req->screen = screen;
867191cded7Smrg    req->lock = lock;
868191cded7Smrg    UnlockDisplay(dpy);
869191cded7Smrg    SyncHandle();
870191cded7Smrg    return True;
871191cded7Smrg}
872d9dcd5aeSmrg
873191cded7SmrgBool
874b290cf36SmrgXF86VidModeGetMonitor(Display* dpy, int screen, XF86VidModeMonitor* monitor)
875191cded7Smrg{
876191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
877191cded7Smrg    xXF86VidModeGetMonitorReply rep;
878191cded7Smrg    xXF86VidModeGetMonitorReq *req;
879191cded7Smrg    CARD32 syncrange;
880191cded7Smrg    int i;
881d9dcd5aeSmrg    Bool result = True;
882191cded7Smrg
883191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
884191cded7Smrg
885191cded7Smrg    LockDisplay(dpy);
886191cded7Smrg    GetReq(XF86VidModeGetMonitor, req);
887191cded7Smrg    req->reqType = info->codes->major_opcode;
888191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetMonitor;
889191cded7Smrg    req->screen = screen;
890191cded7Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
891191cded7Smrg	UnlockDisplay(dpy);
892191cded7Smrg	SyncHandle();
893191cded7Smrg	return False;
894191cded7Smrg    }
895191cded7Smrg    monitor->nhsync = rep.nhsync;
896191cded7Smrg    monitor->nvsync = rep.nvsync;
897191cded7Smrg#if 0
898191cded7Smrg    monitor->bandwidth = (float)rep.bandwidth / 1e6;
899191cded7Smrg#endif
900191cded7Smrg    if (rep.vendorLength) {
901d9dcd5aeSmrg	monitor->vendor = Xcalloc(rep.vendorLength + 1, 1);
902d9dcd5aeSmrg	if (monitor->vendor == NULL)
903d9dcd5aeSmrg	    result = False;
904191cded7Smrg    } else {
905191cded7Smrg	monitor->vendor = NULL;
906191cded7Smrg    }
907d9dcd5aeSmrg    if (result && rep.modelLength) {
908d9dcd5aeSmrg	monitor->model = Xcalloc(rep.modelLength + 1, 1);
909d9dcd5aeSmrg	if (monitor->model == NULL)
910d9dcd5aeSmrg	    result = False;
911191cded7Smrg    } else {
912191cded7Smrg	monitor->model = NULL;
913191cded7Smrg    }
914d9dcd5aeSmrg    if (result) {
915d9dcd5aeSmrg	monitor->hsync = Xcalloc(rep.nhsync, sizeof(XF86VidModeSyncRange));
916d9dcd5aeSmrg	monitor->vsync = Xcalloc(rep.nvsync, sizeof(XF86VidModeSyncRange));
917d9dcd5aeSmrg	if ((monitor->hsync == NULL) || (monitor->vsync == NULL))
918d9dcd5aeSmrg	    result = False;
919d9dcd5aeSmrg    } else {
920d9dcd5aeSmrg	monitor->hsync = monitor->vsync = NULL;
921191cded7Smrg    }
922d9dcd5aeSmrg    if (result == False) {
923d9dcd5aeSmrg	_XEatDataWords(dpy, rep.length);
924d9dcd5aeSmrg	Xfree(monitor->vendor);
925d9dcd5aeSmrg	monitor->vendor = NULL;
926d9dcd5aeSmrg	Xfree(monitor->model);
927d9dcd5aeSmrg	monitor->model = NULL;
928191cded7Smrg	Xfree(monitor->hsync);
929d9dcd5aeSmrg	monitor->hsync = NULL;
930d9dcd5aeSmrg	Xfree(monitor->vsync);
931d9dcd5aeSmrg	monitor->vsync = NULL;
932191cded7Smrg    }
933d9dcd5aeSmrg    else {
934d9dcd5aeSmrg	for (i = 0; i < rep.nhsync; i++) {
935d9dcd5aeSmrg	    _XRead(dpy, (char *)&syncrange, 4);
936d9dcd5aeSmrg	    monitor->hsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0;
937d9dcd5aeSmrg	    monitor->hsync[i].hi = (float)(syncrange >> 16) / 100.0;
938d9dcd5aeSmrg	}
939d9dcd5aeSmrg	for (i = 0; i < rep.nvsync; i++) {
940d9dcd5aeSmrg	    _XRead(dpy, (char *)&syncrange, 4);
941d9dcd5aeSmrg	    monitor->vsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0;
942d9dcd5aeSmrg	    monitor->vsync[i].hi = (float)(syncrange >> 16) / 100.0;
943d9dcd5aeSmrg	}
944d9dcd5aeSmrg	if (rep.vendorLength)
945d9dcd5aeSmrg	    _XReadPad(dpy, monitor->vendor, rep.vendorLength);
946d9dcd5aeSmrg	if (rep.modelLength)
947d9dcd5aeSmrg	    _XReadPad(dpy, monitor->model, rep.modelLength);
948191cded7Smrg    }
949191cded7Smrg    UnlockDisplay(dpy);
950191cded7Smrg    SyncHandle();
951d9dcd5aeSmrg    return result;
952191cded7Smrg}
953191cded7Smrg
954191cded7SmrgBool
955b290cf36SmrgXF86VidModeGetViewPort(Display* dpy, int screen, int *x, int *y)
956191cded7Smrg{
957191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
958191cded7Smrg    xXF86VidModeGetViewPortReply rep;
959191cded7Smrg    xXF86VidModeGetViewPortReq *req;
960191cded7Smrg    int majorVersion, minorVersion;
961191cded7Smrg    Bool protocolBug = False;
962191cded7Smrg
963191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
964191cded7Smrg
965191cded7Smrg    /*
966191cded7Smrg     * Note: There was a bug in the protocol implementation in versions
967191cded7Smrg     * 0.x with x < 8 (no reply was sent, so the client would hang)
968191cded7Smrg     * Check the server's version, and don't wait for a reply with older
969191cded7Smrg     * versions.
970191cded7Smrg     */
971191cded7Smrg
972191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
973191cded7Smrg    if (majorVersion == 0 && minorVersion < 8) {
974191cded7Smrg	protocolBug = True;
975191cded7Smrg#ifdef DEBUG
976191cded7Smrg	fprintf(stderr, "XF86VidModeGetViewPort: Warning: Xserver is"
977191cded7Smrg		"running an old version (%d.%d)\n", majorVersion,
978191cded7Smrg		minorVersion);
979191cded7Smrg#endif
980191cded7Smrg    }
981191cded7Smrg    LockDisplay(dpy);
982191cded7Smrg    GetReq(XF86VidModeGetViewPort, req);
983191cded7Smrg    req->reqType = info->codes->major_opcode;
984191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetViewPort;
985191cded7Smrg    req->screen = screen;
986191cded7Smrg    if (protocolBug) {
987191cded7Smrg	*x = 0;
988191cded7Smrg	*y = 0;
989191cded7Smrg    } else {
990191cded7Smrg	if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
991191cded7Smrg	    UnlockDisplay(dpy);
992191cded7Smrg	    SyncHandle();
993191cded7Smrg	    return False;
994191cded7Smrg	}
995191cded7Smrg	*x = rep.x;
996191cded7Smrg	*y = rep.y;
997191cded7Smrg    }
998191cded7Smrg
999191cded7Smrg    UnlockDisplay(dpy);
1000191cded7Smrg    SyncHandle();
1001191cded7Smrg    return True;
1002191cded7Smrg}
1003191cded7Smrg
1004191cded7SmrgBool
1005b290cf36SmrgXF86VidModeSetViewPort(Display* dpy, int screen, int x, int y)
1006191cded7Smrg{
1007191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1008191cded7Smrg    xXF86VidModeSetViewPortReq *req;
1009191cded7Smrg
1010191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1011191cded7Smrg
1012191cded7Smrg    LockDisplay(dpy);
1013191cded7Smrg    GetReq(XF86VidModeSetViewPort, req);
1014191cded7Smrg    req->reqType = info->codes->major_opcode;
1015191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSetViewPort;
1016191cded7Smrg    req->screen = screen;
1017191cded7Smrg    req->x = x;
1018191cded7Smrg    req->y = y;
1019191cded7Smrg
1020191cded7Smrg    UnlockDisplay(dpy);
1021191cded7Smrg    SyncHandle();
1022191cded7Smrg    return True;
1023191cded7Smrg}
1024191cded7Smrg
1025191cded7SmrgBool
1026b290cf36SmrgXF86VidModeGetDotClocks(Display* dpy, int screen, int *flagsPtr,
1027b290cf36Smrg			int *numclocksPtr, int *maxclocksPtr, int *clocksPtr[])
1028191cded7Smrg{
1029191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1030191cded7Smrg    xXF86VidModeGetDotClocksReply rep;
1031191cded7Smrg    xXF86VidModeGetDotClocksReq *req;
1032191cded7Smrg    int i, *dotclocks;
1033191cded7Smrg    CARD32 dotclk;
1034d9dcd5aeSmrg    Bool result = True;
1035191cded7Smrg
1036191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1037191cded7Smrg
1038191cded7Smrg    LockDisplay(dpy);
1039191cded7Smrg    GetReq(XF86VidModeGetDotClocks, req);
1040191cded7Smrg    req->reqType = info->codes->major_opcode;
1041191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetDotClocks;
1042191cded7Smrg    req->screen = screen;
1043d9dcd5aeSmrg    if (!_XReply(dpy, (xReply *)&rep,
1044191cded7Smrg        (SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2, xFalse))
1045191cded7Smrg    {
1046191cded7Smrg        UnlockDisplay(dpy);
1047191cded7Smrg        SyncHandle();
1048191cded7Smrg        return False;
1049191cded7Smrg    }
1050191cded7Smrg    *numclocksPtr = rep.clocks;
1051191cded7Smrg    *maxclocksPtr = rep.maxclocks;
1052191cded7Smrg    *flagsPtr     = rep.flags;
1053191cded7Smrg
1054d9dcd5aeSmrg    dotclocks = Xcalloc(rep.clocks, sizeof(int));
1055d9dcd5aeSmrg    if (dotclocks == NULL) {
1056d9dcd5aeSmrg        _XEatDataWords(dpy, rep.length -
1057d9dcd5aeSmrg	    ((SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2));
1058d9dcd5aeSmrg        result = False;
1059191cded7Smrg    }
1060d9dcd5aeSmrg    else {
1061d9dcd5aeSmrg	for (i = 0; i < rep.clocks; i++) {
1062d9dcd5aeSmrg	    _XRead(dpy, (char*)&dotclk, 4);
1063d9dcd5aeSmrg	    dotclocks[i] = dotclk;
1064d9dcd5aeSmrg	}
1065191cded7Smrg    }
1066191cded7Smrg    *clocksPtr = dotclocks;
1067191cded7Smrg    UnlockDisplay(dpy);
1068191cded7Smrg    SyncHandle();
1069d9dcd5aeSmrg    return result;
1070191cded7Smrg}
1071191cded7Smrg
1072191cded7SmrgBool
1073191cded7SmrgXF86VidModeSetGammaRamp (
1074191cded7Smrg    Display *dpy,
1075191cded7Smrg    int screen,
1076191cded7Smrg    int size,
1077191cded7Smrg    unsigned short *red,
1078191cded7Smrg    unsigned short *green,
1079191cded7Smrg    unsigned short *blue
1080191cded7Smrg)
1081191cded7Smrg{
1082191cded7Smrg    int length = (size + 1) & ~1;
1083191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1084191cded7Smrg    xXF86VidModeSetGammaRampReq *req;
1085191cded7Smrg
1086191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1087191cded7Smrg    LockDisplay(dpy);
1088191cded7Smrg    GetReq(XF86VidModeSetGammaRamp, req);
1089191cded7Smrg    req->reqType = info->codes->major_opcode;
1090191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSetGammaRamp;
1091191cded7Smrg    req->screen = screen;
1092191cded7Smrg    req->length += (length >> 1) * 3;
1093191cded7Smrg    req->size = size;
1094191cded7Smrg    _XSend(dpy, (char*)red, size * 2);
1095191cded7Smrg    _XSend(dpy, (char*)green, size * 2);
1096191cded7Smrg    _XSend(dpy, (char*)blue, size * 2);
1097191cded7Smrg    UnlockDisplay(dpy);
1098191cded7Smrg    SyncHandle();
1099191cded7Smrg    return True;
1100191cded7Smrg}
1101191cded7Smrg
1102191cded7Smrg
1103191cded7SmrgBool
1104191cded7SmrgXF86VidModeGetGammaRamp (
1105191cded7Smrg    Display *dpy,
1106191cded7Smrg    int screen,
1107191cded7Smrg    int size,
1108191cded7Smrg    unsigned short *red,
1109191cded7Smrg    unsigned short *green,
1110191cded7Smrg    unsigned short *blue
1111191cded7Smrg)
1112191cded7Smrg{
1113191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1114191cded7Smrg    xXF86VidModeGetGammaRampReq *req;
1115191cded7Smrg    xXF86VidModeGetGammaRampReply rep;
1116d9dcd5aeSmrg    Bool result = True;
1117d9dcd5aeSmrg
1118191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1119191cded7Smrg
1120191cded7Smrg    LockDisplay(dpy);
1121191cded7Smrg    GetReq(XF86VidModeGetGammaRamp, req);
1122191cded7Smrg    req->reqType = info->codes->major_opcode;
1123191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetGammaRamp;
1124191cded7Smrg    req->screen = screen;
1125191cded7Smrg    req->size = size;
1126191cded7Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1127d9dcd5aeSmrg        result = False;
1128191cded7Smrg    }
1129d9dcd5aeSmrg    else if (rep.size) {
1130d9dcd5aeSmrg	if (rep.size <= size) {
1131d9dcd5aeSmrg	    _XRead(dpy, (char*)red, rep.size << 1);
1132d9dcd5aeSmrg	    _XRead(dpy, (char*)green, rep.size << 1);
1133d9dcd5aeSmrg	    _XRead(dpy, (char*)blue, rep.size << 1);
1134d9dcd5aeSmrg	}
1135d9dcd5aeSmrg	else {
1136d9dcd5aeSmrg	    _XEatDataWords(dpy, rep.length);
1137d9dcd5aeSmrg	    result = False;
1138d9dcd5aeSmrg	}
1139191cded7Smrg    }
1140191cded7Smrg
1141191cded7Smrg    UnlockDisplay(dpy);
1142191cded7Smrg    SyncHandle();
1143d9dcd5aeSmrg    return result;
1144191cded7Smrg}
1145191cded7Smrg
1146191cded7SmrgBool XF86VidModeGetGammaRampSize(
1147191cded7Smrg    Display *dpy,
1148191cded7Smrg    int screen,
1149191cded7Smrg    int *size
1150191cded7Smrg)
1151191cded7Smrg{
1152191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1153191cded7Smrg    xXF86VidModeGetGammaRampSizeReq *req;
1154191cded7Smrg    xXF86VidModeGetGammaRampSizeReply rep;
1155d9dcd5aeSmrg
1156191cded7Smrg    *size = 0;
1157191cded7Smrg
1158191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1159191cded7Smrg
1160191cded7Smrg    LockDisplay(dpy);
1161191cded7Smrg    GetReq(XF86VidModeGetGammaRampSize, req);
1162191cded7Smrg    req->reqType = info->codes->major_opcode;
1163191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetGammaRampSize;
1164191cded7Smrg    req->screen = screen;
1165191cded7Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
1166191cded7Smrg        UnlockDisplay (dpy);
1167191cded7Smrg        SyncHandle ();
1168d9dcd5aeSmrg        return False;
1169191cded7Smrg    }
1170191cded7Smrg    *size = rep.size;
1171191cded7Smrg    UnlockDisplay(dpy);
1172191cded7Smrg    SyncHandle();
1173191cded7Smrg    return True;
1174191cded7Smrg}
1175191cded7Smrg
1176191cded7SmrgBool XF86VidModeGetPermissions(
1177191cded7Smrg    Display *dpy,
1178191cded7Smrg    int screen,
1179191cded7Smrg    int *permissions
1180191cded7Smrg)
1181191cded7Smrg{
1182191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1183191cded7Smrg    xXF86VidModeGetPermissionsReq *req;
1184191cded7Smrg    xXF86VidModeGetPermissionsReply rep;
1185d9dcd5aeSmrg
1186191cded7Smrg    *permissions = 0;
1187191cded7Smrg
1188191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1189191cded7Smrg
1190191cded7Smrg    LockDisplay(dpy);
1191191cded7Smrg    GetReq(XF86VidModeGetPermissions, req);
1192191cded7Smrg    req->reqType = info->codes->major_opcode;
1193191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetPermissions;
1194191cded7Smrg    req->screen = screen;
1195191cded7Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
1196191cded7Smrg        UnlockDisplay (dpy);
1197191cded7Smrg        SyncHandle ();
1198d9dcd5aeSmrg        return False;
1199191cded7Smrg    }
1200191cded7Smrg    *permissions = rep.permissions;
1201191cded7Smrg    UnlockDisplay(dpy);
1202191cded7Smrg    SyncHandle();
1203191cded7Smrg    return True;
1204191cded7Smrg}
1205191cded7Smrg
1206