 /* ex: set tabstop=4 expandtab: */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <values.h>
#include <GL/glx.h>
#include <GL/glu.h>
#include <string.h>
#include <X11/keysym.h>
#include <sys/ioctl.h>
#include <linux/videodev.h>
#include <sys/mman.h>
#include "gl/image.h"

#define WINDOW_WIDTH 512
#define WINDOW_HEIGHT 512


static int visual[] = {GLX_RGBA, 
    GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, 
    GLX_DOUBLEBUFFER,
    None};
Display       *display;
Window        window;


void openWindow(void)
    {
    XVisualInfo    *vi;
    Colormap        cmap;
    XSetWindowAttributes windowAttrib;
    GLXContext      cx;
    int             dummy;
    XSizeHints      sizeHints = {0};

    sizeHints.flags = USPosition | PSize;
    sizeHints.x = 0;
    sizeHints.y = 0;

     display = XOpenDisplay(NULL);
    if (display == NULL)
        { 
        fprintf(stderr,"Error: failed to open display\n");
        exit (1);
        }
      
    if (!glXQueryExtension(display, &dummy, &dummy))
        {
        fprintf(stderr,"X server has no OpenGL GLX extension");
        exit (1);
        }

    vi = glXChooseVisual(display, 0, visual);
    if (vi == NULL) 
        {
        fprintf(stderr,"Error: could not find visual\n");
        exit (1);
        }
   
    cx = glXCreateContext(display, vi, None, GL_TRUE);
    if (cx == NULL) 
        {
        fprintf(stderr,"could not create rendering context");
        exit (1);
        }

    cmap = XCreateColormap(display, RootWindow(display, vi->screen), 
                               vi->visual, AllocNone);
      
    windowAttrib.colormap = cmap;
    windowAttrib.border_pixel = 0;
    windowAttrib.event_mask = KeyPressMask;
    
    window = XCreateWindow(display, RootWindow(display, vi->screen), 
                              0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, vi->depth,
                  InputOutput, vi->visual, 
                  CWBorderPixel | CWColormap | CWEventMask, &windowAttrib);

    XSetStandardProperties(display, window, NULL, NULL, None, NULL, 0, &sizeHints); 
    XSetWMNormalHints( display, window, &sizeHints );

    glXMakeCurrent(display, window, cx);

    XMapWindow(display, window);
    XPending(display);   
    }


void initDraw(void)
    {
     glClearColor(0., 0., 0., 0.); 
    glDrawBuffer(GL_BACK);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-0.5,WINDOW_WIDTH-0.5,-0.5,WINDOW_HEIGHT-0.5,-1.0,1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glEnable(GL_TEXTURE_2D);
    }


#define MAX_TEX_WIDTH 1024
#define MAX_TEX_HEIGHT 1024

unsigned short img_rbuf[MAX_TEX_WIDTH], img_gbuf[MAX_TEX_WIDTH], img_bbuf[MAX_TEX_WIDTH];

void readImage(char *filename,int *xdim,int *ydim,unsigned char *image)
    {
    IMAGE *imagefp;
    int x,y;
    unsigned char *p;
    if ((imagefp=iopen(filename,"r")) == NULL)
        {
        fprintf(stderr,"createTexture: can't open input file %s\n",
            filename);
        exit(1);
        }
    if ((imagefp->xsize > MAX_TEX_WIDTH) || (imagefp->ysize > MAX_TEX_HEIGHT))
        {
        fprintf(stderr,"ERROR: image %s is %dx%d pixels; maximum supported "
            "size is %dx%d\n",filename,imagefp->xsize,imagefp->ysize,
            MAX_TEX_WIDTH,MAX_TEX_HEIGHT);
        *xdim = 1;
        *ydim = 1;
        return;
        }
    *xdim = imagefp->xsize;
    *ydim = imagefp->ysize;
    for (y=0, p=image; y < imagefp->ysize; y++)
        {
        getrow(imagefp,img_rbuf,y,0);
        getrow(imagefp,img_gbuf,y,1);
        getrow(imagefp,img_bbuf,y,2);
        for (x=0; x<imagefp->xsize; x++)
            {
            *p++ = img_rbuf[x];
            *p++ = img_gbuf[x];
            *p++ = img_bbuf[x];
            }
        }
    iclose(imagefp);
    }


int texid;
unsigned char *tex_imagedata;
int tex_xdim, tex_ydim;

void initTexture(void)
    {
    glGenTextures(1,&texid);
    tex_imagedata = (unsigned char *) malloc(MAX_TEX_WIDTH * MAX_TEX_HEIGHT * sizeof(unsigned long));
    }


void createTexture(char *filename)
    {
    readImage(filename,&tex_xdim,&tex_ydim,tex_imagedata);
    glBindTexture(GL_TEXTURE_2D,texid);
    glTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB_ARB,tex_xdim,tex_ydim,0,
            GL_RGB, GL_UNSIGNED_BYTE, tex_imagedata);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
    }


void drawTexImage(void)
    {
    glColor3f(1.0, 1.0, 1.0);
    glBindTexture(GL_TEXTURE_2D, texid);
    glBegin(GL_QUADS);
     glTexCoord2i(0,0);
     glVertex2i(0, 0);
     glTexCoord2i(1,0);
     glVertex2i(WINDOW_WIDTH, 0);
     glTexCoord2i(1,1);
     glVertex2i(WINDOW_WIDTH, WINDOW_HEIGHT);
     glTexCoord2i(0,1);
     glVertex2i(0, WINDOW_HEIGHT);
    glEnd();
    }


void saveCompressedTexture(char *filename)
    {
    static int fd = -1;
    GLint compressed, internalFormat, compressedSize;
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, &compressed);
    if (compressed == GL_TRUE)
        {
        unsigned char * img;
        glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT,
                     &internalFormat);
        glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
                GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressedSize);
        printf("%s: size = %d   format = %d\n",filename, compressedSize, internalFormat);
        if (fd < 0)
            fd = creat(filename,0644);
        if (fd < 0)
            {
            perror(filename);
            return;
            }
        img = (unsigned char *)malloc(compressedSize * sizeof(unsigned char));
        glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, img);
        write(fd, &internalFormat, sizeof(internalFormat));
        write(fd, &tex_xdim, sizeof(tex_xdim));
        write(fd, &tex_ydim, sizeof(tex_ydim));
        write(fd, &compressedSize, sizeof(compressedSize));
        write(fd, img, compressedSize);
        free(img);
        }
    else
         printf("compression for %s failed\n",filename);
    }


int main(int argc, char* argv[])
    {
    int i;
    openWindow();
    initTexture();
    for (i=1; i < argc; i++)
        {
        initDraw();
        createTexture(argv[i]);
        saveCompressedTexture("movie.ctex");
        drawTexImage();
        glXSwapBuffers(display, window);
        }
    }

