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