Exemple #1
0
static bool compositor_active(MPGLContext *ctx)
{
    // For Windows 7.
    BOOL enabled = 0;
    if (FAILED(DwmIsCompositionEnabled(&enabled)) || !enabled)
        return false;

    // This works at least on Windows 8.1: it returns an error in fullscreen,
    // which is also when we get consistent timings without DwmFlush. Might
    // be cargo-cult.
    DWM_TIMING_INFO info = { .cbSize = sizeof(DWM_TIMING_INFO) };
    if (FAILED(DwmGetCompositionTimingInfo(0, &info)))
        return false;

    // Test if a program is running in exclusive fullscreen mode. If so, it's
    // probably this one, so it's not getting redirected by the compositor.
    if (mp_w32_is_in_exclusive_mode())
        return false;

    return true;
}

static void w32_swap_buffers(MPGLContext *ctx)
{
    struct w32_context *w32_ctx = ctx->priv;
    SwapBuffers(w32_ctx->hdc);

    // default if we don't DwmFLush
    int new_swapinterval = w32_ctx->opt_swapinterval;

    if (ctx->dwm_flush_opt >= 0) {
        if ((ctx->dwm_flush_opt == 1 && !ctx->vo->opts->fullscreen) ||
            (ctx->dwm_flush_opt == 2) ||
            (ctx->dwm_flush_opt == 0 && compositor_active(ctx)))
        {
            if (DwmFlush() == S_OK)
                new_swapinterval = 0;
        }
    }

    if (new_swapinterval != w32_ctx->current_swapinterval &&
        w32_ctx->real_wglSwapInterval)
    {
        w32_ctx->real_wglSwapInterval(new_swapinterval);
        MP_VERBOSE(ctx->vo, "set SwapInterval(%d)\n", new_swapinterval);
    }
    w32_ctx->current_swapinterval = new_swapinterval;
}

static int w32_control(MPGLContext *ctx, int *events, int request, void *arg)
{
    return vo_w32_control(ctx->vo, events, request, arg);
}

const struct mpgl_driver mpgl_driver_w32 = {
    .name           = "w32",
    .priv_size      = sizeof(struct w32_context),
    .init           = w32_init,
    .reconfig       = w32_reconfig,
    .swap_buffers   = w32_swap_buffers,
    .control        = w32_control,
    .uninit         = w32_uninit,
};
HRESULT DemoApp::Initialize()
{
    HRESULT hr;

    //register window class
    WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
    wcex.style         = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc   = DemoApp::WndProc;
    wcex.cbClsExtra    = 0;
    wcex.cbWndExtra    = sizeof(LONG_PTR);
    wcex.hInstance     = HINST_THISCOMPONENT;
    wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = NULL;
    wcex.lpszMenuName  = NULL;
    wcex.lpszClassName = L"D2DDemoApp";

    RegisterClassEx(&wcex);

    hr = CreateDeviceIndependentResources();
    if (SUCCEEDED(hr))
    {
        // Create the application window.
        //
        // Because the CreateWindow function takes its size in pixels, we
        // obtain the system DPI and use it to scale the window size.
        FLOAT dpiX, dpiY;
        m_pD2DFactory->GetDesktopDpi(&dpiX, &dpiY);

        m_hwnd = CreateWindow(
            L"D2DDemoApp",
            L"D2D Simple Path Animation Sample",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            static_cast<UINT>(ceil(512.f * dpiX / 96.f)),
            static_cast<UINT>(ceil(512.f * dpiY / 96.f)),
            NULL,
            NULL,
            HINST_THISCOMPONENT,
            this
            );
        hr = m_hwnd ? S_OK : E_FAIL;
        if (SUCCEEDED(hr))
        {
            float length = 0;

            hr = m_pPathGeometry->ComputeLength(
                NULL, //no transform
                &length
                );
            if (SUCCEEDED(hr))
            {
                m_Animation.SetStart(0);        //start at beginning of path
                m_Animation.SetEnd(length);     //length at end of path
                m_Animation.SetDuration(5.0f);  //seconds

                ZeroMemory(&m_DwmTimingInfo, sizeof(m_DwmTimingInfo));
                m_DwmTimingInfo.cbSize = sizeof(m_DwmTimingInfo);

                // Get the composition refresh rate. If the DWM isn't running,
                // get the refresh rate from GDI -- probably going to be 60Hz
                if (FAILED(DwmGetCompositionTimingInfo(NULL, &m_DwmTimingInfo)))
                {
                    HDC hdc = GetDC(m_hwnd);
                    m_DwmTimingInfo.rateCompose.uiDenominator = 1;
                    m_DwmTimingInfo.rateCompose.uiNumerator = GetDeviceCaps(hdc, VREFRESH);
                    ReleaseDC(m_hwnd, hdc);
                }

                ShowWindow(m_hwnd, SW_SHOWNORMAL);

                UpdateWindow(m_hwnd);
            }
        }
    }

    return hr;
}
Exemple #3
0
HRESULT DemoApp::Initialize()
{
    HRESULT hr;

    //register window class
    WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
    wcex.style         = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc   = DemoApp::WndProc;
    wcex.cbClsExtra    = 0;
    wcex.cbWndExtra    = sizeof(LONG_PTR);
    wcex.hInstance     = HINST_THISCOMPONENT;
    wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = NULL;
    wcex.lpszMenuName  = NULL;
    wcex.lpszClassName = L"App";

    RegisterClassEx(&wcex);

    hr = CreateDeviceIndependentResources();
    if (SUCCEEDED(hr))
    {
        // Create the application window.
        m_hwnd = CreateWindow(
            L"App",
            L"달걀 채색 공장(201001622 이진용)",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            1200,
			600,
            NULL,
            NULL,
            HINST_THISCOMPONENT,
            this
            );
        hr = m_hwnd ? S_OK : E_FAIL;

        if (SUCCEEDED(hr))
        {
            float length = 0;
            hr = m_wheelPath->ComputeLength(
                NULL, //no transform
                &length
                );

            if (SUCCEEDED(hr) )
            {
                m_Animation.SetStart(0);        //start at beginning of path
                m_Animation.SetEnd(length);     //length at end of path
                m_Animation.SetDuration(5.f );  //seconds

                ZeroMemory(&m_DwmTimingInfo, sizeof(m_DwmTimingInfo));
                m_DwmTimingInfo.cbSize = sizeof(m_DwmTimingInfo);

                // Get the composition refresh rate. If the DWM isn't running,
                // get the refresh rate from GDI -- probably going to be 60Hz
                if (FAILED(DwmGetCompositionTimingInfo(NULL, &m_DwmTimingInfo)))
                {
                    HDC hdc = GetDC(m_hwnd);
                    m_DwmTimingInfo.rateCompose.uiDenominator = 1;
                    m_DwmTimingInfo.rateCompose.uiNumerator = GetDeviceCaps(hdc, VREFRESH);
                    ReleaseDC(m_hwnd, hdc);
                }

                ShowWindow(m_hwnd, SW_SHOWNORMAL);

                UpdateWindow(m_hwnd);
            }
        }



		if (SUCCEEDED(hr))
        {
            float pLength = 0;
			hr = m_flyPath->ComputeLength(
                NULL, //no transform
                &pLength
                );

            if (SUCCEEDED(hr) )
            {
                m_linearAnimation.SetStart(0);        //start at beginning of path
                m_linearAnimation.SetEnd(pLength);     //length at end of path
                m_linearAnimation.SetDuration(10.f);  //seconds

                ZeroMemory(&m_DwmTimingInfo, sizeof(m_DwmTimingInfo));
                m_DwmTimingInfo.cbSize = sizeof(m_DwmTimingInfo);

                // Get the composition refresh rate. If the DWM isn't running,
                // get the refresh rate from GDI -- probably going to be 60Hz
                if (FAILED(DwmGetCompositionTimingInfo(NULL, &m_DwmTimingInfo)))
                {
                    HDC hdc = GetDC(m_hwnd);
                    m_DwmTimingInfo.rateCompose.uiDenominator = 1;
                    m_DwmTimingInfo.rateCompose.uiNumerator = GetDeviceCaps(hdc, VREFRESH);
                    ReleaseDC(m_hwnd, hdc);
                }

                ShowWindow(m_hwnd, SW_SHOWNORMAL);

                UpdateWindow(m_hwnd);
            }
        }
    }

	
	//장치 객체 생성
	IDirectSound8* directSound;
	DirectSoundCreate8(NULL,&directSound, NULL);

	
	//협력레벨 지정
	directSound->SetCooperativeLevel(m_hwnd,DSSCL_PRIORITY);

	//주버퍼 포맷 지정
	DSBUFFERDESC dsbd;
	ZeroMemory(&dsbd,sizeof(DSBUFFERDESC) );
	dsbd.dwSize = sizeof(DSBUFFERDESC);
	dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
	dsbd.dwBufferBytes = 0;
	dsbd.lpwfxFormat = NULL;
	

	//IDirectSoundBuffer* pDSBPrimary = NULL;
	directSound->CreateSoundBuffer(&dsbd, &pDSBPrimary, NULL);
	
	WAVEFORMATEX wfx;
	ZeroMemory(&wfx, sizeof(WAVEFORMATEX) );
	wfx.wFormatTag = (WORD)WAVE_FORMAT_PCM;
	wfx.nChannels =(WORD)2;
	wfx.nSamplesPerSec = (DWORD)22050;
	wfx.wBitsPerSample = (WORD)16;
	wfx.nBlockAlign = (WORD)(wfx.wBitsPerSample / 8 * wfx.nChannels );
	wfx.nAvgBytesPerSec = (DWORD)(wfx.nSamplesPerSec * wfx.nBlockAlign );

	pDSBPrimary->SetFormat(&wfx);

	pDSBPrimary->Release();

	//2차 버퍼 생성  BGM
	CWaveFile* pWaveFile = NULL;
	pWaveFile = new CWaveFile();
	pWaveFile->Open( L".\\pokemonCenter.wav", NULL, WAVEFILE_READ );
	
	
	//DSBUFFERDESC dsbd;
	ZeroMemory(&dsbd, sizeof(DSBUFFERDESC) );
	dsbd.dwSize = sizeof(DSBUFFERDESC);
	dsbd.dwFlags = DSBCAPS_CTRLVOLUME;
	dsbd.guid3DAlgorithm = GUID_NULL;
	dsbd.lpwfxFormat = pWaveFile->m_pwfx;
	dsbd.dwBufferBytes = pWaveFile->GetSize();
	

	
	directSound->CreateSoundBuffer(&dsbd, &pDSBuffer, NULL);



	//이차버퍼에 데이터 채우기
	sound = new CSound(&pDSBuffer, dsbd.dwBufferBytes, 1 , pWaveFile, 0 );  // pDSBuffer 위에 전역변수임


	pDSBPrimary->SetVolume(scaledVolume);

	sound->Play(0,DSBPLAY_LOOPING);
	


	soundManager = new CSoundManager;
	if( ! soundManager->init(m_hwnd) )
		return FALSE;

	int id;
	if (! soundManager->add(L".\\boss.wav", &id)) //id=0부터 시작함.
		return FALSE;
	if (! soundManager->add(L".\\storm.wav",&id));




    return hr;
}
/** Blocks the CPU to synchronize with vblank by communicating with DWM. */
void FD3D11Viewport::PresentWithVsyncDWM()
{
#if D3D11_WITH_DWMAPI
	LARGE_INTEGER Cycles;
	DWM_TIMING_INFO TimingInfo;

	// Find out how long since we last flipped and query DWM for timing information.
	QueryPerformanceCounter(&Cycles);
	FMemory::MemZero(TimingInfo);
	TimingInfo.cbSize = sizeof(DWM_TIMING_INFO);
	DwmGetCompositionTimingInfo(WindowHandle, &TimingInfo);

	uint64 QpcAtFlip = Cycles.QuadPart;
	uint64 CyclesSinceLastFlip = Cycles.QuadPart - LastFlipTime;
	float CPUTime = FPlatformTime::ToMilliseconds(CyclesSinceLastFlip);
	float GPUTime = FPlatformTime::ToMilliseconds(TimingInfo.qpcFrameComplete - LastCompleteTime);
	float DisplayRefreshPeriod = FPlatformTime::ToMilliseconds(TimingInfo.qpcRefreshPeriod);

	// Find the smallest multiple of the refresh rate that is >= 33ms, our target frame rate.
	float RefreshPeriod = DisplayRefreshPeriod;
	if (RHIConsoleVariables::bForceThirtyHz && RefreshPeriod > 1.0f)
	{
		while (RefreshPeriod - (1000.0f / 30.0f) < -1.0f)
		{
			RefreshPeriod *= 2.0f;
		}
	}

	// If the last frame hasn't completed yet, we don't know how long the GPU took.
	bool bValidGPUTime = (TimingInfo.cFrameComplete > LastFrameComplete);
	if (bValidGPUTime)
	{
		GPUTime /= (float)(TimingInfo.cFrameComplete - LastFrameComplete);
	}

	// Update the sync counter depending on how much time it took to complete the previous frame.
	float FrameTime = FMath::Max<float>(CPUTime, GPUTime);
	if (FrameTime >= RHIConsoleVariables::SyncRefreshThreshold * RefreshPeriod)
	{
		SyncCounter--;
	}
	else if (bValidGPUTime)
	{
		SyncCounter++;
	}
	SyncCounter = FMath::Clamp<int32>(SyncCounter, 0, RHIConsoleVariables::MaxSyncCounter);

	// If frames are being completed quickly enough, block for vsync.
	bool bSync = (SyncCounter >= RHIConsoleVariables::SyncThreshold);
	if (bSync)
	{
		// This flushes the previous present call and blocks until it is made available to DWM.
		D3DRHI->GetDeviceContext()->Flush();
		DwmFlush();

		// We sleep a percentage of the remaining time. The trick is to get the
		// present call in after the vblank we just synced for but with time to
		// spare for the next vblank.
		float MinFrameTime = RefreshPeriod * RHIConsoleVariables::RefreshPercentageBeforePresent;
		float TimeToSleep;
		do 
		{
			QueryPerformanceCounter(&Cycles);
			float TimeSinceFlip = FPlatformTime::ToMilliseconds(Cycles.QuadPart - LastFlipTime);
			TimeToSleep = (MinFrameTime - TimeSinceFlip);
			if (TimeToSleep > 0.0f)
			{
				FPlatformProcess::Sleep(TimeToSleep * 0.001f);
			}
		}
		while (TimeToSleep > 0.0f);
	}

	// Present.
	PresentChecked(/*SyncInterval=*/ 0);

	// If we are forcing <= 30Hz, block the CPU an additional amount of time if needed.
	// This second block is only needed when RefreshPercentageBeforePresent < 1.0.
	if (bSync)
	{
		LARGE_INTEGER LocalCycles;
		float TimeToSleep;
		bool bSaveCycles = false;
		do 
		{
			QueryPerformanceCounter(&LocalCycles);
			float TimeSinceFlip = FPlatformTime::ToMilliseconds(LocalCycles.QuadPart - LastFlipTime);
			TimeToSleep = (RefreshPeriod - TimeSinceFlip);
			if (TimeToSleep > 0.0f)
			{
				bSaveCycles = true;
				FPlatformProcess::Sleep(TimeToSleep * 0.001f);
			}
		}
		while (TimeToSleep > 0.0f);

		if (bSaveCycles)
		{
			Cycles = LocalCycles;
		}
	}

	// If we are dropping vsync reset the counter. This provides a debounce time
	// before which we try to vsync again.
	if (!bSync && bSyncedLastFrame)
	{
		SyncCounter = 0;
	}

	if (bSync != bSyncedLastFrame || UE_LOG_ACTIVE(LogRHI,VeryVerbose))
	{
		UE_LOG(LogRHI,Verbose,TEXT("BlockForVsync[%d]: CPUTime:%.2fms GPUTime[%d]:%.2fms Blocked:%.2fms Pending/Complete:%d/%d"),
			bSync,
			CPUTime,
			bValidGPUTime,
			GPUTime,
			FPlatformTime::ToMilliseconds(Cycles.QuadPart - QpcAtFlip),
			TimingInfo.cFramePending,
			TimingInfo.cFrameComplete);
	}

	// Remember if we synced, when the frame completed, etc.
	bSyncedLastFrame = bSync;
	LastFlipTime = Cycles.QuadPart;
	LastFrameComplete = TimingInfo.cFrameComplete;
	LastCompleteTime = TimingInfo.qpcFrameComplete;
#endif	//D3D11_WITH_DWMAPI
}
void  VSyncWin::VSyncLoop()
{
	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

	DWM_TIMING_INFO vblankTime;
	// Make sure to init the cbSize, otherwise GetCompositionTiming will fail
	vblankTime.cbSize = sizeof(DWM_TIMING_INFO);

	LARGE_INTEGER frequency;
	QueryPerformanceFrequency(&frequency);
	TimeStamp vsync = Now();
	// On Windows 10, DwmGetCompositionInfo returns the upcoming vsync.
	// See GetAdjustedVsyncTimestamp.
	// On start, set mPrevVsync to the "next" vsync
	// So we'll use this timestamp on the 2nd loop iteration.
	mPrevVsync = vsync + mSoftwareVsyncRate;

	for (;;) {

#if !USING_DWM_FLUSH
		TimeStamp here = Now();

		::QueryPerformanceCounter(&gSS);
		//Sleep(1);
		//Sleep(200);

		
		m_pOutput->WaitForVBlank();

		
		//Sleep(1);
		
		m_pSwapChain->Present(0, 0);
		//DwmFlush();

		//Gdi: NtGdiDdDDIWaitForVerticalBlankEvent()
		//TimerBlit();
		//gS = gSS;
		//::PostMessageA(gHwnd, WM_BLIT_REQUEST, 0, 0);
		//TimerBlit();
		FILE *f;
		fopen_s(&f, "C:\\VSyncThread", "rb");
		//char buf[200];
		LARGE_INTEGER fi;
		char buf[200];
		::QueryPerformanceFrequency(&fi);
		sprintf_s(buf, "\n+++++ %d", int((Now() - here) * 1000000 / fi.QuadPart));
		OutputDebugStringA(buf);
#else
		::QueryPerformanceCounter(&gS);

		gTS = vsync;


		/*mWork = CreateThreadpoolWork(BlittingThread,
		(void*)&gTS,
		&mCallBackEnviron);

		SubmitThreadpoolWork(mWork);*/

		//mVSyncTimeStamp.store(vsync);
		
		char buf[1000];
		LARGE_INTEGER fi;
		//::QueryPerformanceFrequency(&fi);
		//sprintf_s(buf, "\n+++++%d", int((vsync - here) * 1000000 / fi.QuadPart));
		//OutputDebugStringA(buf);

		// Use a combination of DwmFlush + DwmGetCompositionTimingInfoPtr
		// Using WaitForVBlank, the whole system dies :/
		//m_pSwapChain->Present(0, 0);
		//::PostMessageA(gHwnd, WM_BLIT_REQUEST, 0, 0);
		//m_pSwapChain->Present(1, 0);
		//TimerBlit();
		
		HRESULT hr;
		
		hr = DwmFlush();//WinUtils::dwmFlushProcPtr();
		if (!SUCCEEDED(hr)) {
		//	// We don't actually know how long we had to wait on DWMFlush
		//	// Instead of trying to calculate how long DwmFlush actually took
		//	// Fallback to software vsync.
		//	//-->ScheduleSoftwareVsync(Now());

			return;
		}

		//dwmflush does not exactly return at next vblank 
		//TimerBlit();

		hr = DwmGetCompositionTimingInfo(0, &vblankTime);


		/*vsync = SUCCEEDED(hr) ?
		GetAdjustedVsyncTimeStamp(frequency, vblankTime.qpcVBlank) :
		Now();*/
		vsync = vblankTime.qpcVBlank;// +vblankTime.qpcRefreshPeriod;
		mVSyncTimeStamp.store(vsync);
		mBlit = true;
		////char buf[200];
		//LARGE_INTEGER l;
		//

		//QueryPerformanceFrequency(&l);
		////if (((vsync - Now()) * 1000000 / l.QuadPart) > 10000)
		//	//continue;
		///*LARGE_INTEGER le, lf;
		//QueryPerformanceCounter(&le);
		//QueryPerformanceFrequency(&lf);*/
		//sprintf_s(buf, "\nvblank Time  Now =  %u", (vsync - Now()) * 1000000 / l.QuadPart);
		//OutputDebugStringA(buf);
		//sprintf_s(buf, "\n****** ---- %llu --", vsync);
		//OutputDebugStringA(buf);
		/*sprintf_s(buf, "\nv Timed %d ", ((le.QuadPart - gS.QuadPart) * 1000000 / lf.QuadPart));
		OutputDebugStringA(buf);*/
#endif
	} // end for

}