mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 15:58:05 +02:00
progs/es: OpenGL ES 1.x and 2.X demo programs.
The demo programs are written by Brian Paul, and cherry-picked from opengl-es branch. Several minor issues such as a linking problem are fixed. Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
This commit is contained in:
parent
d14ac1073c
commit
5b85cada60
11 changed files with 4461 additions and 0 deletions
77
progs/es1/xegl/Makefile
Normal file
77
progs/es1/xegl/Makefile
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# progs/es1/xegl/Makefile
|
||||
|
||||
TOP = ../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
INCLUDE_DIRS = \
|
||||
-I$(TOP)/include \
|
||||
|
||||
HEADERS = $(TOP)/include/GLES/egl.h
|
||||
|
||||
|
||||
ES1_LIB_DEPS = \
|
||||
$(TOP)/$(LIB_DIR)/libEGL.so \
|
||||
$(TOP)/$(LIB_DIR)/libGLESv1_CM.so
|
||||
|
||||
|
||||
ES1_LIBS = \
|
||||
-L$(TOP)/$(LIB_DIR) -lEGL \
|
||||
-L$(TOP)/$(LIB_DIR) -lGLESv1_CM $(LIBDRM_LIB) -lX11
|
||||
|
||||
PROGRAMS = \
|
||||
drawtex \
|
||||
es1_info \
|
||||
msaa \
|
||||
pbuffer \
|
||||
render_tex \
|
||||
torus \
|
||||
tri \
|
||||
two_win
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
default: $(PROGRAMS)
|
||||
|
||||
|
||||
|
||||
drawtex: drawtex.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) drawtex.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
es1_info: es1_info.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) es1_info.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
msaa: msaa.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) msaa.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
pbuffer: pbuffer.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) pbuffer.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
render_tex: render_tex.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) render_tex.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
torus: torus.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) torus.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
two_win: two_win.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) two_win.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
tri: tri.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) tri.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
rm -f $(PROGRAMS)
|
||||
|
||||
427
progs/es1/xegl/drawtex.c
Normal file
427
progs/es1/xegl/drawtex.c
Normal file
|
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test GL_OES_draw_texture
|
||||
* Brian Paul
|
||||
* August 2008
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
|
||||
static GLfloat view_posx = 10.0, view_posy = 20.0;
|
||||
static GLfloat width = 200, height = 200;
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glDrawTexfOES(view_posx, view_posy, 0.0, width, height);
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
}
|
||||
|
||||
|
||||
static float
|
||||
dist(GLuint i, GLuint j, float x, float y)
|
||||
{
|
||||
return sqrt((i-x) * (i-x) + (j-y) * (j-y));
|
||||
}
|
||||
|
||||
static void
|
||||
make_smile_texture(void)
|
||||
{
|
||||
#define SZ 128
|
||||
GLenum Filter = GL_LINEAR;
|
||||
GLubyte image[SZ][SZ][4];
|
||||
GLuint i, j;
|
||||
GLint cropRect[4];
|
||||
|
||||
for (i = 0; i < SZ; i++) {
|
||||
for (j = 0; j < SZ; j++) {
|
||||
GLfloat d_mouth = dist(i, j, SZ/2, SZ/2);
|
||||
GLfloat d_rt_eye = dist(i, j, SZ*3/4, SZ*3/4);
|
||||
GLfloat d_lt_eye = dist(i, j, SZ*3/4, SZ*1/4);
|
||||
if (d_rt_eye < SZ / 8 || d_lt_eye < SZ / 8) {
|
||||
image[i][j][0] = 20;
|
||||
image[i][j][1] = 50;
|
||||
image[i][j][2] = 255;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else if (i < SZ/2 && d_mouth < SZ/3) {
|
||||
image[i][j][0] = 255;
|
||||
image[i][j][1] = 20;
|
||||
image[i][j][2] = 20;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else {
|
||||
image[i][j][0] = 200;
|
||||
image[i][j][1] = 200;
|
||||
image[i][j][2] = 200;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0); /* unit 0 */
|
||||
glBindTexture(GL_TEXTURE_2D, 42);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
cropRect[0] = 0;
|
||||
cropRect[1] = 0;
|
||||
cropRect[2] = SZ;
|
||||
cropRect[3] = SZ;
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
|
||||
#undef SZ
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
const char *ext = (char *) glGetString(GL_EXTENSIONS);
|
||||
|
||||
if (!strstr(ext, "GL_OES_draw_texture")) {
|
||||
fprintf(stderr, "Sorry, this program requires GL_OES_draw_texture");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
|
||||
make_smile_texture();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
int anim = 0;
|
||||
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
|
||||
if (!anim || XPending(dpy)) {
|
||||
XEvent event;
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_posx -= 1.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_posx += 1.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_posy += 1.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_posy -= 1.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == ' ') {
|
||||
anim = !anim;
|
||||
}
|
||||
else if (buffer[0] == 'w') {
|
||||
width -= 1.0f;
|
||||
}
|
||||
else if (buffer[0] == 'W') {
|
||||
width += 1.0f;
|
||||
}
|
||||
else if (buffer[0] == 'h') {
|
||||
height -= 1.0f;
|
||||
}
|
||||
else if (buffer[0] == 'H') {
|
||||
height += 1.0f;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
}
|
||||
|
||||
if (anim) {
|
||||
view_posx += 1.0;
|
||||
view_posy += 2.0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 400, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"drawtex", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
274
progs/es1/xegl/es1_info.c
Normal file
274
progs/es1/xegl/es1_info.c
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* List OpenGL ES extensions.
|
||||
* Print ES 1 or ES 2 extensions depending on which library we're
|
||||
* linked with: libGLESv1_CM.so vs libGLESv2.so
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
/*
|
||||
* Print a list of extensions, with word-wrapping.
|
||||
*/
|
||||
static void
|
||||
print_extension_list(const char *ext)
|
||||
{
|
||||
const char *indentString = " ";
|
||||
const int indent = 4;
|
||||
const int max = 79;
|
||||
int width, i, j;
|
||||
|
||||
if (!ext || !ext[0])
|
||||
return;
|
||||
|
||||
width = indent;
|
||||
printf(indentString);
|
||||
i = j = 0;
|
||||
while (1) {
|
||||
if (ext[j] == ' ' || ext[j] == 0) {
|
||||
/* found end of an extension name */
|
||||
const int len = j - i;
|
||||
if (width + len > max) {
|
||||
/* start a new line */
|
||||
printf("\n");
|
||||
width = indent;
|
||||
printf(indentString);
|
||||
}
|
||||
/* print the extension name between ext[i] and ext[j] */
|
||||
while (i < j) {
|
||||
printf("%c", ext[i]);
|
||||
i++;
|
||||
}
|
||||
/* either we're all done, or we'll continue with next extension */
|
||||
width += len + 1;
|
||||
if (ext[j] == 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
j++;
|
||||
if (ext[j] == 0)
|
||||
break;
|
||||
printf(", ");
|
||||
width += 2;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
info(EGLDisplay egl_dpy)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_EXTENSIONS:\n");
|
||||
print_extension_list((char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 400, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"ES info", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
/*XMapWindow(x_dpy, win);*/
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
info(egl_dpy);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
442
progs/es1/xegl/msaa.c
Normal file
442
progs/es1/xegl/msaa.c
Normal file
|
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test MSAA with X/EGL and OpenGL ES 1.x
|
||||
* Brian Paul
|
||||
* 15 September 2008
|
||||
*/
|
||||
|
||||
#define USE_FULL_GL 0
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#if USE_FULL_GL
|
||||
#include <GL/gl.h> /* use full OpenGL */
|
||||
#else
|
||||
#include <GLES/gl.h> /* use OpenGL ES 1.x */
|
||||
#include <GLES/glext.h>
|
||||
#endif
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
static GLboolean AA = 0*GL_TRUE;
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
float a;
|
||||
|
||||
static const GLfloat verts[4][2] = {
|
||||
{ -1, -.1 },
|
||||
{ 1, -.1 },
|
||||
{ -1, .1 },
|
||||
{ 1, .1 }
|
||||
};
|
||||
static const GLfloat colors[4][4] = {
|
||||
{ 1, 0, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, 0, 1, 1 },
|
||||
{ 1, 0, 1, 1 }
|
||||
};
|
||||
|
||||
if (AA) {
|
||||
printf("MSAA enabled\n");
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
else {
|
||||
printf("MSAA disabled\n");
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
|
||||
{
|
||||
glVertexPointer(2, GL_FLOAT, 0, verts);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
for (a = 0; a < 360; a += 20.0) {
|
||||
glPushMatrix();
|
||||
|
||||
glRotatef(a, 0, 0, 1);
|
||||
glTranslatef(1.5, 0, 0);
|
||||
|
||||
/* draw triangle */
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ary = 3.0;
|
||||
GLfloat arx = ary * (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glOrthof(-arx, arx, -ary, ary, -1.0, 1.0);
|
||||
#else
|
||||
glOrtho(-arx, arx, -ary, ary, -1.0, 1.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
printf("Press 'a' to toggle multisample antialiasing\n");
|
||||
printf("Press 'Esc' to exit\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_SAMPLES, 1,
|
||||
EGL_SAMPLE_BUFFERS, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (num_configs < 1) {
|
||||
printf("Error: Unable to find multisample pixel format.\n");
|
||||
printf("Try running glxinfo to see if your server supports MSAA.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
#if USE_FULL_GL
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == 'a') {
|
||||
AA = !AA;
|
||||
redraw = 1;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 600, winHeight = 600;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
GLenum value;
|
||||
enum {GetString, GetInteger} type;
|
||||
} info_items[] = {
|
||||
{"GL_RENDERER", GL_RENDERER, GetString},
|
||||
{"GL_VERSION", GL_VERSION, GetString},
|
||||
{"GL_VENDOR", GL_VENDOR, GetString},
|
||||
{"GL_EXTENSIONS", GL_EXTENSIONS, GetString},
|
||||
{"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES, GetInteger},
|
||||
{"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES, GetInteger},
|
||||
};
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"msaa", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
for (i = 0; i < sizeof(info_items)/sizeof(info_items[0]); i++) {
|
||||
switch (info_items[i].type) {
|
||||
case GetString:
|
||||
printf("%s = %s\n", info_items[i].name, (char *)glGetString(info_items[i].value));
|
||||
break;
|
||||
case GetInteger: {
|
||||
GLint rv = -1;
|
||||
glGetIntegerv(info_items[i].value, &rv);
|
||||
printf("%s = %d\n", info_items[i].name, rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
607
progs/es1/xegl/pbuffer.c
Normal file
607
progs/es1/xegl/pbuffer.c
Normal file
|
|
@ -0,0 +1,607 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test EGL Pbuffers
|
||||
* Brian Paul
|
||||
* August 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
|
||||
static int WinWidth = 300, WinHeight = 300;
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
|
||||
static void
|
||||
Normal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz)
|
||||
{
|
||||
n[0] = nx;
|
||||
n[1] = ny;
|
||||
n[2] = nz;
|
||||
}
|
||||
|
||||
static void
|
||||
Vertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz)
|
||||
{
|
||||
v[0] = vx;
|
||||
v[1] = vy;
|
||||
v[2] = vz;
|
||||
}
|
||||
|
||||
static void
|
||||
Texcoord(GLfloat *v, GLfloat s, GLfloat t)
|
||||
{
|
||||
v[0] = s;
|
||||
v[1] = t;
|
||||
}
|
||||
|
||||
|
||||
/* Borrowed from glut, adapted */
|
||||
static void
|
||||
draw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings)
|
||||
{
|
||||
int i, j;
|
||||
GLfloat theta, phi, theta1;
|
||||
GLfloat cosTheta, sinTheta;
|
||||
GLfloat cosTheta1, sinTheta1;
|
||||
GLfloat ringDelta, sideDelta;
|
||||
GLfloat varray[100][3], narray[100][3], tarray[100][2];
|
||||
int vcount;
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, varray);
|
||||
glNormalPointer(GL_FLOAT, 0, narray);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tarray);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
ringDelta = 2.0 * M_PI / rings;
|
||||
sideDelta = 2.0 * M_PI / nsides;
|
||||
|
||||
theta = 0.0;
|
||||
cosTheta = 1.0;
|
||||
sinTheta = 0.0;
|
||||
for (i = rings - 1; i >= 0; i--) {
|
||||
theta1 = theta + ringDelta;
|
||||
cosTheta1 = cos(theta1);
|
||||
sinTheta1 = sin(theta1);
|
||||
|
||||
vcount = 0; /* glBegin(GL_QUAD_STRIP); */
|
||||
|
||||
phi = 0.0;
|
||||
for (j = nsides; j >= 0; j--) {
|
||||
GLfloat s0, s1, t;
|
||||
GLfloat cosPhi, sinPhi, dist;
|
||||
|
||||
phi += sideDelta;
|
||||
cosPhi = cos(phi);
|
||||
sinPhi = sin(phi);
|
||||
dist = R + r * cosPhi;
|
||||
|
||||
s0 = 20.0 * theta / (2.0 * M_PI);
|
||||
s1 = 20.0 * theta1 / (2.0 * M_PI);
|
||||
t = 8.0 * phi / (2.0 * M_PI);
|
||||
|
||||
Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s1, t);
|
||||
Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
|
||||
vcount++;
|
||||
|
||||
Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s0, t);
|
||||
Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist, r * sinPhi);
|
||||
vcount++;
|
||||
}
|
||||
|
||||
/*glEnd();*/
|
||||
assert(vcount <= 100);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount);
|
||||
|
||||
theta = theta1;
|
||||
cosTheta = cosTheta1;
|
||||
sinTheta = sinTheta1;
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
glScalef(0.5, 0.5, 0.5);
|
||||
|
||||
draw_torus(1.0, 3.0, 30, 60);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glFinish();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw to both the window and pbuffer and compare results.
|
||||
*/
|
||||
static void
|
||||
draw_both(EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
unsigned *wbuf, *pbuf;
|
||||
int x = 100, y = 110;
|
||||
int i, dif;
|
||||
|
||||
wbuf = (unsigned *) malloc(WinWidth * WinHeight * 4);
|
||||
pbuf = (unsigned *) malloc(WinWidth * WinHeight * 4);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
/* first draw to window */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(window) failed\n");
|
||||
return;
|
||||
}
|
||||
draw();
|
||||
glReadPixels(0, 0, WinWidth, WinHeight, GL_RGBA, GL_UNSIGNED_BYTE, wbuf);
|
||||
printf("Window[%d,%d] = 0x%08x\n", x, y, wbuf[y*WinWidth+x]);
|
||||
|
||||
/* then draw to pbuffer */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_pbuf, egl_pbuf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(pbuffer) failed\n");
|
||||
return;
|
||||
}
|
||||
draw();
|
||||
glReadPixels(0, 0, WinWidth, WinHeight, GL_RGBA, GL_UNSIGNED_BYTE, pbuf);
|
||||
printf("Pbuffer[%d,%d] = 0x%08x\n", x, y, pbuf[y*WinWidth+x]);
|
||||
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
|
||||
/* compare renderings */
|
||||
for (dif = i = 0; i < WinWidth * WinHeight; i++) {
|
||||
if (wbuf[i] != pbuf[i]) {
|
||||
dif = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dif)
|
||||
printf("Difference at %d: 0x%08x vs. 0x%08x\n", i, wbuf[i], pbuf[i]);
|
||||
else
|
||||
printf("Window rendering matches Pbuffer rendering!\n");
|
||||
|
||||
free(wbuf);
|
||||
free(pbuf);
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
WinWidth = width;
|
||||
WinHeight = height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
make_texture(void)
|
||||
{
|
||||
#define SZ 64
|
||||
GLenum Filter = GL_LINEAR;
|
||||
GLubyte image[SZ][SZ][4];
|
||||
GLuint i, j;
|
||||
|
||||
for (i = 0; i < SZ; i++) {
|
||||
for (j = 0; j < SZ; j++) {
|
||||
GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2);
|
||||
d = sqrt(d);
|
||||
if (d < SZ/3) {
|
||||
image[i][j][0] = 255;
|
||||
image[i][j][1] = 255;
|
||||
image[i][j][2] = 255;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else {
|
||||
image[i][j][0] = 127;
|
||||
image[i][j][1] = 127;
|
||||
image[i][j][2] = 127;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0); /* unit 0 */
|
||||
glBindTexture(GL_TEXTURE_2D, 42);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
#undef SZ
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
static const GLfloat red[4] = {1, 0, 0, 0};
|
||||
static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
|
||||
static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0};
|
||||
static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0};
|
||||
static const GLfloat pos[4] = {20, 20, 50, 1};
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
make_texture();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static EGLSurface
|
||||
make_pbuffer(Display *x_dpy, EGLDisplay egl_dpy, int width, int height)
|
||||
{
|
||||
static const EGLint config_attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLConfig config;
|
||||
EGLSurface pbuf;
|
||||
EGLint num_configs;
|
||||
EGLint pbuf_attribs[5];
|
||||
|
||||
pbuf_attribs[0] = EGL_WIDTH;
|
||||
pbuf_attribs[1] = width;
|
||||
pbuf_attribs[2] = EGL_HEIGHT;
|
||||
pbuf_attribs[3] = height;
|
||||
pbuf_attribs[4] = EGL_NONE;
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, config_attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL config for pbuffer\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pbuf = eglCreatePbufferSurface(egl_dpy, config, pbuf_attribs);
|
||||
|
||||
return pbuf;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
int anim = 0;
|
||||
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
|
||||
if (!anim || XPending(dpy)) {
|
||||
XEvent event;
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
if (event.xconfigure.window == win)
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == ' ') {
|
||||
anim = !anim;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
}
|
||||
|
||||
if (anim) {
|
||||
view_rotx += 1.0;
|
||||
view_roty += 2.0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw_both(egl_dpy, egl_surf, egl_pbuf, egl_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf, egl_pbuf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"pbuffer", 0, 0, WinWidth, WinHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
egl_pbuf = make_pbuffer(x_dpy, egl_dpy, WinWidth, WinHeight);
|
||||
if (!egl_pbuf) {
|
||||
printf("Error: eglCreatePBufferSurface() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(WinWidth, WinHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf, egl_pbuf, egl_ctx);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
657
progs/es1/xegl/render_tex.c
Normal file
657
progs/es1/xegl/render_tex.c
Normal file
|
|
@ -0,0 +1,657 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test EGL render to texture.
|
||||
* Brian Paul
|
||||
* August 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
static int TexWidth = 256, TexHeight = 256;
|
||||
|
||||
static int WinWidth = 300, WinHeight = 300;
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
static GLuint DotTexture, RenderTexture;
|
||||
|
||||
|
||||
static void
|
||||
Normal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz)
|
||||
{
|
||||
n[0] = nx;
|
||||
n[1] = ny;
|
||||
n[2] = nz;
|
||||
}
|
||||
|
||||
static void
|
||||
Vertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz)
|
||||
{
|
||||
v[0] = vx;
|
||||
v[1] = vy;
|
||||
v[2] = vz;
|
||||
}
|
||||
|
||||
static void
|
||||
Texcoord(GLfloat *v, GLfloat s, GLfloat t)
|
||||
{
|
||||
v[0] = s;
|
||||
v[1] = t;
|
||||
}
|
||||
|
||||
|
||||
/* Borrowed from glut, adapted */
|
||||
static void
|
||||
draw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings)
|
||||
{
|
||||
int i, j;
|
||||
GLfloat theta, phi, theta1;
|
||||
GLfloat cosTheta, sinTheta;
|
||||
GLfloat cosTheta1, sinTheta1;
|
||||
GLfloat ringDelta, sideDelta;
|
||||
GLfloat varray[100][3], narray[100][3], tarray[100][2];
|
||||
int vcount;
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, varray);
|
||||
glNormalPointer(GL_FLOAT, 0, narray);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tarray);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
ringDelta = 2.0 * M_PI / rings;
|
||||
sideDelta = 2.0 * M_PI / nsides;
|
||||
|
||||
theta = 0.0;
|
||||
cosTheta = 1.0;
|
||||
sinTheta = 0.0;
|
||||
for (i = rings - 1; i >= 0; i--) {
|
||||
theta1 = theta + ringDelta;
|
||||
cosTheta1 = cos(theta1);
|
||||
sinTheta1 = sin(theta1);
|
||||
|
||||
vcount = 0; /* glBegin(GL_QUAD_STRIP); */
|
||||
|
||||
phi = 0.0;
|
||||
for (j = nsides; j >= 0; j--) {
|
||||
GLfloat s0, s1, t;
|
||||
GLfloat cosPhi, sinPhi, dist;
|
||||
|
||||
phi += sideDelta;
|
||||
cosPhi = cos(phi);
|
||||
sinPhi = sin(phi);
|
||||
dist = R + r * cosPhi;
|
||||
|
||||
s0 = 20.0 * theta / (2.0 * M_PI);
|
||||
s1 = 20.0 * theta1 / (2.0 * M_PI);
|
||||
t = 8.0 * phi / (2.0 * M_PI);
|
||||
|
||||
Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s1, t);
|
||||
Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
|
||||
vcount++;
|
||||
|
||||
Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s0, t);
|
||||
Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist, r * sinPhi);
|
||||
vcount++;
|
||||
}
|
||||
|
||||
/*glEnd();*/
|
||||
assert(vcount <= 100);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount);
|
||||
|
||||
theta = theta1;
|
||||
cosTheta = cosTheta1;
|
||||
sinTheta = sinTheta1;
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_torus_to_texture(void)
|
||||
{
|
||||
glViewport(0, 0, TexWidth, TexHeight);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustumf(-1, 1, -1, 1, 5.0, 60.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, DotTexture);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glScalef(0.5, 0.5, 0.5);
|
||||
|
||||
draw_torus(1.0, 3.0, 30, 60);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
#if 0
|
||||
glBindTexture(GL_TEXTURE_2D, RenderTexture);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
|
||||
#endif
|
||||
|
||||
glFinish();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_textured_quad(void)
|
||||
{
|
||||
GLfloat ar = (GLfloat) WinWidth / (GLfloat) WinHeight;
|
||||
|
||||
glViewport(0, 0, WinWidth, WinHeight);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -8.0);
|
||||
|
||||
glClearColor(0.4, 0.4, 1.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, RenderTexture);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
|
||||
{
|
||||
static const GLfloat texcoord[4][2] = {
|
||||
{ 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 }
|
||||
};
|
||||
static const GLfloat vertex[4][2] = {
|
||||
{ -1, -1 }, { 1, -1 }, { -1, 1 }, { 1, 1 }
|
||||
};
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, vertex);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texcoord);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
draw(EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
/*printf("Begin draw\n");*/
|
||||
|
||||
/* first draw torus to pbuffer /texture */
|
||||
#if 01
|
||||
if (!eglMakeCurrent(egl_dpy, egl_pbuf, egl_pbuf, egl_ctx)) {
|
||||
#else
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
#endif
|
||||
printf("Error: eglMakeCurrent(pbuf) failed\n");
|
||||
return;
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, RenderTexture);
|
||||
eglBindTexImage(egl_dpy, egl_pbuf, EGL_BACK_BUFFER);
|
||||
draw_torus_to_texture();
|
||||
eglReleaseTexImage(egl_dpy, egl_pbuf, EGL_BACK_BUFFER);
|
||||
|
||||
/* draw textured quad to window */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(pbuffer) failed\n");
|
||||
return;
|
||||
}
|
||||
draw_textured_quad();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
|
||||
/*printf("End draw\n");*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
make_dot_texture(void)
|
||||
{
|
||||
#define SZ 64
|
||||
GLenum Filter = GL_LINEAR;
|
||||
GLubyte image[SZ][SZ][4];
|
||||
GLuint i, j;
|
||||
|
||||
for (i = 0; i < SZ; i++) {
|
||||
for (j = 0; j < SZ; j++) {
|
||||
GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2);
|
||||
d = sqrt(d);
|
||||
if (d < SZ/3) {
|
||||
image[i][j][0] = 255;
|
||||
image[i][j][1] = 255;
|
||||
image[i][j][2] = 255;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else {
|
||||
image[i][j][0] = 127;
|
||||
image[i][j][1] = 127;
|
||||
image[i][j][2] = 127;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glGenTextures(1, &DotTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, DotTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
#undef SZ
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
make_render_texture(void)
|
||||
{
|
||||
GLenum Filter = GL_LINEAR;
|
||||
glGenTextures(1, &RenderTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, RenderTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
static const GLfloat red[4] = {1, 0, 0, 0};
|
||||
static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
|
||||
static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0};
|
||||
static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0};
|
||||
static const GLfloat pos[4] = {20, 20, 50, 1};
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0);
|
||||
|
||||
glEnable(GL_LIGHT0);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
make_dot_texture();
|
||||
make_render_texture();
|
||||
|
||||
printf("DotTexture=%u RenderTexture=%u\n", DotTexture, RenderTexture);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static EGLSurface
|
||||
make_pbuffer(Display *x_dpy, EGLDisplay egl_dpy, int width, int height)
|
||||
{
|
||||
static const EGLint config_attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLConfig config;
|
||||
EGLSurface pbuf;
|
||||
EGLint num_configs;
|
||||
EGLint pbuf_attribs[15];
|
||||
int i = 0;
|
||||
|
||||
pbuf_attribs[i++] = EGL_WIDTH;
|
||||
pbuf_attribs[i++] = width;
|
||||
pbuf_attribs[i++] = EGL_HEIGHT;
|
||||
pbuf_attribs[i++] = height;
|
||||
pbuf_attribs[i++] = EGL_TEXTURE_FORMAT;
|
||||
pbuf_attribs[i++] = EGL_TEXTURE_RGBA;
|
||||
pbuf_attribs[i++] = EGL_TEXTURE_TARGET;
|
||||
pbuf_attribs[i++] = EGL_TEXTURE_2D;
|
||||
pbuf_attribs[i++] = EGL_MIPMAP_TEXTURE;
|
||||
pbuf_attribs[i++] = EGL_FALSE;
|
||||
pbuf_attribs[i++] = EGL_NONE;
|
||||
assert(i <= 15);
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, config_attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL config for pbuffer\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pbuf = eglCreatePbufferSurface(egl_dpy, config, pbuf_attribs);
|
||||
|
||||
return pbuf;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
int anim = 0;
|
||||
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
|
||||
if (!anim || XPending(dpy)) {
|
||||
XEvent event;
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
if (event.xconfigure.window == win) {
|
||||
WinWidth = event.xconfigure.width;
|
||||
WinHeight = event.xconfigure.height;
|
||||
}
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == ' ') {
|
||||
anim = !anim;
|
||||
}
|
||||
else if (buffer[0] == 'z') {
|
||||
view_rotz += 5.0;
|
||||
}
|
||||
else if (buffer[0] == 'Z') {
|
||||
view_rotz -= 5.0;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
}
|
||||
|
||||
if (anim) {
|
||||
view_rotx += 1.0;
|
||||
view_roty += 2.0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw(egl_dpy, egl_surf, egl_pbuf, egl_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf, egl_pbuf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"render_tex", 0, 0, WinWidth, WinHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
egl_pbuf = make_pbuffer(x_dpy, egl_dpy, TexWidth, TexHeight);
|
||||
if (!egl_pbuf) {
|
||||
printf("Error: eglCreatePBufferSurface() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf, egl_pbuf, egl_ctx);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
509
progs/es1/xegl/torus.c
Normal file
509
progs/es1/xegl/torus.c
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Draw a lit, textured torus with X/EGL and OpenGL ES 1.x
|
||||
* Brian Paul
|
||||
* July 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
|
||||
static void
|
||||
Normal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz)
|
||||
{
|
||||
n[0] = nx;
|
||||
n[1] = ny;
|
||||
n[2] = nz;
|
||||
}
|
||||
|
||||
static void
|
||||
Vertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz)
|
||||
{
|
||||
v[0] = vx;
|
||||
v[1] = vy;
|
||||
v[2] = vz;
|
||||
}
|
||||
|
||||
static void
|
||||
Texcoord(GLfloat *v, GLfloat s, GLfloat t)
|
||||
{
|
||||
v[0] = s;
|
||||
v[1] = t;
|
||||
}
|
||||
|
||||
|
||||
/* Borrowed from glut, adapted */
|
||||
static void
|
||||
draw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings)
|
||||
{
|
||||
int i, j;
|
||||
GLfloat theta, phi, theta1;
|
||||
GLfloat cosTheta, sinTheta;
|
||||
GLfloat cosTheta1, sinTheta1;
|
||||
GLfloat ringDelta, sideDelta;
|
||||
GLfloat varray[100][3], narray[100][3], tarray[100][2];
|
||||
int vcount;
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, varray);
|
||||
glNormalPointer(GL_FLOAT, 0, narray);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tarray);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
ringDelta = 2.0 * M_PI / rings;
|
||||
sideDelta = 2.0 * M_PI / nsides;
|
||||
|
||||
theta = 0.0;
|
||||
cosTheta = 1.0;
|
||||
sinTheta = 0.0;
|
||||
for (i = rings - 1; i >= 0; i--) {
|
||||
theta1 = theta + ringDelta;
|
||||
cosTheta1 = cos(theta1);
|
||||
sinTheta1 = sin(theta1);
|
||||
|
||||
vcount = 0; /* glBegin(GL_QUAD_STRIP); */
|
||||
|
||||
phi = 0.0;
|
||||
for (j = nsides; j >= 0; j--) {
|
||||
GLfloat s0, s1, t;
|
||||
GLfloat cosPhi, sinPhi, dist;
|
||||
|
||||
phi += sideDelta;
|
||||
cosPhi = cos(phi);
|
||||
sinPhi = sin(phi);
|
||||
dist = R + r * cosPhi;
|
||||
|
||||
s0 = 20.0 * theta / (2.0 * M_PI);
|
||||
s1 = 20.0 * theta1 / (2.0 * M_PI);
|
||||
t = 8.0 * phi / (2.0 * M_PI);
|
||||
|
||||
Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s1, t);
|
||||
Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
|
||||
vcount++;
|
||||
|
||||
Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s0, t);
|
||||
Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist, r * sinPhi);
|
||||
vcount++;
|
||||
}
|
||||
|
||||
/*glEnd();*/
|
||||
assert(vcount <= 100);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount);
|
||||
|
||||
theta = theta1;
|
||||
cosTheta = cosTheta1;
|
||||
sinTheta = sinTheta1;
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
glScalef(0.5, 0.5, 0.5);
|
||||
|
||||
draw_torus(1.0, 3.0, 30, 60);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
make_texture(void)
|
||||
{
|
||||
#define SZ 64
|
||||
GLenum Filter = GL_LINEAR;
|
||||
GLubyte image[SZ][SZ][4];
|
||||
GLuint i, j;
|
||||
|
||||
for (i = 0; i < SZ; i++) {
|
||||
for (j = 0; j < SZ; j++) {
|
||||
GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2);
|
||||
d = sqrt(d);
|
||||
if (d < SZ/3) {
|
||||
image[i][j][0] = 255;
|
||||
image[i][j][1] = 255;
|
||||
image[i][j][2] = 255;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else {
|
||||
image[i][j][0] = 127;
|
||||
image[i][j][1] = 127;
|
||||
image[i][j][2] = 127;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0); /* unit 0 */
|
||||
glBindTexture(GL_TEXTURE_2D, 42);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
#undef SZ
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
static const GLfloat red[4] = {1, 0, 0, 0};
|
||||
static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
|
||||
static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0};
|
||||
static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0};
|
||||
static const GLfloat pos[4] = {20, 20, 50, 1};
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
make_texture();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
int anim = 1;
|
||||
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
|
||||
if (!anim || XPending(dpy)) {
|
||||
XEvent event;
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == ' ') {
|
||||
anim = !anim;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
}
|
||||
|
||||
if (anim) {
|
||||
view_rotx += 1.0;
|
||||
view_roty += 2.0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 300, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"torus", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
470
progs/es1/xegl/tri.c
Normal file
470
progs/es1/xegl/tri.c
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Draw a triangle with X/EGL and OpenGL ES 1.x
|
||||
* Brian Paul
|
||||
* 5 June 2008
|
||||
*/
|
||||
|
||||
#define USE_FULL_GL 0
|
||||
|
||||
#define USE_FIXED_POINT 0
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#if USE_FULL_GL
|
||||
#include <GL/gl.h> /* use full OpenGL */
|
||||
#else
|
||||
#include <GLES/gl.h> /* use OpenGL ES 1.x */
|
||||
#include <GLES/glext.h>
|
||||
#endif
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
#define FLOAT_TO_FIXED(X) ((X) * 65535.0)
|
||||
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
#if USE_FIXED_POINT
|
||||
static const GLfixed verts[3][2] = {
|
||||
{ -65536, -65536 },
|
||||
{ 65536, -65536 },
|
||||
{ 0, 65536 }
|
||||
};
|
||||
static const GLfixed colors[3][4] = {
|
||||
{ 65536, 0, 0, 65536 },
|
||||
{ 0, 65536, 0 , 65536},
|
||||
{ 0, 0, 65536 , 65536}
|
||||
};
|
||||
#else
|
||||
static const GLfloat verts[3][2] = {
|
||||
{ -1, -1 },
|
||||
{ 1, -1 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
static const GLfloat colors[3][4] = {
|
||||
{ 1, 0, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, 0, 1, 1 }
|
||||
};
|
||||
#endif
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
|
||||
{
|
||||
#if USE_FIXED_POINT
|
||||
glVertexPointer(2, GL_FIXED, 0, verts);
|
||||
glColorPointer(4, GL_FIXED, 0, colors);
|
||||
#else
|
||||
glVertexPointer(2, GL_FLOAT, 0, verts);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors);
|
||||
#endif
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
/* draw triangle */
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
/* draw some points */
|
||||
glPointSizex(FLOAT_TO_FIXED(15.5));
|
||||
glDrawArrays(GL_POINTS, 0, 3);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
/* test code */
|
||||
GLfixed size;
|
||||
glGetFixedv(GL_POINT_SIZE, &size);
|
||||
printf("GL_POINT_SIZE = 0x%x %f\n", size, size / 65536.0);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -10.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_query_matrix(void)
|
||||
{
|
||||
PFNGLQUERYMATRIXXOESPROC procQueryMatrixx;
|
||||
typedef void (*voidproc)();
|
||||
GLfixed mantissa[16];
|
||||
GLint exponent[16];
|
||||
GLbitfield rv;
|
||||
int i;
|
||||
|
||||
procQueryMatrixx = (PFNGLQUERYMATRIXXOESPROC) eglGetProcAddress("glQueryMatrixxOES");
|
||||
assert(procQueryMatrixx);
|
||||
/* Actually try out this one */
|
||||
rv = (*procQueryMatrixx)(mantissa, exponent);
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (rv & (1<<i)) {
|
||||
printf("matrix[%d] invalid\n", i);
|
||||
}
|
||||
else {
|
||||
printf("matrix[%d] = %f * 2^(%d)\n", i, mantissa[i]/65536.0, exponent[i]);
|
||||
}
|
||||
}
|
||||
assert(!eglGetProcAddress("glFoo"));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
|
||||
if (0)
|
||||
test_query_matrix();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
#if USE_FULL_GL
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 300, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
GLenum value;
|
||||
enum {GetString, GetInteger} type;
|
||||
} info_items[] = {
|
||||
{"GL_RENDERER", GL_RENDERER, GetString},
|
||||
{"GL_VERSION", GL_VERSION, GetString},
|
||||
{"GL_VENDOR", GL_VENDOR, GetString},
|
||||
{"GL_EXTENSIONS", GL_EXTENSIONS, GetString},
|
||||
{"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES, GetInteger},
|
||||
{"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES, GetInteger},
|
||||
};
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"OpenGL ES 1.x tri", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
for (i = 0; i < sizeof(info_items)/sizeof(info_items[0]); i++) {
|
||||
switch (info_items[i].type) {
|
||||
case GetString:
|
||||
printf("%s = %s\n", info_items[i].name, (char *)glGetString(info_items[i].value));
|
||||
break;
|
||||
case GetInteger: {
|
||||
GLint rv = -1;
|
||||
glGetIntegerv(info_items[i].value, &rv);
|
||||
printf("%s = %d\n", info_items[i].name, rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
433
progs/es1/xegl/two_win.c
Normal file
433
progs/es1/xegl/two_win.c
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test drawing to two windows.
|
||||
* Brian Paul
|
||||
* August 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
static int WinWidth[2] = {150, 300}, WinHeight[2] = {150, 300};
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -10.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(int win)
|
||||
{
|
||||
static const GLfloat verts[3][2] = {
|
||||
{ -1, -1 },
|
||||
{ 1, -1 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
static const GLfloat colors[3][4] = {
|
||||
{ 1, 0, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, 0, 1, 1 }
|
||||
};
|
||||
|
||||
assert(win == 0 || win == 1);
|
||||
|
||||
reshape(WinWidth[win], WinHeight[win]);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
|
||||
/* draw triangle */
|
||||
{
|
||||
glVertexPointer(2, GL_FLOAT, 0, verts);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, x, y, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
#if USE_FULL_GL
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
if (ctxRet) {
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win1, Window win2,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf1, EGLSurface egl_surf2,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
int win;
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
if (event.xconfigure.window == win1)
|
||||
win = 0;
|
||||
else
|
||||
win = 1;
|
||||
WinWidth[win] = event.xconfigure.width;
|
||||
WinHeight[win] = event.xconfigure.height;
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
/* win 1 */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf1, egl_surf1, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(1) failed\n");
|
||||
return;
|
||||
}
|
||||
draw(0);
|
||||
eglSwapBuffers(egl_dpy, egl_surf1);
|
||||
|
||||
/* win 2 */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf2, egl_surf2, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(2) failed\n");
|
||||
return;
|
||||
}
|
||||
draw(1);
|
||||
eglSwapBuffers(egl_dpy, egl_surf2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Display *x_dpy;
|
||||
Window win1, win2;
|
||||
EGLSurface egl_surf1, egl_surf2;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
GLenum value;
|
||||
enum {GetString, GetInteger} type;
|
||||
} info_items[] = {
|
||||
{"GL_RENDERER", GL_RENDERER, GetString},
|
||||
{"GL_VERSION", GL_VERSION, GetString},
|
||||
{"GL_VENDOR", GL_VENDOR, GetString},
|
||||
{"GL_EXTENSIONS", GL_EXTENSIONS, GetString},
|
||||
{"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES, GetInteger},
|
||||
{"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES, GetInteger},
|
||||
};
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"xegl_two_win #1", 0, 0, WinWidth[0], WinHeight[0],
|
||||
&win1, &egl_ctx, &egl_surf1);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"xegl_two_win #2", WinWidth[0] + 50, 0,
|
||||
WinWidth[1], WinHeight[1],
|
||||
&win2, NULL, &egl_surf2);
|
||||
|
||||
XMapWindow(x_dpy, win1);
|
||||
|
||||
XMapWindow(x_dpy, win2);
|
||||
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf1, egl_surf1, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
for (i = 0; i < sizeof(info_items)/sizeof(info_items[0]); i++) {
|
||||
switch (info_items[i].type) {
|
||||
case GetString:
|
||||
printf("%s = %s\n", info_items[i].name, (char *)glGetString(info_items[i].value));
|
||||
break;
|
||||
case GetInteger: {
|
||||
GLint rv = -1;
|
||||
glGetIntegerv(info_items[i].value, &rv);
|
||||
printf("%s = %d\n", info_items[i].name, rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
event_loop(x_dpy, win1, win2, egl_dpy, egl_surf1, egl_surf2, egl_ctx);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf1);
|
||||
eglDestroySurface(egl_dpy, egl_surf2);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
XDestroyWindow(x_dpy, win1);
|
||||
XDestroyWindow(x_dpy, win2);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
51
progs/es2/xegl/Makefile
Normal file
51
progs/es2/xegl/Makefile
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# progs/es2/xegl/Makefile
|
||||
|
||||
TOP = ../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
INCLUDE_DIRS = \
|
||||
-I$(TOP)/include \
|
||||
|
||||
HEADERS = $(TOP)/include/GLES/egl.h
|
||||
|
||||
|
||||
ES2_LIB_DEPS = \
|
||||
$(TOP)/$(LIB_DIR)/libEGL.so \
|
||||
$(TOP)/$(LIB_DIR)/libGLESv2.so
|
||||
|
||||
|
||||
ES2_LIBS = \
|
||||
-L$(TOP)/$(LIB_DIR) -lEGL \
|
||||
-L$(TOP)/$(LIB_DIR) -lGLESv2 $(LIBDRM_LIB) -lX11
|
||||
|
||||
PROGRAMS = \
|
||||
es2_info \
|
||||
tri
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
default: $(PROGRAMS)
|
||||
|
||||
|
||||
|
||||
es2_info.c:
|
||||
cp ../../es1/xegl/es1_info.c es2_info.c
|
||||
|
||||
es2_info: es2_info.o $(ES2_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) es2_info.o $(ES2_LIBS) -o $@
|
||||
|
||||
tri: tri.o $(ES2_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) tri.o $(ES2_LIBS) -o $@
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
rm -f $(PROGRAMS)
|
||||
rm -f es2_info.c
|
||||
|
||||
514
progs/es2/xegl/tri.c
Normal file
514
progs/es2/xegl/tri.c
Normal file
|
|
@ -0,0 +1,514 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Draw a triangle with X/EGL and OpenGL ES 2.x
|
||||
*/
|
||||
|
||||
#define USE_FULL_GL 0
|
||||
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#if USE_FULL_GL
|
||||
#include <GL/gl.h> /* use full OpenGL */
|
||||
#else
|
||||
#include <GLES2/gl2.h> /* use OpenGL ES 2.x */
|
||||
#endif
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
#define FLOAT_TO_FIXED(X) ((X) * 65535.0)
|
||||
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0;
|
||||
|
||||
static GLint u_matrix = -1;
|
||||
static GLint attr_pos = 0, attr_color = 1;
|
||||
|
||||
|
||||
static void
|
||||
make_z_rot_matrix(GLfloat angle, GLfloat *m)
|
||||
{
|
||||
float c = cos(angle * M_PI / 180.0);
|
||||
float s = sin(angle * M_PI / 180.0);
|
||||
int i;
|
||||
for (i = 0; i < 16; i++)
|
||||
m[i] = 0.0;
|
||||
m[0] = m[5] = m[10] = m[15] = 1.0;
|
||||
|
||||
m[0] = c;
|
||||
m[1] = s;
|
||||
m[4] = -s;
|
||||
m[5] = c;
|
||||
}
|
||||
|
||||
static void
|
||||
make_scale_matrix(GLfloat xs, GLfloat ys, GLfloat zs, GLfloat *m)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 16; i++)
|
||||
m[i] = 0.0;
|
||||
m[0] = xs;
|
||||
m[5] = ys;
|
||||
m[10] = zs;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mul_matrix(GLfloat *prod, const GLfloat *a, const GLfloat *b)
|
||||
{
|
||||
#define A(row,col) a[(col<<2)+row]
|
||||
#define B(row,col) b[(col<<2)+row]
|
||||
#define P(row,col) p[(col<<2)+row]
|
||||
GLfloat p[16];
|
||||
GLint i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
|
||||
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
|
||||
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
|
||||
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
|
||||
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
|
||||
}
|
||||
memcpy(prod, p, sizeof(p));
|
||||
#undef A
|
||||
#undef B
|
||||
#undef PROD
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
static const GLfloat verts[3][2] = {
|
||||
{ -1, -1 },
|
||||
{ 1, -1 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
static const GLfloat colors[3][3] = {
|
||||
{ 1, 0, 0 },
|
||||
{ 0, 1, 0 },
|
||||
{ 0, 0, 1 }
|
||||
};
|
||||
GLfloat mat[16], rot[16], scale[16];
|
||||
|
||||
/* Set modelview/projection matrix */
|
||||
make_z_rot_matrix(view_rotx, rot);
|
||||
make_scale_matrix(0.5, 0.5, 0.5, scale);
|
||||
mul_matrix(mat, rot, scale);
|
||||
glUniformMatrix4fv(u_matrix, 1, GL_FALSE, mat);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
{
|
||||
glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(attr_color, 3, GL_FLOAT, GL_FALSE, 0, colors);
|
||||
glEnableVertexAttribArray(attr_pos);
|
||||
glEnableVertexAttribArray(attr_color);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
glDisableVertexAttribArray(attr_pos);
|
||||
glDisableVertexAttribArray(attr_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
create_shaders(void)
|
||||
{
|
||||
static const char *fragShaderText =
|
||||
"varying vec4 v_color;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = v_color;\n"
|
||||
"}\n";
|
||||
static const char *vertShaderText =
|
||||
"uniform mat4 modelviewProjection;\n"
|
||||
"attribute vec4 pos;\n"
|
||||
"attribute vec4 color;\n"
|
||||
"varying vec4 v_color;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = modelviewProjection * pos;\n"
|
||||
" v_color = color;\n"
|
||||
"}\n";
|
||||
|
||||
GLuint fragShader, vertShader, program;
|
||||
GLint stat;
|
||||
|
||||
fragShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragShader, 1, (const char **) &fragShaderText, NULL);
|
||||
glCompileShader(fragShader);
|
||||
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &stat);
|
||||
if (!stat) {
|
||||
printf("Error: fragment shader did not compile!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vertShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertShader, 1, (const char **) &vertShaderText, NULL);
|
||||
glCompileShader(vertShader);
|
||||
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &stat);
|
||||
if (!stat) {
|
||||
printf("Error: vertex shader did not compile!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, fragShader);
|
||||
glAttachShader(program, vertShader);
|
||||
glLinkProgram(program);
|
||||
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &stat);
|
||||
if (!stat) {
|
||||
char log[1000];
|
||||
GLsizei len;
|
||||
glGetProgramInfoLog(program, 1000, &len, log);
|
||||
printf("Error: linking:\n%s\n", log);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
if (1) {
|
||||
/* test setting attrib locations */
|
||||
glBindAttribLocation(program, attr_pos, "pos");
|
||||
glBindAttribLocation(program, attr_color, "color");
|
||||
glLinkProgram(program); /* needed to put attribs into effect */
|
||||
}
|
||||
else {
|
||||
/* test automatic attrib locations */
|
||||
attr_pos = glGetAttribLocation(program, "pos");
|
||||
attr_color = glGetAttribLocation(program, "color");
|
||||
}
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "modelviewProjection");
|
||||
printf("Uniform modelviewProjection at %d\n", u_matrix);
|
||||
printf("Attrib pos at %d\n", attr_pos);
|
||||
printf("Attrib color at %d\n", attr_color);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
typedef void (*proc)();
|
||||
|
||||
#if 1 /* test code */
|
||||
proc p = eglGetProcAddress("glMapBufferOES");
|
||||
assert(p);
|
||||
#endif
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
|
||||
create_shaders();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
static const EGLint ctx_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
#if USE_FULL_GL /* XXX fix this when eglBindAPI() works */
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* test eglQueryContext() */
|
||||
{
|
||||
EGLint val;
|
||||
eglQueryContext(egl_dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &val);
|
||||
assert(val == 2);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
{
|
||||
EGLint val;
|
||||
eglQuerySurface(egl_dpy, *surfRet, EGL_WIDTH, &val);
|
||||
assert(val == width);
|
||||
eglQuerySurface(egl_dpy, *surfRet, EGL_HEIGHT, &val);
|
||||
assert(val == height);
|
||||
eglQuerySurface(egl_dpy, *surfRet, EGL_SURFACE_TYPE, &val);
|
||||
assert(val == EGL_WINDOW_BIT);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 300, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"OpenGL ES 2.x tri", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue