示例#1
0
// 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) {
		NativeUpdate();

		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);
	}

	std::lock_guard<std::mutex> guard(frameCommandLock);
	if (!nativeActivity) {
		while (!frameCommands.empty())
			frameCommands.pop();
		return;
	}
	// Still under lock here.
	ProcessFrameCommands(env);
}
示例#2
0
void UpdateRunLoopAndroid(JNIEnv *env) {
	NativeUpdate();

	NativeRender(graphicsContext);
	time_update();

	std::lock_guard<std::mutex> guard(frameCommandLock);
	if (!nativeActivity) {
		while (!frameCommands.empty())
			frameCommands.pop();
		return;
	}
	// Still under lock here.
	ProcessFrameCommands(env);
}
示例#3
0
// 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);
}
示例#4
0
extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(JNIEnv *env, jobject obj, jobject _surf) {
	// Needed for Vulkan, even if we're not using the old EGL path.

	exitRenderLoop = false;
	// This is up here to prevent race conditions, in case we pause during init.
	renderLoopRunning = true;

	ANativeWindow *wnd = _surf ? ANativeWindow_fromSurface(env, _surf) : nullptr;

	WLOG("runEGLRenderLoop. display_xres=%d display_yres=%d", display_xres, display_yres);

	if (wnd == nullptr) {
		ELOG("Error: Surface is null.");
		renderLoopRunning = false;
		return false;
	}

retry:

	bool vulkan = g_Config.iGPUBackend == (int)GPUBackend::VULKAN;

	int tries = 0;

	if (!graphicsContext->InitFromRenderThread(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) {
		ELOG("Failed to initialize graphics context.");

		if (!exitRenderLoop && (vulkan && tries < 2)) {
			ILOG("Trying again, this time with OpenGL.");
			g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
			SetGPUBackend((GPUBackend)g_Config.iGPUBackend);
			tries++;
			goto retry;
		}

		delete graphicsContext;
		graphicsContext = nullptr;
		renderLoopRunning = false;
		return false;
	}

	if (!exitRenderLoop) {
		if (!useCPUThread) {
			NativeInitGraphics(graphicsContext);
		}
		graphicsContext->ThreadStart();
		renderer_inited = true;
	}

	if (!exitRenderLoop) {
		static bool hasSetThreadName = false;
		if (!hasSetThreadName) {
			hasSetThreadName = true;
			setCurrentThreadName("AndroidRender");
		}
	}

	if (useCPUThread) {
		ELOG("Running graphics loop");
		while (!exitRenderLoop) {
			// This is the "GPU thread".
			graphicsContext->ThreadFrame();
			graphicsContext->SwapBuffers();
		}
	} else {
		while (!exitRenderLoop) {
			NativeUpdate();

			NativeRender(graphicsContext);
			time_update();

			graphicsContext->SwapBuffers();

			ProcessFrameCommands(env);
		}
	}

	ILOG("Leaving EGL/Vulkan render loop.");

	if (useCPUThread) {
		EmuThreadStop("exitrenderloop");
		while (graphicsContext->ThreadFrame()) {
			continue;
		}
		EmuThreadJoin();
	} else {
		NativeShutdownGraphics();
	}
	renderer_inited = false;
	graphicsContext->ThreadEnd();

	// Shut the graphics context down to the same state it was in when we entered the render thread.
	ILOG("Shutting down graphics context from render thread...");
	graphicsContext->ShutdownFromRenderThread();
	renderLoopRunning = false;
	WLOG("Render loop function exited.");
	return true;
}
示例#5
0
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
	(JNIEnv *env, jclass, jstring jmodel, jint jdeviceType, jstring jlangRegion, jstring japkpath,
		jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jcacheDir, jstring jshortcutParam,
		jint jAndroidVersion, jstring jboard) {
	setCurrentThreadName("androidInit");

	// Makes sure we get early permission grants.
	ProcessFrameCommands(env);

	ILOG("NativeApp.init() -- begin");
	PROFILE_INIT();

	renderer_inited = false;
	androidVersion = jAndroidVersion;
	deviceType = jdeviceType;

	left_joystick_x_async = 0;
	left_joystick_y_async = 0;
	right_joystick_x_async = 0;
	right_joystick_y_async = 0;
	hat_joystick_x_async = 0;
	hat_joystick_y_async = 0;

	std::string apkPath = GetJavaString(env, japkpath);
	VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/"));

	systemName = GetJavaString(env, jmodel);
	langRegion = GetJavaString(env, jlangRegion);

	std::string externalDir = GetJavaString(env, jexternalDir);
	std::string user_data_path = GetJavaString(env, jdataDir);
	if (user_data_path.size() > 0)
		user_data_path += "/";
	library_path = GetJavaString(env, jlibraryDir) + "/";
	std::string shortcut_param = GetJavaString(env, jshortcutParam);
	std::string cacheDir = GetJavaString(env, jcacheDir);
	std::string buildBoard = GetJavaString(env, jboard);
	boardName = buildBoard;
	ILOG("NativeApp.init(): External storage path: %s", externalDir.c_str());
	ILOG("NativeApp.init(): Launch shortcut parameter: %s", shortcut_param.c_str());

	std::string app_name;
	std::string app_nice_name;
	std::string version;
	bool landscape;

	// Unfortunately, on the Samsung Galaxy S7, this isn't in /proc/cpuinfo.
	// We also can't read it from __system_property_get.
	if (buildBoard == "universal8890") {
		cpu_info.sQuirks.bExynos8890DifferingCachelineSizes = true;
	}

	NativeGetAppInfo(&app_name, &app_nice_name, &landscape, &version);

	// If shortcut_param is not empty, pass it as additional varargs argument to NativeInit() method.
	// NativeInit() is expected to treat extra argument as boot_filename, which in turn will start game immediately.
	// NOTE: Will only work if ppsspp started from Activity.onCreate(). Won't work if ppsspp app start from onResume().

	if (shortcut_param.empty()) {
		const char *argv[2] = {app_name.c_str(), 0};
		NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), cacheDir.c_str());
	} else {
		const char *argv[3] = {app_name.c_str(), shortcut_param.c_str(), 0};
		NativeInit(2, argv, user_data_path.c_str(), externalDir.c_str(), cacheDir.c_str());
	}

retry:
	// Now that we've loaded config, set javaGL.
	javaGL = NativeQueryConfig("androidJavaGL") == "true";

	switch (g_Config.iGPUBackend) {
	case (int)GPUBackend::OPENGL:
		useCPUThread = true;
		if (javaGL) {
			ILOG("NativeApp.init() -- creating OpenGL context (JavaGL)");
			graphicsContext = new AndroidJavaEGLGraphicsContext();
		} else {
			graphicsContext = new AndroidEGLGraphicsContext();
		}
		break;
	case (int)GPUBackend::VULKAN:
	{
		ILOG("NativeApp.init() -- creating Vulkan context");
		useCPUThread = false;  // The Vulkan render manager manages its own thread.
		// We create and destroy the Vulkan graphics context in the "EGL" thread.
		AndroidVulkanContext *ctx = new AndroidVulkanContext();
		if (!ctx->InitAPI()) {
			ILOG("Failed to initialize Vulkan, switching to OpenGL");
			g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
			SetGPUBackend(GPUBackend::OPENGL);
			goto retry;
		} else {
			graphicsContext = ctx;
		}
		break;
	}
	default:
		ELOG("NativeApp.init(): iGPUBackend %d not supported. Switching to OpenGL.", (int)g_Config.iGPUBackend);
		g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
		goto retry;
		// Crash();
	}

	if (useCPUThread) {
		ILOG("NativeApp.init() - launching emu thread");
		EmuThreadStart();
	}
}
示例#6
0
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;
}
示例#7
0
extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(JNIEnv *env, jobject obj, jobject _surf) {
	ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf);

	// Need to get the local JNI env for the graphics thread. Used later in draw_text_android.
	int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_6);
	if (res != JNI_OK) {
		ELOG("GetEnv failed: %d", res);
	}

	WLOG("runEGLRenderLoop. display_xres=%d display_yres=%d", display_xres, display_yres);

	if (wnd == nullptr) {
		ELOG("Error: Surface is null.");
		return false;
	}

retry:

	bool vulkan = g_Config.iGPUBackend == GPU_BACKEND_VULKAN;

	int tries = 0;
	AndroidGraphicsContext *graphicsContext;
	if (vulkan) {
		graphicsContext = new AndroidVulkanContext();
	} else {
		graphicsContext = new AndroidEGLGraphicsContext();
	}

	if (!graphicsContext->Init(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) {
		ELOG("Failed to initialize graphics context.");

		if (vulkan && tries < 2) {
			ILOG("Trying again, this time with OpenGL.");
			g_Config.iGPUBackend = GPU_BACKEND_OPENGL;
			SetGPUBackend((GPUBackend)g_Config.iGPUBackend);  // Wait, why do we need a separate enum here?
			tries++;
			goto retry;
		}

		delete graphicsContext;
		return false;
	}

	if (!renderer_inited) {
		NativeInitGraphics(graphicsContext);
		if (renderer_ever_inited) {
			NativeDeviceRestore();
		}
		renderer_inited = true;
		renderer_ever_inited = true;
	}

	exitRenderLoop = false;
	renderLoopRunning = true;

	while (!exitRenderLoop) {
		static bool hasSetThreadName = false;
		if (!hasSetThreadName) {
			hasSetThreadName = true;
			setCurrentThreadName("AndroidRender");
		}

		NativeUpdate();

		NativeRender(graphicsContext);
		time_update();

		graphicsContext->SwapBuffers();

		ProcessFrameCommands(env);
	}

	ILOG("After render loop.");
	g_gameInfoCache->WorkQueue()->Flush();

	NativeDeviceLost();
	renderer_inited = false;

	ILOG("Shutting down graphics context.");
	graphicsContext->Shutdown();
	delete graphicsContext;
	graphicsContext = nullptr;
	renderLoopRunning = false;
	WLOG("Render loop function exited.");
	jniEnvGraphics = nullptr;
	return true;
}