tests: test pseudo-XOR blend mode.
authorBrian Paul <brianp@vmware.com>
Mon, 19 Jan 2009 19:03:17 +0000 (12:03 -0700)
committerBrian Paul <brianp@vmware.com>
Mon, 19 Jan 2009 19:09:40 +0000 (12:09 -0700)
GL_XOR logicop mode can be approximated with blending by computing 1 - dst.
Here's a couple test programs for that.

progs/tests/Makefile
progs/tests/blendxor.c [new file with mode: 0644]
progs/tests/rubberband.c [new file with mode: 0644]

index 86b0cb537be71b597848f3a31c619e0335ae7f1a..5f17f88d36cf94599a0616f60264db4575df1cb8 100644 (file)
@@ -26,6 +26,7 @@ SOURCES = \
        arraytexture.c \
        blendminmax.c \
        blendsquare.c \
+       blendxor.c \
        bufferobj.c \
        bug_3050.c \
        bug_3101.c \
@@ -60,6 +61,7 @@ SOURCES = \
        projtex.c \
        random.c \
        readrate.c \
+       rubberband.c \
        seccolor.c \
        shader_api.c \
        sharedtex.c \
diff --git a/progs/tests/blendxor.c b/progs/tests/blendxor.c
new file mode 100644 (file)
index 0000000..8961a82
--- /dev/null
@@ -0,0 +1,196 @@
+/**
+ * Test XOR emulation with blending.
+ *
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glut.h>
+#include "readtex.c"
+
+#define IMAGE_FILE "../images/arch.rgb"
+
+static int ImgWidth, ImgHeight;
+static GLenum ImgFormat;
+static GLubyte *Image = NULL;
+
+static int Win;
+static int Width = 600, Height = 600;
+
+struct rect
+{
+   int x0, y0, x1, y1;
+};
+
+static struct rect OldRect, NewRect;
+
+static GLboolean ButtonDown = GL_FALSE;
+static GLboolean LogicOp = 0*GL_TRUE;
+
+
+static const GLfloat red[4] = {1.0, 0.2, 0.2, 1.0};
+static const GLfloat green[4] = {0.2, 1.0, 0.2, 1.0};
+static const GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
+
+
+static void
+PrintString(const char *s)
+{
+   while (*s) {
+      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
+      s++;
+   }
+}
+
+
+static void
+Draw(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   glWindowPos2i((Width - ImgWidth) / 2, (Height - ImgHeight) / 2);
+   glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image);
+
+   /*
+    * Draw 2D XOR rects
+    */
+   glColor3f(1, 1, 1);
+
+   glWindowPos2i(100, Height - 20);
+   PrintString("XOR LogicOp:");
+   glLogicOp(GL_XOR);
+   glEnable(GL_COLOR_LOGIC_OP);
+   glRecti(100, 30, 250, Height - 30);
+   glDisable(GL_COLOR_LOGIC_OP);
+
+   glWindowPos2i(Width/2 + 10, Height - 20);
+   PrintString("Invert Blending:");
+   glBlendFunc(GL_ONE, GL_ONE);
+   glBlendEquation(GL_FUNC_SUBTRACT);
+   glEnable(GL_BLEND);
+   glRecti(Width / 2, 30, Width / 2 + 150, Height - 30);
+   glDisable(GL_BLEND);
+
+   glutSwapBuffers();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+   Width = width;
+   Height = height;
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(0, Width, 0, Height, -1, 1);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+   case 'b':
+   case 'B':
+      LogicOp = GL_FALSE;
+      break;
+   case 'l':
+   case 'L':
+      LogicOp = GL_TRUE;
+      break;
+   case 27:
+      glutDestroyWindow(Win);
+      exit(0);
+      break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+SpecialKey(int key, int x, int y)
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+   case GLUT_KEY_UP:
+      break;
+   case GLUT_KEY_DOWN:
+      break;
+   case GLUT_KEY_LEFT:
+      break;
+   case GLUT_KEY_RIGHT:
+      break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+MouseMotion(int x, int y)
+{
+   if (ButtonDown) {
+      NewRect.x1 = x;
+      NewRect.y1 = y;
+      glutPostRedisplay();
+   }
+}
+
+
+static void
+MouseButton(int button, int state, int x, int y)
+{
+  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
+     ButtonDown = GL_TRUE;
+     NewRect.x0 = NewRect.x1 = x;
+     NewRect.y0 = NewRect.y1 = y;
+     OldRect = NewRect;
+  }
+  else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
+     ButtonDown = GL_FALSE;
+  }
+}
+
+
+static void
+Init(void)
+{
+   /*
+    * Load image and scale if needed.
+    */
+   Image = LoadRGBImage(IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat);
+   if (!Image) {
+      printf("Couldn't read %s\n", IMAGE_FILE);
+      exit(0);
+   }
+
+   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+   glPixelStorei(GL_PACK_ALIGNMENT, 1);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   glutInit(&argc, argv);
+   glutInitWindowSize(Width, Height);
+   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+   Win = glutCreateWindow(argv[0]);
+   glutReshapeFunc(Reshape);
+   glutKeyboardFunc(Key);
+   glutSpecialFunc(SpecialKey);
+   glutMotionFunc(MouseMotion);
+   glutMouseFunc(MouseButton);
+   glutDisplayFunc(Draw);
+   Init();
+   glutPostRedisplay();
+   glutMainLoop();
+   return 0;
+}
diff --git a/progs/tests/rubberband.c b/progs/tests/rubberband.c
new file mode 100644 (file)
index 0000000..a8e64bc
--- /dev/null
@@ -0,0 +1,245 @@
+/**
+ * Test rubber-band selection box w/ logicops and blend.
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glut.h>
+#include "readtex.c"
+
+#define IMAGE_FILE "../images/arch.rgb"
+
+static int ImgWidth, ImgHeight;
+static GLenum ImgFormat;
+static GLubyte *Image = NULL;
+
+static int Win;
+static int Width = 512, Height = 512;
+
+struct rect
+{
+   int x0, y0, x1, y1;
+};
+
+static struct rect OldRect, NewRect;
+
+static GLboolean ButtonDown = GL_FALSE;
+static GLboolean LogicOp = 0*GL_TRUE;
+
+static GLboolean RedrawBackground = GL_TRUE;
+
+static const GLfloat red[4] = {1.0, 0.2, 0.2, 1.0};
+static const GLfloat green[4] = {0.2, 1.0, 0.2, 1.0};
+static const GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
+
+
+/*
+ * Draw rubberband box in front buffer
+ */
+static void
+DrawRect(const struct rect *r)
+{
+   glDrawBuffer(GL_FRONT);
+
+   if (LogicOp) {
+      glLogicOp(GL_XOR);
+      glEnable(GL_COLOR_LOGIC_OP);
+   }
+   else {
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_ONE, GL_ONE);
+      glBlendEquation(GL_FUNC_SUBTRACT);
+   }
+
+   glColor3f(1, 1, 1);
+
+   glLineWidth(3.0);
+
+   glBegin(GL_LINE_LOOP);
+   glVertex2i(r->x0, r->y0);
+   glVertex2i(r->x1, r->y0);
+   glVertex2i(r->x1, r->y1);
+   glVertex2i(r->x0, r->y1);
+   glEnd();
+
+   glDisable(GL_COLOR_LOGIC_OP);
+   glDisable(GL_BLEND);
+
+   glDrawBuffer(GL_BACK);
+}
+
+
+static void
+PrintString(const char *s)
+{
+   while (*s) {
+      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
+      s++;
+   }
+}
+
+
+static void
+DrawBackground(void)
+{
+   char s[100];
+
+   sprintf(s, "[L/B] %s mode.   Use mouse to make selection box.",
+               LogicOp ? "LogicOp" : "Blend");
+
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   glWindowPos2i((Width - ImgWidth) / 2, (Height - ImgHeight) / 2);
+   glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image);
+
+   glWindowPos2i(10, 10);
+   PrintString(s);
+
+   glutSwapBuffers();
+}
+
+
+static void
+Draw(void)
+{
+   if (RedrawBackground) {
+      DrawBackground();
+   }
+
+   if (ButtonDown) {
+      if (!RedrawBackground)
+         DrawRect(&OldRect); /* erase old */
+
+      DrawRect(&NewRect); /* draw new */
+
+      OldRect = NewRect;
+   }
+
+   RedrawBackground = GL_FALSE;
+}
+
+
+static void
+Reshape(int width, int height)
+{
+   Width = width;
+   Height = height;
+
+   glViewport(0, 0, width, height);
+
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(0, Width, Height, 0, -1, 1); /* Inverted Y! */
+
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+
+   RedrawBackground = GL_TRUE;
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+   case 'b':
+   case 'B':
+      LogicOp = GL_FALSE;
+      break;
+   case 'l':
+   case 'L':
+      LogicOp = GL_TRUE;
+      break;
+   case 27:
+      glutDestroyWindow(Win);
+      exit(0);
+      break;
+   }
+   RedrawBackground = GL_TRUE;
+   glutPostRedisplay();
+}
+
+
+static void
+SpecialKey(int key, int x, int y)
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+   case GLUT_KEY_UP:
+      break;
+   case GLUT_KEY_DOWN:
+      break;
+   case GLUT_KEY_LEFT:
+      break;
+   case GLUT_KEY_RIGHT:
+      break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+MouseMotion(int x, int y)
+{
+   if (ButtonDown) {
+      NewRect.x1 = x;
+      NewRect.y1 = y;
+      glutPostRedisplay();
+   }
+}
+
+
+static void
+MouseButton(int button, int state, int x, int y)
+{
+  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
+     ButtonDown = GL_TRUE;
+     RedrawBackground = GL_TRUE;
+     NewRect.x0 = NewRect.x1 = x;
+     NewRect.y0 = NewRect.y1 = y;
+     OldRect = NewRect;
+  }
+  else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
+     ButtonDown = GL_FALSE;
+  }
+  glutPostRedisplay();
+}
+
+
+static void
+Init(void)
+{
+   Image = LoadRGBImage(IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat);
+   if (!Image) {
+      printf("Couldn't read %s\n", IMAGE_FILE);
+      exit(0);
+   }
+
+   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+   glPixelStorei(GL_PACK_ALIGNMENT, 1);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   glutInit(&argc, argv);
+   glutInitWindowSize(Width, Height);
+   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+   Win = glutCreateWindow(argv[0]);
+   glutReshapeFunc(Reshape);
+   glutKeyboardFunc(Key);
+   glutSpecialFunc(SpecialKey);
+   glutMotionFunc(MouseMotion);
+   glutMouseFunc(MouseButton);
+   glutDisplayFunc(Draw);
+   Init();
+   glutPostRedisplay();
+   glutMainLoop();
+   return 0;
+}