#ifndef n_glTexture_H
#define n_glTexture_H

/*
 *
 * nucleo/gl/texture/glTexture.H --
 *
 * Copyright (C) Nicolas Roussel
 *
 * See the file LICENSE for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
*/

#include <nucleo/gl/texture/glTextureTile.H>

#ifdef __APPLE__
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <list>
#include <map>

namespace nucleo {

  // ------------------------------------------------------------------

  class glTexture {

  private:

    Image memoryholder ;                 // image buffer holder
    unsigned int width, height ;         // dimensions of the textured image

    std::list<glTextureTile *> tiles ;

    static GLUtesselator *tesselator ;

  public:

    glTextureTile::trePolicy trePolicy ; // should tiles use NPOT extensions? (FIRST_CHOICE)
    unsigned int tileSize ;              // box size of each tile (512)
    GLint minFilter, magFilter ;         // filters used by the tiles (GL_LINEAR)
    bool generateMipmaps ;               // should we try to generate mipmaps? (yes)
    bool useClientStorage ;              // should we use client storage extensions? (yes)

    glTexture(void) ;
    ~glTexture() ;

    void clear(void) ;
    bool load(Image *img) ;
    bool update(Image *img) ;

    // Displays the image in a box delimited by the specified
    // coordinates (assumes that top>bottom)
    void display(float left, float bottom, float right, float top,
			  bool preserveAspect=true) ;

    unsigned int getWidth(void) { return width ; }
    unsigned int getHeight(void) { return height ; }

    typedef enum {NW, N, NE, W, C, E, SW, S, SE} anchor ;

    // Returns the bounding box of the image with 0,0 at the specified
    // anchor
    void getBox(float *left, float *bottom, float *right, float *top, anchor a) ;

    // Displays the image with 0,0 at the specified anchor
    void display(anchor a) ;

    struct Point {
	 GLdouble coords[3] ;
	 Point(GLdouble x, GLdouble y, GLdouble z=0.0) {
	   coords[0] = x ;
	   coords[1] = y ;
	   coords[2] = z ;
	 }
    } ;

    typedef std::list<Point> ClipRegion ;

    void displayClipped(anchor a, ClipRegion *region) ;

  } ;

  // ------------------------------------------------------------------

}

#endif
