+ xwindow = (Window) calloc (1, sizeof(*xwindow));
+ xwindow->type = WINDOW;
+ xwindow->window.view = self;
+ CFRetain (xwindow->window.view); // needed for garbage collection?
+
+#ifdef BACKBUFFER_OPENGL
+ CGSize new_backbuffer_size;
+
+ {
+# ifndef USE_IPHONE
+ if (!ogl_ctx) {
+
+ pixfmt = [self getGLPixelFormat];
+ [pixfmt retain];
+
+ NSAssert (pixfmt, @"unable to create NSOpenGLPixelFormat");
+
+ // Fun: On OS X 10.7, the second time an OpenGL context is created, after
+ // the preferences dialog is launched in SaverTester, the context only
+ // lasts until the first full GC. Then it turns black. Solution is to
+ // reuse the OpenGL context after this point.
+ // "Analyze" says that both pixfmt and ogl_ctx are leaked.
+ ogl_ctx = [[NSOpenGLContext alloc] initWithFormat:pixfmt
+ shareContext:nil];
+
+ // Sync refreshes to the vertical blanking interval
+ GLint r = 1;
+ [ogl_ctx setValues:&r forParameter:NSOpenGLCPSwapInterval];
+// check_gl_error ("NSOpenGLCPSwapInterval"); // SEGV sometimes. Too early?
+ }
+
+ [ogl_ctx makeCurrentContext];
+ check_gl_error ("makeCurrentContext");
+
+ // NSOpenGLContext logs an 'invalid drawable' when this is called
+ // from initWithFrame.
+ [ogl_ctx setView:self];
+
+ // Get device pixels instead of points.
+ self.wantsBestResolutionOpenGLSurface = YES;
+
+ // This may not be necessary if there's FBO support.
+# ifdef JWXYZ_GL
+ xwindow->window.pixfmt = pixfmt;
+ CFRetain (xwindow->window.pixfmt);
+ xwindow->window.virtual_screen = [ogl_ctx currentVirtualScreen];
+ xwindow->window.current_drawable = xwindow;
+ NSAssert (ogl_ctx, @"no CGContext");
+# endif
+
+ // Clear frame buffer ASAP, else there are bits left over from other apps.
+ glClearColor (0, 0, 0, 1);
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+// glFinish ();
+// glXSwapBuffers (mi->dpy, mi->window);
+
+
+ // Enable multi-threading, if possible. This runs most OpenGL commands
+ // and GPU management on a second CPU.
+ {
+# ifndef kCGLCEMPEngine
+# define kCGLCEMPEngine 313 // Added in MacOS 10.4.8 + XCode 2.4.
+# endif
+ CGLContextObj cctx = CGLGetCurrentContext();
+ CGLError err = CGLEnable (cctx, kCGLCEMPEngine);
+ if (err != kCGLNoError) {
+ NSLog (@"enabling multi-threaded OpenGL failed: %d", err);
+ }
+ }
+
+ new_backbuffer_size = NSSizeToCGSize ([self bounds].size);
+
+ // Scale factor for desktop retina displays
+ double s = [self hackedContentScaleFactor];
+ new_backbuffer_size.width *= s;
+ new_backbuffer_size.height *= s;
+
+# else // USE_IPHONE
+ if (!ogl_ctx) {
+ CAEAGLLayer *eagl_layer = (CAEAGLLayer *) self.layer;
+ eagl_layer.opaque = TRUE;
+ eagl_layer.drawableProperties = [self getGLProperties];
+
+ // Without this, the GL frame buffer is half the screen resolution!
+ eagl_layer.contentsScale = [UIScreen mainScreen].scale;
+
+ ogl_ctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+# ifdef JWXYZ_GL
+ ogl_ctx_pixmap = [[EAGLContext alloc]
+ initWithAPI:kEAGLRenderingAPIOpenGLES1
+ sharegroup:ogl_ctx.sharegroup];
+# endif // JWXYZ_GL
+
+ eagl_layer.contentsGravity = [self getCAGravity];
+ }
+
+# ifdef JWXYZ_GL
+ xwindow->window.ogl_ctx_pixmap = ogl_ctx_pixmap;
+# endif // JWXYZ_GL
+
+ [EAGLContext setCurrentContext: ogl_ctx];
+
+ [self resizeGL];
+
+ double s = [self hackedContentScaleFactor];
+ new_backbuffer_size = self.bounds.size;
+ new_backbuffer_size.width *= s;
+ new_backbuffer_size.height *= s;
+
+# endif // USE_IPHONE
+
+# ifdef JWXYZ_GL
+ xwindow->ogl_ctx = ogl_ctx;
+# ifndef USE_IPHONE
+ CFRetain (xwindow->ogl_ctx);
+# endif // USE_IPHONE
+# endif // JWXYZ_GL
+
+ check_gl_error ("startAnimation");
+
+// NSLog (@"%s / %s / %s\n", glGetString (GL_VENDOR),
+// glGetString (GL_RENDERER), glGetString (GL_VERSION));
+
+ [self enableBackbuffer:new_backbuffer_size];
+ }
+#endif // BACKBUFFER_OPENGL
+
+ [self setViewport];
+ [self createBackbuffer:new_backbuffer_size];
+
+# ifdef USE_TOUCHBAR
+ if (touchbar_view) [touchbar_view startAnimation];
+# endif // USE_TOUCHBAR
+}