bindtex.c revision 32001f49
1/* 2 * Simple demo for eglBindTexImage. Based on xegl_tri.c by 3 * 4 * Copyright (C) 2008 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24/* 25 * The spec says that eglBindTexImage supports only OpenGL ES context, but this 26 * demo uses OpenGL context. Keep in mind that this is non-standard. 27 */ 28 29#include <math.h> 30#include <stdlib.h> 31#include <stdio.h> 32#include <string.h> 33#include <X11/Xlib.h> 34#include <X11/Xutil.h> 35#include <X11/keysym.h> 36#include <GLES/gl.h> 37#include <EGL/egl.h> 38 39static EGLDisplay dpy; 40static EGLContext ctx_win, ctx_pbuf; 41static EGLSurface surf_win, surf_pbuf; 42static GLuint tex_pbuf; 43 44static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0; 45static GLboolean blend = GL_TRUE; 46static GLuint color_flow; 47 48static void 49make_pbuffer(int width, int height) 50{ 51 static const EGLint config_attribs[] = { 52 EGL_RED_SIZE, 8, 53 EGL_GREEN_SIZE, 8, 54 EGL_BLUE_SIZE, 8, 55 EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE, 56 EGL_NONE 57 }; 58 EGLint pbuf_attribs[] = { 59 EGL_WIDTH, width, 60 EGL_HEIGHT, height, 61 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB, 62 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, 63 EGL_NONE 64 }; 65 EGLConfig config; 66 EGLint num_configs; 67 68 if (!eglChooseConfig(dpy, config_attribs, &config, 1, &num_configs) || 69 !num_configs) { 70 printf("Error: couldn't get an EGL visual config for pbuffer\n"); 71 exit(1); 72 } 73 74 ctx_pbuf = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL ); 75 surf_pbuf = eglCreatePbufferSurface(dpy, config, pbuf_attribs); 76 if (surf_pbuf == EGL_NO_SURFACE) { 77 printf("failed to allocate pbuffer\n"); 78 exit(1); 79 } 80} 81 82static void 83use_pbuffer(void) 84{ 85 static int initialized; 86 87 eglMakeCurrent(dpy, surf_pbuf, surf_pbuf, ctx_pbuf); 88 if (!initialized) { 89 EGLint width, height; 90 GLfloat ar; 91 92 initialized = 1; 93 94 eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &width); 95 eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &height); 96 ar = (GLfloat) width / (GLfloat) height; 97 98 glViewport(0, 0, (GLint) width, (GLint) height); 99 100 glMatrixMode(GL_PROJECTION); 101 glLoadIdentity(); 102 glFrustumf(-ar, ar, -1, 1, 1.0, 10.0); 103 104 glMatrixMode(GL_MODELVIEW); 105 glLoadIdentity(); 106 107 /* y-inverted */ 108 glScalef(1.0, -1.0, 1.0); 109 110 glTranslatef(0.0, 0.0, -5.0); 111 112 glClearColor(0.2, 0.2, 0.2, 0.0); 113 114 glGenTextures(1, &tex_pbuf); 115 } 116} 117 118static void 119make_window(Display *x_dpy, const char *name, 120 int x, int y, int width, int height, 121 Window *winRet) 122{ 123 static const EGLint attribs[] = { 124 EGL_RED_SIZE, 8, 125 EGL_GREEN_SIZE, 8, 126 EGL_BLUE_SIZE, 8, 127 EGL_ALPHA_SIZE, 8, 128 EGL_DEPTH_SIZE, 8, 129 EGL_NONE 130 }; 131 132 int scrnum; 133 XSetWindowAttributes attr; 134 unsigned long mask; 135 Window root; 136 Window win; 137 XVisualInfo *visInfo, visTemplate; 138 int num_visuals; 139 EGLConfig config; 140 EGLint num_configs, vid; 141 142 scrnum = DefaultScreen( x_dpy ); 143 root = RootWindow( x_dpy, scrnum ); 144 145 if (!eglChooseConfig(dpy, attribs, &config, 1, &num_configs) || 146 !num_configs) { 147 printf("Error: couldn't get an EGL visual config\n"); 148 exit(1); 149 } 150 151 if (!eglGetConfigAttrib(dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { 152 printf("Error: eglGetConfigAttrib() failed\n"); 153 exit(1); 154 } 155 156 /* The X window visual must match the EGL config */ 157 visTemplate.visualid = vid; 158 visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals); 159 if (!visInfo) { 160 printf("Error: couldn't get X visual\n"); 161 exit(1); 162 } 163 164 /* window attributes */ 165 attr.background_pixel = 0; 166 attr.border_pixel = 0; 167 attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone); 168 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 169 attr.override_redirect = 0; 170 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; 171 172 win = XCreateWindow( x_dpy, root, 0, 0, width, height, 173 0, visInfo->depth, InputOutput, 174 visInfo->visual, mask, &attr ); 175 176 /* set hints and properties */ 177 { 178 XSizeHints sizehints; 179 sizehints.x = x; 180 sizehints.y = y; 181 sizehints.width = width; 182 sizehints.height = height; 183 sizehints.flags = USSize | USPosition; 184 XSetNormalHints(x_dpy, win, &sizehints); 185 XSetStandardProperties(x_dpy, win, name, name, 186 None, (char **)NULL, 0, &sizehints); 187 } 188 189 ctx_win = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL ); 190 if (!ctx_win) { 191 printf("Error: eglCreateContext failed\n"); 192 exit(1); 193 } 194 195 surf_win = eglCreateWindowSurface(dpy, config, win, NULL); 196 197 XFree(visInfo); 198 199 *winRet = win; 200} 201 202static void 203use_window(void) 204{ 205 static int initialized; 206 207 eglMakeCurrent(dpy, surf_win, surf_win, ctx_win); 208 if (!initialized) { 209 initialized = 1; 210 glEnable(GL_TEXTURE_2D); 211 glBindTexture(GL_TEXTURE_2D, tex_pbuf); 212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 213 214 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 215 } 216} 217 218static void 219draw_triangle(void) 220{ 221 static const GLfloat verts[3][2] = { 222 { -3, -3 }, 223 { 3, -3 }, 224 { 0, 3 } 225 }; 226 GLfloat colors[3][4] = { 227 { 1, 0, 0, 1 }, 228 { 0, 1, 0, 1 }, 229 { 0, 0, 1, 1 } 230 }; 231 GLint i; 232 233 /* flow the color */ 234 for (i = 0; i < 3; i++) { 235 GLint first = (i + color_flow / 256) % 3; 236 GLint second = (first + 1) % 3; 237 GLint third = (second + 1) % 3; 238 GLfloat c = (color_flow % 256) / 256.0f; 239 240 c = c * c * c; 241 colors[i][first] = 1.0f - c; 242 colors[i][second] = c; 243 colors[i][third] = 0.0f; 244 } 245 246 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 247 248 glVertexPointer(2, GL_FLOAT, 0, verts); 249 glColorPointer(4, GL_FLOAT, 0, colors); 250 glEnableClientState(GL_VERTEX_ARRAY); 251 glEnableClientState(GL_COLOR_ARRAY); 252 253 glDrawArrays(GL_TRIANGLES, 0, 3); 254 255 glDisableClientState(GL_VERTEX_ARRAY); 256 glDisableClientState(GL_COLOR_ARRAY); 257} 258 259static void 260draw_textured_cube(void) 261{ 262 static const GLfloat verts[][2] = { 263 { -4, -4 }, 264 { 4, -4 }, 265 { 4, 4 }, 266 { -4, 4 } 267 }; 268 static const GLfloat colors[][4] = { 269 { 1, 1, 1, 0.5 }, 270 { 1, 1, 1, 0.5 }, 271 { 1, 1, 1, 0.5 }, 272 { 1, 1, 1, 0.5 } 273 }; 274 static const GLfloat texs[][2] = { 275 { 0, 0 }, 276 { 1, 0 }, 277 { 1, 1 }, 278 { 0, 1 } 279 }; 280 static const GLfloat xforms[6][4] = { 281 { 0, 0, 1, 0 }, 282 { 90, 0, 1, 0 }, 283 { 180, 0, 1, 0 }, 284 { 270, 0, 1, 0 }, 285 { 90, 1, 0, 0 }, 286 { -90, 1, 0, 0 } 287 }; 288 GLint i; 289 290 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 291 292 if (blend) { 293 glDisable(GL_DEPTH_TEST); 294 glEnable(GL_BLEND); 295 } else { 296 glEnable(GL_DEPTH_TEST); 297 glDisable(GL_BLEND); 298 } 299 300 glVertexPointer(2, GL_FLOAT, 0, verts); 301 glColorPointer(4, GL_FLOAT, 0, colors); 302 glTexCoordPointer(2, GL_FLOAT, 0, texs); 303 304 glEnableClientState(GL_VERTEX_ARRAY); 305 glEnableClientState(GL_COLOR_ARRAY); 306 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 307 308 for (i = 0; i < 6; i++) { 309 glPushMatrix(); 310 glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]); 311 glTranslatef(0, 0, 4.1); 312 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 313 glPopMatrix(); 314 } 315 316 glDisableClientState(GL_VERTEX_ARRAY); 317 glDisableClientState(GL_COLOR_ARRAY); 318 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 319} 320 321static void 322draw(void) 323{ 324 use_pbuffer(); 325 draw_triangle(); 326 327 use_window(); 328 329 eglBindTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER); 330 331 glPushMatrix(); 332 glRotatef(view_rotx, 1, 0, 0); 333 glRotatef(view_roty, 0, 1, 0); 334 glRotatef(view_rotz, 0, 0, 1); 335 336 draw_textured_cube(); 337 338 glPopMatrix(); 339 340 eglReleaseTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER); 341} 342 343/* new window size or exposure */ 344static void 345reshape(int width, int height) 346{ 347 GLfloat ar = (GLfloat) width / (GLfloat) height; 348 349 use_window(); 350 351 glViewport(0, 0, (GLint) width, (GLint) height); 352 353 glMatrixMode(GL_PROJECTION); 354 glLoadIdentity(); 355 glFrustumf(-ar, ar, -1, 1, 5.0, 60.0); 356 357 glMatrixMode(GL_MODELVIEW); 358 glLoadIdentity(); 359 glTranslatef(0.0, 0.0, -40.0); 360} 361 362static void 363event_loop(Display *x_dpy, Window win) 364{ 365 while (1) { 366 int redraw = 1; 367 368 if (XPending(x_dpy) > 0) { 369 XEvent event; 370 XNextEvent(x_dpy, &event); 371 372 switch (event.type) { 373 case Expose: 374 redraw = 1; 375 break; 376 case ConfigureNotify: 377 reshape(event.xconfigure.width, event.xconfigure.height); 378 break; 379 case KeyPress: 380 { 381 char buffer[10]; 382 int r, code; 383 code = XLookupKeysym(&event.xkey, 0); 384 if (code == XK_Left) { 385 view_roty += 5.0; 386 } 387 else if (code == XK_Right) { 388 view_roty -= 5.0; 389 } 390 else if (code == XK_Up) { 391 view_rotx += 5.0; 392 } 393 else if (code == XK_Down) { 394 view_rotx -= 5.0; 395 } 396 else if (code == XK_b) { 397 blend = !blend; 398 } 399 else { 400 r = XLookupString(&event.xkey, buffer, sizeof(buffer), 401 NULL, NULL); 402 if (buffer[0] == 27) { 403 /* escape */ 404 return; 405 } 406 } 407 } 408 redraw = 1; 409 break; 410 default: 411 ; /*no-op*/ 412 } 413 } 414 415 if (redraw) { 416 view_rotx += 1.0; 417 view_roty += 2.0; 418 view_rotz += 1.5; 419 color_flow += 20; 420 draw(); 421 eglSwapBuffers(dpy, surf_win); 422 } 423 } 424} 425 426int 427main(int argc, char *argv[]) 428{ 429 const int winWidth = 300, winHeight = 300; 430 Display *x_dpy; 431 Window win; 432 char *dpyName = NULL; 433 EGLint egl_major, egl_minor; 434 const char *s; 435 436 x_dpy = XOpenDisplay(dpyName); 437 if (!x_dpy) { 438 printf("Error: couldn't open display %s\n", 439 dpyName ? dpyName : getenv("DISPLAY")); 440 return -1; 441 } 442 443 dpy = eglGetDisplay(x_dpy); 444 if (!dpy) { 445 printf("Error: eglGetDisplay() failed\n"); 446 return -1; 447 } 448 449 if (!eglInitialize(dpy, &egl_major, &egl_minor)) { 450 printf("Error: eglInitialize() failed\n"); 451 return -1; 452 } 453 454 s = eglQueryString(dpy, EGL_VERSION); 455 printf("EGL_VERSION = %s\n", s); 456 457 make_window(x_dpy, "color flow", 0, 0, winWidth, winHeight, &win); 458 make_pbuffer(winWidth, winHeight); 459 460 XMapWindow(x_dpy, win); 461 462 reshape(winWidth, winHeight); 463 event_loop(x_dpy, win); 464 465 glDeleteTextures(1, &tex_pbuf); 466 467 eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 468 eglTerminate(dpy); 469 470 XDestroyWindow(x_dpy, win); 471 XCloseDisplay(x_dpy); 472 473 return 0; 474} 475