#include "PEXlib.h"
#include "PEXlibint.h"
#include "pl_global.h"
#include <stdio.h>
int
PEXInitialize (display, info_return, length, error_string)
INPUT Display *display;
OUTPUT PEXExtensionInfo **info_return;
INPUT int length;
OUTPUT char *error_string;
{
pexGetExtensionInfoReq *req;
char *pBuf;
pexGetExtensionInfoReply rep;
PEXExtensionInfo *extInfo;
XExtCodes *pExtCodes;
PEXDisplayInfo *pexDisplayInfo;
int enumType, match, i;
PEXEnumTypeDesc *enumReturn;
unsigned long *numReturn;
char *string;
extern Status _PEXConvertMaxHitsEvent();
Bool _PEXConvertOCError();
void _PEXPrintOCError();
int _PEXCloseDisplay();
LockDisplay (display);
PEXGetDisplayInfo (display, pexDisplayInfo);
if (pexDisplayInfo)
{
*info_return = pexDisplayInfo->extInfo;
UnlockDisplay (display);
PEXSyncHandle (display);
return (0);
}
*info_return = NULL;
if ((pExtCodes = XInitExtension (display, "X3D-PEX")) == NULL)
{
UnlockDisplay (display);
PEXSyncHandle (display);
XGetErrorDatabaseText (display, "PEXlibMessage", "BadExtension",
"Could not initialize the PEX extension on the specified display",
error_string, length);
return (PEXBadExtension);
}
pexDisplayInfo = (PEXDisplayInfo *) Xmalloc (sizeof (PEXDisplayInfo));
if (!pexDisplayInfo)
{
UnlockDisplay (display);
PEXSyncHandle (display);
XGetErrorDatabaseText (display, "PEXlibMessage", "BadLocalAlloc",
"Could not allocate memory for PEXlib internal usage",
error_string, length);
return (PEXBadLocalAlloc);
}
PEXAddDisplayInfo (display, pexDisplayInfo);
pexDisplayInfo->extCodes = pExtCodes;
pexDisplayInfo->extOpcode = pExtCodes->major_opcode;
pexDisplayInfo->lastResID = 0;
pexDisplayInfo->lastReqType = -1;
pexDisplayInfo->lastReqNum = -1;
enumType = PEXETFloatFormat;
if (PEXGetEnumTypeInfo (display, DefaultRootWindow (display), 1,
&enumType, PEXETIndex, &numReturn, &enumReturn) == 0)
{
UnlockDisplay (display);
PEXSyncHandle (display);
XGetErrorDatabaseText (display, "PEXlibMessage", "GetEnumFailure",
"Implicit call to PEXGetEnumTypeInfo by PEXInitialize failed",
error_string, length);
PEXRemoveDisplayInfo (display, pexDisplayInfo);
return (PEXBadFloatConversion);
}
pexDisplayInfo->fpSupport = enumReturn;
pexDisplayInfo->fpCount = *numReturn;
for (i = match = 0; i < *numReturn; i++)
if (enumReturn[i].index == NATIVE_FP_FORMAT)
{
match = 1;
break;
}
if (enumReturn == NULL || *numReturn == 0)
{
UnlockDisplay (display);
PEXSyncHandle (display);
XGetErrorDatabaseText (display, "PEXlibMessage", "NoFloats",
"No floating point formats supported by server",
error_string, length);
PEXRemoveDisplayInfo (display, pexDisplayInfo);
return (PEXBadFloatConversion);
}
else if (match)
{
pexDisplayInfo->fpFormat = NATIVE_FP_FORMAT;
pexDisplayInfo->fpConvert = 0;
}
else
{
pexDisplayInfo->fpFormat = enumReturn[0].index;
pexDisplayInfo->fpConvert = 1;
}
Xfree ((char *) numReturn);
XESetWireToError (display, pExtCodes->first_error + BadPEXOutputCommand,
_PEXConvertOCError);
XESetPrintErrorValues (display, pExtCodes->extension, _PEXPrintOCError);
XESetWireToEvent (display, pExtCodes->first_event + PEXMaxHitsReached,
_PEXConvertMaxHitsEvent);
XESetCloseDisplay (display, pExtCodes->extension, _PEXCloseDisplay);
PEXGetReq (GetExtensionInfo, pBuf);
BEGIN_REQUEST_HEADER (GetExtensionInfo, pBuf, req);
PEXStoreReqHead (GetExtensionInfo, req);
req->clientProtocolMajor = PEX_PROTO_MAJOR;
req->clientProtocolMinor = PEX_PROTO_MINOR;
END_REQUEST_HEADER (GetExtensionInfo, pBuf, req);
if (_XReply (display, (xReply *)&rep, 0, xFalse) == 0)
{
UnlockDisplay (display);
PEXSyncHandle (display);
XGetErrorDatabaseText (display, "PEXlibMessage", "GetInfoFailure",
"Could not get PEX extension information",
error_string, length);
PEXRemoveDisplayInfo (display, pexDisplayInfo);
return (PEXBadExtension);
}
if (!(string = (char *) Xmalloc ((unsigned) (rep.lengthName + 1))))
{
UnlockDisplay (display);
PEXSyncHandle (display);
XGetErrorDatabaseText (display, "PEXlibMessage", "BadLocalAlloc",
"Could not allocate memory for PEXlib internal usage",
error_string, length);
PEXRemoveDisplayInfo (display, pexDisplayInfo);
return (PEXBadLocalAlloc);
}
_XReadPad (display, string, (long) (rep.lengthName));
string[rep.lengthName] = '\0';
UnlockDisplay (display);
PEXSyncHandle (display);
extInfo = *info_return = pexDisplayInfo->extInfo = (PEXExtensionInfo *)
Xmalloc (sizeof (PEXExtensionInfo));
if (!extInfo)
{
XGetErrorDatabaseText (display, "PEXlibMessage", "BadLocalAlloc",
"Could not allocate memory for PEXlib internal usage",
error_string, length);
PEXRemoveDisplayInfo (display, pexDisplayInfo);
return (PEXBadLocalAlloc);
}
extInfo->major_version = rep.majorVersion;
extInfo->minor_version = rep.minorVersion;
extInfo->release = rep.release;
extInfo->subset_info = rep.subsetInfo;
extInfo->vendor_name = string;
extInfo->major_opcode = pExtCodes->major_opcode;
extInfo->first_event = pExtCodes->first_event;
extInfo->first_error = pExtCodes->first_error;
if (rep.majorVersion == PEX_PROTO_MAJOR)
return (0);
else
{
char str[PEXErrorStringLength];
XGetErrorDatabaseText (display, "PEXlibMessage", "BadProtoVersion",
"Client speaks PEX %d.%d; Server speaks PEX %d.%d",
str, PEXErrorStringLength);
sprintf (error_string, str,
PEX_PROTO_MAJOR, PEX_PROTO_MINOR,
rep.majorVersion, rep.minorVersion);
PEXRemoveDisplayInfo (display, pexDisplayInfo);
return (PEXBadProtocolVersion);
}
}
PEXExtensionInfo *
PEXGetExtensionInfo (display)
INPUT Display *display;
{
PEXDisplayInfo *pexDisplayInfo;
PEXGetDisplayInfo (display, pexDisplayInfo);
return (pexDisplayInfo ? pexDisplayInfo->extInfo : NULL);
}
int
PEXGetProtocolFloatFormat (display)
INPUT Display *display;
{
PEXDisplayInfo *pexDisplayInfo;
PEXGetDisplayInfo (display, pexDisplayInfo);
return (pexDisplayInfo ? pexDisplayInfo->fpFormat : 0);
}
Status
PEXGetEnumTypeInfo (display, drawable, numEnumTypes, enumTypes,
itemMask, numReturn, enumInfoReturn)
INPUT Display *display;
INPUT Drawable drawable;
INPUT unsigned long numEnumTypes;
INPUT int *enumTypes;
INPUT unsigned long itemMask;
OUTPUT unsigned long **numReturn;
OUTPUT PEXEnumTypeDesc **enumInfoReturn;
{
register pexGetEnumTypeInfoReq *req;
char *pBuf;
pexGetEnumTypeInfoReply rep;
char *pstartrep;
PEXEnumTypeDesc *penum;
unsigned long *pcounts;
char *pstring;
int numDescs;
int totDescs;
int *srcEnumType;
unsigned int length;
int size;
int i, j;
LockDisplay (display);
size = numEnumTypes * SIZEOF (CARD16);
PEXGetReqExtra (GetEnumTypeInfo, size, pBuf);
BEGIN_REQUEST_HEADER (GetEnumTypeInfo, pBuf, req);
PEXStoreReqExtraHead (GetEnumTypeInfo, size, req);
req->drawable = drawable;
req->itemMask = itemMask;
req->numEnums = numEnumTypes;
END_REQUEST_HEADER (GetEnumTypeInfo, pBuf, req);
for (i = 0, srcEnumType = enumTypes; i < numEnumTypes; i++)
{
STORE_CARD16 (*srcEnumType, pBuf);
srcEnumType++;
}
if (_XReply (display, (xReply *)&rep, 0, xFalse) == 0)
{
UnlockDisplay (display);
PEXSyncHandle (display);
*numReturn = NULL;
*enumInfoReturn = NULL;
return (0);
}
if (rep.numLists < numEnumTypes)
{
UnlockDisplay (display);
PEXSyncHandle (display);
*numReturn = NULL;
*enumInfoReturn = NULL;
return (0);
}
XREAD_INTO_SCRATCH (display, pstartrep, rep.length << 2);
for (i = 0, totDescs = 0, pBuf = pstartrep; i < rep.numLists; i++)
{
EXTRACT_CARD32 (pBuf, numDescs);
totDescs += numDescs;
if (i == rep.numLists - 1)
break;
if (itemMask == PEXETIndex)
{
pBuf += PADDED_BYTES (numDescs * SIZEOF (INT16));
}
else if (itemMask == PEXETMnemonic)
{
for (j = 0; j < numDescs; j++)
{
GET_CARD16 (pBuf, length);
pBuf += PADDED_BYTES (SIZEOF (CARD16) + length);
}
}
else if (itemMask == PEXETAll)
{
for (j = 0; j < numDescs; j++)
{
pBuf += SIZEOF (INT16);
EXTRACT_CARD16 (pBuf, length);
pBuf += PADDED_BYTES (length);
}
}
}
if (itemMask == PEXETCounts)
*enumInfoReturn = NULL;
else
{
*enumInfoReturn = penum = (PEXEnumTypeDesc *)
Xmalloc ((unsigned) (totDescs * sizeof (PEXEnumTypeDesc)));
}
*numReturn = pcounts = (unsigned long *)
Xmalloc ((unsigned) (numEnumTypes * sizeof (unsigned long)));
for (i = 0, pBuf = pstartrep; i < rep.numLists; i++, pcounts++)
{
EXTRACT_CARD32 (pBuf, numDescs);
*pcounts = numDescs;
if (itemMask == PEXETIndex)
{
for (j = 0; j < numDescs; j++, penum++)
{
penum->descriptor = NULL;
EXTRACT_INT16 (pBuf, penum->index);
}
if (numDescs & 1)
pBuf += SIZEOF (INT16);
}
else if (itemMask == PEXETMnemonic)
{
for (j = 0; j < numDescs; j++, penum++)
{
penum->index = 0;
EXTRACT_CARD16 (pBuf, length);
penum->descriptor = pstring =
(char *) Xmalloc ((unsigned) (length + 1));
memcpy (pstring, pBuf, length);
pstring[length] = '\0';
pBuf += (PADDED_BYTES (SIZEOF (CARD16) + length) -
SIZEOF (CARD16));
}
}
else if (itemMask == PEXETAll)
{
for (j = 0; j < numDescs; j++, penum++)
{
EXTRACT_INT16 (pBuf, penum->index);
EXTRACT_CARD16 (pBuf, length);
penum->descriptor = pstring =
(char *) Xmalloc ((unsigned) (length + 1));
memcpy (pstring, pBuf, length);
pstring[length] = '\0';
pBuf += PADDED_BYTES (length);
}
}
}
FINISH_WITH_SCRATCH (display, pstartrep, rep.length << 2);
UnlockDisplay (display);
PEXSyncHandle (display);
return (1);
}
Status
PEXGetImpDepConstants (display, drawable, numNames, names, constantsReturn)
INPUT Display *display;
INPUT Drawable drawable;
INPUT unsigned long numNames;
INPUT unsigned short *names;
OUTPUT PEXImpDepConstant **constantsReturn;
{
register pexGetImpDepConstantsReq *req;
char *pBuf;
pexGetImpDepConstantsReply rep;
long size;
CARD32 *c32list;
float *flist;
int i;
int fpConvert;
int fpFormat;
LockDisplay (display);
size = numNames * SIZEOF (CARD16);
PEXGetReqExtra (GetImpDepConstants, size, pBuf);
BEGIN_REQUEST_HEADER (GetImpDepConstants, pBuf, req);
CHECK_FP (fpConvert, fpFormat);
PEXStoreFPReqExtraHead (GetImpDepConstants, fpFormat, size, req);
req->drawable = drawable;
req->numNames = numNames;
END_REQUEST_HEADER (GetImpDepConstants, pBuf, req);
STORE_LISTOF_CARD16 (numNames, names, pBuf);
if (_XReply (display, (xReply *)&rep, 0, xFalse) == 0)
{
UnlockDisplay (display);
PEXSyncHandle (display);
*constantsReturn = NULL;
return (0);
}
*constantsReturn = (PEXImpDepConstant *) Xmalloc (
(unsigned) (numNames * sizeof (PEXImpDepConstant)));
c32list = (CARD32 *) (*constantsReturn);
flist = (float *) (*constantsReturn);
if (!fpConvert)
{
XREAD_LISTOF_CARD32 (display, numNames, c32list);
}
else
{
for (i = 0; i < numNames; i++)
{
switch (names[i])
{
case PEXIDDitheringSupported:
case PEXIDMaxEdgeWidth:
case PEXIDMaxLineWidth:
case PEXIDMaxMarkerSize:
case PEXIDMaxModelClipPlanes:
case PEXIDMaxNameSetNames:
case PEXIDMaxNonAmbientLights:
case PEXIDMaxNURBOrder:
case PEXIDMaxTrimCurveOrder:
case PEXIDMinEdgeWidth:
case PEXIDMinLineWidth:
case PEXIDMinMarkerSize:
case PEXIDNominalEdgeWidth:
case PEXIDNominalLineWidth:
case PEXIDNominalMarkerSize:
case PEXIDNumSupportedEdgeWidths:
case PEXIDNumSupportedLineWidths:
case PEXIDNumSupportedMarkerSizes:
case PEXIDBestColorApprox:
case PEXIDTransparencySupported:
case PEXIDDoubleBufferingSupported:
case PEXIDMaxHitsEventSupported:
_XRead (display, (char *) &c32list[i], SIZEOF (CARD32));
break;
case PEXIDChromaticityRedU:
case PEXIDChromaticityRedV:
case PEXIDLuminanceRed:
case PEXIDChromaticityGreenU:
case PEXIDChromaticityGreenV:
case PEXIDLuminanceGreen:
case PEXIDChromaticityBlueU:
case PEXIDChromaticityBlueV:
case PEXIDLuminanceBlue:
case PEXIDChromaticityWhiteU:
case PEXIDChromaticityWhiteV:
case PEXIDLuminanceWhite:
{
char temp[4];
_XRead (display, temp, SIZEOF (float));
FP_CONVERT_NTOH_BUFF (temp, flist[i], fpFormat);
}
}
}
}
UnlockDisplay (display);
PEXSyncHandle (display);
return (1);
}
Status
PEXMatchRenderingTargets (display, drawable, depth, type, visual,
maxTargets, numTargets, targets)
INPUT Display *display;
INPUT Drawable drawable;
INPUT int depth;
INPUT int type;
INPUT Visual *visual;
INPUT unsigned long maxTargets;
OUTPUT unsigned long *numTargets;
OUTPUT PEXRenderingTarget **targets;
{
register pexMatchRenderingTargetsReq *req;
char *pBuf;
pexMatchRenderingTargetsReply rep;
PEXRenderingTarget *info;
pexRendererTarget *matchRec;
int i;
LockDisplay (display);
PEXGetReq (MatchRenderingTargets, pBuf);
BEGIN_REQUEST_HEADER (MatchRenderingTargets, pBuf, req);
PEXStoreReqHead (MatchRenderingTargets, req);
req->drawable = drawable;
req->depth = depth;
req->type = type;
req->visualID = visual ? visual->visualid : 0;
req->maxTriplets = maxTargets;
END_REQUEST_HEADER (MatchRenderingTargets, pBuf, req);
if (_XReply (display, (xReply *)&rep, 0, xFalse) == 0)
{
UnlockDisplay (display);
PEXSyncHandle (display);
*numTargets = 0;
*targets = NULL;
return (0);
}
*numTargets = rep.length / 2;
XREAD_INTO_SCRATCH (display, pBuf, rep.length << 2);
matchRec = (pexRendererTarget *) pBuf;
*targets = info = (PEXRenderingTarget *) Xmalloc (
(unsigned) (*numTargets * sizeof (PEXRenderingTarget)));
for (i = 0; i < *numTargets; i++)
{
info->depth = matchRec->depth;
info->type = matchRec->type;
info->visual = _XVIDtoVisual (display, matchRec->visualID);
info++;
matchRec++;
}
FINISH_WITH_SCRATCH (display, pBuf, rep.length << 2);
UnlockDisplay (display);
PEXSyncHandle (display);
return (1);
}
Bool
_PEXConvertOCError (display, client_error, wire_error)
INPUT Display *display;
OUTPUT XErrorEvent *client_error;
INPUT xError *wire_error;
{
PEXOCErrorEvent *client = (PEXOCErrorEvent *) client_error;
pexOutputCommandError *wire = (pexOutputCommandError *) wire_error;
client->op_code = wire->opcode;
client->count = wire->numCommands;
return (True);
}
void
_PEXPrintOCError (display, error, fp)
INPUT Display *display;
INPUT XErrorEvent *error;
#if NeedFunctionPrototypes
INPUT void *fp;
#else
INPUT FILE *fp;
#endif
{
PEXDisplayInfo *pexDisplayInfo;
char opcode_message[PEXErrorStringLength];
char oc_count_message[PEXErrorStringLength];
PEXGetDisplayInfo (display, pexDisplayInfo);
if (error->error_code ==
pexDisplayInfo->extCodes->first_error + BadPEXOutputCommand)
{
PEXOCErrorEvent *oc_error = (PEXOCErrorEvent *) error;
XGetErrorDatabaseText (display,
"PEXlibMessage", "OCErrorOpCode",
"Opcode of failed output command : %d\n",
opcode_message, PEXErrorStringLength);
XGetErrorDatabaseText (display,
"PEXlibMessage", "OCErrorCount",
"Number of output commands processed before error : %d\n",
oc_count_message, PEXErrorStringLength);
fprintf (fp, " ");
fprintf (fp, opcode_message, oc_error->op_code);
fprintf (fp, " ");
fprintf (fp, oc_count_message, oc_error->count);
}
}
int
_PEXCloseDisplay (display, codes)
INPUT Display *display;
INPUT XExtCodes *codes;
{
PEXDisplayInfo *pexDisplayInfo;
PEXRemoveDisplayInfo (display, pexDisplayInfo);
if (pexDisplayInfo == NULL)
return (0);
Xfree ((char *) (pexDisplayInfo->extInfo->vendor_name));
Xfree ((char *) (pexDisplayInfo->extInfo));
Xfree ((char *) (pexDisplayInfo->fpSupport));
Xfree ((char *) pexDisplayInfo);
if (PEXPickCache && !PEXPickCacheInUse)
Xfree ((char *) PEXPickCache);
return (1);
}