blendeq.c revision 32001f49
1/*
2** blendeq.c - Demonstrates the use of the blend_minmax, blend_subtract,
3**    and blend_logic_op extensions using glBlendEquationEXT.
4**
5**    Over a two-color backround, draw rectangles using twelve blend
6**    options.  The values are read back as UNSIGNED_BYTE and printed
7**    in hex over each value.  These values are useful for logic
8**    op comparisons when channels are 8 bits deep.
9*/
10
11#include <string.h>
12#include <stdlib.h>
13#include <stdio.h>
14#include <GL/glew.h>
15#include "glut_wrap.h"
16
17GLenum doubleBuffer;
18static int dithering = 0;
19int use11ops = 0;
20int supportlogops = 0;
21static int doPrint = 1;
22static int deltaY;
23GLint windW, windH;
24
25static const struct {
26   GLenum mode;
27   const char *name;
28} LogicOpModes[] = {
29   { GL_SET, "GL_SET" },
30   { GL_COPY, "GL_COPY" },
31   { GL_NOOP, "GL_NOOP" },
32   { GL_AND, "GL_AND" },
33   { GL_INVERT, "GL_INVERT" },
34   { GL_OR, "GL_OR" },
35   { GL_XOR, "GL_XOR" },
36   { GL_NOR, "GL_NOR" },
37   { GL_NAND, "GL_NAND" },
38   { GL_OR_REVERSE, "GL_OR_REVERSE" },
39   { GL_OR_INVERTED, "GL_OR_INVERTED" },
40   { GL_AND_INVERTED, "GL_AND_INVERTED" },
41   { 0, NULL }
42};
43
44
45
46static void DrawString(const char *string)
47{
48    int i;
49
50    for (i = 0; string[i]; i++)
51	glutBitmapCharacter(GLUT_BITMAP_9_BY_15, string[i]);
52}
53
54static void Init(void)
55{
56
57    glDisable(GL_DITHER);
58    glShadeModel(GL_FLAT);
59}
60
61static void Reshape(int width, int height)
62{
63
64    windW = (GLint)width;
65    windH = (GLint)height;
66
67    glViewport(0, 0, (GLint)width, (GLint)height);
68    deltaY = windH /20;
69
70    glMatrixMode(GL_PROJECTION);
71    glLoadIdentity();
72    gluOrtho2D(0, windW, 0, windH);
73    glMatrixMode(GL_MODELVIEW);
74}
75
76static void Key(unsigned char key, int x, int y)
77{
78
79    switch (key) {
80      case 27:
81	exit(1);
82      case 'd':
83	dithering = !dithering;
84	break;
85      case 'l':
86        if (supportlogops == 3)
87           use11ops = (!use11ops);
88        if (use11ops)
89           printf("Using GL 1.1 color logic ops.\n");
90        else printf("Using GL_EXT_blend_logic_op.\n");
91        break;
92      default:
93	return;
94    }
95
96    glutPostRedisplay();
97}
98
99static void PrintColorStrings( void )
100{
101    GLubyte ubbuf[3];
102    int i, xleft, xright;
103    char colorString[100];
104
105    xleft = 5 + windW/4;
106    xright = 5 + windW/2;
107
108    for (i = windH - deltaY + 4; i > 0; i-=deltaY) {
109        glReadPixels(xleft, i+10, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, ubbuf);
110        sprintf(colorString, "(0x%x, 0x%x, 0x%x)",
111                ubbuf[0], ubbuf[1], ubbuf[2]);
112        glRasterPos2f(xleft, i);
113	DrawString(colorString);
114        glReadPixels(xright, i+10, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, ubbuf);
115        sprintf(colorString, "(0x%x, 0x%x, 0x%x)",
116                ubbuf[0], ubbuf[1], ubbuf[2]);
117        glRasterPos2f(xright, i);
118	DrawString(colorString);
119    }
120}
121
122static void Draw(void)
123{
124    int stringOffset = 5, stringx = 8;
125    int x1, x2, xleft, xright;
126    int i, k;
127
128    (dithering) ? glEnable(GL_DITHER) : glDisable(GL_DITHER);
129    glDisable(GL_BLEND);
130    if (supportlogops & 2)
131       glDisable(GL_COLOR_LOGIC_OP);
132
133    glClearColor(0.5, 0.6, 0.1, 1.0);
134    glClear(GL_COLOR_BUFFER_BIT);
135
136    /* Draw background */
137    glColor3f(0.1, 0.1, 1.0);
138    glRectf(0.0, 0.0, windW/2, windH);
139
140    /* Draw labels */
141    glColor3f(0.8, 0.8, 0.0);
142    i = windH - deltaY + stringOffset;
143
144    glRasterPos2f(stringx, i); i -= deltaY;
145    DrawString("SOURCE");
146    glRasterPos2f(stringx, i); i -= deltaY;
147    DrawString("DEST");
148    glRasterPos2f(stringx, i); i -= deltaY;
149    DrawString("min");
150    glRasterPos2f(stringx, i); i -= deltaY;
151    DrawString("max");
152    glRasterPos2f(stringx, i); i -= deltaY;
153    DrawString("subtract");
154    glRasterPos2f(stringx, i); i -= deltaY;
155    DrawString("reverse_subtract");
156    glRasterPos2f(stringx, i); i -= deltaY;
157    DrawString("clear");
158
159    for (k = 0; LogicOpModes[k].name; k++) {
160       glRasterPos2f(stringx, i);
161       i -= deltaY;
162       DrawString(LogicOpModes[k].name);
163    }
164
165    i = windH - deltaY;
166    x1 = windW/4;
167    x2 = 3 * windW/4;
168    xleft = 5 + windW/4;
169    xright = 5 + windW/2;
170
171    /* Draw foreground color for comparison */
172    glColor3f(0.9, 0.2, 0.8);
173    glRectf(x1, i, x2, i+deltaY);
174
175    /* Leave one rectangle of background color */
176
177    /* Begin test cases */
178    glEnable(GL_BLEND);
179    glBlendFunc(GL_ONE, GL_ONE);
180
181    i -= 2*deltaY;
182    glBlendEquationEXT(GL_MIN_EXT);
183    glRectf(x1, i, x2, i+deltaY);
184
185    i -= deltaY;
186    glBlendEquationEXT(GL_MAX_EXT);
187    glRectf(x1, i, x2, i+deltaY);
188
189    i -= deltaY;
190    glBlendEquationEXT(GL_FUNC_SUBTRACT_EXT);
191    glRectf(x1, i, x2, i+deltaY);
192
193    i -= deltaY;
194    glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
195    glRectf(x1, i, x2, i+deltaY);
196
197    glBlendFunc(GL_ONE, GL_ZERO);
198    i -= deltaY;
199    if (!use11ops)
200       glBlendEquationEXT(GL_LOGIC_OP);
201    else
202       glEnable(GL_COLOR_LOGIC_OP);
203    glLogicOp(GL_CLEAR);
204    glRectf(x1, i, x2, i+deltaY);
205
206    for (k = 0; LogicOpModes[k].name; k++) {
207       i -= deltaY;
208       glLogicOp(LogicOpModes[k].mode);
209       glRectf(x1, i, x2, i+deltaY);
210       if (LogicOpModes[k].mode == GL_XOR) {
211          glRectf(x1, i+10, x2, i+5);
212       }
213    }
214
215    if (doPrint) {
216       glDisable(GL_BLEND);
217       if (supportlogops & 2)
218          glDisable(GL_COLOR_LOGIC_OP);
219       glColor3f(1.0, 1.0, 1.0);
220       PrintColorStrings();
221    }
222    glFlush();
223
224    if (doubleBuffer) {
225       glutSwapBuffers();
226    }
227
228}
229
230static GLenum Args(int argc, char **argv)
231{
232    GLint i;
233
234    doubleBuffer = GL_FALSE;
235
236    for (i = 1; i < argc; i++) {
237	if (strcmp(argv[i], "-sb") == 0) {
238	    doubleBuffer = GL_FALSE;
239	} else if (strcmp(argv[i], "-db") == 0) {
240	    doubleBuffer = GL_TRUE;
241	} else {
242	    printf("%s (Bad option).\n", argv[i]);
243	    return GL_FALSE;
244	}
245    }
246    return GL_TRUE;
247}
248
249int main(int argc, char **argv)
250{
251    GLenum type;
252    char *s;
253    char *extName1 = "GL_EXT_blend_logic_op";
254    char *extName2 = "GL_EXT_blend_minmax";
255    char *extName3 = "GL_EXT_blend_subtract";
256    char *version;
257
258    glutInit(&argc, argv);
259
260    if (Args(argc, argv) == GL_FALSE) {
261	exit(1);
262    }
263
264    glutInitWindowPosition(0, 0); glutInitWindowSize( 800, 520);
265
266    type = GLUT_RGB;
267    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
268    glutInitDisplayMode(type);
269
270    if (glutCreateWindow("Blend Equation") == GL_FALSE) {
271	exit(1);
272    }
273
274    glewInit();
275
276    /* Make sure blend_logic_op extension is there. */
277    s = (char *) glGetString(GL_EXTENSIONS);
278    version = (char*) glGetString(GL_VERSION);
279    if (!s)
280	exit(1);
281    if (strstr(s,extName1)) {
282	supportlogops = 1;
283        use11ops = 0;
284        printf("blend_logic_op extension available.\n");
285    }
286    if (strncmp(version,"1.1",3)>=0) {
287    	supportlogops += 2;
288        use11ops = 1;
289	printf("1.1 color logic ops available.\n");
290    }
291    if (supportlogops == 0) {
292    	printf("Blend_logic_op extension and GL 1.1 not present.\n");
293	exit(1);
294    }
295    if (strstr(s,extName2) == 0) {
296	printf("Blend_minmax extension is not present.\n");
297	exit(1);
298    }
299    if (strstr(s,extName3) == 0) {
300	printf("Blend_subtract extension is not present.\n");
301	exit(1);
302    }
303
304    Init();
305
306    glutReshapeFunc(Reshape);
307    glutKeyboardFunc(Key);
308    glutDisplayFunc(Draw);
309    glutMainLoop();
310    return 0;
311}
312