EGL working on Linux but not on Android - android

I have EGL/GLES 2.0 code, which I try to run on Linux (via Mesa) and Android (iOS to come). On Linux it works fine and renders like expected.
Running on Android (Phone, tablet and emulator - all 4.01) it passes fine but displays nothing (screen stays black).
The code is 99% the same for all 3 - with some special handling for Android.
Following my EGL attributes:
EGLint attribList[] =
{
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
//EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
//EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,
//EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
// For Android this is extremely important - eglCreateContext will fail without it
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE, EGL_NONE
};
Following the EGL creation code:
EGLint numConfigs;
EGLint majorVersion;
EGLint minorVersion;
EGLDisplay display;
EGLContext context;
EGLSurface surface;
EGLConfig config;
EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
// Get Display
display = eglGetDisplay((EGLNativeDisplayType)x_display);
if ( display == EGL_NO_DISPLAY )
{
esLogMessage("eglGetDisplay failed %d\n", eglGetError());
return EGL_FALSE;
}
// Initialize EGL
if ( !eglInitialize(display, &majorVersion, &minorVersion) )
{
esLogMessage("eglInitialize failed %d\n", eglGetError());
return EGL_FALSE;
}
static const size_t CONFIG_COUNT = 128;
EGLConfig configs[CONFIG_COUNT];
// Get configs
if ( !eglGetConfigs(display, configs, CONFIG_COUNT, &numConfigs) )
{
esLogMessage("eglGetConfigs failed %d\n", eglGetError());
return EGL_FALSE;
}
else if( numConfigs == 0 )
{
esLogMessage("eglGetConfigs found no configs for the display\n");
return EGL_FALSE;
}
EGLint chosenConfigCount = 0;
// Choose config
if ( !eglChooseConfig(display, attribList, &config, 1, &chosenConfigCount) )
{
esLogMessage("eglChooseConfig failed %d\n", eglGetError());
return EGL_FALSE;
}
else if( chosenConfigCount == 0 )
{
esLogMessage("eglChooseConfig found no matching configs (%d available)\n", numConfigs);
return EGL_FALSE;
}
EGLint format;
/* 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. */
if( !eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) )
{
esLogMessage("eglGetConfigAttrib failed %d\n", eglGetError());
return EGL_FALSE;
}
#ifdef ANDROID
if( ANativeWindow_setBuffersGeometry(hWnd, 0, 0, format) )
{
esLogMessage("ANativeWindow_setBuffersGeometry failed\n");
return EGL_FALSE;
}
#endif
// Create a surface
surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL);
if ( surface == EGL_NO_SURFACE )
{
esLogMessage("eglCreateWindowSurface failed %d\n", eglGetError());
return EGL_FALSE;
}
// Create a GL context
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );
if ( context == EGL_NO_CONTEXT )
{
esLogMessage("eglCreateContext failed %d\n", eglGetError());
return EGL_FALSE;
}
// Make the context current
if ( !eglMakeCurrent(display, surface, surface, context) )
{
esLogMessage("eglMakeCurrent failed %d\n", eglGetError());
return EGL_FALSE;
}
Could someone shed a light, what to test or how to find the problem?
EDIT:
I fixed some other bugs and it now works fine in the Android Emulator and HP Touchpad (Cyanogenmod 9 alpha) but still leads to a black screen on my Samsung Galaxy S1 with Cyanogenmod 9 *sigh*.

First, just a remark: you don't need two EGL_NONE to end your attribute definitions.
Second, your issue comes from the fact that eglGetConfigs() returns the available configs, but eglChooseConfig(...,1,..) will not necessarily return the config that exactly matches the one you requested.
Thus, you have to scan the configs to find the closest to your needs.
You have to call eglGetConfigAttrib() to compare, for instance, EGL_RED_SIZE, EGL_GREEN_SIZE,EGL_BLUE_SIZE, EGL_ALPHA_SIZE, EGL_RENDERABLE_TYPE, EGL_DEPTH_SIZE, EGL_STENCIL_SIZE.
See eglChooseConfig() for further details.

Related

android ndk open gl es 2 setup without java

I want to make a android application which draws open gl graphics completely from native code, in other words I'm using native_app_glue in my c/c++ code.
However I cant find a single resource on the internet that points to using open gl completely from native code !
All the links I found show how can I use the GLSurfaceView in java and then make a JNI call to C/C++ for each onDraw() call. THIS IS EXACTLY WHAT I DON'T WANT TO DO!!
Even the hello-gl2 sample in the ndk uses the same approach!
I do understand that the native app glue does includes some java code behind the scenes to start up the activity, but I dont want any more frequent JNI calls after that.
Instead I want to setup initialisation and call backs for the screen in native code, by that I want to setup the display surface and its corresponding call backs in my native code and not through java.
1.what are the data structures representing a surface (or window display) in NDK?
2.How do I get access to them and get attributes like width and height of the display (in native code)?
3.How do I draw onto that display (since there is no on draw callback I assume I need to make a loop to draw call manually but in that case how do I know that last frame has finished rendering?)
Below is a simple C program (without Manifest/Java etc...) that spins a triangle for 20 seconds. This is just for information purpose (not the recommended way for creating an Android app). It requires access rights to the 'graphics' group (which is the case if you run it through ADB).
How to compile it:
1) get android NDK from http://developer.android.com/tools/sdk/ndk/index.html
2) install toolchain:
./android-ndk-r9b/build/tools/make-standalone-toolchain.sh \
--platform=android-17 --toolchain=arm-linux-androideabi-4.7 \
--system=linux-x86_64 --install-dir=where_you_want_to_install
3) get libui.so from device:
adb pull /system/lib/libui.so
4) compilation:
arm-linux-androideabi-gcc main.c -lGLESv1_CM -lEGL -landroid -L. -lui -o gles_test
To run the program, you will need access to the 'graphics' group, which is the case if you run it through ADB (but not if you run it from a terminal, e.g., TerminalIDE)
/* Program largely inspired from: */
/* http://jiggawatt.org/badc0de/android/index.html */
/* http://software.intel.com/en-us/articles/setting-up-native-opengl-es-on-android-platforms */
/* http://www.brucesutherland.co.uk/android-ndk/opengl-es-2-0-android-ndk-game-programming/ */
#include <stdio.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <android/native_window.h>
#include <sys/types.h>
#include <sys/times.h>
/* returns current time in seconds */
double now() {
struct tms now_tms ;
return (double)(times(&now_tms)) / 100.0 ;
}
/* from libui.so (get it from the device using adb pull /system/lib/libui.so) */
extern NativeWindowType android_createDisplaySurface();
NativeWindowType displayWindow;
const EGLint config16bpp[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_NONE
};
const EGLint config24bpp[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_NONE
};
const EGLint config32bpp[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE
};
GLfloat colors[3][4] = {
{1.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f}
};
GLfloat vertices[3][3] = {
{0.0f, 0.7f, 0.0f},
{-0.7f, -0.7f, 0.0f},
{0.7f, -0.7f, 0.0f}
};
void draw_tri() {
glViewport(
0,
0,
ANativeWindow_getWidth(displayWindow),
ANativeWindow_getHeight(displayWindow)
);
glRotatef(0.5, 0, 0, 1) ;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_FLOAT, 0, colors);
glVertexPointer(3, GL_FLOAT, 0, vertices);
/* Draw the triangle (3 vertices) */
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
int main(int argc, char** argv) {
EGLint majorVersion, minorVersion;
EGLContext eglContext;
EGLSurface eglSurface;
EGLConfig eglConfig;
EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint format;
const EGLint* config = NULL ;
int numConfigs;
int windowFormat;
double start_time = now() ;
/*
* create a window surface that covers the entire screen.
* This function is from libui.
*/
displayWindow = android_createDisplaySurface();
eglInitialize(eglDisplay, &majorVersion, &minorVersion);
printf("GL version: %d.%d\n",majorVersion,minorVersion);
if(displayWindow == 0) {
printf("Could not create window\n") ;
printf("Started from an on-device shell ?\n") ;
printf("use: adb shell <path_to_exe>/%s\n",argv[0]) ;
exit(-1) ;
}
/* get the format of the window. */
windowFormat = ANativeWindow_getFormat(displayWindow) ;
printf("Window specs: %d*%d format=%d\n",
ANativeWindow_getWidth(displayWindow),
ANativeWindow_getHeight(displayWindow),
windowFormat
) ;
/* choose the config according to the format of the window. */
switch(windowFormat) {
case WINDOW_FORMAT_RGBA_8888:
config = config32bpp ;
break ;
case WINDOW_FORMAT_RGBX_8888:
config = config24bpp ;
break ;
case WINDOW_FORMAT_RGB_565:
config = config16bpp ;
break ;
default:
printf("Unknown window format\n") ;
exit(-1) ;
}
if (!eglChooseConfig(eglDisplay, config32bpp, &eglConfig, 1, &numConfigs)) {
printf("eglChooseConfig failed\n");
if (eglContext==0) printf("Error code: %x\n", eglGetError());
exit(-1) ;
}
eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, NULL);
printf("GL context: %x\n", eglContext);
if (eglContext==0) {
printf("Error code: %x\n", eglGetError());
exit(-1) ;
}
eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, displayWindow, NULL);
printf("GL surface: %x\n", eglSurface);
if (eglSurface==0) {
printf("Error code: %x\n", eglGetError());
exit(-1);
}
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
printf(
"Vendor: %s, Renderer: %s, Version: %s\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION)
) ;
printf("Extensions: %s\n", glGetString(GL_EXTENSIONS)) ;
printf("Spinning triangle for 20s\n") ;
while (now() - start_time < 20.0) {
draw_tri();
eglSwapBuffers(eglDisplay, eglSurface);
}
printf("End (tap the screen of the phone to continue).\n") ;
return 0;
}
See the NDK Samples. There is one here:
\android-ndk\samples\native-activity
On-line link:
http://developer.android.com/reference/android/app/NativeActivity.html

Antialiasing in OpenGL ES 2.0?

Is there a way to implement Antialiasing technique in OpenGL ES 2.0? I have goggled and found few methods but there was no change in the output.
In the worst case, I've planned to implement multiple pass rendering, to smooth the edges in fragment shader, by displaying average colour of the pixels around every pixel, but it costs more GPU performance.
Any suggestions?
A lot of devices support MSAA (Multi-Sample Anti-Aliasing). To take advantage of this feature, you have to choose a EGLConfig that has multisampling.
On Android, if you use GLSurfaceView, you will have to implement your own EGLConfigChooser. You can then use EGL functions, particularly eglChooseConfig() to find a config you like.
The following code is untested, but it should at least sketch how this can be implemented. In the constructor of your GLSurfaceView derived class, before calling setRenderer(), add:
setEGLConfigChooser(new MyConfigChooser());
Then implement MyConfigChooser. You can make this a nested class inside your GLSurfaceView:
class MyConfigChooser implements GLSurfaceView.EGLConfigChooser {
#Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
int attribs[] = {
EGL10.EGL_LEVEL, 0,
EGL10.EGL_RENDERABLE_TYPE, 4, // EGL_OPENGL_ES2_BIT
EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RGB_BUFFER,
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_DEPTH_SIZE, 16,
EGL10.EGL_SAMPLE_BUFFERS, 1,
EGL10.EGL_SAMPLES, 4, // This is for 4x MSAA.
EGL10.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] configCounts = new int[1];
egl.eglChooseConfig(display, attribs, configs, 1, configCounts);
if (configCounts[0] == 0) {
// Failed! Error handling.
return null;
} else {
return configs[0];
}
}
}
You will obviously want to substitute the specific values you need for your configuration. In reality, it's much more robust to call eglChooseConfig() with a small set of strictly necessary attributes, let it enumerate all configs that match those attributes, and then implement your own logic to choose the best among them. The defined behavior of eglChooseConfig() is kind of odd already (see documentation), and there's no telling how GPU vendors implement it.
On iOS, you can set this property on your GLKView to enable 4x MSAA:
[view setDrawableMultisample: GLKViewDrawableMultisample4X];
There are other antialiasing approaches you can consider:
Supersampling: Render to a texture that is a multiple (typically twice) the size of your final render surface in each direction, and then downsample it. This uses a lot of memory, and the overhead is substantial. But if it meets your performance requirements, the quality will be excellent.
Old school: Render the frame multiple times with slight offsets, and average the frames. This was commonly done with the accumulation buffer in the early days of OpenGL. The accumulation buffer is obsolete, but you can do the same thing with FBOs. See the section "Scene Antialiasing" under "The Framebuffer" in the original Red Book for a description of the method.
On Android platform, you can download this OpenGL demo apps source code from GDC 2011: it contains lots of best practices and show you how to do multisampling, including coverage antialiasing.
What you need to do is just customize GLSurfaceView.EGLConfigChooser and set this chooser:
// Set this chooser before calling setRenderer()
setEGLConfigChooser(new MultisampleConfigChooser());
setRenderer(mRenderer);
MultisampleConfigChooser.java sample code below:
package com.example.gdc11;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import android.opengl.GLSurfaceView;
import android.util.Log;
// This class shows how to use multisampling. To use this, call
// myGLSurfaceView.setEGLConfigChooser(new MultisampleConfigChooser());
// before calling setRenderer(). Multisampling will probably slow down
// your app -- measure performance carefully and decide if the vastly
// improved visual quality is worth the cost.
public class MultisampleConfigChooser implements GLSurfaceView.EGLConfigChooser {
static private final String kTag = "GDC11";
#Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
mValue = new int[1];
// Try to find a normal multisample configuration first.
int[] configSpec = {
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_DEPTH_SIZE, 16,
// Requires that setEGLContextClientVersion(2) is called on the view.
EGL10.EGL_RENDERABLE_TYPE, 4 /* EGL_OPENGL_ES2_BIT */,
EGL10.EGL_SAMPLE_BUFFERS, 1 /* true */,
EGL10.EGL_SAMPLES, 2,
EGL10.EGL_NONE
};
if (!egl.eglChooseConfig(display, configSpec, null, 0,
mValue)) {
throw new IllegalArgumentException("eglChooseConfig failed");
}
int numConfigs = mValue[0];
if (numConfigs <= 0) {
// No normal multisampling config was found. Try to create a
// converage multisampling configuration, for the nVidia Tegra2.
// See the EGL_NV_coverage_sample documentation.
final int EGL_COVERAGE_BUFFERS_NV = 0x30E0;
final int EGL_COVERAGE_SAMPLES_NV = 0x30E1;
configSpec = new int[]{
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_DEPTH_SIZE, 16,
EGL10.EGL_RENDERABLE_TYPE, 4 /* EGL_OPENGL_ES2_BIT */,
EGL_COVERAGE_BUFFERS_NV, 1 /* true */,
EGL_COVERAGE_SAMPLES_NV, 2, // always 5 in practice on tegra 2
EGL10.EGL_NONE
};
if (!egl.eglChooseConfig(display, configSpec, null, 0,
mValue)) {
throw new IllegalArgumentException("2nd eglChooseConfig failed");
}
numConfigs = mValue[0];
if (numConfigs <= 0) {
// Give up, try without multisampling.
configSpec = new int[]{
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_DEPTH_SIZE, 16,
EGL10.EGL_RENDERABLE_TYPE, 4 /* EGL_OPENGL_ES2_BIT */,
EGL10.EGL_NONE
};
if (!egl.eglChooseConfig(display, configSpec, null, 0,
mValue)) {
throw new IllegalArgumentException("3rd eglChooseConfig failed");
}
numConfigs = mValue[0];
if (numConfigs <= 0) {
throw new IllegalArgumentException("No configs match configSpec");
}
} else {
mUsesCoverageAa = true;
}
}
// Get all matching configurations.
EGLConfig[] configs = new EGLConfig[numConfigs];
if (!egl.eglChooseConfig(display, configSpec, configs, numConfigs,
mValue)) {
throw new IllegalArgumentException("data eglChooseConfig failed");
}
// CAUTION! eglChooseConfigs returns configs with higher bit depth
// first: Even though we asked for rgb565 configurations, rgb888
// configurations are considered to be "better" and returned first.
// You need to explicitly filter the data returned by eglChooseConfig!
int index = -1;
for (int i = 0; i < configs.length; ++i) {
if (findConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE, 0) == 5) {
index = i;
break;
}
}
if (index == -1) {
Log.w(kTag, "Did not find sane config, using first");
}
EGLConfig config = configs.length > 0 ? configs[index] : null;
if (config == null) {
throw new IllegalArgumentException("No config chosen");
}
return config;
}
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
EGLConfig config, int attribute, int defaultValue) {
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
return mValue[0];
}
return defaultValue;
}
public boolean usesCoverageAa() {
return mUsesCoverageAa;
}
private int[] mValue;
private boolean mUsesCoverageAa;
}
Before using this feature, you should known this will affect rendering efficiency, and may need to do a fully performance test.

glGetString(GL_VERSION) returns "OpenGL ES-CM 1.1" but my phone supports OpenGL 2

I'm trying to make an NDK based OpenGL application. At some point in my code, I want to check the OpenGL version available on the device.
I'm using the following code :
const char *version = (const char *) glGetString(GL_VERSION);
if (strstr(version, "OpenGL ES 2.")) {
// do something
} else {
__android_log_print(ANDROID_LOG_ERROR, "NativeGL", "Open GL 2 not available (%s)", version=;
}
THe problem is that the version string is always equals to "OpenGL ES-CM 1.1".
I'm testing on both a Moto G (Android 4.4.4) and Samsung Galaxy Nexus (Android 4.3), both of which are OpenGL ES 2.0 compliant (the moto G is also OpenGL ES 3.0 compliant).
I tried to force the EGL_CONTEXT_CLIENT_VERSION when I initialise my display, but then eglChooseConfig returns 0 configurations. And when I test the context client version value in the default configuration, it's always 0 :
const EGLint attrib_list[] = {
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
// get the number of configs matching the attrib_list
EGLint num_configs;
eglChooseConfig(display, attrib_list, NULL, 0, &num_configs);
LOG_D(TAG, " • %d EGL configurations found", num_configs);
// find matching configurations
EGLConfig configs[num_configs];
EGLint client_version = 0, depth_size = 0, stencil_size = 0, surface_type = 0;
eglChooseConfig(display, requirements, configs, num_configs, &num_configs);
for(int i = 0; i < num_configs; ++i){
eglGetConfigAttrib(display, configs[i], EGL_CONTEXT_CLIENT_VERSION, &client_version);
LOG_D(TAG, " client version %d = 0x%08x", i, client_version);
}
// Update the window format from the configuration
EGLint format;
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(window, 0, 0, format);
// create the surface and context
EGLSurface surface = eglCreateWindowSurface(display, config, window, NULL);
EGLContext context = eglCreateContext(display, config, NULL, NULL);
I'm linking against the Open GL ES 2.0 library : here's the excerpt from my Android.mk
LOCAL_LDLIBS := -landroid -llog -lEGL -lGLESv2
Thanks to the hints given by mstorsjo, I managed to have the correct initialisation code, shown here if other people struggle with this.
const EGLint attrib_list[] = {
// this specifically requests an Open GL ES 2 renderer
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
// (ommiting other configs regarding the color channels etc...
EGL_NONE
};
EGLConfig config;
EGLint num_configs;
eglChooseConfig(display, attrib_list, &config, 1, &num_configs);
// ommiting other codes
const EGLint context_attrib_list[] = {
// request a context using Open GL ES 2.0
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
EGLContext context = eglCreateContext(display, config, NULL, context_attrib_list);
What version you get from glGetString(GL_VERSION) depends on which library you've linked the code against, either libGLESv1_CM.so or libGLESv2.so. Similarly for all the other common GL functions. This means that in practice, you need to build two separate .so files for your GL ES 1 and 2 versions of your rendering, and only load the right one once you know which one of them you can use (or load the function pointers dynamically). (This apparently is different when having compatibility between GL ES 2 and 3, where you can check using glGetString(GL_VERSION).)
You didn't say where you tried using EGL_CONTEXT_CLIENT_VERSION - it should be used in the parameter array to eglCreateContext (which you only call once you actually have chosen a config). The attribute array given to eglChooseConfig should have the pair EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT to get a suitable config.

How can I create an EGL context from a native function when the NativeWindowType is created in a Java SurfaceView?

I'm trying to create the EGL context to draw everything with OpenglES within a native function call. The problem is that I need access to the NativeWindowType instance, but I could only find a function to create one (which I can't find out how to link, anyway). However, even if I create one, I suspect that would be wrong, since what I really need is the one created by the SurfaceView instance from which I'm calling this native function.
Here is the code:
static int egl_init() {
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 egl_major_version, egl_minor_version;
EGLint numConfigs;
EGLConfig egl_config;
EGLSurface egl_surface;
EGLContext egl_context;
EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
// v--------- This is where I should get the display window
NativeWindowType display_window;
display_window = android_createDisplaySurface();
eglInitialize(egl_display, &egl_major_version, &egl_minor_version);
printf("GL Version: %d.%d\n", egl_major_version, egl_minor_version);
if (!eglChooseConfig(egl_display, attribs, &egl_config, 1, &numConfigs))
{
printf("eglChooseConfig failed\n");
if (egl_context == 0) printf("Error code: %x\n", eglGetError());
}
eglGetConfigAttrib(egl_display, egl_config, EGL_NATIVE_VISUAL_ID, &format);
// v---------- This requires that I link libandroid, it is found in android/native_window.h
ANativeWindow_setBuffersGeometry(display_window, 0, 0, format);
egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, NULL);
if (egl_context == 0) LOGE("Error code: %x\n", eglGetError());
egl_surface = eglCreateWindowSurface(egl_display, egl_config, display_window, NULL);
if (egl_surface == 0) LOGE("Error code: %x\n", eglGetError());
if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) == EGL_FALSE) {
LOGE("Unable to eglMakeCurrent");
return -1;
}
return 0;
}
Thanks for your help
The surface can not support the the requested egl config (red,green and blue being at least 8 bits).
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
Some phones, makes all surface buffers RGB_565 by default.
In Java to get more detailed colors or alpha you can getWindow and setFormat(). Like so:
getWindow().setFormat(PixelFormat.TRANSLUCENT);
To do something equivalent in a native-activity you must do something like the following.
ANativeWindow_setBuffersGeometry(display_window, 0, 0, 1);
as defined in android/native_window.h
/*
* Pixel formats that a window can use.
*/
enum {
WINDOW_FORMAT_RGBA_8888 = 1,
WINDOW_FORMAT_RGBX_8888 = 2,
WINDOW_FORMAT_RGB_565 = 4,
};
Hope this helps. I've seen this question around and I just figured it out.

OGLES 2 Native Android: eglCreateWindowSurface Arguments

I have a funny event with one application in development using OpenGL ES on native NDK C++ for Android. The program compiles and runs with no problem. However if I decide to make a unit test and debug the code, it complains with the following message:
Invalid arguments ' Candidates are:
void * eglCreateWindowSurface(void *, void *, unsigned long int,
const int *) '
Which is related to the last line from the following code snapshot:
EGLint lFormat, lNumConfigs, lErrorResult;
EGLConfig lConfig;
// Defines display requirements. 16bits mode here.
const EGLint lAttributes[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_BLUE_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_RED_SIZE, 5,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
EGL_NONE
};
// Retrieves a display connection and initializes it.
packt_Log_debug("Connecting to the display.");
mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (mDisplay == EGL_NO_DISPLAY) goto ERROR;
if (!eglInitialize(mDisplay, NULL, NULL)) goto ERROR;
// Selects the first OpenGL configuration found.
packt_Log_debug("Selecting a display config.");
if(!eglChooseConfig(mDisplay, lAttributes, &lConfig, 1,
&lNumConfigs) || (lNumConfigs <= 0)) goto ERROR;
// Reconfigures the Android window with the EGL format.
packt_Log_debug("Configuring window format.");
if (!eglGetConfigAttrib(mDisplay, lConfig,
EGL_NATIVE_VISUAL_ID, &lFormat)) goto ERROR;
ANativeWindow_setBuffersGeometry(mApplication->window, 0, 0, lFormat);
// Creates the display surface.
packt_Log_debug("Initializing the display.");
mSurface = eglCreateWindowSurface(mDisplay, lConfig, mApplication->window, NULL);
I already looked on OGLES references, but all different things I tried did not work out yet.
Replacing 'mApplication->window' for 'EGLNativeWindowType window' solved the problem.

Categories

Resources