1/*
2
3Copyright (c) 1995  Kaleb S. KEITHLEY
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the
7"Software"), to deal in the Software without restriction, including
8without limitation the rights to use, copy, modify, merge, publish,
9distribute, sublicense, and/or sell copies of the Software, and to
10permit persons to whom the Software is furnished to do so, subject to
11the following conditions:
12
13The above copyright notice and this permission notice shall be
14included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES
20OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of Kaleb S. KEITHLEY
25shall not be used in advertising or otherwise to promote the sale, use
26or other dealings in this Software without prior written authorization
27from Kaleb S. KEITHLEY.
28
29*/
30
31/* THIS IS NOT AN X CONSORTIUM STANDARD */
32
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36
37#include <X11/Xlibint.h>
38#include <X11/extensions/xf86vmproto.h>
39#include <X11/extensions/xf86vmode.h>
40#include <X11/extensions/Xext.h>
41#include <X11/extensions/extutil.h>
42#include <limits.h>
43
44#ifdef DEBUG
45#include <stdio.h>
46#endif
47
48#ifndef MODE_BAD
49#define MODE_BAD 255
50#endif
51
52static XExtensionInfo _xf86vidmode_info_data;
53static XExtensionInfo *xf86vidmode_info = &_xf86vidmode_info_data;
54static const char *xf86vidmode_extension_name = XF86VIDMODENAME;
55
56#define XF86VidModeCheckExtension(dpy,i,val) \
57  XextCheckExtension (dpy, i, xf86vidmode_extension_name, val)
58
59/*****************************************************************************
60 *                                                                           *
61 *			   private utility routines                          *
62 *                                                                           *
63 *****************************************************************************/
64
65static XEXT_CLOSE_DISPLAY_PROTO(close_display);
66static /* const */ XExtensionHooks xf86vidmode_extension_hooks = {
67    NULL,				/* create_gc */
68    NULL,				/* copy_gc */
69    NULL,				/* flush_gc */
70    NULL,				/* free_gc */
71    NULL,				/* create_font */
72    NULL,				/* free_font */
73    close_display,			/* close_display */
74    NULL,				/* wire_to_event */
75    NULL,				/* event_to_wire */
76    NULL,				/* error */
77    NULL,				/* error_string */
78};
79
80static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86vidmode_info,
81				   xf86vidmode_extension_name,
82				   &xf86vidmode_extension_hooks,
83				   0, NULL)
84
85static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86vidmode_info)
86
87
88/*****************************************************************************
89 *                                                                           *
90 *		    public XFree86-VidMode Extension routines                *
91 *                                                                           *
92 *****************************************************************************/
93
94Bool
95XF86VidModeQueryExtension(Display *dpy, int *event_basep, int *error_basep)
96{
97    XExtDisplayInfo *info = find_display (dpy);
98
99    if (XextHasExtension(info)) {
100	*event_basep = info->codes->first_event;
101	*error_basep = info->codes->first_error;
102	return True;
103    } else {
104	return False;
105    }
106}
107
108Bool
109XF86VidModeQueryVersion(Display* dpy, int* majorVersion, int* minorVersion)
110{
111    XExtDisplayInfo *info = find_display (dpy);
112    xXF86VidModeQueryVersionReply rep;
113    xXF86VidModeQueryVersionReq *req;
114
115    XF86VidModeCheckExtension (dpy, info, False);
116
117    LockDisplay(dpy);
118    GetReq(XF86VidModeQueryVersion, req);
119    req->reqType = info->codes->major_opcode;
120    req->xf86vidmodeReqType = X_XF86VidModeQueryVersion;
121    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
122	UnlockDisplay(dpy);
123	SyncHandle();
124	return False;
125    }
126    *majorVersion = rep.majorVersion;
127    *minorVersion = rep.minorVersion;
128    UnlockDisplay(dpy);
129    SyncHandle();
130    if (*majorVersion >= 2)
131	XF86VidModeSetClientVersion(dpy);
132    return True;
133}
134
135Bool
136XF86VidModeSetClientVersion(Display *dpy)
137{
138    XExtDisplayInfo *info = find_display(dpy);
139    xXF86VidModeSetClientVersionReq *req;
140
141    XF86VidModeCheckExtension(dpy, info, False);
142
143    LockDisplay(dpy);
144    GetReq(XF86VidModeSetClientVersion, req);
145    req->reqType = info->codes->major_opcode;
146    req->xf86vidmodeReqType = X_XF86VidModeSetClientVersion;
147    req->major = XF86VIDMODE_MAJOR_VERSION;
148    req->minor = XF86VIDMODE_MINOR_VERSION;
149    UnlockDisplay(dpy);
150    SyncHandle();
151    return True;
152}
153
154Bool
155XF86VidModeSetGamma(Display *dpy, int screen, XF86VidModeGamma *Gamma)
156{
157    XExtDisplayInfo *info = find_display(dpy);
158    xXF86VidModeSetGammaReq *req;
159
160    XF86VidModeCheckExtension(dpy, info, False);
161
162    LockDisplay(dpy);
163    GetReq(XF86VidModeSetGamma, req);
164    req->reqType = info->codes->major_opcode;
165    req->xf86vidmodeReqType = X_XF86VidModeSetGamma;
166    req->screen = screen;
167    req->red = (CARD32)(Gamma->red * 10000.);
168    req->green = (CARD32)(Gamma->green * 10000.);
169    req->blue = (CARD32)(Gamma->blue * 10000.);
170    UnlockDisplay(dpy);
171    SyncHandle();
172    return True;
173}
174
175Bool
176XF86VidModeGetGamma(Display *dpy, int screen, XF86VidModeGamma *Gamma)
177{
178    XExtDisplayInfo *info = find_display (dpy);
179    xXF86VidModeGetGammaReply rep;
180    xXF86VidModeGetGammaReq *req;
181
182    XF86VidModeCheckExtension (dpy, info, False);
183
184    LockDisplay(dpy);
185    GetReq(XF86VidModeGetGamma, req);
186    req->reqType = info->codes->major_opcode;
187    req->xf86vidmodeReqType = X_XF86VidModeGetGamma;
188    req->screen = screen;
189    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
190	UnlockDisplay(dpy);
191	SyncHandle();
192	return False;
193    }
194    Gamma->red = ((float)rep.red) / 10000.;
195    Gamma->green = ((float)rep.green) / 10000.;
196    Gamma->blue = ((float)rep.blue) / 10000.;
197    UnlockDisplay(dpy);
198    SyncHandle();
199    return True;
200}
201
202Bool
203XF86VidModeGetModeLine(Display* dpy, int screen, int* dotclock,
204		       XF86VidModeModeLine* modeline)
205{
206    XExtDisplayInfo *info = find_display (dpy);
207    xXF86VidModeGetModeLineReq *req;
208    int majorVersion, minorVersion;
209    CARD32 remaining_len;
210    Bool result = True;
211
212    XF86VidModeCheckExtension (dpy, info, False);
213    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
214
215    LockDisplay(dpy);
216    GetReq(XF86VidModeGetModeLine, req);
217    req->reqType = info->codes->major_opcode;
218    req->xf86vidmodeReqType = X_XF86VidModeGetModeLine;
219    req->screen = screen;
220
221    if (_X_UNLIKELY(majorVersion < 2)) {
222	xXF86OldVidModeGetModeLineReply oldrep;
223
224	if (!_XReply(dpy, (xReply *)&oldrep,
225            (SIZEOF(xXF86OldVidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) {
226	    UnlockDisplay(dpy);
227	    SyncHandle();
228	    return False;
229	}
230	remaining_len = oldrep.length -
231	    ((SIZEOF(xXF86OldVidModeGetModeLineReply) - SIZEOF(xReply)) >> 2);
232	*dotclock = oldrep.dotclock;
233	modeline->hdisplay   = oldrep.hdisplay;
234	modeline->hsyncstart = oldrep.hsyncstart;
235	modeline->hsyncend   = oldrep.hsyncend;
236	modeline->htotal     = oldrep.htotal;
237	modeline->hskew      = 0;
238	modeline->vdisplay   = oldrep.vdisplay;
239	modeline->vsyncstart = oldrep.vsyncstart;
240	modeline->vsyncend   = oldrep.vsyncend;
241	modeline->vtotal     = oldrep.vtotal;
242	modeline->flags      = oldrep.flags;
243	modeline->privsize   = oldrep.privsize;
244    } else {
245	xXF86VidModeGetModeLineReply rep;
246
247	if (!_XReply(dpy, (xReply *)&rep,
248            (SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) {
249	    UnlockDisplay(dpy);
250	    SyncHandle();
251	    return False;
252	}
253	remaining_len = rep.length -
254	    ((SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2);
255	*dotclock = rep.dotclock;
256	modeline->hdisplay   = rep.hdisplay;
257	modeline->hsyncstart = rep.hsyncstart;
258	modeline->hsyncend   = rep.hsyncend;
259	modeline->htotal     = rep.htotal;
260	modeline->hskew      = rep.hskew;
261	modeline->vdisplay   = rep.vdisplay;
262	modeline->vsyncstart = rep.vsyncstart;
263	modeline->vsyncend   = rep.vsyncend;
264	modeline->vtotal     = rep.vtotal;
265	modeline->flags      = rep.flags;
266	modeline->privsize   = rep.privsize;
267    }
268
269    if (modeline->privsize > 0) {
270	if ((unsigned) modeline->privsize < (INT_MAX / sizeof(INT32)))
271	    modeline->private = Xcalloc(modeline->privsize, sizeof(INT32));
272	else
273	    modeline->private = NULL;
274	if (modeline->private == NULL) {
275	    _XEatDataWords(dpy, remaining_len);
276	    result = False;
277	} else
278	    _XRead(dpy, (char*)modeline->private, modeline->privsize * sizeof(INT32));
279    } else {
280	modeline->private = NULL;
281    }
282    UnlockDisplay(dpy);
283    SyncHandle();
284    return result;
285}
286
287Bool
288XF86VidModeGetAllModeLines(Display* dpy, int screen, int* modecount,
289			   XF86VidModeModeInfo ***modelinesPtr)
290{
291    XExtDisplayInfo *info = find_display (dpy);
292    xXF86VidModeGetAllModeLinesReply rep;
293    xXF86VidModeGetAllModeLinesReq *req;
294    XF86VidModeModeInfo *mdinfptr, **modelines;
295    xXF86VidModeModeInfo xmdline;
296    xXF86OldVidModeModeInfo oldxmdline;
297    unsigned int i;
298    int majorVersion, minorVersion;
299    Bool protocolBug = False;
300
301    XF86VidModeCheckExtension (dpy, info, False);
302
303    /*
304     * Note: There was a bug in the protocol implementation in versions
305     * 0.x with x < 8 (the .private field wasn't being passed over the wire).
306     * Check the server's version, and accept the old format if appropriate.
307     */
308
309    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
310    if (majorVersion == 0 && minorVersion < 8) {
311	protocolBug = True;
312#ifdef DEBUG
313	fprintf(stderr, "XF86VidModeGetAllModeLines: Warning: Xserver is"
314		"running an old version (%d.%d)\n", majorVersion,
315		minorVersion);
316#endif
317    }
318
319    LockDisplay(dpy);
320    GetReq(XF86VidModeGetAllModeLines, req);
321    req->reqType = info->codes->major_opcode;
322    req->xf86vidmodeReqType = X_XF86VidModeGetAllModeLines;
323    req->screen = screen;
324    if (!_XReply(dpy, (xReply *)&rep,
325        (SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2, xFalse)) {
326        UnlockDisplay(dpy);
327	SyncHandle();
328	return False;
329    }
330
331    *modecount = rep.modecount;
332
333    if (!(modelines = (XF86VidModeModeInfo **) Xcalloc(rep.modecount,
334                                          sizeof(XF86VidModeModeInfo *)
335                                          +sizeof(XF86VidModeModeInfo)))) {
336	_XEatDataWords(dpy, rep.length -
337	    ((SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2));
338	UnlockDisplay(dpy);
339	SyncHandle();
340        return False;
341    }
342    mdinfptr = (XF86VidModeModeInfo *) (
343			    (char *) modelines
344			    + rep.modecount*sizeof(XF86VidModeModeInfo *)
345		    );
346
347    for (i = 0; i < rep.modecount; i++) {
348        modelines[i] = mdinfptr++;
349	if (_X_UNLIKELY(majorVersion < 2)) {
350            _XRead(dpy, (char*)&oldxmdline, sizeof(xXF86OldVidModeModeInfo));
351	    modelines[i]->dotclock   = oldxmdline.dotclock;
352	    modelines[i]->hdisplay   = oldxmdline.hdisplay;
353	    modelines[i]->hsyncstart = oldxmdline.hsyncstart;
354	    modelines[i]->hsyncend   = oldxmdline.hsyncend;
355	    modelines[i]->htotal     = oldxmdline.htotal;
356	    modelines[i]->hskew      = 0;
357	    modelines[i]->vdisplay   = oldxmdline.vdisplay;
358	    modelines[i]->vsyncstart = oldxmdline.vsyncstart;
359	    modelines[i]->vsyncend   = oldxmdline.vsyncend;
360	    modelines[i]->vtotal     = oldxmdline.vtotal;
361	    modelines[i]->flags      = oldxmdline.flags;
362	    if (protocolBug) {
363		modelines[i]->privsize = 0;
364		modelines[i]->private = NULL;
365	    } else {
366		modelines[i]->privsize   = oldxmdline.privsize;
367		if (oldxmdline.privsize > 0) {
368	            if (!(modelines[i]->private =
369			    Xcalloc(oldxmdline.privsize, sizeof(INT32)))) {
370			_XEatDataWords(dpy, oldxmdline.privsize);
371		    } else {
372			_XRead(dpy, (char*)modelines[i]->private,
373			     oldxmdline.privsize * sizeof(INT32));
374		    }
375		} else {
376		  modelines[i]->private = NULL;
377		}
378	    }
379	} else {
380            _XRead(dpy, (char*)&xmdline, sizeof(xXF86VidModeModeInfo));
381	    modelines[i]->dotclock   = xmdline.dotclock;
382	    modelines[i]->hdisplay   = xmdline.hdisplay;
383	    modelines[i]->hsyncstart = xmdline.hsyncstart;
384	    modelines[i]->hsyncend   = xmdline.hsyncend;
385	    modelines[i]->htotal     = xmdline.htotal;
386	    modelines[i]->hskew      = xmdline.hskew;
387	    modelines[i]->vdisplay   = xmdline.vdisplay;
388	    modelines[i]->vsyncstart = xmdline.vsyncstart;
389	    modelines[i]->vsyncend   = xmdline.vsyncend;
390	    modelines[i]->vtotal     = xmdline.vtotal;
391	    modelines[i]->flags      = xmdline.flags;
392	    if (protocolBug) {
393		modelines[i]->privsize = 0;
394		modelines[i]->private = NULL;
395	    } else {
396		modelines[i]->privsize   = xmdline.privsize;
397		if (xmdline.privsize > 0) {
398		    if (!(modelines[i]->private =
399			    Xcalloc(xmdline.privsize, sizeof(INT32)))) {
400			_XEatDataWords(dpy, xmdline.privsize);
401		    } else {
402			_XRead(dpy, (char*)modelines[i]->private,
403			     xmdline.privsize * sizeof(INT32));
404		    }
405		} else {
406		    modelines[i]->private = NULL;
407		}
408	    }
409	}
410    }
411    *modelinesPtr = modelines;
412    UnlockDisplay(dpy);
413    SyncHandle();
414    return True;
415}
416
417/*
418 * GetReq replacement for use with VidMode protocols earlier than 2.0
419 */
420#define GetOldReq(name, oldname, req) \
421	req = (x##oldname##Req *) \
422	    _XGetRequest(dpy, X_##name, SIZEOF(x##oldname##Req))
423
424Bool
425XF86VidModeAddModeLine(Display *dpy, int screen,
426		       XF86VidModeModeInfo* newmodeline,
427		       XF86VidModeModeInfo* aftermodeline)
428{
429    XExtDisplayInfo *info = find_display (dpy);
430    int majorVersion, minorVersion;
431
432    XF86VidModeCheckExtension (dpy, info, False);
433    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
434
435    LockDisplay(dpy);
436    if (_X_UNLIKELY(majorVersion < 2)) {
437	xXF86OldVidModeAddModeLineReq *oldreq;
438
439	GetOldReq(XF86VidModeAddModeLine, XF86OldVidModeAddModeLine, oldreq);
440	oldreq->reqType = info->codes->major_opcode;
441	oldreq->xf86vidmodeReqType = X_XF86VidModeAddModeLine;
442	oldreq->screen = screen;
443	oldreq->dotclock =	newmodeline->dotclock;
444	oldreq->hdisplay =	newmodeline->hdisplay;
445	oldreq->hsyncstart =	newmodeline->hsyncstart;
446	oldreq->hsyncend =	newmodeline->hsyncend;
447	oldreq->htotal =	newmodeline->htotal;
448	oldreq->vdisplay =	newmodeline->vdisplay;
449	oldreq->vsyncstart =	newmodeline->vsyncstart;
450	oldreq->vsyncend =	newmodeline->vsyncend;
451	oldreq->vtotal =	newmodeline->vtotal;
452	oldreq->flags =		newmodeline->flags;
453	oldreq->privsize =	newmodeline->privsize;
454	if (aftermodeline != NULL) {
455	    oldreq->after_dotclock =	aftermodeline->dotclock;
456	    oldreq->after_hdisplay =	aftermodeline->hdisplay;
457	    oldreq->after_hsyncstart =	aftermodeline->hsyncstart;
458	    oldreq->after_hsyncend =	aftermodeline->hsyncend;
459	    oldreq->after_htotal =	aftermodeline->htotal;
460	    oldreq->after_vdisplay =	aftermodeline->vdisplay;
461	    oldreq->after_vsyncstart =	aftermodeline->vsyncstart;
462	    oldreq->after_vsyncend =	aftermodeline->vsyncend;
463	    oldreq->after_vtotal =	aftermodeline->vtotal;
464	    oldreq->after_flags =	aftermodeline->flags;
465	} else {
466	    oldreq->after_dotclock =	0;
467	    oldreq->after_hdisplay =	0;
468	    oldreq->after_hsyncstart =	0;
469	    oldreq->after_hsyncend =	0;
470	    oldreq->after_htotal =	0;
471	    oldreq->after_vdisplay =	0;
472	    oldreq->after_vsyncstart =	0;
473	    oldreq->after_vsyncend =	0;
474	    oldreq->after_vtotal =	0;
475	    oldreq->after_flags =	0;
476	}
477	if (newmodeline->privsize) {
478	    oldreq->length += newmodeline->privsize;
479	    Data32(dpy, (long *) newmodeline->private,
480	       newmodeline->privsize * sizeof(INT32));
481	}
482    } else {
483	xXF86VidModeAddModeLineReq *req;
484
485	GetReq(XF86VidModeAddModeLine, req);
486	req->reqType = info->codes->major_opcode;
487	req->xf86vidmodeReqType = X_XF86VidModeAddModeLine;
488	req->screen = screen;
489	req->dotclock =		newmodeline->dotclock;
490	req->hdisplay =		newmodeline->hdisplay;
491	req->hsyncstart =	newmodeline->hsyncstart;
492	req->hsyncend =		newmodeline->hsyncend;
493	req->htotal =		newmodeline->htotal;
494	req->hskew =		newmodeline->hskew;
495	req->vdisplay =		newmodeline->vdisplay;
496	req->vsyncstart =	newmodeline->vsyncstart;
497	req->vsyncend =		newmodeline->vsyncend;
498	req->vtotal =		newmodeline->vtotal;
499	req->flags =		newmodeline->flags;
500	req->privsize =		newmodeline->privsize;
501	if (aftermodeline != NULL) {
502	    req->after_dotclock =	aftermodeline->dotclock;
503	    req->after_hdisplay =	aftermodeline->hdisplay;
504	    req->after_hsyncstart =	aftermodeline->hsyncstart;
505	    req->after_hsyncend =	aftermodeline->hsyncend;
506	    req->after_htotal =		aftermodeline->htotal;
507	    req->after_hskew =		aftermodeline->hskew;
508	    req->after_vdisplay =	aftermodeline->vdisplay;
509	    req->after_vsyncstart =	aftermodeline->vsyncstart;
510	    req->after_vsyncend =	aftermodeline->vsyncend;
511	    req->after_vtotal =		aftermodeline->vtotal;
512	    req->after_flags =		aftermodeline->flags;
513	} else {
514	    req->after_dotclock =	0;
515	    req->after_hdisplay =	0;
516	    req->after_hsyncstart =	0;
517	    req->after_hsyncend =	0;
518	    req->after_htotal =		0;
519	    req->after_hskew =		0;
520	    req->after_vdisplay =	0;
521	    req->after_vsyncstart =	0;
522	    req->after_vsyncend =	0;
523	    req->after_vtotal =		0;
524	    req->after_flags =		0;
525	}
526	if (newmodeline->privsize) {
527	    req->length += newmodeline->privsize;
528	    Data32(dpy, (long *) newmodeline->private,
529	       newmodeline->privsize * sizeof(INT32));
530	}
531    }
532    UnlockDisplay(dpy);
533    SyncHandle();
534    return True;
535}
536
537Bool
538XF86VidModeDeleteModeLine(Display *dpy, int screen,
539			  XF86VidModeModeInfo* modeline)
540{
541    XExtDisplayInfo *info = find_display (dpy);
542    int majorVersion, minorVersion;
543
544    XF86VidModeCheckExtension (dpy, info, 0);
545    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
546
547    LockDisplay(dpy);
548    if (_X_UNLIKELY(majorVersion < 2)) {
549	xXF86OldVidModeDeleteModeLineReq *oldreq;
550
551	GetOldReq(XF86VidModeDeleteModeLine, XF86OldVidModeDeleteModeLine, oldreq);
552	oldreq->reqType = info->codes->major_opcode;
553	oldreq->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine;
554	oldreq->screen = screen;
555	oldreq->dotclock =	modeline->dotclock;
556	oldreq->hdisplay =	modeline->hdisplay;
557	oldreq->hsyncstart =	modeline->hsyncstart;
558	oldreq->hsyncend =	modeline->hsyncend;
559	oldreq->htotal =	modeline->htotal;
560	oldreq->vdisplay =	modeline->vdisplay;
561	oldreq->vsyncstart =	modeline->vsyncstart;
562	oldreq->vsyncend =	modeline->vsyncend;
563	oldreq->vtotal =	modeline->vtotal;
564	oldreq->flags =		modeline->flags;
565	oldreq->privsize =	modeline->privsize;
566	if (modeline->privsize) {
567	    oldreq->length += modeline->privsize;
568	    Data32(dpy, (long *) modeline->private,
569	       modeline->privsize * sizeof(INT32));
570	}
571    } else {
572	xXF86VidModeDeleteModeLineReq *req;
573
574	GetReq(XF86VidModeDeleteModeLine, req);
575	req->reqType = info->codes->major_opcode;
576	req->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine;
577	req->screen = screen;
578	req->dotclock =		modeline->dotclock;
579	req->hdisplay =		modeline->hdisplay;
580	req->hsyncstart =	modeline->hsyncstart;
581	req->hsyncend =		modeline->hsyncend;
582	req->htotal =		modeline->htotal;
583	req->hskew =		modeline->hskew;
584	req->vdisplay =		modeline->vdisplay;
585	req->vsyncstart =	modeline->vsyncstart;
586	req->vsyncend =		modeline->vsyncend;
587	req->vtotal =		modeline->vtotal;
588	req->flags =		modeline->flags;
589	req->privsize =		modeline->privsize;
590	if (modeline->privsize) {
591	    req->length += modeline->privsize;
592	    Data32(dpy, (long *) modeline->private,
593	       modeline->privsize * sizeof(INT32));
594	}
595    }
596    UnlockDisplay(dpy);
597    SyncHandle();
598    return True;
599}
600
601Bool
602XF86VidModeModModeLine(Display *dpy, int screen, XF86VidModeModeLine* modeline)
603{
604    XExtDisplayInfo *info = find_display (dpy);
605    int majorVersion, minorVersion;
606
607    XF86VidModeCheckExtension (dpy, info, 0);
608    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
609
610    LockDisplay(dpy);
611    if (_X_UNLIKELY(majorVersion < 2)) {
612	xXF86OldVidModeModModeLineReq *oldreq;
613
614	GetOldReq(XF86VidModeModModeLine, XF86OldVidModeModModeLine, oldreq);
615	oldreq->reqType = info->codes->major_opcode;
616	oldreq->xf86vidmodeReqType = X_XF86VidModeModModeLine;
617	oldreq->screen = screen;
618	oldreq->hdisplay =	modeline->hdisplay;
619	oldreq->hsyncstart =	modeline->hsyncstart;
620	oldreq->hsyncend =	modeline->hsyncend;
621	oldreq->htotal =	modeline->htotal;
622	oldreq->vdisplay =	modeline->vdisplay;
623	oldreq->vsyncstart =	modeline->vsyncstart;
624	oldreq->vsyncend =	modeline->vsyncend;
625	oldreq->vtotal =	modeline->vtotal;
626	oldreq->flags =		modeline->flags;
627	oldreq->privsize =	modeline->privsize;
628	if (modeline->privsize) {
629	    oldreq->length += modeline->privsize;
630	    Data32(dpy, (long *) modeline->private,
631	       modeline->privsize * sizeof(INT32));
632	}
633    } else {
634	xXF86VidModeModModeLineReq *req;
635
636	GetReq(XF86VidModeModModeLine, req);
637	req->reqType = info->codes->major_opcode;
638	req->xf86vidmodeReqType = X_XF86VidModeModModeLine;
639	req->screen = screen;
640	req->hdisplay =		modeline->hdisplay;
641	req->hsyncstart =	modeline->hsyncstart;
642	req->hsyncend =		modeline->hsyncend;
643	req->htotal =		modeline->htotal;
644	req->hskew =		modeline->hskew;
645	req->vdisplay =		modeline->vdisplay;
646	req->vsyncstart =	modeline->vsyncstart;
647	req->vsyncend =		modeline->vsyncend;
648	req->vtotal =		modeline->vtotal;
649	req->flags =		modeline->flags;
650	req->privsize =		modeline->privsize;
651	if (modeline->privsize) {
652	    req->length += modeline->privsize;
653	    Data32(dpy, (long *) modeline->private,
654	       modeline->privsize * sizeof(INT32));
655	}
656    }
657    UnlockDisplay(dpy);
658    SyncHandle();
659    return True;
660}
661
662Status
663XF86VidModeValidateModeLine(Display *dpy, int screen,
664			    XF86VidModeModeInfo* modeline)
665{
666    XExtDisplayInfo *info = find_display (dpy);
667    xXF86VidModeValidateModeLineReply rep;
668    int majorVersion, minorVersion;
669
670    XF86VidModeCheckExtension (dpy, info, 0);
671    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
672
673    LockDisplay(dpy);
674
675    if (_X_UNLIKELY(majorVersion < 2)) {
676	xXF86OldVidModeValidateModeLineReq *oldreq;
677
678	GetOldReq(XF86VidModeValidateModeLine, XF86OldVidModeValidateModeLine, oldreq);
679	oldreq->reqType = info->codes->major_opcode;
680	oldreq->xf86vidmodeReqType = X_XF86VidModeValidateModeLine;
681	oldreq->screen = screen;
682	oldreq->dotclock =	modeline->dotclock;
683	oldreq->hdisplay =	modeline->hdisplay;
684	oldreq->hsyncstart =	modeline->hsyncstart;
685	oldreq->hsyncend =	modeline->hsyncend;
686	oldreq->htotal =	modeline->htotal;
687	oldreq->vdisplay =	modeline->vdisplay;
688	oldreq->vsyncstart =	modeline->vsyncstart;
689	oldreq->vsyncend =	modeline->vsyncend;
690	oldreq->vtotal =	modeline->vtotal;
691	oldreq->flags =		modeline->flags;
692	oldreq->privsize =	modeline->privsize;
693	if (modeline->privsize) {
694	    oldreq->length += modeline->privsize;
695	    Data32(dpy, (long *) modeline->private,
696	       modeline->privsize * sizeof(INT32));
697	}
698    } else {
699	xXF86VidModeValidateModeLineReq *req;
700
701	GetReq(XF86VidModeValidateModeLine, req);
702	req->reqType = info->codes->major_opcode;
703	req->xf86vidmodeReqType = X_XF86VidModeValidateModeLine;
704	req->screen = screen;
705	req->dotclock =		modeline->dotclock;
706	req->hdisplay =		modeline->hdisplay;
707	req->hsyncstart =	modeline->hsyncstart;
708	req->hsyncend =		modeline->hsyncend;
709	req->htotal =		modeline->htotal;
710	req->hskew =		modeline->hskew;
711	req->vdisplay =		modeline->vdisplay;
712	req->vsyncstart =	modeline->vsyncstart;
713	req->vsyncend =		modeline->vsyncend;
714	req->vtotal =		modeline->vtotal;
715	req->flags =		modeline->flags;
716	req->privsize =		modeline->privsize;
717	if (modeline->privsize) {
718	    req->length += modeline->privsize;
719	    Data32(dpy, (long *) modeline->private,
720	       modeline->privsize * sizeof(INT32));
721	}
722    }
723    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
724	UnlockDisplay(dpy);
725	SyncHandle();
726	return MODE_BAD;
727    }
728    UnlockDisplay(dpy);
729    SyncHandle();
730    return rep.status;
731}
732
733Bool
734XF86VidModeSwitchMode(Display* dpy, int screen, int zoom)
735{
736    XExtDisplayInfo *info = find_display (dpy);
737    xXF86VidModeSwitchModeReq *req;
738
739    XF86VidModeCheckExtension (dpy, info, False);
740
741    LockDisplay(dpy);
742    GetReq(XF86VidModeSwitchMode, req);
743    req->reqType = info->codes->major_opcode;
744    req->xf86vidmodeReqType = X_XF86VidModeSwitchMode;
745    req->screen = screen;
746    req->zoom = zoom;
747    UnlockDisplay(dpy);
748    SyncHandle();
749    return True;
750}
751
752Bool
753XF86VidModeSwitchToMode(Display* dpy, int screen, XF86VidModeModeInfo* modeline)
754{
755    XExtDisplayInfo *info = find_display (dpy);
756    xXF86VidModeSwitchToModeReq *req;
757    xXF86OldVidModeSwitchToModeReq *oldreq;
758    int majorVersion, minorVersion;
759    Bool protocolBug = False;
760
761    XF86VidModeCheckExtension (dpy, info, False);
762
763    /*
764     * Note: There was a bug in the protocol implementation in versions
765     * 0.x with x < 8 (the .private field wasn't expected to be sent over
766     * the wire).  Check the server's version, and accept the old format
767     * if appropriate.
768     */
769
770    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
771    if (_X_UNLIKELY(majorVersion == 0 && minorVersion < 8)) {
772	protocolBug = True;
773#ifdef DEBUG
774	fprintf(stderr, "XF86VidModeSwitchToMode: Warning: Xserver is"
775		"running an old version (%d.%d)\n", majorVersion,
776		minorVersion);
777#endif
778    }
779
780    LockDisplay(dpy);
781    if (_X_UNLIKELY(majorVersion < 2)) {
782	GetOldReq(XF86VidModeSwitchToMode, XF86OldVidModeSwitchToMode, oldreq);
783	oldreq->reqType = info->codes->major_opcode;
784	oldreq->xf86vidmodeReqType = X_XF86VidModeSwitchToMode;
785	oldreq->screen = screen;
786	oldreq->dotclock =	modeline->dotclock;
787	oldreq->hdisplay =	modeline->hdisplay;
788	oldreq->hsyncstart =	modeline->hsyncstart;
789	oldreq->hsyncend =	modeline->hsyncend;
790	oldreq->htotal =	modeline->htotal;
791	oldreq->vdisplay =	modeline->vdisplay;
792	oldreq->vsyncstart =	modeline->vsyncstart;
793	oldreq->vsyncend =	modeline->vsyncend;
794	oldreq->vtotal =	modeline->vtotal;
795	oldreq->flags =	modeline->flags;
796	if (protocolBug) {
797	    oldreq->privsize = 0;
798	} else {
799	    oldreq->privsize =	modeline->privsize;
800	    if (modeline->privsize) {
801		oldreq->length += modeline->privsize;
802		Data32(dpy, (long *) modeline->private,
803	           modeline->privsize * sizeof(INT32));
804	    }
805	}
806    } else {
807	GetReq(XF86VidModeSwitchToMode, req);
808	req->reqType = info->codes->major_opcode;
809	req->xf86vidmodeReqType = X_XF86VidModeSwitchToMode;
810	req->screen = screen;
811	req->dotclock =	modeline->dotclock;
812	req->hdisplay =	modeline->hdisplay;
813	req->hsyncstart =	modeline->hsyncstart;
814	req->hsyncend =	modeline->hsyncend;
815	req->htotal =	modeline->htotal;
816	req->hskew =	modeline->hskew;
817	req->vdisplay =	modeline->vdisplay;
818	req->vsyncstart =	modeline->vsyncstart;
819	req->vsyncend =	modeline->vsyncend;
820	req->vtotal =	modeline->vtotal;
821	req->flags =	modeline->flags;
822	if (protocolBug) {
823	    req->privsize = 0;
824	} else {
825	    req->privsize =	modeline->privsize;
826	    if (modeline->privsize) {
827		req->length += modeline->privsize;
828		Data32(dpy, (long *) modeline->private,
829	           modeline->privsize * sizeof(INT32));
830	    }
831	}
832    }
833    UnlockDisplay(dpy);
834    SyncHandle();
835    return True;
836}
837
838Bool
839XF86VidModeLockModeSwitch(Display* dpy, int screen, int lock)
840{
841    XExtDisplayInfo *info = find_display (dpy);
842    xXF86VidModeLockModeSwitchReq *req;
843
844    XF86VidModeCheckExtension (dpy, info, False);
845
846    LockDisplay(dpy);
847    GetReq(XF86VidModeLockModeSwitch, req);
848    req->reqType = info->codes->major_opcode;
849    req->xf86vidmodeReqType = X_XF86VidModeLockModeSwitch;
850    req->screen = screen;
851    req->lock = lock;
852    UnlockDisplay(dpy);
853    SyncHandle();
854    return True;
855}
856
857Bool
858XF86VidModeGetMonitor(Display* dpy, int screen, XF86VidModeMonitor* monitor)
859{
860    XExtDisplayInfo *info = find_display (dpy);
861    xXF86VidModeGetMonitorReply rep;
862    xXF86VidModeGetMonitorReq *req;
863    CARD32 syncrange;
864    int i;
865    Bool result = True;
866
867    XF86VidModeCheckExtension (dpy, info, False);
868
869    LockDisplay(dpy);
870    GetReq(XF86VidModeGetMonitor, req);
871    req->reqType = info->codes->major_opcode;
872    req->xf86vidmodeReqType = X_XF86VidModeGetMonitor;
873    req->screen = screen;
874    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
875	UnlockDisplay(dpy);
876	SyncHandle();
877	return False;
878    }
879    monitor->nhsync = rep.nhsync;
880    monitor->nvsync = rep.nvsync;
881#if 0
882    monitor->bandwidth = (float)rep.bandwidth / 1e6;
883#endif
884    if (rep.vendorLength) {
885	monitor->vendor = Xcalloc(rep.vendorLength + 1, 1);
886	if (monitor->vendor == NULL)
887	    result = False;
888    } else {
889	monitor->vendor = NULL;
890    }
891    if (result && rep.modelLength) {
892	monitor->model = Xcalloc(rep.modelLength + 1, 1);
893	if (monitor->model == NULL)
894	    result = False;
895    } else {
896	monitor->model = NULL;
897    }
898    if (result) {
899	monitor->hsync = Xcalloc(rep.nhsync, sizeof(XF86VidModeSyncRange));
900	monitor->vsync = Xcalloc(rep.nvsync, sizeof(XF86VidModeSyncRange));
901	if ((monitor->hsync == NULL) || (monitor->vsync == NULL))
902	    result = False;
903    } else {
904	monitor->hsync = monitor->vsync = NULL;
905    }
906    if (result == False) {
907	_XEatDataWords(dpy, rep.length);
908	Xfree(monitor->vendor);
909	monitor->vendor = NULL;
910	Xfree(monitor->model);
911	monitor->model = NULL;
912	Xfree(monitor->hsync);
913	monitor->hsync = NULL;
914	Xfree(monitor->vsync);
915	monitor->vsync = NULL;
916    }
917    else {
918	for (i = 0; i < rep.nhsync; i++) {
919	    _XRead(dpy, (char *)&syncrange, 4);
920	    monitor->hsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0;
921	    monitor->hsync[i].hi = (float)(syncrange >> 16) / 100.0;
922	}
923	for (i = 0; i < rep.nvsync; i++) {
924	    _XRead(dpy, (char *)&syncrange, 4);
925	    monitor->vsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0;
926	    monitor->vsync[i].hi = (float)(syncrange >> 16) / 100.0;
927	}
928	if (rep.vendorLength)
929	    _XReadPad(dpy, monitor->vendor, rep.vendorLength);
930	if (rep.modelLength)
931	    _XReadPad(dpy, monitor->model, rep.modelLength);
932    }
933    UnlockDisplay(dpy);
934    SyncHandle();
935    return result;
936}
937
938Bool
939XF86VidModeGetViewPort(Display* dpy, int screen, int *x, int *y)
940{
941    XExtDisplayInfo *info = find_display (dpy);
942    xXF86VidModeGetViewPortReply rep;
943    xXF86VidModeGetViewPortReq *req;
944    int majorVersion, minorVersion;
945    Bool protocolBug = False;
946
947    XF86VidModeCheckExtension (dpy, info, False);
948
949    /*
950     * Note: There was a bug in the protocol implementation in versions
951     * 0.x with x < 8 (no reply was sent, so the client would hang)
952     * Check the server's version, and don't wait for a reply with older
953     * versions.
954     */
955
956    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
957    if (majorVersion == 0 && minorVersion < 8) {
958	protocolBug = True;
959#ifdef DEBUG
960	fprintf(stderr, "XF86VidModeGetViewPort: Warning: Xserver is"
961		"running an old version (%d.%d)\n", majorVersion,
962		minorVersion);
963#endif
964    }
965    LockDisplay(dpy);
966    GetReq(XF86VidModeGetViewPort, req);
967    req->reqType = info->codes->major_opcode;
968    req->xf86vidmodeReqType = X_XF86VidModeGetViewPort;
969    req->screen = screen;
970    if (protocolBug) {
971	*x = 0;
972	*y = 0;
973    } else {
974	if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
975	    UnlockDisplay(dpy);
976	    SyncHandle();
977	    return False;
978	}
979	*x = rep.x;
980	*y = rep.y;
981    }
982
983    UnlockDisplay(dpy);
984    SyncHandle();
985    return True;
986}
987
988Bool
989XF86VidModeSetViewPort(Display* dpy, int screen, int x, int y)
990{
991    XExtDisplayInfo *info = find_display (dpy);
992    xXF86VidModeSetViewPortReq *req;
993
994    XF86VidModeCheckExtension (dpy, info, False);
995
996    LockDisplay(dpy);
997    GetReq(XF86VidModeSetViewPort, req);
998    req->reqType = info->codes->major_opcode;
999    req->xf86vidmodeReqType = X_XF86VidModeSetViewPort;
1000    req->screen = screen;
1001    req->x = x;
1002    req->y = y;
1003
1004    UnlockDisplay(dpy);
1005    SyncHandle();
1006    return True;
1007}
1008
1009Bool
1010XF86VidModeGetDotClocks(Display* dpy, int screen, int *flagsPtr,
1011			int *numclocksPtr, int *maxclocksPtr, int *clocksPtr[])
1012{
1013    XExtDisplayInfo *info = find_display (dpy);
1014    xXF86VidModeGetDotClocksReply rep;
1015    xXF86VidModeGetDotClocksReq *req;
1016    int *dotclocks;
1017    CARD32 dotclk;
1018    Bool result = True;
1019
1020    XF86VidModeCheckExtension (dpy, info, False);
1021
1022    LockDisplay(dpy);
1023    GetReq(XF86VidModeGetDotClocks, req);
1024    req->reqType = info->codes->major_opcode;
1025    req->xf86vidmodeReqType = X_XF86VidModeGetDotClocks;
1026    req->screen = screen;
1027    if (!_XReply(dpy, (xReply *)&rep,
1028        (SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2, xFalse))
1029    {
1030        UnlockDisplay(dpy);
1031        SyncHandle();
1032        return False;
1033    }
1034    *numclocksPtr = rep.clocks;
1035    *maxclocksPtr = rep.maxclocks;
1036    *flagsPtr     = rep.flags;
1037
1038    dotclocks = Xcalloc(rep.clocks, sizeof(int));
1039    if (dotclocks == NULL) {
1040        _XEatDataWords(dpy, rep.length -
1041	    ((SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2));
1042        result = False;
1043    }
1044    else {
1045	unsigned int i;
1046
1047	for (i = 0; i < rep.clocks; i++) {
1048	    _XRead(dpy, (char*)&dotclk, 4);
1049	    dotclocks[i] = dotclk;
1050	}
1051    }
1052    *clocksPtr = dotclocks;
1053    UnlockDisplay(dpy);
1054    SyncHandle();
1055    return result;
1056}
1057
1058Bool
1059XF86VidModeSetGammaRamp (
1060    Display *dpy,
1061    int screen,
1062    int size,
1063    unsigned short *red,
1064    unsigned short *green,
1065    unsigned short *blue
1066)
1067{
1068    int length = (size + 1) & ~1;
1069    XExtDisplayInfo *info = find_display (dpy);
1070    xXF86VidModeSetGammaRampReq *req;
1071
1072    XF86VidModeCheckExtension (dpy, info, False);
1073    LockDisplay(dpy);
1074    GetReq(XF86VidModeSetGammaRamp, req);
1075    req->reqType = info->codes->major_opcode;
1076    req->xf86vidmodeReqType = X_XF86VidModeSetGammaRamp;
1077    req->screen = screen;
1078    req->length += (length >> 1) * 3;
1079    req->size = size;
1080    _XSend(dpy, (char*)red, size * 2);
1081    _XSend(dpy, (char*)green, size * 2);
1082    _XSend(dpy, (char*)blue, size * 2);
1083    UnlockDisplay(dpy);
1084    SyncHandle();
1085    return True;
1086}
1087
1088
1089Bool
1090XF86VidModeGetGammaRamp (
1091    Display *dpy,
1092    int screen,
1093    int size,
1094    unsigned short *red,
1095    unsigned short *green,
1096    unsigned short *blue
1097)
1098{
1099    XExtDisplayInfo *info = find_display (dpy);
1100    xXF86VidModeGetGammaRampReq *req;
1101    xXF86VidModeGetGammaRampReply rep;
1102    Bool result = True;
1103
1104    XF86VidModeCheckExtension (dpy, info, False);
1105
1106    LockDisplay(dpy);
1107    GetReq(XF86VidModeGetGammaRamp, req);
1108    req->reqType = info->codes->major_opcode;
1109    req->xf86vidmodeReqType = X_XF86VidModeGetGammaRamp;
1110    req->screen = screen;
1111    req->size = size;
1112    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1113        result = False;
1114    }
1115    else if (rep.size) {
1116	if (rep.size <= size) {
1117	    _XRead(dpy, (char*)red, rep.size << 1);
1118	    _XRead(dpy, (char*)green, rep.size << 1);
1119	    _XRead(dpy, (char*)blue, rep.size << 1);
1120	}
1121	else {
1122	    _XEatDataWords(dpy, rep.length);
1123	    result = False;
1124	}
1125    }
1126
1127    UnlockDisplay(dpy);
1128    SyncHandle();
1129    return result;
1130}
1131
1132Bool XF86VidModeGetGammaRampSize(
1133    Display *dpy,
1134    int screen,
1135    int *size
1136)
1137{
1138    XExtDisplayInfo *info = find_display (dpy);
1139    xXF86VidModeGetGammaRampSizeReq *req;
1140    xXF86VidModeGetGammaRampSizeReply rep;
1141
1142    *size = 0;
1143
1144    XF86VidModeCheckExtension (dpy, info, False);
1145
1146    LockDisplay(dpy);
1147    GetReq(XF86VidModeGetGammaRampSize, req);
1148    req->reqType = info->codes->major_opcode;
1149    req->xf86vidmodeReqType = X_XF86VidModeGetGammaRampSize;
1150    req->screen = screen;
1151    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
1152        UnlockDisplay (dpy);
1153        SyncHandle ();
1154        return False;
1155    }
1156    *size = rep.size;
1157    UnlockDisplay(dpy);
1158    SyncHandle();
1159    return True;
1160}
1161
1162Bool XF86VidModeGetPermissions(
1163    Display *dpy,
1164    int screen,
1165    int *permissions
1166)
1167{
1168    XExtDisplayInfo *info = find_display (dpy);
1169    xXF86VidModeGetPermissionsReq *req;
1170    xXF86VidModeGetPermissionsReply rep;
1171
1172    *permissions = 0;
1173
1174    XF86VidModeCheckExtension (dpy, info, False);
1175
1176    LockDisplay(dpy);
1177    GetReq(XF86VidModeGetPermissions, req);
1178    req->reqType = info->codes->major_opcode;
1179    req->xf86vidmodeReqType = X_XF86VidModeGetPermissions;
1180    req->screen = screen;
1181    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
1182        UnlockDisplay (dpy);
1183        SyncHandle ();
1184        return False;
1185    }
1186    *permissions = rep.permissions;
1187    UnlockDisplay(dpy);
1188    SyncHandle();
1189    return True;
1190}
1191
1192