XF86VMode.c revision b290cf36
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#define NEED_EVENTS
34#define NEED_REPLIES
35#include <X11/Xlibint.h>
36#include <X11/extensions/xf86vmproto.h>
37#include <X11/extensions/xf86vmode.h>
38#include <X11/extensions/Xext.h>
39#include <X11/extensions/extutil.h>
40
41#ifdef DEBUG
42#include <stdio.h>
43#endif
44
45#ifndef MODE_BAD
46#define MODE_BAD 255
47#endif
48
49static XExtensionInfo _xf86vidmode_info_data;
50static XExtensionInfo *xf86vidmode_info = &_xf86vidmode_info_data;
51static char *xf86vidmode_extension_name = XF86VIDMODENAME;
52
53#define XF86VidModeCheckExtension(dpy,i,val) \
54  XextCheckExtension (dpy, i, xf86vidmode_extension_name, val)
55
56/*****************************************************************************
57 *                                                                           *
58 *			   private utility routines                          *
59 *                                                                           *
60 *****************************************************************************/
61
62static XEXT_CLOSE_DISPLAY_PROTO(close_display);
63static /* const */ XExtensionHooks xf86vidmode_extension_hooks = {
64    NULL,				/* create_gc */
65    NULL,				/* copy_gc */
66    NULL,				/* flush_gc */
67    NULL,				/* free_gc */
68    NULL,				/* create_font */
69    NULL,				/* free_font */
70    close_display,			/* close_display */
71    NULL,				/* wire_to_event */
72    NULL,				/* event_to_wire */
73    NULL,				/* error */
74    NULL,				/* error_string */
75};
76
77static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86vidmode_info,
78				   xf86vidmode_extension_name,
79				   &xf86vidmode_extension_hooks,
80				   0, NULL)
81
82static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86vidmode_info)
83
84
85/*****************************************************************************
86 *                                                                           *
87 *		    public XFree86-VidMode Extension routines                *
88 *                                                                           *
89 *****************************************************************************/
90
91Bool
92XF86VidModeQueryExtension(Display *dpy, int *event_basep, int *error_basep)
93{
94    XExtDisplayInfo *info = find_display (dpy);
95
96    if (XextHasExtension(info)) {
97	*event_basep = info->codes->first_event;
98	*error_basep = info->codes->first_error;
99	return True;
100    } else {
101	return False;
102    }
103}
104
105Bool
106XF86VidModeQueryVersion(Display* dpy, int* majorVersion, int* minorVersion)
107{
108    XExtDisplayInfo *info = find_display (dpy);
109    xXF86VidModeQueryVersionReply rep;
110    xXF86VidModeQueryVersionReq *req;
111
112    XF86VidModeCheckExtension (dpy, info, False);
113
114    LockDisplay(dpy);
115    GetReq(XF86VidModeQueryVersion, req);
116    req->reqType = info->codes->major_opcode;
117    req->xf86vidmodeReqType = X_XF86VidModeQueryVersion;
118    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
119	UnlockDisplay(dpy);
120	SyncHandle();
121	return False;
122    }
123    *majorVersion = rep.majorVersion;
124    *minorVersion = rep.minorVersion;
125    UnlockDisplay(dpy);
126    SyncHandle();
127    if (*majorVersion >= 2)
128	XF86VidModeSetClientVersion(dpy);
129    return True;
130}
131
132Bool
133XF86VidModeSetClientVersion(Display *dpy)
134{
135    XExtDisplayInfo *info = find_display(dpy);
136    xXF86VidModeSetClientVersionReq *req;
137
138    XF86VidModeCheckExtension(dpy, info, False);
139
140    LockDisplay(dpy);
141    GetReq(XF86VidModeSetClientVersion, req);
142    req->reqType = info->codes->major_opcode;
143    req->xf86vidmodeReqType = X_XF86VidModeSetClientVersion;
144    req->major = XF86VIDMODE_MAJOR_VERSION;
145    req->minor = XF86VIDMODE_MINOR_VERSION;
146    UnlockDisplay(dpy);
147    SyncHandle();
148    return True;
149}
150
151Bool
152XF86VidModeSetGamma(Display *dpy, int screen, XF86VidModeGamma *Gamma)
153{
154    XExtDisplayInfo *info = find_display(dpy);
155    xXF86VidModeSetGammaReq *req;
156
157    XF86VidModeCheckExtension(dpy, info, False);
158
159    LockDisplay(dpy);
160    GetReq(XF86VidModeSetGamma, req);
161    req->reqType = info->codes->major_opcode;
162    req->xf86vidmodeReqType = X_XF86VidModeSetGamma;
163    req->screen = screen;
164    req->red = (CARD32)(Gamma->red * 10000.);
165    req->green = (CARD32)(Gamma->green * 10000.);
166    req->blue = (CARD32)(Gamma->blue * 10000.);
167    UnlockDisplay(dpy);
168    SyncHandle();
169    return True;
170}
171
172Bool
173XF86VidModeGetGamma(Display *dpy, int screen, XF86VidModeGamma *Gamma)
174{
175    XExtDisplayInfo *info = find_display (dpy);
176    xXF86VidModeGetGammaReply rep;
177    xXF86VidModeGetGammaReq *req;
178
179    XF86VidModeCheckExtension (dpy, info, False);
180
181    LockDisplay(dpy);
182    GetReq(XF86VidModeGetGamma, req);
183    req->reqType = info->codes->major_opcode;
184    req->xf86vidmodeReqType = X_XF86VidModeGetGamma;
185    req->screen = screen;
186    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
187	UnlockDisplay(dpy);
188	SyncHandle();
189	return False;
190    }
191    Gamma->red = ((float)rep.red) / 10000.;
192    Gamma->green = ((float)rep.green) / 10000.;
193    Gamma->blue = ((float)rep.blue) / 10000.;
194    UnlockDisplay(dpy);
195    SyncHandle();
196    return True;
197}
198
199Bool
200XF86VidModeGetModeLine(Display* dpy, int screen, int* dotclock,
201		       XF86VidModeModeLine* modeline)
202{
203    XExtDisplayInfo *info = find_display (dpy);
204    xXF86VidModeGetModeLineReply rep;
205    xXF86OldVidModeGetModeLineReply oldrep;
206    xXF86VidModeGetModeLineReq *req;
207    int majorVersion, minorVersion;
208
209    XF86VidModeCheckExtension (dpy, info, False);
210    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
211
212    LockDisplay(dpy);
213    GetReq(XF86VidModeGetModeLine, req);
214    req->reqType = info->codes->major_opcode;
215    req->xf86vidmodeReqType = X_XF86VidModeGetModeLine;
216    req->screen = screen;
217
218    if (majorVersion < 2) {
219	if (!_XReply(dpy, (xReply *)&oldrep,
220            (SIZEOF(xXF86OldVidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) {
221	    UnlockDisplay(dpy);
222	    SyncHandle();
223	    return False;
224	}
225	*dotclock = oldrep.dotclock;
226	modeline->hdisplay   = oldrep.hdisplay;
227	modeline->hsyncstart = oldrep.hsyncstart;
228	modeline->hsyncend   = oldrep.hsyncend;
229	modeline->htotal     = oldrep.htotal;
230	modeline->hskew      = 0;
231	modeline->vdisplay   = oldrep.vdisplay;
232	modeline->vsyncstart = oldrep.vsyncstart;
233	modeline->vsyncend   = oldrep.vsyncend;
234	modeline->vtotal     = oldrep.vtotal;
235	modeline->flags      = oldrep.flags;
236	modeline->privsize   = oldrep.privsize;
237    } else {
238	if (!_XReply(dpy, (xReply *)&rep,
239            (SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) {
240	    UnlockDisplay(dpy);
241	    SyncHandle();
242	    return False;
243	}
244	*dotclock = rep.dotclock;
245	modeline->hdisplay   = rep.hdisplay;
246	modeline->hsyncstart = rep.hsyncstart;
247	modeline->hsyncend   = rep.hsyncend;
248	modeline->htotal     = rep.htotal;
249	modeline->hskew      = rep.hskew;
250	modeline->vdisplay   = rep.vdisplay;
251	modeline->vsyncstart = rep.vsyncstart;
252	modeline->vsyncend   = rep.vsyncend;
253	modeline->vtotal     = rep.vtotal;
254	modeline->flags      = rep.flags;
255	modeline->privsize   = rep.privsize;
256    }
257
258    if (modeline->privsize > 0) {
259	if (!(modeline->private = Xcalloc(modeline->privsize, sizeof(INT32)))) {
260	    _XEatData(dpy, (modeline->privsize) * sizeof(INT32));
261	    Xfree(modeline->private);
262	    return False;
263	}
264	_XRead(dpy, (char*)modeline->private, modeline->privsize * sizeof(INT32));
265    } else {
266	modeline->private = NULL;
267    }
268    UnlockDisplay(dpy);
269    SyncHandle();
270    return True;
271}
272
273Bool
274XF86VidModeGetAllModeLines(Display* dpy, int screen, int* modecount,
275			   XF86VidModeModeInfo ***modelinesPtr)
276{
277    XExtDisplayInfo *info = find_display (dpy);
278    xXF86VidModeGetAllModeLinesReply rep;
279    xXF86VidModeGetAllModeLinesReq *req;
280    XF86VidModeModeInfo *mdinfptr, **modelines;
281    xXF86VidModeModeInfo xmdline;
282    xXF86OldVidModeModeInfo oldxmdline;
283    int i;
284    int majorVersion, minorVersion;
285    Bool protocolBug = False;
286
287    XF86VidModeCheckExtension (dpy, info, False);
288
289    /*
290     * Note: There was a bug in the protocol implementation in versions
291     * 0.x with x < 8 (the .private field wasn't being passed over the wire).
292     * Check the server's version, and accept the old format if appropriate.
293     */
294
295    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
296    if (majorVersion == 0 && minorVersion < 8) {
297	protocolBug = True;
298#ifdef DEBUG
299	fprintf(stderr, "XF86VidModeGetAllModeLines: Warning: Xserver is"
300		"running an old version (%d.%d)\n", majorVersion,
301		minorVersion);
302#endif
303    }
304
305    LockDisplay(dpy);
306    GetReq(XF86VidModeGetAllModeLines, req);
307    req->reqType = info->codes->major_opcode;
308    req->xf86vidmodeReqType = X_XF86VidModeGetAllModeLines;
309    req->screen = screen;
310    if (!_XReply(dpy, (xReply *)&rep,
311        (SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2, xFalse)) {
312        UnlockDisplay(dpy);
313	SyncHandle();
314	return False;
315    }
316
317    *modecount = rep.modecount;
318
319    if (!(modelines = (XF86VidModeModeInfo **) Xcalloc(rep.modecount,
320                                          sizeof(XF86VidModeModeInfo *)
321                                          +sizeof(XF86VidModeModeInfo)))) {
322	if (majorVersion < 2)
323            _XEatData(dpy, (rep.modecount) * sizeof(xXF86OldVidModeModeInfo));
324	else
325            _XEatData(dpy, (rep.modecount) * sizeof(xXF86VidModeModeInfo));
326        Xfree(modelines);
327        return False;
328    }
329    mdinfptr = (XF86VidModeModeInfo *) (
330			    (char *) modelines
331			    + rep.modecount*sizeof(XF86VidModeModeInfo *)
332		    );
333
334    for (i = 0; i < rep.modecount; i++) {
335        modelines[i] = mdinfptr++;
336	if (majorVersion < 2) {
337            _XRead(dpy, (char*)&oldxmdline, sizeof(xXF86OldVidModeModeInfo));
338	    modelines[i]->dotclock   = oldxmdline.dotclock;
339	    modelines[i]->hdisplay   = oldxmdline.hdisplay;
340	    modelines[i]->hsyncstart = oldxmdline.hsyncstart;
341	    modelines[i]->hsyncend   = oldxmdline.hsyncend;
342	    modelines[i]->htotal     = oldxmdline.htotal;
343	    modelines[i]->hskew      = 0;
344	    modelines[i]->vdisplay   = oldxmdline.vdisplay;
345	    modelines[i]->vsyncstart = oldxmdline.vsyncstart;
346	    modelines[i]->vsyncend   = oldxmdline.vsyncend;
347	    modelines[i]->vtotal     = oldxmdline.vtotal;
348	    modelines[i]->flags      = oldxmdline.flags;
349	    if (protocolBug) {
350		modelines[i]->privsize = 0;
351		modelines[i]->private = NULL;
352	    } else {
353		modelines[i]->privsize   = oldxmdline.privsize;
354		if (oldxmdline.privsize > 0) {
355	            if (!(modelines[i]->private =
356			    Xcalloc(oldxmdline.privsize, sizeof(INT32)))) {
357			_XEatData(dpy, (oldxmdline.privsize) * sizeof(INT32));
358			Xfree(modelines[i]->private);
359		    } else {
360			_XRead(dpy, (char*)modelines[i]->private,
361			     oldxmdline.privsize * sizeof(INT32));
362		    }
363		} else {
364		  modelines[i]->private = NULL;
365		}
366	    }
367	} else {
368            _XRead(dpy, (char*)&xmdline, sizeof(xXF86VidModeModeInfo));
369	    modelines[i]->dotclock   = xmdline.dotclock;
370	    modelines[i]->hdisplay   = xmdline.hdisplay;
371	    modelines[i]->hsyncstart = xmdline.hsyncstart;
372	    modelines[i]->hsyncend   = xmdline.hsyncend;
373	    modelines[i]->htotal     = xmdline.htotal;
374	    modelines[i]->hskew      = xmdline.hskew;
375	    modelines[i]->vdisplay   = xmdline.vdisplay;
376	    modelines[i]->vsyncstart = xmdline.vsyncstart;
377	    modelines[i]->vsyncend   = xmdline.vsyncend;
378	    modelines[i]->vtotal     = xmdline.vtotal;
379	    modelines[i]->flags      = xmdline.flags;
380	    if (protocolBug) {
381		modelines[i]->privsize = 0;
382		modelines[i]->private = NULL;
383	    } else {
384		modelines[i]->privsize   = xmdline.privsize;
385		if (xmdline.privsize > 0) {
386		    if (!(modelines[i]->private =
387			    Xcalloc(xmdline.privsize, sizeof(INT32)))) {
388			_XEatData(dpy, (xmdline.privsize) * sizeof(INT32));
389			Xfree(modelines[i]->private);
390		    } else {
391			_XRead(dpy, (char*)modelines[i]->private,
392			     xmdline.privsize * sizeof(INT32));
393		    }
394		} else {
395		    modelines[i]->private = NULL;
396		}
397	    }
398	}
399    }
400    *modelinesPtr = modelines;
401    UnlockDisplay(dpy);
402    SyncHandle();
403    return True;
404}
405
406/*
407 * GetReq replacement for use with VidMode protocols earlier than 2.0
408 */
409#if !defined(UNIXCPP) || defined(ANSICPP)
410#define GetOldReq(name, oldname, req) \
411        WORD64ALIGN\
412	if ((dpy->bufptr + SIZEOF(x##oldname##Req)) > dpy->bufmax)\
413		_XFlush(dpy);\
414	req = (x##oldname##Req *)(dpy->last_req = dpy->bufptr);\
415	req->reqType = X_##name;\
416	req->length = (SIZEOF(x##oldname##Req))>>2;\
417	dpy->bufptr += SIZEOF(x##oldname##Req);\
418	dpy->request++
419
420#else  /* non-ANSI C uses empty comment instead of "##" for token concatenation */
421#define GetOldReq(name, oldname, req) \
422        WORD64ALIGN\
423	if ((dpy->bufptr + SIZEOF(x/**/oldname/**/Req)) > dpy->bufmax)\
424		_XFlush(dpy);\
425	req = (x/**/oldname/**/Req *)(dpy->last_req = dpy->bufptr);\
426	req->reqType = X_/**/name;\
427	req->length = (SIZEOF(x/**/oldname/**/Req))>>2;\
428	dpy->bufptr += SIZEOF(x/**/oldname/**/Req);\
429	dpy->request++
430#endif
431
432Bool
433XF86VidModeAddModeLine(Display *dpy, int screen,
434		       XF86VidModeModeInfo* newmodeline,
435		       XF86VidModeModeInfo* aftermodeline)
436{
437    XExtDisplayInfo *info = find_display (dpy);
438    xXF86VidModeAddModeLineReq *req;
439    xXF86OldVidModeAddModeLineReq *oldreq;
440    int majorVersion, minorVersion;
441
442    XF86VidModeCheckExtension (dpy, info, False);
443    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
444
445    LockDisplay(dpy);
446    if (majorVersion < 2) {
447	GetOldReq(XF86VidModeAddModeLine, XF86OldVidModeAddModeLine, oldreq);
448	oldreq->reqType = info->codes->major_opcode;
449	oldreq->xf86vidmodeReqType = X_XF86VidModeAddModeLine;
450	oldreq->screen = screen;
451	oldreq->dotclock =	newmodeline->dotclock;
452	oldreq->hdisplay =	newmodeline->hdisplay;
453	oldreq->hsyncstart =	newmodeline->hsyncstart;
454	oldreq->hsyncend =	newmodeline->hsyncend;
455	oldreq->htotal =	newmodeline->htotal;
456	oldreq->vdisplay =	newmodeline->vdisplay;
457	oldreq->vsyncstart =	newmodeline->vsyncstart;
458	oldreq->vsyncend =	newmodeline->vsyncend;
459	oldreq->vtotal =	newmodeline->vtotal;
460	oldreq->flags =		newmodeline->flags;
461	oldreq->privsize =	newmodeline->privsize;
462	if (aftermodeline != NULL) {
463	    oldreq->after_dotclock =	aftermodeline->dotclock;
464	    oldreq->after_hdisplay =	aftermodeline->hdisplay;
465	    oldreq->after_hsyncstart =	aftermodeline->hsyncstart;
466	    oldreq->after_hsyncend =	aftermodeline->hsyncend;
467	    oldreq->after_htotal =	aftermodeline->htotal;
468	    oldreq->after_vdisplay =	aftermodeline->vdisplay;
469	    oldreq->after_vsyncstart =	aftermodeline->vsyncstart;
470	    oldreq->after_vsyncend =	aftermodeline->vsyncend;
471	    oldreq->after_vtotal =	aftermodeline->vtotal;
472	    oldreq->after_flags =	aftermodeline->flags;
473	} else {
474	    oldreq->after_dotclock =	0;
475	    oldreq->after_hdisplay =	0;
476	    oldreq->after_hsyncstart =	0;
477	    oldreq->after_hsyncend =	0;
478	    oldreq->after_htotal =	0;
479	    oldreq->after_vdisplay =	0;
480	    oldreq->after_vsyncstart =	0;
481	    oldreq->after_vsyncend =	0;
482	    oldreq->after_vtotal =	0;
483	    oldreq->after_flags =	0;
484	}
485	if (newmodeline->privsize) {
486	    oldreq->length += newmodeline->privsize;
487	    Data32(dpy, (long *) newmodeline->private,
488	       newmodeline->privsize * sizeof(INT32));
489	}
490    } else {
491	GetReq(XF86VidModeAddModeLine, req);
492	req->reqType = info->codes->major_opcode;
493	req->xf86vidmodeReqType = X_XF86VidModeAddModeLine;
494	req->screen = screen;
495	req->dotclock =		newmodeline->dotclock;
496	req->hdisplay =		newmodeline->hdisplay;
497	req->hsyncstart =	newmodeline->hsyncstart;
498	req->hsyncend =		newmodeline->hsyncend;
499	req->htotal =		newmodeline->htotal;
500	req->hskew =		newmodeline->hskew;
501	req->vdisplay =		newmodeline->vdisplay;
502	req->vsyncstart =	newmodeline->vsyncstart;
503	req->vsyncend =		newmodeline->vsyncend;
504	req->vtotal =		newmodeline->vtotal;
505	req->flags =		newmodeline->flags;
506	req->privsize =		newmodeline->privsize;
507	if (aftermodeline != NULL) {
508	    req->after_dotclock =	aftermodeline->dotclock;
509	    req->after_hdisplay =	aftermodeline->hdisplay;
510	    req->after_hsyncstart =	aftermodeline->hsyncstart;
511	    req->after_hsyncend =	aftermodeline->hsyncend;
512	    req->after_htotal =		aftermodeline->htotal;
513	    req->after_hskew =		aftermodeline->hskew;
514	    req->after_vdisplay =	aftermodeline->vdisplay;
515	    req->after_vsyncstart =	aftermodeline->vsyncstart;
516	    req->after_vsyncend =	aftermodeline->vsyncend;
517	    req->after_vtotal =		aftermodeline->vtotal;
518	    req->after_flags =		aftermodeline->flags;
519	} else {
520	    req->after_dotclock =	0;
521	    req->after_hdisplay =	0;
522	    req->after_hsyncstart =	0;
523	    req->after_hsyncend =	0;
524	    req->after_htotal =		0;
525	    req->after_hskew =		0;
526	    req->after_vdisplay =	0;
527	    req->after_vsyncstart =	0;
528	    req->after_vsyncend =	0;
529	    req->after_vtotal =		0;
530	    req->after_flags =		0;
531	}
532	if (newmodeline->privsize) {
533	    req->length += newmodeline->privsize;
534	    Data32(dpy, (long *) newmodeline->private,
535	       newmodeline->privsize * sizeof(INT32));
536	}
537    }
538    UnlockDisplay(dpy);
539    SyncHandle();
540    return True;
541}
542
543Bool
544XF86VidModeDeleteModeLine(Display *dpy, int screen,
545			  XF86VidModeModeInfo* modeline)
546{
547    XExtDisplayInfo *info = find_display (dpy);
548    xXF86VidModeDeleteModeLineReq *req;
549    xXF86OldVidModeDeleteModeLineReq *oldreq;
550    int majorVersion, minorVersion;
551
552    XF86VidModeCheckExtension (dpy, info, 0);
553    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
554
555    LockDisplay(dpy);
556    if (majorVersion < 2) {
557	GetOldReq(XF86VidModeDeleteModeLine, XF86OldVidModeDeleteModeLine, oldreq);
558	oldreq->reqType = info->codes->major_opcode;
559	oldreq->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine;
560	oldreq->screen = screen;
561	oldreq->dotclock =	modeline->dotclock;
562	oldreq->hdisplay =	modeline->hdisplay;
563	oldreq->hsyncstart =	modeline->hsyncstart;
564	oldreq->hsyncend =	modeline->hsyncend;
565	oldreq->htotal =	modeline->htotal;
566	oldreq->vdisplay =	modeline->vdisplay;
567	oldreq->vsyncstart =	modeline->vsyncstart;
568	oldreq->vsyncend =	modeline->vsyncend;
569	oldreq->vtotal =	modeline->vtotal;
570	oldreq->flags =		modeline->flags;
571	oldreq->privsize =	modeline->privsize;
572	if (modeline->privsize) {
573	    oldreq->length += modeline->privsize;
574	    Data32(dpy, (long *) modeline->private,
575	       modeline->privsize * sizeof(INT32));
576	}
577    } else {
578	GetReq(XF86VidModeDeleteModeLine, req);
579	req->reqType = info->codes->major_opcode;
580	req->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine;
581	req->screen = screen;
582	req->dotclock =		modeline->dotclock;
583	req->hdisplay =		modeline->hdisplay;
584	req->hsyncstart =	modeline->hsyncstart;
585	req->hsyncend =		modeline->hsyncend;
586	req->htotal =		modeline->htotal;
587	req->hskew =		modeline->hskew;
588	req->vdisplay =		modeline->vdisplay;
589	req->vsyncstart =	modeline->vsyncstart;
590	req->vsyncend =		modeline->vsyncend;
591	req->vtotal =		modeline->vtotal;
592	req->flags =		modeline->flags;
593	req->privsize =		modeline->privsize;
594	if (modeline->privsize) {
595	    req->length += modeline->privsize;
596	    Data32(dpy, (long *) modeline->private,
597	       modeline->privsize * sizeof(INT32));
598	}
599    }
600    UnlockDisplay(dpy);
601    SyncHandle();
602    return True;
603}
604
605Bool
606XF86VidModeModModeLine(Display *dpy, int screen, XF86VidModeModeLine* modeline)
607{
608    XExtDisplayInfo *info = find_display (dpy);
609    xXF86VidModeModModeLineReq *req;
610    xXF86OldVidModeModModeLineReq *oldreq;
611    int majorVersion, minorVersion;
612
613    XF86VidModeCheckExtension (dpy, info, 0);
614    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
615
616    LockDisplay(dpy);
617    if (majorVersion < 2) {
618	GetOldReq(XF86VidModeModModeLine, XF86OldVidModeModModeLine, oldreq);
619	oldreq->reqType = info->codes->major_opcode;
620	oldreq->xf86vidmodeReqType = X_XF86VidModeModModeLine;
621	oldreq->screen = screen;
622	oldreq->hdisplay =	modeline->hdisplay;
623	oldreq->hsyncstart =	modeline->hsyncstart;
624	oldreq->hsyncend =	modeline->hsyncend;
625	oldreq->htotal =	modeline->htotal;
626	oldreq->vdisplay =	modeline->vdisplay;
627	oldreq->vsyncstart =	modeline->vsyncstart;
628	oldreq->vsyncend =	modeline->vsyncend;
629	oldreq->vtotal =	modeline->vtotal;
630	oldreq->flags =		modeline->flags;
631	oldreq->privsize =	modeline->privsize;
632	if (modeline->privsize) {
633	    oldreq->length += modeline->privsize;
634	    Data32(dpy, (long *) modeline->private,
635	       modeline->privsize * sizeof(INT32));
636	}
637    } else {
638	GetReq(XF86VidModeModModeLine, req);
639	req->reqType = info->codes->major_opcode;
640	req->xf86vidmodeReqType = X_XF86VidModeModModeLine;
641	req->screen = screen;
642	req->hdisplay =		modeline->hdisplay;
643	req->hsyncstart =	modeline->hsyncstart;
644	req->hsyncend =		modeline->hsyncend;
645	req->htotal =		modeline->htotal;
646	req->hskew =		modeline->hskew;
647	req->vdisplay =		modeline->vdisplay;
648	req->vsyncstart =	modeline->vsyncstart;
649	req->vsyncend =		modeline->vsyncend;
650	req->vtotal =		modeline->vtotal;
651	req->flags =		modeline->flags;
652	req->privsize =		modeline->privsize;
653	if (modeline->privsize) {
654	    req->length += modeline->privsize;
655	    Data32(dpy, (long *) modeline->private,
656	       modeline->privsize * sizeof(INT32));
657	}
658    }
659    UnlockDisplay(dpy);
660    SyncHandle();
661    return True;
662}
663
664Status
665XF86VidModeValidateModeLine(Display *dpy, int screen,
666			    XF86VidModeModeInfo* modeline)
667{
668    XExtDisplayInfo *info = find_display (dpy);
669    xXF86VidModeValidateModeLineReq *req;
670    xXF86OldVidModeValidateModeLineReq *oldreq;
671    xXF86VidModeValidateModeLineReply rep;
672    int majorVersion, minorVersion;
673
674    XF86VidModeCheckExtension (dpy, info, 0);
675    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
676
677    LockDisplay(dpy);
678
679    if (majorVersion < 2) {
680	GetOldReq(XF86VidModeValidateModeLine, XF86OldVidModeValidateModeLine, oldreq);
681	oldreq->reqType = info->codes->major_opcode;
682	oldreq->xf86vidmodeReqType = X_XF86VidModeValidateModeLine;
683	oldreq->screen = screen;
684	oldreq->dotclock =	modeline->dotclock;
685	oldreq->hdisplay =	modeline->hdisplay;
686	oldreq->hsyncstart =	modeline->hsyncstart;
687	oldreq->hsyncend =	modeline->hsyncend;
688	oldreq->htotal =	modeline->htotal;
689	oldreq->vdisplay =	modeline->vdisplay;
690	oldreq->vsyncstart =	modeline->vsyncstart;
691	oldreq->vsyncend =	modeline->vsyncend;
692	oldreq->vtotal =	modeline->vtotal;
693	oldreq->flags =		modeline->flags;
694	oldreq->privsize =	modeline->privsize;
695	if (modeline->privsize) {
696	    oldreq->length += modeline->privsize;
697	    Data32(dpy, (long *) modeline->private,
698	       modeline->privsize * sizeof(INT32));
699	}
700    } else {
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 (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 (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
866    XF86VidModeCheckExtension (dpy, info, False);
867
868    LockDisplay(dpy);
869    GetReq(XF86VidModeGetMonitor, req);
870    req->reqType = info->codes->major_opcode;
871    req->xf86vidmodeReqType = X_XF86VidModeGetMonitor;
872    req->screen = screen;
873    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
874	UnlockDisplay(dpy);
875	SyncHandle();
876	return False;
877    }
878    monitor->nhsync = rep.nhsync;
879    monitor->nvsync = rep.nvsync;
880#if 0
881    monitor->bandwidth = (float)rep.bandwidth / 1e6;
882#endif
883    if (rep.vendorLength) {
884	if (!(monitor->vendor = (char *)Xcalloc(rep.vendorLength + 1, 1))) {
885	    _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 +
886		      ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3));
887	    return False;
888	}
889    } else {
890	monitor->vendor = NULL;
891    }
892    if (rep.modelLength) {
893	if (!(monitor->model = Xcalloc(rep.modelLength + 1, 1))) {
894	    _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 +
895		      ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3));
896	    if (monitor->vendor)
897		Xfree(monitor->vendor);
898	    return False;
899	}
900    } else {
901	monitor->model = NULL;
902    }
903    if (!(monitor->hsync = Xcalloc(rep.nhsync, sizeof(XF86VidModeSyncRange)))) {
904	_XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 +
905		  ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3));
906
907	if (monitor->vendor)
908	    Xfree(monitor->vendor);
909	if (monitor->model)
910	    Xfree(monitor->model);
911	return False;
912    }
913    if (!(monitor->vsync = Xcalloc(rep.nvsync, sizeof(XF86VidModeSyncRange)))) {
914	_XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 +
915		  ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3));
916	if (monitor->vendor)
917	    Xfree(monitor->vendor);
918	if (monitor->model)
919	    Xfree(monitor->model);
920	Xfree(monitor->hsync);
921	return False;
922    }
923    for (i = 0; i < rep.nhsync; i++) {
924	_XRead(dpy, (char *)&syncrange, 4);
925	monitor->hsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0;
926	monitor->hsync[i].hi = (float)(syncrange >> 16) / 100.0;
927    }
928    for (i = 0; i < rep.nvsync; i++) {
929	_XRead(dpy, (char *)&syncrange, 4);
930	monitor->vsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0;
931	monitor->vsync[i].hi = (float)(syncrange >> 16) / 100.0;
932    }
933    if (rep.vendorLength)
934	_XReadPad(dpy, monitor->vendor, rep.vendorLength);
935    if (rep.modelLength)
936	_XReadPad(dpy, monitor->model, rep.modelLength);
937
938    UnlockDisplay(dpy);
939    SyncHandle();
940    return True;
941}
942
943Bool
944XF86VidModeGetViewPort(Display* dpy, int screen, int *x, int *y)
945{
946    XExtDisplayInfo *info = find_display (dpy);
947    xXF86VidModeGetViewPortReply rep;
948    xXF86VidModeGetViewPortReq *req;
949    int majorVersion, minorVersion;
950    Bool protocolBug = False;
951
952    XF86VidModeCheckExtension (dpy, info, False);
953
954    /*
955     * Note: There was a bug in the protocol implementation in versions
956     * 0.x with x < 8 (no reply was sent, so the client would hang)
957     * Check the server's version, and don't wait for a reply with older
958     * versions.
959     */
960
961    XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion);
962    if (majorVersion == 0 && minorVersion < 8) {
963	protocolBug = True;
964#ifdef DEBUG
965	fprintf(stderr, "XF86VidModeGetViewPort: Warning: Xserver is"
966		"running an old version (%d.%d)\n", majorVersion,
967		minorVersion);
968#endif
969    }
970    LockDisplay(dpy);
971    GetReq(XF86VidModeGetViewPort, req);
972    req->reqType = info->codes->major_opcode;
973    req->xf86vidmodeReqType = X_XF86VidModeGetViewPort;
974    req->screen = screen;
975    if (protocolBug) {
976	*x = 0;
977	*y = 0;
978    } else {
979	if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
980	    UnlockDisplay(dpy);
981	    SyncHandle();
982	    return False;
983	}
984	*x = rep.x;
985	*y = rep.y;
986    }
987
988    UnlockDisplay(dpy);
989    SyncHandle();
990    return True;
991}
992
993Bool
994XF86VidModeSetViewPort(Display* dpy, int screen, int x, int y)
995{
996    XExtDisplayInfo *info = find_display (dpy);
997    xXF86VidModeSetViewPortReq *req;
998
999    XF86VidModeCheckExtension (dpy, info, False);
1000
1001    LockDisplay(dpy);
1002    GetReq(XF86VidModeSetViewPort, req);
1003    req->reqType = info->codes->major_opcode;
1004    req->xf86vidmodeReqType = X_XF86VidModeSetViewPort;
1005    req->screen = screen;
1006    req->x = x;
1007    req->y = y;
1008
1009    UnlockDisplay(dpy);
1010    SyncHandle();
1011    return True;
1012}
1013
1014Bool
1015XF86VidModeGetDotClocks(Display* dpy, int screen, int *flagsPtr,
1016			int *numclocksPtr, int *maxclocksPtr, int *clocksPtr[])
1017{
1018    XExtDisplayInfo *info = find_display (dpy);
1019    xXF86VidModeGetDotClocksReply rep;
1020    xXF86VidModeGetDotClocksReq *req;
1021    int i, *dotclocks;
1022    CARD32 dotclk;
1023
1024    XF86VidModeCheckExtension (dpy, info, False);
1025
1026    LockDisplay(dpy);
1027    GetReq(XF86VidModeGetDotClocks, req);
1028    req->reqType = info->codes->major_opcode;
1029    req->xf86vidmodeReqType = X_XF86VidModeGetDotClocks;
1030    req->screen = screen;
1031    if (!_XReply(dpy, (xReply *)&rep,
1032        (SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2, xFalse))
1033    {
1034        UnlockDisplay(dpy);
1035        SyncHandle();
1036        return False;
1037    }
1038    *numclocksPtr = rep.clocks;
1039    *maxclocksPtr = rep.maxclocks;
1040    *flagsPtr     = rep.flags;
1041
1042    if (!(dotclocks = (int*) Xcalloc(rep.clocks, sizeof(int)))) {
1043        _XEatData(dpy, (rep.clocks) * 4);
1044        Xfree(dotclocks);
1045        return False;
1046    }
1047
1048    for (i = 0; i < rep.clocks; i++) {
1049        _XRead(dpy, (char*)&dotclk, 4);
1050	dotclocks[i] = dotclk;
1051    }
1052    *clocksPtr = dotclocks;
1053    UnlockDisplay(dpy);
1054    SyncHandle();
1055    return True;
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
1103    XF86VidModeCheckExtension (dpy, info, False);
1104
1105    LockDisplay(dpy);
1106    GetReq(XF86VidModeGetGammaRamp, req);
1107    req->reqType = info->codes->major_opcode;
1108    req->xf86vidmodeReqType = X_XF86VidModeGetGammaRamp;
1109    req->screen = screen;
1110    req->size = size;
1111    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1112        UnlockDisplay (dpy);
1113        SyncHandle ();
1114        return False;
1115    }
1116    if(rep.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
1122    UnlockDisplay(dpy);
1123    SyncHandle();
1124    return True;
1125}
1126
1127Bool XF86VidModeGetGammaRampSize(
1128    Display *dpy,
1129    int screen,
1130    int *size
1131)
1132{
1133    XExtDisplayInfo *info = find_display (dpy);
1134    xXF86VidModeGetGammaRampSizeReq *req;
1135    xXF86VidModeGetGammaRampSizeReply rep;
1136
1137    *size = 0;
1138
1139    XF86VidModeCheckExtension (dpy, info, False);
1140
1141    LockDisplay(dpy);
1142    GetReq(XF86VidModeGetGammaRampSize, req);
1143    req->reqType = info->codes->major_opcode;
1144    req->xf86vidmodeReqType = X_XF86VidModeGetGammaRampSize;
1145    req->screen = screen;
1146    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
1147        UnlockDisplay (dpy);
1148        SyncHandle ();
1149        return False;
1150    }
1151    *size = rep.size;
1152    UnlockDisplay(dpy);
1153    SyncHandle();
1154    return True;
1155}
1156
1157Bool XF86VidModeGetPermissions(
1158    Display *dpy,
1159    int screen,
1160    int *permissions
1161)
1162{
1163    XExtDisplayInfo *info = find_display (dpy);
1164    xXF86VidModeGetPermissionsReq *req;
1165    xXF86VidModeGetPermissionsReply rep;
1166
1167    *permissions = 0;
1168
1169    XF86VidModeCheckExtension (dpy, info, False);
1170
1171    LockDisplay(dpy);
1172    GetReq(XF86VidModeGetPermissions, req);
1173    req->reqType = info->codes->major_opcode;
1174    req->xf86vidmodeReqType = X_XF86VidModeGetPermissions;
1175    req->screen = screen;
1176    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
1177        UnlockDisplay (dpy);
1178        SyncHandle ();
1179        return False;
1180    }
1181    *permissions = rep.permissions;
1182    UnlockDisplay(dpy);
1183    SyncHandle();
1184    return True;
1185}
1186
1187