// 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 } } } }
func (m *mainLoop) frame() { var timeout C.int = 0 if !m.isRunning() { timeout = -1 } ident := C.ALooper_pollAll(timeout, nil, nil, nil) switch ident { case LOOPER_ID_INPUT: if m.inputQ != nil { m.processInput(m.inputQ) } case C.ALOOPER_POLL_ERROR: log.Fatalf("ALooper_pollAll returned ALOOPER_POLL_ERROR\n") } if m.isRunning() { m.checkSize() createCtx := m.renderState.ctx == egl.Context(unsafe.Pointer(nil)) if createCtx { log.Printf("Creating context\n") ctx_attribs := [...]int32{ egl.CONTEXT_CLIENT_VERSION, 2, egl.NONE, } m.renderState.ctx = egl.CreateContext(m.renderState.disp, m.renderState.conf, egl.NO_CONTEXT, &ctx_attribs[0]) if m.renderState.ctx == egl.Context(unsafe.Pointer(nil)) { panic("Error: eglCreateContext failed\n") } } if !egl.MakeCurrent(m.renderState.disp, m.renderState.surf, m.renderState.surf, m.renderState.ctx) { panic("Error: eglMakeCurrent() failed\n") } if createCtx { m.game.initGL() } m.game.drawFrame() egl.SwapBuffers(m.renderState.disp, m.renderState.surf) } }
// SwapBuffers swaps the surface with the display actually showing the // result of rendering. func (win *window) SwapBuffers() { egl.SwapBuffers(win.eglState.Display, win.eglState.Surface) }