Xdbe.c revision e5383a99
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
44static XExtensionInfo _dbe_info_data;
45static XExtensionInfo *dbe_info = &_dbe_info_data;
46static 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 */
67static int close_display(Display *dpy, XExtCodes *codes);
68static char *error_string(Display *dpy, int code, XExtCodes *codes,
69			  char *buf, int n);
70static 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
84static const char *dbe_error_list[] = {
85    "BadBuffer",			/* DbeBadBuffer */
86};
87
88static XEXT_GENERATE_FIND_DISPLAY (find_display, dbe_info,
89				   dbe_extension_name,
90				   &dbe_extension_hooks,
91				   DbeNumberEvents, NULL)
92
93static XEXT_GENERATE_CLOSE_DISPLAY (close_display, dbe_info)
94
95static 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 */
118Status 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
164XdbeBackBuffer 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 */
196Status 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 */
223Status 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 */
264Status 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 */
284Status 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 */
317XdbeScreenVisualInfo *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 */
416void 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 */
435XdbeBackBufferAttributes *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