From a7ea785a104a2254ace3b17ff0bde8231295f0fa Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Wed, 6 Aug 2003 17:47:15 +0000 Subject: [PATCH] miniglx test programs --- progs/miniglx/Makefile | 30 +++ progs/miniglx/glfbdevtest.c | 478 +++++++++++++++++++++++++++++++++ progs/miniglx/manytex.c | 381 ++++++++++++++++++++++++++ progs/miniglx/miniglxsample.c | 127 +++++++++ progs/miniglx/miniglxtest.c | 194 +++++++++++++ progs/miniglx/sample_server.c | 112 ++++++++ progs/miniglx/sample_server2.c | 227 ++++++++++++++++ progs/miniglx/texline.c | 268 ++++++++++++++++++ 8 files changed, 1817 insertions(+) create mode 100644 progs/miniglx/Makefile create mode 100644 progs/miniglx/glfbdevtest.c create mode 100644 progs/miniglx/manytex.c create mode 100644 progs/miniglx/miniglxsample.c create mode 100644 progs/miniglx/miniglxtest.c create mode 100644 progs/miniglx/sample_server.c create mode 100644 progs/miniglx/sample_server2.c create mode 100644 progs/miniglx/texline.c diff --git a/progs/miniglx/Makefile b/progs/miniglx/Makefile new file mode 100644 index 00000000000..48923ebcff0 --- /dev/null +++ b/progs/miniglx/Makefile @@ -0,0 +1,30 @@ + +# Simple makefile for compiling test programs on Linux +# These programs aren't intended to be included with the normal +# distro. They're not too interesting but they're good for testing. + + +CC = gcc +CFLAGS = -g -I../include +LIBS = -L../lib -lGL -lGLU -lglut -lm -Wl,-rpath,../lib + +PROGS = miniglxtest miniglxsample sample_server sample_server2 manytex texline + + +##### RULES ##### + +.SUFFIXES: +.SUFFIXES: .c + +.c: + $(CC) $(CFLAGS) $< $(LIBS) -o $@ + + +##### TARGETS ##### + +default: $(PROGS) + +clean: + rm -f $(PROGS) + rm -f *.o + diff --git a/progs/miniglx/glfbdevtest.c b/progs/miniglx/glfbdevtest.c new file mode 100644 index 00000000000..c82ca6e5f63 --- /dev/null +++ b/progs/miniglx/glfbdevtest.c @@ -0,0 +1,478 @@ +/* $Id: glfbdevtest.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */ + +/* + * Test the GLFBDev interface. Only tested with radeonfb driver!!!! + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "GL/glfbdev.h" + +#define DEFAULT_DEPTH 8 + +static struct fb_fix_screeninfo FixedInfo; +static struct fb_var_screeninfo VarInfo, OrigVarInfo; +static int DesiredDepth = 0; +static int OriginalVT = -1; +static int ConsoleFD = -1; +static int FrameBufferFD = -1; +static caddr_t FrameBuffer = (caddr_t) -1; +static caddr_t MMIOAddress = (caddr_t) -1; + + +static void +print_fixed_info(const struct fb_fix_screeninfo *fixed, const char *s) +{ + static const char *visuals[] = { + "MONO01", "MONO10", "TRUECOLOR", "PSEUDOCOLOR", + "DIRECTCOLOR", "STATIC_PSEUDOCOLOR" + }; + + printf("%s info -----------------------\n", s); + printf("id = %16s\n", fixed->id); + printf("smem_start = 0x%x\n", fixed->smem_start); + printf("smem_len = %d (0x%x)\n", fixed->smem_len, fixed->smem_len); + printf("type = 0x%x\n", fixed->type); + printf("type_aux = 0x%x\n", fixed->type_aux); + printf("visual = 0x%x (%s)\n", fixed->visual, visuals[fixed->visual]); + printf("xpanstep = %d\n", fixed->xpanstep); + printf("ypanstep = %d\n", fixed->ypanstep); + printf("ywrapstep = %d\n", fixed->ywrapstep); + printf("line_length = %d\n", fixed->line_length); + printf("mmio_start = 0x%x\n", fixed->mmio_start); + printf("mmio_len = %d (0x%x)\n", fixed->mmio_len, fixed->mmio_len); + printf("accel = 0x%x\n", fixed->accel); +} + + +static void +print_var_info(const struct fb_var_screeninfo *var, const char *s) +{ + printf("%s info -----------------------\n", s); + printf("xres = %d\n", var->xres); + printf("yres = %d\n", var->yres); + printf("xres_virtual = %d\n", var->xres_virtual); + printf("yres_virtual = %d\n", var->yres_virtual); + printf("xoffset = %d\n", var->xoffset); + printf("yoffset = %d\n", var->yoffset); + printf("bits_per_pixel = %d\n", var->bits_per_pixel); + printf("grayscale = %d\n", var->grayscale); + + printf("red.offset = %d length = %d msb_right = %d\n", + var->red.offset, var->red.length, var->red.msb_right); + printf("green.offset = %d length = %d msb_right = %d\n", + var->green.offset, var->green.length, var->green.msb_right); + printf("blue.offset = %d length = %d msb_right = %d\n", + var->blue.offset, var->blue.length, var->blue.msb_right); + printf("transp.offset = %d length = %d msb_right = %d\n", + var->transp.offset, var->transp.length, var->transp.msb_right); + + printf("nonstd = %d\n", var->nonstd); + printf("activate = %d\n", var->activate); + printf("height = %d mm\n", var->height); + printf("width = %d mm\n", var->width); + printf("accel_flags = 0x%x\n", var->accel_flags); + printf("pixclock = %d\n", var->pixclock); + printf("left_margin = %d\n", var->left_margin); + printf("right_margin = %d\n", var->right_margin); + printf("upper_margin = %d\n", var->upper_margin); + printf("lower_margin = %d\n", var->lower_margin); + printf("hsync_len = %d\n", var->hsync_len); + printf("vsync_len = %d\n", var->vsync_len); + printf("sync = %d\n", var->sync); + printf("vmode = %d\n", var->vmode); +} + + +static void +signal_handler(int signumber) +{ + signal(signumber, SIG_IGN); /* prevent recursion! */ + fprintf(stderr, "error: got signal %d (exiting)\n", signumber); + exit(1); +} + + +static void +initialize_fbdev( void ) +{ + char ttystr[1000]; + int fd, vtnumber, ttyfd; + int sz; + + if (geteuid()) { + fprintf(stderr, "error: you need to be root\n"); + exit(1); + } + +#if 1 + /* open the framebuffer device */ + FrameBufferFD = open("/dev/fb0", O_RDWR); + if (FrameBufferFD < 0) { + fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno)); + exit(1); + } +#endif + + /* open /dev/tty0 and get the vt number */ + if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) { + fprintf(stderr, "error opening /dev/tty0\n"); + exit(1); + } + if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) { + fprintf(stderr, "error: couldn't get a free vt\n"); + exit(1); + } + close(fd); + + /* open the console tty */ + sprintf(ttystr, "/dev/tty%d", vtnumber); /* /dev/tty1-64 */ + ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0); + if (ConsoleFD < 0) { + fprintf(stderr, "error couldn't open console fd\n"); + exit(1); + } + + /* save current vt number */ + { + struct vt_stat vts; + if (ioctl(ConsoleFD, VT_GETSTATE, &vts) == 0) + OriginalVT = vts.v_active; + } + + /* disconnect from controlling tty */ + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd >= 0) { + ioctl(ttyfd, TIOCNOTTY, 0); + close(ttyfd); + } + + /* some magic to restore the vt when we exit */ + { + struct vt_mode vt; + if (ioctl(ConsoleFD, VT_ACTIVATE, vtnumber) != 0) + printf("ioctl VT_ACTIVATE: %s\n", strerror(errno)); + if (ioctl(ConsoleFD, VT_WAITACTIVE, vtnumber) != 0) + printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno)); + + if (ioctl(ConsoleFD, VT_GETMODE, &vt) < 0) { + fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno)); + exit(1); + } + + vt.mode = VT_PROCESS; + vt.relsig = SIGUSR1; + vt.acqsig = SIGUSR1; + if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) { + fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n", + strerror(errno)); + exit(1); + } + } + + /* go into graphics mode */ + if (ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) { + fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n", + strerror(errno)); + exit(1); + } + + +#if 0 + /* open the framebuffer device */ + FrameBufferFD = open("/dev/fb0", O_RDWR); + if (FrameBufferFD < 0) { + fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno)); + exit(1); + } +#endif + + /* Get the fixed screen info */ + if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) { + fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n", + strerror(errno)); + exit(1); + } + + print_fixed_info(&FixedInfo, "Fixed"); + + + /* get the variable screen info */ + if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) { + fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n", + strerror(errno)); + exit(1); + } + + print_var_info(&OrigVarInfo, "Orig Var"); + + /* operate on a copy */ + VarInfo = OrigVarInfo; + + /* set the depth, resolution, etc */ + DesiredDepth = 32; + if (DesiredDepth) + VarInfo.bits_per_pixel = DesiredDepth; + + if (VarInfo.bits_per_pixel == 16) { + VarInfo.red.offset = 11; + VarInfo.green.offset = 5; + VarInfo.blue.offset = 0; + VarInfo.red.length = 5; + VarInfo.green.length = 6; + VarInfo.blue.length = 5; + VarInfo.transp.offset = 0; + VarInfo.transp.length = 0; + } + else if (VarInfo.bits_per_pixel == 32) { + VarInfo.red.offset = 16; + VarInfo.green.offset = 8; + VarInfo.blue.offset = 0; + VarInfo.transp.offset = 24; + VarInfo.red.length = 8; + VarInfo.green.length = 8; + VarInfo.blue.length = 8; + VarInfo.transp.length = 8; + } + /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */ + VarInfo.xres_virtual = VarInfo.xres = 1280; + VarInfo.yres_virtual = VarInfo.yres = 1024; + VarInfo.pixclock = 7408; + VarInfo.left_margin = 248; + VarInfo.right_margin = 16; + VarInfo.upper_margin = 38; + VarInfo.lower_margin = 1; + VarInfo.hsync_len = 144; + VarInfo.vsync_len = 3; + + VarInfo.xoffset = 0; + VarInfo.yoffset = 0; + VarInfo.nonstd = 0; + VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */ + + /* set new variable screen info */ + if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) { + fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n", + strerror(errno)); + exit(1); + } + + print_var_info(&VarInfo, "New Var"); + + if (FixedInfo.visual != FB_VISUAL_TRUECOLOR && + FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) { + fprintf(stderr, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n", FixedInfo.visual); + exit(1); + } + + /* initialize colormap */ + if (FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) { + struct fb_cmap cmap; + unsigned short red[256], green[256], blue[256]; + int i; + + /* we're assuming 256 entries here */ + printf("initializing directcolor colormap\n"); + cmap.start = 0; + cmap.len = 256; + cmap.red = red; + cmap.green = green; + cmap.blue = blue; + cmap.transp = NULL; + for (i = 0; i < cmap.len; i++) { + red[i] = green[i] = blue[i] = (i << 8) | i; + } + if (ioctl(FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) { + fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i); + } + } + + /* + * fbdev says the frame buffer is at offset zero, and the mmio region + * is immediately after. + */ + + /* mmap the framebuffer into our address space */ + FrameBuffer = (caddr_t) mmap(0, /* start */ + FixedInfo.smem_len, /* bytes */ + PROT_READ | PROT_WRITE, /* prot */ + MAP_SHARED, /* flags */ + FrameBufferFD, /* fd */ + 0 /* offset */); + if (FrameBuffer == (caddr_t) - 1) { + fprintf(stderr, "error: unable to mmap framebuffer: %s\n", + strerror(errno)); + exit(1); + } + printf("FrameBuffer = %p\n", FrameBuffer); + +#if 1 + /* mmap the MMIO region into our address space */ + MMIOAddress = (caddr_t) mmap(0, /* start */ + FixedInfo.mmio_len, /* bytes */ + PROT_READ | PROT_WRITE, /* prot */ + MAP_SHARED, /* flags */ + FrameBufferFD, /* fd */ + FixedInfo.smem_len /* offset */); + if (MMIOAddress == (caddr_t) - 1) { + fprintf(stderr, "error: unable to mmap mmio region: %s\n", + strerror(errno)); + } + printf("MMIOAddress = %p\n", MMIOAddress); + + /* try out some simple MMIO register reads */ + if (1) + { + typedef unsigned int CARD32; + typedef unsigned char CARD8; +#define RADEON_CONFIG_MEMSIZE 0x00f8 +#define RADEON_MEM_SDRAM_MODE_REG 0x0158 +#define MMIO_IN32(base, offset) \ + *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) +#define INREG(addr) MMIO_IN32(MMIOAddress, addr) + int sz, type; + const char *typeStr[] = {"SDR", "DDR", "64-bit SDR"}; + sz = INREG(RADEON_CONFIG_MEMSIZE); + type = INREG(RADEON_MEM_SDRAM_MODE_REG); + printf("RADEON_CONFIG_MEMSIZE = %d (%d MB)\n", sz, sz / 1024 / 1024); + printf("RADEON_MEM_SDRAM_MODE_REG >> 30 = %d (%s)\n", + type >> 30, typeStr[type>>30]); + } +#endif + +} + + +static void +shutdown_fbdev( void ) +{ + struct vt_mode VT; + + printf("cleaning up...\n"); + /* restore original variable screen info */ + if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo)) { + fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n", + strerror(errno)); + exit(1); + } + + munmap(MMIOAddress, FixedInfo.mmio_len); + munmap(FrameBuffer, FixedInfo.smem_len); + close(FrameBufferFD); + + /* restore text mode */ + ioctl(ConsoleFD, KDSETMODE, KD_TEXT); + + /* set vt */ + if (ioctl(ConsoleFD, VT_GETMODE, &VT) != -1) { + VT.mode = VT_AUTO; + ioctl(ConsoleFD, VT_SETMODE, &VT); + } + + /* restore original vt */ + if (OriginalVT >= 0) { + ioctl(ConsoleFD, VT_ACTIVATE, OriginalVT); + OriginalVT = -1; + } + + close(ConsoleFD); +} + + +static void +gltest( void ) +{ + static const int attribs[] = { + GLFBDEV_DOUBLE_BUFFER, + GLFBDEV_DEPTH_SIZE, 16, + GLFBDEV_NONE + }; + GLFBDevContextPtr ctx; + GLFBDevBufferPtr buf; + GLFBDevVisualPtr vis; + int bytes, r, g, b, a; + float ang; + + printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR)); + printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION)); + + /* framebuffer size */ + bytes = VarInfo.xres_virtual * VarInfo.yres_virtual * VarInfo.bits_per_pixel / 8; + + vis = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs ); + assert(vis); + + buf = glFBDevCreateBuffer( &FixedInfo, &VarInfo, vis, FrameBuffer, NULL, bytes ); + assert(buf); + + ctx = glFBDevCreateContext( vis, NULL ); + assert(buf); + + b = glFBDevMakeCurrent( ctx, buf, buf ); + assert(b); + + /*printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));*/ + glGetIntegerv(GL_RED_BITS, &r); + glGetIntegerv(GL_GREEN_BITS, &g); + glGetIntegerv(GL_BLUE_BITS, &b); + glGetIntegerv(GL_ALPHA_BITS, &a); + printf("RED_BITS=%d GREEN_BITS=%d BLUE_BITS=%d ALPHA_BITS=%d\n", + r, g, b, a); + + glClearColor(0.5, 0.5, 1.0, 0); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1, 1, -1, 1, 2, 30); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -15); + glViewport(0, 0, VarInfo.xres_virtual, VarInfo.yres_virtual); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + for (ang = 0; ang <= 180; ang += 15) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushMatrix(); + glRotatef(ang, 1, 0, 0); + glutSolidTorus(1, 3, 40, 20); + glPopMatrix(); + glFBDevSwapBuffers(buf); + } + + /* clean up */ + b = glFBDevMakeCurrent( NULL, NULL, NULL); + assert(b); + + glFBDevDestroyContext(ctx); + glFBDevDestroyBuffer(buf); + glFBDevDestroyVisual(vis); +} + + +int +main( int argc, char *argv[] ) +{ + signal(SIGUSR1, signal_handler); /* exit if someone tries a vt switch */ + signal(SIGSEGV, signal_handler); /* catch segfaults */ + + initialize_fbdev(); + gltest(); + shutdown_fbdev(); + + return 0; +} diff --git a/progs/miniglx/manytex.c b/progs/miniglx/manytex.c new file mode 100644 index 00000000000..3801963f9db --- /dev/null +++ b/progs/miniglx/manytex.c @@ -0,0 +1,381 @@ +/* $Id: manytex.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */ + +/* + * test handling of many texture maps + * Also tests texture priority and residency. + * + * Brian Paul + * August 2, 2000 + */ + + +#include +#include +#include +#include +#include + + +static GLint NumTextures = 20; +static GLuint *TextureID = NULL; +static GLint *TextureWidth = NULL, *TextureHeight = NULL; +static GLboolean *TextureResidency = NULL; +static GLint TexWidth = 128, TexHeight = 128; +static GLfloat Zrot = 0; +static GLboolean Anim = GL_TRUE; +static GLint WinWidth = 500, WinHeight = 400; +static GLboolean MipMap = GL_FALSE; +static GLboolean LinearFilter = GL_FALSE; +static GLboolean RandomSize = GL_FALSE; +static GLint Rows, Columns; +static GLint LowPriorityCount = 0; + + +static void Idle( void ) +{ + Zrot += 1.0; + glutPostRedisplay(); +} + + +static void Display( void ) +{ + GLfloat spacing = WinWidth / Columns; + GLfloat size = spacing * 0.4; + GLint i; + + /* test residency */ + if (0) + { + GLboolean b; + GLint i, resident; + b = glAreTexturesResident(NumTextures, TextureID, TextureResidency); + if (b) { + printf("all resident\n"); + } + else { + resident = 0; + for (i = 0; i < NumTextures; i++) { + if (TextureResidency[i]) { + resident++; + } + } + printf("%d of %d texture resident\n", resident, NumTextures); + } + } + + /* render the textured quads */ + glClear( GL_COLOR_BUFFER_BIT ); + for (i = 0; i < NumTextures; i++) { + GLint row = i / Columns; + GLint col = i % Columns; + GLfloat x = col * spacing + spacing * 0.5; + GLfloat y = row * spacing + spacing * 0.5; + + GLfloat maxDim = (TextureWidth[i] > TextureHeight[i]) + ? TextureWidth[i] : TextureHeight[i]; + GLfloat w = TextureWidth[i] / maxDim; + GLfloat h = TextureHeight[i] / maxDim; + + glPushMatrix(); + glTranslatef(x, y, 0.0); + glRotatef(Zrot, 0, 0, 1); + glScalef(size, size, 1); + + glBindTexture(GL_TEXTURE_2D, TextureID[i]); + glBegin(GL_POLYGON); +#if 0 + glTexCoord2f(0, 0); glVertex2f(-1, -1); + glTexCoord2f(1, 0); glVertex2f( 1, -1); + glTexCoord2f(1, 1); glVertex2f( 1, 1); + glTexCoord2f(0, 1); glVertex2f(-1, 1); +#else + glTexCoord2f(0, 0); glVertex2f(-w, -h); + glTexCoord2f(1, 0); glVertex2f( w, -h); + glTexCoord2f(1, 1); glVertex2f( w, h); + glTexCoord2f(0, 1); glVertex2f(-w, h); +#endif + glEnd(); + glPopMatrix(); + } + + glutSwapBuffers(); +} + + +static void Reshape( int width, int height ) +{ + WinWidth = width; + WinHeight = height; + glViewport( 0, 0, width, height ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glOrtho(0, width, 0, height, -1, 1); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); +} + + +/* + * Return a random int in [min, max]. + */ +static int RandomInt(int min, int max) +{ + int i = rand(); + int j = i % (max - min + 1); + return min + j; +} + + + +static void Init( void ) +{ + GLint i; + + if (RandomSize) { + printf("Creating %d %s random-size textures, ", NumTextures, + MipMap ? "Mipmapped" : "non-Mipmapped"); + } + else { + printf("Creating %d %s %d x %d textures, ", NumTextures, + MipMap ? "Mipmapped" : "non-Mipmapped", + TexWidth, TexHeight); + } + + if (LinearFilter) { + printf("bilinear filtering\n"); + } + else { + printf("nearest filtering\n"); + } + + + /* compute number of rows and columns of rects */ + { + GLfloat area = (GLfloat) (WinWidth * WinHeight) / (GLfloat) NumTextures; + GLfloat edgeLen = sqrt(area); + + Columns = WinWidth / edgeLen; + Rows = (NumTextures + Columns - 1) / Columns; + printf("Rows: %d Cols: %d\n", Rows, Columns); + } + + + if (!TextureID) { + TextureID = (GLuint *) malloc(sizeof(GLuint) * NumTextures); + assert(TextureID); + glGenTextures(NumTextures, TextureID); + } + + if (!TextureResidency) { + TextureResidency = (GLboolean *) malloc(sizeof(GLboolean) * NumTextures); + assert(TextureResidency); + } + + if (!TextureWidth) { + TextureWidth = (GLint *) malloc(sizeof(GLint) * NumTextures); + assert(TextureWidth); + } + if (!TextureHeight) { + TextureHeight = (GLint *) malloc(sizeof(GLint) * NumTextures); + assert(TextureHeight); + } + + for (i = 0; i < NumTextures; i++) { + GLubyte color[4]; + GLubyte *texImage; + GLint j, row, col; + + row = i / Columns; + col = i % Columns; + + glBindTexture(GL_TEXTURE_2D, TextureID[i]); + + if (i < LowPriorityCount) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 0.5F); + + if (RandomSize) { +#if 0 + int k = (glutGet(GLUT_ELAPSED_TIME) % 7) + 2; + TexWidth = 1 << k; + TexHeight = 1 << k; +#else + TexWidth = 1 << RandomInt(2, 7); + TexHeight = 1 << RandomInt(2, 7); + printf("Random size of %3d: %d x %d\n", i, TexWidth, TexHeight); +#endif + } + + TextureWidth[i] = TexWidth; + TextureHeight[i] = TexHeight; + + texImage = (GLubyte*) malloc(4 * TexWidth * TexHeight * sizeof(GLubyte)); + assert(texImage); + + /* determine texture color */ + color[0] = (GLint) (255.0 * ((float) col / (Columns - 1))); + color[1] = 127; + color[2] = (GLint) (255.0 * ((float) row / (Rows - 1))); + color[3] = 255; + + /* fill in solid-colored teximage */ + for (j = 0; j < TexWidth * TexHeight; j++) { + texImage[j*4+0] = color[0]; + texImage[j*4+1] = color[1]; + texImage[j*4+2] = color[2]; + texImage[j*4+3] = color[3]; + } + + if (MipMap) { + GLint level = 0; + GLint w = TexWidth, h = TexHeight; + while (1) { + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texImage); + if (w == 1 && h == 1) + break; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + level++; + /*printf("%d: %d x %d\n", level, w, h);*/ + } + if (LinearFilter) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + } + else { + /* Set corners to white */ + int k = 0; + texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255; + k = (TexWidth - 1) * 4; + texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255; + k = (TexWidth * TexHeight - TexWidth) * 4; + texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255; + k = (TexWidth * TexHeight - 1) * 4; + texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255; + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texImage); + if (LinearFilter) { + 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); + } + } + + free(texImage); + } + + glEnable(GL_TEXTURE_2D); +} + + +static void Key( unsigned char key, int x, int y ) +{ + const GLfloat step = 3.0; + (void) x; + (void) y; + switch (key) { + case 'a': + Anim = !Anim; + if (Anim) + glutIdleFunc(Idle); + else + glutIdleFunc(NULL); + break; + case 's': + Idle(); + break; + case 'z': + Zrot -= step; + break; + case 'Z': + Zrot += step; + break; + case ' ': + Init(); + break; + case 27: + exit(0); + break; + } + glutPostRedisplay(); +} + + +int main( int argc, char *argv[] ) +{ + GLint i; + + glutInit( &argc, argv ); + glutInitWindowPosition( 0, 0 ); + glutInitWindowSize( WinWidth, WinHeight ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + glutCreateWindow(argv[0]); + glutReshapeFunc( Reshape ); + glutKeyboardFunc( Key ); + glutDisplayFunc( Display ); + if (Anim) + glutIdleFunc(Idle); + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-n") == 0) { + NumTextures = atoi(argv[i+1]); + if (NumTextures <= 0) { + printf("Error, bad number of textures\n"); + return 1; + } + i++; + } + else if (strcmp(argv[i], "-mipmap") == 0) { + MipMap = GL_TRUE; + } + else if (strcmp(argv[i], "-linear") == 0) { + LinearFilter = GL_TRUE; + } + else if (strcmp(argv[i], "-size") == 0) { + TexWidth = atoi(argv[i+1]); + TexHeight = atoi(argv[i+2]); + assert(TexWidth >= 1); + assert(TexHeight >= 1); + i += 2; + } + else if (strcmp(argv[i], "-randomsize") == 0) { + RandomSize = GL_TRUE; + } + else if (strcmp(argv[i], "-lowpri") == 0) { + LowPriorityCount = atoi(argv[i+1]); + i++; + } + else { + printf("Usage:\n"); + printf(" manytex [options]\n"); + printf("Options:\n"); + printf(" -n \n"); + printf(" -size - specify texture size\n"); + printf(" -randomsize - use random size textures\n"); + printf(" -mipmap - generate mipmaps\n"); + printf(" -linear - use linear filtering instead of nearest\n"); + printf(" -lowpri - Set lower priority on textures\n"); + return 0; + } + } + + Init(); + + glutMainLoop(); + + return 0; +} diff --git a/progs/miniglx/miniglxsample.c b/progs/miniglx/miniglxsample.c new file mode 100644 index 00000000000..bea845c8ff7 --- /dev/null +++ b/progs/miniglx/miniglxsample.c @@ -0,0 +1,127 @@ + +#define USE_MINIGLX 1 /* 1 = use Mini GLX, 0 = use Xlib/GLX */ + +#include +#include +#include + +#if USE_MINIGLX +#include +#else +#include +#include +#endif + +static void _subset_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + glBegin( GL_QUADS ); + glVertex2f( x1, y1 ); + glVertex2f( x2, y1 ); + glVertex2f( x2, y2 ); + glVertex2f( x1, y2 ); + glEnd(); +} + + +/* + * Create a simple double-buffered RGBA window. + */ +static Window +MakeWindow(Display * dpy, unsigned int width, unsigned int height) +{ + int visAttributes[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + None + }; + XSetWindowAttributes attr; + unsigned long attrMask; + Window root; + Window win; + GLXContext ctx; + XVisualInfo *visinfo; + + root = RootWindow(dpy, 0); + + /* Choose GLX visual / pixel format */ + visinfo = glXChooseVisual(dpy, 0, visAttributes); + if (!visinfo) { + printf("Error: couldn't get an RGB, Double-buffered visual\n"); + exit(1); + } + + /* Create the window */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); + attrMask = CWBackPixel | CWBorderPixel | CWColormap; + win = XCreateWindow(dpy, root, 0, 0, width, height, + 0, visinfo->depth, InputOutput, + visinfo->visual, attrMask, &attr); + if (!win) { + printf("Error: XCreateWindow failed\n"); + exit(1); + } + + /* Display the window */ + XMapWindow(dpy, win); + + /* Create GLX rendering context */ + ctx = glXCreateContext(dpy, visinfo, NULL, True); + if (!ctx) { + printf("Error: glXCreateContext failed\n"); + exit(1); + } + + /* Bind the rendering context and window */ + glXMakeCurrent(dpy, win, ctx); + + glViewport(0, 0, width, height); + + return win; +} + + +/* + * Draw a few frames of a rotating square. + */ +static void +DrawFrames(Display * dpy, Window win) +{ + int angle; + glShadeModel(GL_FLAT); + glClearColor(0.5, 0.5, 0.5, 1.0); + for (angle = 0; angle < 360; angle += 10) { + glClear(GL_COLOR_BUFFER_BIT); + glColor3f(1.0, 1.0, 0.0); + glPushMatrix(); + glRotatef(angle, 0, 0, 1); + _subset_Rectf(-0.8, -0.8, 0.8, 0.8); + glPopMatrix(); + glXSwapBuffers(dpy, win); + sleep(1); + } +} + + +int +main(int argc, char *argv[]) +{ + Display *dpy; + Window win; + + dpy = XOpenDisplay(NULL); + if (!dpy) { + printf("Error: XOpenDisplay failed\n"); + return 1; + } + + win = MakeWindow(dpy, 300, 300); + + DrawFrames(dpy, win); + + return 0; +} diff --git a/progs/miniglx/miniglxtest.c b/progs/miniglx/miniglxtest.c new file mode 100644 index 00000000000..911bf4cb869 --- /dev/null +++ b/progs/miniglx/miniglxtest.c @@ -0,0 +1,194 @@ +/* $Id: miniglxtest.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */ + +/* + * Test the mini GLX interface. + */ + + +#include +#include +#include +#define USE_MINI_GLX 1 +#if USE_MINI_GLX +#include +#else +#include +#endif + +#define FRONTBUFFER 1 +#define NR 6 +#define DO_SLEEPS 1 +#define NR_DISPLAYS 2 + +GLXContext ctx; + + +static void _subset_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + glBegin( GL_QUADS ); + glVertex2f( x1, y1 ); + glVertex2f( x2, y1 ); + glVertex2f( x2, y2 ); + glVertex2f( x1, y2 ); + glEnd(); +} + + + +static void redraw( Display *dpy, Window w, int rot ) +{ + printf("Redraw event\n"); + +#if FRONTBUFFER + glDrawBuffer( GL_FRONT ); +#else +/* glDrawBuffer( GL_BACK ); */ +#endif + + glClearColor( rand()/(float)RAND_MAX, + rand()/(float)RAND_MAX, + rand()/(float)RAND_MAX, + 1); + + glClear( GL_COLOR_BUFFER_BIT ); + +#if 1 + glColor3f( rand()/(float)RAND_MAX, + rand()/(float)RAND_MAX, + rand()/(float)RAND_MAX ); + glPushMatrix(); + glRotatef(rot, 0, 0, 1); + glScalef(.5, .5, .5); + _subset_Rectf( -1, -1, 1, 1 ); + glPopMatrix(); +#endif + +#if FRONTBUFFER + glFlush(); +#else + glXSwapBuffers( dpy, w ); +#endif + glFinish(); +} + + +static Window make_rgb_db_window( Display *dpy, + unsigned int width, unsigned int height ) +{ + int attrib[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, +#if !FRONT_BUFFER + GLX_DOUBLEBUFFER, +#endif + None }; + int scrnum; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + Window win; + XVisualInfo *visinfo; + + scrnum = 0; + root = RootWindow( dpy, scrnum ); + + if (!(visinfo = glXChooseVisual( dpy, scrnum, attrib ))) { + printf("Error: couldn't get an RGB, Double-buffered visual\n"); + exit(1); + } + + if(!(ctx = glXCreateContext( dpy, visinfo, NULL, True ))) { + printf("Error: glXCreateContext failed\n"); + exit(1); + } + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | ExposureMask; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + win = XCreateWindow( dpy, root, 0, 0, width, height, + 0, visinfo->depth, InputOutput, + visinfo->visual, mask, &attr ); + if (!win) { + printf("Error: XCreateWindow failed\n"); + exit(1); + } + + glXMakeCurrent( dpy, win, ctx ); + + glViewport(0, 0, width, height); + + return win; +} + + +static void event_loop( Display *dpy, Window win ) +{ + int i; + + printf("Hang on... drawing %d frames\n", NR); + for (i = 0; i < NR; i++) { + redraw( dpy, win, i*10 ); + if (DO_SLEEPS) { + printf("sleep(1)\n"); + sleep(1); + } + } +} + + +int foo( ) +{ + Display *dpy; + Window win; + + dpy = XOpenDisplay(NULL); + if (!dpy) { + printf("Error: XOpenDisplay failed\n"); + return 1; + } + + win = make_rgb_db_window( dpy, 800, 600); + + srand(getpid()); + + glShadeModel( GL_FLAT ); + glClearColor( 0.5, 0.5, 0.5, 1.0 ); + + XMapWindow( dpy, win ); + + { + XEvent e; + while (1) { + XNextEvent( dpy, &e ); + if (e.type == MapNotify && e.xmap.window == win) { + break; + } + } + } + + event_loop( dpy, win ); + + glXDestroyContext( dpy, ctx ); + XDestroyWindow( dpy, win ); + + XCloseDisplay( dpy ); + + return 0; +} + + +int main() +{ + int i; + for (i = 0 ; i < NR_DISPLAYS ; i++) { + if (foo() != 0) + break; + } + + return 0; +} diff --git a/progs/miniglx/sample_server.c b/progs/miniglx/sample_server.c new file mode 100644 index 00000000000..039c04fa40a --- /dev/null +++ b/progs/miniglx/sample_server.c @@ -0,0 +1,112 @@ +/* $Id: sample_server.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */ + +/* + * Sample server that just keeps first available window mapped. + */ + + +#include +#include +#include +#include + +struct client { + struct client *next; + Window windowid; + int mappable; +}; + +struct client *clients = 0, *mapped_client = 0; + + +static struct client *find_client( Window id ) +{ + struct client *c; + + for (c = clients ; c ; c = c->next) + if (c->windowid == id) + return c; + + return 0; +} + +int main( int argc, char *argv[] ) +{ + Display *dpy; + XEvent ev; + + dpy = __miniglx_StartServer(NULL); + if (!dpy) { + fprintf(stderr, "Error: __miniglx_StartServer failed\n"); + return 1; + } + + while (XNextEvent( dpy, &ev )) { + struct client *c; + + switch (ev.type) { + case MapRequest: + fprintf(stderr, "MapRequest\n"); + c = find_client(ev.xmaprequest.window); + if (!c) break; + c->mappable = True; + break; + + case UnmapNotify: + fprintf(stderr, "UnmapNotify\n"); + c = find_client(ev.xunmap.window); + if (!c) break; + c->mappable = False; + if (c == mapped_client) + mapped_client = 0; + break; + + case CreateNotify: + fprintf(stderr, "CreateNotify\n"); + c = malloc(sizeof(*c)); + c->next = clients; + c->windowid = ev.xcreatewindow.window; + c->mappable = False; + clients = c; + break; + + case DestroyNotify: + fprintf(stderr, "DestroyNotify\n"); + c = find_client(ev.xdestroywindow.window); + if (!c) break; + if (c == clients) + clients = c->next; + else { + struct client *t; + for (t = clients ; t->next != c ; t = t->next) + ; + t->next = c->next; + } + + if (c == mapped_client) + mapped_client = 0; + + free(c); + break; + + default: + break; + } + + /* Search for first mappable client if none already mapped. + */ + if (!mapped_client) { + for (c = clients ; c ; c = c->next) { + if (c->mappable) { + XMapWindow( dpy, c->windowid ); + mapped_client = c; + break; + } + } + } + } + + XCloseDisplay( dpy ); + + return 0; +} diff --git a/progs/miniglx/sample_server2.c b/progs/miniglx/sample_server2.c new file mode 100644 index 00000000000..3508a21950c --- /dev/null +++ b/progs/miniglx/sample_server2.c @@ -0,0 +1,227 @@ +/* $Id: sample_server2.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */ + +/* + * Sample server that just keeps first available window mapped. + * + * It also reads and echos anything that happens on stdin as an + * example of tracking events from sources other than miniglx clients. + * + * It reads & writes without blocking, so that eg. piping a lot of + * text to stdin and then hitting 'ctrl-S' on the output stream won't + * cause it to stop handling miniglx events. + * + * See select_tut in the linux manual pages for a good overview of the + * select(2) system call. + */ + + +#include +#include +#include +#include +#include +#include + +struct client { + struct client *next; + Window windowid; + int mappable; +}; + +struct client *clients = 0, *mapped_client = 0; + +#define BUFSZ 4096 +char rbuf[BUFSZ]; +int rbuf_count; + + +static struct client *find_client( Window id ) +{ + struct client *c; + + for (c = clients ; c ; c = c->next) + if (c->windowid == id) + return c; + + return 0; +} + +int main( int argc, char *argv[] ) +{ + Display *dpy; + XEvent ev; + int autostart = 0; + + if (argc == 2 && strcmp(argv[1], "-autostart") == 0) + autostart = 1; + + dpy = __miniglx_StartServer(NULL); + if (!dpy) { + fprintf(stderr, "Error: __miniglx_StartServer failed\n"); + return 1; + } + + /* How is vt switching communicated through the XNextEvent interface? + */ + while (1) { + int r, n; + struct timeval tv; + fd_set rfds, wfds; + int bored = 0; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + tv.tv_sec = 1; + tv.tv_usec = 0; + + if (rbuf_count) { + FD_SET( 1, &wfds ); /* notify when we can write out buffer */ + n = 1; + } + else { + FD_SET( 0, &rfds ); /* else notify when new data to read */ + n = 0; + } + + /* __miniglx_Select waits until any of these file groups becomes + * readable/writable/etc (like regular select), until timeout + * expires (like regular select), until a signal is received + * (like regular select) or until an event is available for + * XCheckMaskEvent(). + */ + r = __miniglx_Select( dpy, n+1, &rfds, &wfds, 0, &tv ); + + /* This can happen if select() is interrupted by a signal: + */ + if (r < 0 && errno != EINTR && errno != EAGAIN) { + perror ("select()"); + exit (1); + } + + if (tv.tv_sec == 0 && tv.tv_usec == 0) + bored = 1; + + /* Check and handle events on our local file descriptors + */ + if (FD_ISSET( 0, &rfds )) { + /* Something on stdin */ + assert(rbuf_count == 0); + r = read(0, rbuf, BUFSZ); + if (r < 1) { + perror("read"); + abort(); + } + rbuf_count = r; + } + + if (FD_ISSET( 1, &wfds )) { + /* Can write to stdout */ + assert(rbuf_count > 0); + r = write(1, rbuf, rbuf_count); + if (r < 1) { + perror("write"); + abort(); + } + rbuf_count -= r; + if (rbuf_count) + memmove(rbuf + r, rbuf, rbuf_count); + } + + + /* Check and handle events generated by miniglx: + */ + while (XCheckMaskEvent( dpy, ~0, &ev )) { + struct client *c; + bored = 0; + + fprintf(stderr, "Received event %d\n", ev.type); + + switch (ev.type) { + case CreateNotify: + fprintf(stderr, "CreateNotify -- new client\n"); + c = malloc(sizeof(*c)); + c->next = clients; + c->windowid = ev.xcreatewindow.window; + c->mappable = False; + clients = c; + break; + + case DestroyNotify: + fprintf(stderr, "DestroyNotify\n"); + c = find_client(ev.xdestroywindow.window); + if (!c) break; + if (c == clients) + clients = c->next; + else { + struct client *t; + for (t = clients ; t->next != c ; t = t->next) + ; + t->next = c->next; + } + + if (c == mapped_client) + mapped_client = 0; + + free(c); + break; + + case MapRequest: + fprintf(stderr, "MapRequest\n"); + c = find_client(ev.xmaprequest.window); + if (!c) break; + c->mappable = True; + break; + + case UnmapNotify: + fprintf(stderr, "UnmapNotify\n"); + c = find_client(ev.xunmap.window); + if (!c) break; + c->mappable = False; + if (c == mapped_client) + mapped_client = 0; + break; + + default: + break; + } + } + + + /* Search for first mappable client if none already mapped. + */ + if (!mapped_client) { + struct client *c; + for (c = clients ; c ; c = c->next) { + if (c->mappable) { + XMapWindow( dpy, c->windowid ); + mapped_client = c; + break; + } + } + if (!clients && autostart) { + system("nohup ./texline &"); + system("nohup ./manytex &"); + } + } + else if (bored) { + struct client *c; + /* bored of mapped client now, let's try & find another one */ + for (c = mapped_client->next ; c && !c->mappable ; c = c->next) + ; + if (!c) + for (c = clients ; c && !c->mappable ; c = c->next) + ; + if (c && c != mapped_client) { + XUnmapWindow( dpy, mapped_client->windowid ); + XMapWindow( dpy, c->windowid ); + mapped_client = c; + } + else + fprintf(stderr, "I'm bored!\n"); + } + } + + XCloseDisplay( dpy ); + + return 0; +} diff --git a/progs/miniglx/texline.c b/progs/miniglx/texline.c new file mode 100644 index 00000000000..d2a97d2876e --- /dev/null +++ b/progs/miniglx/texline.c @@ -0,0 +1,268 @@ +/* $Id: texline.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */ + +/* + * Test textured lines. + * + * Brian Paul + * September 2000 + */ + + +#include +#include +#include +#include +#include "../util/readtex.c" /* I know, this is a hack. */ + +#define TEXTURE_FILE "../images/girl.rgb" + +static GLboolean Antialias = GL_FALSE; +static GLboolean Animate = GL_FALSE; +static GLint Texture = 1; +static GLboolean Stipple = GL_FALSE; +static GLfloat LineWidth = 1.0; + +static GLfloat Xrot = -60.0, Yrot = 0.0, Zrot = 0.0; +static GLfloat DYrot = 1.0; +static GLboolean Points = GL_FALSE; +static GLfloat Scale = 1.0; + +static void Idle( void ) +{ + if (Animate) { + Zrot += DYrot; + glutPostRedisplay(); + } +} + + +static void Display( void ) +{ + GLfloat x, y, s, t; + + glClear( GL_COLOR_BUFFER_BIT ); + + glPushMatrix(); + glRotatef(Xrot, 1.0, 0.0, 0.0); + glRotatef(Yrot, 0.0, 1.0, 0.0); + glRotatef(Zrot, 0.0, 0.0, 1.0); + glScalef(Scale, Scale, Scale); + + if (Texture) + glColor3f(1, 1, 1); + + if (Points) { + glBegin(GL_POINTS); + for (t = 0.0; t <= 1.0; t += 0.025) { + for (s = 0.0; s <= 1.0; s += 0.025) { + x = s * 2.0 - 1.0; + y = t * 2.0 - 1.0; + if (!Texture) + glColor3f(1, 0, 1); + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t, s); + glTexCoord2f(s, t); + glVertex2f(x, y); + } + } + glEnd(); + } + else { + glBegin(GL_LINES); + for (t = 0.0; t <= 1.0; t += 0.025) { + x = t * 2.0 - 1.0; + if (!Texture) + glColor3f(1, 0, 1); + glTexCoord2f(t, 0.0); + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0, t); + glVertex2f(x, -1.0); + if (!Texture) + glColor3f(0, 1, 0); + glTexCoord2f(t, 1.0); + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0, t); + glVertex2f(x, 1.0); + } + glEnd(); + } + + glPopMatrix(); + + glutSwapBuffers(); +} + + +static void Reshape( int width, int height ) +{ + GLfloat ar = (float) width / height; + glViewport( 0, 0, width, height ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glFrustum( -ar, ar, -1.0, 1.0, 10.0, 100.0 ); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glTranslatef( 0.0, 0.0, -12.0 ); +} + + +static void Key( unsigned char key, int x, int y ) +{ + (void) x; + (void) y; + switch (key) { + case 'a': + Antialias = !Antialias; + if (Antialias) { + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POINT_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glDisable(GL_LINE_SMOOTH); + glDisable(GL_POINT_SMOOTH); + glDisable(GL_BLEND); + } + break; + case 't': + Texture++; + if (Texture > 2) + Texture = 0; + if (Texture == 0) { + glActiveTextureARB(GL_TEXTURE0_ARB); + glDisable(GL_TEXTURE_2D); + glActiveTextureARB(GL_TEXTURE1_ARB); + glDisable(GL_TEXTURE_2D); + } + else if (Texture == 1) { + glActiveTextureARB(GL_TEXTURE0_ARB); + glEnable(GL_TEXTURE_2D); + glActiveTextureARB(GL_TEXTURE1_ARB); + glDisable(GL_TEXTURE_2D); + } + else { + glActiveTextureARB(GL_TEXTURE0_ARB); + glEnable(GL_TEXTURE_2D); + glActiveTextureARB(GL_TEXTURE1_ARB); + glEnable(GL_TEXTURE_2D); + } + break; + case 'w': + LineWidth -= 0.25; + if (LineWidth < 0.25) + LineWidth = 0.25; + glLineWidth(LineWidth); + glPointSize(LineWidth); + break; + case 'W': + LineWidth += 0.25; + if (LineWidth > 8.0) + LineWidth = 8.0; + glLineWidth(LineWidth); + glPointSize(LineWidth); + break; + case 'p': + Points = !Points; + break; + case 's': + Stipple = !Stipple; + if (Stipple) + glEnable(GL_LINE_STIPPLE); + else + glDisable(GL_LINE_STIPPLE); + break; + case ' ': + Animate = !Animate; + if (Animate) + glutIdleFunc(Idle); + else + glutIdleFunc(NULL); + break; + case 27: + exit(0); + break; + } + printf("LineWidth, PointSize = %f\n", LineWidth); + glutPostRedisplay(); +} + + +static void SpecialKey( int key, int x, int y ) +{ + float step = 3.0; + (void) x; + (void) y; + + switch (key) { + case GLUT_KEY_UP: + Xrot += step; + break; + case GLUT_KEY_DOWN: + Xrot -= step; + break; + case GLUT_KEY_LEFT: + Yrot += step; + break; + case GLUT_KEY_RIGHT: + Yrot -= step; + break; + } + glutPostRedisplay(); +} + + +static void Init( int argc, char *argv[] ) +{ + GLuint u; + for (u = 0; u < 2; u++) { + glActiveTextureARB(GL_TEXTURE0_ARB + u); + glBindTexture(GL_TEXTURE_2D, 10+u); + if (u == 0) + glEnable(GL_TEXTURE_2D); + 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_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + if (u == 0) + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + else + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) { + printf("Error: couldn't load texture image\n"); + exit(1); + } + } + + glLineStipple(1, 0xff); + + if (argc > 1 && strcmp(argv[1], "-info")==0) { + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); + } +} + + +int main( int argc, char *argv[] ) +{ + glutInit( &argc, argv ); + glutInitWindowSize( 400, 300 ); + + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + + glutCreateWindow(argv[0] ); + + Init(argc, argv); + + glutReshapeFunc( Reshape ); + glutKeyboardFunc( Key ); + glutSpecialFunc( SpecialKey ); + glutDisplayFunc( Display ); + if (Animate) + glutIdleFunc( Idle ); + + glutMainLoop(); + return 0; +} -- 2.30.2