Example #1
0
void hleEnterVblank(u64 userdata, int cyclesLate) {
	int vbCount = userdata;

	DEBUG_LOG(HLE, "Enter VBlank %i", vbCount);

	isVblank = 1;
	vCount++; // // vCount increases at each VBLANK.

	// Fire the vblank listeners before we wake threads.
	__DisplayFireVblank();

	// Wake up threads waiting for VBlank
	for (size_t i = 0; i < vblankWaitingThreads.size(); i++) {
		if (--vblankWaitingThreads[i].vcountUnblock == 0) {
			__KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0);
			vblankWaitingThreads.erase(vblankWaitingThreads.begin() + i--);
		}
	}

	// Trigger VBlank interrupt handlers.
	__TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL);

	CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount + 1);

	// TODO: Should this be done here or in hleLeaveVblank?
	if (framebufIsLatched) {
		DEBUG_LOG(HLE, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr);
		framebuf = latchedFramebuf;
		framebufIsLatched = false;
		gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat);
	}

	gpuStats.numFrames++;

	if (g_Config.bShowFPSCounter) {
		CalculateFPS();
	}

	bool skipFlip = false;

	// This frame was skipped, so no need to flip.
	if (gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) {
		skipFlip = true;
	}

	// Draw screen overlays before blitting. Saves and restores the Ge context.
	// Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity
	// to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have
	// anything to draw here.
	gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME;

	bool throttle, skipFrame;
	
	DoFrameTiming(throttle, skipFrame);

	if (skipFrame) {
		gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME;
		numSkippedFrames++;
	} else {
		numSkippedFrames = 0;
	}

	if (!skipFlip) {
		// Setting CORE_NEXTFRAME causes a swap.
		// Check first though, might've just quit / been paused.
		if (coreState == CORE_RUNNING && gpu->FramebufferDirty()) {
			coreState = CORE_NEXTFRAME;
		}

		gpu->CopyDisplayToOutput();
	}

	// Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame).
	// Right after, we regain control for a little bit in hleAfterFlip. I think that's a great
	// place to do housekeeping.
	CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0);
}
Example #2
0
void hleEnterVblank(u64 userdata, int cyclesLate) {
	int vbCount = userdata;

	DEBUG_LOG(SCEDISPLAY, "Enter VBlank %i", vbCount);

	isVblank = 1;
	vCount++; // vCount increases at each VBLANK.
	hCountBase += hCountPerVblank; // This is the "accumulated" hcount base.
	if (hCountBase > 0x7FFFFFFF) {
		hCountBase -= 0x80000000;
	}
	frameStartTicks = CoreTiming::GetTicks();

	// Wake up threads waiting for VBlank
	u32 error;
	for (size_t i = 0; i < vblankWaitingThreads.size(); i++) {
		if (--vblankWaitingThreads[i].vcountUnblock == 0) {
			// Only wake it if it wasn't already released by someone else.
			SceUID waitID = __KernelGetWaitID(vblankWaitingThreads[i].threadID, WAITTYPE_VBLANK, error);
			if (waitID == 1) {
				__KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0);
			}
			vblankWaitingThreads.erase(vblankWaitingThreads.begin() + i--);
		}
	}

	// Trigger VBlank interrupt handlers.
	__TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL);

	CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount + 1);

	gpuStats.numVBlanks++;

	numVBlanksSinceFlip++;

	// TODO: Should this be done here or in hleLeaveVblank?
	if (framebufIsLatched) {
		DEBUG_LOG(SCEDISPLAY, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr);
		framebuf = latchedFramebuf;
		framebufIsLatched = false;
		gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat);
	}
	// We flip only if the framebuffer was dirty. This eliminates flicker when using
	// non-buffered rendering. The interaction with frame skipping seems to need
	// some work.
	// But, let's flip at least once every 10 frames if possible, since there may be sound effects.
	if (gpu->FramebufferDirty() || (g_Config.iRenderingMode != 0 && numVBlanksSinceFlip >= 10)) {
		if (g_Config.iShowFPSCounter && g_Config.iShowFPSCounter < 4) {
			CalculateFPS();
		}

		// Setting CORE_NEXTFRAME causes a swap.
		// Check first though, might've just quit / been paused.
		if (gpu->FramebufferReallyDirty()) {
			if (coreState == CORE_RUNNING) {
				coreState = CORE_NEXTFRAME;
				gpu->CopyDisplayToOutput();
				actualFlips++;
			}
		}

		gpuStats.numFlips++;

		bool throttle, skipFrame;
		// 1.001f to compensate for the classic 59.94 NTSC framerate that the PSP seems to have.
		DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * (1.001f / 60.0f));

		int maxFrameskip = 8;
		if (throttle) {
			// 4 here means 1 drawn, 4 skipped - so 12 fps minimum.
			maxFrameskip = g_Config.iFrameSkip;
		}
		if (numSkippedFrames >= maxFrameskip) {
			skipFrame = false;
		}

		if (skipFrame) {
			gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME;
			numSkippedFrames++;
		} else {
			gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME;
			numSkippedFrames = 0;
		}

		// Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame).
		// Right after, we regain control for a little bit in hleAfterFlip. I think that's a great
		// place to do housekeeping.
		CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0);
		numVBlanksSinceFlip = 0;
	}
}
Example #3
0
void hleEnterVblank(u64 userdata, int cyclesLate) {
	int vbCount = userdata;

	DEBUG_LOG(HLE, "Enter VBlank %i", vbCount);

	isVblank = 1;

	// Fire the vblank listeners before we wake threads.
	__DisplayFireVblank();

	// Wake up threads waiting for VBlank
	for (size_t i = 0; i < vblankWaitingThreads.size(); i++) {
		if (--vblankWaitingThreads[i].vcountUnblock == 0) {
			__KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0);
			vblankWaitingThreads.erase(vblankWaitingThreads.begin() + i--);
		}
	}

	// Trigger VBlank interrupt handlers.
	__TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL);

	CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount + 1);

	// TODO: Should this be done here or in hleLeaveVblank?
	if (framebufIsLatched) {
		DEBUG_LOG(HLE, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr);
		framebuf = latchedFramebuf;
		framebufIsLatched = false;
		gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat);
	}

	gpuStats.numFrames++;

	// Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc.
	if (g_Config.bShowDebugStats && gpuStats.numDrawCalls) {
		DebugStats();
	}

	if (g_Config.bShowFPSCounter) {
		char stats[50];

		sprintf(stats, "%0.1f", calculateFPS());

		#ifdef USING_GLES2
			float zoom = 0.7f; /// g_Config.iWindowZoom;
			float soff = 0.7f;
		#else
			float zoom = 0.5f; /// g_Config.iWindowZoom;
			float soff = 0.5f;
		#endif
		PPGeBegin();
		PPGeDrawText(stats, 476 + soff, 4 + soff, PPGE_ALIGN_RIGHT, zoom, 0xCC000000);
		PPGeDrawText(stats, 476 + -soff, 4 -soff, PPGE_ALIGN_RIGHT, zoom, 0xCC000000);
		PPGeDrawText(stats, 476, 4, PPGE_ALIGN_RIGHT, zoom, 0xFF30FF30);
		PPGeEnd();
	}

	// Draw screen overlays before blitting. Saves and restores the Ge context.
	// Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity
	// to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have
	// anything to draw here.
	gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME;

	bool throttle, skipFrame, skipFlip;
	
	DoFrameTiming(throttle, skipFrame, skipFlip);

	// Setting CORE_NEXTFRAME causes a swap.
	if (skipFrame) {
		gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME;
		numSkippedFrames++;
	} else {
		numSkippedFrames = 0;
	}

	if (!skipFlip) {
		// Might've just quit / been paused.
		if (coreState == CORE_RUNNING) {
			coreState = CORE_NEXTFRAME;
		}
		CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0);

		gpu->CopyDisplayToOutput();
	}

	// Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame).
	// Right after, we regain control for a little bit in hleAfterFlip. I think that's a great
	// place to do housekeeping.
}
Example #4
0
void hleEnterVblank(u64 userdata, int cyclesLate) {
	int vbCount = userdata;

	DEBUG_LOG(HLE, "Enter VBlank %i", vbCount);

	isVblank = 1;
	vCount++; // // vCount increases at each VBLANK.

	// Fire the vblank listeners before we wake threads.
	__DisplayFireVblank();

	// Wake up threads waiting for VBlank
	for (size_t i = 0; i < vblankWaitingThreads.size(); i++) {
		if (--vblankWaitingThreads[i].vcountUnblock == 0) {
			__KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0);
			vblankWaitingThreads.erase(vblankWaitingThreads.begin() + i--);
		}
	}

	// Trigger VBlank interrupt handlers.
	__TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL);

	CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount + 1);

	// TODO: Should this be done here or in hleLeaveVblank?
	if (framebufIsLatched) {
		DEBUG_LOG(HLE, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr);
		framebuf = latchedFramebuf;
		framebufIsLatched = false;
		gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat);
	}

	gpuStats.numVBlanks++;

	numVBlanksSinceFlip++;

	if (g_Config.iShowFPSCounter) {
		CalculateFPS();
	}

	// We flip only if the framebuffer was dirty. This eliminates flicker when using
	// non-buffered rendering. The interaction with frame skipping seems to need
	// some work.
	if (gpu->FramebufferDirty()) {
		gpuStats.numFlips++;

		bool wasSkipped = (gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) != 0;
		gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME;

		bool throttle, skipFrame;
		DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * (1.0f / 60.0f));

		if (skipFrame) {
			gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME;
			numSkippedFrames++;
		} else {
			numSkippedFrames = 0;
		}

		// Setting CORE_NEXTFRAME causes a swap.
		// Check first though, might've just quit / been paused.
		if (!wasSkipped) {
			if (coreState == CORE_RUNNING) {
				coreState = CORE_NEXTFRAME;
				gpu->CopyDisplayToOutput();
			}
		}

		// Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame).
		// Right after, we regain control for a little bit in hleAfterFlip. I think that's a great
		// place to do housekeeping.
		CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0);
		numVBlanksSinceFlip = 0;
	}
}