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
44191cded7Smrg#ifdef DEBUG
45191cded7Smrg#include <stdio.h>
46191cded7Smrg#endif
47191cded7Smrg
48191cded7Smrg#ifndef MODE_BAD
49191cded7Smrg#define MODE_BAD 255
50191cded7Smrg#endif
51191cded7Smrg
52191cded7Smrgstatic XExtensionInfo _xf86vidmode_info_data;
53191cded7Smrgstatic XExtensionInfo *xf86vidmode_info = &_xf86vidmode_info_data;
54347791aaSmrgstatic const char *xf86vidmode_extension_name = XF86VIDMODENAME;
55191cded7Smrg
56191cded7Smrg#define XF86VidModeCheckExtension(dpy,i,val) \
57191cded7Smrg  XextCheckExtension (dpy, i, xf86vidmode_extension_name, val)
58191cded7Smrg
59191cded7Smrg/*****************************************************************************
60191cded7Smrg *                                                                           *
61191cded7Smrg *			   private utility routines                          *
62191cded7Smrg *                                                                           *
63191cded7Smrg *****************************************************************************/
64191cded7Smrg
65191cded7Smrgstatic XEXT_CLOSE_DISPLAY_PROTO(close_display);
66191cded7Smrgstatic /* const */ XExtensionHooks xf86vidmode_extension_hooks = {
67191cded7Smrg    NULL,				/* create_gc */
68191cded7Smrg    NULL,				/* copy_gc */
69191cded7Smrg    NULL,				/* flush_gc */
70191cded7Smrg    NULL,				/* free_gc */
71191cded7Smrg    NULL,				/* create_font */
72191cded7Smrg    NULL,				/* free_font */
73191cded7Smrg    close_display,			/* close_display */
74191cded7Smrg    NULL,				/* wire_to_event */
75191cded7Smrg    NULL,				/* event_to_wire */
76191cded7Smrg    NULL,				/* error */
77191cded7Smrg    NULL,				/* error_string */
78191cded7Smrg};
79191cded7Smrg
80d9dcd5aeSmrgstatic XEXT_GENERATE_FIND_DISPLAY (find_display, xf86vidmode_info,
81d9dcd5aeSmrg				   xf86vidmode_extension_name,
82d9dcd5aeSmrg				   &xf86vidmode_extension_hooks,
83191cded7Smrg				   0, NULL)
84191cded7Smrg
85191cded7Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86vidmode_info)
86191cded7Smrg
87191cded7Smrg
88191cded7Smrg/*****************************************************************************
89191cded7Smrg *                                                                           *
90191cded7Smrg *		    public XFree86-VidMode Extension routines                *
91191cded7Smrg *                                                                           *
92191cded7Smrg *****************************************************************************/
93191cded7Smrg
94191cded7SmrgBool
95b290cf36SmrgXF86VidModeQueryExtension(Display *dpy, int *event_basep, int *error_basep)
96191cded7Smrg{
97191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
98191cded7Smrg
99191cded7Smrg    if (XextHasExtension(info)) {
100191cded7Smrg	*event_basep = info->codes->first_event;
101191cded7Smrg	*error_basep = info->codes->first_error;
102191cded7Smrg	return True;
103191cded7Smrg    } else {
104191cded7Smrg	return False;
105191cded7Smrg    }
106191cded7Smrg}
107191cded7Smrg
108191cded7SmrgBool
109b290cf36SmrgXF86VidModeQueryVersion(Display* dpy, int* majorVersion, int* minorVersion)
110191cded7Smrg{
111191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
112191cded7Smrg    xXF86VidModeQueryVersionReply rep;
113191cded7Smrg    xXF86VidModeQueryVersionReq *req;
114191cded7Smrg
115191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
116191cded7Smrg
117191cded7Smrg    LockDisplay(dpy);
118191cded7Smrg    GetReq(XF86VidModeQueryVersion, req);
119191cded7Smrg    req->reqType = info->codes->major_opcode;
120191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeQueryVersion;
121191cded7Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
122191cded7Smrg	UnlockDisplay(dpy);
123191cded7Smrg	SyncHandle();
124191cded7Smrg	return False;
125191cded7Smrg    }
126191cded7Smrg    *majorVersion = rep.majorVersion;
127191cded7Smrg    *minorVersion = rep.minorVersion;
128191cded7Smrg    UnlockDisplay(dpy);
129191cded7Smrg    SyncHandle();
130191cded7Smrg    if (*majorVersion >= 2)
131191cded7Smrg	XF86VidModeSetClientVersion(dpy);
132191cded7Smrg    return True;
133191cded7Smrg}
134191cded7Smrg
135191cded7SmrgBool
136191cded7SmrgXF86VidModeSetClientVersion(Display *dpy)
137191cded7Smrg{
138191cded7Smrg    XExtDisplayInfo *info = find_display(dpy);
139191cded7Smrg    xXF86VidModeSetClientVersionReq *req;
140191cded7Smrg
141191cded7Smrg    XF86VidModeCheckExtension(dpy, info, False);
142191cded7Smrg
143191cded7Smrg    LockDisplay(dpy);
144191cded7Smrg    GetReq(XF86VidModeSetClientVersion, req);
145191cded7Smrg    req->reqType = info->codes->major_opcode;
146191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSetClientVersion;
147191cded7Smrg    req->major = XF86VIDMODE_MAJOR_VERSION;
148191cded7Smrg    req->minor = XF86VIDMODE_MINOR_VERSION;
149191cded7Smrg    UnlockDisplay(dpy);
150191cded7Smrg    SyncHandle();
151191cded7Smrg    return True;
152191cded7Smrg}
153191cded7Smrg
154191cded7SmrgBool
155191cded7SmrgXF86VidModeSetGamma(Display *dpy, int screen, XF86VidModeGamma *Gamma)
156191cded7Smrg{
157191cded7Smrg    XExtDisplayInfo *info = find_display(dpy);
158191cded7Smrg    xXF86VidModeSetGammaReq *req;
159191cded7Smrg
160191cded7Smrg    XF86VidModeCheckExtension(dpy, info, False);
161191cded7Smrg
162191cded7Smrg    LockDisplay(dpy);
163191cded7Smrg    GetReq(XF86VidModeSetGamma, req);
164191cded7Smrg    req->reqType = info->codes->major_opcode;
165191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSetGamma;
166191cded7Smrg    req->screen = screen;
167191cded7Smrg    req->red = (CARD32)(Gamma->red * 10000.);
168191cded7Smrg    req->green = (CARD32)(Gamma->green * 10000.);
169191cded7Smrg    req->blue = (CARD32)(Gamma->blue * 10000.);
170191cded7Smrg    UnlockDisplay(dpy);
171191cded7Smrg    SyncHandle();
172191cded7Smrg    return True;
173191cded7Smrg}
174191cded7Smrg
175191cded7SmrgBool
176191cded7SmrgXF86VidModeGetGamma(Display *dpy, int screen, XF86VidModeGamma *Gamma)
177191cded7Smrg{
178191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
179191cded7Smrg    xXF86VidModeGetGammaReply rep;
180191cded7Smrg    xXF86VidModeGetGammaReq *req;
181191cded7Smrg
182191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
183191cded7Smrg
184191cded7Smrg    LockDisplay(dpy);
185191cded7Smrg    GetReq(XF86VidModeGetGamma, req);
186191cded7Smrg    req->reqType = info->codes->major_opcode;
187191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetGamma;
188191cded7Smrg    req->screen = screen;
189191cded7Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
190191cded7Smrg	UnlockDisplay(dpy);
191191cded7Smrg	SyncHandle();
192191cded7Smrg	return False;
193191cded7Smrg    }
194191cded7Smrg    Gamma->red = ((float)rep.red) / 10000.;
195191cded7Smrg    Gamma->green = ((float)rep.green) / 10000.;
196191cded7Smrg    Gamma->blue = ((float)rep.blue) / 10000.;
197191cded7Smrg    UnlockDisplay(dpy);
198191cded7Smrg    SyncHandle();
199191cded7Smrg    return True;
200191cded7Smrg}
201191cded7Smrg
202191cded7SmrgBool
203b290cf36SmrgXF86VidModeGetModeLine(Display* dpy, int screen, int* dotclock,
204b290cf36Smrg		       XF86VidModeModeLine* modeline)
205191cded7Smrg{
206191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
207191cded7Smrg    xXF86VidModeGetModeLineReq *req;
208191cded7Smrg    int majorVersion, minorVersion;
209adf1ce27Smrg    CARD32 remaining_len;
210d9dcd5aeSmrg    Bool result = True;
211191cded7Smrg
212191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
213191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
214191cded7Smrg
215191cded7Smrg    LockDisplay(dpy);
216191cded7Smrg    GetReq(XF86VidModeGetModeLine, req);
217191cded7Smrg    req->reqType = info->codes->major_opcode;
218191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetModeLine;
219191cded7Smrg    req->screen = screen;
220d9dcd5aeSmrg
221adf1ce27Smrg    if (_X_UNLIKELY(majorVersion < 2)) {
222adf1ce27Smrg	xXF86OldVidModeGetModeLineReply oldrep;
223adf1ce27Smrg
224d9dcd5aeSmrg	if (!_XReply(dpy, (xReply *)&oldrep,
225191cded7Smrg            (SIZEOF(xXF86OldVidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) {
226191cded7Smrg	    UnlockDisplay(dpy);
227191cded7Smrg	    SyncHandle();
228191cded7Smrg	    return False;
229191cded7Smrg	}
230adf1ce27Smrg	remaining_len = oldrep.length -
231adf1ce27Smrg	    ((SIZEOF(xXF86OldVidModeGetModeLineReply) - SIZEOF(xReply)) >> 2);
232191cded7Smrg	*dotclock = oldrep.dotclock;
233191cded7Smrg	modeline->hdisplay   = oldrep.hdisplay;
234191cded7Smrg	modeline->hsyncstart = oldrep.hsyncstart;
235191cded7Smrg	modeline->hsyncend   = oldrep.hsyncend;
236191cded7Smrg	modeline->htotal     = oldrep.htotal;
237191cded7Smrg	modeline->hskew      = 0;
238191cded7Smrg	modeline->vdisplay   = oldrep.vdisplay;
239191cded7Smrg	modeline->vsyncstart = oldrep.vsyncstart;
240191cded7Smrg	modeline->vsyncend   = oldrep.vsyncend;
241191cded7Smrg	modeline->vtotal     = oldrep.vtotal;
242191cded7Smrg	modeline->flags      = oldrep.flags;
243191cded7Smrg	modeline->privsize   = oldrep.privsize;
244191cded7Smrg    } else {
245adf1ce27Smrg	xXF86VidModeGetModeLineReply rep;
246adf1ce27Smrg
247d9dcd5aeSmrg	if (!_XReply(dpy, (xReply *)&rep,
248191cded7Smrg            (SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) {
249191cded7Smrg	    UnlockDisplay(dpy);
250191cded7Smrg	    SyncHandle();
251191cded7Smrg	    return False;
252191cded7Smrg	}
253adf1ce27Smrg	remaining_len = rep.length -
254adf1ce27Smrg	    ((SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2);
255191cded7Smrg	*dotclock = rep.dotclock;
256191cded7Smrg	modeline->hdisplay   = rep.hdisplay;
257191cded7Smrg	modeline->hsyncstart = rep.hsyncstart;
258191cded7Smrg	modeline->hsyncend   = rep.hsyncend;
259191cded7Smrg	modeline->htotal     = rep.htotal;
260191cded7Smrg	modeline->hskew      = rep.hskew;
261191cded7Smrg	modeline->vdisplay   = rep.vdisplay;
262191cded7Smrg	modeline->vsyncstart = rep.vsyncstart;
263191cded7Smrg	modeline->vsyncend   = rep.vsyncend;
264191cded7Smrg	modeline->vtotal     = rep.vtotal;
265191cded7Smrg	modeline->flags      = rep.flags;
266191cded7Smrg	modeline->privsize   = rep.privsize;
267191cded7Smrg    }
268d9dcd5aeSmrg
269191cded7Smrg    if (modeline->privsize > 0) {
270072eb593Smrg	if ((unsigned) modeline->privsize < (INT_MAX / sizeof(INT32)))
271d9dcd5aeSmrg	    modeline->private = Xcalloc(modeline->privsize, sizeof(INT32));
272d9dcd5aeSmrg	else
273d9dcd5aeSmrg	    modeline->private = NULL;
274d9dcd5aeSmrg	if (modeline->private == NULL) {
275adf1ce27Smrg	    _XEatDataWords(dpy, remaining_len);
276d9dcd5aeSmrg	    result = False;
277d9dcd5aeSmrg	} else
278d9dcd5aeSmrg	    _XRead(dpy, (char*)modeline->private, modeline->privsize * sizeof(INT32));
279191cded7Smrg    } else {
280191cded7Smrg	modeline->private = NULL;
281191cded7Smrg    }
282191cded7Smrg    UnlockDisplay(dpy);
283191cded7Smrg    SyncHandle();
284d9dcd5aeSmrg    return result;
285191cded7Smrg}
286191cded7Smrg
287191cded7SmrgBool
288b290cf36SmrgXF86VidModeGetAllModeLines(Display* dpy, int screen, int* modecount,
289b290cf36Smrg			   XF86VidModeModeInfo ***modelinesPtr)
290191cded7Smrg{
291191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
292191cded7Smrg    xXF86VidModeGetAllModeLinesReply rep;
293191cded7Smrg    xXF86VidModeGetAllModeLinesReq *req;
294191cded7Smrg    XF86VidModeModeInfo *mdinfptr, **modelines;
295191cded7Smrg    xXF86VidModeModeInfo xmdline;
296191cded7Smrg    xXF86OldVidModeModeInfo oldxmdline;
297adf1ce27Smrg    unsigned int i;
298191cded7Smrg    int majorVersion, minorVersion;
299191cded7Smrg    Bool protocolBug = False;
300191cded7Smrg
301191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
302191cded7Smrg
303191cded7Smrg    /*
304191cded7Smrg     * Note: There was a bug in the protocol implementation in versions
305191cded7Smrg     * 0.x with x < 8 (the .private field wasn't being passed over the wire).
306191cded7Smrg     * Check the server's version, and accept the old format if appropriate.
307191cded7Smrg     */
308191cded7Smrg
309191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
310191cded7Smrg    if (majorVersion == 0 && minorVersion < 8) {
311191cded7Smrg	protocolBug = True;
312191cded7Smrg#ifdef DEBUG
313191cded7Smrg	fprintf(stderr, "XF86VidModeGetAllModeLines: Warning: Xserver is"
314191cded7Smrg		"running an old version (%d.%d)\n", majorVersion,
315191cded7Smrg		minorVersion);
316191cded7Smrg#endif
317191cded7Smrg    }
318d9dcd5aeSmrg
319191cded7Smrg    LockDisplay(dpy);
320191cded7Smrg    GetReq(XF86VidModeGetAllModeLines, req);
321191cded7Smrg    req->reqType = info->codes->major_opcode;
322191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetAllModeLines;
323191cded7Smrg    req->screen = screen;
324d9dcd5aeSmrg    if (!_XReply(dpy, (xReply *)&rep,
325191cded7Smrg        (SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2, xFalse)) {
326191cded7Smrg        UnlockDisplay(dpy);
327191cded7Smrg	SyncHandle();
328191cded7Smrg	return False;
329191cded7Smrg    }
330191cded7Smrg
331191cded7Smrg    *modecount = rep.modecount;
332191cded7Smrg
333191cded7Smrg    if (!(modelines = (XF86VidModeModeInfo **) Xcalloc(rep.modecount,
334191cded7Smrg                                          sizeof(XF86VidModeModeInfo *)
335191cded7Smrg                                          +sizeof(XF86VidModeModeInfo)))) {
336d9dcd5aeSmrg	_XEatDataWords(dpy, rep.length -
337d9dcd5aeSmrg	    ((SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2));
338d9dcd5aeSmrg	UnlockDisplay(dpy);
339d9dcd5aeSmrg	SyncHandle();
340191cded7Smrg        return False;
341191cded7Smrg    }
342191cded7Smrg    mdinfptr = (XF86VidModeModeInfo *) (
343191cded7Smrg			    (char *) modelines
344191cded7Smrg			    + rep.modecount*sizeof(XF86VidModeModeInfo *)
345191cded7Smrg		    );
346191cded7Smrg
347191cded7Smrg    for (i = 0; i < rep.modecount; i++) {
348191cded7Smrg        modelines[i] = mdinfptr++;
349adf1ce27Smrg	if (_X_UNLIKELY(majorVersion < 2)) {
350191cded7Smrg            _XRead(dpy, (char*)&oldxmdline, sizeof(xXF86OldVidModeModeInfo));
351191cded7Smrg	    modelines[i]->dotclock   = oldxmdline.dotclock;
352191cded7Smrg	    modelines[i]->hdisplay   = oldxmdline.hdisplay;
353191cded7Smrg	    modelines[i]->hsyncstart = oldxmdline.hsyncstart;
354191cded7Smrg	    modelines[i]->hsyncend   = oldxmdline.hsyncend;
355191cded7Smrg	    modelines[i]->htotal     = oldxmdline.htotal;
356191cded7Smrg	    modelines[i]->hskew      = 0;
357191cded7Smrg	    modelines[i]->vdisplay   = oldxmdline.vdisplay;
358191cded7Smrg	    modelines[i]->vsyncstart = oldxmdline.vsyncstart;
359191cded7Smrg	    modelines[i]->vsyncend   = oldxmdline.vsyncend;
360191cded7Smrg	    modelines[i]->vtotal     = oldxmdline.vtotal;
361191cded7Smrg	    modelines[i]->flags      = oldxmdline.flags;
362191cded7Smrg	    if (protocolBug) {
363191cded7Smrg		modelines[i]->privsize = 0;
364191cded7Smrg		modelines[i]->private = NULL;
365191cded7Smrg	    } else {
366191cded7Smrg		modelines[i]->privsize   = oldxmdline.privsize;
367191cded7Smrg		if (oldxmdline.privsize > 0) {
368191cded7Smrg	            if (!(modelines[i]->private =
369191cded7Smrg			    Xcalloc(oldxmdline.privsize, sizeof(INT32)))) {
370d9dcd5aeSmrg			_XEatDataWords(dpy, oldxmdline.privsize);
371191cded7Smrg		    } else {
372191cded7Smrg			_XRead(dpy, (char*)modelines[i]->private,
373191cded7Smrg			     oldxmdline.privsize * sizeof(INT32));
374191cded7Smrg		    }
375191cded7Smrg		} else {
376191cded7Smrg		  modelines[i]->private = NULL;
377191cded7Smrg		}
378191cded7Smrg	    }
379191cded7Smrg	} else {
380191cded7Smrg            _XRead(dpy, (char*)&xmdline, sizeof(xXF86VidModeModeInfo));
381191cded7Smrg	    modelines[i]->dotclock   = xmdline.dotclock;
382191cded7Smrg	    modelines[i]->hdisplay   = xmdline.hdisplay;
383191cded7Smrg	    modelines[i]->hsyncstart = xmdline.hsyncstart;
384191cded7Smrg	    modelines[i]->hsyncend   = xmdline.hsyncend;
385191cded7Smrg	    modelines[i]->htotal     = xmdline.htotal;
386191cded7Smrg	    modelines[i]->hskew      = xmdline.hskew;
387191cded7Smrg	    modelines[i]->vdisplay   = xmdline.vdisplay;
388191cded7Smrg	    modelines[i]->vsyncstart = xmdline.vsyncstart;
389191cded7Smrg	    modelines[i]->vsyncend   = xmdline.vsyncend;
390191cded7Smrg	    modelines[i]->vtotal     = xmdline.vtotal;
391191cded7Smrg	    modelines[i]->flags      = xmdline.flags;
392191cded7Smrg	    if (protocolBug) {
393191cded7Smrg		modelines[i]->privsize = 0;
394191cded7Smrg		modelines[i]->private = NULL;
395191cded7Smrg	    } else {
396191cded7Smrg		modelines[i]->privsize   = xmdline.privsize;
397191cded7Smrg		if (xmdline.privsize > 0) {
398191cded7Smrg		    if (!(modelines[i]->private =
399191cded7Smrg			    Xcalloc(xmdline.privsize, sizeof(INT32)))) {
400d9dcd5aeSmrg			_XEatDataWords(dpy, xmdline.privsize);
401191cded7Smrg		    } else {
402191cded7Smrg			_XRead(dpy, (char*)modelines[i]->private,
403191cded7Smrg			     xmdline.privsize * sizeof(INT32));
404191cded7Smrg		    }
405191cded7Smrg		} else {
406191cded7Smrg		    modelines[i]->private = NULL;
407191cded7Smrg		}
408191cded7Smrg	    }
409191cded7Smrg	}
410191cded7Smrg    }
411191cded7Smrg    *modelinesPtr = modelines;
412191cded7Smrg    UnlockDisplay(dpy);
413191cded7Smrg    SyncHandle();
414191cded7Smrg    return True;
415191cded7Smrg}
416191cded7Smrg
417191cded7Smrg/*
418191cded7Smrg * GetReq replacement for use with VidMode protocols earlier than 2.0
419191cded7Smrg */
420191cded7Smrg#define GetOldReq(name, oldname, req) \
421072eb593Smrg	req = (x##oldname##Req *) \
422072eb593Smrg	    _XGetRequest(dpy, X_##name, SIZEOF(x##oldname##Req))
423191cded7Smrg
424191cded7SmrgBool
425b290cf36SmrgXF86VidModeAddModeLine(Display *dpy, int screen,
426b290cf36Smrg		       XF86VidModeModeInfo* newmodeline,
427b290cf36Smrg		       XF86VidModeModeInfo* aftermodeline)
428191cded7Smrg{
429191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
430191cded7Smrg    int majorVersion, minorVersion;
431191cded7Smrg
432191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
433191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
434191cded7Smrg
435191cded7Smrg    LockDisplay(dpy);
436adf1ce27Smrg    if (_X_UNLIKELY(majorVersion < 2)) {
437072eb593Smrg	xXF86OldVidModeAddModeLineReq *oldreq;
438072eb593Smrg
439191cded7Smrg	GetOldReq(XF86VidModeAddModeLine, XF86OldVidModeAddModeLine, oldreq);
440191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
441191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeAddModeLine;
442191cded7Smrg	oldreq->screen = screen;
443191cded7Smrg	oldreq->dotclock =	newmodeline->dotclock;
444191cded7Smrg	oldreq->hdisplay =	newmodeline->hdisplay;
445191cded7Smrg	oldreq->hsyncstart =	newmodeline->hsyncstart;
446191cded7Smrg	oldreq->hsyncend =	newmodeline->hsyncend;
447191cded7Smrg	oldreq->htotal =	newmodeline->htotal;
448191cded7Smrg	oldreq->vdisplay =	newmodeline->vdisplay;
449191cded7Smrg	oldreq->vsyncstart =	newmodeline->vsyncstart;
450191cded7Smrg	oldreq->vsyncend =	newmodeline->vsyncend;
451191cded7Smrg	oldreq->vtotal =	newmodeline->vtotal;
452191cded7Smrg	oldreq->flags =		newmodeline->flags;
453191cded7Smrg	oldreq->privsize =	newmodeline->privsize;
454191cded7Smrg	if (aftermodeline != NULL) {
455191cded7Smrg	    oldreq->after_dotclock =	aftermodeline->dotclock;
456191cded7Smrg	    oldreq->after_hdisplay =	aftermodeline->hdisplay;
457191cded7Smrg	    oldreq->after_hsyncstart =	aftermodeline->hsyncstart;
458191cded7Smrg	    oldreq->after_hsyncend =	aftermodeline->hsyncend;
459191cded7Smrg	    oldreq->after_htotal =	aftermodeline->htotal;
460191cded7Smrg	    oldreq->after_vdisplay =	aftermodeline->vdisplay;
461191cded7Smrg	    oldreq->after_vsyncstart =	aftermodeline->vsyncstart;
462191cded7Smrg	    oldreq->after_vsyncend =	aftermodeline->vsyncend;
463191cded7Smrg	    oldreq->after_vtotal =	aftermodeline->vtotal;
464191cded7Smrg	    oldreq->after_flags =	aftermodeline->flags;
465191cded7Smrg	} else {
466191cded7Smrg	    oldreq->after_dotclock =	0;
467191cded7Smrg	    oldreq->after_hdisplay =	0;
468191cded7Smrg	    oldreq->after_hsyncstart =	0;
469191cded7Smrg	    oldreq->after_hsyncend =	0;
470191cded7Smrg	    oldreq->after_htotal =	0;
471191cded7Smrg	    oldreq->after_vdisplay =	0;
472191cded7Smrg	    oldreq->after_vsyncstart =	0;
473191cded7Smrg	    oldreq->after_vsyncend =	0;
474191cded7Smrg	    oldreq->after_vtotal =	0;
475191cded7Smrg	    oldreq->after_flags =	0;
476191cded7Smrg	}
477191cded7Smrg	if (newmodeline->privsize) {
478191cded7Smrg	    oldreq->length += newmodeline->privsize;
479191cded7Smrg	    Data32(dpy, (long *) newmodeline->private,
480191cded7Smrg	       newmodeline->privsize * sizeof(INT32));
481191cded7Smrg	}
482191cded7Smrg    } else {
483072eb593Smrg	xXF86VidModeAddModeLineReq *req;
484072eb593Smrg
485191cded7Smrg	GetReq(XF86VidModeAddModeLine, req);
486191cded7Smrg	req->reqType = info->codes->major_opcode;
487191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeAddModeLine;
488191cded7Smrg	req->screen = screen;
489191cded7Smrg	req->dotclock =		newmodeline->dotclock;
490191cded7Smrg	req->hdisplay =		newmodeline->hdisplay;
491191cded7Smrg	req->hsyncstart =	newmodeline->hsyncstart;
492191cded7Smrg	req->hsyncend =		newmodeline->hsyncend;
493191cded7Smrg	req->htotal =		newmodeline->htotal;
494191cded7Smrg	req->hskew =		newmodeline->hskew;
495191cded7Smrg	req->vdisplay =		newmodeline->vdisplay;
496191cded7Smrg	req->vsyncstart =	newmodeline->vsyncstart;
497191cded7Smrg	req->vsyncend =		newmodeline->vsyncend;
498191cded7Smrg	req->vtotal =		newmodeline->vtotal;
499191cded7Smrg	req->flags =		newmodeline->flags;
500191cded7Smrg	req->privsize =		newmodeline->privsize;
501191cded7Smrg	if (aftermodeline != NULL) {
502191cded7Smrg	    req->after_dotclock =	aftermodeline->dotclock;
503191cded7Smrg	    req->after_hdisplay =	aftermodeline->hdisplay;
504191cded7Smrg	    req->after_hsyncstart =	aftermodeline->hsyncstart;
505191cded7Smrg	    req->after_hsyncend =	aftermodeline->hsyncend;
506191cded7Smrg	    req->after_htotal =		aftermodeline->htotal;
507191cded7Smrg	    req->after_hskew =		aftermodeline->hskew;
508191cded7Smrg	    req->after_vdisplay =	aftermodeline->vdisplay;
509191cded7Smrg	    req->after_vsyncstart =	aftermodeline->vsyncstart;
510191cded7Smrg	    req->after_vsyncend =	aftermodeline->vsyncend;
511191cded7Smrg	    req->after_vtotal =		aftermodeline->vtotal;
512191cded7Smrg	    req->after_flags =		aftermodeline->flags;
513191cded7Smrg	} else {
514191cded7Smrg	    req->after_dotclock =	0;
515191cded7Smrg	    req->after_hdisplay =	0;
516191cded7Smrg	    req->after_hsyncstart =	0;
517191cded7Smrg	    req->after_hsyncend =	0;
518191cded7Smrg	    req->after_htotal =		0;
519191cded7Smrg	    req->after_hskew =		0;
520191cded7Smrg	    req->after_vdisplay =	0;
521191cded7Smrg	    req->after_vsyncstart =	0;
522191cded7Smrg	    req->after_vsyncend =	0;
523191cded7Smrg	    req->after_vtotal =		0;
524191cded7Smrg	    req->after_flags =		0;
525191cded7Smrg	}
526191cded7Smrg	if (newmodeline->privsize) {
527191cded7Smrg	    req->length += newmodeline->privsize;
528191cded7Smrg	    Data32(dpy, (long *) newmodeline->private,
529191cded7Smrg	       newmodeline->privsize * sizeof(INT32));
530191cded7Smrg	}
531191cded7Smrg    }
532191cded7Smrg    UnlockDisplay(dpy);
533191cded7Smrg    SyncHandle();
534191cded7Smrg    return True;
535191cded7Smrg}
536191cded7Smrg
537191cded7SmrgBool
538b290cf36SmrgXF86VidModeDeleteModeLine(Display *dpy, int screen,
539b290cf36Smrg			  XF86VidModeModeInfo* modeline)
540191cded7Smrg{
541191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
542191cded7Smrg    int majorVersion, minorVersion;
543191cded7Smrg
544191cded7Smrg    XF86VidModeCheckExtension (dpy, info, 0);
545191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
546191cded7Smrg
547191cded7Smrg    LockDisplay(dpy);
548adf1ce27Smrg    if (_X_UNLIKELY(majorVersion < 2)) {
549072eb593Smrg	xXF86OldVidModeDeleteModeLineReq *oldreq;
550072eb593Smrg
551191cded7Smrg	GetOldReq(XF86VidModeDeleteModeLine, XF86OldVidModeDeleteModeLine, oldreq);
552191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
553191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine;
554191cded7Smrg	oldreq->screen = screen;
555191cded7Smrg	oldreq->dotclock =	modeline->dotclock;
556191cded7Smrg	oldreq->hdisplay =	modeline->hdisplay;
557191cded7Smrg	oldreq->hsyncstart =	modeline->hsyncstart;
558191cded7Smrg	oldreq->hsyncend =	modeline->hsyncend;
559191cded7Smrg	oldreq->htotal =	modeline->htotal;
560191cded7Smrg	oldreq->vdisplay =	modeline->vdisplay;
561191cded7Smrg	oldreq->vsyncstart =	modeline->vsyncstart;
562191cded7Smrg	oldreq->vsyncend =	modeline->vsyncend;
563191cded7Smrg	oldreq->vtotal =	modeline->vtotal;
564191cded7Smrg	oldreq->flags =		modeline->flags;
565191cded7Smrg	oldreq->privsize =	modeline->privsize;
566191cded7Smrg	if (modeline->privsize) {
567191cded7Smrg	    oldreq->length += modeline->privsize;
568191cded7Smrg	    Data32(dpy, (long *) modeline->private,
569191cded7Smrg	       modeline->privsize * sizeof(INT32));
570191cded7Smrg	}
571191cded7Smrg    } else {
572072eb593Smrg	xXF86VidModeDeleteModeLineReq *req;
573072eb593Smrg
574191cded7Smrg	GetReq(XF86VidModeDeleteModeLine, req);
575191cded7Smrg	req->reqType = info->codes->major_opcode;
576191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine;
577191cded7Smrg	req->screen = screen;
578191cded7Smrg	req->dotclock =		modeline->dotclock;
579191cded7Smrg	req->hdisplay =		modeline->hdisplay;
580191cded7Smrg	req->hsyncstart =	modeline->hsyncstart;
581191cded7Smrg	req->hsyncend =		modeline->hsyncend;
582191cded7Smrg	req->htotal =		modeline->htotal;
583191cded7Smrg	req->hskew =		modeline->hskew;
584191cded7Smrg	req->vdisplay =		modeline->vdisplay;
585191cded7Smrg	req->vsyncstart =	modeline->vsyncstart;
586191cded7Smrg	req->vsyncend =		modeline->vsyncend;
587191cded7Smrg	req->vtotal =		modeline->vtotal;
588191cded7Smrg	req->flags =		modeline->flags;
589191cded7Smrg	req->privsize =		modeline->privsize;
590191cded7Smrg	if (modeline->privsize) {
591191cded7Smrg	    req->length += modeline->privsize;
592191cded7Smrg	    Data32(dpy, (long *) modeline->private,
593191cded7Smrg	       modeline->privsize * sizeof(INT32));
594191cded7Smrg	}
595191cded7Smrg    }
596191cded7Smrg    UnlockDisplay(dpy);
597191cded7Smrg    SyncHandle();
598191cded7Smrg    return True;
599191cded7Smrg}
600191cded7Smrg
601191cded7SmrgBool
602b290cf36SmrgXF86VidModeModModeLine(Display *dpy, int screen, XF86VidModeModeLine* modeline)
603191cded7Smrg{
604191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
605191cded7Smrg    int majorVersion, minorVersion;
606191cded7Smrg
607191cded7Smrg    XF86VidModeCheckExtension (dpy, info, 0);
608191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
609191cded7Smrg
610191cded7Smrg    LockDisplay(dpy);
611adf1ce27Smrg    if (_X_UNLIKELY(majorVersion < 2)) {
612072eb593Smrg	xXF86OldVidModeModModeLineReq *oldreq;
613072eb593Smrg
614191cded7Smrg	GetOldReq(XF86VidModeModModeLine, XF86OldVidModeModModeLine, oldreq);
615191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
616191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeModModeLine;
617191cded7Smrg	oldreq->screen = screen;
618191cded7Smrg	oldreq->hdisplay =	modeline->hdisplay;
619191cded7Smrg	oldreq->hsyncstart =	modeline->hsyncstart;
620191cded7Smrg	oldreq->hsyncend =	modeline->hsyncend;
621191cded7Smrg	oldreq->htotal =	modeline->htotal;
622191cded7Smrg	oldreq->vdisplay =	modeline->vdisplay;
623191cded7Smrg	oldreq->vsyncstart =	modeline->vsyncstart;
624191cded7Smrg	oldreq->vsyncend =	modeline->vsyncend;
625191cded7Smrg	oldreq->vtotal =	modeline->vtotal;
626191cded7Smrg	oldreq->flags =		modeline->flags;
627191cded7Smrg	oldreq->privsize =	modeline->privsize;
628191cded7Smrg	if (modeline->privsize) {
629191cded7Smrg	    oldreq->length += modeline->privsize;
630191cded7Smrg	    Data32(dpy, (long *) modeline->private,
631191cded7Smrg	       modeline->privsize * sizeof(INT32));
632191cded7Smrg	}
633191cded7Smrg    } else {
634072eb593Smrg	xXF86VidModeModModeLineReq *req;
635072eb593Smrg
636191cded7Smrg	GetReq(XF86VidModeModModeLine, req);
637191cded7Smrg	req->reqType = info->codes->major_opcode;
638191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeModModeLine;
639191cded7Smrg	req->screen = screen;
640191cded7Smrg	req->hdisplay =		modeline->hdisplay;
641191cded7Smrg	req->hsyncstart =	modeline->hsyncstart;
642191cded7Smrg	req->hsyncend =		modeline->hsyncend;
643191cded7Smrg	req->htotal =		modeline->htotal;
644191cded7Smrg	req->hskew =		modeline->hskew;
645191cded7Smrg	req->vdisplay =		modeline->vdisplay;
646191cded7Smrg	req->vsyncstart =	modeline->vsyncstart;
647191cded7Smrg	req->vsyncend =		modeline->vsyncend;
648191cded7Smrg	req->vtotal =		modeline->vtotal;
649191cded7Smrg	req->flags =		modeline->flags;
650191cded7Smrg	req->privsize =		modeline->privsize;
651191cded7Smrg	if (modeline->privsize) {
652191cded7Smrg	    req->length += modeline->privsize;
653191cded7Smrg	    Data32(dpy, (long *) modeline->private,
654191cded7Smrg	       modeline->privsize * sizeof(INT32));
655191cded7Smrg	}
656191cded7Smrg    }
657191cded7Smrg    UnlockDisplay(dpy);
658191cded7Smrg    SyncHandle();
659191cded7Smrg    return True;
660191cded7Smrg}
661191cded7Smrg
662191cded7SmrgStatus
663b290cf36SmrgXF86VidModeValidateModeLine(Display *dpy, int screen,
664b290cf36Smrg			    XF86VidModeModeInfo* modeline)
665191cded7Smrg{
666191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
667191cded7Smrg    xXF86VidModeValidateModeLineReply rep;
668191cded7Smrg    int majorVersion, minorVersion;
669191cded7Smrg
670191cded7Smrg    XF86VidModeCheckExtension (dpy, info, 0);
671191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
672191cded7Smrg
673191cded7Smrg    LockDisplay(dpy);
674191cded7Smrg
675adf1ce27Smrg    if (_X_UNLIKELY(majorVersion < 2)) {
676072eb593Smrg	xXF86OldVidModeValidateModeLineReq *oldreq;
677072eb593Smrg
678191cded7Smrg	GetOldReq(XF86VidModeValidateModeLine, XF86OldVidModeValidateModeLine, oldreq);
679191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
680191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeValidateModeLine;
681191cded7Smrg	oldreq->screen = screen;
682191cded7Smrg	oldreq->dotclock =	modeline->dotclock;
683191cded7Smrg	oldreq->hdisplay =	modeline->hdisplay;
684191cded7Smrg	oldreq->hsyncstart =	modeline->hsyncstart;
685191cded7Smrg	oldreq->hsyncend =	modeline->hsyncend;
686191cded7Smrg	oldreq->htotal =	modeline->htotal;
687191cded7Smrg	oldreq->vdisplay =	modeline->vdisplay;
688191cded7Smrg	oldreq->vsyncstart =	modeline->vsyncstart;
689191cded7Smrg	oldreq->vsyncend =	modeline->vsyncend;
690191cded7Smrg	oldreq->vtotal =	modeline->vtotal;
691191cded7Smrg	oldreq->flags =		modeline->flags;
692191cded7Smrg	oldreq->privsize =	modeline->privsize;
693191cded7Smrg	if (modeline->privsize) {
694191cded7Smrg	    oldreq->length += modeline->privsize;
695191cded7Smrg	    Data32(dpy, (long *) modeline->private,
696191cded7Smrg	       modeline->privsize * sizeof(INT32));
697191cded7Smrg	}
698191cded7Smrg    } else {
699072eb593Smrg	xXF86VidModeValidateModeLineReq *req;
700072eb593Smrg
701191cded7Smrg	GetReq(XF86VidModeValidateModeLine, req);
702191cded7Smrg	req->reqType = info->codes->major_opcode;
703191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeValidateModeLine;
704191cded7Smrg	req->screen = screen;
705191cded7Smrg	req->dotclock =		modeline->dotclock;
706191cded7Smrg	req->hdisplay =		modeline->hdisplay;
707191cded7Smrg	req->hsyncstart =	modeline->hsyncstart;
708191cded7Smrg	req->hsyncend =		modeline->hsyncend;
709191cded7Smrg	req->htotal =		modeline->htotal;
710191cded7Smrg	req->hskew =		modeline->hskew;
711191cded7Smrg	req->vdisplay =		modeline->vdisplay;
712191cded7Smrg	req->vsyncstart =	modeline->vsyncstart;
713191cded7Smrg	req->vsyncend =		modeline->vsyncend;
714191cded7Smrg	req->vtotal =		modeline->vtotal;
715191cded7Smrg	req->flags =		modeline->flags;
716191cded7Smrg	req->privsize =		modeline->privsize;
717191cded7Smrg	if (modeline->privsize) {
718191cded7Smrg	    req->length += modeline->privsize;
719191cded7Smrg	    Data32(dpy, (long *) modeline->private,
720191cded7Smrg	       modeline->privsize * sizeof(INT32));
721191cded7Smrg	}
722191cded7Smrg    }
723191cded7Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
724191cded7Smrg	UnlockDisplay(dpy);
725191cded7Smrg	SyncHandle();
726191cded7Smrg	return MODE_BAD;
727191cded7Smrg    }
728191cded7Smrg    UnlockDisplay(dpy);
729191cded7Smrg    SyncHandle();
730191cded7Smrg    return rep.status;
731191cded7Smrg}
732191cded7Smrg
733191cded7SmrgBool
734b290cf36SmrgXF86VidModeSwitchMode(Display* dpy, int screen, int zoom)
735191cded7Smrg{
736191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
737191cded7Smrg    xXF86VidModeSwitchModeReq *req;
738191cded7Smrg
739191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
740191cded7Smrg
741191cded7Smrg    LockDisplay(dpy);
742191cded7Smrg    GetReq(XF86VidModeSwitchMode, req);
743191cded7Smrg    req->reqType = info->codes->major_opcode;
744191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSwitchMode;
745191cded7Smrg    req->screen = screen;
746191cded7Smrg    req->zoom = zoom;
747191cded7Smrg    UnlockDisplay(dpy);
748191cded7Smrg    SyncHandle();
749191cded7Smrg    return True;
750191cded7Smrg}
751d9dcd5aeSmrg
752191cded7SmrgBool
753b290cf36SmrgXF86VidModeSwitchToMode(Display* dpy, int screen, XF86VidModeModeInfo* modeline)
754191cded7Smrg{
755191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
756191cded7Smrg    xXF86VidModeSwitchToModeReq *req;
757191cded7Smrg    xXF86OldVidModeSwitchToModeReq *oldreq;
758191cded7Smrg    int majorVersion, minorVersion;
759191cded7Smrg    Bool protocolBug = False;
760191cded7Smrg
761191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
762191cded7Smrg
763191cded7Smrg    /*
764191cded7Smrg     * Note: There was a bug in the protocol implementation in versions
765191cded7Smrg     * 0.x with x < 8 (the .private field wasn't expected to be sent over
766191cded7Smrg     * the wire).  Check the server's version, and accept the old format
767191cded7Smrg     * if appropriate.
768191cded7Smrg     */
769191cded7Smrg
770191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
771adf1ce27Smrg    if (_X_UNLIKELY(majorVersion == 0 && minorVersion < 8)) {
772191cded7Smrg	protocolBug = True;
773191cded7Smrg#ifdef DEBUG
774191cded7Smrg	fprintf(stderr, "XF86VidModeSwitchToMode: Warning: Xserver is"
775191cded7Smrg		"running an old version (%d.%d)\n", majorVersion,
776191cded7Smrg		minorVersion);
777191cded7Smrg#endif
778191cded7Smrg    }
779d9dcd5aeSmrg
780191cded7Smrg    LockDisplay(dpy);
781adf1ce27Smrg    if (_X_UNLIKELY(majorVersion < 2)) {
782191cded7Smrg	GetOldReq(XF86VidModeSwitchToMode, XF86OldVidModeSwitchToMode, oldreq);
783191cded7Smrg	oldreq->reqType = info->codes->major_opcode;
784191cded7Smrg	oldreq->xf86vidmodeReqType = X_XF86VidModeSwitchToMode;
785191cded7Smrg	oldreq->screen = screen;
786191cded7Smrg	oldreq->dotclock =	modeline->dotclock;
787191cded7Smrg	oldreq->hdisplay =	modeline->hdisplay;
788191cded7Smrg	oldreq->hsyncstart =	modeline->hsyncstart;
789191cded7Smrg	oldreq->hsyncend =	modeline->hsyncend;
790191cded7Smrg	oldreq->htotal =	modeline->htotal;
791191cded7Smrg	oldreq->vdisplay =	modeline->vdisplay;
792191cded7Smrg	oldreq->vsyncstart =	modeline->vsyncstart;
793191cded7Smrg	oldreq->vsyncend =	modeline->vsyncend;
794191cded7Smrg	oldreq->vtotal =	modeline->vtotal;
795191cded7Smrg	oldreq->flags =	modeline->flags;
796191cded7Smrg	if (protocolBug) {
797191cded7Smrg	    oldreq->privsize = 0;
798191cded7Smrg	} else {
799191cded7Smrg	    oldreq->privsize =	modeline->privsize;
800191cded7Smrg	    if (modeline->privsize) {
801191cded7Smrg		oldreq->length += modeline->privsize;
802191cded7Smrg		Data32(dpy, (long *) modeline->private,
803191cded7Smrg	           modeline->privsize * sizeof(INT32));
804191cded7Smrg	    }
805191cded7Smrg	}
806191cded7Smrg    } else {
807191cded7Smrg	GetReq(XF86VidModeSwitchToMode, req);
808191cded7Smrg	req->reqType = info->codes->major_opcode;
809191cded7Smrg	req->xf86vidmodeReqType = X_XF86VidModeSwitchToMode;
810191cded7Smrg	req->screen = screen;
811191cded7Smrg	req->dotclock =	modeline->dotclock;
812191cded7Smrg	req->hdisplay =	modeline->hdisplay;
813191cded7Smrg	req->hsyncstart =	modeline->hsyncstart;
814191cded7Smrg	req->hsyncend =	modeline->hsyncend;
815191cded7Smrg	req->htotal =	modeline->htotal;
816191cded7Smrg	req->hskew =	modeline->hskew;
817191cded7Smrg	req->vdisplay =	modeline->vdisplay;
818191cded7Smrg	req->vsyncstart =	modeline->vsyncstart;
819191cded7Smrg	req->vsyncend =	modeline->vsyncend;
820191cded7Smrg	req->vtotal =	modeline->vtotal;
821191cded7Smrg	req->flags =	modeline->flags;
822191cded7Smrg	if (protocolBug) {
823191cded7Smrg	    req->privsize = 0;
824191cded7Smrg	} else {
825191cded7Smrg	    req->privsize =	modeline->privsize;
826191cded7Smrg	    if (modeline->privsize) {
827191cded7Smrg		req->length += modeline->privsize;
828191cded7Smrg		Data32(dpy, (long *) modeline->private,
829191cded7Smrg	           modeline->privsize * sizeof(INT32));
830191cded7Smrg	    }
831191cded7Smrg	}
832191cded7Smrg    }
833191cded7Smrg    UnlockDisplay(dpy);
834191cded7Smrg    SyncHandle();
835191cded7Smrg    return True;
836191cded7Smrg}
837d9dcd5aeSmrg
838191cded7SmrgBool
839b290cf36SmrgXF86VidModeLockModeSwitch(Display* dpy, int screen, int lock)
840191cded7Smrg{
841191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
842191cded7Smrg    xXF86VidModeLockModeSwitchReq *req;
843191cded7Smrg
844191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
845191cded7Smrg
846191cded7Smrg    LockDisplay(dpy);
847191cded7Smrg    GetReq(XF86VidModeLockModeSwitch, req);
848191cded7Smrg    req->reqType = info->codes->major_opcode;
849191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeLockModeSwitch;
850191cded7Smrg    req->screen = screen;
851191cded7Smrg    req->lock = lock;
852191cded7Smrg    UnlockDisplay(dpy);
853191cded7Smrg    SyncHandle();
854191cded7Smrg    return True;
855191cded7Smrg}
856d9dcd5aeSmrg
857191cded7SmrgBool
858b290cf36SmrgXF86VidModeGetMonitor(Display* dpy, int screen, XF86VidModeMonitor* monitor)
859191cded7Smrg{
860191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
861191cded7Smrg    xXF86VidModeGetMonitorReply rep;
862191cded7Smrg    xXF86VidModeGetMonitorReq *req;
863191cded7Smrg    CARD32 syncrange;
864191cded7Smrg    int i;
865d9dcd5aeSmrg    Bool result = True;
866191cded7Smrg
867191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
868191cded7Smrg
869191cded7Smrg    LockDisplay(dpy);
870191cded7Smrg    GetReq(XF86VidModeGetMonitor, req);
871191cded7Smrg    req->reqType = info->codes->major_opcode;
872191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetMonitor;
873191cded7Smrg    req->screen = screen;
874191cded7Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
875191cded7Smrg	UnlockDisplay(dpy);
876191cded7Smrg	SyncHandle();
877191cded7Smrg	return False;
878191cded7Smrg    }
879191cded7Smrg    monitor->nhsync = rep.nhsync;
880191cded7Smrg    monitor->nvsync = rep.nvsync;
881191cded7Smrg#if 0
882191cded7Smrg    monitor->bandwidth = (float)rep.bandwidth / 1e6;
883191cded7Smrg#endif
884191cded7Smrg    if (rep.vendorLength) {
885d9dcd5aeSmrg	monitor->vendor = Xcalloc(rep.vendorLength + 1, 1);
886d9dcd5aeSmrg	if (monitor->vendor == NULL)
887d9dcd5aeSmrg	    result = False;
888191cded7Smrg    } else {
889191cded7Smrg	monitor->vendor = NULL;
890191cded7Smrg    }
891d9dcd5aeSmrg    if (result && rep.modelLength) {
892d9dcd5aeSmrg	monitor->model = Xcalloc(rep.modelLength + 1, 1);
893d9dcd5aeSmrg	if (monitor->model == NULL)
894d9dcd5aeSmrg	    result = False;
895191cded7Smrg    } else {
896191cded7Smrg	monitor->model = NULL;
897191cded7Smrg    }
898d9dcd5aeSmrg    if (result) {
899d9dcd5aeSmrg	monitor->hsync = Xcalloc(rep.nhsync, sizeof(XF86VidModeSyncRange));
900d9dcd5aeSmrg	monitor->vsync = Xcalloc(rep.nvsync, sizeof(XF86VidModeSyncRange));
901d9dcd5aeSmrg	if ((monitor->hsync == NULL) || (monitor->vsync == NULL))
902d9dcd5aeSmrg	    result = False;
903d9dcd5aeSmrg    } else {
904d9dcd5aeSmrg	monitor->hsync = monitor->vsync = NULL;
905191cded7Smrg    }
906d9dcd5aeSmrg    if (result == False) {
907d9dcd5aeSmrg	_XEatDataWords(dpy, rep.length);
908d9dcd5aeSmrg	Xfree(monitor->vendor);
909d9dcd5aeSmrg	monitor->vendor = NULL;
910d9dcd5aeSmrg	Xfree(monitor->model);
911d9dcd5aeSmrg	monitor->model = NULL;
912191cded7Smrg	Xfree(monitor->hsync);
913d9dcd5aeSmrg	monitor->hsync = NULL;
914d9dcd5aeSmrg	Xfree(monitor->vsync);
915d9dcd5aeSmrg	monitor->vsync = NULL;
916191cded7Smrg    }
917d9dcd5aeSmrg    else {
918d9dcd5aeSmrg	for (i = 0; i < rep.nhsync; i++) {
919d9dcd5aeSmrg	    _XRead(dpy, (char *)&syncrange, 4);
920d9dcd5aeSmrg	    monitor->hsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0;
921d9dcd5aeSmrg	    monitor->hsync[i].hi = (float)(syncrange >> 16) / 100.0;
922d9dcd5aeSmrg	}
923d9dcd5aeSmrg	for (i = 0; i < rep.nvsync; i++) {
924d9dcd5aeSmrg	    _XRead(dpy, (char *)&syncrange, 4);
925d9dcd5aeSmrg	    monitor->vsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0;
926d9dcd5aeSmrg	    monitor->vsync[i].hi = (float)(syncrange >> 16) / 100.0;
927d9dcd5aeSmrg	}
928d9dcd5aeSmrg	if (rep.vendorLength)
929d9dcd5aeSmrg	    _XReadPad(dpy, monitor->vendor, rep.vendorLength);
930d9dcd5aeSmrg	if (rep.modelLength)
931d9dcd5aeSmrg	    _XReadPad(dpy, monitor->model, rep.modelLength);
932191cded7Smrg    }
933191cded7Smrg    UnlockDisplay(dpy);
934191cded7Smrg    SyncHandle();
935d9dcd5aeSmrg    return result;
936191cded7Smrg}
937191cded7Smrg
938191cded7SmrgBool
939b290cf36SmrgXF86VidModeGetViewPort(Display* dpy, int screen, int *x, int *y)
940191cded7Smrg{
941191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
942191cded7Smrg    xXF86VidModeGetViewPortReply rep;
943191cded7Smrg    xXF86VidModeGetViewPortReq *req;
944191cded7Smrg    int majorVersion, minorVersion;
945191cded7Smrg    Bool protocolBug = False;
946191cded7Smrg
947191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
948191cded7Smrg
949191cded7Smrg    /*
950191cded7Smrg     * Note: There was a bug in the protocol implementation in versions
951191cded7Smrg     * 0.x with x < 8 (no reply was sent, so the client would hang)
952191cded7Smrg     * Check the server's version, and don't wait for a reply with older
953191cded7Smrg     * versions.
954191cded7Smrg     */
955191cded7Smrg
956191cded7Smrg    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
957191cded7Smrg    if (majorVersion == 0 && minorVersion < 8) {
958191cded7Smrg	protocolBug = True;
959191cded7Smrg#ifdef DEBUG
960191cded7Smrg	fprintf(stderr, "XF86VidModeGetViewPort: Warning: Xserver is"
961191cded7Smrg		"running an old version (%d.%d)\n", majorVersion,
962191cded7Smrg		minorVersion);
963191cded7Smrg#endif
964191cded7Smrg    }
965191cded7Smrg    LockDisplay(dpy);
966191cded7Smrg    GetReq(XF86VidModeGetViewPort, req);
967191cded7Smrg    req->reqType = info->codes->major_opcode;
968191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetViewPort;
969191cded7Smrg    req->screen = screen;
970191cded7Smrg    if (protocolBug) {
971191cded7Smrg	*x = 0;
972191cded7Smrg	*y = 0;
973191cded7Smrg    } else {
974191cded7Smrg	if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
975191cded7Smrg	    UnlockDisplay(dpy);
976191cded7Smrg	    SyncHandle();
977191cded7Smrg	    return False;
978191cded7Smrg	}
979191cded7Smrg	*x = rep.x;
980191cded7Smrg	*y = rep.y;
981191cded7Smrg    }
982191cded7Smrg
983191cded7Smrg    UnlockDisplay(dpy);
984191cded7Smrg    SyncHandle();
985191cded7Smrg    return True;
986191cded7Smrg}
987191cded7Smrg
988191cded7SmrgBool
989b290cf36SmrgXF86VidModeSetViewPort(Display* dpy, int screen, int x, int y)
990191cded7Smrg{
991191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
992191cded7Smrg    xXF86VidModeSetViewPortReq *req;
993191cded7Smrg
994191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
995191cded7Smrg
996191cded7Smrg    LockDisplay(dpy);
997191cded7Smrg    GetReq(XF86VidModeSetViewPort, req);
998191cded7Smrg    req->reqType = info->codes->major_opcode;
999191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSetViewPort;
1000191cded7Smrg    req->screen = screen;
1001191cded7Smrg    req->x = x;
1002191cded7Smrg    req->y = y;
1003191cded7Smrg
1004191cded7Smrg    UnlockDisplay(dpy);
1005191cded7Smrg    SyncHandle();
1006191cded7Smrg    return True;
1007191cded7Smrg}
1008191cded7Smrg
1009191cded7SmrgBool
1010b290cf36SmrgXF86VidModeGetDotClocks(Display* dpy, int screen, int *flagsPtr,
1011b290cf36Smrg			int *numclocksPtr, int *maxclocksPtr, int *clocksPtr[])
1012191cded7Smrg{
1013191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1014191cded7Smrg    xXF86VidModeGetDotClocksReply rep;
1015191cded7Smrg    xXF86VidModeGetDotClocksReq *req;
1016adf1ce27Smrg    int *dotclocks;
1017191cded7Smrg    CARD32 dotclk;
1018d9dcd5aeSmrg    Bool result = True;
1019191cded7Smrg
1020191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1021191cded7Smrg
1022191cded7Smrg    LockDisplay(dpy);
1023191cded7Smrg    GetReq(XF86VidModeGetDotClocks, req);
1024191cded7Smrg    req->reqType = info->codes->major_opcode;
1025191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetDotClocks;
1026191cded7Smrg    req->screen = screen;
1027d9dcd5aeSmrg    if (!_XReply(dpy, (xReply *)&rep,
1028191cded7Smrg        (SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2, xFalse))
1029191cded7Smrg    {
1030191cded7Smrg        UnlockDisplay(dpy);
1031191cded7Smrg        SyncHandle();
1032191cded7Smrg        return False;
1033191cded7Smrg    }
1034191cded7Smrg    *numclocksPtr = rep.clocks;
1035191cded7Smrg    *maxclocksPtr = rep.maxclocks;
1036191cded7Smrg    *flagsPtr     = rep.flags;
1037191cded7Smrg
1038d9dcd5aeSmrg    dotclocks = Xcalloc(rep.clocks, sizeof(int));
1039d9dcd5aeSmrg    if (dotclocks == NULL) {
1040d9dcd5aeSmrg        _XEatDataWords(dpy, rep.length -
1041d9dcd5aeSmrg	    ((SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2));
1042d9dcd5aeSmrg        result = False;
1043191cded7Smrg    }
1044d9dcd5aeSmrg    else {
1045adf1ce27Smrg	unsigned int i;
1046adf1ce27Smrg
1047d9dcd5aeSmrg	for (i = 0; i < rep.clocks; i++) {
1048d9dcd5aeSmrg	    _XRead(dpy, (char*)&dotclk, 4);
1049d9dcd5aeSmrg	    dotclocks[i] = dotclk;
1050d9dcd5aeSmrg	}
1051191cded7Smrg    }
1052191cded7Smrg    *clocksPtr = dotclocks;
1053191cded7Smrg    UnlockDisplay(dpy);
1054191cded7Smrg    SyncHandle();
1055d9dcd5aeSmrg    return result;
1056191cded7Smrg}
1057191cded7Smrg
1058191cded7SmrgBool
1059191cded7SmrgXF86VidModeSetGammaRamp (
1060191cded7Smrg    Display *dpy,
1061191cded7Smrg    int screen,
1062191cded7Smrg    int size,
1063191cded7Smrg    unsigned short *red,
1064191cded7Smrg    unsigned short *green,
1065191cded7Smrg    unsigned short *blue
1066191cded7Smrg)
1067191cded7Smrg{
1068191cded7Smrg    int length = (size + 1) & ~1;
1069191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1070191cded7Smrg    xXF86VidModeSetGammaRampReq *req;
1071191cded7Smrg
1072191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1073191cded7Smrg    LockDisplay(dpy);
1074191cded7Smrg    GetReq(XF86VidModeSetGammaRamp, req);
1075191cded7Smrg    req->reqType = info->codes->major_opcode;
1076191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeSetGammaRamp;
1077191cded7Smrg    req->screen = screen;
1078191cded7Smrg    req->length += (length >> 1) * 3;
1079191cded7Smrg    req->size = size;
1080191cded7Smrg    _XSend(dpy, (char*)red, size * 2);
1081191cded7Smrg    _XSend(dpy, (char*)green, size * 2);
1082191cded7Smrg    _XSend(dpy, (char*)blue, size * 2);
1083191cded7Smrg    UnlockDisplay(dpy);
1084191cded7Smrg    SyncHandle();
1085191cded7Smrg    return True;
1086191cded7Smrg}
1087191cded7Smrg
1088191cded7Smrg
1089191cded7SmrgBool
1090191cded7SmrgXF86VidModeGetGammaRamp (
1091191cded7Smrg    Display *dpy,
1092191cded7Smrg    int screen,
1093191cded7Smrg    int size,
1094191cded7Smrg    unsigned short *red,
1095191cded7Smrg    unsigned short *green,
1096191cded7Smrg    unsigned short *blue
1097191cded7Smrg)
1098191cded7Smrg{
1099191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1100191cded7Smrg    xXF86VidModeGetGammaRampReq *req;
1101191cded7Smrg    xXF86VidModeGetGammaRampReply rep;
1102d9dcd5aeSmrg    Bool result = True;
1103d9dcd5aeSmrg
1104191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1105191cded7Smrg
1106191cded7Smrg    LockDisplay(dpy);
1107191cded7Smrg    GetReq(XF86VidModeGetGammaRamp, req);
1108191cded7Smrg    req->reqType = info->codes->major_opcode;
1109191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetGammaRamp;
1110191cded7Smrg    req->screen = screen;
1111191cded7Smrg    req->size = size;
1112191cded7Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1113d9dcd5aeSmrg        result = False;
1114191cded7Smrg    }
1115d9dcd5aeSmrg    else if (rep.size) {
1116d9dcd5aeSmrg	if (rep.size <= size) {
1117d9dcd5aeSmrg	    _XRead(dpy, (char*)red, rep.size << 1);
1118d9dcd5aeSmrg	    _XRead(dpy, (char*)green, rep.size << 1);
1119d9dcd5aeSmrg	    _XRead(dpy, (char*)blue, rep.size << 1);
1120d9dcd5aeSmrg	}
1121d9dcd5aeSmrg	else {
1122d9dcd5aeSmrg	    _XEatDataWords(dpy, rep.length);
1123d9dcd5aeSmrg	    result = False;
1124d9dcd5aeSmrg	}
1125191cded7Smrg    }
1126191cded7Smrg
1127191cded7Smrg    UnlockDisplay(dpy);
1128191cded7Smrg    SyncHandle();
1129d9dcd5aeSmrg    return result;
1130191cded7Smrg}
1131191cded7Smrg
1132191cded7SmrgBool XF86VidModeGetGammaRampSize(
1133191cded7Smrg    Display *dpy,
1134191cded7Smrg    int screen,
1135191cded7Smrg    int *size
1136191cded7Smrg)
1137191cded7Smrg{
1138191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1139191cded7Smrg    xXF86VidModeGetGammaRampSizeReq *req;
1140191cded7Smrg    xXF86VidModeGetGammaRampSizeReply rep;
1141d9dcd5aeSmrg
1142191cded7Smrg    *size = 0;
1143191cded7Smrg
1144191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1145191cded7Smrg
1146191cded7Smrg    LockDisplay(dpy);
1147191cded7Smrg    GetReq(XF86VidModeGetGammaRampSize, req);
1148191cded7Smrg    req->reqType = info->codes->major_opcode;
1149191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetGammaRampSize;
1150191cded7Smrg    req->screen = screen;
1151191cded7Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
1152191cded7Smrg        UnlockDisplay (dpy);
1153191cded7Smrg        SyncHandle ();
1154d9dcd5aeSmrg        return False;
1155191cded7Smrg    }
1156191cded7Smrg    *size = rep.size;
1157191cded7Smrg    UnlockDisplay(dpy);
1158191cded7Smrg    SyncHandle();
1159191cded7Smrg    return True;
1160191cded7Smrg}
1161191cded7Smrg
1162191cded7SmrgBool XF86VidModeGetPermissions(
1163191cded7Smrg    Display *dpy,
1164191cded7Smrg    int screen,
1165191cded7Smrg    int *permissions
1166191cded7Smrg)
1167191cded7Smrg{
1168191cded7Smrg    XExtDisplayInfo *info = find_display (dpy);
1169191cded7Smrg    xXF86VidModeGetPermissionsReq *req;
1170191cded7Smrg    xXF86VidModeGetPermissionsReply rep;
1171d9dcd5aeSmrg
1172191cded7Smrg    *permissions = 0;
1173191cded7Smrg
1174191cded7Smrg    XF86VidModeCheckExtension (dpy, info, False);
1175191cded7Smrg
1176191cded7Smrg    LockDisplay(dpy);
1177191cded7Smrg    GetReq(XF86VidModeGetPermissions, req);
1178191cded7Smrg    req->reqType = info->codes->major_opcode;
1179191cded7Smrg    req->xf86vidmodeReqType = X_XF86VidModeGetPermissions;
1180191cded7Smrg    req->screen = screen;
1181191cded7Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
1182191cded7Smrg        UnlockDisplay (dpy);
1183191cded7Smrg        SyncHandle ();
1184d9dcd5aeSmrg        return False;
1185191cded7Smrg    }
1186191cded7Smrg    *permissions = rep.permissions;
1187191cded7Smrg    UnlockDisplay(dpy);
1188191cded7Smrg    SyncHandle();
1189191cded7Smrg    return True;
1190191cded7Smrg}
1191191cded7Smrg
1192