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