1 /******************************************************************************
2  *
3  * Copyright (c) 1994, 1995  Hewlett-Packard Company
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM,
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Except as contained in this notice, the name of the Hewlett-Packard
25  * Company shall not be used in advertising or otherwise to promote the
26  * sale, use or other dealings in this Software without prior written
27  * authorization from the Hewlett-Packard Company.
28  *
29  *     Xlib DBE code
30  *
31  *****************************************************************************/
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 #include <stdio.h>
37 #include <X11/Xlibint.h>
38 #include <X11/extensions/Xext.h>
39 #include <X11/extensions/extutil.h>
40 #include <X11/extensions/Xdbe.h>
41 #include <X11/extensions/dbeproto.h>
42 #include <limits.h>
43 
44 static XExtensionInfo _dbe_info_data;
45 static XExtensionInfo *dbe_info = &_dbe_info_data;
46 static const char *dbe_extension_name = DBE_PROTOCOL_NAME;
47 
48 #define DbeCheckExtension(dpy,i,val) \
49   XextCheckExtension (dpy, i, dbe_extension_name, val)
50 #define DbeSimpleCheckExtension(dpy,i) \
51   XextSimpleCheckExtension (dpy, i, dbe_extension_name)
52 
53 #define DbeGetReq(name,req,info) GetReq (name, req); \
54         req->reqType = info->codes->major_opcode; \
55         req->dbeReqType = X_##name;
56 
57 
58 /*****************************************************************************
59  *                                                                           *
60  *			   private utility routines                          *
61  *                                                                           *
62  *****************************************************************************/
63 
64 /*
65  * find_display - locate the display info block
66  */
67 static int close_display(Display *dpy, XExtCodes *codes);
68 static char *error_string(Display *dpy, int code, XExtCodes *codes,
69 			  char *buf, int n);
70 static XExtensionHooks dbe_extension_hooks = {
71     NULL,                               /* create_gc */
72     NULL,                               /* copy_gc */
73     NULL,                               /* flush_gc */
74     NULL,                               /* free_gc */
75     NULL,                               /* create_font */
76     NULL,                               /* free_font */
77     close_display,                      /* close_display */
78     NULL,                               /* wire_to_event */
79     NULL,                               /* event_to_wire */
80     NULL,                               /* error */
81     error_string,                       /* error_string */
82 };
83 
84 static const char *dbe_error_list[] = {
85     "BadBuffer",			/* DbeBadBuffer */
86 };
87 
88 static XEXT_GENERATE_FIND_DISPLAY (find_display, dbe_info,
89 				   dbe_extension_name,
90 				   &dbe_extension_hooks,
91 				   DbeNumberEvents, NULL)
92 
XEXT_GENERATE_CLOSE_DISPLAY(close_display,dbe_info)93 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, dbe_info)
94 
95 static XEXT_GENERATE_ERROR_STRING (error_string, dbe_extension_name,
96 				   DbeNumberErrors,
97 				   dbe_error_list)
98 
99 
100 /*****************************************************************************
101  *                                                                           *
102  *		       Double-Buffering public interfaces                    *
103  *                                                                           *
104  *****************************************************************************/
105 
106 /*
107  * XdbeQueryExtension -
108  *	Sets major_version_return and minor_verion_return to the major and
109  *	minor DBE protocol version supported by the server.  If the DBE
110  *	library is compatible with the version returned by the server, this
111  *	function returns non-zero.  If dpy does not support the DBE
112  *	extension, or if there was an error during communication with the
113  *	server, or if the server and library protocol versions are
114  *	incompatible, this functions returns zero.  No other Xdbe functions
115  *	may be called before this function.   If a client violates this rule,
116  *	the effects of all subsequent Xdbe calls are undefined.
117  */
118 Status XdbeQueryExtension (
119     Display *dpy,
120     int *major_version_return,
121     int *minor_version_return)
122 {
123     XExtDisplayInfo *info = find_display (dpy);
124     xDbeGetVersionReply rep;
125     register xDbeGetVersionReq *req;
126 
127     if (!XextHasExtension (info))
128         return (Status)0; /* failure */
129 
130     LockDisplay (dpy);
131     DbeGetReq (DbeGetVersion, req, info);
132     req->majorVersion = DBE_MAJOR_VERSION;
133     req->minorVersion = DBE_MINOR_VERSION;
134 
135     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
136 	UnlockDisplay (dpy);
137 	SyncHandle ();
138 	return (Status)0; /* failure */
139     }
140     *major_version_return = rep.majorVersion;
141     *minor_version_return = rep.minorVersion;
142     UnlockDisplay (dpy);
143 
144     SyncHandle ();
145 
146     if (*major_version_return != DBE_MAJOR_VERSION)
147         return (Status)0; /* failure */
148     else
149         return (Status)1; /* success */
150 }
151 
152 
153 /*
154  * XdbeAllocateBackBuffer -
155  *	This function returns a drawable ID used to refer to the back buffer
156  *	of the specified window.  The swap_action is a hint to indicate the
157  *	swap action that will likely be used in subsequent calls to
158  *	XdbeSwapBuffers.  The actual swap action used in calls to
159  *	XdbeSwapBuffers does not have to be the same as the swap_action
160  *	passed to this function, though clients are encouraged to provide
161  *	accurate information whenever possible.
162  */
163 
XdbeAllocateBackBufferName(Display * dpy,Window window,XdbeSwapAction swap_action)164 XdbeBackBuffer XdbeAllocateBackBufferName(
165     Display *dpy,
166     Window window,
167     XdbeSwapAction swap_action)
168 {
169     XExtDisplayInfo *info = find_display (dpy);
170     register xDbeAllocateBackBufferNameReq *req;
171     XdbeBackBuffer buffer;
172 
173     /* make sure extension is available; if not, return the
174      * third parameter (0).
175      */
176     DbeCheckExtension (dpy, info, (XdbeBackBuffer)0);
177 
178     LockDisplay(dpy);
179     DbeGetReq(DbeAllocateBackBufferName, req, info);
180     req->window = window;
181     req->swapAction = (unsigned char)swap_action;
182     req->buffer = buffer = XAllocID (dpy);
183 
184     UnlockDisplay (dpy);
185     SyncHandle ();
186     return buffer;
187 
188 } /* XdbeAllocateBackBufferName() */
189 
190 /*
191  * XdbeDeallocateBackBufferName -
192  *	This function frees a drawable ID, buffer, that was obtained via
193  *	XdbeAllocateBackBufferName.  The buffer must refer to the back buffer
194  *	of the specified window, or a protocol error results.
195  */
XdbeDeallocateBackBufferName(Display * dpy,XdbeBackBuffer buffer)196 Status XdbeDeallocateBackBufferName (
197     Display *dpy,
198     XdbeBackBuffer buffer)
199 {
200     XExtDisplayInfo *info = find_display (dpy);
201     register xDbeDeallocateBackBufferNameReq *req;
202 
203     DbeCheckExtension (dpy, info, (Status)0 /* failure */);
204 
205     LockDisplay (dpy);
206     DbeGetReq (DbeDeallocateBackBufferName, req, info);
207     req->buffer = buffer;
208     UnlockDisplay (dpy);
209     SyncHandle ();
210 
211     return (Status)1; /* success */
212 }
213 
214 
215 /*
216  * XdbeSwapBuffers -
217  *	This function swaps the front and back buffers for a list of windows.
218  *	The argument num_windows specifies how many windows are to have their
219  *	buffers swapped; it is the number of elements in the swap_info array.
220  *	The argument swap_info specifies the information needed per window
221  *	to do the swap.
222  */
XdbeSwapBuffers(Display * dpy,XdbeSwapInfo * swap_info,int num_windows)223 Status XdbeSwapBuffers (
224     Display *dpy,
225     XdbeSwapInfo *swap_info,
226     int num_windows)
227 {
228     XExtDisplayInfo *info = find_display (dpy);
229     register xDbeSwapBuffersReq *req;
230     int i;
231 
232     DbeCheckExtension (dpy, info, (Status)0 /* failure */);
233 
234     LockDisplay (dpy);
235     DbeGetReq (DbeSwapBuffers, req, info);
236     req->length += 2*num_windows;
237     req->n = num_windows;
238 
239     /* We need to handle 64-bit machines, where we can not use PackData32
240      * directly because info would be lost in translating from 32- to 64-bit.
241      * Instead we send data via a loop that accounts for the translation.
242      */
243     for (i = 0; i < num_windows; i++)
244     {
245         char tmp[4];
246         Data32 (dpy, (long *)&swap_info[i].swap_window, 4);
247         tmp[0] = swap_info[i].swap_action;
248         Data (dpy, (char *)tmp, 4);
249     }
250 
251     UnlockDisplay (dpy);
252     SyncHandle ();
253 
254 
255     return (Status)1; /* success */
256 
257 } /* XdbeSwapBuffers() */
258 
259 
260 /*
261  * XdbeBeginIdiom -
262  *	This function marks the beginning of an idiom sequence.
263  */
XdbeBeginIdiom(Display * dpy)264 Status XdbeBeginIdiom (Display *dpy)
265 {
266     XExtDisplayInfo *info = find_display(dpy);
267     register xDbeBeginIdiomReq *req;
268 
269     DbeCheckExtension (dpy, info, (Status)0 /* failure */);
270 
271     LockDisplay (dpy);
272     DbeGetReq (DbeBeginIdiom, req, info);
273     UnlockDisplay (dpy);
274     SyncHandle ();
275 
276     return (Status)1; /* success */
277 }
278 
279 
280 /*
281  * XdbeEndIdiom -
282  *	This function marks the end of an idiom sequence.
283  */
XdbeEndIdiom(Display * dpy)284 Status XdbeEndIdiom (Display *dpy)
285 {
286     XExtDisplayInfo *info = find_display(dpy);
287     register xDbeEndIdiomReq *req;
288 
289     DbeCheckExtension (dpy, info, (Status)0 /* failure */);
290 
291     LockDisplay (dpy);
292     DbeGetReq (DbeEndIdiom, req, info);
293     UnlockDisplay (dpy);
294     SyncHandle ();
295 
296     return (Status)1; /* success */
297 }
298 
299 
300 /*
301  * XdbeGetVisualInfo -
302  *	This function returns information about which visuals support
303  *	double buffering.  The argument num_screens specifies how many
304  *	elements there are in the screen_specifiers list.  Each drawable
305  *	in screen_specifiers designates a screen for which the supported
306  *	visuals are being requested.  If num_screens is zero, information
307  *	for all screens is requested.  In this case, upon return from this
308  *	function, num_screens will be set to the number of screens that were
309  *	found.  If an error occurs, this function returns NULL, else it returns
310  *	a pointer to a list of XdbeScreenVisualInfo structures of length
311  *	num_screens.  The nth element in the returned list corresponds to the
312  *	nth drawable in the screen_specifiers list, unless num_screens was
313  *	passed in with the value zero, in which case the nth element in the
314  *	returned list corresponds to the nth screen of the server, starting
315  *	with screen zero.
316  */
XdbeGetVisualInfo(Display * dpy,Drawable * screen_specifiers,int * num_screens)317 XdbeScreenVisualInfo *XdbeGetVisualInfo (
318     Display        *dpy,
319     Drawable       *screen_specifiers,
320     int            *num_screens)  /* SEND and RETURN */
321 {
322     XExtDisplayInfo *info = find_display(dpy);
323     register xDbeGetVisualInfoReq *req;
324     xDbeGetVisualInfoReply rep;
325     XdbeScreenVisualInfo *scrVisInfo;
326     int i;
327 
328     DbeCheckExtension (dpy, info, (XdbeScreenVisualInfo *)NULL);
329 
330     LockDisplay (dpy);
331 
332     DbeGetReq(DbeGetVisualInfo, req, info);
333     req->length = 2 + *num_screens;
334     req->n      = *num_screens;
335     Data32 (dpy, screen_specifiers, (*num_screens * sizeof (CARD32)));
336 
337     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
338         UnlockDisplay (dpy);
339         SyncHandle ();
340         return NULL;
341     }
342 
343     /* return the number of screens actually found if we
344      * requested information about all screens (*num_screens == 0)
345      */
346     if (*num_screens == 0)
347        *num_screens = rep.m;
348 
349     /* allocate list of visual information to be returned */
350     if ((*num_screens > 0) && (*num_screens < 65536))
351         scrVisInfo = Xmalloc(*num_screens * sizeof(XdbeScreenVisualInfo));
352     else
353         scrVisInfo = NULL;
354     if (scrVisInfo == NULL) {
355         _XEatDataWords(dpy, rep.length);
356         UnlockDisplay (dpy);
357         SyncHandle ();
358         return NULL;
359     }
360 
361     for (i = 0; i < *num_screens; i++)
362     {
363         int j;
364         unsigned long c;
365 
366         _XRead32 (dpy, (long *) &c, sizeof(CARD32));
367 
368         if (c < 65536) {
369             scrVisInfo[i].count = c;
370             scrVisInfo[i].visinfo = Xmalloc(c * sizeof(XdbeVisualInfo));
371         } else
372             scrVisInfo[i].visinfo = NULL;
373 
374         /* if we can not allocate the list of visual/depth info
375          * then free the lists that we already allocate as well
376          * as the visual info list itself
377          */
378         if (scrVisInfo[i].visinfo == NULL) {
379             for (j = 0; j < i; j++) {
380                 Xfree ((char *)scrVisInfo[j].visinfo);
381             }
382             Xfree ((char *)scrVisInfo);
383             _XEatDataWords(dpy, rep.length);
384             UnlockDisplay (dpy);
385             SyncHandle ();
386             return NULL;
387         }
388 
389         /* Read the visual info item into the wire structure.  Then copy each
390          * element into the library structure.  The element sizes and/or
391          * padding may be different in the two structures.
392          */
393         for (j = 0; j < scrVisInfo[i].count; j++) {
394             xDbeVisInfo xvi;
395 
396             _XRead (dpy, (char *)&xvi, sizeof(xDbeVisInfo));
397             scrVisInfo[i].visinfo[j].visual    = xvi.visualID;
398             scrVisInfo[i].visinfo[j].depth     = xvi.depth;
399             scrVisInfo[i].visinfo[j].perflevel = xvi.perfLevel;
400         }
401 
402     }
403 
404     UnlockDisplay (dpy);
405     SyncHandle ();
406     return scrVisInfo;
407 
408 } /* XdbeGetVisualInfo() */
409 
410 
411 /*
412  * XdbeFreeVisualInfo -
413  *	This function frees the list of XdbeScreenVisualInfo returned by the
414  *	function XdbeGetVisualInfo.
415  */
XdbeFreeVisualInfo(XdbeScreenVisualInfo * visual_info)416 void XdbeFreeVisualInfo(XdbeScreenVisualInfo *visual_info)
417 {
418     if (visual_info == NULL) {
419         return;
420     }
421 
422     if (visual_info->visinfo) {
423         XFree(visual_info->visinfo);
424     }
425 
426     XFree(visual_info);
427 }
428 
429 
430 /*
431  * XdbeGetBackBufferAttributes -
432  *	This function returns the attributes associated with the specified
433  *	buffer.
434  */
XdbeGetBackBufferAttributes(Display * dpy,XdbeBackBuffer buffer)435 XdbeBackBufferAttributes *XdbeGetBackBufferAttributes(
436     Display *dpy,
437     XdbeBackBuffer buffer)
438 {
439     XExtDisplayInfo *info = find_display(dpy);
440     register xDbeGetBackBufferAttributesReq *req;
441     xDbeGetBackBufferAttributesReply rep;
442     XdbeBackBufferAttributes *attr;
443 
444     DbeCheckExtension(dpy, info, (XdbeBackBufferAttributes *)NULL);
445 
446     if (!(attr =
447        (XdbeBackBufferAttributes *)Xmalloc(sizeof(XdbeBackBufferAttributes)))) {
448         return NULL;
449     }
450 
451     LockDisplay(dpy);
452     DbeGetReq(DbeGetBackBufferAttributes, req, info);
453     req->buffer = buffer;
454 
455     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
456         UnlockDisplay (dpy);
457         SyncHandle ();
458 	Xfree(attr);
459         return NULL;
460     }
461     attr->window = rep.attributes;
462 
463     UnlockDisplay (dpy);
464     SyncHandle ();
465 
466     return attr;
467 }
468 
469