]> git.cworth.org Git - apitrace-tests/blob - apps/egl/gl/tri_glsl.c
ab7e23603bc81c3c8a9cf058906de72e426ada72
[apitrace-tests] / apps / egl / gl / tri_glsl.c
1 /**************************************************************************
2  *
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  *
6  **************************************************************************/
7
8 /*
9  * Draw a triangle with X/EGL and OpenGL ES 2.x
10  */
11
12 #define USE_FULL_GL 1
13
14
15
16 #include <assert.h>
17 #include <math.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <X11/Xlib.h>
22 #include <X11/Xutil.h>
23 #include <X11/keysym.h>
24 #if USE_FULL_GL
25 #include <GL/gl.h>  /* use full OpenGL */
26 #else
27 #include <GLES2/gl2.h>  /* use OpenGL ES 2.x */
28 #endif
29 #include <EGL/egl.h>
30
31
32 #define FLOAT_TO_FIXED(X)   ((X) * 65535.0)
33
34
35
36 static GLfloat view_rotx = 0.0, view_roty = 0.0;
37
38 static GLint u_matrix = -1;
39 static GLint attr_pos = 0, attr_color = 1;
40
41
42 static void
43 make_z_rot_matrix(GLfloat angle, GLfloat *m)
44 {
45    float c = cos(angle * M_PI / 180.0);
46    float s = sin(angle * M_PI / 180.0);
47    int i;
48    for (i = 0; i < 16; i++)
49       m[i] = 0.0;
50    m[0] = m[5] = m[10] = m[15] = 1.0;
51
52    m[0] = c;
53    m[1] = s;
54    m[4] = -s;
55    m[5] = c;
56 }
57
58 static void
59 make_scale_matrix(GLfloat xs, GLfloat ys, GLfloat zs, GLfloat *m)
60 {
61    int i;
62    for (i = 0; i < 16; i++)
63       m[i] = 0.0;
64    m[0] = xs;
65    m[5] = ys;
66    m[10] = zs;
67    m[15] = 1.0;
68 }
69
70
71 static void
72 mul_matrix(GLfloat *prod, const GLfloat *a, const GLfloat *b)
73 {
74 #define A(row,col)  a[(col<<2)+row]
75 #define B(row,col)  b[(col<<2)+row]
76 #define P(row,col)  p[(col<<2)+row]
77    GLfloat p[16];
78    GLint i;
79    for (i = 0; i < 4; i++) {
80       const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
81       P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
82       P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
83       P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
84       P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
85    }
86    memcpy(prod, p, sizeof(p));
87 #undef A
88 #undef B
89 #undef PROD
90 }
91
92
93 static void
94 draw(void)
95 {
96    static const GLfloat verts[3][2] = {
97       { -1, -1 },
98       {  1, -1 },
99       {  0,  1 }
100    };
101    static const GLfloat colors[3][3] = {
102       { 1, 0, 0 },
103       { 0, 1, 0 },
104       { 0, 0, 1 }
105    };
106    GLfloat mat[16], rot[16], scale[16];
107
108    /* Set modelview/projection matrix */
109    make_z_rot_matrix(view_rotx, rot);
110    make_scale_matrix(0.5, 0.5, 0.5, scale);
111    mul_matrix(mat, rot, scale);
112    glUniformMatrix4fv(u_matrix, 1, GL_FALSE, mat);
113
114    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
115
116    {
117       glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
118       glVertexAttribPointer(attr_color, 3, GL_FLOAT, GL_FALSE, 0, colors);
119       glEnableVertexAttribArray(attr_pos);
120       glEnableVertexAttribArray(attr_color);
121
122       glDrawArrays(GL_TRIANGLES, 0, 3);
123
124       glDisableVertexAttribArray(attr_pos);
125       glDisableVertexAttribArray(attr_color);
126    }
127 }
128
129
130 /* new window size or exposure */
131 static void
132 reshape(int width, int height)
133 {
134    glViewport(0, 0, (GLint) width, (GLint) height);
135 }
136
137
138 static void
139 create_shaders(void)
140 {
141    static const char *fragShaderText =
142       "varying vec4 v_color;\n"
143       "void main() {\n"
144       "   gl_FragColor = v_color;\n"
145       "}\n";
146    static const char *vertShaderText =
147       "uniform mat4 modelviewProjection;\n"
148       "attribute vec4 pos;\n"
149       "attribute vec4 color;\n"
150       "varying vec4 v_color;\n"
151       "void main() {\n"
152       "   gl_Position = modelviewProjection * pos;\n"
153       "   v_color = color;\n"
154       "}\n";
155
156    GLuint fragShader, vertShader, program;
157    GLint stat;
158
159    fragShader = glCreateShader(GL_FRAGMENT_SHADER);
160    glShaderSource(fragShader, 1, (const char **) &fragShaderText, NULL);
161    glCompileShader(fragShader);
162    glGetShaderiv(fragShader, GL_COMPILE_STATUS, &stat);
163    if (!stat) {
164       printf("Error: fragment shader did not compile!\n");
165       exit(1);
166    }
167
168    vertShader = glCreateShader(GL_VERTEX_SHADER);
169    glShaderSource(vertShader, 1, (const char **) &vertShaderText, NULL);
170    glCompileShader(vertShader);
171    glGetShaderiv(vertShader, GL_COMPILE_STATUS, &stat);
172    if (!stat) {
173       printf("Error: vertex shader did not compile!\n");
174       exit(1);
175    }
176
177    program = glCreateProgram();
178    glAttachShader(program, fragShader);
179    glAttachShader(program, vertShader);
180    glLinkProgram(program);
181
182    glGetProgramiv(program, GL_LINK_STATUS, &stat);
183    if (!stat) {
184       char log[1000];
185       GLsizei len;
186       glGetProgramInfoLog(program, 1000, &len, log);
187       printf("Error: linking:\n%s\n", log);
188       exit(1);
189    }
190
191    glUseProgram(program);
192
193    if (1) {
194       /* test setting attrib locations */
195       glBindAttribLocation(program, attr_pos, "pos");
196       glBindAttribLocation(program, attr_color, "color");
197       glLinkProgram(program);  /* needed to put attribs into effect */
198    }
199    else {
200       /* test automatic attrib locations */
201       attr_pos = glGetAttribLocation(program, "pos");
202       attr_color = glGetAttribLocation(program, "color");
203    }
204
205    u_matrix = glGetUniformLocation(program, "modelviewProjection");
206    printf("Uniform modelviewProjection at %d\n", u_matrix);
207    printf("Attrib pos at %d\n", attr_pos);
208    printf("Attrib color at %d\n", attr_color);
209 }
210
211
212 static void
213 init(void)
214 {
215    typedef void (*proc)();
216
217 #if 1 /* test code */
218    proc p = eglGetProcAddress("glMapBufferOES");
219    assert(p);
220 #endif
221
222    glClearColor(0.4, 0.4, 0.4, 0.0);
223
224    create_shaders();
225 }
226
227
228 /*
229  * Create an RGB, double-buffered X window.
230  * Return the window and context handles.
231  */
232 static void
233 make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
234               const char *name,
235               int x, int y, int width, int height,
236               Window *winRet,
237               EGLContext *ctxRet,
238               EGLSurface *surfRet)
239 {
240    static const EGLint attribs[] = {
241       EGL_RED_SIZE, 1,
242       EGL_GREEN_SIZE, 1,
243       EGL_BLUE_SIZE, 1,
244       EGL_DEPTH_SIZE, 1,
245       EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
246       EGL_NONE
247    };
248 #if USE_FULL_GL
249    static const EGLint ctx_attribs[] = {
250        EGL_NONE
251    };
252 #else
253    static const EGLint ctx_attribs[] = {
254       EGL_CONTEXT_CLIENT_VERSION, 2,
255       EGL_NONE
256    };
257 #endif
258
259    int scrnum;
260    XSetWindowAttributes attr;
261    unsigned long mask;
262    Window root;
263    Window win;
264    XVisualInfo *visInfo, visTemplate;
265    int num_visuals;
266    EGLContext ctx;
267    EGLConfig config;
268    EGLint num_configs;
269    EGLint vid;
270
271    scrnum = DefaultScreen( x_dpy );
272    root = RootWindow( x_dpy, scrnum );
273
274    if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
275       printf("Error: couldn't get an EGL visual config\n");
276       exit(1);
277    }
278
279    assert(config);
280    assert(num_configs > 0);
281
282    if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
283       printf("Error: eglGetConfigAttrib() failed\n");
284       exit(1);
285    }
286
287    /* The X window visual must match the EGL config */
288    visTemplate.visualid = vid;
289    visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
290    if (!visInfo) {
291       printf("Error: couldn't get X visual\n");
292       exit(1);
293    }
294
295    /* window attributes */
296    attr.background_pixel = 0;
297    attr.border_pixel = 0;
298    attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
299    attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
300    mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
301
302    win = XCreateWindow( x_dpy, root, 0, 0, width, height,
303                         0, visInfo->depth, InputOutput,
304                         visInfo->visual, mask, &attr );
305
306    /* set hints and properties */
307    {
308       XSizeHints sizehints;
309       sizehints.x = x;
310       sizehints.y = y;
311       sizehints.width  = width;
312       sizehints.height = height;
313       sizehints.flags = USSize | USPosition;
314       XSetNormalHints(x_dpy, win, &sizehints);
315       XSetStandardProperties(x_dpy, win, name, name,
316                               None, (char **)NULL, 0, &sizehints);
317    }
318
319 #if USE_FULL_GL /* XXX fix this when eglBindAPI() works */
320    eglBindAPI(EGL_OPENGL_API);
321 #else
322    eglBindAPI(EGL_OPENGL_ES_API);
323 #endif
324
325    ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
326    if (!ctx) {
327       printf("Error: eglCreateContext failed\n");
328       exit(1);
329    }
330
331 #if !USE_FULL_GL
332    /* test eglQueryContext() */
333    {
334       EGLint val;
335       eglQueryContext(egl_dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &val);
336       assert(val == 2);
337    }
338 #endif
339
340    *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
341    if (!*surfRet) {
342       printf("Error: eglCreateWindowSurface failed\n");
343       exit(1);
344    }
345
346    /* sanity checks */
347    {
348       EGLint val;
349       eglQuerySurface(egl_dpy, *surfRet, EGL_WIDTH, &val);
350       assert(val == width);
351       eglQuerySurface(egl_dpy, *surfRet, EGL_HEIGHT, &val);
352       assert(val == height);
353       assert(eglGetConfigAttrib(egl_dpy, config, EGL_SURFACE_TYPE, &val));
354       assert(val & EGL_WINDOW_BIT);
355    }
356
357    XFree(visInfo);
358
359    *winRet = win;
360    *ctxRet = ctx;
361 }
362
363
364 static void
365 event_loop(Display *dpy, Window win,
366            EGLDisplay egl_dpy, EGLSurface egl_surf)
367 {
368    while (1) {
369       int redraw = 0;
370       XEvent event;
371
372       XNextEvent(dpy, &event);
373
374       switch (event.type) {
375       case Expose:
376          redraw = 1;
377          break;
378       case ConfigureNotify:
379          reshape(event.xconfigure.width, event.xconfigure.height);
380          break;
381       case KeyPress:
382          {
383             char buffer[10];
384             int r, code;
385             code = XLookupKeysym(&event.xkey, 0);
386             if (code == XK_Left) {
387                view_roty += 5.0;
388             }
389             else if (code == XK_Right) {
390                view_roty -= 5.0;
391             }
392             else if (code == XK_Up) {
393                view_rotx += 5.0;
394             }
395             else if (code == XK_Down) {
396                view_rotx -= 5.0;
397             }
398             else {
399                r = XLookupString(&event.xkey, buffer, sizeof(buffer),
400                                  NULL, NULL);
401                if (buffer[0] == 27) {
402                   /* escape */
403                   return;
404                }
405             }
406          }
407          redraw = 1;
408          break;
409       default:
410          ; /*no-op*/
411       }
412
413       if (redraw) {
414          draw();
415          eglSwapBuffers(egl_dpy, egl_surf);
416          exit(0);
417       }
418    }
419 }
420
421
422 static void
423 usage(void)
424 {
425    printf("Usage:\n");
426    printf("  -display <displayname>  set the display to run on\n");
427    printf("  -info                   display OpenGL renderer info\n");
428 }
429
430
431 int
432 main(int argc, char *argv[])
433 {
434    const int winWidth = 300, winHeight = 300;
435    Display *x_dpy;
436    Window win;
437    EGLSurface egl_surf;
438    EGLContext egl_ctx;
439    EGLDisplay egl_dpy;
440    char *dpyName = NULL;
441    GLboolean printInfo = GL_FALSE;
442    EGLint egl_major, egl_minor;
443    int i;
444    const char *s;
445
446    for (i = 1; i < argc; i++) {
447       if (strcmp(argv[i], "-display") == 0) {
448          dpyName = argv[i+1];
449          i++;
450       }
451       else if (strcmp(argv[i], "-info") == 0) {
452          printInfo = GL_TRUE;
453       }
454       else {
455          usage();
456          return -1;
457       }
458    }
459
460    x_dpy = XOpenDisplay(dpyName);
461    if (!x_dpy) {
462       printf("Error: couldn't open display %s\n",
463              dpyName ? dpyName : getenv("DISPLAY"));
464       return -1;
465    }
466
467    egl_dpy = eglGetDisplay(x_dpy);
468    if (!egl_dpy) {
469       printf("Error: eglGetDisplay() failed\n");
470       return -1;
471    }
472
473    if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
474       printf("Error: eglInitialize() failed\n");
475       return -1;
476    }
477
478    s = eglQueryString(egl_dpy, EGL_VERSION);
479    printf("EGL_VERSION = %s\n", s);
480
481    s = eglQueryString(egl_dpy, EGL_VENDOR);
482    printf("EGL_VENDOR = %s\n", s);
483
484    s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
485    printf("EGL_EXTENSIONS = %s\n", s);
486
487    s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
488    printf("EGL_CLIENT_APIS = %s\n", s);
489
490    make_x_window(x_dpy, egl_dpy,
491                  "OpenGL ES 2.x tri", 0, 0, winWidth, winHeight,
492                  &win, &egl_ctx, &egl_surf);
493
494    XMapWindow(x_dpy, win);
495    if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
496       printf("Error: eglMakeCurrent() failed\n");
497       return -1;
498    }
499
500    if (printInfo) {
501       printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
502       printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
503       printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
504       printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
505    }
506
507    init();
508
509    /* Set initial projection/viewing transformation.
510     * We can't be sure we'll get a ConfigureNotify event when the window
511     * first appears.
512     */
513    reshape(winWidth, winHeight);
514
515    event_loop(x_dpy, win, egl_dpy, egl_surf);
516
517    eglDestroyContext(egl_dpy, egl_ctx);
518    eglDestroySurface(egl_dpy, egl_surf);
519    eglTerminate(egl_dpy);
520
521
522    XDestroyWindow(x_dpy, win);
523    XCloseDisplay(x_dpy);
524
525    return 0;
526 }