// Simple test problem that causes the case in question. // Compile using: g++ opengl-test-context.cpp -o opengl-test-context -lEGL -lGL // No issue: ./opengl-test-context // Issue arrises when you run with: ./opengl-test-context --nobind #include #include #include #include // X11 Headers. #include #include // OpenGL Headers #include #include // EGL Headers #include #include EGLint eglConfigCount; bool Forget_bind = false; EGLint attrib[] = { EGL_RED_SIZE, 8, // 1, 2 EGL_GREEN_SIZE, 8, // 3, 4 EGL_BLUE_SIZE, 8, // 5, 6 EGL_ALPHA_SIZE, 8, // 7, 8 EGL_DEPTH_SIZE, 24, // 9, 10 EGL_STENCIL_SIZE, 8, // 11, 12 EGL_BUFFER_SIZE, 24, // 13, 14 // This next Line Should Imply OpenGL EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, // 15, 16 EGL_NONE, // 17 }; #define ATTR_RED_IDX 1 #define ATTR_GREEN_IDX 3 #define ATTR_BLUE_IDX 5 #define ATTR_ALPHA_IDX 7 #define ATTR_DEPTH_IDX 9 #define ATTR_STENCIL_IDX 11 #define ATTR_BUFFER_SIZE_IDX 13 #define ATTR_RENDERABLE_TYPE 15 Display *dpy = NULL; static int scrnum = 0; Window win = 0; static EGLDisplay eglDisplay = EGL_NO_DISPLAY; static EGLContext eglContext = EGL_NO_CONTEXT; static EGLSurface eglSurface = EGL_NO_SURFACE; EGLConfig eglConfig; EGLint eglNumConfig; int EGL_Init() { Window root; XVisualInfo *visinfo; XSetWindowAttributes attr; XSizeHints sizehints; unsigned long mask; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int actualWidth = 800, actualHeight = 600; int i; const char *glstring; printf("Initializing EGL\n"); // that should be the first call into X if (!XInitThreads()) { printf("XInitThreads failed\n"); return false; } if (!(dpy = XOpenDisplay(NULL))) { printf("Couldn't open the X display\n"); return false; } scrnum = DefaultScreen(dpy); if (!(eglDisplay = eglGetDisplay((EGLNativeDisplayType) dpy))) { printf("Couldn't open the EGL display\n"); return false; } if (!eglInitialize(eglDisplay, NULL, NULL)) { printf("Couldn't initialize EGL\n"); return false; } root = RootWindow(dpy, scrnum); if (!eglChooseConfig(eglDisplay, attrib, &eglConfig, 1, &eglNumConfig)) { printf("Couldn't get a EGL config 0x%04x\n", eglGetError()); return false; } colorbits = 32; depthbits = 24; stencilbits = 8; for (i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2: if (colorbits == 24) colorbits = 16; break; case 1: if (depthbits == 24) depthbits = 16; else if (depthbits == 16) depthbits = 8; case 3: if (stencilbits == 24) stencilbits = 16; else if (stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ((i % 4) == 3) { // reduce colorbits if (tcolorbits == 24) tcolorbits = 16; } if ((i % 4) == 2) { // reduce depthbits if (tdepthbits == 24) tdepthbits = 16; else if (tdepthbits == 16) tdepthbits = 8; } if ((i % 4) == 1) { // reduce stencilbits if (tstencilbits == 24) tstencilbits = 16; else if (tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } if (tcolorbits == 24) { attrib[ATTR_RED_IDX] = 8; attrib[ATTR_GREEN_IDX] = 8; attrib[ATTR_BLUE_IDX] = 8; attrib[ATTR_BUFFER_SIZE_IDX] = 24; } else { // must be 16 bit attrib[ATTR_RED_IDX] = 4; attrib[ATTR_GREEN_IDX] = 4; attrib[ATTR_BLUE_IDX] = 4; attrib[ATTR_BUFFER_SIZE_IDX] = 16; } attrib[ATTR_DEPTH_IDX] = tdepthbits; // default to 24 depth attrib[ATTR_STENCIL_IDX] = tstencilbits; if (!eglChooseConfig(eglDisplay, attrib, &eglConfig, 1, &eglNumConfig)) { printf("Couldn't get a EGL config 0x%04x\n", eglGetError()); continue; } printf("Using %d/%d/%d Color bits, %d Alpha bits, %d depth, %d stencil display.\n", attrib[ATTR_RED_IDX], attrib[ATTR_GREEN_IDX], attrib[ATTR_BLUE_IDX], attrib[ATTR_ALPHA_IDX], attrib[ATTR_DEPTH_IDX], attrib[ATTR_STENCIL_IDX]); break; } if (!eglNumConfig) { printf("No acceptable EGL configurations found!\n"); return false; } visinfo = (XVisualInfo*)malloc(sizeof(XVisualInfo)); if (!(XMatchVisualInfo(dpy, scrnum, tdepthbits, TrueColor, (XVisualInfo*)visinfo))) { printf("Couldn't get a visual\n"); return false; } // window attributes printf("wwindow\n"); #define KEY_MASK (KeyPressMask | KeyReleaseMask) #define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask ) #define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask ) attr.background_pixel = BlackPixel(dpy, scrnum); attr.border_pixel = 0; attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); attr.event_mask = X_MASK; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(dpy, root, 0, 0, actualWidth, actualHeight, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); XStoreName(dpy, win, "Test Window"); // don't let the window be resized // FIXME: allow resize (win32 does) sizehints.flags = PMinSize | PMaxSize; sizehints.min_width = sizehints.max_width = actualWidth; sizehints.min_height = sizehints.max_height = actualHeight; XSetWMNormalHints(dpy, win, &sizehints); XMapWindow(dpy, win); // Free the visinfo after we're done with it XFree(visinfo); eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, win, NULL); if (eglSurface == EGL_NO_SURFACE) { printf("Couldn't get a EGL surface\n"); return false; } EGLint ctxattrib[] = { EGL_NONE }; if(!Forget_bind) { if(!eglBindAPI(EGL_OPENGL_API)) { printf("Couldn't Bind OpenGL API\n"); return false; } } eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, ctxattrib); if (eglContext == EGL_NO_CONTEXT) { printf("Couldn't get a EGL context\n"); return false; } eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); // end. return true; } void EGL_Shutdown() { // SHutdown if (dpy) { eglDestroyContext(eglDisplay, eglContext); eglDestroySurface(eglDisplay, eglSurface); eglTerminate(eglDisplay); XDestroyWindow(dpy, win); XFlush(dpy); // FIXME: that's going to crash //XCloseDisplay( dpy ); dpy = NULL; win = 0; eglDisplay = EGL_NO_DISPLAY; eglContext = EGL_NO_CONTEXT; eglSurface = EGL_NO_SURFACE; } } int main (int argc, char ** argv) { for(int i = 1; i < argc;i++) { if(strcmp("--nobind",argv[i]) == 0) { Forget_bind = true; } } const char *glstring; if(EGL_Init()) { glstring = (const char *) glGetString(GL_RENDERER); printf("GL_RENDERER: %s\n", glstring); glstring = (const char *) glGetString(GL_EXTENSIONS); printf("GL_EXTENSIONS: %s\n", glstring); } EGL_Shutdown(); return 0; }