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