示例#1
0
unsigned int WINAPI ConsoleListener::RunThread(void *lpParam)
{
	setCurrentThreadName("ConsoleThread");
	ConsoleListener *consoleLog = (ConsoleListener *)lpParam;
	consoleLog->LogWriterThread();
	return 0;
}
示例#2
0
VOID CL_ThreadUnix::SetThreadName()
{
#if defined (_LINUX)
    // if thread is running  do reset the running threadname
    if (!m_tid) return;
    // for task name length can be only 16 byte
    char threadname[TASKNAME_COMLEN];
    strncpy(threadname, m_szThreadName, TASKNAME_COMLEN);
    threadname[TASKNAME_COMLEN - 1] = '\0';
    if (pthread_setname_np(m_tid, threadname))
    {
        CL_PERROR("<<<< Set thread [%lu] [%s] name to [%s] failed : %s.", m_dwThreadID, m_szThreadName, threadname, strerror(errno));
    }
    else
    {
        CL_Printf("<<<< Set thread [%lu] [%s] name to [%s] TC : %lu.", m_dwThreadID, m_szThreadName, threadname, ::GetTickCount());
    }
#elif defined(_FOR_ANDROID_)
    if (m_dwThreadID != (DWORD)gettid())
    {
        CL_PERROR("<<<< Set thread [%s][%lu, 0x%x] name failed, NOT in current Thread.", m_szThreadName, m_dwThreadID, m_dwThreadID);
        return;
    }
    prctl(PR_SET_NAME, (unsigned long) m_szThreadName, 0, 0, 0);
    CL_Printf("<<<< Set thread [%s] (%lu, 0x%x) name TC: %lu.", m_szThreadName, m_dwThreadID, m_dwThreadID, ::GetTickCount());
#elif defined(_FOR_APPLE_)
    if (m_dwThreadID != (DWORD)gettid())
    {
        CL_PERROR("<<<< Set thread [%s][%lu, 0x%x] name failed, NOT in current Thread.", m_szThreadName, m_dwThreadID, m_dwThreadID);
        return;
    }
    setCurrentThreadName(m_szThreadName);
#endif
}
示例#3
0
static void EmuThreadFunc() {
	JNIEnv *env;
	gJvm->AttachCurrentThread(&env, nullptr);

	setCurrentThreadName("Emu");
	ILOG("Entering emu thread");

	// Wait for render loop to get started.
	if (!graphicsContext || !graphicsContext->Initialized()) {
		ILOG("Runloop: Waiting for displayInit...");
		while (!graphicsContext || !graphicsContext->Initialized()) {
			sleep_ms(20);
		}
	} else {
		ILOG("Runloop: Graphics context available! %p", graphicsContext);
	}
	NativeInitGraphics(graphicsContext);

	ILOG("Graphics initialized. Entering loop.");

	// There's no real requirement that NativeInit happen on this thread.
	// We just call the update/render loop here.
	emuThreadState = (int)EmuThreadState::RUNNING;
	while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
		UpdateRunLoopAndroid(env);
	}
	emuThreadState = (int)EmuThreadState::STOPPED;

	NativeShutdownGraphics();

	gJvm->DetachCurrentThread();
	ILOG("Leaving emu thread");
}
示例#4
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);
}
示例#5
0
static void EmuThreadFunc() {
	setCurrentThreadName("Emu");

	while (true) {
		switch ((EmuThreadState)emuThreadState) {
		case EmuThreadState::START_REQUESTED:
			emuThreadState = EmuThreadState::RUNNING;
			/* fallthrough */
		case EmuThreadState::RUNNING:
			EmuFrame();
			break;
		case EmuThreadState::PAUSE_REQUESTED:
			emuThreadState = EmuThreadState::PAUSED;
			/* fallthrough */
		case EmuThreadState::PAUSED:
			sleep_ms(1);
			break;
		default:
		case EmuThreadState::QUIT_REQUESTED:
			emuThreadState = EmuThreadState::STOPPED;
			ctx->StopThread();
			return;
		}
	}
}
示例#6
0
	unsigned int WINAPI soundThread(void *)
	{
		setCurrentThreadName("DSoundThread");
		currentPos = 0;
		lastPos = 0;
		//writeDataToBuffer(0,realtimeBuffer,bufferSize);
		//  dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0); 

		dsBuffer->Play(0,0,DSBPLAY_LOOPING);

		while (!threadData)
		{
			EnterCriticalSection(&soundCriticalSection);

			dsBuffer->GetCurrentPosition((DWORD *)&currentPos, 0);
			int numBytesToRender = RoundDown128(ModBufferSize(currentPos - lastPos)); 

			if (numBytesToRender >= 256)
			{
				int numBytesRendered = 4 * (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2);
				//We need to copy the full buffer, regardless of what the mixer claims to have filled
				//If we don't do this then the sound will loop if the sound stops and the mixer writes only zeroes
				numBytesRendered = numBytesToRender;
				writeDataToBuffer(lastPos, (char *) realtimeBuffer, numBytesRendered);

				currentPos = ModBufferSize(lastPos + numBytesRendered);
				totalRenderedBytes += numBytesRendered;

				lastPos = currentPos;
			}

			LeaveCriticalSection(&soundCriticalSection);
			WaitForSingleObject(soundSyncEvent, MAXWAIT);
		}
示例#7
0
// TODO: Move the init into the thread, like WASAPI?
int DSoundAudioBackend::RunThread() {
	setCurrentThreadName("DSound");
	currentPos_ = 0;
	lastPos_ = 0;

	dsBuffer_->Play(0,0,DSBPLAY_LOOPING);

	while (!threadData_) {
		EnterCriticalSection(&soundCriticalSection);

		dsBuffer_->GetCurrentPosition((DWORD *)&currentPos_, 0);
		int numBytesToRender = RoundDown128(ModBufferSize(currentPos_ - lastPos_)); 

		if (numBytesToRender >= 256) {
			int numBytesRendered = 4 * (*callback_)(realtimeBuffer_, numBytesToRender >> 2, 16, 44100, 2);
			//We need to copy the full buffer, regardless of what the mixer claims to have filled
			//If we don't do this then the sound will loop if the sound stops and the mixer writes only zeroes
			numBytesRendered = numBytesToRender;
			WriteDataToBuffer(lastPos_, (char *) realtimeBuffer_, numBytesRendered);

			currentPos_ = ModBufferSize(lastPos_ + numBytesRendered);
			totalRenderedBytes_ += numBytesRendered;

			lastPos_ = currentPos_;
		}

		LeaveCriticalSection(&soundCriticalSection);
		WaitForSingleObject(soundSyncEvent_, MAXWAIT);
	}
示例#8
0
void COLD AsyncJobRouterController::start() {
    //Lambdas rock
    childThread = new std::thread([](void* ctx, Tablespace& tablespace) {
        setCurrentThreadName("Yak job router");
        AsyncJobRouter worker(ctx, tablespace);
        while(worker.processNextRequest()) {
            //Loop until stop msg is received (--> processNextRequest() returns false)
        }
    }, ctx, std::ref(tablespace));
}
示例#9
0
//==============================================================================
void Thread::threadEntryPoint()
{
    if (!threadName.empty ())
        setCurrentThreadName (threadName);

    if (startSuspensionEvent.wait (10000))
        run();

    closeThreadHandle();
}
示例#10
0
int DSoundAudioBackend::RunThread() {
	if (FAILED(DirectSoundCreate8(0, &ds_, 0))) {
		ds_ = NULL;
		threadData_ = 2;
		return 1;
	}

	ds_->SetCooperativeLevel(window_, DSSCL_PRIORITY);
	if (!CreateBuffer()) {
		ds_->Release();
		ds_ = NULL;
		threadData_ = 2;
		return 1;
	}

	soundSyncEvent_ = CreateEvent(0, false, false, 0);
	InitializeCriticalSection(&soundCriticalSection);

	DWORD num1;
	short *p1;

	dsBuffer_->Lock(0, bufferSize_, (void **)&p1, &num1, 0, 0, 0);

	memset(p1, 0, num1);
	dsBuffer_->Unlock(p1, num1, 0, 0);
	totalRenderedBytes_ = -bufferSize_;

	setCurrentThreadName("DSound");
	currentPos_ = 0;
	lastPos_ = 0;

	dsBuffer_->Play(0,0,DSBPLAY_LOOPING);

	while (!threadData_) {
		EnterCriticalSection(&soundCriticalSection);

		dsBuffer_->GetCurrentPosition((DWORD *)&currentPos_, 0);
		int numBytesToRender = RoundDown128(ModBufferSize(currentPos_ - lastPos_)); 

		if (numBytesToRender >= 256) {
			int numBytesRendered = 4 * (*callback_)(realtimeBuffer_, numBytesToRender >> 2, 16, 44100, 2);
			//We need to copy the full buffer, regardless of what the mixer claims to have filled
			//If we don't do this then the sound will loop if the sound stops and the mixer writes only zeroes
			numBytesRendered = numBytesToRender;
			WriteDataToBuffer(lastPos_, (char *) realtimeBuffer_, numBytesRendered);

			currentPos_ = ModBufferSize(lastPos_ + numBytesRendered);
			totalRenderedBytes_ += numBytesRendered;

			lastPos_ = currentPos_;
		}

		LeaveCriticalSection(&soundCriticalSection);
		WaitForSingleObject(soundSyncEvent_, MAXWAIT);
	}
示例#11
0
void CPU_RunLoop() {
	setCurrentThreadName("CPU");
	FPU_SetFastMode();

	if (CPU_NextState(CPU_THREAD_PENDING, CPU_THREAD_STARTING)) {
		CPU_Init();
		CPU_NextState(CPU_THREAD_STARTING, CPU_THREAD_RUNNING);
	} else if (!CPU_NextState(CPU_THREAD_RESUME, CPU_THREAD_RUNNING)) {
		ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState);
		return;
	}

	while (cpuThreadState != CPU_THREAD_SHUTDOWN)
	{
		CPU_WaitStatus(cpuThreadCond, &CPU_HasPendingAction);
		switch (cpuThreadState) {
		case CPU_THREAD_EXECUTE:
			mipsr4k.RunLoopUntil(cpuThreadUntil);
			gpu->FinishEventLoop();
			CPU_NextState(CPU_THREAD_EXECUTE, CPU_THREAD_RUNNING);
			break;

		// These are fine, just keep looping.
		case CPU_THREAD_RUNNING:
		case CPU_THREAD_SHUTDOWN:
			break;

		case CPU_THREAD_QUIT:
			// Just leave the thread, CPU is switching off thread.
			CPU_SetState(CPU_THREAD_NOT_RUNNING);
			return;

		default:
			ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState);
			// Begin shutdown, otherwise we'd just spin on this bad state.
			CPU_SetState(CPU_THREAD_SHUTDOWN);
			break;
		}
	}

	if (coreState != CORE_ERROR) {
		coreState = CORE_POWERDOWN;
	}

	// Let's make sure the gpu has already cleaned up before we start freeing memory.
	if (gpu) {
		gpu->FinishEventLoop();
		gpu->SyncThread(true);
	}

	CPU_Shutdown();
	CPU_SetState(CPU_THREAD_NOT_RUNNING);
}
示例#12
0
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);
	}
}
示例#13
0
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) {
	static bool hasSetThreadName = false;
	if (!hasSetThreadName) {
		hasSetThreadName = true;
		setCurrentThreadName("AndroidRender");
	}
	
	if (useCPUThread) {
		// This is the "GPU thread".
		graphicsContext->ThreadFrame();
	} else {
		UpdateRunLoopAndroid(env);
	}
}
示例#14
0
static void EmuThreadFunc(GraphicsContext *graphicsContext) {
	setCurrentThreadName("Emu");

	// There's no real requirement that NativeInit happen on this thread.
	// We just call the update/render loop here.
	emuThreadState = (int)EmuThreadState::RUNNING;

	NativeInitGraphics(graphicsContext);

	while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
		UpdateRunLoop();
	}
	emuThreadState = (int)EmuThreadState::STOPPED;

	NativeShutdownGraphics();
}
示例#15
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);
}
示例#16
0
static void RunInputThread() {
	setCurrentThreadName("Input");

	// NOTE: The keyboard and mouse buttons are handled via raw input, not here.
	// This is mainly for controllers which need to be polled, instead of generating events.

	while (inputThreadEnabled) {
		ExecuteInputPoll();

		// Try to update 250 times per second.
		Sleep(4);
	}

	lock_guard guard(inputMutex);
	inputThreadStatus = false;
	inputEndCond.notify_one();
}
示例#17
0
void VulkanRenderManager::ThreadFunc() {
	setCurrentThreadName("RenderMan");
	int threadFrame = threadInitFrame_;
	bool nextFrame = false;
	bool firstFrame = true;
	while (true) {
		{
			if (nextFrame) {
				threadFrame++;
				if (threadFrame >= vulkan_->GetInflightFrames())
					threadFrame = 0;
			}
			FrameData &frameData = frameData_[threadFrame];
			std::unique_lock<std::mutex> lock(frameData.pull_mutex);
			while (!frameData.readyForRun && run_) {
				VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame);
				frameData.pull_condVar.wait(lock);
			}
			if (!frameData.readyForRun && !run_) {
				// This means we're out of frames to render and run_ is false, so bail.
				break;
			}
			VLOG("PULL: frame[%d].readyForRun = false", threadFrame);
			frameData.readyForRun = false;
			// Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false,
			// but that created a race condition where frames could end up not finished properly on resize etc.

			// Only increment next time if we're done.
			nextFrame = frameData.type == VKRRunType::END;
			assert(frameData.type == VKRRunType::END || frameData.type == VKRRunType::SYNC);
		}
		VLOG("PULL: Running frame %d", threadFrame);
		if (firstFrame) {
			ILOG("Running first frame (%d)", threadFrame);
			firstFrame = false;
		}
		Run(threadFrame);
		VLOG("PULL: Finished frame %d", threadFrame);
	}

	// Wait for the device to be done with everything, before tearing stuff down.
	vkDeviceWaitIdle(vulkan_->GetDevice());

	VLOG("PULL: Quitting");
}
示例#18
0
void Thread::threadEntryPoint()
{
    const CurrentThreadHolder::Ptr currentThreadHolder (getCurrentThreadHolder());
    currentThreadHolder->value = this;

    if (threadName.isNotEmpty())
        setCurrentThreadName (threadName);

    if (startSuspensionEvent.wait (10000))
    {
        bassert (getCurrentThreadId() == threadId);

        if (affinityMask != 0)
            setCurrentThreadAffinityMask (affinityMask);

        run();
    }

    currentThreadHolder->value.releaseCurrentThreadStorage();
    closeThreadHandle();
}
示例#19
0
	static int CalculateCRCThread() {
		setCurrentThreadName("ReportCRC");

		// TODO: Use the blockDevice from pspFileSystem?
		FileLoader *fileLoader = ConstructFileLoader(crcFilename);
		BlockDevice *blockDevice = constructBlockDevice(fileLoader);

		u32 crc = 0;
		if (blockDevice) {
			crc = blockDevice->CalculateCRC();
		}

		delete blockDevice;
		delete fileLoader;

		lock_guard guard(crcLock);
		crcResults[crcFilename] = crc;
		crcCond.notify_one();

		return 0;
	}
示例#20
0
void CPU_RunLoop() {
	setCurrentThreadName("CPUThread");
	if (!CPU_NextState(CPU_THREAD_PENDING, CPU_THREAD_STARTING)) {
		ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState);
		return;
	}

	CPU_Init();
	CPU_NextState(CPU_THREAD_STARTING, CPU_THREAD_RUNNING);

	while (cpuThreadState != CPU_THREAD_SHUTDOWN)
	{
		CPU_WaitStatus(&CPU_HasPendingAction);
		switch (cpuThreadState) {
		case CPU_THREAD_EXECUTE:
			mipsr4k.RunLoopUntil(cpuThreadUntil);
			gpu->FinishEventLoop();
			CPU_NextState(CPU_THREAD_EXECUTE, CPU_THREAD_RUNNING);
			break;

		// These are fine, just keep looping.
		case CPU_THREAD_RUNNING:
		case CPU_THREAD_SHUTDOWN:
			break;

		default:
			ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState);
			// Begin shutdown, otherwise we'd just spin on this bad state.
			CPU_SetState(CPU_THREAD_SHUTDOWN);
			break;
		}
	}

	if (coreState != CORE_ERROR) {
		coreState = CORE_POWERDOWN;
	}

	CPU_Shutdown();
	CPU_SetState(CPU_THREAD_NOT_RUNNING);
}
示例#21
0
	unsigned int WINAPI soundThread(void *)
	{
		setCurrentThreadName("DSoundThread");
		currentPos = 0;
		lastPos = 0;
		//writeDataToBuffer(0,realtimeBuffer,bufferSize);
		//  dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0); 

		dsBuffer->Play(0,0,DSBPLAY_LOOPING);

		while (!threadData)
		{
			EnterCriticalSection(&soundCriticalSection);

			dsBuffer->GetCurrentPosition((DWORD *)&currentPos, 0);
			int numBytesToRender = RoundDown128(ModBufferSize(currentPos - lastPos)); 

			//renderStuff(numBytesToRender/2);
			//if (numBytesToRender>bufferSize/2) numBytesToRender=0;

			if (numBytesToRender >= 256)
			{
				int numBytesRendered = 4 * (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2);

				if (numBytesRendered != 0)
					writeDataToBuffer(lastPos, (char *)realtimeBuffer, numBytesRendered);

				currentPos = ModBufferSize(lastPos + numBytesRendered);
				totalRenderedBytes += numBytesRendered;

				lastPos = currentPos;
			}


			LeaveCriticalSection(&soundCriticalSection);
			WaitForSingleObject(soundSyncEvent, MAXWAIT);
		}
示例#22
0
unsigned int WINAPI TheThread(void *)
{
    _InterlockedExchange(&emuThreadReady, THREAD_INIT);

    setCurrentThreadName("EmuThread");

    std::string memstick, flash0;
    GetSysDirectories(memstick, flash0);

    // Native overwrites host. Can't allow that.

    Host *oldHost = host;
    UpdateScreenScale();

    NativeInit(__argc, (const char **)__argv, memstick.c_str(), memstick.c_str(), "1234");
    Host *nativeHost = host;
    host = oldHost;

    host->UpdateUI();

    std::string error_string;
    if (!host->InitGL(&error_string)) {
        Reporting::ReportMessage("OpenGL init error: %s", error_string.c_str());
        std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str());
        MessageBoxA(0, full_error.c_str(), "OpenGL Error", MB_OK | MB_ICONERROR);
        ERROR_LOG(BOOT, full_error.c_str());
        goto shutdown;
    }

    NativeInitGraphics();

    INFO_LOG(BOOT, "Done.");
    _dbg_update_();

    if (coreState == CORE_POWERDOWN) {
        INFO_LOG(BOOT, "Exit before core loop.");
        goto shutdown;
    }

    _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP);

    if (g_Config.bBrowse)
    {
        PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0);
        //MainWindow::BrowseAndBoot("");
    }

    Core_EnableStepping(FALSE);

    while (globalUIState != UISTATE_EXIT)
    {
        Core_Run();

        // We're here again, so the game quit.  Restart Core_Run() which controls the UI.
        // This way they can load a new game.
        Core_UpdateState(CORE_RUNNING);
    }

shutdown:
    _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN);

    NativeShutdownGraphics();
    host = nativeHost;
    NativeShutdown();
    host = oldHost;
    host->ShutdownGL();

    _InterlockedExchange(&emuThreadReady, THREAD_END);

    //The CPU should return when a game is stopped and cleanup should be done here,
    //so we can restart the plugins (or load new ones) for the next game
    return 0;
}
示例#23
0
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
  (JNIEnv *env, jclass, jstring jmodel, jint jdeviceType, jint jxres, jint jyres, jstring jlangRegion, jstring japkpath,
		jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam,
		jstring jinstallID, jint jAndroidVersion) {
	jniEnvUI = env;

	setCurrentThreadName("androidInit");

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

	memset(&input_state, 0, sizeof(input_state));
	renderer_inited = false;
	first_lost = true;
	androidVersion = jAndroidVersion;
	deviceType = jdeviceType;

	g_buttonTracker.Reset();

	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;
	display_xres = jxres;
	display_yres = jyres;

	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) + "/";
	library_path = GetJavaString(env, jlibraryDir) + "/";
	std::string shortcut_param = GetJavaString(env, jshortcutParam);
	std::string installID = GetJavaString(env, jinstallID);

	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;

	net::Init();

	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(), installID.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(), installID.c_str());
	}

	ILOG("NativeApp.init() -- end");
}
示例#24
0
int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
	setCurrentThreadName("Main");

	// Windows Vista and above: alert Windows that PPSSPP is DPI aware,
	// so that we don't flicker in fullscreen on some PCs.
	MakePPSSPPDPIAware();

	// FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it.
#ifdef _M_X64
	_set_FMA3_enable(0);
#endif

	EnableCrashingOnCrashes();

	wchar_t modulePath[MAX_PATH];
	GetModuleFileName(NULL, modulePath, MAX_PATH);
	for (size_t i = wcslen(modulePath) - 1; i > 0; i--) {
		if (modulePath[i] == '\\') {
			modulePath[i] = 0;
			break;
		}
	}
	SetCurrentDirectory(modulePath);
	// GetCurrentDirectory(MAX_PATH, modulePath);  // for checking in the debugger

#ifndef _DEBUG
	bool showLog = false;
#else
	bool showLog = false;
#endif

	VFSRegister("", new DirectoryAssetReader("assets/"));
	VFSRegister("", new DirectoryAssetReader(""));

	wchar_t lcCountry[256];

	// LOCALE_SNAME is only available in WinVista+
	// Really should find a way to do this in XP too :/
	if (0 != GetLocaleInfo(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, lcCountry, 256)) {
		langRegion = ConvertWStringToUTF8(lcCountry);
		for (size_t i = 0; i < langRegion.size(); i++) {
			if (langRegion[i] == '-')
				langRegion[i] = '_';
		}
	} else {
		langRegion = "en_US";
	}

	osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture();

	const char *configFilename = NULL;
	const char *configOption = "--config=";

	const char *controlsConfigFilename = NULL;
	const char *controlsOption = "--controlconfig=";

	for (int i = 1; i < __argc; ++i)
	{
		if (__argv[i][0] == '\0')
			continue;
		if (__argv[i][0] == '-')
		{
			if (!strncmp(__argv[i], configOption, strlen(configOption)) && strlen(__argv[i]) > strlen(configOption)) {
				configFilename = __argv[i] + strlen(configOption);
			}
			if (!strncmp(__argv[i], controlsOption, strlen(controlsOption)) && strlen(__argv[i]) > strlen(controlsOption)) {
				controlsConfigFilename = __argv[i] + strlen(controlsOption);
			}
		}
	}

	// On Win32 it makes more sense to initialize the system directories here 
	// because the next place it was called was in the EmuThread, and it's too late by then.
	InitSysDirectories();

	// Load config up here, because those changes below would be overwritten
	// if it's not loaded here first.
	g_Config.AddSearchPath("");
	g_Config.AddSearchPath(GetSysDirectory(DIRECTORY_SYSTEM));
	g_Config.SetDefaultPath(GetSysDirectory(DIRECTORY_SYSTEM));
	g_Config.Load(configFilename, controlsConfigFilename);

	bool debugLogLevel = false;

	// The rest is handled in NativeInit().
	for (int i = 1; i < __argc; ++i)
	{
		if (__argv[i][0] == '\0')
			continue;

		if (__argv[i][0] == '-')
		{
			switch (__argv[i][1])
			{
			case 'l':
				showLog = true;
				g_Config.bEnableLogging = true;
				break;
			case 's':
				g_Config.bAutoRun = false;
				g_Config.bSaveSettings = false;
				break;
			case 'd':
				debugLogLevel = true;
				break;
			}

			if (!strncmp(__argv[i], "--fullscreen", strlen("--fullscreen")))
				g_Config.bFullScreen = true;

			if (!strncmp(__argv[i], "--windowed", strlen("--windowed")))
				g_Config.bFullScreen = false;
		}
	}
#ifdef _DEBUG
	g_Config.bEnableLogging = true;
#endif

	LogManager::Init();
	// Consider at least the following cases before changing this code:
	//   - By default in Release, the console should be hidden by default even if logging is enabled.
	//   - By default in Debug, the console should be shown by default.
	//   - The -l switch is expected to show the log console, REGARDLESS of config settings.
	//   - It should be possible to log to a file without showing the console.
	LogManager::GetInstance()->GetConsoleListener()->Init(showLog, 150, 120, "PPSSPP Debug Console");
	
	if (debugLogLevel)
		LogManager::GetInstance()->SetAllLogLevels(LogTypes::LDEBUG);

	//Windows, API init stuff
	INITCOMMONCONTROLSEX comm;
	comm.dwSize = sizeof(comm);
	comm.dwICC = ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES;
	InitCommonControlsEx(&comm);
	timeBeginPeriod(1);
	MainWindow::Init(_hInstance);

	g_hPopupMenus = LoadMenu(_hInstance, (LPCWSTR)IDR_POPUPMENUS);

	MainWindow::Show(_hInstance, iCmdShow);

	HWND hwndMain = MainWindow::GetHWND();
	HWND hwndDisplay = MainWindow::GetDisplayHWND();
	
	//initialize custom controls
	CtrlDisAsmView::init();
	CtrlMemView::init();
	CtrlRegisterList::init();
	CGEDebugger::Init();

	DialogManager::AddDlg(vfpudlg = new CVFPUDlg(_hInstance, hwndMain, currentDebugMIPS));

	host = new WindowsHost(hwndMain, hwndDisplay);
	host->SetWindowTitle(0);

	MainWindow::CreateDebugWindows();

	// Emu thread is always running!
	EmuThread_Start();
	InputDevice::BeginPolling();

	HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS);
	HACCEL hDebugAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_DEBUGACCELS);

	//so.. we're at the message pump of the GUI thread
	for (MSG msg; GetMessage(&msg, NULL, 0, 0); )	// for no quit
	{
		if (msg.message == WM_KEYDOWN)
		{
			//hack to enable/disable menu command accelerate keys
			MainWindow::UpdateCommands();

			//hack to make it possible to get to main window from floating windows with Esc
			if (msg.hwnd != hwndMain && msg.wParam == VK_ESCAPE)
				BringWindowToTop(hwndMain);
		}

		//Translate accelerators and dialog messages...
		HWND wnd;
		HACCEL accel;
		switch (g_activeWindow)
		{
		case WINDOW_MAINWINDOW:
			wnd = hwndMain;
			accel = hAccelTable;
			break;
		case WINDOW_CPUDEBUGGER:
			wnd = disasmWindow[0] ? disasmWindow[0]->GetDlgHandle() : 0;
			accel = hDebugAccelTable;
			break;
		case WINDOW_GEDEBUGGER:
		default:
			wnd = 0;
			accel = 0;
			break;
		}

		if (!TranslateAccelerator(wnd, accel, &msg))
		{
			if (!DialogManager::IsDialogMessage(&msg))
			{
				//and finally translate and dispatch
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
	}

	VFSShutdown();

	InputDevice::StopPolling();
	EmuThread_Stop();

	MainWindow::DestroyDebugWindows();
	DialogManager::DestroyAll();
	timeEndPeriod(1);
	delete host;
	g_Config.Save();
	LogManager::Shutdown();
	return 0;
}
示例#25
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;
}
示例#26
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();
	}
}
示例#27
0
unsigned int WINAPI TheThread(void *)
{
	_InterlockedExchange(&emuThreadReady, THREAD_INIT);

	setCurrentThreadName("Emu");  // And graphics...

	host = new WindowsHost(MainWindow::GetHInstance(), MainWindow::GetHWND(), MainWindow::GetDisplayHWND());
	host->SetWindowTitle(nullptr);

	// Convert the command-line arguments to Unicode, then to proper UTF-8 
	// (the benefit being that we don't have to pollute the UI project with win32 ifdefs and lots of Convert<whatever>To<whatever>).
	// This avoids issues with PPSSPP inadvertently destroying paths with Unicode glyphs 
	// (using the ANSI args resulted in Japanese/Chinese glyphs being turned into question marks, at least for me..).
	// -TheDax
	std::vector<std::wstring> wideArgs = GetWideCmdLine();
	std::vector<std::string> argsUTF8;
	for (auto& string : wideArgs) {
		argsUTF8.push_back(ConvertWStringToUTF8(string));
	}

	std::vector<const char *> args;

	for (auto& string : argsUTF8) {
		args.push_back(string.c_str());
	}

	bool performingRestart = NativeIsRestarting();
	NativeInit(static_cast<int>(args.size()), &args[0], "1234", "1234", nullptr);

	host->UpdateUI();

	GraphicsContext *graphicsContext = nullptr;

	std::string error_string;
	if (!host->InitGraphics(&error_string, &graphicsContext)) {
		// Before anything: are we restarting right now?
		if (performingRestart) {
			// Okay, switching graphics didn't work out.  Probably a driver bug - fallback to restart.
			// This happens on NVIDIA when switching OpenGL -> Vulkan.
			g_Config.Save();
			W32Util::ExitAndRestart();
		}

		I18NCategory *err = GetI18NCategory("Error");
		Reporting::ReportMessage("Graphics init error: %s", error_string.c_str());

		const char *defaultErrorVulkan = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to OpenGL?\n\nError message:";
		const char *defaultErrorOpenGL = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to DirectX 9?\n\nError message:";
		const char *defaultErrorDirect3D9 = "Failed initializing graphics. Try upgrading your graphics drivers and directx 9 runtime.\n\nWould you like to try switching to OpenGL?\n\nError message:";
		const char *genericError;
		int nextBackend = GPU_BACKEND_DIRECT3D9;
		switch (g_Config.iGPUBackend) {
		case GPU_BACKEND_DIRECT3D9:
			nextBackend = GPU_BACKEND_OPENGL;
			genericError = err->T("GenericDirect3D9Error", defaultErrorDirect3D9);
			break;
		case GPU_BACKEND_VULKAN:
			nextBackend = GPU_BACKEND_OPENGL;
			genericError = err->T("GenericVulkanError", defaultErrorVulkan);
			break;
		case GPU_BACKEND_OPENGL:
		default:
			nextBackend = GPU_BACKEND_DIRECT3D9;
			genericError = err->T("GenericOpenGLError", defaultErrorOpenGL);
			break;
		}
		std::string full_error = StringFromFormat("%s\n\n%s", genericError, error_string.c_str());
		std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error"));
		bool yes = IDYES == MessageBox(0, ConvertUTF8ToWString(full_error).c_str(), title.c_str(), MB_ICONERROR | MB_YESNO);
		ERROR_LOG(BOOT, full_error.c_str());

		if (yes) {
			// Change the config to the alternative and restart.
			g_Config.iGPUBackend = nextBackend;
			g_Config.Save();

			W32Util::ExitAndRestart();
		}

		// No safe way out without graphics.
		ExitProcess(1);
	}

	NativeInitGraphics(graphicsContext);
	NativeResized();

	INFO_LOG(BOOT, "Done.");
	_dbg_update_();

	if (coreState == CORE_POWERDOWN) {
		INFO_LOG(BOOT, "Exit before core loop.");
		goto shutdown;
	}

	_InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP);

	if (g_Config.bBrowse)
		PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0);

	Core_EnableStepping(FALSE);

	while (GetUIState() != UISTATE_EXIT)
	{
		// We're here again, so the game quit.  Restart Core_Run() which controls the UI.
		// This way they can load a new game.
		if (!Core_IsActive())
			UpdateUIState(UISTATE_MENU);

		Core_Run(graphicsContext);
	}

shutdown:
	_InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN);

	NativeShutdownGraphics();

	// NativeShutdown deletes the graphics context through host->ShutdownGraphics().
	NativeShutdown();
	
	_InterlockedExchange(&emuThreadReady, THREAD_END);

	return 0;
}
示例#28
0
static void DoExecuteIOAction(PSPSaveDialog *dialog) {
	setCurrentThreadName("SaveIO");
	dialog->ExecuteIOAction();
}
示例#29
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;
}
示例#30
0
unsigned int WINAPI TheThread(void *)
{
    _InterlockedExchange(&emuThreadReady, THREAD_INIT);

    setCurrentThreadName("EmuThread");

    // Native overwrites host. Can't allow that.

    Host *oldHost = host;
    UpdateScreenScale();

    NativeInit(__argc, (const char **)__argv, "1234", "1234", "1234");
    Host *nativeHost = host;
    host = oldHost;

    host->UpdateUI();

    //Check Colour depth
    HDC dc = GetDC(NULL);
    u32 colour_depth = GetDeviceCaps(dc, BITSPIXEL);
    ReleaseDC(NULL, dc);
    if (colour_depth != 32) {
        MessageBoxA(0, "Please switch your display to 32-bit colour mode", "OpenGL Error", MB_OK);
        ExitProcess(1);
    }

    std::string error_string;
    if (!host->InitGL(&error_string)) {
        Reporting::ReportMessage("OpenGL init error: %s", error_string.c_str());
        std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str());
        MessageBoxA(0, full_error.c_str(), "OpenGL Error", MB_OK | MB_ICONERROR);
        ERROR_LOG(BOOT, full_error.c_str());

        // No safe way out without OpenGL.
        ExitProcess(1);
    }

    NativeInitGraphics();

    INFO_LOG(BOOT, "Done.");
    _dbg_update_();

    if (coreState == CORE_POWERDOWN) {
        INFO_LOG(BOOT, "Exit before core loop.");
        goto shutdown;
    }

    _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP);

    if (g_Config.bBrowse)
        PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0);

    Core_EnableStepping(FALSE);

    while (globalUIState != UISTATE_EXIT)
    {
        // We're here again, so the game quit.  Restart Core_Run() which controls the UI.
        // This way they can load a new game.
        if (!Core_IsActive())
            UpdateUIState(UISTATE_MENU);

        Core_Run();
    }

shutdown:
    _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN);

    NativeShutdownGraphics();

    host->ShutdownSound();
    host = nativeHost;
    NativeShutdown();
    host = oldHost;
    host->ShutdownGL();

    _InterlockedExchange(&emuThreadReady, THREAD_END);

    return 0;
}