+
+ /* Note: https://source.android.com/devices/graphics/arch-egl-opengl */
+
+ /* ####: This is lame, use a resource. */
+ rh->jwxyz_gl_p =
+ rh->xsft->visual == DEFAULT_VISUAL &&
+ strcmp (progname, "kumppa") &&
+ strcmp (progname, "petri") &&
+ strcmp (progname, "slip") &&
+ strcmp (progname, "testx11");
+
+ Log ("init: %s @ %dx%d: using JWXYZ_%s", progname, w, h,
+ rh->jwxyz_gl_p ? "GL" : "IMAGE");
+
+ rh->egl_p = rh->jwxyz_gl_p || rh->xsft->visual == GL_VISUAL;
+
+ if (rh->egl_p) {
+ // GL init. Must come after resource processing.
+
+ rh->egl_display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+ Assert (rh->egl_display != EGL_NO_DISPLAY, "init: EGL_NO_DISPLAY");
+
+ int egl_major, egl_minor;
+ Assert (eglInitialize (rh->egl_display, &egl_major, &egl_minor),
+ "eglInitialize failed");
+
+ // TODO: Skip depth and (probably) alpha for Xlib.
+ // TODO: Could ask for EGL_SWAP_BEHAVIOR_PRESERVED_BIT here...maybe?
+ // TODO: Probably should try to ask for EGL_PBUFFER_BIT.
+ // TODO: Do like visual-gl.c and work from a list of configs.
+ /* Probably don't need EGL_FRAMEBUFFER_TARGET_ANDROID here if GLSurfaceView
+ doesn't use it.
+ */
+ EGLint config_attribs[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 16,
+ EGL_NONE
+ };
+
+ EGLint num_config;
+ Assert (eglChooseConfig (rh->egl_display, config_attribs,
+ &rh->egl_config, 1, &num_config),
+ "eglChooseConfig failed");
+ Assert (num_config == 1, "no EGL config chosen");
+
+ EGLint no_attribs[] = {EGL_NONE};
+ rh->egl_ctx = eglCreateContext (rh->egl_display, rh->egl_config,
+ EGL_NO_CONTEXT, no_attribs);
+ Assert (rh->egl_ctx != EGL_NO_CONTEXT, "init: EGL_NO_CONTEXT");
+
+ ANativeWindow *native_window =
+ ANativeWindow_fromSurface (env, jni_surface);
+
+ rh->egl_surface = eglCreateWindowSurface (rh->egl_display, rh->egl_config,
+ native_window, no_attribs);
+ Assert (rh->egl_surface != EGL_NO_SURFACE, "init: EGL_NO_SURFACE");
+
+ ANativeWindow_release (native_window);
+ } else {
+ rh->native_window = ANativeWindow_fromSurface (env, jni_surface);
+
+ int result = ANativeWindow_setBuffersGeometry (rh->native_window, w, h,
+ WINDOW_FORMAT_RGBX_8888);
+ if (result < 0) {
+ // Maybe check this earlier?
+ Log ("can't set format (%d), surface may be invalid.", result);
+ (*env)->ThrowNew (env,
+ (*env)->FindClass(env, "org/jwz/xscreensaver/jwxyz$SurfaceLost"),
+ "Surface lost");
+
+ ANativeWindow_release (rh->native_window);
+ rh->native_window = NULL;
+ return;
+ }
+ }
+
+ prepare_context (rh);
+
+ if (rh->egl_p) {
+ Log ("init %s / %s / %s",
+ glGetString (GL_VENDOR),
+ glGetString (GL_RENDERER),
+ glGetString (GL_VERSION));
+ }
+
+ if (rh->jwxyz_gl_p) {
+ const GLubyte *extensions = glGetString (GL_EXTENSIONS);
+ rh->gl_fbo_p = jwzgles_gluCheckExtension (
+ (const GLubyte *)"GL_OES_framebuffer_object", extensions);
+
+ if (rh->gl_fbo_p) {
+ glGetIntegerv (GL_FRAMEBUFFER_BINDING_OES, &rh->fb_default);
+ Assert (!rh->fb_default, "default framebuffer not current framebuffer");
+ glGenFramebuffersOES (1, &rh->fb_pixmap);
+ wnd->texture = 0;
+ } else {
+ wnd->egl_surface = rh->egl_surface;
+ }
+
+ rh->frontbuffer_p = False;
+
+ if (rh->xsft->visual == DEFAULT_VISUAL ||
+ (rh->xsft->visual == GL_VISUAL &&
+ strcmp("True", get_string_resource_window(wnd, "doubleBuffer")))) {
+
+ rh->frontbuffer_p = True;
+
+# if 0 /* Might need to be 0 for Adreno...? */
+ if (egl_major > 1 || (egl_major == 1 && egl_minor >= 2)) {
+ EGLint surface_type;
+ eglGetConfigAttrib(rh->egl_display, rh->egl_config, EGL_SURFACE_TYPE,
+ &surface_type);
+ if(surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
+ eglSurfaceAttrib(rh->egl_display, rh->egl_surface, EGL_SWAP_BEHAVIOR,
+ EGL_BUFFER_PRESERVED);
+ rh->frontbuffer_p = False;
+ }
+ }
+# endif
+
+ if (rh->frontbuffer_p) {
+ /* create_pixmap needs rh->gl_fbo_p and wnd->frame. */
+ create_pixmap (wnd, wnd);
+
+ /* No preserving backbuffers, so manual blit from back to "front". */
+ rh->frontbuffer.type = PIXMAP;
+ rh->frontbuffer.frame = wnd->frame;
+ rh->frontbuffer.pixmap.depth = visual_depth (NULL, NULL);
+
+ if(rh->gl_fbo_p) {
+ rh->frontbuffer.texture = 0;
+ } else {
+ Assert (wnd->egl_surface != rh->egl_surface,
+ "oops: wnd->egl_surface == rh->egl_surface");
+ rh->frontbuffer.egl_surface = rh->egl_surface;
+ }
+ }
+ }
+
+ rh->dpy = jwxyz_gl_make_display(wnd);
+
+ } else {
+
+ if (rh->xsft->visual == DEFAULT_VISUAL)
+ create_pixmap (wnd, wnd);
+ else
+ wnd->image_data = NULL;
+
+ static const unsigned char rgba_bytes[] = {0, 1, 2, 3};
+ rh->dpy = jwxyz_image_make_display(wnd, rgba_bytes);
+
+ }
+
+ Assert(wnd == XRootWindow(rh->dpy, 0), "Wrong root window.");
+ // TODO: Zero looks right, but double-check that is the right number
+
+ /* Requires valid rh->dpy. */
+ if (rh->jwxyz_gl_p)
+ rh->copy_gc = XCreateGC (rh->dpy, &rh->frontbuffer, 0, NULL);
+
+ if (rh->xsft->visual == GL_VISUAL)
+ rh->gles_state = jwzgles_make_state();