#define	PRIVATE_GL_HEADERS /* force ARB_MULTITEXTURE - enabled GL header */
#include <v_lib.h>

#ifdef	HAVE_GL_1_3

#define	vglActiveTextureARB	glActiveTexture
#define	vglMultiTexCoord2fARB glMultiTexCoord2f

/*
 * GL_TEXTUREx_ARB and GL_TEXTUREx are the same.
 */

#else

PFNGLACTIVETEXTUREARBPROC	vglActiveTextureARB = NULL;
PFNGLMULTITEXCOORD2FARBPROC	vglMultiTexCoord2fARB = NULL;

#endif

void upload()
{
	static GLfloat tex[] = {
		1,.5f,1,.6f,
		.3f,1,.2f,1,
		1,.2f,1,.3f,
		.6f,1,.5f,1
	};
	glTexImage2D(GL_TEXTURE_2D,0,1,4,4,0,GL_LUMINANCE,GL_FLOAT,tex);
	glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
}

GLuint quad;

vboolean init()
{
	if(LIBV_INVALID_HANDLE ==
		vglCreateWindow("Multitexture: separate texture matrices",0,0,512,512))
		return false;

#ifndef HAVE_GL_1_3

	vglQueryExtension("glActiveTextureARB",(void**)&vglActiveTextureARB);
	vglQueryExtension("glMultiTexCoord2fARB",(void**)&vglMultiTexCoord2fARB);

	if(!vglActiveTextureARB || !vglMultiTexCoord2fARB)
	{
		conlPrintf(LOG_ERROR,"This demo requires GL_ARB_MULTITEXTURE.\n");
		return false;
	}

#endif

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-100,100,-100,100,-100,100);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	vglActiveTextureARB(GL_TEXTURE0_ARB);
	upload();
	glEnable(GL_TEXTURE_2D);
	vglActiveTextureARB(GL_TEXTURE1_ARB);
	upload();
	glEnable(GL_TEXTURE_2D);

	quad = glGenLists(1);
	glNewList(quad,GL_COMPILE);
		glColor3f(0.95f,0.8f,1);
		glBegin(GL_QUADS);
			/* Note: the texcoords are _idential_ */
			vglMultiTexCoord2fARB(GL_TEXTURE0_ARB,-1,-1);
			vglMultiTexCoord2fARB(GL_TEXTURE1_ARB,-1,-1);
			glVertex2f(80,80);
			vglMultiTexCoord2fARB(GL_TEXTURE0_ARB,1,-1);
			vglMultiTexCoord2fARB(GL_TEXTURE1_ARB,1,-1);
			glVertex2f(-80,80);
			vglMultiTexCoord2fARB(GL_TEXTURE0_ARB,1,1);
			vglMultiTexCoord2fARB(GL_TEXTURE1_ARB,1,1);
			glVertex2f(-80,-80);
			vglMultiTexCoord2fARB(GL_TEXTURE0_ARB,-1,1);
			vglMultiTexCoord2fARB(GL_TEXTURE1_ARB,-1,1);
			glVertex2f(80,-80);
		glEnd();
	glEndList();

	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

	return true;
}

void draw()
{
	static GLfloat alpha = 0, scale_phase = 0;
	GLfloat sine, scale;

	sine = (GLfloat)(sin(scale_phase) * 0.5);

	glMatrixMode(GL_TEXTURE);
	
	vglActiveTextureARB(GL_TEXTURE0_ARB);
	glLoadIdentity();
	scale = 1 + sine;
	glScalef(scale,scale,scale);
	glRotatef(alpha,0,0,1);
	
	vglActiveTextureARB(GL_TEXTURE1_ARB);
	glLoadIdentity();
	scale = 1 - sine;
	glScalef(scale,scale,scale);
	glRotatef(-alpha / 5,0,0,1);

	glMatrixMode(GL_MODELVIEW);

	glClear(GL_COLOR_BUFFER_BIT);

	glCallList(quad);

	vglSwapBuffers();

	alpha += 1;
	scale_phase += ANGLE_1;
}

int main()
{
	input_record_t ev;

	logStartConsoleLog();
	logUpperLevel(LOG_TRACE);
	
	if(!init())
		return -1;

	for(;;)
	{
		while(vglPending())
		{
			vglNextEvent(&ev);
			if(ev.event == ev_key_down)
				goto outer_break;
		}
		draw();
	}
outer_break:;

	glDeleteLists(quad,1);
	vglDestroyWindow(vglGetCurrentWindow());
	
	return 0;
}
