/************************************************************************
 * exdisplay.h -- routines for providing Display interfaces for 
 *              Exluna programs.
 *
 * (c) Copyright 2001 Exluna, Inc.  All rights reserved.
 *
 * $Revision: 1.11 $
 ************************************************************************/

#ifndef EXDISPLAY_H
#define EXDISPLAY_H


/*
 * In Windows, routines in a DLL that are visible to the main program
 * must be tagged with a special code.  This is not necessary in Unix.
 * We therefore define the symbol EXPORT that does the right magic
 * in either case.  Make sure that you use EXPORT to declare any routines
 * that must be exported from the DSO/DLL.
 */
#ifndef EXPORT
# ifdef _WIN32
#   define EXPORT __declspec(dllexport)
# else
#   define EXPORT
# endif
#endif



/* NOTE - In addition to subclassing ExDisplay, you also need to provide 
 *  two "C" linkable function:
 *      EXPORT ExDisplay *CreateDisplay (int, const Parameter *);
 *      EXPORT int DisplayVersion (void);
 */

#define EX_DISPLAY_VERSION 2

class ExDisplay {
public:
    enum Type {
	TYPE_UNKNOWN = 0,
	TYPE_FLOAT,
	TYPE_INT,
	TYPE_STRING,
    };
    struct Parameter {
	const char *token;
	Type type;
	int numElements; /* How many things of 'type' are there ? */
	const void *value;
    };
    struct PixelPacket {
	int x0, y0;
	int x1, y1;
	int pixelStride;
	int rowStride;
	const float *data;
    };
    
    EXPORT ExDisplay ();
    virtual EXPORT ~ExDisplay ();

    // Do we need data in scanline order ?
    virtual bool needsScanline () = 0;
    
    // Can we call 'start' multiple times ?
    virtual bool canRedraw () = 0;

    // Do we want to receive messages from the renderer?  Default is 
    // to just return false.
    EXPORT virtual bool wantMessages ();
    
    // Actually open the file/image.  Return true if no error occurred.
    virtual bool open (const char *name,
		       int numChannels, const char **channelNames,
		       int xRes, int yRes,
		       int rxorigin, int ryorigin, 
		       int rxpixels, int rypixels, 
		       int nparams, const Parameter *params) = 0;
    
    // Begin the frame.  Return true if no error occurred.
    virtual bool start () = 0;

    // Accept pixel data.  Return true if no error occurred.
    virtual bool data (const PixelPacket &pixels) = 0;

    // Close the file, cleanup, we're done.  Return true if no error occurred.
    // NOTE - if canRedraw () is true, we might not really be "done-done"
    // ie we could call 'start ()' again.
    virtual bool finish () = 0;

    // Respond to a message sent from client to display server.
    // Return true if we understood and no error occurred, false if
    // it's a message we don't understand or an action we can't
    // perform.  Arguments are passed as token/value pairs, terminated
    // by a NULL (just like RiOption).  The default implementation of
    // this function is to ignore all messages and return false.
    EXPORT virtual bool messageToDisplayServer (const char *messagetype, ...);

    // NOTE = invgamma = 1.0/gamma.
    EXPORT static float exposure (float value, float gain, float invgamma);

    EXPORT static int quantize (float value, float zero, float one, 
			 float Min, float Max, float ditheramp); 

    // Conveninence to find a given token in the parameter list and
    // return it's value, NULL if not found.
    EXPORT static const void *findValue (const char *tok, int &index,
				  int nparams, const Parameter *params);
    // Even more specific: find only if it matches the type and numelements
    EXPORT static const void *findValue (const char *tok,
				  Type typeExpected, int numElementsExpected,
				  int &index,
				  int nparams, const Parameter *params);

    // Send a message back to the client.  Returns true if the client
    // understood and no error occurred, false if it was a message the
    // client didn't understand or an action it could not perform.
    // Arguments are passed as token/value pairs, terminated by a NULL
    // (just like RiOption).  Currently, the implementation ignores
    // all messages from the server and returns false.
    EXPORT bool messageToClient (const char *messagetype, ...);

    // The server can return an error message by calling this function
    EXPORT void error (const char *message);

    // The client can retrieve the last error message...
    EXPORT const char *lasterror (void) const { return errmsg; }
private:
    char *errmsg;
};


#endif /* EXDISPLAY_H */
