//export onNativeWindowDestroyed func onNativeWindowDestroyed(act *C.ANativeActivity, win unsafe.Pointer) { defer func() { handleCallbackError(act, recover()) }() log.Printf("onWindowDestroy...\n") state := states[act] state.mLoop.UpdateRenderState(nil) egl.DestroySurface(state.renderState.disp, state.renderState.surf) state.renderState.surf = egl.Surface(unsafe.Pointer(nil)) log.Printf("onWindowDestroy done\n") }
// Run runs renderLoop. The loop renders a frame and swaps the buffer // at each tick received. func renderLoopFunc(controlCh *controlCh) loop.LoopFunc { return func(loop loop.Loop) error { var state renderState // Lock/unlock the loop to the current OS thread. This is // necessary because OpenGL functions should be called from // the same thread. runtime.LockOSThread() defer runtime.UnlockOSThread() // We don't have yet a proper rendering state so the // ticker should be stopped as soon as it is created. ticker := time.NewTicker(time.Duration(int(time.Second) / int(FRAMES_PER_SECOND))) ticker.Stop() for { select { // At each tick render a frame and swap buffers. case <-ticker.C: state.angle += 0.05 state.cube.Rotate(state.angle, [3]float32{0, 1, 0}) state.world.Draw() egl.SwapBuffers(state.eglState.Display, state.eglState.Surface) // Receive an EGL state from the // native graphics subsystem and // initialize a rendering state. case eglState := <-controlCh.eglState: if err := state.init(eglState); err != nil { panic(err) } // Now that we have a proper rendering // state we can start the ticker. ticker = time.NewTicker(time.Duration(int(time.Second) / int(FRAMES_PER_SECOND))) case <-controlCh.exit: go loop.Stop() case <-loop.ShallStop(): ticker.Stop() egl.DestroySurface(state.eglState.Display, state.eglState.Surface) egl.DestroyContext(state.eglState.Display, state.eglState.Context) egl.Terminate(state.eglState.Display) return nil } } } }