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