void QtEmuGL::paintGL() { NativeUpdate(*input_state); NativeRender(); EndInputState(input_state); time_update(); }
static inline void UpdateRunLoop() { NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } if (globalUIState != UISTATE_EXIT) { NativeRender(); } }
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { static bool hasSetThreadName = false; if (!hasSetThreadName) { hasSetThreadName = true; setCurrentThreadName("AndroidRender"); } if (renderer_inited) { // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; input_state.pad_rstick_x = right_joystick_x_async; input_state.pad_rstick_y = right_joystick_y_async; UpdateInputState(&input_state); } NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } NativeRender(); time_update(); } else { ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); // Shouldn't really get here. Let's draw magenta. glDepthMask(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(1.0, 0.0, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } lock_guard guard(frameCommandLock); while (!frameCommands.empty()) { FrameCommand frameCmd; frameCmd = frameCommands.front(); frameCommands.pop(); DLOG("frameCommand %s %s", frameCmd.command.c_str(), frameCmd.params.c_str()); jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); jstring param = env->NewStringUTF(frameCmd.params.c_str()); env->CallVoidMethod(obj, postCommand, cmd, param); env->DeleteLocalRef(cmd); env->DeleteLocalRef(param); } }
extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { // Too spammy // ILOG("NativeApp.displayRender()"); if (renderer_inited) { // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); pad_buttons_down |= pad_buttons_async_set; pad_buttons_down &= ~pad_buttons_async_clear; input_state.pad_buttons = pad_buttons_down; KeyQueueCopyQueue(key_queue_async, input_state.key_queue); UpdateInputState(&input_state); } { lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; } NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } NativeRender(); time_update(); } else { ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); // Shouldn't really get here. Let's draw magenta. glstate.depthWrite.set(GL_TRUE); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(1.0, 0.0, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } if (!frameCommand.empty()) { ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); jstring cmd = env->NewStringUTF(frameCommand.c_str()); jstring param = env->NewStringUTF(frameCommandParam.c_str()); env->CallVoidMethod(obj, postCommand, cmd, param); frameCommand = ""; frameCommandParam = ""; } }
void UpdateRunLoop() { if (windowHidden && g_Config.bPauseWhenMinimized) { sleep_ms(16); return; } NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } if (GetUIState() != UISTATE_EXIT) { NativeRender(); } }
// JavaEGL extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { static bool hasSetThreadName = false; if (!hasSetThreadName) { hasSetThreadName = true; setCurrentThreadName("AndroidRender"); } if (renderer_inited) { // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; input_state.pad_rstick_x = right_joystick_x_async; input_state.pad_rstick_y = right_joystick_y_async; UpdateInputState(&input_state); } NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } NativeRender(graphicsContext); time_update(); } else { ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); // Shouldn't really get here. Let's draw magenta. // TODO: Should we have GL here? glDepthMask(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(1.0, 0.0, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } lock_guard guard(frameCommandLock); if (!nativeActivity) { while (!frameCommands.empty()) frameCommands.pop(); return; } ProcessFrameCommands(env); }
extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { if (renderer_inited) { // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; input_state.pad_rstick_x = right_joystick_x_async; input_state.pad_rstick_y = right_joystick_y_async; UpdateInputState(&input_state); } NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } NativeRender(); time_update(); } else { ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); // Shouldn't really get here. Let's draw magenta. glstate.depthWrite.set(GL_TRUE); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(1.0, 0.0, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } lock_guard guard(frameCommandLock); while (!frameCommands.empty()) { FrameCommand frameCmd; frameCmd = frameCommands.front(); frameCommands.pop(); DLOG("frameCommand %s %s", frameCmd.command.c_str(), frameCmd.params.c_str()); jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); jstring param = env->NewStringUTF(frameCmd.params.c_str()); env->CallVoidMethod(obj, postCommand, cmd, param); } }
static inline void UpdateRunLoop() { UpdateScreenScale(); { { #ifdef _WIN32 lock_guard guard(input_state.lock); input_state.pad_buttons = 0; input_state.pad_lstick_x = 0; input_state.pad_lstick_y = 0; input_state.pad_rstick_x = 0; input_state.pad_rstick_y = 0; host->PollControllers(input_state); UpdateInputState(&input_state); #endif } NativeUpdate(input_state); EndInputState(&input_state); } NativeRender(); }
void Core_RunLoop() { while (!coreState) { time_update(); double startTime = time_now_d(); UpdateScreenScale(); { { #ifdef _WIN32 lock_guard guard(input_state.lock); input_state.pad_buttons = 0; input_state.pad_lstick_x = 0; input_state.pad_lstick_y = 0; input_state.pad_rstick_x = 0; input_state.pad_rstick_y = 0; // Temporary hack. if (GetAsyncKeyState(VK_ESCAPE)) { input_state.pad_buttons |= PAD_BUTTON_MENU; } host->PollControllers(input_state); UpdateInputState(&input_state); #endif } NativeUpdate(input_state); EndInputState(&input_state); } NativeRender(); time_update(); // Simple throttling to not burn the GPU in the menu. #ifdef _WIN32 if (globalUIState != UISTATE_INGAME) { double sleepTime = 16.666 - (time_now_d() - startTime) * 1000.0; if (sleepTime > 0.0) Sleep((int)sleepTime); GL_SwapBuffers(); } else if (!Core_IsStepping()) { GL_SwapBuffers(); } #endif } }
static inline void UpdateRunLoop() { { { #ifdef _WIN32 lock_guard guard(input_state.lock); input_state.pad_buttons = 0; input_state.pad_lstick_x = 0; input_state.pad_lstick_y = 0; input_state.pad_rstick_x = 0; input_state.pad_rstick_y = 0; host->PollControllers(input_state); UpdateInputState(&input_state); #endif } NativeUpdate(input_state); EndInputState(&input_state); } if (globalUIState != UISTATE_EXIT) { NativeRender(); } }
void Core_RunLoop() { while (!coreState) { time_update(); double startTime = time_now_d(); UpdateScreenScale(); { { #ifdef _WIN32 lock_guard guard(input_state.lock); input_state.pad_buttons = 0; input_state.pad_lstick_x = 0; input_state.pad_lstick_y = 0; input_state.pad_rstick_x = 0; input_state.pad_rstick_y = 0; host->PollControllers(input_state); UpdateInputState(&input_state); #endif } NativeUpdate(input_state); EndInputState(&input_state); } NativeRender(); time_update(); // Simple throttling to not burn the GPU in the menu. #ifdef _WIN32 if (globalUIState != UISTATE_INGAME) { double diffTime = time_now_d() - startTime; int sleepTime = (int) (1000000.0 / 60.0) - (int) (diffTime * 1000000.0); if (sleepTime > 0) Sleep(sleepTime / 1000); GL_SwapBuffers(); } else if (!Core_IsStepping()) { GL_SwapBuffers(); } #endif } }
extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(JNIEnv *env, jobject obj, jobject _surf) { ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf); WLOG("runEGLRenderLoop. display_xres=%d display_yres=%d", display_xres, display_yres); if (wnd == nullptr) { ELOG("Error: Surface is null."); return false; } AndroidEGLGraphicsContext *graphicsContext = new AndroidEGLGraphicsContext(); if (!graphicsContext->Init(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format)) { ELOG("Failed to initialize graphics context."); delete graphicsContext; return false; } if (!renderer_inited) { NativeInitGraphics(graphicsContext); renderer_inited = true; } exitRenderLoop = false; renderLoopRunning = true; while (!exitRenderLoop) { static bool hasSetThreadName = false; if (!hasSetThreadName) { hasSetThreadName = true; setCurrentThreadName("AndroidRender"); } // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; input_state.pad_rstick_x = right_joystick_x_async; input_state.pad_rstick_y = right_joystick_y_async; UpdateInputState(&input_state); } NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } NativeRender(graphicsContext); time_update(); graphicsContext->SwapBuffers(); lock_guard guard(frameCommandLock); while (!frameCommands.empty()) { FrameCommand frameCmd; frameCmd = frameCommands.front(); frameCommands.pop(); WLOG("frameCommand! '%s' '%s'", frameCmd.command.c_str(), frameCmd.params.c_str()); jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); jstring param = env->NewStringUTF(frameCmd.params.c_str()); env->CallVoidMethod(nativeActivity, postCommand, cmd, param); env->DeleteLocalRef(cmd); env->DeleteLocalRef(param); } } // Restore lost device objects. TODO: This feels like the wrong place for this. NativeDeviceLost(); ILOG("NativeDeviceLost completed."); NativeShutdownGraphics(); renderer_inited = false; graphicsContext->Shutdown(); renderLoopRunning = false; WLOG("Render loop exited;"); return true; }
extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(JNIEnv *env, jobject obj, jobject _surf) { ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf); WLOG("runEGLRenderLoop. display_xres=%d display_yres=%d", display_xres, display_yres); if (wnd == nullptr) { ELOG("Error: Surface is null."); return false; } cInterfaceBase *gl = HostGL_CreateGLInterface(); if (!gl) { ELOG("ERROR: Failed to create GL interface"); return false; } ILOG("EGL interface created. Desired backbuffer size: %dx%d", desiredBackbufferSizeX, desiredBackbufferSizeY); // Apparently we still have to set this through Java through setFixedSize on the bufferHolder for it to take effect... gl->SetBackBufferDimensions(desiredBackbufferSizeX, desiredBackbufferSizeY); gl->SetMode(MODE_DETECT_ES); bool use565 = false; switch (backbuffer_format) { case 4: // PixelFormat.RGB_565 use565 = true; break; } if (!gl->Create(wnd, false, use565)) { ELOG("EGL creation failed"); // TODO: What do we do now? return false; } gl->MakeCurrent(); if (!renderer_inited) { NativeInitGraphics(); renderer_inited = true; } exitRenderLoop = false; renderLoopRunning = true; while (!exitRenderLoop) { static bool hasSetThreadName = false; if (!hasSetThreadName) { hasSetThreadName = true; setCurrentThreadName("AndroidRender"); } // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; input_state.pad_rstick_x = right_joystick_x_async; input_state.pad_rstick_y = right_joystick_y_async; UpdateInputState(&input_state); } NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } NativeRender(); time_update(); gl->Swap(); lock_guard guard(frameCommandLock); while (!frameCommands.empty()) { FrameCommand frameCmd; frameCmd = frameCommands.front(); frameCommands.pop(); WLOG("frameCommand! '%s' '%s'", frameCmd.command.c_str(), frameCmd.params.c_str()); jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); jstring param = env->NewStringUTF(frameCmd.params.c_str()); env->CallVoidMethod(nativeActivity, postCommand, cmd, param); env->DeleteLocalRef(cmd); env->DeleteLocalRef(param); } } // Restore lost device objects. TODO: This feels like the wrong place for this. NativeDeviceLost(); ILOG("NativeDeviceLost completed."); NativeShutdownGraphics(); renderer_inited = false; gl->ClearCurrent(); delete gl; ANativeWindow_release(wnd); renderLoopRunning = false; WLOG("Render loop exited;"); return true; }
int main(int argc, char *argv[]) { std::string app_name; std::string app_name_nice; float zoom = 1.0f; bool tablet = false; bool aspect43 = false; const char *zoomenv = getenv("ZOOM"); const char *tabletenv = getenv("TABLET"); const char *ipad = getenv("IPAD"); if (zoomenv) { zoom = atof(zoomenv); } if (tabletenv) { tablet = atoi(tabletenv) ? true : false; } if (ipad) aspect43 = true; bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); // Change these to temporarily test other resolutions. aspect43 = false; tablet = false; float density = 1.0f; //zoom = 1.5f; if (landscape) { if (tablet) { pixel_xres = 1280 * zoom; pixel_yres = 800 * zoom; } else if (aspect43) { pixel_xres = 1024 * zoom; pixel_yres = 768 * zoom; } else { pixel_xres = 800 * zoom; pixel_yres = 480 * zoom; } } else { // PC development hack for more space //pixel_xres = 1580 * zoom; //pixel_yres = 1000 * zoom; if (tablet) { pixel_xres = 800 * zoom; pixel_yres = 1280 * zoom; } else if (aspect43) { pixel_xres = 768 * zoom; pixel_yres = 1024 * zoom; } else { pixel_xres = 480 * zoom; pixel_yres = 800 * zoom; } } net::Init(); #ifdef __APPLE__ // Make sure to request a somewhat modern GL context at least - the // latest supported by MacOSX (really, really sad...) // Requires SDL 2.0 (which is even more sad, as that hasn't been released yet) //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); #endif if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } #ifdef EGL if (EGL_Open()) return 1; #endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, #ifdef USING_GLES2 SDL_SWSURFACE | SDL_FULLSCREEN #else SDL_OPENGL #endif ) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return(2); } #ifdef EGL EGL_Init(); #endif SDL_WM_SetCaption(app_name_nice.c_str(), NULL); #ifdef MAEMO SDL_ShowCursor(SDL_DISABLE); #endif #ifndef USING_GLES2 if (GLEW_OK != glewInit()) { printf("Failed to initialize glew!\n"); return 1; } if (GLEW_VERSION_2_0) { printf("OpenGL 2.0 or higher.\n"); } else { printf("Sorry, this program requires OpenGL 2.0.\n"); return 1; } #endif #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); TCHAR path[MAX_PATH]; SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); PathAppend(path, (app_name + "\\").c_str()); #else // Mac / Linux char path[512]; const char *the_path = getenv("HOME"); if (!the_path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) the_path = pwd->pw_dir; } strcpy(path, the_path); if (path[strlen(path)-1] != '/') strcat(path, "/"); #endif #ifdef _WIN32 NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE"); #else NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif dp_xres = (float)pixel_xres * density / zoom; dp_yres = (float)pixel_yres * density / zoom; pixel_in_dps = (float)pixel_xres / dp_xres; NativeInitGraphics(); glstate.viewport.set(0, 0, pixel_xres, pixel_yres); float dp_xscale = (float)dp_xres / pixel_xres; float dp_yscale = (float)dp_yres / pixel_yres; printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); SDL_AudioSpec fmt; fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; fmt.samples = 1024; fmt.callback = &mixaudio; fmt.userdata = (void *)0; if (SDL_OpenAudio(&fmt, NULL) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); return 1; } // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); #ifdef PANDORA // Joysticks init, we the nubs if setup as Joystick int numjoys = SDL_NumJoysticks(); if (numjoys>0) for (int i=0; i<numjoys; i++) { if (strncmp(SDL_JoystickName(i), "nub0", 4) == 0) ljoy=SDL_JoystickOpen(i); if (strncmp(SDL_JoystickName(i), "nub1", 4) == 0) rjoy=SDL_JoystickOpen(i); } #endif int framecount = 0; bool nextFrameMD = 0; float t = 0, lastT = 0; while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; int quitRequested = 0; SDL_Event event; while (SDL_PollEvent(&event)) { float mx = event.motion.x * dp_xscale; float my = event.motion.y * dp_yscale; if (event.type == SDL_QUIT) { quitRequested = 1; } else if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == SDLK_ESCAPE) { quitRequested = 1; } } else if (event.type == SDL_MOUSEMOTION) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; NativeTouch(0, mx, my, 0, TOUCH_MOVE); } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { //input_state.mouse_buttons_down = 1; input_state.pointer_down[0] = true; nextFrameMD = true; NativeTouch(0, mx, my, 0, TOUCH_DOWN); } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { input_state.pointer_down[0] = false; nextFrameMD = false; //input_state.mouse_buttons_up = 1; NativeTouch(0, mx, my, 0, TOUCH_UP); } } } if (quitRequested) break; const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); if (keys[SDLK_ESCAPE]) break; SimulateGamepad(keys, &input_state); UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); EndInputState(&input_state); if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } #ifdef EGL eglSwapBuffers(g_eglDisplay, g_eglSurface); #else if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) { SDL_GL_SwapBuffers(); lastT = t; } #endif // Simple frame rate limiting // while (time_now() < t + 1.0f/60.0f) { // sleep_ms(0); // time_update(); // } time_update(); t = time_now(); framecount++; } // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though #ifdef _WIN32 exit(0); #endif NativeShutdownGraphics(); SDL_PauseAudio(1); SDL_CloseAudio(); NativeShutdown(); #ifdef EGL EGL_Close(); #endif SDL_Quit(); net::Shutdown(); exit(0); return 0; }
int main(int argc, char *argv[]) { std::string app_name; std::string app_name_nice; bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); net::Init(); #ifdef __APPLE__ // Make sure to request a somewhat modern GL context at least - the // latest supported by MacOSX (really, really sad...) // Requires SDL 2.0 // We really should upgrade to SDL 2.0 soon. //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); #endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } #ifdef EGL if (EGL_Open()) return 1; #endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); int mode; #ifdef USING_GLES2 mode = SDL_SWSURFACE | SDL_FULLSCREEN; #else mode = SDL_OPENGL; for (int i = 1; i < argc; i++) if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; #endif if (mode & SDL_FULLSCREEN) { const SDL_VideoInfo* info = SDL_GetVideoInfo(); pixel_xres = info->current_w; pixel_yres = info->current_h; g_Config.bFullScreen = true; } else { // set a sensible default resolution (2x) pixel_xres = 480 * 2; pixel_yres = 272 * 2; g_Config.bFullScreen = false; } dp_xres = (float)pixel_xres; dp_yres = (float)pixel_yres; if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return(2); } #ifdef EGL EGL_Init(); #endif SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL); #ifdef MAEMO SDL_ShowCursor(SDL_DISABLE); #endif #ifndef USING_GLES2 if (GLEW_OK != glewInit()) { printf("Failed to initialize glew!\n"); return 1; } if (GLEW_VERSION_2_0) { printf("OpenGL 2.0 or higher.\n"); } else { printf("Sorry, this program requires OpenGL 2.0.\n"); return 1; } #endif #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); TCHAR path[MAX_PATH]; SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); PathAppend(path, (app_name + "\\").c_str()); #else // Mac / Linux char path[512]; const char *the_path = getenv("HOME"); if (!the_path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) the_path = pwd->pw_dir; } strcpy(path, the_path); if (path[strlen(path)-1] != '/') strcat(path, "/"); #endif #ifdef _WIN32 NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE"); #else NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif pixel_in_dps = (float)pixel_xres / dp_xres; float dp_xscale = (float)dp_xres / pixel_xres; float dp_yscale = (float)dp_yres / pixel_yres; g_dpi_scale = dp_xres / (float)pixel_xres; printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); NativeInitGraphics(); SDL_AudioSpec fmt; fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; fmt.samples = 2048; fmt.callback = &mixaudio; fmt.userdata = (void *)0; if (SDL_OpenAudio(&fmt, NULL) < 0) ELOG("Failed to open audio: %s", SDL_GetError()); // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); #ifdef PANDORA int numjoys = SDL_NumJoysticks(); // Joysticks init, we the nubs if setup as Joystick if (numjoys > 0) { ljoy = SDL_JoystickOpen(0); if (numjoys > 1) rjoy = SDL_JoystickOpen(1); } #else joystick = new SDLJoystick(); #endif EnableFZ(); int framecount = 0; float t = 0; float lastT = 0; while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; int quitRequested = 0; SDL_Event event; while (SDL_PollEvent(&event)) { float mx = event.motion.x * dp_xscale; float my = event.motion.y * dp_yscale; switch (event.type) { case SDL_QUIT: quitRequested = 1; break; case SDL_KEYDOWN: { int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_DOWN; key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_KEYUP: { int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_UP; key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; //input_state.mouse_buttons_down = 1; input_state.pointer_down[0] = true; input_state.mouse_valid = true; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_DOWN; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_WHEELUP: { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_DOWN; NativeKey(key); } break; case SDL_BUTTON_WHEELDOWN: { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_DOWN; NativeKey(key); } break; } break; case SDL_MOUSEMOTION: if (input_state.pointer_down[0]) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; input_state.mouse_valid = true; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_MOVE; input.id = 0; NativeTouch(input); } break; case SDL_MOUSEBUTTONUP: switch (event.button.button) { case SDL_BUTTON_LEFT: { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; input_state.pointer_down[0] = false; input_state.mouse_valid = true; //input_state.mouse_buttons_up = 1; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_UP; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_WHEELUP: { KeyInput key; key.deviceId = DEVICE_ID_DEFAULT; key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_UP; NativeKey(key); } break; case SDL_BUTTON_WHEELDOWN: { KeyInput key; key.deviceId = DEVICE_ID_DEFAULT; key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_UP; NativeKey(key); } break; } break; default: joystick->ProcessInput(event); break; } } if (quitRequested) break; const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); SimulateGamepad(keys, &input_state); UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); #ifndef MAEMO if (lastUIState != globalUIState) { lastUIState = globalUIState; if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) SDL_ShowCursor(SDL_DISABLE); if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen) SDL_ShowCursor(SDL_ENABLE); } #endif EndInputState(&input_state); if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } #ifdef EGL eglSwapBuffers(g_eglDisplay, g_eglSurface); #else if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) { SDL_GL_SwapBuffers(); lastT = t; } #endif time_update(); t = time_now(); framecount++; } #ifndef PANDORA delete joystick; joystick = NULL; #endif // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though #ifdef _WIN32 exit(0); #endif NativeShutdownGraphics(); SDL_PauseAudio(1); SDL_CloseAudio(); NativeShutdown(); #ifdef EGL EGL_Close(); #endif SDL_Quit(); net::Shutdown(); exit(0); return 0; }
void EmuThread::run() { running = true; setCurrentThreadName("EmuThread"); g_State.bEmuThreadStarted = true; host->UpdateUI(); host->InitGL(); glWindow->makeCurrent(); #ifndef USING_GLES2 glewInit(); #endif NativeInitGraphics(); INFO_LOG(BOOT, "Starting up hardware."); CoreParameter coreParameter; coreParameter.fileToStart = fileToStart.toStdString(); coreParameter.enableSound = true; coreParameter.gpuCore = GPU_GLES; coreParameter.cpuCore = (CPUCore)g_Config.iCpuCore; coreParameter.enableDebugging = true; coreParameter.printfEmuLog = false; coreParameter.headLess = false; coreParameter.renderWidth = 480 * g_Config.iWindowZoom; coreParameter.renderHeight = 272 * g_Config.iWindowZoom; coreParameter.outputWidth = dp_xres; coreParameter.outputHeight = dp_yres; coreParameter.pixelWidth = pixel_xres; coreParameter.pixelHeight = pixel_yres; coreParameter.startPaused = !g_Config.bAutoRun; std::string error_string; if (!PSP_Init(coreParameter, &error_string)) { ERROR_LOG(BOOT, "Error loading: %s", error_string.c_str()); FinalShutdown(); return; } LayoutGamepad(dp_xres, dp_yres); _dbg_update_(); host->UpdateDisassembly(); Core_EnableStepping(coreParameter.startPaused ? TRUE : FALSE); g_State.bBooted = true; #ifdef _DEBUG host->UpdateMemView(); #endif host->BootDone(); QElapsedTimer timer; while(running) { //UpdateGamepad(*input_state); timer.start(); UpdateInputState(input_state); static const int mapping[12][2] = { {PAD_BUTTON_A, CTRL_CROSS}, {PAD_BUTTON_B, CTRL_CIRCLE}, {PAD_BUTTON_X, CTRL_SQUARE}, {PAD_BUTTON_Y, CTRL_TRIANGLE}, {PAD_BUTTON_UP, CTRL_UP}, {PAD_BUTTON_DOWN, CTRL_DOWN}, {PAD_BUTTON_LEFT, CTRL_LEFT}, {PAD_BUTTON_RIGHT, CTRL_RIGHT}, {PAD_BUTTON_LBUMPER, CTRL_LTRIGGER}, {PAD_BUTTON_RBUMPER, CTRL_RTRIGGER}, {PAD_BUTTON_START, CTRL_START}, {PAD_BUTTON_SELECT, CTRL_SELECT}, }; for (int i = 0; i < 12; i++) { if (input_state->pad_buttons_down & mapping[i][0]) { __CtrlButtonDown(mapping[i][1]); } if (input_state->pad_buttons_up & mapping[i][0]) { __CtrlButtonUp(mapping[i][1]); } } __CtrlSetAnalog(input_state->pad_lstick_x, input_state->pad_lstick_y); EndInputState(input_state); glstate.Restore(); glViewport(0, 0, pixel_xres, pixel_yres); Matrix4x4 ortho; ortho.setOrtho(0.0f, dp_xres, dp_yres, 0.0f, -1.0f, 1.0f); glsl_bind(UIShader_Get()); glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr()); ReapplyGfxState(); Core_Run(); // Hopefully coreState is now CORE_NEXTFRAME if (coreState == CORE_NEXTFRAME) { // set back to running for the next frame coreState = CORE_RUNNING; qint64 time = timer.elapsed(); const int frameTime = (1.0f/60.0f) * 1000; if(time < frameTime) { msleep(frameTime-time); } timer.start(); } fbo_unbind(); UIShader_Prepare(); uiTexture->Bind(0); glViewport(0, 0, pixel_xres, pixel_yres); ui_draw2d.Begin(DBMODE_NORMAL); //if (g_Config.bShowTouchControls) // DrawGamepad(ui_draw2d); glsl_bind(UIShader_Get()); ui_draw2d.End(); ui_draw2d.Flush(UIShader_Get()); // Tiled renderers like PowerVR should benefit greatly from this. However - seems I can't call it? #if defined(USING_GLES2) bool hasDiscard = false; // TODO if (hasDiscard) { //glDiscardFramebuffer(GL_COLOR_EXT | GL_DEPTH_EXT | GL_STENCIL_EXT); } #endif glWindow->swapBuffers(); } glWindow->doneCurrent(); }
int main(int argc, char *argv[]) { #ifdef RPI bcm_host_init(); #endif putenv((char*)"SDL_VIDEO_CENTERED=1"); std::string app_name; std::string app_name_nice; bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); net::Init(); #ifdef __APPLE__ // Make sure to request a somewhat modern GL context at least - the // latest supported by MacOSX (really, really sad...) // Requires SDL 2.0 // We really should upgrade to SDL 2.0 soon. //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); #endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } #ifdef USING_EGL if (EGL_Open()) return 1; #endif // Get the video info before doing anything else, so we don't get skewed resolution results. const SDL_VideoInfo* desktopVideoInfo = SDL_GetVideoInfo(); g_DesktopWidth = desktopVideoInfo->current_w; g_DesktopHeight = desktopVideoInfo->current_h; SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); int mode; #ifdef USING_GLES2 mode = SDL_SWSURFACE | SDL_FULLSCREEN; #else mode = SDL_OPENGL | SDL_RESIZABLE; #endif int set_xres = -1; int set_yres = -1; bool portrait = false; bool set_ipad = false; float set_dpi = 1.0f; float set_scale = 1.0f; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; if (set_xres == -2) { set_xres = parseInt(argv[i]); } else if (set_yres == -2) { set_yres = parseInt(argv[i]); } if (set_dpi == -2) set_dpi = parseFloat(argv[i]); if (set_scale == -2) set_scale = parseFloat(argv[i]); if (!strcmp(argv[i],"--xres")) set_xres = -2; if (!strcmp(argv[i],"--yres")) set_yres = -2; if (!strcmp(argv[i],"--dpi")) set_dpi = -2; if (!strcmp(argv[i],"--scale")) set_scale = -2; if (!strcmp(argv[i],"--ipad")) set_ipad = true; if (!strcmp(argv[i],"--portrait")) portrait = true; } if (mode & SDL_FULLSCREEN) { const SDL_VideoInfo* info = SDL_GetVideoInfo(); pixel_xres = info->current_w; pixel_yres = info->current_h; #ifdef PPSSPP g_Config.bFullScreen = true; #endif } else { // set a sensible default resolution (2x) pixel_xres = 480 * 2 * set_scale; pixel_yres = 272 * 2 * set_scale; if (portrait) { std::swap(pixel_xres, pixel_yres); } #ifdef PPSSPP g_Config.bFullScreen = false; #endif } set_dpi = 1.0f / set_dpi; if (set_ipad) { pixel_xres = 1024; pixel_yres = 768; } if (!landscape) { std::swap(pixel_xres, pixel_yres); } if (set_xres > 0) { pixel_xres = set_xres; } if (set_yres > 0) { pixel_yres = set_yres; } float dpi_scale = 1.0f; if (set_dpi > 0) { dpi_scale = set_dpi; } dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; g_Screen = SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode); if (g_Screen == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return 2; } #ifdef USING_EGL EGL_Init(); #endif #ifdef PPSSPP SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL); #endif #ifdef MOBILE_DEVICE SDL_ShowCursor(SDL_DISABLE); #endif #ifndef USING_GLES2 if (GLEW_OK != glewInit()) { printf("Failed to initialize glew!\n"); return 1; } if (GLEW_VERSION_2_0) { printf("OpenGL 2.0 or higher.\n"); } else { printf("Sorry, this program requires OpenGL 2.0.\n"); return 1; } #endif #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); TCHAR path[MAX_PATH]; SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); PathAppend(path, (app_name + "\\").c_str()); #else // Mac / Linux char path[512]; const char *the_path = getenv("HOME"); if (!the_path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) the_path = pwd->pw_dir; } strcpy(path, the_path); if (path[strlen(path)-1] != '/') strcat(path, "/"); #endif #ifdef _WIN32 NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE"); #else NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif pixel_in_dps = (float)pixel_xres / dp_xres; g_dpi_scale = dp_xres / (float)pixel_xres; printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); NativeInitGraphics(); NativeResized(); SDL_AudioSpec fmt, ret_fmt; memset(&fmt, 0, sizeof(fmt)); fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; fmt.samples = 2048; fmt.callback = &mixaudio; fmt.userdata = (void *)0; if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); } else { if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2 || fmt.samples != 2048) { ELOG("Sound buffer format does not match requested format."); ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, 44100); ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, AUDIO_S16); ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, 2); ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, 2048); } if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2) { ELOG("Provided output format does not match requirement, turning audio off"); SDL_CloseAudio(); } else { ELOG("Provided output audio format is usable, thus using it"); } } // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); #ifndef _WIN32 joystick = new SDLJoystick(); #endif EnableFZ(); int framecount = 0; float t = 0; float lastT = 0; uint32_t pad_buttons = 0; // legacy pad buttons while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; SDL_Event event; while (SDL_PollEvent(&event)) { float mx = event.motion.x * g_dpi_scale; float my = event.motion.y * g_dpi_scale; switch (event.type) { case SDL_QUIT: g_QuitRequested = 1; break; #if !defined(MOBILE_DEVICE) case SDL_VIDEORESIZE: { g_Screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_OPENGL | SDL_RESIZABLE); if (g_Screen == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return 2; } pixel_xres = event.resize.w; pixel_yres = event.resize.h; dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; NativeResized(); break; } #endif case SDL_KEYDOWN: { int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_DOWN; key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); for (int i = 0; i < ARRAY_SIZE(legacyKeyMap); i++) { if (legacyKeyMap[i] == key.keyCode) pad_buttons |= 1 << i; } break; } case SDL_KEYUP: { int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_UP; key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); for (int i = 0; i < ARRAY_SIZE(legacyKeyMap); i++) { if (legacyKeyMap[i] == key.keyCode) pad_buttons &= ~(1 << i); } break; } case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; input_state.pointer_down[0] = true; input_state.mouse_valid = true; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_DOWN; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_WHEELUP: { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_DOWN; NativeKey(key); } break; case SDL_BUTTON_WHEELDOWN: { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_DOWN; NativeKey(key); } break; } break; case SDL_MOUSEMOTION: if (input_state.pointer_down[0]) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; input_state.mouse_valid = true; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_MOVE; input.id = 0; NativeTouch(input); } break; case SDL_MOUSEBUTTONUP: switch (event.button.button) { case SDL_BUTTON_LEFT: { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; input_state.pointer_down[0] = false; input_state.mouse_valid = true; //input_state.mouse_buttons_up = 1; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_UP; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_WHEELUP: { KeyInput key; key.deviceId = DEVICE_ID_DEFAULT; key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_UP; NativeKey(key); } break; case SDL_BUTTON_WHEELDOWN: { KeyInput key; key.deviceId = DEVICE_ID_DEFAULT; key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_UP; NativeKey(key); } break; } break; default: #ifndef _WIN32 joystick->ProcessInput(event); #endif break; } } if (g_QuitRequested) break; const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); SimulateGamepad(keys, &input_state); input_state.pad_buttons = pad_buttons; UpdateInputState(&input_state, true); NativeUpdate(input_state); if (g_QuitRequested) break; NativeRender(); #if defined(PPSSPP) && !defined(MOBILE_DEVICE) if (lastUIState != globalUIState) { lastUIState = globalUIState; if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) SDL_ShowCursor(SDL_DISABLE); if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen) SDL_ShowCursor(SDL_ENABLE); } #endif EndInputState(&input_state); if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } #ifdef USING_EGL eglSwapBuffers(g_eglDisplay, g_eglSurface); #else if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) { SDL_GL_SwapBuffers(); lastT = t; } #endif ToggleFullScreenIfFlagSet(); time_update(); t = time_now(); framecount++; } #ifndef _WIN32 delete joystick; #endif // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though #ifndef MOBILE_DEVICE exit(0); #endif NativeShutdownGraphics(); SDL_PauseAudio(1); SDL_CloseAudio(); NativeShutdown(); #ifdef USING_EGL EGL_Close(); #endif SDL_Quit(); net::Shutdown(); #ifdef RPI bcm_host_deinit(); #endif exit(0); return 0; }
void BlackberryMain::runMain() { bool running = true; while (running && !g_quitRequested) { input_state.mouse_valid = false; input_state.accelerometer_valid = false; while (true) { // Handle Blackberry events bps_event_t *event = NULL; bps_get_event(&event, 0); if (event == NULL) break; // Ran out of events int domain = bps_event_get_domain(event); if (domain == screen_get_domain()) { handleInput(screen_event_get_event(event)); } else if (domain == navigator_get_domain()) { switch(bps_event_get_code(event)) { case NAVIGATOR_INVOKE_TARGET: { const navigator_invoke_invocation_t *invoke = navigator_invoke_event_get_invocation(event); if(invoke) { boot_filename = navigator_invoke_invocation_get_uri(invoke)+7; // Remove file:// } } break; case NAVIGATOR_ORIENTATION: sensor_remap_coordinates(navigator_event_get_orientation_angle(event)); break; case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN)); break; case NAVIGATOR_EXIT: return; } } else if (domain == sensor_get_domain()) { if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) { sensor_event_get_xyz(event, &(input_state.acc.y), &(input_state.acc.x), &(input_state.acc.z)); AxisInput axis; axis.deviceId = DEVICE_ID_ACCELEROMETER; axis.flags = 0; axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; axis.value = input_state.acc.x; NativeAxis(axis); axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; axis.value = input_state.acc.y; NativeAxis(axis); axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; axis.value = input_state.acc.z; NativeAxis(axis); } } } UpdateInputState(&input_state); NativeUpdate(input_state); // Work in Progress // Currently: Render to HDMI port (eg. 1080p) when in game. Render to device when in menu. // Idea: Render to all displays. Controls go to internal, game goes to external(s). if (GetUIState() == UISTATE_INGAME && !emulating) { emulating = true; switchDisplay(screen_emu); if (g_Config.iShowFPSCounter == 4) { int options = SCREEN_DEBUG_STATISTICS; screen_set_window_property_iv(screen_win[0], SCREEN_PROPERTY_DEBUG, &options); } } else if (GetUIState() != UISTATE_INGAME && emulating) { emulating = false; switchDisplay(screen_ui); } NativeRender(); EndInputState(&input_state); time_update(); // This handles VSync if (emulating) eglSwapBuffers(egl_disp[screen_emu], egl_surf[screen_emu]); else eglSwapBuffers(egl_disp[screen_ui], egl_surf[screen_ui]); } }
extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(JNIEnv *env, jobject obj, jobject _surf) { ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf); WLOG("runEGLRenderLoop. display_xres=%d display_yres=%d", display_xres, display_yres); if (wnd == nullptr) { ELOG("Error: Surface is null."); return false; } AndroidEGLGraphicsContext *graphicsContext = new AndroidEGLGraphicsContext(); if (!graphicsContext->Init(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format)) { ELOG("Failed to initialize graphics context."); delete graphicsContext; return false; } if (!renderer_inited) { NativeInitGraphics(graphicsContext); renderer_inited = true; } exitRenderLoop = false; renderLoopRunning = true; while (!exitRenderLoop) { static bool hasSetThreadName = false; if (!hasSetThreadName) { hasSetThreadName = true; setCurrentThreadName("AndroidRender"); } // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; input_state.pad_rstick_x = right_joystick_x_async; input_state.pad_rstick_y = right_joystick_y_async; UpdateInputState(&input_state); } NativeUpdate(input_state); { lock_guard guard(input_state.lock); EndInputState(&input_state); } NativeRender(graphicsContext); time_update(); graphicsContext->SwapBuffers(); ProcessFrameCommands(env); } ILOG("After render loop."); g_gameInfoCache->WorkQueue()->Flush(); NativeDeviceLost(); ILOG("NativeDeviceLost completed."); NativeShutdownGraphics(); renderer_inited = false; graphicsContext->Shutdown(); renderLoopRunning = false; WLOG("Render loop function exited."); return true; }
void EmuThread::run() { running = true; setCurrentThreadName("EmuThread"); host->UpdateUI(); host->InitGL(); glWindow->makeCurrent(); #ifndef USING_GLES2 glewInit(); #endif NativeInitGraphics(); INFO_LOG(BOOT, "Starting up hardware."); QElapsedTimer timer; while(running) { //UpdateGamepad(*input_state); timer.start(); gameMutex.lock(); bool gRun = gameRunning; gameMutex.unlock(); if(gRun) { gameMutex.lock(); glWindow->makeCurrent(); if(needInitGame) { g_State.bEmuThreadStarted = true; CoreParameter coreParameter; coreParameter.fileToStart = fileToStart.toStdString(); coreParameter.enableSound = true; coreParameter.gpuCore = GPU_GLES; coreParameter.cpuCore = (CPUCore)g_Config.iCpuCore; coreParameter.enableDebugging = true; coreParameter.printfEmuLog = false; coreParameter.headLess = false; coreParameter.renderWidth = 480 * g_Config.iWindowZoom; coreParameter.renderHeight = 272 * g_Config.iWindowZoom; coreParameter.outputWidth = dp_xres; coreParameter.outputHeight = dp_yres; coreParameter.pixelWidth = pixel_xres; coreParameter.pixelHeight = pixel_yres; coreParameter.startPaused = !g_Config.bAutoRun; std::string error_string; if (!PSP_Init(coreParameter, &error_string)) { ERROR_LOG(BOOT, "Error loading: %s", error_string.c_str()); FinalShutdown(); return; } LayoutGamepad(dp_xres, dp_yres); _dbg_update_(); host->UpdateDisassembly(); Core_EnableStepping(coreParameter.startPaused ? TRUE : FALSE); g_State.bBooted = true; #ifdef _DEBUG host->UpdateMemView(); #endif host->BootDone(); needInitGame = false; } UpdateInputState(input_state); for (int i = 0; i < controllistCount; i++) { if (input_state->pad_buttons_down & controllist[i].emu_id) { __CtrlButtonDown(controllist[i].psp_id); } if (input_state->pad_buttons_up & controllist[i].emu_id) { __CtrlButtonUp(controllist[i].psp_id); } } __CtrlSetAnalog(input_state->pad_lstick_x, input_state->pad_lstick_y); EndInputState(input_state); glstate.Restore(); glViewport(0, 0, pixel_xres, pixel_yres); Matrix4x4 ortho; ortho.setOrtho(0.0f, dp_xres, dp_yres, 0.0f, -1.0f, 1.0f); glsl_bind(UIShader_Get()); glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr()); ReapplyGfxState(); Core_Run(); // Hopefully coreState is now CORE_NEXTFRAME if (coreState == CORE_NEXTFRAME) { // set back to running for the next frame coreState = CORE_RUNNING; qint64 time = timer.elapsed(); const int frameTime = (1.0f/60.0f) * 1000; gameMutex.unlock(); if(time < frameTime) { glWindow->doneCurrent(); msleep(frameTime-time); glWindow->makeCurrent(); } gameMutex.lock(); timer.start(); } fbo_unbind(); UIShader_Prepare(); uiTexture->Bind(0); glViewport(0, 0, pixel_xres, pixel_yres); ui_draw2d.Begin(DBMODE_NORMAL); //if (g_Config.bShowTouchControls) // DrawGamepad(ui_draw2d); glsl_bind(UIShader_Get()); ui_draw2d.End(); ui_draw2d.Flush(UIShader_Get()); // Tiled renderers like PowerVR should benefit greatly from this. However - seems I can't call it? #if defined(USING_GLES2) bool hasDiscard = false; // TODO if (hasDiscard) { //glDiscardFramebuffer(GL_COLOR_EXT | GL_DEPTH_EXT | GL_STENCIL_EXT); } #endif glWindow->swapBuffers(); glWindow->doneCurrent(); gameMutex.unlock(); } else { gameMutex.lock(); glWindow->makeCurrent(); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); time_update(); float t = (float)frames_ / 60.0f; frames_++; float alpha = t; if (t > 1.0f) alpha = 1.0f; float alphaText = alpha; //if (t > 2.0f) alphaText = 3.0f - t; glstate.Restore(); glViewport(0, 0, pixel_xres, pixel_yres); Matrix4x4 ortho; ortho.setOrtho(0.0f, dp_xres, dp_yres, 0.0f, -1.0f, 1.0f); glsl_bind(UIShader_Get()); glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr()); ReapplyGfxState(); UIShader_Prepare(); UIBegin(); DrawBackground(alpha); ui_draw2d.SetFontScale(1.5f, 1.5f); ui_draw2d.DrawText(UBUNTU48, "PPSSPP", dp_xres / 2, dp_yres / 2 - 30, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); ui_draw2d.SetFontScale(1.0f, 1.0f); ui_draw2d.DrawText(UBUNTU24, "Created by Henrik Rydgard", dp_xres / 2, dp_yres / 2 + 40, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); ui_draw2d.DrawText(UBUNTU24, "Free Software under GPL 2.0", dp_xres / 2, dp_yres / 2 + 70, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); ui_draw2d.DrawText(UBUNTU24, "www.ppsspp.org", dp_xres / 2, dp_yres / 2 + 130, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); UIEnd(); glsl_bind(UIShader_Get()); ui_draw2d.Flush(UIShader_Get()); glWindow->swapBuffers(); glWindow->doneCurrent(); gameMutex.unlock(); qint64 time = timer.elapsed(); const int frameTime = (1.0f/60.0f) * 1000; if(time < frameTime) { msleep(frameTime-time); } timer.start(); } } if(gameRunning) { stopGame(); } }
// Entry Point int main(int argc, char *argv[]) { static screen_context_t screen_cxt; // Receive events from window manager screen_create_context(&screen_cxt, 0); //Initialise Blackberry Platform Services bps_initialize(); net::Init(); init_GLES2(screen_cxt); #ifdef BLACKBERRY10 // Dev Alpha: 1280x768, 4.2", 356DPI, 0.6f scale int dpi; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_DPI, &dpi); #else // Playbook: 1024x600, 7", 170DPI, 1.25f scale int screen_phys_size[2]; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_PHYSICAL_SIZE, screen_phys_size); int screen_resolution[2]; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); double diagonal_pixels = sqrt(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1]); double diagonal_inches = 0.0393700787 * sqrt(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1]); int dpi = (int)(diagonal_pixels / diagonal_inches + 0.5); #endif float dpi_scale = 213.6f / dpi; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); NativeInit(argc, (const char **)argv, "data/", "/accounts/1000/shared", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); dialog_request_events(0); #ifdef BLACKBERRY10 vibration_request_events(0); #endif BlackberryAudio* audio = new BlackberryAudio(); InputState input_state; bool running = true; while (running) { input_state.mouse_valid = false; input_state.accelerometer_valid = false; SimulateGamepad(&input_state); while (true) { // Handle Blackberry events bps_event_t *event = NULL; bps_get_event(&event, 0); if (event == NULL) break; // Ran out of events int domain = bps_event_get_domain(event); if (domain == screen_get_domain()) { int screen_val, buttons, pointerId; int pair[2]; screen_event_t screen_event = screen_event_get_event(event); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); input_state.mouse_valid = true; switch(screen_val) { // Touchscreen case SCREEN_EVENT_MTOUCH_TOUCH: case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down input_state.pointer_down[pointerId] = (screen_val == SCREEN_EVENT_MTOUCH_TOUCH); case SCREEN_EVENT_MTOUCH_MOVE: input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; break; // Mouse, Simulator case SCREEN_EVENT_POINTER: screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = true; } else if (input_state.pointer_down[pointerId]) { // Up input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = false; } break; // Keyboard case SCREEN_EVENT_KEYBOARD: int flags, value; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); if (flags & (KEY_DOWN | KEY_SYM_VALID)) { for (int b = 0; b < 14; b++) { if (value == buttonMappings[b]) input_state.pad_buttons |= (1<<b); } } break; } } else if (domain == navigator_get_domain()) { switch(bps_event_get_code(event)) { case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: input_state.pad_buttons |= PAD_BUTTON_MENU; break; case NAVIGATOR_EXIT: running = false; break; } } } UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); NativeRender(); // On Blackberry, this handles VSync for us eglSwapBuffers(egl_disp, egl_surf); } screen_stop_events(screen_cxt); bps_shutdown(); NativeShutdownGraphics(); delete audio; NativeShutdown(); kill_GLES2(); net::Shutdown(); screen_destroy_context(screen_cxt); exit(0); return 0; }