Display "ball.tif" "tiff" "rgba"RenderDotC has an open display driver architecture. It comes with several standard drivers for TIFF and framebuffer display. The user can extend this set by writing custom drivers as described in this document. Source code for a complete example display driver can be found in $RDCROOT/etc/d_zfile.c
#include <ndspy.h>Then it must implement these four entry points:
PtDspyError DspyImageOpen(PtDspyImageHandle *image,It may optionally implement this one also:
const char *drivername, const char *filename, int width, int height,
int paramCount, const UserParameter *parameters, int iFormatCount,
PtDspyDevFormat *format, PtFlagStuff *flagstuff)
PtDspyError DspyImageQuery(PtDspyImageHandle pvImage, PtDspyQueryType type,
int size, void *p)
PtDspyError DspyImageClose(PtDspyImageHandle pvImage)
PtDspyError DspyImageData(PtDspyImageHandle image, int xmin, int xmax_plusone,
int ymin, int ymax_plusone, int entrysize, const unsigned char *data)
PtDspyError DspyImageDelayClose(PtDspyImageHandle)Each of these functions returns an error code of type enum PtDspyError. Possible values are:
PkDspyErrorNone successful completionCompilation details depend up the platform.
PkDspyErrorNoMemory unable to allocate memory
PkDspyErrorUnsupported unsupported operation requested
PkDspyErrorBadParams bad parameters
PkDspyErrorNoResource no resource available, file not found...
PkDspyErrorUndefined no other error messages appropriate
SGI mips3: CC -I$RDCROOT/include -mips3 -n32 -O
-elf -shared d_log10.c -o d_log10.so
SGI mips4: CC -I$RDCROOT/include -mips4 -n32
-O -elf -shared d_log10.c -o d_log10.so
Visual C++: cl -I%RDCROOT%/include -LD d_log10.c
Borland C++: bcc32 -I%RDCROOT%/include -tWD d_log10.c
Linux: g++ -I$RDCROOT/include
-shared d_log10.c -o d_log10.so
BSD/OS: g++ -I$RDCROOT/include
-shared d_log10.c -o d_log10.so
The first argument is a pointer to an opaque pointer. The display driver may create local data of any size and store a pointer to it in *image. This is blind data as far as the renderer is concerned. It will blindly pass that pointer as the first argument to subsequent entry points in the display driver.
The name of the display driver, as it was given to RiDisplay(), is passed in the drivername argument. The file or display name from RiDisplay() is pased as filename. The width and height arguments usually match the values that were given to RiFormat(). However, if either or both equals 0, the display driver must provide a suitable default.
The parameters array contains paramCount user parameters. The UserParameter structure is defined in ndspy.h as follows:
typedef struct uparam {where name and value are a token-value pair. A character, vtype, represents the type of data stored in value and is interpreted as:
RtToken name;
char vtype, vcount;
#ifdef __BORLANDC__
char pad1, pad2; /* Waste space for Visual C++ compatibility */
#endif
RtPointer value;
int nbytes;
} UserParameter;
'i' IntegerSince value can be an array of values, vcount represents the number of elements in that array. The total size of the data pointed to by value is nbytes. When DspyImageOpen() returns, the renderer is free to delete the array pointed to by value. Therefore, the display driver should make a local copy if necessary.
'f' Floating point
's' String
The following user parameters are predefined by RenderDotC:
name | vtype | vcount | purpose |
NP | 'f' | 16 | World to NDC transformation matrix |
Nl | 'f' | 16 | World to camera transformation matrix |
near | 'f' | 1 | Near clipping plane |
far | 'f' | 1 | Far clipping plane |
origin | 'i' | 2 | Origin of crop window within full image |
OriginalSize | 'i' | 2 | Size of full window (not crop window) |
PixelAspectRatio | 'f' | 1 | Aspect ratio from RiFormat (or default if -1) |
Software | 's' | 1 | Name of renderer |
HostComputer | 's' | 1 | Name of computer rendererd on |
Additional user parameters may be passed in the token-value list of the Display command.
After user parameters comes the format of the data that will be sent to the display driver. The number of color channels to be sent is iFormatCount. The format array contains iFormatCount entries, one for each channel. The PtDspyDevFormat structure is defined in ndspy.h as follows:
typedef struct {The name field will be one of "r", "g", "b", "a", or "z". The other field, type, may be any of the following:
char *name;
unsigned type;
} PtDspyDevFormat;
PkDspyNoneThe display driver may rearrange the entries in format to receive the data in a more convenient order. However, the name fields must still point to the original strings as passed in from the renderer. The display driver may also change type to reflect what type of data it can handle. For example, a framebuffer display driver generally can't display more than 8 bits per color channel. Setting type to PkDspyUnsigned8 will cause RenderDotC to rescale the quantization parameters and deliver unsigned 8 bit data to the driver.
PkDspyFloat32
PkDspyUnsigned32
PkDspySigned32
PkDspyUnsigned16
PkDspySigned16
PkDspyUnsigned8
PkDspySigned8
The final argument is flagstuff. The renderer passes in 0 and the display driver can set various bits (using bitwise OR) to indicate how it wants the data. Available flags include:
PkDspyFlagsWantsScanLineOrder Requests that data be sent in sequential, not random, order
PkDspyFlagsWantsEmptyBuckets If a bucket is empty, send it anyway with all black pixels
PkDspyFlagsWantsNullEmptyBuckets If a bucket is empty, call DspyImageData with data = NULL
The renderer may call DspyImageQuery() to get additional information from the display driver. The first argument, pvImage, is either a handle returned by DspyImageOpen() or a NULL pointer. The second argument represents the type of query that the renderer is making. It can be one of the following:
PkSizeQuery What are the width, height, and aspect ratio?The renderer passes in a pointer p that addresses at least size bytes. The display driver then copies the requested data into p. Each query type has its own data structure, defined in ndspy.h:
PkOverwriteQuery Does the display driver overwrite the named file?
typedef struct {and:
PtDspyUnsigned32 width;
PtDspyUnsigned32 height;
PtDspyFloat32 aspectRatio;
} PtDspySizeInfo;
typedef struct {A complete implementation of DspyImageQuery usually looks like this:
PtDspyUnsigned8 overwrite; Non-zero if display driver overwrites named file
PtDspyUnsigned8 interactive; Not used
} PtDspyOverwriteInfo;
PtDspyError DspyImageQuery(PtDspyImageHandle pvImage,
PtDspyQueryType querytype, int datalen, void *data)
{
MyImageType image = (MyImageType)pvImage;
PtDspyOverwriteInfo overwriteInfo;
PtDspySizeInfo sizeInfo;if (datalen <= 0 || !data)
return PkDspyErrorBadParams;switch (querytype) {
case PkOverwriteQuery:
if (datalen > sizeof(overwriteInfo))
datalen = sizeof(overwriteInfo);
overwriteInfo.overwrite = 1;
overwriteInfo.interactive = 0;
memcpy(data, &overwriteInfo, datalen);
break;
case PkSizeQuery:
if (datalen > sizeof(sizeInfo))
datalen = sizeof(sizeInfo);
if (image) {
if (!image->width || !image->height) {
image->width = 640;
image->height = 480;
}
sizeInfo.width = image->width;
sizeInfo.height = image->height;
sizeInfo.aspectRatio = 1.0f;
}
else {
sizeInfo.width = 640;
sizeInfo.height = 480;
sizeInfo.aspectRatio = 1.0f;
}
memcpy(data, &sizeInfo, datalen);
break;
default:
return PkDspyErrorUnsupported;
}return PkDspyErrorNone;
}
This function closes the output and frees the resources pointed to by pvImage.
DspyImageData() should output a rectangle of pixels with upper-left corner at (xmin, ymin), width xmax_plusone - xmax, and height ymax_plusone - ymax. The pixels to be output are passed in data in row-major order. Each pixel is entrysize bytes.
If this optional function is present in a display driver, the renderer will start a separate thread and call it instead of DspyImageClose(). This allows the renderer to exit or continue with another frame while the display driver continues to run. It is appropriate for drivers that render to a display.
PtDspyError DspyFindStringInParamList(const char *string, char **result,
int n, const UserParameter *p)
{
int i;
for (i = 0; i < n; i++, p++)
if (p->vtype == 's'
&&
p->name[0] == string[0] &&
strcmp(p->name, string) == 0) {
*result = *(char **)p->value;
return PkDspyErrorNone;
}
return PkDspyErrorNoResource;
}
PtDspyError DspyFindMatrixInParamList(const char *string, float
*result,
int n, const UserParameter *p)
{
int i;
for (i = 0; i < n; i++, p++) {
if (p->vtype == 'f'
&&
p->vcount == 16 &&
p->name[0] == string[0] &&
strcmp(p->name, string) == 0) {
memcpy(result, (float *)p->value, 16 * sizeof(float));
return PkDspyErrorNone;
}
}
return PkDspyErrorNoResource;
}
PtDspyError DspyFindFloatInParamList(const char *string, float *result,
int n, const UserParameter *p)
{
int i;
for (i = 0; i < n; i++, p++) {
if ((p->vtype == 'f'
|| p->vtype == 'i') &&
p->name[0] == string[0] &&
strcmp(p->name, string) == 0) {
if (p->vtype == 'f') {
*result = *(float *)p->value;
return PkDspyErrorNone;
}
else {
*result = (float)(*(int *)p->value);
return PkDspyErrorNone;
}
}
}
return PkDspyErrorNoResource;
}
PtDspyError DspyFindFloatsInParamList(const char *string, int *resultCount,
float *result, int n, const UserParameter *p)
{
int i, j, *ip;
for (i = 0; i < n; i++, p++) {
if ((p->vtype == 'f'
|| p->vtype == 'i') &&
p->name[0] == string[0] &&
strcmp(p->name, string) == 0) {
if (p->vcount < *resultCount)
*resultCount = p->vcount;
if (p->vtype == 'f') {
memcpy(result, (float *)p->value, *resultCount * sizeof(float));
return PkDspyErrorNone;
}
else {
for (j = 0, ip = (int *)p->value; j < *resultCount; j++)
*result++ = (float)*ip++;
return PkDspyErrorNone;
}
}
}
return PkDspyErrorNoResource;
}
PtDspyError DspyFindIntInParamList(const char *string, int *result,
int n, const UserParameter *p)
{
int i;
for (i = 0; i < n; i++, p++) {
if ((p->vtype == 'i'
|| p->vtype == 'f') &&
p->name[0] == string[0] &&
strcmp(p->name, string) == 0) {
if (p->vtype == 'i') {
*result = *(int *)p->value;
return PkDspyErrorNone;
}
else {
*result = (int)(*(float *)p->value);
return PkDspyErrorNone;
}
}
}
return PkDspyErrorNoResource;
}
PtDspyError DspyFindIntsInParamList(const char *string, int *resultCount,
int *result, int n, const UserParameter *p)
{
int i, j;
float *fp;
for (i = 0; i < n; i++, p++) {
if ((p->vtype == 'i'
|| p->vtype == 'f') &&
p->name[0] == string[0] &&
strcmp(p->name, string) == 0) {
if (p->vcount < *resultCount)
*resultCount = p->vcount;
if (p->vtype == 'i') {
memcpy(result, (int *)p->value, *resultCount * sizeof(int));
return PkDspyErrorNone;
}
else {
for (j = 0, fp = (float *)p->value; j < *resultCount; j++)
*result++ = (int)*fp++;
return PkDspyErrorNone;
}
}
}
return PkDspyErrorNoResource;
}
PtDspyError DspyReorderFormatting(int formatCount, PtDspyDevFormat
*format,
int outFormatCount, const PtDspyDevFormat *outFormat)
{
PtDspyError ret = PkDspyErrorNone;
int i, j;
if (formatCount < outFormatCount)
outFormatCount = formatCount;
for (i = 0; i < outFormatCount; i++) {
for (j = i; j < formatCount;
j++) {
if (format[j].name[0] == outFormat[i].name[0] &&
strcmp(format[j].name, outFormat[i].name) == 0) {
if (i != j) {
PtDspyDevFormat tmpFormat;
tmpFormat = format[i];
format[i] = format[j];
format[j] = tmpFormat;
}
if (outFormat[i].type)
format[i].type = outFormat[i].type;
break;
}
}
if (j >= formatCount)
ret = PkDspyErrorBadParams;
}
return ret;
}
void DspyMemReverseCopy(unsigned char *t, const unsigned char *s,
int n)
{
int i;
s += n;
for (i = 0; i < n; i++)
*t++ = *--s;
}