Xdbe.c revision 0760f5d2
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#include "reallocarray.h" 44 45static XExtensionInfo _dbe_info_data; 46static XExtensionInfo *dbe_info = &_dbe_info_data; 47static const char *dbe_extension_name = DBE_PROTOCOL_NAME; 48 49#define DbeCheckExtension(dpy,i,val) \ 50 XextCheckExtension (dpy, i, dbe_extension_name, val) 51#define DbeSimpleCheckExtension(dpy,i) \ 52 XextSimpleCheckExtension (dpy, i, dbe_extension_name) 53 54#define DbeGetReq(name,req,info) GetReq (name, req); \ 55 req->reqType = info->codes->major_opcode; \ 56 req->dbeReqType = X_##name; 57 58 59/***************************************************************************** 60 * * 61 * private utility routines * 62 * * 63 *****************************************************************************/ 64 65/* 66 * find_display - locate the display info block 67 */ 68static int close_display(Display *dpy, XExtCodes *codes); 69static char *error_string(Display *dpy, int code, XExtCodes *codes, 70 char *buf, int n); 71static XExtensionHooks dbe_extension_hooks = { 72 NULL, /* create_gc */ 73 NULL, /* copy_gc */ 74 NULL, /* flush_gc */ 75 NULL, /* free_gc */ 76 NULL, /* create_font */ 77 NULL, /* free_font */ 78 close_display, /* close_display */ 79 NULL, /* wire_to_event */ 80 NULL, /* event_to_wire */ 81 NULL, /* error */ 82 error_string, /* error_string */ 83}; 84 85static const char *dbe_error_list[] = { 86 "BadBuffer", /* DbeBadBuffer */ 87}; 88 89static XEXT_GENERATE_FIND_DISPLAY (find_display, dbe_info, 90 dbe_extension_name, 91 &dbe_extension_hooks, 92 DbeNumberEvents, NULL) 93 94static XEXT_GENERATE_CLOSE_DISPLAY (close_display, dbe_info) 95 96static XEXT_GENERATE_ERROR_STRING (error_string, dbe_extension_name, 97 DbeNumberErrors, 98 dbe_error_list) 99 100 101/***************************************************************************** 102 * * 103 * Double-Buffering public interfaces * 104 * * 105 *****************************************************************************/ 106 107/* 108 * XdbeQueryExtension - 109 * Sets major_version_return and minor_verion_return to the major and 110 * minor DBE protocol version supported by the server. If the DBE 111 * library is compatible with the version returned by the server, this 112 * function returns non-zero. If dpy does not support the DBE 113 * extension, or if there was an error during communication with the 114 * server, or if the server and library protocol versions are 115 * incompatible, this functions returns zero. No other Xdbe functions 116 * may be called before this function. If a client violates this rule, 117 * the effects of all subsequent Xdbe calls are undefined. 118 */ 119Status XdbeQueryExtension ( 120 Display *dpy, 121 int *major_version_return, 122 int *minor_version_return) 123{ 124 XExtDisplayInfo *info = find_display (dpy); 125 xDbeGetVersionReply rep; 126 register xDbeGetVersionReq *req; 127 128 if (!XextHasExtension (info)) 129 return (Status)0; /* failure */ 130 131 LockDisplay (dpy); 132 DbeGetReq (DbeGetVersion, req, info); 133 req->majorVersion = DBE_MAJOR_VERSION; 134 req->minorVersion = DBE_MINOR_VERSION; 135 136 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { 137 UnlockDisplay (dpy); 138 SyncHandle (); 139 return (Status)0; /* failure */ 140 } 141 *major_version_return = rep.majorVersion; 142 *minor_version_return = rep.minorVersion; 143 UnlockDisplay (dpy); 144 145 SyncHandle (); 146 147 if (*major_version_return != DBE_MAJOR_VERSION) 148 return (Status)0; /* failure */ 149 else 150 return (Status)1; /* success */ 151} 152 153 154/* 155 * XdbeAllocateBackBuffer - 156 * This function returns a drawable ID used to refer to the back buffer 157 * of the specified window. The swap_action is a hint to indicate the 158 * swap action that will likely be used in subsequent calls to 159 * XdbeSwapBuffers. The actual swap action used in calls to 160 * XdbeSwapBuffers does not have to be the same as the swap_action 161 * passed to this function, though clients are encouraged to provide 162 * accurate information whenever possible. 163 */ 164 165XdbeBackBuffer XdbeAllocateBackBufferName( 166 Display *dpy, 167 Window window, 168 XdbeSwapAction swap_action) 169{ 170 XExtDisplayInfo *info = find_display (dpy); 171 register xDbeAllocateBackBufferNameReq *req; 172 XdbeBackBuffer buffer; 173 174 /* make sure extension is available; if not, return the 175 * third parameter (0). 176 */ 177 DbeCheckExtension (dpy, info, (XdbeBackBuffer)0); 178 179 LockDisplay(dpy); 180 DbeGetReq(DbeAllocateBackBufferName, req, info); 181 req->window = window; 182 req->swapAction = (unsigned char)swap_action; 183 req->buffer = buffer = XAllocID (dpy); 184 185 UnlockDisplay (dpy); 186 SyncHandle (); 187 return buffer; 188 189} /* XdbeAllocateBackBufferName() */ 190 191/* 192 * XdbeDeallocateBackBufferName - 193 * This function frees a drawable ID, buffer, that was obtained via 194 * XdbeAllocateBackBufferName. The buffer must refer to the back buffer 195 * of the specified window, or a protocol error results. 196 */ 197Status XdbeDeallocateBackBufferName ( 198 Display *dpy, 199 XdbeBackBuffer buffer) 200{ 201 XExtDisplayInfo *info = find_display (dpy); 202 register xDbeDeallocateBackBufferNameReq *req; 203 204 DbeCheckExtension (dpy, info, (Status)0 /* failure */); 205 206 LockDisplay (dpy); 207 DbeGetReq (DbeDeallocateBackBufferName, req, info); 208 req->buffer = buffer; 209 UnlockDisplay (dpy); 210 SyncHandle (); 211 212 return (Status)1; /* success */ 213} 214 215 216/* 217 * XdbeSwapBuffers - 218 * This function swaps the front and back buffers for a list of windows. 219 * The argument num_windows specifies how many windows are to have their 220 * buffers swapped; it is the number of elements in the swap_info array. 221 * The argument swap_info specifies the information needed per window 222 * to do the swap. 223 */ 224Status XdbeSwapBuffers ( 225 Display *dpy, 226 XdbeSwapInfo *swap_info, 227 int num_windows) 228{ 229 XExtDisplayInfo *info = find_display (dpy); 230 register xDbeSwapBuffersReq *req; 231 int i; 232 233 DbeCheckExtension (dpy, info, (Status)0 /* failure */); 234 235 LockDisplay (dpy); 236 DbeGetReq (DbeSwapBuffers, req, info); 237 req->length += 2*num_windows; 238 req->n = num_windows; 239 240 /* We need to handle 64-bit machines, where we can not use PackData32 241 * directly because info would be lost in translating from 32- to 64-bit. 242 * Instead we send data via a loop that accounts for the translation. 243 */ 244 for (i = 0; i < num_windows; i++) 245 { 246 char tmp[4]; 247 Data32 (dpy, (long *)&swap_info[i].swap_window, 4); 248 tmp[0] = swap_info[i].swap_action; 249 Data (dpy, (char *)tmp, 4); 250 } 251 252 UnlockDisplay (dpy); 253 SyncHandle (); 254 255 256 return (Status)1; /* success */ 257 258} /* XdbeSwapBuffers() */ 259 260 261/* 262 * XdbeBeginIdiom - 263 * This function marks the beginning of an idiom sequence. 264 */ 265Status XdbeBeginIdiom (Display *dpy) 266{ 267 XExtDisplayInfo *info = find_display(dpy); 268 register xDbeBeginIdiomReq *req; 269 270 DbeCheckExtension (dpy, info, (Status)0 /* failure */); 271 272 LockDisplay (dpy); 273 DbeGetReq (DbeBeginIdiom, req, info); 274 UnlockDisplay (dpy); 275 SyncHandle (); 276 277 return (Status)1; /* success */ 278} 279 280 281/* 282 * XdbeEndIdiom - 283 * This function marks the end of an idiom sequence. 284 */ 285Status XdbeEndIdiom (Display *dpy) 286{ 287 XExtDisplayInfo *info = find_display(dpy); 288 register xDbeEndIdiomReq *req; 289 290 DbeCheckExtension (dpy, info, (Status)0 /* failure */); 291 292 LockDisplay (dpy); 293 DbeGetReq (DbeEndIdiom, req, info); 294 UnlockDisplay (dpy); 295 SyncHandle (); 296 297 return (Status)1; /* success */ 298} 299 300 301/* 302 * XdbeGetVisualInfo - 303 * This function returns information about which visuals support 304 * double buffering. The argument num_screens specifies how many 305 * elements there are in the screen_specifiers list. Each drawable 306 * in screen_specifiers designates a screen for which the supported 307 * visuals are being requested. If num_screens is zero, information 308 * for all screens is requested. In this case, upon return from this 309 * function, num_screens will be set to the number of screens that were 310 * found. If an error occurs, this function returns NULL, else it returns 311 * a pointer to a list of XdbeScreenVisualInfo structures of length 312 * num_screens. The nth element in the returned list corresponds to the 313 * nth drawable in the screen_specifiers list, unless num_screens was 314 * passed in with the value zero, in which case the nth element in the 315 * returned list corresponds to the nth screen of the server, starting 316 * with screen zero. 317 */ 318XdbeScreenVisualInfo *XdbeGetVisualInfo ( 319 Display *dpy, 320 Drawable *screen_specifiers, 321 int *num_screens) /* SEND and RETURN */ 322{ 323 XExtDisplayInfo *info = find_display(dpy); 324 register xDbeGetVisualInfoReq *req; 325 xDbeGetVisualInfoReply rep; 326 XdbeScreenVisualInfo *scrVisInfo; 327 int i; 328 329 DbeCheckExtension (dpy, info, (XdbeScreenVisualInfo *)NULL); 330 331 LockDisplay (dpy); 332 333 DbeGetReq(DbeGetVisualInfo, req, info); 334 req->length = 2 + *num_screens; 335 req->n = *num_screens; 336 Data32 (dpy, screen_specifiers, (*num_screens * sizeof (CARD32))); 337 338 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { 339 UnlockDisplay (dpy); 340 SyncHandle (); 341 return NULL; 342 } 343 344 /* return the number of screens actually found if we 345 * requested information about all screens (*num_screens == 0) 346 */ 347 if (*num_screens == 0) 348 *num_screens = rep.m; 349 350 /* allocate list of visual information to be returned */ 351 if ((*num_screens > 0) && (*num_screens < 65536)) 352 scrVisInfo = Xcalloc(*num_screens, sizeof(XdbeScreenVisualInfo)); 353 else 354 scrVisInfo = NULL; 355 if (scrVisInfo == NULL) { 356 _XEatDataWords(dpy, rep.length); 357 UnlockDisplay (dpy); 358 SyncHandle (); 359 return NULL; 360 } 361 362 for (i = 0; i < *num_screens; i++) 363 { 364 int j; 365 unsigned long c; 366 367 _XRead32 (dpy, (long *) &c, sizeof(CARD32)); 368 369 if (c < 65536) { 370 scrVisInfo[i].count = c; 371 scrVisInfo[i].visinfo = Xmallocarray(c, sizeof(XdbeVisualInfo)); 372 } else 373 scrVisInfo[i].visinfo = NULL; 374 375 /* if we can not allocate the list of visual/depth info 376 * then free the lists that we already allocated as well 377 * as the visual info list itself 378 */ 379 if (scrVisInfo[i].visinfo == NULL) { 380 for (j = 0; j < i; j++) { 381 Xfree (scrVisInfo[j].visinfo); 382 } 383 Xfree (scrVisInfo); 384 _XEatDataWords(dpy, rep.length); 385 UnlockDisplay (dpy); 386 SyncHandle (); 387 return NULL; 388 } 389 390 /* Read the visual info item into the wire structure. Then copy each 391 * element into the library structure. The element sizes and/or 392 * padding may be different in the two structures. 393 */ 394 for (j = 0; j < scrVisInfo[i].count; j++) { 395 xDbeVisInfo xvi; 396 397 _XRead (dpy, (char *)&xvi, sizeof(xDbeVisInfo)); 398 scrVisInfo[i].visinfo[j].visual = xvi.visualID; 399 scrVisInfo[i].visinfo[j].depth = xvi.depth; 400 scrVisInfo[i].visinfo[j].perflevel = xvi.perfLevel; 401 } 402 403 } 404 405 UnlockDisplay (dpy); 406 SyncHandle (); 407 return scrVisInfo; 408 409} /* XdbeGetVisualInfo() */ 410 411 412/* 413 * XdbeFreeVisualInfo - 414 * This function frees the list of XdbeScreenVisualInfo returned by the 415 * function XdbeGetVisualInfo. 416 */ 417void XdbeFreeVisualInfo(XdbeScreenVisualInfo *visual_info) 418{ 419 if (visual_info == NULL) { 420 return; 421 } 422 423 if (visual_info->visinfo) { 424 XFree(visual_info->visinfo); 425 } 426 427 XFree(visual_info); 428} 429 430 431/* 432 * XdbeGetBackBufferAttributes - 433 * This function returns the attributes associated with the specified 434 * buffer. 435 */ 436XdbeBackBufferAttributes *XdbeGetBackBufferAttributes( 437 Display *dpy, 438 XdbeBackBuffer buffer) 439{ 440 XExtDisplayInfo *info = find_display(dpy); 441 register xDbeGetBackBufferAttributesReq *req; 442 xDbeGetBackBufferAttributesReply rep; 443 XdbeBackBufferAttributes *attr; 444 445 DbeCheckExtension(dpy, info, (XdbeBackBufferAttributes *)NULL); 446 447 if (!(attr = 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