func (s *renderState) Destroy() { if s == nil { return } if s.disp != egl.Display(unsafe.Pointer(nil)) { if s.ctx != egl.Context(unsafe.Pointer(nil)) { egl.DestroyContext(s.disp, s.ctx) } egl.Terminate(s.disp) } }
// 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 } } } }