libEGL called unimplemented OpenGL ES API. Can anyone try if this works on a non-tegra OpenGL ES 2.0 device?

2,921 views
Skip to first unread message

Ronnie van Aarle

unread,
Sep 13, 2011, 9:07:21 AM9/13/11
to android-ndk
I am trying to develop some simple test applications on my LG P990 nv
Tegra device.

Now I took the NativeActivity sample and have modified the source so
that it should display a traingle, exactly the same way as in the java
sdk example, using a vertex and fragment shader on a vertex buffer
object.

I changed from GLES/gl.h go GLES2/gl2.h and GLES2/gl2ext.h

And in Android.mk I changed:

LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM

into

LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2

So it links against the OpenGL ES 2.0 runtime libraries. With gl.h
GL_VERTEX_SHADER and GL_FRAGMENT_SHADER are not defined. Compiling and
linking works fine now, and I can install native-triangle.so into /
data/data/com.rvasolutions.native-triangle/lib/

It also runs, but I don't see any triangle yet. The log gets stuffed
with about a zillion times 'libEGL called unimplemented OpenGL ES API'
so I am almost sure something called from the function DrawFrame is
not supported on my device.

Here's the source.

/**
* Just the current frame in the display.
*/
static void engine_draw_frame(struct engine* engine) {
if (engine->display == NULL) {
// No display.
return;
}

// Just fill the screen with a color.
glClearColor(((float)engine->state.x)/engine->width, engine-
>state.angle,
((float)engine->state.y)/engine->height, 1);
glClear(GL_COLOR_BUFFER_BIT);

// Draw the vbo using the shader program
glUseProgram(mProgram);
glVertexAttribPointer(maPositionHandle,3,GL_FLOAT, GL_FALSE, 12,
&VBOBuffer);
glEnableVertexAttribArray(maPositionHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);

eglSwapBuffers(engine->display, engine->surface);
}

When I look further into the filesystem of the device I see in /system/
lib there is indeed no libGLESv2.so avialable, but in /system/lib/EGL
there are some equivalents like libGLESv2_tegra. Linking against this
file causes a program crash.

Now I'm not sure what's best to do. I cannot install libGLESv2.so into
system/lib/egl because this is a read only directory, and I can't get
linking against libGLESv2_tegra to work. I also don't know which
function exactly calls the missing library, but I just guess it must
be glUseProgram because this is an OpenGL ES 2.0 function, which get's
called many times..

The original NativeActivity glClearColor animation does work, but my
triangle just does not appear on top.

The other function that I have modified is:

/**
* Initialize an EGL context for the current display.
*/
static int engine_init_display(struct engine* engine) {
// initialize OpenGL ES and EGL

/*
* Here specify the attributes of the desired configuration.
* Below, we select an EGLConfig with at least 8 bits per color
* component compatible with on-screen windows
*/
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
EGLint w, h, dummy, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;

EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

eglInitialize(display, 0, 0);

/* Here, the application chooses the configuration it desires. In
this
* sample, we have a very simplified selection process, where we
pick
* the first EGLConfig that matches our criteria */
eglChooseConfig(display, attribs, &config, 1, &numConfigs);

/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
* guaranteed to be accepted by
ANativeWindow_setBuffersGeometry().
* As soon as we picked a EGLConfig, we can safely reconfigure the
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID,
&format);

ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0,
format);

surface = eglCreateWindowSurface(display, config, engine->app-
>window, NULL);
context = eglCreateContext(display, config, NULL, NULL);

if (eglMakeCurrent(display, surface, surface, context) ==
EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return -1;
}

eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);

engine->display = display;
engine->context = context;
engine->surface = surface;
engine->width = w;
engine->height = h;
engine->state.angle = 0;

// Initialize GL state.
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
//glEnable(GL_CULL_FACE);
//glShadeModel(GL_SMOOTH);
//glDisable(GL_DEPTH_TEST);

// RvA : vertex data for a simple triangle
GLfloat triangleCoords[] = { -0.5f, -0.25f, 0, 0.5f, -0.25f, 0,
0.0f, 0.559016994f, 0 };
// RvA: Initialize VBO Buffer and assign data
glGenBuffers(1, &VBOBuffer); // Generates one buffer object.
glBindBuffer(GL_ARRAY_BUFFER, VBOBuffer);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr) 9*sizeof(GLfloat),
&VBOBuffer, GL_STATIC_DRAW);

// shader routines:
// Create shader object, assign source and compile.
vertexShader = glCreateShader(GL_VERTEX_SHADER);

// for debugging:
if (vertexShader == 0) LOGW("can't create GL_VERTEX_SHADER");

glShaderSource(vertexShader,
(GLsizei)sizeof(vertexShaderCode),
(const char**)vertexShaderCode,
(const GLuint*)sizeof(vertexShaderCode)
);

glCompileShader(vertexShader);

fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

// for debugging:
if (fragmentShader == 0) LOGW("can't create GL_FRAGMENT_SHADER");

glShaderSource(fragmentShader,
(GLsizei)sizeof(fragmentShaderCode),
(const char**)fragmentShaderCode,
(const GLuint*)sizeof(fragmentShaderCode)
);

glCompileShader(fragmentShader);

// Create a program object and attach both shaders
mProgram = glCreateProgram();
glAttachShader(mProgram, vertexShader);
glAttachShader(mProgram, fragmentShader);

// Store the compiled programs in the programmable units in the
pipeline
glLinkProgram(mProgram);

// Get a handle to the attribute variable "vPosition" from the
vertex shader
maPositionHandle = glGetAttribLocation(mProgram, "vPosition");

LOGI("Initialization succesfull");

return 0;
}

And I also declared a couple more global variables:

// RvA
GLuint VBOBuffer; // Pointer to VBO

GLbyte vertexShaderCode[] = "attribute vec4 vPosition;void main()
{gl_Position = vPosition;}"; // 62 GLchar elements
GLbyte fragmentShaderCode[] = "precision mediump float;void main()
{gl_FragColor = vec4 (1.0, 1.0, 1.0, 1.0);}"; // 78 GLchar elements
GLuint mProgram, maPositionHandle, vertexShader, fragmentShader;

The rest of the source is the same As in NativeActivity main.c

Thanks in advance.

Fredrik Ehnbom

unread,
Sep 13, 2011, 12:04:57 PM9/13/11
to Ronnie van Aarle, andro...@googlegroups.com
You need to add

EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT

to your "attribs" array, and

your eglCreateContext call need to look something like:

EGLint contextAttrs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};

context = eglCreateContext(display, config, NULL, contextAttrs);


Otherwise egl thinks you want to use GLES 1.

/f

> glGenBuffers(1,&VBOBuffer); // Generates one buffer object.

Ronnie van Aarle

unread,
Sep 14, 2011, 9:19:08 AM9/14/11
to android-ndk
Thanks Fredrik,

This solved the unimplemented GLES API call error. I removed a couple
more bugs and now it's working fine.
Reply all
Reply to author
Forward
0 new messages