Initial commit
[xorg_rtime.git] / libXext-1.0.2 / src / XMultibuf.c
blob3e0049e92d58a8cf89c1f5dc756bff2e57acaeed
1 /*
2 * $Xorg: XMultibuf.c,v 1.6 2001/02/09 02:03:49 xorgcvs Exp $
4 Copyright 1989, 1998 The Open Group
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
26 * Authors: Jim Fulton, MIT X Consortium
28 /* $XFree86: xc/lib/Xext/XMultibuf.c,v 1.5 2001/12/14 19:55:00 dawes Exp $ */
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>
41 static XExtensionInfo _multibuf_info_data;
42 static XExtensionInfo *multibuf_info = &_multibuf_info_data;
43 static /* const */ char *multibuf_extension_name = MULTIBUFFER_PROTOCOL_NAME;
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)
51 /*****************************************************************************
52 * *
53 * private utility routines *
54 * *
55 *****************************************************************************/
58 * find_display - locate the display info block
60 static int close_display(Display *dpy, XExtCodes *codes);
61 static char *error_string(Display *dpy, int code, XExtCodes *codes, char *buf, int n);
62 static Bool wire_to_event(Display *dpy, XEvent *libevent, xEvent *netevent);
63 static Status event_to_wire(Display *dpy, XEvent *libevent, xEvent *netevent);
64 static /* 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 */
78 static /* const */ char *multibuf_error_list[] = {
79 "BadBuffer", /* MultibufferBadBuffer */
82 static XEXT_GENERATE_FIND_DISPLAY (find_display, multibuf_info,
83 multibuf_extension_name,
84 &multibuf_extension_hooks,
85 MultibufferNumberEvents, NULL)
87 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, multibuf_info)
89 static XEXT_GENERATE_ERROR_STRING (error_string, multibuf_extension_name,
90 MultibufferNumberErrors,
91 multibuf_error_list)
94 * wire_to_event - convert a wire event in network format to a C
95 * event structure
97 static Bool wire_to_event (Display *dpy, XEvent *libevent, xEvent *netevent)
99 XExtDisplayInfo *info = find_display (dpy);
101 MbufCheckExtension (dpy, info, False);
103 switch ((netevent->u.u.type & 0x7f) - info->codes->first_event) {
104 case MultibufferClobberNotify:
106 XmbufClobberNotifyEvent *ev;
107 xMbufClobberNotifyEvent *event;
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;
119 case MultibufferUpdateNotify:
121 XmbufUpdateNotifyEvent *ev;
122 xMbufUpdateNotifyEvent *event;
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;
134 return False;
139 * event_to_wire - convert a C event structure to a wire event in
140 * network format
142 static Status event_to_wire (Display *dpy, XEvent *libevent, xEvent *netevent)
144 XExtDisplayInfo *info = find_display (dpy);
146 MbufCheckExtension (dpy, info, 0);
148 switch ((libevent->type & 0x7f) - info->codes->first_event) {
149 case MultibufferClobberNotify:
151 XmbufClobberNotifyEvent *ev;
152 xMbufClobberNotifyEvent *event;
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;
162 case MultibufferUpdateNotify:
164 XmbufUpdateNotifyEvent *ev;
165 xMbufUpdateNotifyEvent *event;
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;
175 return 0;
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.
183 #define TALLOC(type,count) ((type *) Xmalloc ((unsigned) count * sizeof(type)))
185 static XmbufBufferInfo *read_buffer_info (Display *dpy, int nbufs)
187 xMbufBufferInfo *netbuf = TALLOC (xMbufBufferInfo, nbufs);
188 XmbufBufferInfo *bufinfo = NULL;
189 long netbytes = nbufs * SIZEOF(xMbufBufferInfo);
191 if (netbuf) {
192 _XRead (dpy, (char *) netbuf, netbytes);
194 bufinfo = TALLOC (XmbufBufferInfo, nbufs);
195 if (bufinfo) {
196 register XmbufBufferInfo *c;
197 register xMbufBufferInfo *net;
198 register int i;
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;
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;
213 if (nbytes > netbytes) nbytes = netbytes;
214 _XRead (dpy, dummy, nbytes);
215 netbytes -= nbytes;
219 return bufinfo;
222 #undef TALLOC
225 /*****************************************************************************
227 * Multibuffering/stereo public interfaces *
229 *****************************************************************************/
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.
243 Bool XmbufQueryExtension (
244 Display *dpy,
245 int *event_base_return, int *error_base_return)
247 XExtDisplayInfo *info = find_display (dpy);
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;
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.
264 Status XmbufGetVersion (
265 Display *dpy,
266 int *major_version_return, int *minor_version_return)
268 XExtDisplayInfo *info = find_display (dpy);
269 xMbufGetBufferVersionReply rep;
270 register xMbufGetBufferVersionReq *req;
272 MbufCheckExtension (dpy, info, 0);
274 LockDisplay (dpy);
275 MbufGetReq (MbufGetBufferVersion, req, info);
276 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
277 UnlockDisplay (dpy);
278 SyncHandle ();
279 return 0;
281 *major_version_return = rep.majorVersion;
282 *minor_version_return = rep.minorVersion;
283 UnlockDisplay (dpy);
285 SyncHandle ();
286 return 1;
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.
297 int XmbufCreateBuffers (
298 Display *dpy,
299 Window w,
300 int count,
301 int update_action, int update_hint,
302 Multibuffer *buffers)
304 XExtDisplayInfo *info = find_display (dpy);
305 xMbufCreateImageBuffersReply rep;
306 register xMbufCreateImageBuffersReq *req;
307 int result;
309 MbufCheckExtension (dpy, info, 0);
311 LockDisplay (dpy);
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;
326 result = rep.numberBuffer;
327 UnlockDisplay (dpy);
329 SyncHandle ();
330 return result;
335 * XmbufDestroyBuffers -
336 * Destroys the buffers associated with the given window.
338 void XmbufDestroyBuffers (Display *dpy, Window window)
340 XExtDisplayInfo *info = find_display (dpy);
341 register xMbufDestroyImageBuffersReq *req;
343 MbufSimpleCheckExtension (dpy, info);
345 LockDisplay (dpy);
346 MbufGetReq (MbufDestroyImageBuffers, req, info);
347 req->window = window;
348 UnlockDisplay (dpy);
349 SyncHandle ();
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 Matc
358 * error is generated.
360 void XmbufDisplayBuffers (
361 Display *dpy,
362 int count,
363 Multibuffer *buffers,
364 int min_delay, int max_delay)
366 XExtDisplayInfo *info = find_display (dpy);
367 register xMbufDisplayImageBuffersReq *req;
369 MbufSimpleCheckExtension (dpy, info);
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();
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.
389 Status XmbufGetWindowAttributes (
390 Display *dpy,
391 Window w,
392 XmbufWindowAttributes *attr)
394 XExtDisplayInfo *info = find_display (dpy);
395 register xMbufGetMBufferAttributesReq *req;
396 xMbufGetMBufferAttributesReply rep;
398 MbufCheckExtension (dpy, info, 0);
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;
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);
419 _XRead32 (dpy, (long *) attr->buffers, nbytes);
421 attr->displayed_index = rep.displayedBuffer;
422 attr->update_action = rep.updateAction;
423 attr->update_hint = rep.updateHint;
424 attr->window_mode = rep.windowMode;
426 UnlockDisplay (dpy);
427 SyncHandle();
428 return 1;
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.
437 void XmbufChangeWindowAttributes (
438 Display *dpy,
439 Window w,
440 unsigned long valuemask,
441 XmbufSetWindowAttributes *attr)
443 XExtDisplayInfo *info = find_display (dpy);
444 register xMbufSetMBufferAttributesReq *req;
446 MbufSimpleCheckExtension (dpy, info);
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;
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);
462 UnlockDisplay (dpy);
463 SyncHandle();
468 * XmbufGetBufferAttributes -
469 * Gets the attributes for the indicated buffer. Returns non-zero on
470 * success and zero if an error occurs.
472 Status XmbufGetBufferAttributes (
473 Display *dpy,
474 Multibuffer b,
475 XmbufBufferAttributes *attr)
477 XExtDisplayInfo *info = find_display (dpy);
478 register xMbufGetBufferAttributesReq *req;
479 xMbufGetBufferAttributesReply rep;
481 MbufCheckExtension (dpy, info, 0);
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;
491 attr->window = rep.window;
492 attr->event_mask = rep.eventMask;
493 attr->buffer_index = rep.bufferIndex;
494 attr->side = rep.side;
496 UnlockDisplay (dpy);
497 SyncHandle();
498 return 1;
503 * XmbufChangeBufferAttributes -
504 * Sets the attributes for the indicated buffer. This is currently
505 * limited to the event_mask.
507 void XmbufChangeBufferAttributes (
508 Display *dpy,
509 Multibuffer b,
510 unsigned long valuemask,
511 XmbufSetBufferAttributes *attr)
513 XExtDisplayInfo *info = find_display (dpy);
514 register xMbufSetBufferAttributesReq *req;
516 MbufSimpleCheckExtension (dpy, info);
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;
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);
532 UnlockDisplay (dpy);
533 SyncHandle();
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.
551 Status 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)
559 XExtDisplayInfo *info = find_display (dpy);
560 register xMbufGetBufferInfoReq *req;
561 xMbufGetBufferInfoReply rep;
562 int nmono, nstereo;
563 XmbufBufferInfo *minfo, *sinfo;
565 MbufCheckExtension (dpy, info, 0);
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;
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);
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;
589 *nmono_return = nmono;
590 *mono_info_return = minfo;
591 *nstereo_return = nstereo;
592 *stereo_info_return = sinfo;
594 UnlockDisplay (dpy);
595 SyncHandle();
596 return 1;
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
606 Window 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)
618 XExtDisplayInfo *info = find_display (dpy);
619 Window wid;
620 register xMbufCreateStereoWindowReq *req;
622 MbufCheckExtension (dpy, info, None);
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;
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);
683 nvalues <<= 2; /* watch out for macros... */
684 Data32 (dpy, (long *) values, (long)nvalues);
686 UnlockDisplay(dpy);
687 SyncHandle();
688 return wid;
691 void XmbufClearBufferArea (
692 Display *dpy,
693 Multibuffer buffer,
694 int x, int y,
695 unsigned int width, unsigned int height,
696 Bool exposures)
698 XExtDisplayInfo *info = find_display (dpy);
699 register xMbufClearImageBufferAreaReq *req;
701 MbufSimpleCheckExtension (dpy, info);
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();