Merge branch '7.8'
[mesa.git] / progs / samples / blendeq.c
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 <GL/glut.h>
16
17 GLenum doubleBuffer;
18 static int dithering = 0;
19 int use11ops = 0;
20 int supportlogops = 0;
21 static int doPrint = 1;
22 static int deltaY;
23 GLint windW, windH;
24
25 static 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
46 static 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
54 static void Init(void)
55 {
56
57 glDisable(GL_DITHER);
58 glShadeModel(GL_FLAT);
59 }
60
61 static 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
76 static 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
99 static 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
122 static 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
230 static 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
249 int 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 }