#ifndef MMXNOW_H
#define MMXNOW_H

#include <inttypes.h>
/*
 *		General interface for mmxnow library
 *
 *  call mmxnow_create with flags - choose whatever implementation
 *  you wish to use (probably should match your CPU capabilities)
 */

#ifdef __cplusplus
extern "C" {
#endif
    enum
    {
	// shuld be in order of prefered usage
	MMXNOW_K7 = 1,
	MMXNOW_MMX = 2,
	MMXNOW_MMX2 = 4,
	MMXNOW_3DNOW = 8,
	MMXNOW_SSE = 16,
	MMXNOW_SSE2 = 32,
    };

    enum
    {
	MMXNOW_TAGEND,	      /* marks taglist end */

	MMXNOW_MEMCPY,	      /* for larger memory blocks */
	MMXNOW_MEMSET,

	/* image conversion methods */
	/* converts just few lines per call (usually just one)
         * depends on the convertor function and its context
	 * parameters -
	 *  struct { int w; uint8_t* dst[16]; uint8_t* src[16]; }
	 *
         * e.g. rgb conversion just w, dst[0] & src[0] would be used
         */

        /* planar YV12 */
	MMXNOW_YV12_TO_BGR15 = 1000,
	MMXNOW_YV12_TO_BGR16,
	MMXNOW_YV12_TO_BGR24,
	MMXNOW_YV12_TO_BGR32,

	MMXNOW_BGR15_TO_YV12,
	MMXNOW_BGR16_TO_YV12,
	MMXNOW_BGR24_TO_YV12,
	MMXNOW_BGR32_TO_YV12,

        /* packed YUY2 */
	MMXNOW_YUY2_TO_BGR15,
	MMXNOW_YUY2_TO_BGR16,
	MMXNOW_YUY2_TO_BGR24,
	MMXNOW_YUY2_TO_BGR32,

	MMXNOW_BGR15_TO_YUY2,
	MMXNOW_BGR16_TO_YUY2,
	MMXNOW_BGR24_TO_YUY2,
	MMXNOW_BGR32_TO_YUY2,

        /* 3 byte YUV */
	MMXNOW_BGR15_TO_YUV,
	MMXNOW_BGR16_TO_YUV,
	MMXNOW_BGR24_TO_YUV,
	MMXNOW_BGR32_TO_YUV,

	MMXNOW_YUV_TO_BGR15,
	MMXNOW_YUV_TO_BGR16,
	MMXNOW_YUV_TO_BGR24,
	MMXNOW_YUV_TO_BGR32,

        /* all RGB conversions */
	MMXNOW_BGR15_TO_BGR16,
	MMXNOW_BGR15_TO_BGR24,
	MMXNOW_BGR15_TO_BGR32,

	MMXNOW_BGR16_TO_BGR15,
	MMXNOW_BGR16_TO_BGR24,
	MMXNOW_BGR16_TO_BGR32,

	MMXNOW_BGR24_TO_BGR15,
	MMXNOW_BGR24_TO_BGR16,
	MMXNOW_BGR24_TO_BGR32,

	MMXNOW_BGR32_TO_BGR15,
	MMXNOW_BGR32_TO_BGR16,
	MMXNOW_BGR32_TO_BGR24,


	/* audio - proposition */
	MMXNOW_AUDIO_SOMETHING = 2000,
    };

    struct mmxnow_context_t;
    typedef struct mmxnow_context_t
    {
	/*
	 * address of function for given CPU flags
	 * data will be casted to the expected type
	 * user has to provide thread safety locking himself -
	 * or he could create new context for each thread
	 * but generally - its better to leave running only
	 * one MMX task - otherwice there is big speed penaly hit!
	 */
	int (*method)(struct mmxnow_context_t*);
	/* free static data data */
	int (*free)(struct mmxnow_context_t*);

	void* data;		/* data - paramaters for function */
	void* user;		/* private data for user - e.g. -store mutex */
	const char* name;	/* text name of method - for debugging */
	unsigned int flags;	/* copy of initialization CPU flags */
    } mmxnow_context_t;


    /*
     * only few calls here - so if should be simple to dlopen library in
     * runtime and use it if its available on the system
     */

    /*
     * get requested method - private context will be initialized when
     * necesseary
     */
    mmxnow_context_t* mmxnow_create(int method, unsigned int flags);

    /*
     * when function is no longer necessary - call delete to free all
     * allocated resources
     */
    void mmxnow_destroy(mmxnow_context_t* cntx);

    unsigned int mmxnow_detect(void); /* not implemented yet */

    /****  DATASTRUCTURES ****/

    /*
     * data structure used for image conversion
     * many fields might not be supported by various function
     */
    typedef struct
    {
	int width, height;	/* width of processed image */
	int x, y;
	uint8_t* plane[3];      /* Y U V */
	int stride[3];
        int format;
	int bpp;		/* bits per plane */
    } mmxnow_image_t;

    typedef struct { uint8_t r,g,b; } mmxnow_rgb_t;
    typedef struct { uint8_t y,cb,cr; } mmxnow_yuv_t;

    typedef struct
    {
	void* context;		/* private data structure */
	unsigned int supports;	/* flag of supported operation
				 * e.g - support rescale, flip,
				 * bit plane conversion,...
				 */
	mmxnow_image_t in;	/* input image */
	mmxnow_image_t out;	/* output image */

	int flip;		/* flip image during processing */
	int bottom_up;		/* process image from bottom */
	int reserved[20];
    } mmxnow_image_data_t;

#ifdef __cplusplus
}
#endif

#endif /* MMXNOW_H */
