Home | History | Annotate | Line # | Download | only in src
      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 
     45 static XExtensionInfo _dbe_info_data;
     46 static XExtensionInfo *dbe_info = &_dbe_info_data;
     47 static 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  */
     68 static int close_display(Display *dpy, XExtCodes *codes);
     69 static char *error_string(Display *dpy, int code, XExtCodes *codes,
     70 			  char *buf, int n);
     71 static 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 
     85 static const char *dbe_error_list[] = {
     86     "BadBuffer",			/* DbeBadBuffer */
     87 };
     88 
     89 static XEXT_GENERATE_FIND_DISPLAY (find_display, dbe_info,
     90 				   dbe_extension_name,
     91 				   &dbe_extension_hooks,
     92 				   DbeNumberEvents, NULL)
     93 
     94 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, dbe_info)
     95 
     96 static 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  */
    119 Status 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 
    165 XdbeBackBuffer 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  */
    197 Status 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  */
    224 Status 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  */
    265 Status 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  */
    285 Status 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  */
    318 XdbeScreenVisualInfo *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  */
    417 void 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  */
    436 XdbeBackBufferAttributes *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