Having Trouble Creating An Egl Context


el_pango

Member
Joined
May 31, 2006
Messages
145
Location
California
Good morning,

In my code, I'm doing the following:
Code:
#define DUH_WHERE_AM_I(x) fprintf(stderr,"%s, ln %d: %s\n",__FILE__,__LINE__,x)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GLES/gl.h>
#include <GLES/egl.h>

static EGLint const attributes[] =
{
	EGL_BLUE_SIZE,	5,
	EGL_GREEN_SIZE, 6,
	EGL_RED_SIZE, 	5,
	EGL_DEPTH_SIZE,	16,
	EGL_NONE
};

static EGLDisplay	egl_disp	= 0;
static EGLSurface	egl_surface	= 0;
static EGLContext	egl_context	= 0;

static Window		my_window	= 0;
Display*		disp	= 0;

/* later on */

	disp = XOpenDisplay(NULL);

	screen = DefaultScreen(disp);
	root_window = RootWindow(disp,screen);
	my_window = XCreateSimpleWindow(disp, root_window,0,0,SCRN_W,SCRN_H,0,0,0);

	XUndefineCursor(disp, my_window);
	XMapRaised(disp,my_window);
	XFlush(disp);

	egl_disp = eglGetDisplay((NativeDisplayType)disp);

	result = eglInitialize(egl_disp, NULL, NULL);

	result = eglChooseConfig(egl_disp,attributes,&gl_config,1,&num_gl_configs);

        egl_surface = eglCreateWindowSurface(egl_disp, gl_config,(NativeWindowType)my_window,NULL);

	/* finally, try to create the context and set it up	*/
	/* use.							*/
	egl_context = eglCreateContext(egl_disp, gl_config, EGL_NO_CONTEXT, attributes);
	if(egl_context == EGL_NO_CONTEXT)
	{
		DUH_WHERE_AM_I("Couldn't create the EGL context...");
		clean_up_gl();
		clean_up_x();
		exit(1);
	}

(Some error checks have been removed from the above for brevity's sake, but all the previous steps seem to complete cleanly.)

I more or less copied what I saw in WakeBreaker, but alas, no luck.

What kinds of things could cause creating a context to fail (especially after EGL was happy about everything else)? Is there the equivalent of 'errno' that I can check to see what made it unhappy?

edit: This is on the target device itself.
 
just a quick idea - what happens if you pass NULL instead of attributes at eglCreateContext? - you already have them implicitly within the gl_config ...

*edit*
probably 'eglGetError' is what you're looking for, too.
 
el_pango, on a first glance the config attributes you use for obtaining the config might be insufficient - you need EGL_SURFACE_TYPE = EGL_WINDOW_BIT (since that's the type of surface you create later on) and EGL_RENDERABLE_TYPE = { EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT } depending on what context you want.

here's an example of getting an ES2 context on the pandora: https://code.google.com/p/ntsh-jass/source/browse/testbed_es/main.cpp - look at EGL::initGLES2.
 
This works:

Code:
int GLES2D_InitVideoX11( int w, int h, int fullscreen, int vsync, int fsaa )
{
	Window			sRootWindow;
	XSetWindowAttributes	sWA;
	unsigned int		ui32Mask;
	int			i32Depth;

	x11Display = XOpenDisplay( ":0" );
	if (!x11Display)
	{
		WB_LOGGER(LOG_ERR,"Error: Unable to open X display\n");
		GLES2D_Quit();
		return 0;
	}
	x11Screen = XDefaultScreen( x11Display );

	sRootWindow	= RootWindow(x11Display, x11Screen);
	i32Depth	= DefaultDepth(x11Display, x11Screen);
	x11Visual	= (XVisualInfo *)malloc(sizeof(XVisualInfo));
	XMatchVisualInfo( x11Display, x11Screen, i32Depth, TrueColor, x11Visual);
	if (!x11Visual)
	{
		WB_LOGGER(LOG_ERR,"Error: Unable to acquire visual\n");
		GLES2D_Quit();
		exit(0);
	}

	// Colormap of the specified visual type for the display.
	x11Colormap = XCreateColormap( x11Display, sRootWindow, x11Visual->visual, AllocNone );
	sWA.colormap = x11Colormap;

	// List of events to be handled by the application. Add to these for handling other events.
	sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;

	// Display capabilities list.
   	ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;

	// Creates the X11 window
	x11Window = XCreateWindow( x11Display, RootWindow(x11Display, x11Screen), 0, 0, w, h,
								 0, CopyFromParent, InputOutput, CopyFromParent, ui32Mask, &sWA);

	// Make the window viewable and flush the output buffer.
	XMapWindow(x11Display, x11Window);
	XFlush(x11Display);

	GLES2D_eglDisplay = eglGetDisplay((NativeDisplayType)x11Display);

	EGLint iMajorVersion, iMinorVersion;
	if (!eglInitialize(GLES2D_eglDisplay, &iMajorVersion, &iMinorVersion))
	{
		WB_LOGGER(LOG_ERR,"Error: eglInitialize() failed.\n");
		GLES2D_Quit();
		return 0;
	}

	EGLint pi32ConfigAttribs[5];
	int attrib = 0;
	pi32ConfigAttribs[attrib++] = EGL_SURFACE_TYPE;
	pi32ConfigAttribs[attrib++] = EGL_WINDOW_BIT;
	pi32ConfigAttribs[attrib++] = EGL_NONE;
	if ( fsaa )
	{
		pi32ConfigAttribs[attrib++] = EGL_SAMPLE_BUFFERS, 1;
		pi32ConfigAttribs[attrib++] = EGL_SAMPLES, 4;
	}
	pi32ConfigAttribs[attrib++] = EGL_NONE;


	int iConfigs;
	if (!eglChooseConfig(GLES2D_eglDisplay, pi32ConfigAttribs, &GLES2D_eglConfig, 1, &iConfigs) || (iConfigs != 1))
	{
		WB_LOGGER(LOG_ERR,"Error: eglChooseConfig() failed.\n");
		GLES2D_Quit();
		return 0;
	}

	GLES2D_eglSurface = eglCreateWindowSurface(GLES2D_eglDisplay, GLES2D_eglConfig, (NativeWindowType)x11Window, NULL);
	if (!GLES2D_TestEGLError((char *)"eglCreateWindowSurface"))
	{
		GLES2D_Quit();
		return 0;
	}

	GLES2D_eglContext = eglCreateContext(GLES2D_eglDisplay, GLES2D_eglConfig, NULL, NULL);
	if (!GLES2D_TestEGLError((char *)"eglCreateContext"))
	{
		GLES2D_Quit();
		return 0;
	}

	eglMakeCurrent(GLES2D_eglDisplay, GLES2D_eglSurface, GLES2D_eglSurface, GLES2D_eglContext);
	if (!GLES2D_TestEGLError((char *)"eglMakeCurrent"))
	{
		GLES2D_Quit();
		return 0;
	}

	if ( vsync )
	{
#ifdef _PANDORA_
		vsync_on = 1;
#else
		eglSwapInterval( GLES2D_eglDisplay, 1 );
#endif
	}

	return 1;
}



.. The only thing I can see is that you're not checking the display value (could be NULL) and that you're asking for the X11 server to give you the default display screen number, instead of explicitly requesting the one you want - and there is no guarantee that this will work. You need to do:

Code:
        disp = XOpenDisplay(":0");  // instead of NULL
 
Hi, and thanks for all the helpful replies!

Adding EGL_SURFACE_TYPE and EGL_RENDERABLE_TYPE seemed to make it work, so thanks for that.

A second question, though - how do I get it to go fullscreen? (It doesn't look like we have the equivalent of XRandR or XF86VidMode available).
 
el_pango said:
Hi, and thanks for all the helpful replies!

Adding EGL_SURFACE_TYPE and EGL_RENDERABLE_TYPE seemed to make it work, so thanks for that.

A second question, though - how do I get it to go fullscreen? (It doesn't look like we have the equivalent of XRandR or XF86VidMode available).
fullscreen code from penjin: http://code.google.com/p/penjin/source/browse/trunk/GFX.cpp#282
 
Last edited by a moderator:
I just wanted to come back and thank everyone - in the space of a day and five forum posts, I went from angry clueless newbie to happy clueless newbie with rotating textured cube (and a .mod playing to boot!).

Rockthesmurf: that's exactly what I was trying to do. Try this - all it does is make a window, hide the mouse, take it full screen, and create an ES 1.1 context.

Code:
#include 	<stdlib.h>
#include 	<stdio.h>
#include 	<math.h>
#include		<linux/input.h>
#include		<sys/ioctl.h>
#include 	<X11/Xlib.h>
#include 	<X11/Xutil.h>
#include 	<GLES/gl.h>
#include 	<GLES/egl.h>
#include 	"pandora_gfx.h"
#include 	"common.h"

/******************************************************************************/

static EGLint const attributes[] =
{
	EGL_BLUE_SIZE,			5,
	EGL_GREEN_SIZE, 		6,
	EGL_RED_SIZE, 			5,
	EGL_DEPTH_SIZE,		16,
	EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,
	EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES_BIT,
	EGL_NONE
};

// EGL variables
static EGLDisplay	egl_disp	= 0;
static EGLSurface	egl_surface	= 0;
static EGLContext	egl_context	= 0;

// X11 variables
static Window		my_window	= 0;
Display*		disp	= 0;
XEvent		x11_event;
Atom			x11_state_atom;
Atom			x11_fs_atom;


/******************************************************************************/

void clean_up_gl(void)
{
	eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
	eglDestroyContext(egl_disp, egl_context);
	eglDestroySurface(egl_disp, egl_surface);
	eglTerminate(egl_disp);
}

/******************************************************************************/

void clean_up_x(void)
{
	if(my_window)	XDestroyWindow(disp,my_window);
	if(disp) 		XCloseDisplay(disp);
	return;
}

/******************************************************************************/

void GFX_init(void)
{
	Window		root_window;
	int			screen;
	int 		result;
	int			num_gl_configs; 	// not actually used
	EGLConfig   gl_config;     	// meh, we're going to accept the first one we get

	/* attempt to connect to X and create a full-screen 	*/
	/* borderless window. 											*/
	disp = XOpenDisplay(":0");

	if(disp == NULL)
	{
		DUH_WHERE_AM_I("Couldn't connect to X server.");
		exit(1);
	}

	/* connected to display, actually create the window	*/
	screen = DefaultScreen(disp);
	root_window = RootWindow(disp,screen);
	my_window = XCreateSimpleWindow(disp, root_window,0,0,SCRN_W,SCRN_H,0,0,0);

	/* hide the cursor and push the window all the way		*/
	/* to the top.														*/
	XUndefineCursor(disp, my_window);
	XMapRaised(disp,my_window);
	XFlush(disp);

	/* generate X event to make us full screen.				*/
	/* this portion came from penjin								*/
	x11_state_atom = XInternAtom(disp,"_NET_WM_STATE",False);
	x11_fs_atom		= XInternAtom(disp,"_NET_WM_STATE_FULLSCREEN", False);

	x11_event.xclient.type				= ClientMessage;
	x11_event.xclient.serial			= 0;
	x11_event.xclient.send_event		= True;
	x11_event.xclient.window 			= my_window;
	x11_event.xclient.message_type	= x11_state_atom;
	x11_event.xclient.format			= 32;
	x11_event.xclient.data.l[0]		= 1;
	x11_event.xclient.data.l[1]		= x11_fs_atom;
	x11_event.xclient.data.l[2]		= 0;

	XSendEvent(disp,root_window,False,SubstructureRedirectMask | SubstructureNotifyMask, &x11_event);


	/* create egl display and initialize it             	*/
	egl_disp = eglGetDisplay((NativeDisplayType)disp);

	if(egl_disp == NULL)
	{
		DUH_WHERE_AM_I("eglGetDisplay() failed.");
		clean_up_x();
		exit(1);
	}

	result = eglInitialize(egl_disp, NULL, NULL);

	if(result != EGL_TRUE)
	{
		DUH_WHERE_AM_I("Couldn't initialize the EGL display...?");
		clean_up_x();
		exit(1);
	}

	/* beseech the hardware for a matching configuration	*/
	result = eglChooseConfig(egl_disp,attributes,&gl_config,1,&num_gl_configs);

	if((result != EGL_TRUE) || (num_gl_configs != 1))
	{
		DUH_WHERE_AM_I("Couldn't choose a config...!");
		clean_up_gl();
		clean_up_x();
		exit(1);
	}

	/* try to create a surface 									*/
   egl_surface = eglCreateWindowSurface(egl_disp, gl_config,(NativeWindowType)my_window,NULL);

   if(egl_surface == EGL_NO_SURFACE)
	{
		DUH_WHERE_AM_I("Couldn't create the EGL surface...?!");
		clean_up_gl();
		clean_up_x();
		exit(1);
	}

	/* finally, try to create the context and set it up	*/
	/* use.																*/
//	egl_context = eglCreateContext(egl_disp, gl_config, EGL_NO_CONTEXT, attributes);
	egl_context = eglCreateContext(egl_disp, gl_config, EGL_NO_CONTEXT, NULL);
	if(egl_context == EGL_NO_CONTEXT)
	{
		DUH_WHERE_AM_I("Couldn't create the EGL context...");
		clean_up_gl();
		clean_up_x();
		exit(1);
	}

	eglMakeCurrent(egl_disp, egl_surface, egl_surface, egl_context);

   DUH_WHERE_AM_I("Successfully created render context.");

	glDepthFunc(GL_LEQUAL);
	glViewport(0,0,SCRN_W,SCRN_H);

	atexit(GFX_close);
}

/******************************************************************************/

void GFX_flip(void)
{
	glFlush();
	eglSwapBuffers(egl_disp, egl_surface);
	
}

/******************************************************************************/

void GFX_to_perspective(void)
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glFrustumf(	-2.0f, 2.0f,
					-1.2f, 1.2f,
					1.0f,	FAR_CLIP_DEPTH);

	glEnable(GL_DEPTH_TEST);

	glMatrixMode(GL_MODELVIEW);
}

/******************************************************************************/

void GFX_to_ortho(void)
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrthof(	0.0f, (float)SCRN_W,
					(float)SCRN_H, 0.0f,
					1.0f,	10.0f);

	glDisable(GL_DEPTH_TEST);

	glMatrixMode(GL_MODELVIEW);
}

/******************************************************************************/

void GFX_close(void)
{
	clean_up_gl();
	clean_up_x();
}

/******************************************************************************/

Feel free to use the above however you need to.

(sorry about the crazy indentation - I had tabs set to three spaces when I wrote it, the boards don't seem to agree with that)
 
Rockthesmurf: the code I pasted above doesn't use GLES2D .. I got the code *from* GLES2D, but there's nothing in there, any more, that is GLES2D-specific .. and it uses just GLES/X11 ..
 
Thanks, I'll look again tonight, by the end of last night I managed to get a GL window rendering my game, but I pulled in the GLES2D and SDL headers/libs to do it, I'll see if I can get it going without these dependencies tonight. It was quite exciting seeing it running on Pandora for the first time (I actually heard it before I could see it, as before I had a GL context I could just hear the background music while looking at a console!).

I did have a problem with using compressed textures, but I'll take another look tonight and create a new thread about it if necessary. But yes, thanks for everyone's input to the above, should be very helpful!

Steve
 
el_pango, the flush in the GFX_flip routine is redundant - swapping of buffers flushes unconditionally.
 
Could you tell me what makes it GLES 1.1 specific? i would like to go full steam ahead with shaders and stuff, so I am interested in GLES 2.0.
However, I will go thru your code when I find the time and use it. Till now i only relied on GLX for getting the GL context.
With some modifications I was able to compile your code (took me 3 minutes a :) ) Thanks for the skeleton.


el_pango said:
I just wanted to come back and thank everyone - in the space of a day and five forum posts, I went from angry clueless newbie to happy clueless newbie with rotating textured cube (and a .mod playing to boot!).

Rockthesmurf: that's exactly what I was trying to do. Try this - all it does is make a window, hide the mouse, take it full screen, and create an ES 1.1 context.

Code:
 printf( "Hello, World!\n");    // Just kidding :)

Feel free to use the above however you need to.
 
Last edited by a moderator:
Hi,

the
Code:
EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES_BIT,
should be changed to
Code:
EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
. Everything else remains the same.
 
Back
Top