VOID CMiniportWaveRTStream::UpdatePosition ( _In_ LARGE_INTEGER ilQPC ) { // Convert ticks to 100ns units. LONGLONG hnsCurrentTime = KSCONVERT_PERFORMANCE_TIME(m_ullPerformanceCounterFrequency.QuadPart, ilQPC); // Calculate the time elapsed since the last call to GetPosition() or since the // DMA engine started. Note that the division by 10000 to convert to milliseconds // may cause us to lose some of the time, so we will carry the remainder forward // to the next GetPosition() call. // ULONG TimeElapsedInMS = (ULONG)(hnsCurrentTime - m_ullDmaTimeStamp + m_hnsElapsedTimeCarryForward)/10000; // Carry forward the remainder of this division so we don't fall behind with our position too much. // m_hnsElapsedTimeCarryForward = (hnsCurrentTime - m_ullDmaTimeStamp + m_hnsElapsedTimeCarryForward) % 10000; // Calculate how many bytes in the DMA buffer would have been processed in the elapsed // time. Note that the division by 1000 to convert to milliseconds may cause us to // lose some bytes, so we will carry the remainder forward to the next GetPosition() call. // // need to divide by 1000 because m_ulDmaMovementRate is average bytes per sec. ULONG ByteDisplacement = (m_ulDmaMovementRate * TimeElapsedInMS) / 1000; if (m_bCapture) { // Write sine wave to buffer. ByteDisplacement %= m_ulDmaBufferSize; // just for not crashing when debugging the driver. WriteBytes(ByteDisplacement); } else if (!g_DoNotCreateDataFiles) { // // Read from buffer and write to a file. // ByteDisplacement %= m_ulDmaBufferSize; // just for not crashing when debugging the driver. ReadBytes(ByteDisplacement); } // Increment the DMA position by the number of bytes displaced since the last // call to GetPosition() and ensure we properly wrap at buffer length. // m_ullPlayPosition = m_ullWritePosition = (m_ullWritePosition + ByteDisplacement) % m_ulDmaBufferSize; // m_ullDmaTimeStamp is updated in both GetPostion and GetLinearPosition calls // so m_ullLinearPosition needs to be updated accordingly here // m_ullLinearPosition += ByteDisplacement; // Update the DMA time stamp for the next call to GetPosition() // m_ullDmaTimeStamp = hnsCurrentTime; }
HRESULT STDMETHODCALLTYPE IDirect3DDevice9_EndScene_Hook(IDirect3DDevice9* This) { static unsigned count = 0; auto ticks = []() { LARGE_INTEGER value; QueryPerformanceCounter(&value); return KSCONVERT_PERFORMANCE_TIME(frequency, value); }(); static auto start = [This, &ticks]() { IDirect3DSurface9* renderTarget; IDirect3DDevice9_GetRenderTarget(This, 0, &renderTarget); IDirect3DSurface9_GetDesc(renderTarget, &desc); IDirect3DSurface9_Release(renderTarget); // quick hack, first 'ticks - start' is 1. return ticks++; }(); fps = static_cast<unsigned>(static_cast<ULONGLONG>(++count) * NANOSECONDS / (ticks - start)); FramePtr frame = Frame; if (frame) { IDirect3DSurface9* offsecreen; check(TEXT("CreateOffscreenPlainSurface"), IDirect3DDevice9_CreateOffscreenPlainSurface(This, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &offsecreen, nullptr)); { IDirect3DSurface9* target; check(TEXT("GetRenderTarget"), IDirect3DDevice9_GetRenderTarget(This, 0, &target)); #if 0 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) { IDirect3DSurface9* resolved; check(TEXT("CreateRenderTarget"), IDirect3DDevice9_CreateRenderTarget(This, desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, false, &resolved, nullptr)); check(TEXT("StretchRect"), IDirect3DDevice9_StretchRect(This, target, nullptr, resolved, nullptr, D3DTEXF_NONE)); IDirect3DSurface9_Release(target); target = resolved; } #endif check(TEXT("GetRenderTargetData"), IDirect3DDevice9_GetRenderTargetData(This, target, offsecreen)); IDirect3DSurface9_Release(target); } frame(ticks, offsecreen); IDirect3DSurface9_Release(offsecreen); } return IDirect3DDevice9_EndScene_Orig(This); }
ULONGLONG CHardwareSimulation:: ConvertQPCtoTimeStamp( _In_opt_ PLARGE_INTEGER pQpcTime ) /*++ Routine Description: Get the QPC measured in 100ns units. Arguments: pQpcTime - An optional time value to convert. If NULL, use the current QPC. Return Value: ULONLONG - The time in 100ns increments. --*/ { PAGED_CODE(); LARGE_INTEGER qpcTime = {0}; LARGE_INTEGER qpcFrequency; qpcTime = KeQueryPerformanceCounter(&qpcFrequency); if( pQpcTime ) { qpcTime = *pQpcTime; } return KSCONVERT_PERFORMANCE_TIME( qpcFrequency.QuadPart, qpcTime ); }
NTSTATUS CMiniportWaveRTStream::SetState ( _In_ KSSTATE State_ ) { PAGED_CODE(); NTSTATUS ntStatus = STATUS_SUCCESS; PADAPTERCOMMON pAdapterComm = m_pMiniport->GetAdapterCommObj(); // Spew an event for a pin state change request from portcls //Event type: eMINIPORT_PIN_STATE //Parameter 1: Current linear buffer position //Parameter 2: Current WaveRtBufferWritePosition //Parameter 3: Pin State 0->KS_STOP, 1->KS_ACQUIRE, 2->KS_PAUSE, 3->KS_RUN //Parameter 4:0 pAdapterComm->WriteEtwEvent(eMINIPORT_PIN_STATE, 100, // replace with the correct "Current linear buffer position" m_ulCurrentWritePosition, // replace with the previous WaveRtBufferWritePosition that the drive received State_, // repalce with the correct "Data length completed" 0); // always zero switch (State_) { case KSSTATE_STOP: // Reset DMA m_ullPlayPosition = 0; m_ullWritePosition = 0; m_ullLinearPosition = 0; // Wait until all work items are completed. if (!m_bCapture && !g_DoNotCreateDataFiles) { m_SaveData.WaitAllWorkItems(); } #ifdef SYSVAD_BTH_BYPASS if (m_ScoOpen) { PBTHHFPDEVICECOMMON bthHfpDevice; ASSERT(m_pMiniport->IsBthHfpDevice()); bthHfpDevice = m_pMiniport->GetBthHfpDevice(); // weak ref. ASSERT(bthHfpDevice != NULL); // // Close the SCO connection. // ntStatus = bthHfpDevice->StreamClose(); if (!NT_SUCCESS(ntStatus)) { DPF(D_ERROR, ("SetState: KSSTATE_STOP, StreamClose failed, 0x%x", ntStatus)); } m_ScoOpen = FALSE; } #endif // SYSVAD_BTH_BYPASS break; case KSSTATE_ACQUIRE: #ifdef SYSVAD_BTH_BYPASS if (m_pMiniport->IsBthHfpDevice()) { if(m_ScoOpen == FALSE) { PBTHHFPDEVICECOMMON bthHfpDevice; bthHfpDevice = m_pMiniport->GetBthHfpDevice(); // weak ref. ASSERT(bthHfpDevice != NULL); // // Open the SCO connection. // ntStatus = bthHfpDevice->StreamOpen(); IF_FAILED_ACTION_JUMP( ntStatus, DPF(D_ERROR, ("SetState: KSSTATE_ACQUIRE, StreamOpen failed, 0x%x", ntStatus)), Done); m_ScoOpen = TRUE; } } #endif // SYSVAD_BTH_BYPASS break; case KSSTATE_PAUSE: ULONGLONG ullPositionTemp; // Pause DMA if (m_ulNotificationIntervalMs > 0) { KeCancelTimer(m_pNotificationTimer); KeFlushQueuedDpcs(); } // This call updates the linear buffer position. GetLinearBufferPosition(&ullPositionTemp, NULL); break; case KSSTATE_RUN: // Start DMA LARGE_INTEGER ullPerfCounterTemp; ullPerfCounterTemp = KeQueryPerformanceCounter(&m_ullPerformanceCounterFrequency); m_ullDmaTimeStamp = KSCONVERT_PERFORMANCE_TIME(m_ullPerformanceCounterFrequency.QuadPart, ullPerfCounterTemp); m_hnsElapsedTimeCarryForward = 0; if (m_ulNotificationIntervalMs > 0) { LARGE_INTEGER delay; delay.HighPart = 0; delay.LowPart = m_ulNotificationIntervalMs * HNSTIME_PER_MILLISECOND * -1; KeSetTimerEx ( m_pNotificationTimer, delay, m_ulNotificationIntervalMs, m_pNotificationDpc ); } break; } m_KsState = State_; #ifdef SYSVAD_BTH_BYPASS Done: #endif // SYSVAD_BTH_BYPASS return ntStatus; }