winsurf2.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:134k
- pItem->rcDst.right = rcSize.cx;
- pItem->rcDst.bottom = rcSize.cy;
- }
- SetLastScale(&pItem->rcSrc, &pItem->rcDst);
- double dScaleX = m_scaleFactorX,
- dScaleY = m_scaleFactorY;
- // Setup new src and dest rects....
- _ConstructRects( pItem->rcSrc,
- pItem->rcDst,
- FALSE,
- nNumRects,
- &m_paSrcRects,
- &m_paDestRects);
- if (nNumRects != 1)
- {
- HXxPoint screenOffset = m_pSite->GetScreenOffset();
- if (!m_paSrcRects)
- m_paSrcRects = (HXxRect*)malloc(sizeof(HXxRect));
- if (!m_paDestRects)
- m_paDestRects = (HXxRect*)malloc(sizeof(HXxRect));;
- m_paSrcRects[0] = pItem->rcSrc;
- m_paDestRects[0] = pItem->rcDst;
- m_paSrcRects[0].left += screenOffset.x;
- m_paSrcRects[0].top += screenOffset.y;
- m_paSrcRects[0].right += screenOffset.x;
- m_paSrcRects[0].bottom += screenOffset.y;
- }
- if (m_paSrcRects && m_paDestRects)
- {
- ForceUpdateOverlay(&m_paDestRects[0], &m_paSrcRects[0], HX_OVER_SHOW|HX_OVER_KEYDEST, TRUE);
- }
- if (m_bNeedColorKeyFilled)
- {
- m_bDisableFillColorKey = FALSE;
- _FillColorKey();
- }
- // Alpha blended images are drawn before the video so the scaling gets messed up on
- // static images. Force a redraw to correct the problem.
- if ((dScaleX != m_scaleFactorX || dScaleY != m_scaleFactorY) && m_pSite->IsFullScreen())
- {
- HXxRect dirty = {m_pSite->m_pTopLevelSite->m_topleft.x,
- m_pSite->m_pTopLevelSite->m_topleft.y,
- m_pSite->m_pTopLevelSite->m_topleft.x+m_pSite->m_pTopLevelSite->m_size.cx,
- m_pSite->m_pTopLevelSite->m_topleft.y+m_pSite->m_pTopLevelSite->m_size.cy};
- m_pSite->m_pTopLevelSite->_RecursiveDamageRect(&dirty, TRUE);
- m_pSite->m_pTopLevelSite->_ForceRedrawAll();
- }
- }
- }
- else if (HXR_FAIL == hr)
- {
- // Turn off overlay
- m_bMultipleOverlay = TRUE;
- }
- }
- else if (pItem->nBltMode == HX_BLT_YUV_STRETCH)
- {
- // If no src rect is specified, use surface
- if (!pItem->rcSrc.right && !pItem->rcSrc.bottom)
- {
- pItem->rcSrc.right = m_allocatedFallbackSize.cx;
- pItem->rcSrc.bottom = m_allocatedFallbackSize.cy;
- }
- // If no src rect is specified, use surface
- if (!pItem->rcDst.right && !pItem->rcDst.bottom)
- {
- m_pSite->GetSize(rcSize);
- pItem->rcDst.right = rcSize.cx;
- pItem->rcDst.bottom = rcSize.cy;
- }
- SetLastScale(&pItem->rcSrc, &pItem->rcDst);
- if (bVisibleSite && !m_bFlushing)
- {
- m_nLastBltMode = HX_BLT_YUV_STRETCH;
- // Ok, this is great. We need to add the regions from our
- // yuv alphablending rects to our m_Region so that
- // constructrects will return the correct scaled rects for
- // us to blt. We have to do this here because
- // _ConstructRects doesn't know anything about YUV
- // optimized alphablending. It works in overlay because
- // we have m_pAdditionalColorKey
- //
- HXREGION* pTmp = NULL;
- if( pItem->pAlphaList && m_pSite->m_Region )
- {
- pTmp = HXCreateRegion();
- HXUnionRegion( pTmp, m_pSite->m_Region, pTmp );
- for( int w=0 ; w<pItem->count; w++)
- {
- HXRECTANGLE pRect;
- pRect.x = (short)pItem->pAlphaList[w].rcImageRect.left;
- pRect.y = (short)pItem->pAlphaList[w].rcImageRect.top;
- pRect.width = (short)HXxRECT_WIDTH(pItem->pAlphaList[w].rcImageRect);
- pRect.height = (short)HXxRECT_HEIGHT(pItem->pAlphaList[w].rcImageRect);
- //Add in our offsets from the corner of the
- //toplevel site.
- pRect.x += (short)m_pSite->m_topleft.x;
- pRect.y += (short)m_pSite->m_topleft.y;
- // We must scale this rect to the scale factor of
- // this surface. This really only comes into play
- // if we are shrinking the site to sub 1x and we
- // are still BLTing a YUV surface.
- pRect.x = (int)((double)pRect.x*m_scaleFactorX+.5);
- pRect.y = (int)((double)pRect.y*m_scaleFactorY+.5);
- HXUnionRectWithRegion( &pRect, pTmp, pTmp );
- }
- }
- // Setup new src and dest rects....
- _ConstructRects( pItem->rcSrc,
- pItem->rcDst,
- FALSE,
- nNumRects,
- &m_paSrcRects,
- &m_paDestRects,
- pTmp);
- if( pTmp )
- {
- HXDestroyRegion(pTmp);
- }
- bSub1x = IsShrinking() && !_AllowsOverlayShrinking();
- BOOL bLoseOverlay = FALSE;
- // Lose overlay
- if (HX_OVERLAY_BLT == m_nBltMode && bSub1x)
- {
- bLoseOverlay = TRUE;
- m_bDisableFillColorKey = TRUE;
- }
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- EnterCriticalSection(&m_csFallback);
- // Do an offscreen blt for each display rect
- for( int j=0 ; j<nNumRects ; j++ )
- {
- hr = WinDrawSurface_Blt(pWindraw, &m_fallbackSurface, (RECT*)&m_paDestRects[j], (RECT*)&m_paSrcRects[j]);
- if (hr != DD_OK)
- {
- // Some boards fail on yuv blts, so try a new format on strange errors
- if (DDERR_INVALIDRECT != hr &&
- DDERR_INVALIDPARAMS != hr &&
- DDERR_SURFACEBUSY != hr &&
- DDERR_SURFACELOST != hr)
- {
- if (HXR_OK == TryNewFallback())
- {
- // we created a new surface, discard this frame
- break;
- }
- }
- break;
- }
- }
- LeaveCriticalSection(&m_csFallback);
- if (bLoseOverlay)
- {
- m_bDisableFillColorKey = TRUE;
- ForceUpdateOverlay(&m_paDestRects[0], &m_paSrcRects[0], HX_OVER_HIDE|HX_OVER_KEYDEST);
- ForceGDIMode(TRUE);
- }
- }
- if (pItem->pAlphaList)
- {
- delete [] pItem->pAlphaList;
- }
- SetEvent(m_hFallbackEmpty);
- }
- else
- {
- INT32 nLastGdiSurface = m_nLastGdiSurface;
- // If no src rect is specified, use surface
- if (!pItem->rcSrc.right && !pItem->rcSrc.bottom)
- {
- pItem->rcSrc.right = m_allocatedGdiSize.cx;
- pItem->rcSrc.bottom = m_allocatedGdiSize.cy;
- }
- // If no src rect is specified, use surface
- if (!pItem->rcDst.right && !pItem->rcDst.bottom)
- {
- m_pSite->GetSize(rcSize);
- pItem->rcDst.right = rcSize.cx;
- pItem->rcDst.bottom = rcSize.cy;
- }
- SetLastScale(&pItem->rcSrc, &pItem->rcDst);
- if (bVisibleSite && !m_bFlushing)
- {
- m_nLastBltMode = HX_BASIC_BLT;
- // Setup new src and dest rects....
- _ConstructRects( pItem->rcSrc,
- pItem->rcDst,
- FALSE,
- nNumRects,
- &m_paSrcRects,
- &m_paDestRects);
- // Do a gdi blt for each display rect
- for( int j=0 ; j<nNumRects ; j++ )
- {
- hr = WinDrawSurface_Blt(pWindraw, &m_GDIsurface, (RECT*)&m_paDestRects[j], (RECT*)&m_paSrcRects[j], pItem->nIndex);
- }
- if (HX_OVERLAY_BLT == m_nBltMode)
- {
- m_bDisableFillColorKey = TRUE;
- m_bDisableFillColorKey = TRUE;
- ForceUpdateOverlay(&m_paDestRects[0], &m_paSrcRects[0], HX_OVER_HIDE|HX_OVER_KEYDEST);
- ForceGDIMode(TRUE);
- }
- }
- m_nLastGdiSurface = pItem->nIndex;
- // Release the lock on this surface after we updated it. We keep around the last
- // image for refreshing.
- if (nLastGdiSurface >= 0)
- {
- SetEvent(m_GDIsurface.gdi.lpGDIBackBuffer[nLastGdiSurface]->hEmpty);
- }
- }
- //We are done blt'ing all our rects. Lets notify everyone that
- //might be interested in alpha blending that we changed.
- int nTot = m_pSite->m_AlphaBlendNotifiers.GetCount();
- if( nTot>0 && !m_pSite->IsCompositionMode() && m_bOffBecauseofShinking)
- {
- //XXXgfw Once we have optimized YUV blenders, do even bother
- //calling this as YUV blends from the bottom up and all this
- //has already been done.
- if( m_pSite && m_pSite->m_pTopLevelSite )
- m_pSite->m_pTopLevelSite->ScheduleCallback(REDRAW_ALL, 0);
- }
- m_pSite->_TLSUnlock();
- if (DDERR_WRONGMODE == hr)
- hr = HXR_OK;
- // Update blt stats
- if (HXR_OK == hr && !m_bFlushing)
- {
- UpdateBltStats(&pItem->rcDst);
- }
- return hr;
- }
- DWORD WINAPI CWinSurface2::ThreadProc(CWinSurface2* pThis)
- {
- return pThis->RenThread();
- }
- DWORD CWinSurface2::RenThread()
- {
- BOOL bMeasureJitter = FALSE;
- HRESULT hr;
- tFrameElement *pItem;
- HANDLE aObjects[2] = {m_hFrameSem, m_hAbort},
- aRenderObjects[2] = {m_hForceRender, m_hAbort};
- UINT32 nResolution = SCHEDULE_GRANULE;
- tFrameElement lastItem;
- #ifdef ENABLE_ERROR_TRACE
- g_ulFrameCount = 0;
- g_ulSleepCount = 0;
- #endif // ENABLE_ERROR_TRACE
- // Read some preferences
- IHXPreferences* pPreferences = NULL;
- IHXBuffer* pBuffer = NULL;
- #if !defined(_GOLD) && 0
- CTimeSample sample;
- sample.Init(m_pContext, (void*)this);
- #endif
- if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
- {
- // Use vblank flags for flipping
- if (pPreferences->ReadPref("VideoBoost\MeasureJitter", pBuffer) == HXR_OK)
- bMeasureJitter = ::atoi((char*) pBuffer->GetBuffer());
- HX_RELEASE(pBuffer);
- if (pPreferences->ReadPref("VideoBoost\SchedulerResolution", pBuffer) == HXR_OK)
- nResolution = ::atoi((char*) pBuffer->GetBuffer());
- if (pPreferences->ReadPref("VideoBoost\IgnorePresentIfReady", pBuffer) == HXR_OK)
- m_bIngnorePresentIfReady = ::atoi((char*) pBuffer->GetBuffer());
- HX_RELEASE(pPreferences);
- }
- CWinBaseRootSurface *pSurface = NULL;
- WINDRAW *pWindraw = NULL;
- pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- if (pSurface)
- {
- pWindraw = pSurface->GetWinDraw();
- pWindraw->nSchedulerResolution = nResolution;
- }
- #ifdef HARDCODE_GRANULE
- if (nResolution)
- timeBeginPeriod(nResolution);
- #endif //HARDCODE_GRANULE
- // Make sure timeline is active. If Wait returns and error,
- // an abort message work it up, so check if our thread is
- // supposed to keep running, and if so, wait again.
- while (HXR_OK != WaitForTimeLine(0) && m_bCont && !m_bFlushing)
- continue;
- while (m_bCont)
- {
- m_nLastDisplayTime = -1;
- // Wait for a frame or an abort
- hr = WaitForMultipleObjects(2, aObjects, FALSE, INFINITE);
- if (hr - WAIT_OBJECT_0 == 0 || hr - WAIT_OBJECT_0 == 1)
- {
- if (m_pListOfFrames->GetCount())
- {
- // Grab the first frame off the list
- EnterCriticalSection(&m_csList);
- pItem = (tFrameElement*)m_pListOfFrames->GetHead();
- LeaveCriticalSection(&m_csList);
- EnterCriticalSection(&m_csDisplay);
- TIME_AND_BLT_AGAIN:
- pItem->dwDDFlags = 0;
- pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- HX_ASSERT(pSurface);
- // The root surface may have been destroyed
- if (pSurface)
- {
- pWindraw = pSurface->GetWinDraw();
- if (m_bQueryMonitorFreq)
- {
- HX_ASSERT(pWindraw->dRefreshRate != 0);
- HX_ASSERT(pWindraw->dwReportedHeight);
- }
- // Blocks until display time
- _ScheduleFrameForDisplay(pWindraw, pItem, nResolution);
- // Preserve our frame descriptor
- lastItem = *pItem;
- hr = DisplayFrame(pItem);
- // Check if the root surface was destroyed during the scheduling
- pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- if (pSurface)
- pWindraw = pSurface->GetWinDraw();
- // Need to try again
- if (DDERR_WASSTILLDRAWING == hr)
- {
- // Restore our frame descriptor
- *pItem = lastItem;
- WaitForMultipleObjects(2, aRenderObjects, FALSE, 10);
- goto TIME_AND_BLT_AGAIN;
- }
- // Probably can not async flip, so turn it off
- else if (DDERR_INVALIDPARAMS == hr && m_bUseVBlankFlip)
- {
- // Restore our frame descriptor
- *pItem = lastItem;
- m_bUseVBlankFlip = FALSE;
- goto TIME_AND_BLT_AGAIN;
- }
- else if (DD_OK != hr)
- {
- // Need to discard the overlay
- if (pItem->nBltMode == HX_OVERLAY_BLT && pSurface)
- {
- WinDraw_DisplaySurface(pWindraw, &m_surface, pItem->dwDDFlags, pItem->nIndex, TRUE);
- }
- hr = DD_OK;
- }
- if (m_bQueryMonitorFreq &&
- DD_OK == hr &&
- pSurface)
- {
- m_bQueryMonitorFreq = FALSE;
- WinDraw2_GetMonitorProperties(pWindraw);
- }
- if (HXR_OK == hr)
- {
- // Delete the frame element
- EnterCriticalSection(&m_csList);
- pItem = (tFrameElement*)m_pListOfFrames->RemoveHead();
- LeaveCriticalSection(&m_csList);
- delete pItem;
- pItem = NULL;
- }
- }
- LeaveCriticalSection(&m_csDisplay);
- }
- }
- }
- #ifdef ENABLE_ERROR_TRACE
- // Calculate mean and std. dev:
- double dSum = 0;
- double dAbsSum = 0;
- double dMin = 1000000;
- double dMax = -1000000;
- UINT32 i;
- // Skip first and last ten frames:
- for (i = 10; i < min(g_ulFrameCount - 10, 10000); i++)
- {
- dSum += g_error[i][1];
- dAbsSum += abs(g_error[i][1]);
- if (g_error[i][1] < dMin)
- {
- dMin = g_error[i][1];
- }
- if (g_error[i][1] > dMax)
- {
- dMax = g_error[i][1];
- }
- }
- HX_TRACE("Min:t%fn", dMin);
- HX_TRACE("Max:t%fn", dMax);
- double dMean = dSum / min(g_ulFrameCount - 20, 10000);
- HX_TRACE("Mean:t%fn", dMean);
- HX_TRACE("Abs. Mean:t%fn", dAbsSum / min(g_ulFrameCount - 20, 10000));
- double dStdDev = 0;
- for (i = 10; i < min(g_ulFrameCount - 10, 10000); i++)
- {
- dStdDev += pow(dMean - g_error[i][1], 2);
- }
- dStdDev /= min(g_ulFrameCount -20, 10000) - 1;
- dStdDev = sqrt(dStdDev);
- HX_TRACE("Std. dev:t%fn", dStdDev);
- // Calculate alternate mean and std. dev:
- dSum = 0;
- dMin = 1000000;
- dMax = -1000000;
- for (i = 10; i < min(g_ulFrameCount - 10, 10000); i++)
- {
- dSum += g_alternateError[i];
- if (g_alternateError[i] < dMin)
- {
- dMin = g_alternateError[i];
- }
- if (g_alternateError[i] > dMax)
- {
- dMax = g_alternateError[i];
- }
- }
- HX_TRACE("Alternate min:t%fn", dMin);
- HX_TRACE("Alternate Max:t%fn", dMax);
- dMean = dSum / min(g_ulFrameCount - 20, 10000);
- HX_TRACE("Alternate mean:t%fn", dMean);
- dStdDev = 0;
- for (i = 10; i < min(g_ulFrameCount - 10, 10000); i++)
- {
- dStdDev += pow(dMean - g_alternateError[i], 2);
- }
- dStdDev /= min(g_ulFrameCount - 20, 10000) - 1;
- dStdDev = sqrt(dStdDev);
- HX_TRACE("Alternate std. dev:t%fn", dStdDev);
- DumpErrorEntries();
- #endif // ENABLE_ERROR_TRACE
- #ifdef ENABLE_SYNC_TRACE
- DumpSyncEntries();
- #endif // ENABLE_SYNC_TRACE
- #ifdef HARDCODE_GRANULE
- if (nResolution)
- timeEndPeriod(nResolution);
- #endif //HARDCODE_GRANULE
- return 0;
- }
- BOOL CWinSurface2::GetColorConverter(int cIdIn, int cIdOut)
- {
- //grab the non padded converters...
- BOOL bConverter = zm_pColorAcc->CheckColorConverter(cIdIn, cIdOut);
- m_pSite->ColorConverterRequest(cIdIn, cIdOut, bConverter);
- return bConverter;
- }
- BOOL CWinSurface2::GetColorConverter2(int cIdIn, int cIdOut)
- {
- //grab the padded converters...
- BOOL bConverter = zm_pColorAcc->CheckColorConverter2(cIdIn, cIdOut);
- m_pSite->ColorConverterRequest(cIdIn, cIdOut, bConverter);
- return bConverter;
- }
- int CWinSurface2::ColorConvert(INT32 cidOut, unsigned char *dest_ptr,
- int dest_width, int dest_height,
- int dest_pitch, int dest_x, int dest_y,
- int dest_dx, int dest_dy,
- INT32 cidIn, unsigned char *src_ptr,
- int src_width, int src_height,
- int src_pitch, int src_x, int src_y,
- int src_dx, int src_dy)
- {
- return zm_pColorAcc->ColorConvert(cidOut, dest_ptr,
- dest_width, dest_height,
- dest_pitch, dest_x, dest_y,
- dest_dx, dest_dy,
- cidIn, src_ptr,
- src_width, src_height,
- src_pitch, src_x, src_y,
- src_dx, src_dy);
- }
- int CWinSurface2::ColorConvert2(INT32 cidOut, unsigned char *dest_ptr,
- int dest_width, int dest_height,
- int dest_pitch, int dest_x, int dest_y,
- int dest_dx, int dest_dy,
- INT32 cidIn, unsigned char *pY,
- unsigned char *pU, unsigned char *pV,
- int src_width, int src_height,
- int yPitch, int uPitch, int vPitch,
- int src_x, int src_y, int src_dx, int src_dy)
- {
- return zm_pColorAcc->ColorConvert2(cidOut, dest_ptr,
- dest_width, dest_height,
- dest_pitch, dest_x, dest_y,
- dest_dx, dest_dy,
- cidIn, pY, pU, pV,
- src_width, src_height,
- yPitch, uPitch, vPitch,
- src_x, src_y, src_dx, src_dy);
- }
- HX_RESULT CWinSurface2::RelinquishOverlay()
- {
- // Prevent access to video memory while we tear down our surfaces
- WaitForSingleObject(m_hSurfaceMutex, INFINITE);
- m_bSwitchingingOverlay = TRUE;
- WaitForQueuedFrames();
- HX_RESULT res = CWinSurface::RelinquishOverlay();
- if (res == HXR_OK)
- {
- // Create a fallback and always use it
- if (m_bVideoSurface2)
- {
- CreateFallbackSurface(m_nFallbackSurfaceCID, &m_allocatedFallbackSize);
- m_bMultipleOverlay = TRUE;
- }
- // Force the renderer who lost overlay to redraw to cover the colorkey
- HXxRect dirty = {m_pSite->m_topleft.x,
- m_pSite->m_topleft.y,
- m_pSite->m_topleft.x+m_pSite->m_size.cx,
- m_pSite->m_topleft.y+m_pSite->m_size.cy};
- m_pSite->m_pTopLevelSite->_RecursiveDamageRect(&dirty, TRUE);
- m_pSite->m_pTopLevelSite->ScheduleCallback(REPAINT, 0);
- }
- m_bSwitchingingOverlay = FALSE;
- ReleaseMutex(m_hSurfaceMutex);
- return res;
- }
- HX_RESULT CWinSurface2::AcquireOverlay()
- {
- m_bSwitchingingOverlay = TRUE;
- HX_RESULT res = HXR_FAIL;
- if (m_bVideoSurface2)
- {
- _ReleaseSurface();
- ReInitSurfaces();
- res = HXR_OK;
- }
- else
- res = CWinSurface::AcquireOverlay();
- m_bSwitchingingOverlay = FALSE;
- return res;
- }
- HX_RESULT CWinSurface2::CreateFallbackSurface(int nSurfaceCID, HXxSize* pSize, int *pcidList, int nListSize)
- {
- if (m_bFallbackSurfaceCreated)
- {
- if (pSize->cx == m_allocatedFallbackSize.cx &&
- pSize->cy == m_allocatedFallbackSize.cy)
- {
- return HXR_OK;
- }
- else
- {
- DestroyFallbackSurface();
- }
- }
- //Get our windraw object from the root surface
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- if( !pSurface )
- return HXR_FAIL;
- EnterCriticalSection(&m_csFallback);
- pSurface->OpenWindraw();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- BMI bmi;
- memset(&bmi, 0, sizeof(BMI));
- BOOL bSuccess = FALSE;
- int fFlags = WINDRAWSURFACE_DIRECTDRAW | WINDRAWSURFACE_VIDEOMEMORY;
- int acid[4] = {nSurfaceCID, CID_YV12, CID_YUY2, CID_UYVY};
- int dwId;
- if (!pcidList)
- {
- pcidList = &acid[0];
- nListSize = sizeof(acid)/sizeof(acid[0]);
- }
- // Try video memory, then system memory
- for (int j=0; j<2; j++, fFlags = WINDRAWSURFACE_DIRECTDRAW)
- {
- // If the dd driver can do color space conversion blts, create a yuv surface
- if (pWindraw->dd.m_caps.dwCaps & DDCAPS_BLTFOURCC)
- {
- // Try to create an offscreen yuv surface
- for (int i=0; i<nListSize && IsYUV(pcidList[i]); i++)
- {
- MakeBitmap((LPBITMAPINFO)&bmi, sizeof(BMI), pcidList[i], pSize->cx, pSize->cy, NULL, NULL);
- memset(&m_fallbackSurface, 0, sizeof(m_fallbackSurface));
- if (NOERROR == WinDraw2_CreateSurface(pWindraw, &m_fallbackSurface, &bmi, fFlags, 0, 0))
- {
- // Test if blitting to the primary works (but don't let the user see it)
- RECT rcSrc = {0,0,pSize->cx, pSize->cy};
- RECT rcDst = {-pSize->cx, -pSize->cy, 0, 0};
- if (NOERROR == WinDrawSurface_Blt(pWindraw, &m_fallbackSurface, &rcDst, &rcSrc))
- {
- bSuccess = TRUE;
- dwId = pcidList[i];
- #ifdef _DEBUG
- char szTmp[128]; /* Flawfinder: ignore */
- char cid[6][5] = {{"I420"}, {"YV12"}, {"YVU9"}, {"YUY2"}, {"UYVY"}, {"DVPF"}}; /* Flawfinder: ignore */
- if (dwId == CID_DVPF)
- dwId = 5;
- wsprintf(szTmp, "CreateFallbackSurface Created 1 %s buffersn", cid[dwId]);
- OutputDebugString(szTmp);
- #endif
- break;
- }
- }
- }
- }
- // Try to create an offscreen surface matching the primary format if
- // yuv surface failed.
- if (!bSuccess)
- {
- memset(&bmi, 0, sizeof(BMI));
- WinDraw2_GetDisplayFormat(pWindraw, &bmi);
- int cid = GetBitmapColor((LPBITMAPINFO)&bmi);
- MakeBitmap((LPBITMAPINFO)&bmi, sizeof(BMI), cid, m_pOptimizedFormat->biWidth, m_pOptimizedFormat->biHeight, NULL, NULL);
- // Don't use hardware rgb...it kills performance on some cards
- fFlags = WINDRAWSURFACE_DIRECTDRAW;
- if (NOERROR == WinDraw2_CreateSurface(pWindraw, &m_fallbackSurface, &bmi, fFlags, 0, 0))
- {
- bSuccess = TRUE;
- dwId = cid;
- #ifdef _DEBUG
- OutputDebugString("Created RGB offscreen surfacen");
- #endif
- }
- }
- if (bSuccess)
- {
- m_allocatedFallbackSize.cx = pSize->cx;
- m_allocatedFallbackSize.cy = pSize->cy;
- m_nFallbackSurfaceCID = dwId;
- m_bFallbackSurfaceCreated = TRUE;
- if (!m_nBitsPerPixel ||
- !m_nHozRes ||
- !m_nVertRes)
- {
- // Store the display mode we were created in.
- m_pSite->_GetDeviceCaps(NULL, m_nBitsPerPixel, m_nHozRes, m_nVertRes);
- }
- if (m_hRenThread)
- {
- // We create our surface, start servicing GetVidMem calls
- SetEvent(m_hReinit);
- }
- LeaveCriticalSection(&m_csFallback);
- return HXR_OK;
- }
- }
- #if 1
- LeaveCriticalSection(&m_csFallback);
- return HXR_FAIL;
- #else
- // Result to sys mem buffers
- return CreateSysMemSurface(nSurfaceCID, pSize, 1);
- #endif
- }
- HX_RESULT CWinSurface2::DestroyFallbackSurface()
- {
- if (!m_bFallbackSurfaceCreated)
- return HXR_OK;
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- if (!pSurface)
- return HXR_FAIL;
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- if (!pWindraw)
- return HXR_FAIL;
- EnterCriticalSection(&m_csFallback);
- WinDraw2_ReleaseSurface(pWindraw, &m_fallbackSurface);
- m_bFallbackSurfaceCreated = FALSE;
- LeaveCriticalSection(&m_csFallback);
- return HXR_OK;
- }
- HX_RESULT CWinSurface2::LockFallbackSurface(UCHAR* &pVidMem, INT32 &nPitch, BOOL bBlock)
- {
- if (!bBlock)
- {
- if (WAIT_OBJECT_0 != WaitForSingleObject(m_hFallbackEmpty, 0))
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- HANDLE aObjects[2] = {m_hFallbackEmpty, m_hAbort};
- if (WaitForMultipleObjects(2, aObjects, FALSE, INFINITE) - WAIT_OBJECT_0 == 0)
- {
- HRESULT hr;
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- HXxSize rcSize = {m_surfaceSize.cx,m_surfaceSize.cy};
- if (HXR_OK != CreateFallbackSurface(m_nSurfaceCID, &rcSize))
- return HXR_FAIL;
- LONG lPitch;
- hr = WinDrawSurface_Lock (pWindraw, &m_fallbackSurface, 0, (void**)&pVidMem, &lPitch);
- if (hr != HXR_OK)
- return hr;
- m_bScratchSurface = TRUE;
- nPitch = lPitch;
- }
- else
- return HXR_FAIL;
- return HXR_OK;
- }
- HX_RESULT CWinSurface2::TryNewFallback()
- {
- int nNewCID = 0;
- int acid[5] = {m_nFallbackSurfaceCID, 0,0,0,0};
- for (int i=0; i<5; i++)
- {
- // Try a new format for our offscreen buffer ending in rgb
- switch (acid[i])
- {
- case CID_I420: acid[i+1] = CID_YV12; nNewCID++; break;
- case CID_YV12: acid[i+1] = CID_YUY2; nNewCID++; break;
- case CID_YUY2: acid[i+1] = CID_UYVY; nNewCID++; break;
- case CID_UYVY: acid[i+1] = CID_RGB32; nNewCID++; break;
- default:
- i=5; // jump out of loop
- }
- }
- if (!nNewCID)
- return HXR_FAIL;
- EnterCriticalSection(&m_csFallback);
- DestroyFallbackSurface();
- HRESULT hr = CreateFallbackSurface(acid[1], &m_allocatedFallbackSize, &acid[1], nNewCID);
- LeaveCriticalSection(&m_csFallback);
- return hr;
- }
- HX_RESULT CWinSurface2::CreateSysMemSurface(int nSurfaceCID,
- HXxSize* pSize,
- int nBuffers)
- {
- // Do we need to create new buffers?
- if (m_pSysMemSurf)
- {
- if (nBuffers == m_nSysMemSurfCount &&
- pSize->cx == m_bmi.biWidth &&
- pSize->cy == m_bmi.biHeight)
- {
- return HXR_OK;
- }
- DestroySysMemSurface();
- }
- // Calculate the size of each frame buffer
- m_nSysMemSurfSize = pSize->cx * pSize->cy * GetBitsPerPixel(CID_I420) / 8;
- // Allocate the surface list
- m_pSysMemSurf = new tSysMemSurf[nBuffers];
- if (!m_pSysMemSurf)
- return HXR_OUTOFMEMORY;
- memset(m_pSysMemSurf, 0, sizeof(tSysMemSurf)*nBuffers);
- // Allocate each buffer
- for (int i=0; i<nBuffers; i++)
- {
- m_pSysMemSurf[i].pBuffer = new UCHAR[m_nSysMemSurfSize + 31 & ~31];
- if (!m_pSysMemSurf[i].pBuffer)
- {
- DestroySysMemSurface();
- return HXR_OUTOFMEMORY;
- }
- m_pSysMemSurf[i].hEmpty = CreateEvent(NULL, TRUE, TRUE, NULL);
- ++m_nSysMemSurfCount;
- }
- m_allocatedSysMemSurfSize = *pSize;
- m_nSysMemSurfID = CID_I420;
- m_bUseSysMemSurface = TRUE;
- m_nSysMemSurfPitch = pSize->cx;
- if (!m_nBitsPerPixel ||
- !m_nHozRes ||
- !m_nVertRes)
- {
- // Store the display mode we were created in.
- m_pSite->_GetDeviceCaps(NULL, m_nBitsPerPixel, m_nHozRes, m_nVertRes);
- }
- return HXR_OK;
- }
- HX_RESULT CWinSurface2::LockSysMemSurface(UCHAR* &pVidMem, INT32 &nPitch, BOOL bBlock)
- {
- HXxSize rcSize = {m_bmi.biWidth,m_bmi.biHeight};
- if (HXR_OK != CreateSysMemSurface(m_nSurfaceCID, &rcSize, 1))
- return HXR_FAIL;
- if (!bBlock)
- {
- if (WAIT_OBJECT_0 != WaitForSingleObject(m_pSysMemSurf[m_nNextSysMemBuffer].hEmpty, 0))
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- HANDLE aWait[2] = {m_pSysMemSurf[m_nNextSysMemBuffer].hEmpty, m_hAbort};
- if (WaitForMultipleObjects(2, aWait, FALSE, INFINITE) - WAIT_OBJECT_0 == 0)
- {
- pVidMem = m_pSysMemSurf[m_nNextSysMemBuffer].pBuffer;
- nPitch = m_nSysMemSurfPitch;
- return HXR_OK;
- }
- else
- return HXR_FAIL;
- }
- HX_RESULT CWinSurface2::DestroySysMemSurface()
- {
- if (!m_pSysMemSurf)
- return HXR_OK;
- for (int i=0; i<m_nSysMemSurfCount; i++)
- {
- if (m_pSysMemSurf[i].pBuffer)
- {
- delete [] m_pSysMemSurf[i].pBuffer;
- m_pSysMemSurf[i].pBuffer = NULL;
- }
- if (m_pSysMemSurf[i].hEmpty)
- {
- CloseHandle(m_pSysMemSurf[i].hEmpty);
- m_pSysMemSurf[i].hEmpty = 0;
- }
- }
- delete [] m_pSysMemSurf;
- m_pSysMemSurf = NULL;
- m_nSysMemSurfSize = 0;
- m_nSysMemSurfCount = 0;
- m_nNextSysMemBuffer = 0;
- m_nSysMemSurfPitch = 0;
- m_bUseSysMemSurface = FALSE;
- return HXR_OK;
- }
- INT32 CWinSurface2::GetBitsPerPixel(int nSurfaceID)
- {
- switch (nSurfaceID)
- {
- case CID_YV12:
- case CID_I420:
- return 12;
- case CID_YUY2:
- case CID_UYVY:
- return 16;
- default:
- return 24;
- }
- }
- HX_RESULT CWinSurface2::CreateGdiSurface(HXxSize* pSize)
- {
- HX_RESULT hr = HXR_OK;
- if (m_bGdiSurfaceCreated)
- return hr;
- // Create GDI buffers
- BMI bmi;
- memset(&bmi, 0, sizeof(BMI));
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- WinDraw2_GetDisplayFormat(pWindraw, &bmi);
- int cid = GetBitmapColor((LPBITMAPINFO)&bmi);
- memset(&bmi, 0, sizeof(BMI));
- MakeBitmap((LPBITMAPINFO)&bmi, sizeof(BMI), cid, pSize->cx, pSize->cy, NULL, NULL);
- for (int nBuffers = m_nOverlayBackBuffersCreated; nBuffers; nBuffers--)
- {
- hr = WinDraw2_CreateSurface(pWindraw, &m_GDIsurface, &bmi, 0, nBuffers, 0);
- if (NOERROR == hr)
- {
- m_allocatedGdiSize = *pSize;
- m_nGdiSurfaceCID = cid;
- m_nGdiSurfaceCount = nBuffers+1;
- m_bGdiSurfaceCreated = TRUE;
- m_nLastGdiSurface = -1;
- if (m_hRenThread)
- SetEvent(m_hReinit);
- break;
- }
- }
- return hr;
- }
- HX_RESULT CWinSurface2::LockGdiSurface(UCHAR* &pVidMem, INT32 &nPitch, BOOL bBlock)
- {
- HX_RESULT hr = HXR_FAIL;
- // Create the gdi surface if necessary
- if (!m_bGdiSurfaceCreated)
- {
- HXxSize size = {m_pOptimizedFormat->biWidth,
- m_pOptimizedFormat->biHeight};
- hr = CreateGdiSurface(&size);
- if (HXR_OK != hr)
- return hr;
- }
- // Do we have a surface available
- if (!bBlock)
- {
- if (WAIT_OBJECT_0 != WaitForSingleObject(m_GDIsurface.gdi.lpGDIBackBuffer[m_nNextGdiSurface]->hEmpty, 0))
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- // Wait for the next surface
- HANDLE aWait[2] = {m_GDIsurface.gdi.lpGDIBackBuffer[m_nNextGdiSurface]->hEmpty, m_hAbort};
- if (WaitForMultipleObjects(2, aWait, FALSE, INFINITE) - WAIT_OBJECT_0 == 0)
- {
- LPVOID pTemp = NULL;
- LONG lPitch = 0;
- hr = WinDrawSurface_Lock(pWindraw, &m_GDIsurface, m_nNextGdiSurface, &pTemp, &lPitch);
- if (HXR_OK == hr)
- {
- pVidMem = (UCHAR*)pTemp;
- nPitch = lPitch;
- m_bGDISurface = TRUE;
- }
- }
- return hr;
- }
- HX_RESULT CWinSurface2::DestroyGdiSurface()
- {
- if (m_bGdiSurfaceCreated)
- {
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- if (m_allocatedGdiSize.cx && m_allocatedGdiSize.cy)
- {
- WinDraw2_ReleaseSurface(pWindraw, &m_GDIsurface);
- memset(&m_GDIsurface,0,sizeof(m_GDIsurface));
- memset(&m_allocatedGdiSize,0,sizeof(m_allocatedGdiSize));
- m_nGdiSurfaceCID = 0;
- }
- m_bGdiSurfaceCreated = FALSE;
- m_nLastGdiSurface = -1;
- }
- return HXR_OK;
- }
- void CWinSurface2::SetLastScale(HXxRect *pSrc, HXxRect *pDest)
- {
- EnterCriticalSection(&m_csScale);
- m_dLastXScale = (((double)pDest->right - (double)pDest->left) /
- ((double)pSrc->right - (double)pSrc->left));
- m_dLastYScale = (((double)pDest->bottom - (double)pDest->top) /
- ((double)pSrc->bottom - (double)pSrc->top));
- LeaveCriticalSection(&m_csScale);
- }
- int CWinSurface2::GetBestBltMode()
- {
- // Here is our blt mode prority
- // 1. DD overlay
- // 2. DD offscreen (yuv then rgb)
- // 3. GDI
- BOOL bSub1x = FALSE;
- int nBltMode = HX_OVERLAY_BLT;
- int nPreferredBltMode = nBltMode;
- if (IsShrinking() && !_AllowsOverlayShrinking())
- bSub1x = TRUE;
- // Drop to yuv stretch blts if
- // sub1x OR
- // another app has the overlay
- if (bSub1x | m_bMultipleOverlay)
- {
- nBltMode = HX_BLT_YUV_STRETCH;
- }
- // Drop to GDI if
- // DD not available
- if (m_bLostHWAcceleration)
- {
- nPreferredBltMode = nBltMode;
- nBltMode = HX_BASIC_BLT;
- }
- // Can we restore DirectDraw
- /*if (m_bLostHWAcceleration)
- {
- LPWINDRAWSURFACE lpwds = NULL;
- switch(nPreferredBltMode)
- {
- case HX_OVERLAY_BLT: lpwds = &m_surface; break;
- case HX_BLT_YUV_STRETCH: lpwds = &m_fallbackSurface; break;
- default: lpwds = &m_GDIsurface;
- }
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- m_bLostHWAcceleration = !pSurface->_IsHardwareAccelerationAvail(lpwds);
- if (!m_bLostHWAcceleration)
- {
- if (HXR_OK != WaitForQueuedFrames())
- Flush();
- DestroyGdiSurface();
- pSurface->_AcquireHardwareAcceleration();
- ReInitSurfaces();
- }
- }*/
- return nBltMode;
- }
- BOOL CWinSurface2::IsShrinking()
- {
- BOOL bShrink = FALSE;
- EnterCriticalSection(&m_csScale);
- if (m_dLastXScale != 0.0 && m_dLastYScale != 0.0 &&
- (m_dLastXScale < 1.0 || m_dLastYScale < 1.0))
- {
- bShrink = TRUE;
- }
- LeaveCriticalSection(&m_csScale);
- return bShrink;
- }
- void CWinSurface2::_WaitForFlush()
- {
- m_bWaitingForFlush = TRUE;
- // In the transition for VideoSurface2 to VideoSurface1, wait
- // until all frames are displayed.
- if (m_bWasInVidSurf2 && m_pListOfFrames)
- {
- while (m_pListOfFrames->GetCount())
- {
- Sleep(5);
- }
- // When switching to vidsurf1, set the backbuffer
- // to NULL so we do not flip the overlay. The flipping
- // chain seems to get out of whack in the transition from
- // vidsurf1 to 2.
- m_surface.dd.lpDDBackBuffer = NULL;
- }
- m_bWaitingForFlush = FALSE;
- }
- HX_RESULT CWinSurface2::ForceUpdateOverlay(HXxRect *pDst, HXxRect *pSrc, DWORD dwFlags, BOOL bCheckPos)
- {
- HXxRect destRect,
- srcRect = *pSrc;
- BOOL bUpdate = FALSE;
- if (HX_OVER_SHOW | dwFlags)
- {
- memset( &destRect, 0, sizeof(HXxRect) );
- _GetWindowDeviceCords(&destRect);
- destRect.right = destRect.left + pDst->right;
- destRect.bottom = destRect.top + pDst->bottom;
- destRect.left += pDst->left;
- destRect.top += pDst->top;
- // Ensure we limit update coordinates to screen res
- UINT16 uBitesPerPixel;
- UINT16 uHorzRes;
- UINT16 uVertRes;
- m_pSite->_GetDeviceCaps(NULL, uBitesPerPixel, uHorzRes, uVertRes);
- double ratio;
- if (destRect.left < 0)
- {
- ratio = ((double)abs(destRect.left)) / (double)(destRect.right - destRect.left);
- destRect.left = 0;
- srcRect.left = (int) (((double) m_surfaceSize.cx) * ratio);
- }
- if (destRect.right> uHorzRes)
- {
- ratio = ((double)(destRect.right - uHorzRes)) / (double)(destRect.right - destRect.left);
- destRect.right = uHorzRes;
- srcRect.right = (int) (((double) m_surfaceSize.cx) * (1.0 - ratio));
- }
- if (destRect.top < 0)
- {
- ratio = ((double)abs(destRect.top)) / (double)(destRect.bottom - destRect.top);
- destRect.top = 0;
- srcRect.top = (int) (((double) m_surfaceSize.cy) * ratio);
- }
- if (destRect.bottom > uVertRes)
- {
- ratio = ((double)(destRect.bottom - uVertRes)) / (double)(destRect.bottom - destRect.top);
- destRect.bottom = uVertRes;
- srcRect.bottom = (int) (((double) m_surfaceSize.cy) * (1.0 - ratio));
- }
- if (uBitesPerPixel != m_oldOverlayColorDepth)
- {
- m_oldOverlayColorDepth = uBitesPerPixel;
- // XXXAH Probably do not need this, but keeping it to make sure.
- m_convertedOverlayColor = _InsureColorMatch(GetOverlayColor());
- }
- if (bCheckPos)
- {
- CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW *pWindraw = pSurface->GetWinDraw();
- // If the overlay is invisible or if it nees to be
- // moved update its position.
- if (!WinDraw2_IsSurfaceVisible(pWindraw, &m_surface) ||
- ((m_lastUpdateDestRect.left != destRect.left) |
- (m_lastUpdateDestRect.right != destRect.right) |
- (m_lastUpdateDestRect.top != destRect.top) |
- (m_lastUpdateDestRect.bottom != destRect.bottom) |
- (m_lastUpdateSrcRect.left != srcRect.left) |
- (m_lastUpdateSrcRect.right != srcRect.right) |
- (m_lastUpdateSrcRect.top != srcRect.top) |
- (m_lastUpdateSrcRect.bottom != srcRect.bottom)))
- {
- bUpdate = TRUE;
- }
- }
- else
- {
- bUpdate = TRUE;
- }
- memcpy(&m_lastUpdateDestRect, &destRect, sizeof(HXxRect)); /* Flawfinder: ignore */
- memcpy(&m_lastUpdateSrcRect, &srcRect, sizeof(HXxRect)); /* Flawfinder: ignore */
- }
- if (bUpdate)
- {
- _SetColorKey(m_convertedOverlayColor, m_convertedOverlayColor);
- _UpdateOverlay(&destRect, &srcRect, dwFlags);
- }
- return HXR_OK;
- }
- HX_RESULT CWinSurface2::HandleDisplayModeChange()
- {
- UINT16 nBitDepth = 0,
- nHozRes = 0,
- nVertRes = 0;
- m_pSite->_GetDeviceCaps(NULL, nBitDepth, nHozRes, nVertRes);
- // The site handles surface reinit when bitdepth and
- // dimensions change. If the mode changed in some other
- // way (like refresh rate), handle it here.
- if (m_pSite->zm_bInFullScreenTest ||
- (nBitDepth == m_nBitsPerPixel &&
- nHozRes == m_nHozRes &&
- nVertRes == m_nVertRes &&
- WAIT_OBJECT_0 == WaitForSingleObject(m_hReinit, 0)))
- {
- // Wait for display buffers to render
- Flush();
- DestroySurfaces();
- ReInitSurfaces();
- m_bQueryMonitorFreq = TRUE;
- }
- else
- {
- // Wait on the next GetVidMem call for new surface creation
- ResetEvent(m_hReinit);
- m_nBitsPerPixel = nBitDepth;
- m_nHozRes = nHozRes;
- m_nVertRes = nVertRes;
- }
- return HXR_OK;
- }
- BOOL CWinSurface2::HandleDirectDrawLoss(BOOL bLockedTLSMutex)
- {
- BOOL bRet = FALSE;
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- m_bLostHWAcceleration = !pSurface->_IsHardwareAccelerationAvail();
- if (m_bLostHWAcceleration)
- {
- if (bLockedTLSMutex)
- m_pSite->_TLSUnlock();
- DestroySurfaces();
- pSurface->_LoseHardwareAcceleration();
- // RGB blitting is expensive, so drop the render thread priority
- if (m_bBoostRenderThread)
- SetThreadPriority(m_hRenThread, THREAD_PRIORITY_NORMAL);
- bRet = TRUE;
- }
- return bRet;
- }
- HX_RESULT CWinSurface2::ReleaseSurface(VideoMemStruct* pVidStruct, BOOL bDiscard, BOOL bDeleteAlphaList)
- {
- UCHAR* pVidMem = pVidStruct->pVidMem;
- if (pVidStruct->pAlphaList && bDeleteAlphaList)
- {
- delete [] pVidStruct->pAlphaList;
- }
- m_bFrameHasHWAlphaBlend = FALSE;
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- if (!m_bUseSysMemSurface)
- {
- if (m_bScratchSurface)
- {
- if (!bDiscard && m_pSite->HasFocusRect())
- {
- pSurface->DrawFocusRect(//&m_fallbackSurface,
- m_nFallbackSurfaceCID,
- &m_allocatedFallbackSize,
- pVidMem,
- m_pSite);
- }
- WinDrawSurface_Unlock (pWindraw, &m_fallbackSurface, 0);
- if (bDiscard)
- SetEvent(m_hFallbackEmpty);
- m_bScratchSurface = FALSE;
- }
- else if (m_bGDISurface)
- {
- if (!bDiscard && m_pSite->HasFocusRect())
- {
- pSurface->DrawFocusRect(//&m_GDIsurface,
- m_nGdiSurfaceCID,
- &m_allocatedGdiSize,
- pVidMem,
- m_pSite);
- }
- WinDrawSurface_Unlock (pWindraw, &m_GDIsurface, m_nNextGdiSurface);
- if (!bDiscard)
- {
- ResetEvent(m_GDIsurface.gdi.lpGDIBackBuffer[m_nNextGdiSurface]->hEmpty);
- if (++m_nNextGdiSurface == m_nGdiSurfaceCount)
- m_nNextGdiSurface = 0;
- }
- m_bGDISurface = FALSE;
- }
- else
- {
- if (m_pHwMemObj)
- {
- pVidMem = (UCHAR*)m_pHwMemObj->RendererToDevice(pVidMem);
- m_bFrameHasHWAlphaBlend = FALSE;
- }
- WinDraw_ReleaseLockedSurface (pWindraw, &m_surface, pVidMem, bDiscard);
- }
- }
- // Unlocked the surface
- ReleaseMutex(m_hSurfaceMutex);
- m_pSite->_TLSUnlock();
- return HXR_OK;
- }
- HX_RESULT CWinSurface2::WaitForTimeLine(INT32 lTimeStamp)
- {
- HX_RESULT hr = HXR_OK;
- if (m_pTimeLine)
- {
- DWORD dwRet = 0;
- UINT32 ulTime = 0;
- HX_RESULT hrTimeLine = m_pTimeLine->GetTimeLineValue(ulTime);
- while (HXR_TIMELINE_SUSPENDED == hrTimeLine &&
- m_bCont &&
- !m_bFlushing &&
- !m_bWaitingForFlush)
- {
- dwRet = WaitForSingleObject(m_hAbort, 5);
- if (WAIT_TIMEOUT != dwRet)
- {
- hr = HXR_FAIL;
- break;
- }
- hrTimeLine = m_pTimeLine->GetTimeLineValue(ulTime);
- }
- }
- return hr;
- }
- HX_RESULT CWinSurface2::WaitForQueuedFrames()
- {
- if (m_pTimeLine)
- {
- UINT32 ulTime = 0;
- if (HXR_TIMELINE_SUSPENDED == m_pTimeLine->GetTimeLineValue(ulTime))
- return HXR_FAIL;
- }
- // Wait until our queue count reaches 0
- int nCount = m_pListOfFrames->GetCount();
- while (nCount)
- {
- Sleep(5);
- nCount = m_pListOfFrames->GetCount();
- }
- return HXR_OK;
- }
- void CWinSurface2::CreateAlphaList(VideoMemStruct* pVidStruct)
- {
- _SetUpBlendRects();
- if(m_imageBlocks.GetCount())
- {
- UCHAR* pSysBuf = NULL;
- INT32 nPitch = 0;
- HRESULT hr = LockSysMemSurface(pSysBuf, nPitch, TRUE);
- // yuck..."sys mem" mode means we are passing system memory
- // buffers for the video but here we are using it for alpha blending,
- // so we need to set it to false.
- m_bUseSysMemSurface = FALSE;
- if (HXR_OK == hr)
- {
- ImageBlock* pBlock = NULL;
- // Create an alpha struct for every region rect
- pVidStruct->ulCount = m_imageBlocks.GetCount();
- pVidStruct->pAlphaList = new AlphaStruct[pVidStruct->ulCount];
- // Set each alpha struct rect as a pointer to a sys mem buffer
- // the size of one video frame. rcImageRect is the subrect
- // we need copied.
- CHXSimpleList::Iterator j = m_imageBlocks.Begin();
- for (int i=0; j != m_imageBlocks.End(); ++i, ++j)
- {
- pBlock = (ImageBlock*)*j;
- pVidStruct->pAlphaList[i].rcImageRect = pBlock->rect;
- pVidStruct->pAlphaList[i].ulImageWidth = m_allocatedSysMemSurfSize.cx;
- pVidStruct->pAlphaList[i].ulImageHeight = m_allocatedSysMemSurfSize.cy;
- pVidStruct->pAlphaList[i].ulFourCC = HX_I420;
- pVidStruct->pAlphaList[i].lPitch = m_nSysMemSurfPitch;
- pVidStruct->pAlphaList[i].pBuffer = pSysBuf;
- // The alpha source is greater than our video...yikes
- if (pBlock->rect.right > m_allocatedSysMemSurfSize.cx ||
- pBlock->rect.bottom > m_allocatedSysMemSurfSize.cy ||
- pBlock->rect.right-pBlock->rect.left > m_allocatedSysMemSurfSize.cx ||
- pBlock->rect.bottom-pBlock->rect.top > m_allocatedSysMemSurfSize.cy)
- {
- pVidStruct->ulCount = 0;
- HX_VECTOR_DELETE(pVidStruct->pAlphaList);
- return;
- }
- }
- }
- }
- m_bImageBlocksGood = TRUE;
- }
- void CWinSurface2::YuvAlphaBlend(AlphaStruct* pList,
- UINT32 ulCount,
- UCHAR* pDest,
- UINT32 ulFourCC,
- INT32 lPitch,
- HXxSize* pDestDim)
- {
- // Alpha blend each list entry and blt on the video frame
- if (m_bImageBlocksGood)
- {
- if( _BlendYUVRects(pList, ulCount, HX_I420) )
- {
- BOOL bConverter;
- INT32 ulDestCID = MapFourCCtoCID(ulFourCC);
- if (CID_UNKNOWN == ulDestCID)
- ulDestCID = ulFourCC;
- CHXSimpleList::Iterator gg = m_imageBlocks.Begin();
- for (int i=0; gg != m_imageBlocks.End(); ++i, ++gg)
- {
- ImageBlock* pBlock = (ImageBlock*)*gg;
- Image* pTmp = pBlock->pImage;
- // Get a converter
- bConverter = GetColorConverter(MapFourCCtoCID(pList[i].ulFourCC), ulDestCID);
- if (bConverter)
- {
- ColorConvert( ulDestCID,
- pDest,
- pDestDim->cx,
- pDestDim->cy,
- lPitch,
- pBlock->rect.left,
- pBlock->rect.top,
- pBlock->rect.right-pBlock->rect.left,
- pBlock->rect.bottom-pBlock->rect.top,
- MapFourCCtoCID(pList[i].ulFourCC),
- pTmp->pucImage,
- pTmp->bmiImage.biWidth,
- pTmp->bmiImage.biHeight,
- GETBITMAPPITCH(&pTmp->bmiImage),
- 0,
- 0,
- pBlock->rect.right-pBlock->rect.left,
- pBlock->rect.bottom-pBlock->rect.top);
- }
- }
- }
- }
- }
- /************************************************************************
- * Method:
- * _ScheduleFrameForDisplay
- * Purpose:
- */
- HX_RESULT CWinSurface2::_ScheduleFrameForDisplay(void* pOsData,
- tFrameElement* pItem,
- UINT32 nResolution)
- {
- // Display immediately when we do not have a clock
- if (!m_pTimeLine)
- return HXR_OK;
- HX_RESULT hr = HXR_OK;
- UINT32 ulTime = 0;
- HANDLE aWaitObjects[2] = {m_hForceRender, m_hAbort};
- // Number of ms the frame is ahead of the clock
- INT32 nTimeAhead = 0;
- // Use default scheduler
- if (!m_bOptimalVideoScheduler)
- {
- if (HXR_OK != CWinSurface::_ScheduleFrameForDisplay(pOsData, pItem, nResolution))
- {
- m_pTimeLine->GetTimeLineValue(ulTime);
- nTimeAhead = pItem->lTimeStamp - ulTime;
- // Ignore scheduling during a flush
- if (!m_bFlushing &&
- hr != HXR_TIMELINE_SUSPENDED &&
- nTimeAhead > 0)
- {
- m_nLastDisplayTime = ulTime + nTimeAhead;
- if (nResolution)
- timeBeginPeriod(nResolution);
- WaitForMultipleObjects(2, aWaitObjects, FALSE, nTimeAhead);
- if (nResolution)
- timeEndPeriod(nResolution);
- m_nLastDisplayTime = -1;
- }
- }
- pItem->dTimeAvailable = GetMSTickDouble32() + 15;
- return HXR_OK;
- }
- WINDRAW* pWindraw = (WINDRAW*)pOsData;
- double dTickAtStreamTime = 0;
- double dPreemptionCheckTick = 0;
- // Number of ms to the next vertical retrace
- double dMsToNextVBlank = 0;
- double dCurrentError = 0;
- // Number of vblanks the display device can schedule the blt
- INT32 nMaxVBlanksPerSchedule = 0;
- // The display device's current vertical scan line
- UINT32 dwScanLine = 0;
- double dFilteredScanLine = 0.0;
- // Number of vblanks until we need to display the frame
- double dVblanksToWait = 0.0;
- double dIdealVBlank = 0.0;
- INT32 nVblanksToWait = 0;
- // Fraction of a vertical trace the video starts on
- double dWindowPosScanLine = 0;
- // Final window placement:
- HXxRect windowRect = { 0, 0, 0, 0 };
- // Window of error for picking a vblank to flip on.
- double dWindowOfError = .2;
- if (pItem->nBltMode == HX_OVERLAY_BLT)
- {
- // Some cards can schedule an overlay flip 4 vblanks in advance
- if (m_bUseVBlankFlip)
- nMaxVBlanksPerSchedule = 4;
- else
- nMaxVBlanksPerSchedule = 1;
- }
- while (1)
- {
- dTickAtStreamTime = GetMSTickDouble32();
- hr = m_pTimeLine->GetTimeLineValue(ulTime);
- dPreemptionCheckTick = GetMSTickDouble32();
- // Calculate how far the video is ahead of the clock in ms
- UINT32 i;
- for (i = 0; (dPreemptionCheckTick - dTickAtStreamTime > OS_THREAD_QUANTUM / 5.0)
- && i < MAX_PREEMPTION_CHECK_ATTEMPTS; ++i)
- {
- HX_TRACE("Preemption!n");
- dTickAtStreamTime = GetMSTickDouble32();
- hr = m_pTimeLine->GetTimeLineValue(ulTime);
- dPreemptionCheckTick = GetMSTickDouble32();
- }
- nTimeAhead = pItem->lTimeStamp - ulTime;
- WinDraw2_GetScanLine(pWindraw, &dwScanLine);
- // GetScanLine is terribly noisy on the G400 - one can get better
- // results by using high precision timers!
- // dFilteredScanLine = FilterScanLine(dwScanLine, dTickAtStreamTime - dVblankTime, pWindraw);
- dFilteredScanLine = dwScanLine;
- HX_ASSERT(dFilteredScanLine < pWindraw->dwMaxScanLine + 1);
- #ifdef ENABLE_SYNC_TRACE
- syncTraceArray[ulSyncTraceIdx % MAX_SYNC_TRACE_ENTRIES][0] = dTickAtStreamTime;
- syncTraceArray[ulSyncTraceIdx % MAX_SYNC_TRACE_ENTRIES][1] = dwScanLine;
- syncTraceArray[ulSyncTraceIdx++ % MAX_SYNC_TRACE_ENTRIES][2] = GetMSTickDouble32() - dPreemptionCheckTick;
- #endif // ENABLE_SYNC_TRACE
- _GetWindowDeviceCords(&windowRect);
- dWindowPosScanLine = windowRect.top / (double) (pWindraw->dwMaxScanLine + 1);
- // How many ms until the next vblank
- dMsToNextVBlank = (1.0 - (dFilteredScanLine / (double) (pWindraw->dwMaxScanLine + 1))) * pWindraw->dMsPerVBlank;
- // How many vblanks after the current one, until display time
- dVblanksToWait = (nTimeAhead - dMsToNextVBlank) / pWindraw->dMsPerVBlank;
- #ifdef KAYA_CODE
- // Pick the appropriate vblank to display our frame. First truncate
- // dVblanksToWait then round up and down and pick the smallest error.
- // In the rounding code, use nWindowPosScanLine to increase the a/v sync
- // accuracy. We want to draw the first line of video as close to
- // the time give to us in pItem.
- double dPrevVBlank = ((INT32) dVblanksToWait) + dWindowPosScanLine - 1;
- double dCurrentVBlank = dPrevVBlank + 1;
- double dNextVBlank = dCurrentVBlank + 1;
- dIdealVBlank = fabs(dPrevVBlank - dVblanksToWait)
- < fabs(dCurrentVBlank - dVblanksToWait) ? dPrevVBlank : dCurrentVBlank;
- dIdealVBlank = fabs(dIdealVBlank - dVblanksToWait)
- < fabs(dNextVBlank - dVblanksToWait) ? dIdealVBlank : dNextVBlank;
- // If the refresh rate is a close multiple of the frame rate, we may
- // see rapid +/- oscillation of choice of vblanks due to timing error.
- // We only want to snap once per beat, so bias to the previous frame's
- // error in this case.
- dCurrentError = dVblanksToWait - (((INT32) dIdealVBlank <= 0 ? 0 : (INT32) dIdealVBlank)
- + dWindowPosScanLine);
- if (fabs(dCurrentError) > TIME_JITTER_FILTER_THRESHOLD)
- {
- if ((m_dLastBlitError < 0) && (dCurrentError > 0))
- {
- //HX_TRACE("Error sign change: %fn", dCurrentError);
- // Decrease error:
- dIdealVBlank++;
- }
- else if ((m_dLastBlitError > 0) && (dCurrentError < 0))
- {
- //HX_TRACE("Error sign change: %fn", dCurrentError);
- // Increase error:
- dIdealVBlank--;
- }
- // An error of zero indicates an unitialized value on
- // start of playback or an unlikely coincidence. Don't dampen
- // arbitrarily on the first frame to reduce the odds
- // of an initial, preventable snap; coincidences are harmless
- }
- nVblanksToWait = (INT32) dIdealVBlank;
- if (nVblanksToWait < 0)
- {
- nVblanksToWait = 0;
- }
- #else
- // Determine the appropriate time to schedule this frame for display.
- // The basic idea is to map the time stamp with a vertical retrace.
- // When the refresh rate is evenly divisible by video frame rate there
- // will be an even map but the rest of the time we must approximate.
- //
- // The approximation is simple, find the vtrace the time stamps maps
- // to, calculate the time of this vtrace and compare this value with
- // the next vtrace. Select the one that is closest to the time stamp.
- double dBltTime1 = pItem->lTimeStamp - (dVblanksToWait-(INT32)dVblanksToWait)*pWindraw->dMsPerVBlank;
- double dBltTime2 = dBltTime1 + pWindraw->dMsPerVBlank;
- double dBltTime;
- if ( fabs(dBltTime1-pItem->lTimeStamp) < fabs( dBltTime2-pItem->lTimeStamp))
- {
- dBltTime = dBltTime1;
- nVblanksToWait = (INT32)dVblanksToWait;
- }
- else
- {
- dBltTime = dBltTime2;
- nVblanksToWait = (INT32)(dVblanksToWait + 1);
- }
- INT32 nScheduleTime = dBltTime - nMaxVBlanksPerSchedule*pWindraw->dMsPerVBlank;
- // Ignore scheduling when the clock stops updating to avoid an infinite loop
- if (m_bFlushing || hr == HXR_TIMELINE_SUSPENDED)
- {
- nVblanksToWait = max(min(nVblanksToWait,nMaxVBlanksPerSchedule-1), 0);
- ulTime = nScheduleTime+1;
- }
- #endif //KAYA_CODE
- // If the clock is within our allowed scheduling time, schedule the blt
- if (ulTime > nScheduleTime)
- {
- #ifdef LOG_JITTER_DATA
- FILE *fp = fopen(JITTER_LOG_FILE, "a+");
- if (fp)
- {
- fprintf(fp, "Ready to flip: ts %ld clock %ld scan line %ld mstvb %.3f vbw %.3f jitter %ldn",
- pItem->lTimeStamp, ulTime, dwScanLine, dMsToNextVBlank, dVblanksToWait, (INT32)(pItem->lTimeStamp-(ulTime+dMsToNextVBlank+(INT32)nVblanksToWait*pWindraw->dMsPerVBlank)));
- fclose(fp);
- }
- #endif //LOG_JITTER_DATA
- m_dLastBlitError = pItem->lTimeStamp-(ulTime+dMsToNextVBlank+(INT32)nVblanksToWait*pWindraw->dMsPerVBlank);
- nVblanksToWait = 0;
- break;
- }
- else
- {
- // We want to wake up as soon as we can display the frame
- long lSleep = nScheduleTime - ulTime + 1;
- m_nLastDisplayTime = ulTime + lSleep;
- #ifdef LOG_JITTER_DATA
- INT32 lB4Sleep = GetBetterTickCount();
- #endif //LOG_JITTER_DATA
- if (lSleep > 0)
- {
- #ifndef HARDCODE_GRANULE
- if (nResolution)
- timeBeginPeriod(nResolution);
- #endif //HARDCODE_GRANULE
- WaitForMultipleObjects(2, aWaitObjects, FALSE, lSleep);
- #ifndef HARDCODE_GRANULE
- if (nResolution)
- timeEndPeriod(nResolution);
- #endif //HARDCODE_GRANULE
- }
- m_nLastDisplayTime = -1;
- #ifdef LOG_JITTER_DATA
- FILE *fp = fopen(JITTER_LOG_FILE, "a+");
- if (fp)
- {
- fprintf(fp, "ts %ld clock %ld scan line %ld mstvb %.3f vbw %.3f sleep %ld sleep dur %ldn",
- pItem->lTimeStamp, ulTime, dwScanLine, dMsToNextVBlank, dVblanksToWait, lSleep, GetBetterTickCount()-lB4Sleep);
- fclose(fp);
- }
- #endif //LOG_JITTER_DATA
- if (lSleep < 0)
- break;
- }
- }
- #ifdef ENABLE_ERROR_TRACE
- //char szTmp[1000];
- //HX_TRACE("%lut:: blit error: %fn", pItem->lTimeStamp, (dIdealVBlank - dVblanksToWait)*pWindraw->dMsPerVBlank);
- //sprintf(szTmp, "Timing error: %fn", (dIdealVBlank - dVblanksToWait)*pWindraw->dMsPerVBlank);
- g_error[g_ulFrameCount % 10000][0] = dTickAtStreamTime;
- g_error[g_ulFrameCount % 10000][1] = m_dLastBlitError*pWindraw->dMsPerVBlank;
- g_error[g_ulFrameCount % 10000][2] = dIdealVBlank;
- g_alternateError[g_ulFrameCount++ % 10000] = pItem->lTimeStamp - (INT32) ulTime;
- // Get the DC and render this to the screen:
- //OutputDebugString(szTmp);
- #endif // ENABLE_ERROR_TRACE
- // Set the minimum time this frame needs to be displayed (1 vblank)
- pItem->dTimeAvailable = dTickAtStreamTime + dMsToNextVBlank + (nVblanksToWait+1)*pWindraw->dMsPerVBlank + 1;
- HX_ASSERT(pItem->dTimeAvailable);
- // Set the DD flags for interval flipping
- if (pItem->nBltMode == HX_OVERLAY_BLT && m_bUseVBlankFlip)
- {
- switch((INT32)nVblanksToWait+1)
- {
- case 4: pItem->dwDDFlags = DDFLIP_INTERVAL4; break;
- case 3: pItem->dwDDFlags = DDFLIP_INTERVAL3; break;
- case 2: pItem->dwDDFlags = DDFLIP_INTERVAL2; break;
- default:pItem->dwDDFlags = 0;
- }
- }
- return hr;
- }
- double CWinSurface2::FilterScanLine(UINT32 ulScanLine, double dTickAtStreamTime,
- WINDRAW* pWindraw, BOOL bResetFilter)
- {
- #ifdef FILTER_SCAN_LINE
- // No mutex needed (for now) - this function is only called from the
- // render thread.
- // On reset, wait for vertical blank and reset m_ulScanLineFilterDepth:
- if (bResetFilter)
- {
- m_dMaxRegression = 0;
- m_ulScanLineFilterDepth = 0;
- return 0;
- }
- // This filter should adjust the max scan line (i.e. vertical refresh time),
- // refresh rate, and current scan line. It is critical that we at least get
- // the phase (scan line) accurate.
- double currentRefresh = ulScanLine / pWindraw->dMsPerVBlank;
- UINT32 ulSamplesUsed = 0;
- double m;
- double b;
- // Ignore both zero and max scan line; some drivers play games with these.
- if (ulScanLine == 0 && ulScanLine != pWindraw->dwMaxScanLine)
- {
- // Add to filter:
- m_scanLineFilter[m_ulScanLineFilterDepth % SCAN_LINE_FILTER_DEPTH][0] = dTickAtStreamTime;
- m_scanLineFilter[m_ulScanLineFilterDepth++ % SCAN_LINE_FILTER_DEPTH][1]= currentRefresh;
- #ifdef _DEBUG
- double dLastPhaseError;
- #endif // _DEBUG
- // If we assume our refresh + scan line error is +/- 5%, then our
- // phase error should be monotonic to 20 past vblanks.
- // Perform a linear regression to correct our sample, if needed.
- double sumX,
- sumY,
- sumXY,
- sumXSquared,
- sumYSquared = 0;
- for (int i = 1; i < m_ulScanLineFilterDepth && i < SCAN_LINE_FILTER_DEPTH; ++i)
- {
- double elapsedTime = m_scanLineFilter[(m_ulScanLineFilterDepth - i - 1) % SCAN_LINE_FILTER_DEPTH][0] -
- m_scanLineFilter[(m_ulScanLineFilterDepth - i) % SCAN_LINE_FILTER_DEPTH][0];
- if (elapsedTime >= 10*pWindraw->dMsPerVBlank)
- {
- continue;
- }
- #ifdef _DEBUG
- // Monotonic?
- #endif // _DEBUG
- ulSamplesUsed++;
- double refresh = (m_scanLineFilter[(m_ulScanLineFilterDepth - i - 1) % SCAN_LINE_FILTER_DEPTH][1] / pWindraw->dMsPerVBlank) + fmod(elapsedTime, pWindraw->dMsPerVBlank);
- refresh = refresh - (INT32) refresh;
- double error = m_scanLineFilter[(m_ulScanLineFilterDepth - i) % SCAN_LINE_FILTER_DEPTH][1] - refresh;
- //HX_TRACE("terror : %lfn", error);
- sumX += elapsedTime;
- sumY += error;
- sumXY = elapsedTime*error;
- sumXSquared += elapsedTime*elapsedTime;
- sumYSquared += error*error;
- }
- if (ulSamplesUsed < 100)
- {
- //HX_TRACE("skipn");
- goto nofilter;
- }
- double meanX = sumX / ulSamplesUsed;
- double meanY = sumY / ulSamplesUsed;
- double sumSquaredErrorX = 0;
- double sumSquaredErrorY = 0;
- double sumErrorProduct = 0;
- for (i = 1; i < m_ulScanLineFilterDepth && i < SCAN_LINE_FILTER_DEPTH; ++i)
- {
- double elapsedTime = m_scanLineFilter[(m_ulScanLineFilterDepth - i - 1) % SCAN_LINE_FILTER_DEPTH][0] -
- m_scanLineFilter[(m_ulScanLineFilterDepth - i) % SCAN_LINE_FILTER_DEPTH][0];
- if (elapsedTime >= 10*pWindraw->dMsPerVBlank)
- {
- continue;
- }
- double refresh = (m_scanLineFilter[(m_ulScanLineFilterDepth - i - 1) % SCAN_LINE_FILTER_DEPTH][1] / pWindraw->dMsPerVBlank) + fmod(elapsedTime, pWindraw->dMsPerVBlank);
- refresh = refresh - (INT32) refresh;
- double error = m_scanLineFilter[(m_ulScanLineFilterDepth - i) % SCAN_LINE_FILTER_DEPTH][1] - refresh;
- sumSquaredErrorX += (elapsedTime - meanX)*(elapsedTime - meanX);
- sumSquaredErrorY += (error - meanY)*(error - meanY);
- sumErrorProduct += (elapsedTime - meanX)*(error - meanY);
- }
- double rho = sumErrorProduct / sqrt(sumSquaredErrorX*sumSquaredErrorY);
- //double rho = (sumXY - ((sumX*sumY) / ulSamplesUsed)) /
- // sqrt((sumXSquared - ((sumX*sumX) / ulSamplesUsed))*(sumYSquared - ((sumY*sumY) / ulSamplesUsed)));
- double stdDevX = sumSquaredErrorX / ulSamplesUsed - 1;
- double stdDevY = sumSquaredErrorY / ulSamplesUsed - 1;
- m = rho*stdDevY/stdDevX;
- b = meanY - (m*meanX);
- //HX_TRACE("current phase error: %lfn");
- //HX_TRACE("current refresh error: %lfn");
- // Do we have enough data to update our phase point
- #if 0
- if (rho >= MIN_ALLOWED_REGRESSION)
- {
- m_dMaxRegression = rho;
- HX_TRACE("current rho: %lfn", rho);
- HX_TRACE("current m: %lfn", m);
- HX_TRACE("current b: %lfn", b);
- // Regression still has a sample delay; let's not worry about it for
- // now; nor any error due to an inaccurate max scan line.
- // Update refresh rate:
- // A negative slope = error decreasing back in time, increasing forwards in time.
- // Refresh rate should increase.
- // Positive slope = error increasing back in time, decreasing forwards in time.
- // Refresh rate should decrease.
- pWindraw->dRefreshRate -= m*1000;
- pWindraw->dMsPerVBlank = 1 / pWindraw->dRefreshRate;
- HX_TRACE("new refresh: %lfn", pWindraw->dRefreshRate);
- // Update phase point:
- currentRefresh -= b;
- if (currentRefresh > 0)
- {
- m_dPhasePoint = dTickAtStreamTime - (currentRefresh)/pWindraw->dMsPerVBlank;
- }
- else
- {
- m_dPhasePoint = dTickAtStreamTime - ((currentRefresh)+1)/pWindraw->dMsPerVBlank;
- }
- }
- #endif // 0
- }
- //if (m_dMaxRegression >= MIN_ALLOWED_REGRESSION)
- {
- double dRefreshes = (dTickAtStreamTime - m_dPhasePoint) / pWindraw->dMsPerVBlank;
- HX_TRACE("current b: %lfn", b);
- dRefreshes -= b;
- if (dRefreshes < 0)
- {
- dRefreshes++;
- }
- double dScanLine = (dRefreshes - ((UINT32) dRefreshes))*(pWindraw->dwMaxScanLine + 1);
- // If we're off by less than 15%, let it slide?
- return fabs(dScanLine - ulScanLine) / (pWindraw->dwMaxScanLine + 1) > 15
- ? dScanLine : ulScanLine;
- }
- #endif // FILTER_SCAN_LINE
- #ifdef FILTER_SCAN_LINE
- nofilter:
- #endif
- return ulScanLine;
- }