Esempio n. 1
0
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)
	}
}
Esempio n. 2
0
// The loop handles native input events.
func androidEventLoopFunc(event chan interface{}, looperCh chan *C.ALooper) loop.LoopFunc {
	return func(l loop.Loop) error {
		var inputQueue *C.AInputQueue
		runtime.LockOSThread()
		defer runtime.UnlockOSThread()

		looper := C.ALooper_prepare(C.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS)
		if looper == nil {
			Fatalf("ALooper_prepare returned nil")
		}

		looperCh <- looper

		for {
			select {
			case untypedEvent := <-event:
				switch event := untypedEvent.(type) {
				case inputQueueCreatedEvent:
					inputQueue = (*C.AInputQueue)(event.inputQueue)
					C.AInputQueue_attachLooper(inputQueue, looper, LOOPER_ID_INPUT, nil, nil)
				case inputQueueDestroyedEvent:
					inputQueue = (*C.AInputQueue)(event.inputQueue)
					C.AInputQueue_detachLooper(inputQueue)
				}
			default:
				if inputQueue != nil {
					ident := C.ALooper_pollAll(-1, nil, nil, nil)
					switch ident {
					case LOOPER_ID_INPUT:
						processInput(inputQueue)
					case C.ALOOPER_POLL_ERROR:
						Fatalf("ALooper_pollAll returned ALOOPER_POLL_ERROR\n")
					}
				}
			}
		}
	}
}
Esempio n. 3
0
func runInputQueue(vm, jniEnv, ctx uintptr) error {
	env := (*C.JNIEnv)(unsafe.Pointer(jniEnv)) // not a Go heap pointer

	// Android loopers select on OS file descriptors, not Go channels, so we
	// translate the inputQueue channel to an ALooper_wake call.
	l := C.ALooper_prepare(C.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS)
	pending := make(chan *C.AInputQueue, 1)
	go func() {
		for q := range inputQueue {
			pending <- q
			C.ALooper_wake(l)
		}
	}()

	var q *C.AInputQueue
	for {
		if C.ALooper_pollAll(-1, nil, nil, nil) == C.ALOOPER_POLL_WAKE {
			select {
			default:
			case p := <-pending:
				if q != nil {
					processEvents(env, q)
					C.AInputQueue_detachLooper(q)
				}
				q = p
				if q != nil {
					C.AInputQueue_attachLooper(q, l, 0, nil, nil)
				}
				inputQueueDone <- struct{}{}
			}
		}
		if q != nil {
			processEvents(env, q)
		}
	}
}