NativeEngine::NativeEngine(struct android_app *app) { LOGD("NativeEngine: initializing."); mApp = app; mHasFocus = mIsVisible = mHasWindow = false; mHasGLObjects = false; mEglDisplay = EGL_NO_DISPLAY; mEglSurface = EGL_NO_SURFACE; mEglContext = EGL_NO_CONTEXT; mEglConfig = 0; mSurfWidth = mSurfHeight = 0; mApiVersion = 0; mJniEnv = NULL; memset(&mState, 0, sizeof(mState)); mIsFirstFrame = true; if (app->savedState != NULL) { // we are starting with previously saved state -- restore it mState = *(struct NativeEngineSavedState*) app->savedState; } // only one instance of NativeEngine may exist! MY_ASSERT(_singleton == NULL); _singleton = this; VLOGD("NativeEngine: querying API level."); LOGD("NativeEngine: API version %d.", mApiVersion); }
void NativeEngine::DoFrame() { // prepare to render (create context, surfaces, etc, if needed) if (!PrepareToRender()) { // not ready VLOGD("NativeEngine: preparation to render failed."); return; } SceneManager *mgr = SceneManager::GetInstance(); // how big is the surface? We query every frame because it's cheap, and some // strange devices out there change the surface size without calling any callbacks... int width, height; eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &width); eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &height); if (width != mSurfWidth || height != mSurfHeight) { // notify scene manager that the surface has changed size LOGD("NativeEngine: surface changed size %dx%d --> %dx%d", mSurfWidth, mSurfHeight, width, height); mSurfWidth = width; mSurfHeight = height; mgr->SetScreenSize(mSurfWidth, mSurfHeight); glViewport(0, 0, mSurfWidth, mSurfHeight); } // if this is the first frame, install the welcome scene if (mIsFirstFrame) { mIsFirstFrame = false; mgr->RequestNewScene(new WelcomeScene()); } // render! mgr->DoFrame(); // swap buffers if (EGL_FALSE == eglSwapBuffers(mEglDisplay, mEglSurface)) { // failed to swap buffers... LOGW("NativeEngine: eglSwapBuffers failed, EGL error %d", eglGetError()); HandleEglError(eglGetError()); } // print out GL errors, if any GLenum e; static int errorsPrinted = 0; while ((e = glGetError()) != GL_NO_ERROR) { if (errorsPrinted < MAX_GL_ERRORS) { _log_opengl_error(e); ++errorsPrinted; if (errorsPrinted >= MAX_GL_ERRORS) { LOGE("*** NativeEngine: TOO MANY OPENGL ERRORS. NO LONGER PRINTING."); } } } }
NativeEngine::~NativeEngine() { VLOGD("NativeEngine: destructor running"); KillContext(); if (mJniEnv) { LOGD("Detaching current thread from JNI."); mApp->activity->vm->DetachCurrentThread(); LOGD("Current thread detached from JNI."); mJniEnv = NULL; } _singleton = NULL; }
void logg(void *a,int b,const char *c,va_list d){ switch(b){ case AV_LOG_INFO: VLOGI(c,d); break; case AV_LOG_DEBUG: VLOGD(c,d); break; case AV_LOG_WARNING: VLOGW(c,d); break; case AV_LOG_ERROR: VLOGE(c,d); break; } }
void NativeEngine::HandleCommand(int32_t cmd) { SceneManager *mgr = SceneManager::GetInstance(); VLOGD("NativeEngine: handling command %d.", cmd); switch (cmd) { case APP_CMD_SAVE_STATE: // The system has asked us to save our current state. VLOGD("NativeEngine: APP_CMD_SAVE_STATE"); mApp->savedState = malloc(sizeof(mState)); *((NativeEngineSavedState*)mApp->savedState) = mState; mApp->savedStateSize = sizeof(mState); break; case APP_CMD_INIT_WINDOW: // We have a window! VLOGD("NativeEngine: APP_CMD_INIT_WINDOW"); if (mApp->window != NULL) { mHasWindow = true; } break; case APP_CMD_TERM_WINDOW: // The window is going away -- kill the surface VLOGD("NativeEngine: APP_CMD_TERM_WINDOW"); KillSurface(); mHasWindow = false; break; case APP_CMD_GAINED_FOCUS: VLOGD("NativeEngine: APP_CMD_GAINED_FOCUS"); mHasFocus = true; break; case APP_CMD_LOST_FOCUS: VLOGD("NativeEngine: APP_CMD_LOST_FOCUS"); mHasFocus = false; break; case APP_CMD_PAUSE: VLOGD("NativeEngine: APP_CMD_PAUSE"); mgr->OnPause(); break; case APP_CMD_RESUME: VLOGD("NativeEngine: APP_CMD_RESUME"); mgr->OnResume(); break; case APP_CMD_STOP: VLOGD("NativeEngine: APP_CMD_STOP"); mIsVisible = false; break; case APP_CMD_START: VLOGD("NativeEngine: APP_CMD_START"); mIsVisible = true; break; case APP_CMD_WINDOW_RESIZED: case APP_CMD_CONFIG_CHANGED: VLOGD("NativeEngine: %s", cmd == APP_CMD_WINDOW_RESIZED ? "APP_CMD_WINDOW_RESIZED" : "APP_CMD_CONFIG_CHANGED"); // Window was resized or some other configuration changed. // Note: we don't handle this event because we check the surface dimensions // every frame, so that's how we know it was resized. If you are NOT doing that, // then you need to handle this event! break; case APP_CMD_LOW_MEMORY: VLOGD("NativeEngine: APP_CMD_LOW_MEMORY"); // system told us we have low memory. So if we are not visible, let's // cooperate by deallocating all of our graphic resources. if (!mHasWindow) { VLOGD("NativeEngine: trimming memory footprint (deleting GL objects)."); KillGLObjects(); } break; default: VLOGD("NativeEngine: (unknown command)."); break; } VLOGD("NativeEngine: STATUS: F%d, V%d, W%d, EGL: D %p, S %p, CTX %p, CFG %p", mHasFocus, mIsVisible, mHasWindow, mEglDisplay, mEglSurface, mEglContext, mEglConfig); }