]> git.cworth.org Git - apitrace-tests/blob - apps/egl/gles2/tri.c
Add egl apps.
[apitrace-tests] / apps / egl / gles2 / tri.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 0
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       }
417    }
418 }
419
420
421 static void
422 usage(void)
423 {
424    printf("Usage:\n");
425    printf("  -display <displayname>  set the display to run on\n");
426    printf("  -info                   display OpenGL renderer info\n");
427 }
428
429
430 int
431 main(int argc, char *argv[])
432 {
433    const int winWidth = 300, winHeight = 300;
434    Display *x_dpy;
435    Window win;
436    EGLSurface egl_surf;
437    EGLContext egl_ctx;
438    EGLDisplay egl_dpy;
439    char *dpyName = NULL;
440    GLboolean printInfo = GL_FALSE;
441    EGLint egl_major, egl_minor;
442    int i;
443    const char *s;
444
445    for (i = 1; i < argc; i++) {
446       if (strcmp(argv[i], "-display") == 0) {
447          dpyName = argv[i+1];
448          i++;
449       }
450       else if (strcmp(argv[i], "-info") == 0) {
451          printInfo = GL_TRUE;
452       }
453       else {
454          usage();
455          return -1;
456       }
457    }
458
459    x_dpy = XOpenDisplay(dpyName);
460    if (!x_dpy) {
461       printf("Error: couldn't open display %s\n",
462              dpyName ? dpyName : getenv("DISPLAY"));
463       return -1;
464    }
465
466    egl_dpy = eglGetDisplay(x_dpy);
467    if (!egl_dpy) {
468       printf("Error: eglGetDisplay() failed\n");
469       return -1;
470    }
471
472    if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
473       printf("Error: eglInitialize() failed\n");
474       return -1;
475    }
476
477    s = eglQueryString(egl_dpy, EGL_VERSION);
478    printf("EGL_VERSION = %s\n", s);
479
480    s = eglQueryString(egl_dpy, EGL_VENDOR);
481    printf("EGL_VENDOR = %s\n", s);
482
483    s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
484    printf("EGL_EXTENSIONS = %s\n", s);
485
486    s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
487    printf("EGL_CLIENT_APIS = %s\n", s);
488
489    make_x_window(x_dpy, egl_dpy,
490                  "OpenGL ES 2.x tri", 0, 0, winWidth, winHeight,
491                  &win, &egl_ctx, &egl_surf);
492
493    XMapWindow(x_dpy, win);
494    if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
495       printf("Error: eglMakeCurrent() failed\n");
496       return -1;
497    }
498
499    if (printInfo) {
500       printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
501       printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
502       printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
503       printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
504    }
505
506    init();
507
508    /* Set initial projection/viewing transformation.
509     * We can't be sure we'll get a ConfigureNotify event when the window
510     * first appears.
511     */
512    reshape(winWidth, winHeight);
513
514    event_loop(x_dpy, win, egl_dpy, egl_surf);
515
516    eglDestroyContext(egl_dpy, egl_ctx);
517    eglDestroySurface(egl_dpy, egl_surf);
518    eglTerminate(egl_dpy);
519
520
521    XDestroyWindow(x_dpy, win);
522    XCloseDisplay(x_dpy);
523
524    return 0;
525 }