void fgAndroidTryCreateContextAndSurface(SFG_Window* window) { if (!window->Window.Context) { window->State.WorkMask |= GLUT_INIT_WORK; /* Create context */ fghChooseConfig(&window->Window.pContext.egl.Config); window->Window.Context = fghCreateNewContextEGL(window); } if (!window->Window.pContext.egl.Surface) { EGLDisplay display = fgDisplay.pDisplay.egl.Display; /* 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. */ EGLint vid; eglGetConfigAttrib(display, window->Window.pContext.egl.Config, EGL_NATIVE_VISUAL_ID, &vid); int32_t err = ANativeWindow_setBuffersGeometry(*window->Window.Handle, 0, 0, vid); assert(!err); fghPlatformOpenWindowEGL(window); window->State.Visible = GL_TRUE; } }
/* * Opens a window. Requires a SFG_Window object created and attached * to the freeglut structure. OpenGL context is created here. */ void fgPlatformOpenWindow( SFG_Window* window, const char* title, GLboolean positionUse, int x, int y, GLboolean sizeUse, int w, int h, GLboolean gameMode, GLboolean isSubWindow ) { XVisualInfo * visualInfo = NULL; XSetWindowAttributes winAttr; XTextProperty textProperty; XSizeHints sizeHints; XWMHints wmHints; XEvent eventReturnBuffer; /* return buffer required for a call */ unsigned long mask; unsigned int current_DisplayMode = fgState.DisplayMode ; XConfigureEvent fakeEvent = {0}; /* Save the display mode if we are creating a menu window */ if( window->IsMenu && ( ! fgStructure.MenuContext ) ) fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ; #ifdef EGL_VERSION_1_0 #define WINDOW_CONFIG window->Window.pContext.egl.Config #else #define WINDOW_CONFIG window->Window.pContext.FBConfig #endif fghChooseConfig(&WINDOW_CONFIG); if( window->IsMenu && ( ! fgStructure.MenuContext ) ) fgState.DisplayMode = current_DisplayMode ; if( ! WINDOW_CONFIG ) { /* * The "fghChooseConfig" returned a null meaning that the visual * context is not available. * Try a couple of variations to see if they will work. */ #ifndef EGL_VERSION_1_0 if( !( fgState.DisplayMode & GLUT_DOUBLE ) ) { fgState.DisplayMode |= GLUT_DOUBLE ; fghChooseConfig(&WINDOW_CONFIG); fgState.DisplayMode &= ~GLUT_DOUBLE; } #endif if( fgState.DisplayMode & GLUT_MULTISAMPLE ) { fgState.DisplayMode &= ~GLUT_MULTISAMPLE ; fghChooseConfig(&WINDOW_CONFIG); fgState.DisplayMode |= GLUT_MULTISAMPLE; } } FREEGLUT_INTERNAL_ERROR_EXIT( WINDOW_CONFIG != NULL, "FBConfig with necessary capabilities not found", "fgOpenWindow" ); /* Get the X visual. */ #ifdef EGL_VERSION_1_0 EGLint vid = 0; XVisualInfo visualTemplate; int num_visuals; if (!eglGetConfigAttrib(fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Config, EGL_NATIVE_VISUAL_ID, &vid)) fgError("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed"); visualTemplate.visualid = vid; visualInfo = XGetVisualInfo(fgDisplay.pDisplay.Display, VisualIDMask, &visualTemplate, &num_visuals); #else visualInfo = glXGetVisualFromFBConfig( fgDisplay.pDisplay.Display, window->Window.pContext.FBConfig ); #endif FREEGLUT_INTERNAL_ERROR_EXIT( visualInfo != NULL, "visualInfo could not be retrieved from FBConfig", "fgOpenWindow" ); /* * XXX HINT: the masks should be updated when adding/removing callbacks. * XXX This might speed up message processing. Is that true? * XXX * XXX A: Not appreciably, but it WILL make it easier to debug. * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT * XXX turns off events that it doesn't need and is a whole lot * XXX more pleasant to trace. (Think mouse-motion! Tons of * XXX ``bonus'' GUI events stream in.) */ winAttr.event_mask = StructureNotifyMask | SubstructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask; winAttr.background_pixmap = None; winAttr.background_pixel = 0; winAttr.border_pixel = 0; winAttr.colormap = XCreateColormap( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow, visualInfo->visual, AllocNone ); mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; if( window->IsMenu || ( gameMode == GL_TRUE ) ) { winAttr.override_redirect = True; mask |= CWOverrideRedirect; } if( ! positionUse ) x = y = -1; /* default window position */ if( ! sizeUse ) w = h = 300; /* default window size */ window->Window.Handle = XCreateWindow( fgDisplay.pDisplay.Display, window->Parent == NULL ? fgDisplay.pDisplay.RootWindow : window->Parent->Window.Handle, x, y, w, h, 0, visualInfo->depth, InputOutput, visualInfo->visual, mask, &winAttr ); /* Fake configure event to force viewport setup * even with no window manager. */ fakeEvent.type = ConfigureNotify; fakeEvent.display = fgDisplay.pDisplay.Display; fakeEvent.window = window->Window.Handle; fakeEvent.x = x; fakeEvent.y = y; fakeEvent.width = w; fakeEvent.height = h; XPutBackEvent(fgDisplay.pDisplay.Display, (XEvent*)&fakeEvent); /* * The GLX context creation, possibly trying the direct context rendering * or else use the current context if the user has so specified */ if( window->IsMenu ) { /* * If there isn't already an OpenGL rendering context for menu * windows, make one */ if( !fgStructure.MenuContext ) { fgStructure.MenuContext = (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) ); fgStructure.MenuContext->MContext = fghCreateNewContext( window ); } /* window->Window.Context = fgStructure.MenuContext->MContext; */ window->Window.Context = fghCreateNewContext( window ); } else if( fgState.UseCurrentContext ) { #ifdef EGL_VERSION_1_0 window->Window.Context = eglGetCurrentContext( ); #else window->Window.Context = glXGetCurrentContext( ); #endif if( ! window->Window.Context ) window->Window.Context = fghCreateNewContext( window ); } else window->Window.Context = fghCreateNewContext( window ); #if !defined( __FreeBSD__ ) && !defined( __NetBSD__ ) && !defined(EGL_VERSION_1_0) if( !glXIsDirect( fgDisplay.pDisplay.Display, window->Window.Context ) ) { if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT ) fgError( "Unable to force direct context rendering for window '%s'", title ); } #endif sizeHints.flags = 0; if ( positionUse ) sizeHints.flags |= USPosition; if ( sizeUse ) sizeHints.flags |= USSize; /* * Fill in the size hints values now (the x, y, width and height * settings are obsolete, are there any more WMs that support them?) * Unless the X servers actually stop supporting these, we should * continue to fill them in. It is *not* our place to tell the user * that they should replace a window manager that they like, and which * works, just because *we* think that it's not "modern" enough. */ sizeHints.x = x; sizeHints.y = y; sizeHints.width = w; sizeHints.height = h; wmHints.flags = StateHint; wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState; /* Prepare the window and iconified window names... */ XStringListToTextProperty( (char **) &title, 1, &textProperty ); XSetWMProperties( fgDisplay.pDisplay.Display, window->Window.Handle, &textProperty, &textProperty, 0, 0, &sizeHints, &wmHints, NULL ); XFree( textProperty.value ); XSetWMProtocols( fgDisplay.pDisplay.Display, window->Window.Handle, &fgDisplay.pDisplay.DeleteWindow, 1 ); #ifdef EGL_VERSION_1_0 fghPlatformOpenWindowEGL(window); #else glXMakeContextCurrent( fgDisplay.pDisplay.Display, window->Window.Handle, window->Window.Handle, window->Window.Context ); #endif #ifdef FREEGLUT_REGAL RegalMakeCurrent(window->Window.Context); #endif /* register extension events _before_ window is mapped */ #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H fgRegisterDevices( fgDisplay.pDisplay.Display, &(window->Window.Handle) ); #endif if (!window->IsMenu) /* Don't show window after creation if its a menu */ { XMapWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); window->State.Visible = GL_TRUE; } XFree(visualInfo); /* wait till window visible */ if( !isSubWindow && !window->IsMenu) XPeekIfEvent( fgDisplay.pDisplay.Display, &eventReturnBuffer, &fghWindowIsVisible, (XPointer)(window->Window.Handle) ); #undef WINDOW_CONFIG }