[BACK]Return to texsubimage.c CVS log [TXT][DIR] Up to [Development] / projects / ogl-sample / main / gfx / samples / extensions

File: [Development] / projects / ogl-sample / main / gfx / samples / extensions / texsubimage.c (download)

Revision 1.2, Wed Apr 5 06:43:44 2000 UTC (17 years, 6 months ago) by ljp
Branch: MAIN
CVS Tags: tested_with_xf86_3_3, HEAD
Changes since 1.1: +1 -1 lines

Change license version to 1.1.

/*
** License Applicability. Except to the extent portions of this file are
** made subject to an alternative license as permitted in the SGI Free
** Software License B, Version 1.1 (the "License"), the contents of this
** file are subject only to the provisions of the License. You may not use
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
** 
** http://oss.sgi.com/projects/FreeB
** 
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
** 
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
** 
** Additional Notice Provisions: The application programming interfaces
** established by SGI in conjunction with the Original Code are The
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
** Window System(R) (Version 1.3), released October 19, 1998. This software
** was created using the OpenGL(R) version 1.2.1 Sample Implementation
** published by SGI, but has not been independently verified as being
** compliant with the OpenGL(R) version 1.2.1 Specification.
**
** $Date$ $Revision$
*/
/*
** cc -o texsubimage texsubimage.c -lglut -lGLU -lGL -lXext -lX11 -lrgb
**
** Demonstrates how to replace a portion of a texture using glTexSubImage.
**
** Requires the GL_EXT_subtexture extension.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/rgb.h>

#if defined(GL_EXT_subtexture)

char *filename = NULL;
int winX = 0, winY = 0;
int winWidth = 300, winHeight = 300;
float curX = 0.0, curY = 0.0;
GLboolean doubleBuffered = GL_FALSE;
int *visualAttr = NULL;
GLboolean useLinear = GL_FALSE;
GLboolean useDisplayList = GL_FALSE;
GLboolean buttonPressed = GL_FALSE;
GLboolean needsRedraw = GL_TRUE;
int baseWidth = 256, baseHeight = 256;
GLubyte *baseImage = NULL;
int imageWidth = 0, imageHeight = 0;
GLubyte *imageData = NULL;

void
imgLoad(char *inFilename, int *outW, int *outH, GLubyte **outImg)
{
    RGBImageRec *rgbimage;

    if ((rgbimage = rgbImageLoad(inFilename)) == NULL) {
	fprintf(stderr, "unable to read %s\n", inFilename);
	exit(EXIT_FAILURE);
    }

    *outW = rgbimage->sizeX;
    *outH = rgbimage->sizeY;
    *outImg = rgbimage->data;
}

void
checkErrors(void)
{
    GLenum error;
    while ((error = glGetError()) != GL_NO_ERROR) {
	fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error));
    }
}

void
keyboard(unsigned char c, int x, int y)
{
    switch (c) {
      case 'l':
	useLinear = !useLinear;
	break;
      case 'd':
	useDisplayList = !useDisplayList;
	break;
      default:
	break;
    }
    glutPostRedisplay();
}

void
mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
	buttonPressed = GL_TRUE;
	curX = (float) x / winWidth;
	curY = (float) (winHeight - y) / winHeight;
    }
    if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
	buttonPressed = GL_FALSE;
	glutPostRedisplay();
    }
}

void
motion(int x, int y)
{
    if (buttonPressed) {
	curX = (float) x / winWidth;
	curY = (float) (winHeight - y) / winHeight;
	glutPostRedisplay();
    }
}

void
reshape(int w, int h)
{
    winWidth = w;
    winHeight = h;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, winWidth, 0, winHeight, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glViewport(0, 0, winWidth, winHeight);
    glutPostRedisplay();
}

void
display(void)
{
    int subX = (int) (curX * baseWidth);
    int subY = (int) (curY * baseHeight);
    int subWidth = imageWidth;
    int subHeight = imageHeight;

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    if (useLinear) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    } else {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    }
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    if (baseImage == NULL) {
	int i, j;

	baseImage = (GLubyte *) calloc(baseHeight, 4*baseWidth);

	for (i=0; i<baseHeight; ++i) {
	    GLubyte *p = baseImage + 4*baseWidth*i;
	    for (j=0; j<baseHeight; ++j) {
		if ((i ^ j) & 4) {
		    p[0] = 0x10;
		    p[1] = 0x10;
		    p[2] = 0x10;
		    p[3] = 0x10;
		} else {
		    p[0] = 0x20;
		    p[1] = 0x20;
		    p[2] = 0x20;
		    p[3] = 0x20;
		}
		p += 4;
	    }
	}
    }

    if (useDisplayList) {
	glNewList(1, GL_COMPILE);
    }

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
		 baseWidth, baseHeight, 0,
		 GL_RGB, GL_UNSIGNED_BYTE, baseImage);

    /* clip subimage to base image size */
    glPixelStorei(GL_UNPACK_ROW_LENGTH, subWidth);
    if (subX < 0) {
	glPixelStorei(GL_UNPACK_SKIP_PIXELS, -subX);
	subWidth += subX;
	subX = 0;
    }
    if (subX > baseWidth) {
	subX = 0;
	subWidth = 0;
    }
    if (subX + subWidth > baseWidth) {
	subWidth -= (subX + subWidth) - baseWidth;
    }
    if (subWidth < 0) {
	subWidth = 0;
    }

    if (subY < 0) {
	glPixelStorei(GL_UNPACK_SKIP_ROWS, -subY);
	subHeight += subY;
	subY = 0;
    }
    if (subY > baseHeight) {
	subY = 0;
	subHeight = 0;
    }
    if (subY + subHeight > baseHeight) {
	subHeight -= (subY + subHeight) - baseHeight;
    }
    if (subHeight < 0) {
	subHeight = 0;
    }

    /* load subimage over base image */
    glTexSubImage2DEXT(GL_TEXTURE_2D, 0,
		       subX, subY, subWidth, subHeight,
		       GL_RGB, GL_UNSIGNED_BYTE, imageData);

    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);

    if (useDisplayList) {
	glEndList();
	glCallList(1);
    }

    glClear(GL_COLOR_BUFFER_BIT);

    /* draw a textured polygon the size of the window */
    glEnable(GL_TEXTURE_2D);

    glColor3f(1.0, 1.0, 1.0);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0);
    glVertex2i(0, 0);
    glTexCoord2f(1.0, 0.0);
    glVertex2i(winWidth-1, 0);
    glTexCoord2f(1.0, 1.0);
    glVertex2i(winWidth-1, winHeight-1);
    glTexCoord2f(0.0, 1.0);
    glVertex2i(0, winHeight-1);
    glEnd();

    glDisable(GL_TEXTURE_2D);

    if (doubleBuffered) {
	glutSwapBuffers();
    } else {
	glFlush();
    }

    checkErrors();
}

void
usage(int argc, char **argv)
{
    fprintf(stderr, "\n");
    fprintf(stderr, "usage: %s [ options ] file\n", argv[0]);
    fprintf(stderr, "\n");
    fprintf(stderr, "  Options:\n");
    fprintf(stderr, "    -sb    single buffered\n");
    fprintf(stderr, "    -db    double buffered\n");
    fprintf(stderr, "\n");
}

int
main(int argc, char **argv)
{
    char *name = "TexSubImage Test";
    int i;

    for (i=1; i<argc; ++i) {
	if (strcmp("-sb", argv[i]) == 0) {
	    doubleBuffered = GL_FALSE;

	} else if (strcmp("-db", argv[i]) == 0) {
	    doubleBuffered = GL_TRUE;

	} else if (i==argc-1 && argv[i][0] != '-') {
	    filename = argv[i];

	} else {
	    usage(argc, argv);
	    exit(EXIT_FAILURE);
	}
    }

    if (filename == NULL) {
	usage(argc, argv);
	exit(EXIT_FAILURE);
    }

    imgLoad(filename, &imageWidth, &imageHeight, &imageData);

    if (doubleBuffered) {
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    } else {
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    }

    glutInitWindowSize(winWidth, winHeight);
    glutCreateWindow(name);

    if (!glutExtensionSupported("GL_EXT_subtexture")) {
	fprintf(stderr, "missing extension: GL_EXT_subtexture\n");
	exit(EXIT_FAILURE);
    }

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutMainLoop();
}

#else

int main(int argc, char **argv)
{

    printf("Couldn't find GL_EXT_subtexture extension.\n");
}

#endif