XMultibuf.c revision caade7cc
1/* 2 * $Xorg: XMultibuf.c,v 1.6 2001/02/09 02:03:49 xorgcvs Exp $ 3 * 4Copyright 1989, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall not be 23used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from The Open Group. 25 * 26 * Authors: Jim Fulton, MIT X Consortium 27 */ 28/* $XFree86: xc/lib/Xext/XMultibuf.c,v 1.5 2001/12/14 19:55:00 dawes Exp $ */ 29 30#define NEED_EVENTS 31#define NEED_REPLIES 32#ifdef HAVE_CONFIG_H 33#include <config.h> 34#endif 35#include <X11/Xlibint.h> 36#include <stdio.h> 37#include <X11/extensions/Xext.h> 38#include <X11/extensions/extutil.h> 39#include <X11/extensions/multibufst.h> 40 41static XExtensionInfo _multibuf_info_data; 42static XExtensionInfo *multibuf_info = &_multibuf_info_data; 43static /* const */ char *multibuf_extension_name = MULTIBUFFER_PROTOCOL_NAME; 44 45#define MbufCheckExtension(dpy,i,val) \ 46 XextCheckExtension (dpy, i, multibuf_extension_name, val) 47#define MbufSimpleCheckExtension(dpy,i) \ 48 XextSimpleCheckExtension (dpy, i, multibuf_extension_name) 49 50 51/***************************************************************************** 52 * * 53 * private utility routines * 54 * * 55 *****************************************************************************/ 56 57/* 58 * find_display - locate the display info block 59 */ 60static int close_display(Display *dpy, XExtCodes *codes); 61static char *error_string(Display *dpy, int code, XExtCodes *codes, char *buf, int n); 62static Bool wire_to_event(Display *dpy, XEvent *libevent, xEvent *netevent); 63static Status event_to_wire(Display *dpy, XEvent *libevent, xEvent *netevent); 64static /* const */ XExtensionHooks multibuf_extension_hooks = { 65 NULL, /* create_gc */ 66 NULL, /* copy_gc */ 67 NULL, /* flush_gc */ 68 NULL, /* free_gc */ 69 NULL, /* create_font */ 70 NULL, /* free_font */ 71 close_display, /* close_display */ 72 wire_to_event, /* wire_to_event */ 73 event_to_wire, /* event_to_wire */ 74 NULL, /* error */ 75 error_string, /* error_string */ 76}; 77 78static /* const */ char *multibuf_error_list[] = { 79 "BadBuffer", /* MultibufferBadBuffer */ 80}; 81 82static XEXT_GENERATE_FIND_DISPLAY (find_display, multibuf_info, 83 multibuf_extension_name, 84 &multibuf_extension_hooks, 85 MultibufferNumberEvents, NULL) 86 87static XEXT_GENERATE_CLOSE_DISPLAY (close_display, multibuf_info) 88 89static XEXT_GENERATE_ERROR_STRING (error_string, multibuf_extension_name, 90 MultibufferNumberErrors, 91 multibuf_error_list) 92 93/* 94 * wire_to_event - convert a wire event in network format to a C 95 * event structure 96 */ 97static Bool wire_to_event (Display *dpy, XEvent *libevent, xEvent *netevent) 98{ 99 XExtDisplayInfo *info = find_display (dpy); 100 101 MbufCheckExtension (dpy, info, False); 102 103 switch ((netevent->u.u.type & 0x7f) - info->codes->first_event) { 104 case MultibufferClobberNotify: 105 { 106 XmbufClobberNotifyEvent *ev; 107 xMbufClobberNotifyEvent *event; 108 109 ev = (XmbufClobberNotifyEvent *) libevent; 110 event = (xMbufClobberNotifyEvent *) netevent; 111 ev->type = event->type & 0x7f; 112 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent); 113 ev->send_event = ((event->type & 0x80) != 0); 114 ev->display = dpy; 115 ev->buffer = event->buffer; 116 ev->state = event->state; 117 return True; 118 } 119 case MultibufferUpdateNotify: 120 { 121 XmbufUpdateNotifyEvent *ev; 122 xMbufUpdateNotifyEvent *event; 123 124 ev = (XmbufUpdateNotifyEvent *) libevent; 125 event = (xMbufUpdateNotifyEvent *) netevent; 126 ev->type = event->type & 0x7f; 127 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent); 128 ev->send_event = ((event->type & 0x80) != 0); 129 ev->display = dpy; 130 ev->buffer = event->buffer; 131 return True; 132 } 133 } 134 return False; 135} 136 137 138/* 139 * event_to_wire - convert a C event structure to a wire event in 140 * network format 141 */ 142static Status event_to_wire (Display *dpy, XEvent *libevent, xEvent *netevent) 143{ 144 XExtDisplayInfo *info = find_display (dpy); 145 146 MbufCheckExtension (dpy, info, 0); 147 148 switch ((libevent->type & 0x7f) - info->codes->first_event) { 149 case MultibufferClobberNotify: 150 { 151 XmbufClobberNotifyEvent *ev; 152 xMbufClobberNotifyEvent *event; 153 154 ev = (XmbufClobberNotifyEvent *) libevent; 155 event = (xMbufClobberNotifyEvent *) netevent; 156 event->type = ev->type; 157 event->sequenceNumber = (ev->serial & 0xffff); 158 event->buffer = ev->buffer; 159 event->state = ev->state; 160 return 1; 161 } 162 case MultibufferUpdateNotify: 163 { 164 XmbufUpdateNotifyEvent *ev; 165 xMbufUpdateNotifyEvent *event; 166 167 ev = (XmbufUpdateNotifyEvent *) libevent; 168 event = (xMbufUpdateNotifyEvent *) netevent; 169 event->type = ev->type; 170 event->sequenceNumber = (ev->serial & 0xffff); 171 event->buffer = ev->buffer; 172 return 1; 173 } 174 } 175 return 0; 176} 177 178 179/* 180 * read_buffer_info - read Buffer Info descriptors from the net; if unable 181 * to allocate memory, read junk to make sure that stream is clear. 182 */ 183#define TALLOC(type,count) ((type *) Xmalloc ((unsigned) count * sizeof(type))) 184 185static XmbufBufferInfo *read_buffer_info (Display *dpy, int nbufs) 186{ 187 xMbufBufferInfo *netbuf = TALLOC (xMbufBufferInfo, nbufs); 188 XmbufBufferInfo *bufinfo = NULL; 189 long netbytes = nbufs * SIZEOF(xMbufBufferInfo); 190 191 if (netbuf) { 192 _XRead (dpy, (char *) netbuf, netbytes); 193 194 bufinfo = TALLOC (XmbufBufferInfo, nbufs); 195 if (bufinfo) { 196 register XmbufBufferInfo *c; 197 register xMbufBufferInfo *net; 198 register int i; 199 200 for (i = 0, c = bufinfo, net = netbuf; i < nbufs; 201 i++, c++, net++) { 202 c->visualid = net->visualID; 203 c->max_buffers = net->maxBuffers; 204 c->depth = net->depth; 205 } 206 } 207 Xfree ((char *) netbuf); 208 } else { /* eat the data */ 209 while (netbytes > 0) { 210 char dummy[256]; /* stack size vs loops tradeoff */ 211 long nbytes = sizeof dummy; 212 213 if (nbytes > netbytes) nbytes = netbytes; 214 _XRead (dpy, dummy, nbytes); 215 netbytes -= nbytes; 216 } 217 } 218 219 return bufinfo; 220} 221 222#undef TALLOC 223 224 225/***************************************************************************** 226 * * 227 * Multibuffering/stereo public interfaces * 228 * * 229 *****************************************************************************/ 230 231 232/* 233 * XmbufQueryExtension - 234 * Returns True if the multibuffering/stereo extension is available 235 * on the given display. If the extension exists, the value of the 236 * first event code (which should be added to the event type constants 237 * MultibufferClobberNotify and MultibufferUpdateNotify to get the 238 * actual values) is stored into event_base and the value of the first 239 * error code (which should be added to the error type constant 240 * MultibufferBadBuffer to get the actual value) is stored into 241 * error_base. 242 */ 243Bool XmbufQueryExtension ( 244 Display *dpy, 245 int *event_base_return, int *error_base_return) 246{ 247 XExtDisplayInfo *info = find_display (dpy); 248 249 if (XextHasExtension (info)) { 250 *event_base_return = info->codes->first_event; 251 *error_base_return = info->codes->first_error; 252 return True; 253 } else { 254 return False; 255 } 256} 257 258 259/* 260 * XmbufGetVersion - 261 * Gets the major and minor version numbers of the extension. The return 262 * value is zero if an error occurs or non-zero if no error happens. 263 */ 264Status XmbufGetVersion ( 265 Display *dpy, 266 int *major_version_return, int *minor_version_return) 267{ 268 XExtDisplayInfo *info = find_display (dpy); 269 xMbufGetBufferVersionReply rep; 270 register xMbufGetBufferVersionReq *req; 271 272 MbufCheckExtension (dpy, info, 0); 273 274 LockDisplay (dpy); 275 MbufGetReq (MbufGetBufferVersion, req, info); 276 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { 277 UnlockDisplay (dpy); 278 SyncHandle (); 279 return 0; 280 } 281 *major_version_return = rep.majorVersion; 282 *minor_version_return = rep.minorVersion; 283 UnlockDisplay (dpy); 284 285 SyncHandle (); 286 return 1; 287} 288 289 290/* 291 * XmbufCreateBuffers - 292 * Requests that "count" buffers be created with the given update_action 293 * and update_hint and be associated with the indicated window. The 294 * number of buffers created is returned (zero if an error occurred) 295 * and buffers_return is filled in with that many Multibuffer identifiers. 296 */ 297int XmbufCreateBuffers ( 298 Display *dpy, 299 Window w, 300 int count, 301 int update_action, int update_hint, 302 Multibuffer *buffers) 303{ 304 XExtDisplayInfo *info = find_display (dpy); 305 xMbufCreateImageBuffersReply rep; 306 register xMbufCreateImageBuffersReq *req; 307 int result; 308 309 MbufCheckExtension (dpy, info, 0); 310 311 LockDisplay (dpy); 312 313 XAllocIDs(dpy, buffers, count); 314 MbufGetReq (MbufCreateImageBuffers, req, info); 315 req->window = w; 316 req->updateAction = update_action; 317 req->updateHint = update_hint; 318 req->length += count; 319 count <<= 2; 320 PackData32 (dpy, buffers, count); 321 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { 322 UnlockDisplay (dpy); 323 SyncHandle (); 324 return 0; 325 } 326 result = rep.numberBuffer; 327 UnlockDisplay (dpy); 328 329 SyncHandle (); 330 return result; 331} 332 333 334/* 335 * XmbufDestroyBuffers - 336 * Destroys the buffers associated with the given window. 337 */ 338void XmbufDestroyBuffers (Display *dpy, Window window) 339{ 340 XExtDisplayInfo *info = find_display (dpy); 341 register xMbufDestroyImageBuffersReq *req; 342 343 MbufSimpleCheckExtension (dpy, info); 344 345 LockDisplay (dpy); 346 MbufGetReq (MbufDestroyImageBuffers, req, info); 347 req->window = window; 348 UnlockDisplay (dpy); 349 SyncHandle (); 350} 351 352 353/* 354 * XmbufDisplayBuffers - 355 * Displays the indicated buffers their appropriate windows within 356 * max_delay milliseconds after min_delay milliseconds have passed. 357 * No two buffers may be associated with the same window or else a Match 358 * error is generated. 359 */ 360void XmbufDisplayBuffers ( 361 Display *dpy, 362 int count, 363 Multibuffer *buffers, 364 int min_delay, int max_delay) 365{ 366 XExtDisplayInfo *info = find_display (dpy); 367 register xMbufDisplayImageBuffersReq *req; 368 369 MbufSimpleCheckExtension (dpy, info); 370 371 LockDisplay (dpy); 372 MbufGetReq (MbufDisplayImageBuffers, req, info); 373 req->minDelay = min_delay; 374 req->maxDelay = max_delay; 375 req->length += count; 376 count <<= 2; 377 PackData32 (dpy, buffers, count); 378 UnlockDisplay (dpy); 379 SyncHandle(); 380} 381 382 383/* 384 * XmbufGetWindowAttributes - 385 * Gets the multibuffering attributes that apply to all buffers associated 386 * with the given window. Returns non-zero on success and zero if an 387 * error occurs. 388 */ 389Status XmbufGetWindowAttributes ( 390 Display *dpy, 391 Window w, 392 XmbufWindowAttributes *attr) 393{ 394 XExtDisplayInfo *info = find_display (dpy); 395 register xMbufGetMBufferAttributesReq *req; 396 xMbufGetMBufferAttributesReply rep; 397 398 MbufCheckExtension (dpy, info, 0); 399 400 LockDisplay (dpy); 401 MbufGetReq (MbufGetMBufferAttributes, req, info); 402 req->window = w; 403 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { 404 UnlockDisplay (dpy); 405 SyncHandle (); 406 return 0; 407 } 408 attr->buffers = (Multibuffer *) NULL; 409 if ((attr->nbuffers = rep.length)) { 410 int nbytes = rep.length * sizeof(Multibuffer); 411 attr->buffers = (Multibuffer *) Xmalloc((unsigned) nbytes); 412 nbytes = rep.length << 2; 413 if (! attr->buffers) { 414 _XEatData(dpy, (unsigned long) nbytes); 415 UnlockDisplay(dpy); 416 SyncHandle(); 417 return (0); 418 } 419 _XRead32 (dpy, (long *) attr->buffers, nbytes); 420 } 421 attr->displayed_index = rep.displayedBuffer; 422 attr->update_action = rep.updateAction; 423 attr->update_hint = rep.updateHint; 424 attr->window_mode = rep.windowMode; 425 426 UnlockDisplay (dpy); 427 SyncHandle(); 428 return 1; 429} 430 431 432/* 433 * XmbufChangeWindowAttributes - 434 * Sets the multibuffering attributes that apply to all buffers associated 435 * with the given window. This is currently limited to the update_hint. 436 */ 437void XmbufChangeWindowAttributes ( 438 Display *dpy, 439 Window w, 440 unsigned long valuemask, 441 XmbufSetWindowAttributes *attr) 442{ 443 XExtDisplayInfo *info = find_display (dpy); 444 register xMbufSetMBufferAttributesReq *req; 445 446 MbufSimpleCheckExtension (dpy, info); 447 448 LockDisplay (dpy); 449 MbufGetReq (MbufSetMBufferAttributes, req, info); 450 req->window = w; 451 if ((req->valueMask = valuemask)) { /* stolen from lib/X/XWindow.c */ 452 unsigned long values[1]; /* one per element in if stmts below */ 453 unsigned long *v = values; 454 unsigned int nvalues; 455 456 if (valuemask & MultibufferWindowUpdateHint) 457 *v++ = attr->update_hint; 458 req->length += (nvalues = v - values); 459 nvalues <<= 2; /* watch out for macros... */ 460 Data32 (dpy, (long *) values, (long)nvalues); 461 } 462 UnlockDisplay (dpy); 463 SyncHandle(); 464} 465 466 467/* 468 * XmbufGetBufferAttributes - 469 * Gets the attributes for the indicated buffer. Returns non-zero on 470 * success and zero if an error occurs. 471 */ 472Status XmbufGetBufferAttributes ( 473 Display *dpy, 474 Multibuffer b, 475 XmbufBufferAttributes *attr) 476{ 477 XExtDisplayInfo *info = find_display (dpy); 478 register xMbufGetBufferAttributesReq *req; 479 xMbufGetBufferAttributesReply rep; 480 481 MbufCheckExtension (dpy, info, 0); 482 483 LockDisplay (dpy); 484 MbufGetReq (MbufGetBufferAttributes, req, info); 485 req->buffer = b; 486 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { 487 UnlockDisplay (dpy); 488 SyncHandle (); 489 return 0; 490 } 491 attr->window = rep.window; 492 attr->event_mask = rep.eventMask; 493 attr->buffer_index = rep.bufferIndex; 494 attr->side = rep.side; 495 496 UnlockDisplay (dpy); 497 SyncHandle(); 498 return 1; 499} 500 501 502/* 503 * XmbufChangeBufferAttributes - 504 * Sets the attributes for the indicated buffer. This is currently 505 * limited to the event_mask. 506 */ 507void XmbufChangeBufferAttributes ( 508 Display *dpy, 509 Multibuffer b, 510 unsigned long valuemask, 511 XmbufSetBufferAttributes *attr) 512{ 513 XExtDisplayInfo *info = find_display (dpy); 514 register xMbufSetBufferAttributesReq *req; 515 516 MbufSimpleCheckExtension (dpy, info); 517 518 LockDisplay (dpy); 519 MbufGetReq (MbufSetBufferAttributes, req, info); 520 req->buffer = b; 521 if ((req->valueMask = valuemask)) { /* stolen from lib/X/XWindow.c */ 522 unsigned long values[1]; /* one per element in if stmts below */ 523 unsigned long *v = values; 524 unsigned int nvalues; 525 526 if (valuemask & MultibufferBufferEventMask) 527 *v++ = attr->event_mask; 528 req->length += (nvalues = v - values); 529 nvalues <<= 2; /* watch out for macros... */ 530 Data32 (dpy, (long *) values, (long)nvalues); 531 } 532 UnlockDisplay (dpy); 533 SyncHandle(); 534} 535 536 537 538/* 539 * XmbufGetScreenInfo - 540 * Gets the parameters controlling how mono and stereo windows may be 541 * created on the indicated screen. The numbers of sets of visual and 542 * depths are returned in nmono_return and nstereo_return. If 543 * nmono_return is greater than zero, then mono_info_return is set to 544 * the address of an array of XmbufBufferInfo structures describing the 545 * various visuals and depths that may be used. Otherwise, 546 * mono_info_return is set to NULL. Similarly, stereo_info_return is 547 * set according to nstereo_return. The storage returned in 548 * mono_info_return and stereo_info_return may be released by XFree. 549 * If no errors are encounted, non-zero will be returned. 550 */ 551Status XmbufGetScreenInfo ( 552 Display *dpy, 553 Drawable d, 554 int *nmono_return, 555 XmbufBufferInfo **mono_info_return, 556 int *nstereo_return, 557 XmbufBufferInfo **stereo_info_return) 558{ 559 XExtDisplayInfo *info = find_display (dpy); 560 register xMbufGetBufferInfoReq *req; 561 xMbufGetBufferInfoReply rep; 562 int nmono, nstereo; 563 XmbufBufferInfo *minfo, *sinfo; 564 565 MbufCheckExtension (dpy, info, 0); 566 567 LockDisplay (dpy); 568 MbufGetReq (MbufGetBufferInfo, req, info); 569 req->drawable = d; 570 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { 571 UnlockDisplay (dpy); 572 SyncHandle (); 573 return 0; 574 } 575 nmono = rep.normalInfo; 576 nstereo = rep.stereoInfo; 577 minfo = ((nmono > 0) ? read_buffer_info (dpy, nmono) : NULL); 578 sinfo = ((nstereo > 0) ? read_buffer_info (dpy, nstereo) : NULL); 579 580 /* check for bad reads indicating we need to return an error */ 581 if ((nmono > 0 && !minfo) || (nstereo > 0 && !sinfo)) { 582 if (minfo) Xfree ((char *) minfo); 583 if (sinfo) Xfree ((char *) sinfo); 584 UnlockDisplay (dpy); 585 SyncHandle(); 586 return 0; 587 } 588 589 *nmono_return = nmono; 590 *mono_info_return = minfo; 591 *nstereo_return = nstereo; 592 *stereo_info_return = sinfo; 593 594 UnlockDisplay (dpy); 595 SyncHandle(); 596 return 1; 597} 598 599 600/* 601 * XmbufCreateStereoWindow - 602 * Creates a stereo window in the same way that XCreateWindow creates 603 * a mono window (in fact, use the same code, except for the request) 604 * and returns the left and right buffers that may be 605 */ 606Window XmbufCreateStereoWindow ( 607 Display *dpy, 608 Window parent, 609 int x, int y, 610 unsigned int width, unsigned int height, unsigned int border_width, 611 int depth, 612 unsigned int class, 613 Visual *visual, 614 unsigned long valuemask, 615 XSetWindowAttributes *attr, 616 Multibuffer *leftp, Multibuffer *rightp) 617{ 618 XExtDisplayInfo *info = find_display (dpy); 619 Window wid; 620 register xMbufCreateStereoWindowReq *req; 621 622 MbufCheckExtension (dpy, info, None); 623 624 LockDisplay(dpy); 625 MbufGetReq(MbufCreateStereoWindow, req, info); 626 wid = req->wid = XAllocID(dpy); 627 req->parent = parent; 628 req->left = *leftp = XAllocID (dpy); 629 req->right = *rightp = XAllocID (dpy); 630 req->x = x; 631 req->y = y; 632 req->width = width; 633 req->height = height; 634 req->borderWidth = border_width; 635 req->depth = depth; 636 req->class = class; 637 if (visual == CopyFromParent) 638 req->visual = CopyFromParent; 639 else 640 req->visual = visual->visualid; 641 valuemask &= (CWBackPixmap|CWBackPixel|CWBorderPixmap| 642 CWBorderPixel|CWBitGravity|CWWinGravity| 643 CWBackingStore|CWBackingPlanes|CWBackingPixel| 644 CWOverrideRedirect|CWSaveUnder|CWEventMask| 645 CWDontPropagate|CWColormap|CWCursor); 646 if ((req->mask = valuemask)) { 647 unsigned long values[32]; 648 register unsigned long *value = values; 649 unsigned int nvalues; 650 651 if (valuemask & CWBackPixmap) 652 *value++ = attr->background_pixmap; 653 if (valuemask & CWBackPixel) 654 *value++ = attr->background_pixel; 655 if (valuemask & CWBorderPixmap) 656 *value++ = attr->border_pixmap; 657 if (valuemask & CWBorderPixel) 658 *value++ = attr->border_pixel; 659 if (valuemask & CWBitGravity) 660 *value++ = attr->bit_gravity; 661 if (valuemask & CWWinGravity) 662 *value++ = attr->win_gravity; 663 if (valuemask & CWBackingStore) 664 *value++ = attr->backing_store; 665 if (valuemask & CWBackingPlanes) 666 *value++ = attr->backing_planes; 667 if (valuemask & CWBackingPixel) 668 *value++ = attr->backing_pixel; 669 if (valuemask & CWOverrideRedirect) 670 *value++ = attr->override_redirect; 671 if (valuemask & CWSaveUnder) 672 *value++ = attr->save_under; 673 if (valuemask & CWEventMask) 674 *value++ = attr->event_mask; 675 if (valuemask & CWDontPropagate) 676 *value++ = attr->do_not_propagate_mask; 677 if (valuemask & CWColormap) 678 *value++ = attr->colormap; 679 if (valuemask & CWCursor) 680 *value++ = attr->cursor; 681 req->length += (nvalues = value - values); 682 683 nvalues <<= 2; /* watch out for macros... */ 684 Data32 (dpy, (long *) values, (long)nvalues); 685 } 686 UnlockDisplay(dpy); 687 SyncHandle(); 688 return wid; 689} 690 691void XmbufClearBufferArea ( 692 Display *dpy, 693 Multibuffer buffer, 694 int x, int y, 695 unsigned int width, unsigned int height, 696 Bool exposures) 697{ 698 XExtDisplayInfo *info = find_display (dpy); 699 register xMbufClearImageBufferAreaReq *req; 700 701 MbufSimpleCheckExtension (dpy, info); 702 703 LockDisplay (dpy); 704 MbufGetReq (MbufClearImageBufferArea, req, info); 705 req->buffer = buffer; 706 req->x = x; 707 req->y = y; 708 req->width = width; 709 req->height = height; 710 req->exposures = exposures; 711 UnlockDisplay (dpy); 712 SyncHandle(); 713} 714 715