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