2 * Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
6 * Test EGL render to texture.
18 #include <X11/Xutil.h>
19 #include <X11/keysym.h>
21 #include <GLES/glext.h>
25 static int TexWidth
= 256, TexHeight
= 256;
27 static int WinWidth
= 300, WinHeight
= 300;
29 static GLfloat view_rotx
= 0.0, view_roty
= 0.0, view_rotz
= 0.0;
31 static GLuint DotTexture
, RenderTexture
;
35 Normal(GLfloat
*n
, GLfloat nx
, GLfloat ny
, GLfloat nz
)
43 Vertex(GLfloat
*v
, GLfloat vx
, GLfloat vy
, GLfloat vz
)
51 Texcoord(GLfloat
*v
, GLfloat s
, GLfloat t
)
58 /* Borrowed from glut, adapted */
60 draw_torus(GLfloat r
, GLfloat R
, GLint nsides
, GLint rings
)
63 GLfloat theta
, phi
, theta1
;
64 GLfloat cosTheta
, sinTheta
;
65 GLfloat cosTheta1
, sinTheta1
;
66 GLfloat ringDelta
, sideDelta
;
67 GLfloat varray
[100][3], narray
[100][3], tarray
[100][2];
70 glVertexPointer(3, GL_FLOAT
, 0, varray
);
71 glNormalPointer(GL_FLOAT
, 0, narray
);
72 glTexCoordPointer(2, GL_FLOAT
, 0, tarray
);
73 glEnableClientState(GL_VERTEX_ARRAY
);
74 glEnableClientState(GL_NORMAL_ARRAY
);
75 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
77 ringDelta
= 2.0 * M_PI
/ rings
;
78 sideDelta
= 2.0 * M_PI
/ nsides
;
83 for (i
= rings
- 1; i
>= 0; i
--) {
84 theta1
= theta
+ ringDelta
;
85 cosTheta1
= cos(theta1
);
86 sinTheta1
= sin(theta1
);
88 vcount
= 0; /* glBegin(GL_QUAD_STRIP); */
91 for (j
= nsides
; j
>= 0; j
--) {
93 GLfloat cosPhi
, sinPhi
, dist
;
98 dist
= R
+ r
* cosPhi
;
100 s0
= 20.0 * theta
/ (2.0 * M_PI
);
101 s1
= 20.0 * theta1
/ (2.0 * M_PI
);
102 t
= 8.0 * phi
/ (2.0 * M_PI
);
104 Normal(narray
[vcount
], cosTheta1
* cosPhi
, -sinTheta1
* cosPhi
, sinPhi
);
105 Texcoord(tarray
[vcount
], s1
, t
);
106 Vertex(varray
[vcount
], cosTheta1
* dist
, -sinTheta1
* dist
, r
* sinPhi
);
109 Normal(narray
[vcount
], cosTheta
* cosPhi
, -sinTheta
* cosPhi
, sinPhi
);
110 Texcoord(tarray
[vcount
], s0
, t
);
111 Vertex(varray
[vcount
], cosTheta
* dist
, -sinTheta
* dist
, r
* sinPhi
);
116 assert(vcount
<= 100);
117 glDrawArrays(GL_TRIANGLE_STRIP
, 0, vcount
);
120 cosTheta
= cosTheta1
;
121 sinTheta
= sinTheta1
;
124 glDisableClientState(GL_VERTEX_ARRAY
);
125 glDisableClientState(GL_NORMAL_ARRAY
);
126 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
131 draw_torus_to_texture(void)
133 glViewport(0, 0, TexWidth
, TexHeight
);
135 glMatrixMode(GL_PROJECTION
);
137 glFrustumf(-1, 1, -1, 1, 5.0, 60.0);
139 glMatrixMode(GL_MODELVIEW
);
141 glTranslatef(0.0, 0.0, -15.0);
143 glClearColor(0.4, 0.4, 0.4, 0.0);
144 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
146 glBindTexture(GL_TEXTURE_2D
, DotTexture
);
148 glEnable(GL_LIGHTING
);
151 glRotatef(view_roty
, 0, 1, 0);
152 glScalef(0.5, 0.5, 0.5);
154 draw_torus(1.0, 3.0, 30, 60);
158 glDisable(GL_LIGHTING
);
161 glBindTexture(GL_TEXTURE_2D
, RenderTexture
);
162 glCopyTexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, 0, 0, TexWidth
, TexHeight
);
170 draw_textured_quad(void)
172 GLfloat ar
= (GLfloat
) WinWidth
/ (GLfloat
) WinHeight
;
174 glViewport(0, 0, WinWidth
, WinHeight
);
176 glMatrixMode(GL_PROJECTION
);
178 glFrustumf(-ar
, ar
, -1, 1, 5.0, 60.0);
180 glMatrixMode(GL_MODELVIEW
);
182 glTranslatef(0.0, 0.0, -8.0);
184 glClearColor(0.4, 0.4, 1.0, 0.0);
185 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
187 glBindTexture(GL_TEXTURE_2D
, RenderTexture
);
190 glRotatef(view_rotx
, 1, 0, 0);
191 glRotatef(view_rotz
, 0, 0, 1);
194 static const GLfloat texcoord
[4][2] = {
195 { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 }
197 static const GLfloat vertex
[4][2] = {
198 { -1, -1 }, { 1, -1 }, { -1, 1 }, { 1, 1 }
201 glVertexPointer(2, GL_FLOAT
, 0, vertex
);
202 glTexCoordPointer(2, GL_FLOAT
, 0, texcoord
);
203 glEnableClientState(GL_VERTEX_ARRAY
);
204 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
206 glDrawArrays(GL_TRIANGLE_STRIP
, 0, 4);
208 glDisableClientState(GL_VERTEX_ARRAY
);
209 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
218 draw(EGLDisplay egl_dpy
, EGLSurface egl_surf
, EGLSurface egl_pbuf
,
221 /*printf("Begin draw\n");*/
223 /* first draw torus to pbuffer /texture */
225 if (!eglMakeCurrent(egl_dpy
, egl_pbuf
, egl_pbuf
, egl_ctx
)) {
227 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
229 printf("Error: eglMakeCurrent(pbuf) failed\n");
232 draw_torus_to_texture();
234 /* draw textured quad to window */
235 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
236 printf("Error: eglMakeCurrent(pbuffer) failed\n");
240 glBindTexture(GL_TEXTURE_2D
, RenderTexture
);
241 eglBindTexImage(egl_dpy
, egl_pbuf
, EGL_BACK_BUFFER
);
242 draw_textured_quad();
243 eglReleaseTexImage(egl_dpy
, egl_pbuf
, EGL_BACK_BUFFER
);
245 eglSwapBuffers(egl_dpy
, egl_surf
);
247 /*printf("End draw\n");*/
253 make_dot_texture(void)
256 GLenum Filter
= GL_LINEAR
;
257 GLubyte image
[SZ
][SZ
][4];
260 for (i
= 0; i
< SZ
; i
++) {
261 for (j
= 0; j
< SZ
; j
++) {
262 GLfloat d
= (i
- SZ
/2) * (i
- SZ
/2) + (j
- SZ
/2) * (j
- SZ
/2);
265 image
[i
][j
][0] = 255;
266 image
[i
][j
][1] = 255;
267 image
[i
][j
][2] = 255;
268 image
[i
][j
][3] = 255;
271 image
[i
][j
][0] = 127;
272 image
[i
][j
][1] = 127;
273 image
[i
][j
][2] = 127;
274 image
[i
][j
][3] = 255;
279 glGenTextures(1, &DotTexture
);
280 glBindTexture(GL_TEXTURE_2D
, DotTexture
);
281 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, SZ
, SZ
, 0,
282 GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
283 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, Filter
);
284 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, Filter
);
285 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
286 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
292 make_render_texture(void)
294 GLenum Filter
= GL_LINEAR
;
295 glGenTextures(1, &RenderTexture
);
296 glBindTexture(GL_TEXTURE_2D
, RenderTexture
);
297 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, TexWidth
, TexHeight
, 0,
298 GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
299 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, Filter
);
300 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, Filter
);
301 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
302 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
309 static const GLfloat red
[4] = {1, 0, 0, 0};
310 static const GLfloat white
[4] = {1.0, 1.0, 1.0, 1.0};
311 static const GLfloat diffuse
[4] = {0.7, 0.7, 0.7, 1.0};
312 static const GLfloat specular
[4] = {0.001, 0.001, 0.001, 1.0};
313 static const GLfloat pos
[4] = {20, 20, 50, 1};
315 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, red
);
316 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, white
);
317 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 9.0);
320 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
321 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, diffuse
);
322 glLightfv(GL_LIGHT0
, GL_SPECULAR
, specular
);
324 glEnable(GL_DEPTH_TEST
);
327 make_render_texture();
329 printf("DotTexture=%u RenderTexture=%u\n", DotTexture
, RenderTexture
);
331 glEnable(GL_TEXTURE_2D
);
336 * Create an RGB, double-buffered X window.
337 * Return the window and context handles.
340 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
342 int x
, int y
, int width
, int height
,
347 static const EGLint attribs
[] = {
356 XSetWindowAttributes attr
;
360 XVisualInfo
*visInfo
, visTemplate
;
367 scrnum
= DefaultScreen( x_dpy
);
368 root
= RootWindow( x_dpy
, scrnum
);
370 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
371 printf("Error: couldn't get an EGL visual config\n");
376 assert(num_configs
> 0);
378 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
379 printf("Error: eglGetConfigAttrib() failed\n");
383 /* The X window visual must match the EGL config */
384 visTemplate
.visualid
= vid
;
385 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
387 printf("Error: couldn't get X visual\n");
391 /* window attributes */
392 attr
.background_pixel
= 0;
393 attr
.border_pixel
= 0;
394 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
395 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
396 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
398 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
399 0, visInfo
->depth
, InputOutput
,
400 visInfo
->visual
, mask
, &attr
);
402 /* set hints and properties */
404 XSizeHints sizehints
;
407 sizehints
.width
= width
;
408 sizehints
.height
= height
;
409 sizehints
.flags
= USSize
| USPosition
;
410 XSetNormalHints(x_dpy
, win
, &sizehints
);
411 XSetStandardProperties(x_dpy
, win
, name
, name
,
412 None
, (char **)NULL
, 0, &sizehints
);
415 eglBindAPI(EGL_OPENGL_ES_API
);
417 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
419 printf("Error: eglCreateContext failed\n");
423 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
426 printf("Error: eglCreateWindowSurface failed\n");
438 make_pbuffer(Display
*x_dpy
, EGLDisplay egl_dpy
, int width
, int height
)
440 static const EGLint config_attribs
[] = {
450 EGLint pbuf_attribs
[15];
453 pbuf_attribs
[i
++] = EGL_WIDTH
;
454 pbuf_attribs
[i
++] = width
;
455 pbuf_attribs
[i
++] = EGL_HEIGHT
;
456 pbuf_attribs
[i
++] = height
;
457 pbuf_attribs
[i
++] = EGL_TEXTURE_FORMAT
;
458 pbuf_attribs
[i
++] = EGL_TEXTURE_RGBA
;
459 pbuf_attribs
[i
++] = EGL_TEXTURE_TARGET
;
460 pbuf_attribs
[i
++] = EGL_TEXTURE_2D
;
461 pbuf_attribs
[i
++] = EGL_MIPMAP_TEXTURE
;
462 pbuf_attribs
[i
++] = EGL_FALSE
;
463 pbuf_attribs
[i
++] = EGL_NONE
;
466 if (!eglChooseConfig( egl_dpy
, config_attribs
, &config
, 1, &num_configs
)) {
467 printf("Error: couldn't get an EGL config for pbuffer\n");
471 pbuf
= eglCreatePbufferSurface(egl_dpy
, config
, pbuf_attribs
);
478 event_loop(Display
*dpy
, Window win
,
479 EGLDisplay egl_dpy
, EGLSurface egl_surf
, EGLSurface egl_pbuf
,
487 if (!anim
|| XPending(dpy
)) {
489 XNextEvent(dpy
, &event
);
491 switch (event
.type
) {
495 case ConfigureNotify
:
496 if (event
.xconfigure
.window
== win
) {
497 WinWidth
= event
.xconfigure
.width
;
498 WinHeight
= event
.xconfigure
.height
;
505 code
= XLookupKeysym(&event
.xkey
, 0);
506 if (code
== XK_Left
) {
509 else if (code
== XK_Right
) {
512 else if (code
== XK_Up
) {
515 else if (code
== XK_Down
) {
519 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
521 if (buffer
[0] == ' ') {
524 else if (buffer
[0] == 'z') {
527 else if (buffer
[0] == 'Z') {
530 else if (buffer
[0] == 27) {
550 draw(egl_dpy
, egl_surf
, egl_pbuf
, egl_ctx
);
560 printf(" -display <displayname> set the display to run on\n");
561 printf(" -info display OpenGL renderer info\n");
566 main(int argc
, char *argv
[])
570 EGLSurface egl_surf
, egl_pbuf
;
573 char *dpyName
= NULL
;
574 GLboolean printInfo
= GL_FALSE
;
575 EGLint egl_major
, egl_minor
;
579 for (i
= 1; i
< argc
; i
++) {
580 if (strcmp(argv
[i
], "-display") == 0) {
584 else if (strcmp(argv
[i
], "-info") == 0) {
593 x_dpy
= XOpenDisplay(dpyName
);
595 printf("Error: couldn't open display %s\n",
596 dpyName
? dpyName
: getenv("DISPLAY"));
600 egl_dpy
= eglGetDisplay(x_dpy
);
602 printf("Error: eglGetDisplay() failed\n");
606 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
607 printf("Error: eglInitialize() failed\n");
611 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
612 printf("EGL_VERSION = %s\n", s
);
614 s
= eglQueryString(egl_dpy
, EGL_VENDOR
);
615 printf("EGL_VENDOR = %s\n", s
);
617 s
= eglQueryString(egl_dpy
, EGL_EXTENSIONS
);
618 printf("EGL_EXTENSIONS = %s\n", s
);
620 s
= eglQueryString(egl_dpy
, EGL_CLIENT_APIS
);
621 printf("EGL_CLIENT_APIS = %s\n", s
);
623 make_x_window(x_dpy
, egl_dpy
,
624 "render_tex", 0, 0, WinWidth
, WinHeight
,
625 &win
, &egl_ctx
, &egl_surf
);
627 egl_pbuf
= make_pbuffer(x_dpy
, egl_dpy
, TexWidth
, TexHeight
);
629 printf("Error: eglCreatePBufferSurface() failed\n");
633 XMapWindow(x_dpy
, win
);
634 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
635 printf("Error: eglMakeCurrent() failed\n");
640 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
641 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
642 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
643 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
648 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
, egl_pbuf
, egl_ctx
);
650 eglDestroyContext(egl_dpy
, egl_ctx
);
651 eglDestroySurface(egl_dpy
, egl_surf
);
652 eglTerminate(egl_dpy
);
655 XDestroyWindow(x_dpy
, win
);
656 XCloseDisplay(x_dpy
);