void CPushPinDesktop::doJustBitBltOrScaling(HDC hMemDC, int nWidth, int nHeight, int iFinalWidth, int iFinalHeight, HDC hScrDC, int nX, int nY) { __int64 start = StartCounter(); boolean notNeedStretching = (iFinalWidth == nWidth) && (iFinalHeight == nHeight); if(m_iHwndToTrack != NULL) ASSERT_RAISE(notNeedStretching); // we don't support HWND plus scaling...hmm... LODO move assertion LODO implement this (low prio since they probably are just needing that window, not with scaling too [?]) int captureType = SRCCOPY; if(m_bUseCaptureBlt) captureType = captureType | CAPTUREBLT; // CAPTUREBLT here [last param] is for layered (transparent) windows in non-aero I guess (which happens to include the mouse, but we do that elsewhere) if (notNeedStretching) { if(m_iHwndToTrack != NULL) { // make sure we only capture 'not too much' i.e. not past the border of this HWND, for the case of Aero being turned off, it shows other windows that we don't want // a bit confusing... RECT p; if (m_bHwndTrackDecoration) GetWindowRectIncludingAero(m_iHwndToTrack, &p); // 0.05 ms else GetClientRect(m_iHwndToTrack, &p); // 0.005 ms //GetWindowRect(m_iHwndToTrack, &p); // 0.005 ms nWidth = min(p.right-p.left, nWidth); nHeight = min(p.bottom-p.top, nHeight); } // Bit block transfer from screen our compatible memory DC. Apparently this is faster than stretching. BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, captureType); // 9.3 ms 1920x1080 -> 1920x1080 (100 fps) (11 ms? 14? random?) } else { if (m_iStretchMode == 0) { // low quality scaling -- looks terrible SetStretchBltMode (hMemDC, COLORONCOLOR); // the SetStretchBltMode call itself takes 0.003ms // COLORONCOLOR took 92ms for 1920x1080 -> 1000x1000, 69ms/80ms for 1920x1080 -> 500x500 aero // 20 ms 1920x1080 -> 500x500 without aero // LODO can we get better results with good speed? it is sooo ugly! } else { SetStretchBltMode (hMemDC, HALFTONE); // high quality stretching // HALFTONE took 160ms for 1920x1080 -> 1000x1000, 107ms/120ms for 1920x1080 -> 1000x1000 // 50 ms 1920x1080 -> 500x500 without aero SetBrushOrgEx(hMemDC, 0, 0, 0); // MSDN says I should call this after using HALFTONE } StretchBlt(hMemDC, 0, 0, iFinalWidth, iFinalHeight, hScrDC, nX, nY, nWidth, nHeight, captureType); } if(show_performance) LocalOutput("%s took %.02f ms", notNeedStretching ? "bitblt" : "stretchblt", GetCounterSinceStartMillis(start)); }
void CPushPinDesktop::reReadCurrentStartXY(int isReRead) { __int64 start = StartCounter(); // assume 0 means not set...negative ignore :) // TODO no overflows, that's a bad value too... they cause a crash, I think! [position youtube too far bottom right, track it...] int old_x = m_rScreen.left; int old_y = m_rScreen.top; int config_start_x = read_config_setting(TEXT("start_x"), m_rScreen.left, true); m_rScreen.left = config_start_x; // is there a better way to do this registry stuff? int config_start_y = read_config_setting(TEXT("start_y"), m_rScreen.top, true); m_rScreen.top = config_start_y; if(old_x != m_rScreen.left || old_y != m_rScreen.top) { if(isReRead) { m_rScreen.right = m_rScreen.left + m_iCaptureConfigWidth; m_rScreen.bottom = m_rScreen.top + m_iCaptureConfigHeight; } } if(show_performance) { wchar_t out[1000]; swprintf(out, 1000, L"new screen pos from reg: %d %d\n", config_start_x, config_start_y); LocalOutput("[re]readCurrentPosition (including swprintf call) took %.02fms", GetCounterSinceStartMillis(start)); // takes 0.42ms (2000 fps) LocalOutput(out); } }
/* Initialize OpenGL Graphics */ void InitGL() { StartCounter(); gLastTime = GetCounter(); // Set "clearing" or background color glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black and opaque }
void CPushPinDesktop::doDIBits(HDC hScrDC, HBITMAP hRawBitmap, int nHeightScanLines, BYTE *pData, BITMAPINFO *pHeader) { __int64 start = StartCounter(); // Copy the bitmap data into the provided BYTE buffer, in the right format I guess. GetDIBits(hScrDC, hRawBitmap, 0, nHeightScanLines, pData, pHeader, DIB_RGB_COLORS); // just copies raw bits to pData, I guess, from an HBITMAP handle. "like" GetObject, but also does conversions [?] if(show_performance) LocalOutput("doDiBits took %.02fms", GetCounterSinceStartMillis(start)); // took 1.1/3.8ms total, so this brings us down to 80fps compared to max 251...but for larger things might make more difference... }
/** * @brief Plays a tone. * * @param[in] freq approximated tone frequency * @param[in] duration tone duration in systicks */ void buzzPlayWait(uint32_t freq, systime_t duration) { TC *tc = T1Base; StopCounter(tc); tc->TC_MR0 = tc->TC_MR1 = (PCLK / (freq * 2)); StartCounter(tc); chThdSleep(duration); StopCounter(tc); }
int StartSampling(void) { #ifdef USE_NMI int cpuId = smp_processor_id(); if (cpuId == 0) { WRITEMSR(INS_FIXED_COUNTER, COUNTER_OVERFLOW); WRITEMSR(INS_FIXED_MSR, 0x0a); } #endif StartCounter(&counterPackage); return 0; }
/** * @brief Plays a tone asynchronously. * * @param[in] freq approximated tone frequency * @param[in] duration tone duration in systicks */ void buzzPlay(uint32_t freq, systime_t duration) { static VirtualTimer bvt; TC *tc = T1Base; chSysLock(); if (chVTIsArmedI(&bvt)) { /* If a sound is already being */ chVTResetI(&bvt); /* played then aborts it. */ StopCounter(tc); } tc->TC_MR0 = tc->TC_MR1 = (PCLK / (freq * 2)); StartCounter(tc); chVTSetI(&bvt, duration, stop, tc); chSysUnlock(); }
//....................................................................................... double Object::ReleaseObjectData(bool _log) { __int64 t0 = StartCounter(); free(m_pVertices); free(m_pIndices); if (m_texture.m_pTexture) m_texture.m_pTexture->FreeTextureData(_log); double time = GetElapsed(t0); if (_log) Logw("Object::ReleaseObjectData(): Released object data (%d bytes) in %.4f ms\n", m_nVertices * sizeof(GLvertex) + m_nIndices * sizeof(unsigned int), time); return (time); } // end Object::ReleaseObjectData()
double get_sort_time(int *pa, int len, void (fsort)(int * , int )) { # if 0 // 计时方法1 const clock_t begin = clock(); fsort(pa, len); const clock_t end = clock(); return (double)(end-begin)/CLOCKS_PER_SEC ; #endif #if 0 // 计时方法2 DWORD begin = GetTickCount(); fsort(pa, len); DWORD end = GetTickCount(); return end - begin; #endif StartCounter(); fsort(pa, len); return GetCounter() ; }
PlatformDesktop::PlatformDesktop() : mGraphics( NULL ), mFrameCount( 0 ), mFrameRate( 0 ), mOneFrameShouldLast( 1.f / 60.f ), mFixedTimeStep( true ), mWidth( 0 ), mHeight( 0 ), mEventRecorder( NULL ), mMouse( NULL ), mKeyboard( NULL ), mTouch( NULL ), mJoysticks(), mSoundPlayer( NULL ), mRunning( 0 ), mMousePos(), mSleepingMode( PORO_NEVER_SLEEP ), mPrintFramerate( false ), mRandomSeed( 1234567 ) { StartCounter(); }
//....................................................................................... unsigned char *TextureGenerator::GenPerlinNoise(GLenum *_type, int *_w, int *_h, int *_d) { (*_w) = m_x; (*_h) = m_y; (*_d) = m_z; Logw("TextureGenerator::GenPerlinNoise(): Generating noise (%dx%dx%d px)\n", (*_w), (*_h), (*_d)); int offset = 0; __int64 t0 = StartCounter(); PerlinNoise *pn = NULL; // seed engine for new permutation? if (m_iPerlinSeed) pn = new PerlinNoise(m_iPerlinSeed); // use standard permutation vector G else pn = new PerlinNoise(); unsigned char *textureData = NULL; double *noiseData = NULL; double dmin = 0.0, dmax = 0.0; // GL_TEXTURE_1D|2D|3D ? switch (*_type) { case GL_TEXTURE_1D: textureData = new unsigned char[m_x * m_iBPP]; #pragma omp parallel for for (int x = 0; x < m_x; x++) { int offset = m_x * m_iBPP; double xp = (double)x / (double)m_x; double noise = pn->Noise(m_iPerlinAmp * xp, 0, 0); int c = floor(xp * 256); textureData[offset + 0] = c; textureData[offset + 1] = c; textureData[offset + 2] = c; } break; case GL_TEXTURE_2D: textureData = new unsigned char[m_x * m_y * m_iBPP]; noiseData = new double[m_x * m_y]; switch (m_ePerlinType) { case PerlinNoiseType::Simple: #pragma omp parallel for for (int y = 0; y < m_y; y++) { for (int x = 0; x < m_x; x++) { double xp = (double)x / (double)m_x; double yp = (double)y / (double)m_y; double noise = pn->Noise(m_iPerlinAmp * xp, m_iPerlinAmp * yp, 0.0); dmin = MIN(dmin, noise); dmax = MAX(dmax, noise); int offset = (y * m_x + x); noiseData[offset] = noise; } } break; case PerlinNoiseType::FractalSum: #pragma omp parallel for for (int y = 0; y < m_y; y++) { for (int x = 0; x < m_x; x++) { double xp = (double)x / (double)m_x; double yp = (double)y / (double)m_y; double noise = 0.0; for (int n = 1; n < (1 << m_nPerlinOctaves); n *= 2) noise += (1.0 / (double)n) * pn->Noise(m_iPerlinAmp * n * xp, m_iPerlinAmp * n * yp, 0.0); dmin = MIN(dmin, noise); dmax = MAX(dmax, noise); int offset = (y * m_x + x); noiseData[offset] = noise; } } break; case PerlinNoiseType::Wood: #pragma omp parallel for for (int y = 0; y < m_y; y++) { for (int x = 0; x < m_x; x++) { double xp = (double)x / (double)m_x; double yp = (double)y / (double)m_y; double noise = m_iPerlinThickness * pn->Noise(m_iPerlinAmp * xp, m_iPerlinAmp * yp, 0.0); noise -= floor(noise); dmin = MIN(dmin, noise); dmax = MAX(dmax, noise); int offset = (y * m_x + x); noiseData[offset] = noise; } } break; } // end switch PerlinNoiseType #pragma omp parallel for for (int y = 0; y < m_y; y++) { for (int x = 0; x < m_x; x++) { int offset = y * m_x + x; int offset_bpp = offset * m_iBPP; int color = (int)(((noiseData[offset] - dmin) / (dmax - dmin)) * 255.0); textureData[offset_bpp + 0] = color; textureData[offset_bpp + 1] = color; textureData[offset_bpp + 2] = color; } } break; // end GL_TEXTURE_2D case GL_TEXTURE_3D: break; } // release temp noise data if (noiseData) delete noiseData; // release pn class if (pn) delete pn; // done return (textureData); }
HRESULT CPushPinDesktop::FillBuffer(IMediaSample *pSample) { __int64 startThisRound = StartCounter(); BYTE *pData; CheckPointer(pSample, E_POINTER); if(m_bReReadRegistry) { reReadCurrentPosition(1); } // Access the sample's data buffer pSample->GetPointer(&pData); // Make sure that we're still using video format ASSERT(m_mt.formattype == FORMAT_VideoInfo); VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*) m_mt.pbFormat; // for some reason the timings are messed up initially, as there's no start time at all for the first frame (?) we don't start in State_Running ? // race condition? // so don't do some calculations unless we're in State_Running FILTER_STATE myState; CSourceStream::m_pFilter->GetState(INFINITE, &myState); bool fullyStarted = myState == State_Running; boolean gotNew = false; while(!gotNew) { CopyScreenToDataBlock(hScrDc, pData, (BITMAPINFO *) &(pVih->bmiHeader), pSample); if(m_bDeDupe) { if(memcmp(pData, pOldData, pSample->GetSize())==0) { // took desktop: 10ms for 640x1152, still 100 fps uh guess... Sleep(m_millisToSleepBeforePollForChanges); } else { gotNew = true; memcpy( /* dest */ pOldData, pData, pSample->GetSize()); // took 4ms for 640x1152, but it's worth it LOL. // LODO memcmp and memcpy in the same loop LOL. } } else { // it's always new for everyone else! gotNew = true; } } // capture how long it took before we add in our own arbitrary delay to enforce fps... long double millisThisRoundTook = GetCounterSinceStartMillis(startThisRound); fastestRoundMillis = min(millisThisRoundTook, fastestRoundMillis); // keep stats :) sumMillisTook += millisThisRoundTook; CRefTime now; CRefTime endFrame; CSourceStream::m_pFilter->StreamTime(now); // wait until we "should" send this frame out... if((now > 0) && (now < previousFrameEndTime)) { // now > 0 to accomodate for if there is no reference graph clock at all...also boot strap time ignore it :P while(now < previousFrameEndTime) { // guarantees monotonicity too :P Sleep(1); CSourceStream::m_pFilter->StreamTime(now); } // avoid a tidge of creep since we sleep until [typically] just past the previous end. endFrame = previousFrameEndTime + m_rtFrameLength; previousFrameEndTime = endFrame; } else { if(show_performance) LocalOutput("it missed a frame--can't keep up %d", countMissed++); // we don't miss time typically I don't think, unless de-dupe is turned on, or aero, or slow computer, buffering problems downstream, etc. // have to add a bit here, or it will always be "it missed some time" for the next round...forever! endFrame = now + m_rtFrameLength; // most of this stuff I just made up because it "sounded right" //LocalOutput("checking to see if I can catch up again now: %llu previous end: %llu subtr: %llu %i", now, previousFrameEndTime, previousFrameEndTime - m_rtFrameLength, previousFrameEndTime - m_rtFrameLength); if(now > (previousFrameEndTime - (long long) m_rtFrameLength)) { // do I need a long long cast? // let it pretend and try to catch up, it's not quite a frame behind previousFrameEndTime = previousFrameEndTime + m_rtFrameLength; } else { endFrame = now + m_rtFrameLength/2; // ?? seems to work...I guess... previousFrameEndTime = endFrame; } } previousFrameEndTime = max(0, previousFrameEndTime);// avoid startup negatives, which would kill our math on the next loop... // LocalOutput("marking frame with timestamps: %llu %llu", now, endFrame); pSample->SetTime((REFERENCE_TIME *) &now, (REFERENCE_TIME *) &endFrame); //pSample->SetMediaTime((REFERENCE_TIME *)&now, (REFERENCE_TIME *) &endFrame); //useless seemingly if(fullyStarted) { m_iFrameNumber++; } // Set TRUE on every sample for uncompressed frames http://msdn.microsoft.com/en-us/library/windows/desktop/dd407021%28v=vs.85%29.aspx pSample->SetSyncPoint(TRUE); // only set discontinuous for the first...I think... pSample->SetDiscontinuity(m_iFrameNumber <= 1); // the swprintf costs like 0.04ms (25000 fps LOL) m_fFpsSinceBeginningOfTime = ((double) m_iFrameNumber)/(GetTickCount() - globalStart)*1000; swprintf(out, L"done frame! total frames: %d this one %dx%d -> (%dx%d) took: %.02Lfms, %.02f ave fps (%.02f is the theoretical max fps based on this round, ave. possible fps %.02f, fastest round fps %.02f, negotiated fps %.06f), frame missed %d", m_iFrameNumber, m_iCaptureConfigHeight, m_iCaptureConfigWidth, getNegotiatedFinalWidth(), getNegotiatedFinalHeight(), millisThisRoundTook, m_fFpsSinceBeginningOfTime, 1.0*1000/millisThisRoundTook, /* average */ 1.0*1000*m_iFrameNumber/sumMillisTook, 1.0*1000/fastestRoundMillis, GetFps(), countMissed); //#ifdef _DEBUG // probably not worth it but we do hit this a lot...hmm... LocalOutput(out); set_config_string_setting(L"frame_stats", out); //#endif return S_OK; }
// the default child constructor... CPushPinDesktop::CPushPinDesktop(HRESULT *phr, CPushSourceDesktop *pFilter) : CSourceStream(NAME("Push Source CPushPinDesktop child/pin"), phr, pFilter, L"Capture"), m_FramesWritten(0), m_bReReadRegistry(0), m_bDeDupe(0), m_iFrameNumber(0), pOldData(NULL), m_bConvertToI420(false), //m_nCurrentBitDepth(32), // negotiated later... m_pParent(pFilter), m_bFormatAlreadySet(false), hRawBitmap(NULL) { // Get the device context of the main display, just to get some metrics for it... globalStart = GetTickCount(); m_iHwndToTrack = (HWND) read_config_setting(TEXT("hwnd_to_track"), NULL); hScrDc = GetDC(m_iHwndToTrack); m_iScreenBitDepth = GetTrueScreenDepth(hScrDc); ASSERT(hScrDc != 0); GdiSetBatchLimit(1); // disable any GDI...just in case this helps anybody... // Get the dimensions of the main desktop window as the default m_rScreen.left = m_rScreen.top = 0; m_rScreen.right = GetDeviceCaps(hScrDc, HORZRES); // NB this *fails* for dual monitor support currently... but we just get the wrong width by default, at least with aero windows 7 both can capture both monitors m_rScreen.bottom = GetDeviceCaps(hScrDc, VERTRES); // now read some custom settings... WarmupCounter(); reReadCurrentPosition(0); int config_width = read_config_setting(TEXT("capture_width"), 0); ASSERT(config_width >= 0); // negatives not allowed... int config_height = read_config_setting(TEXT("capture_height"), 0); ASSERT(config_height >= 0); // negatives not allowed, if it's set :) if(config_width > 0) { int desired = m_rScreen.left + config_width; //int max_possible = m_rScreen.right; // disabled check until I get dual monitor working. or should I allow off screen captures anyway? //if(desired < max_possible) m_rScreen.right = desired; //else // m_rScreen.right = max_possible; } else { // leave full screen } m_iCaptureConfigWidth = m_rScreen.right - m_rScreen.left; ASSERT(m_iCaptureConfigWidth > 0); if(config_height > 0) { int desired = m_rScreen.top + config_height; //int max_possible = m_rScreen.bottom; // disabled, see above. //if(desired < max_possible) m_rScreen.bottom = desired; //else // m_rScreen.bottom = max_possible; } else { // leave full screen } m_iCaptureConfigHeight = m_rScreen.bottom - m_rScreen.top; ASSERT(m_iCaptureConfigHeight > 0); m_iStretchToThisConfigWidth = read_config_setting(TEXT("stretch_to_width"), 0); m_iStretchToThisConfigHeight = read_config_setting(TEXT("stretch_to_height"), 0); m_iStretchMode = read_config_setting(TEXT("stretch_mode_high_quality_if_1"), 0); ASSERT(m_iStretchToThisConfigWidth >= 0 && m_iStretchToThisConfigHeight >= 0 && m_iStretchMode >= 0); // sanity checks // default 30 fps...hmm... int config_max_fps = read_config_setting(TEXT("default_max_fps"), 30); // TODO allow floats [?] when ever requested ASSERT(config_max_fps >= 0); // m_rtFrameLength is also re-negotiated later... m_rtFrameLength = UNITS / config_max_fps; if(is_config_set_to_1(TEXT("track_new_x_y_coords_each_frame_if_1"))) { m_bReReadRegistry = 1; // takes 0.416880ms, but I thought it took more when I made it off by default :P } if(is_config_set_to_1(TEXT("dedup_if_1"))) { m_bDeDupe = 1; // takes 10 or 20ms...but useful to me! :) } m_millisToSleepBeforePollForChanges = read_config_setting(TEXT("millis_to_sleep_between_poll_for_dedupe_changes"), 10); wchar_t out[1000]; swprintf(out, 1000, L"default/from reg read config as: %dx%d -> %dx%d (%dtop %db %dl %dr) %dfps, dedupe? %d, millis between dedupe polling %d, m_bReReadRegistry? %d \n", m_iCaptureConfigHeight, m_iCaptureConfigWidth, getCaptureDesiredFinalHeight(), getCaptureDesiredFinalWidth(), m_rScreen.top, m_rScreen.bottom, m_rScreen.left, m_rScreen.right, config_max_fps, m_bDeDupe, m_millisToSleepBeforePollForChanges, m_bReReadRegistry); LocalOutput(out); // warmup for the below debug :) __int64 measureDebugOutputSpeed = StartCounter(); LocalOutput(out); LocalOutput("writing a large-ish debug itself took: %.0Lf ms", GetCounterSinceStartMillis(measureDebugOutputSpeed)); // does this work with flash? set_config_string_setting(L"last_init_config_was", out); }
// the default child constructor... CPushPinDesktop::CPushPinDesktop(HRESULT *phr, CPushSourceDesktop *pFilter) : CSourceStream(NAME("Push Source CPushPinDesktop child/pin"), phr, pFilter, L"Capture"), m_bReReadRegistry(0), m_bDeDupe(0), m_iFrameNumber(0), pOldData(NULL), m_bConvertToI420(false), m_pParent(pFilter), m_bFormatAlreadySet(false), hRawBitmap(NULL), m_bUseCaptureBlt(false), previousFrameEndTime(0) { // Get the device context of the main display, just to get some metrics for it... globalStart = GetTickCount(); m_iHwndToTrack = (HWND) read_config_setting(TEXT("hwnd_to_track"), NULL, false); if(m_iHwndToTrack) { LocalOutput("using specified hwnd no decoration: %d", m_iHwndToTrack); hScrDc = GetDC(m_iHwndToTrack); // using GetDC here seemingly allows you to capture "just a window" without decoration m_bHwndTrackDecoration = false; } else { m_iHwndToTrack = (HWND) read_config_setting(TEXT("hwnd_to_track_with_window_decoration"), NULL, false); if(m_iHwndToTrack) { LocalOutput("using specified hwnd with decoration: %d", m_iHwndToTrack); hScrDc = GetWindowDC(m_iHwndToTrack); m_bHwndTrackDecoration = true; } else { int useForeGroundWindow = read_config_setting(TEXT("capture_foreground_window_if_1"), 0, true); if(useForeGroundWindow) { LocalOutput("using foreground window %d", GetForegroundWindow()); hScrDc = GetDC(GetForegroundWindow()); } else { // the default, just capture desktop // hScrDc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); // possibly better than GetDC(0), supposed to be multi monitor? // LocalOutput("using the dangerous CreateDC DISPLAY\n"); // danger, CreateDC DC is only good as long as this particular thread is still alive...hmm...is it better for directdraw hScrDc = GetDC(NULL); } } } //m_iScreenBitDepth = GetTrueScreenDepth(hScrDc); ASSERT_RAISE(hScrDc != 0); // 0 implies failure... [if using hwnd, can mean the window is gone!] // Get the dimensions of the main desktop window as the default m_rScreen.left = m_rScreen.top = 0; m_rScreen.right = GetDeviceCaps(hScrDc, HORZRES); // NB this *fails* for dual monitor support currently... but we just get the wrong width by default, at least with aero windows 7 both can capture both monitors m_rScreen.bottom = GetDeviceCaps(hScrDc, VERTRES); // now read some custom settings... WarmupCounter(); if(!m_iHwndToTrack) { reReadCurrentStartXY(0); } else { LocalOutput("ignoring startx, starty since hwnd was specified"); } int config_width = read_config_setting(TEXT("capture_width"), 0, false); ASSERT_RAISE(config_width >= 0); // negatives not allowed... int config_height = read_config_setting(TEXT("capture_height"), 0, false); ASSERT_RAISE(config_height >= 0); // negatives not allowed, if it's set :) if(config_width > 0) { int desired = m_rScreen.left + config_width; //int max_possible = m_rScreen.right; // disabled check until I get dual monitor working. or should I allow off screen captures anyway? //if(desired < max_possible) m_rScreen.right = desired; //else // m_rScreen.right = max_possible; } else { // leave full screen } m_iCaptureConfigWidth = m_rScreen.right - m_rScreen.left; ASSERT_RAISE(m_iCaptureConfigWidth > 0); if(config_height > 0) { int desired = m_rScreen.top + config_height; //int max_possible = m_rScreen.bottom; // disabled, see above. //if(desired < max_possible) m_rScreen.bottom = desired; //else // m_rScreen.bottom = max_possible; } else { // leave full screen } m_iCaptureConfigHeight = m_rScreen.bottom - m_rScreen.top; ASSERT_RAISE(m_iCaptureConfigHeight > 0); m_iStretchToThisConfigWidth = read_config_setting(TEXT("stretch_to_width"), 0, false); m_iStretchToThisConfigHeight = read_config_setting(TEXT("stretch_to_height"), 0, false); m_iStretchMode = read_config_setting(TEXT("stretch_mode_high_quality_if_1"), 0, true); // guess it's either stretch mode 0 or 1 ASSERT_RAISE(m_iStretchToThisConfigWidth >= 0 && m_iStretchToThisConfigHeight >= 0 && m_iStretchMode >= 0); // sanity checks m_bUseCaptureBlt = read_config_setting(TEXT("capture_transparent_windows_including_mouse_in_non_aero_if_1_causes_annoying_mouse_flicker"), 0, true) == 1; m_bCaptureMouse = read_config_setting(TEXT("capture_mouse_default_1"), 1, true) == 1; // default 30 fps...hmm... int config_max_fps = read_config_setting(TEXT("default_max_fps"), 30, false); // TODO allow floats [?] when ever requested ASSERT_RAISE(config_max_fps > 0); // m_rtFrameLength is also re-negotiated later... m_rtFrameLength = UNITS / config_max_fps; if(is_config_set_to_1(TEXT("track_new_x_y_coords_each_frame_if_1"))) { m_bReReadRegistry = 1; // takes 0.416880ms, but I thought it took more when I made it off by default :P } if(is_config_set_to_1(TEXT("dedup_if_1"))) { m_bDeDupe = 1; // takes 10 or 20ms...but useful to me! :) } m_millisToSleepBeforePollForChanges = read_config_setting(TEXT("millis_to_sleep_between_poll_for_dedupe_changes"), 10, true); wchar_t out[10000]; swprintf(out, 10000, L"default/from reg read config as: %dx%d -> %dx%d (%d top %d bottom %d l %d r) %dfps, dedupe? %d, millis between dedupe polling %d, m_bReReadRegistry? %d hwnd:%d \n", m_iCaptureConfigHeight, m_iCaptureConfigWidth, getCaptureDesiredFinalHeight(), getCaptureDesiredFinalWidth(), m_rScreen.top, m_rScreen.bottom, m_rScreen.left, m_rScreen.right, config_max_fps, m_bDeDupe, m_millisToSleepBeforePollForChanges, m_bReReadRegistry, m_iHwndToTrack); // warmup the debugging message system __int64 measureDebugOutputSpeed = StartCounter(); LocalOutput(out); LocalOutput("writing a large-ish debug itself took: %.02Lf ms", GetCounterSinceStartMillis(measureDebugOutputSpeed)); set_config_string_setting(L"last_init_config_was", out); }
HRESULT CPushPinDesktop::FillBuffer(IMediaSample *pSample) { LocalOutput("video frame requested"); __int64 startThisRound = StartCounter(); BYTE *pData; CheckPointer(pSample, E_POINTER); if(m_bReReadRegistry) { reReadCurrentStartXY(1); } if(!ever_started) { // allow it to startup until Run is called...so StreamTime can work see http://stackoverflow.com/questions/2469855/how-to-get-imediacontrol-run-to-start-a-file-playing-with-no-delay/2470548#2470548 // since StreamTime anticipates that the graph's start time has already been set FILTER_STATE myState; CSourceStream::m_pFilter->GetState(INFINITE, &myState); while(myState != State_Running) { // TODO accomodate for pausing better, we're single run only currently [does VLC do pausing even?] Sleep(1); LocalOutput("sleeping till graph running for audio..."); m_pParent->GetState(INFINITE, &myState); } ever_started = true; } // Access the sample's data buffer pSample->GetPointer(&pData); // Make sure that we're still using video format ASSERT_RETURN(m_mt.formattype == FORMAT_VideoInfo); VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*) m_mt.pbFormat; boolean gotNew = false; // dedupe stuff while(!gotNew) { CopyScreenToDataBlock(hScrDc, pData, (BITMAPINFO *) &(pVih->bmiHeader), pSample); if(m_bDeDupe) { if(memcmp(pData, pOldData, pSample->GetSize())==0) { // took desktop: 10ms for 640x1152, still 100 fps uh guess... Sleep(m_millisToSleepBeforePollForChanges); } else { gotNew = true; memcpy( /* dest */ pOldData, pData, pSample->GetSize()); // took 4ms for 640x1152, but it's worth it LOL. // LODO memcmp and memcpy in the same loop LOL. } } else { // it's always new for everyone else (the typical case) gotNew = true; } } // capture some debug stats (how long it took) before we add in our own arbitrary delay to enforce fps... long double millisThisRoundTook = GetCounterSinceStartMillis(startThisRound); fastestRoundMillis = min(millisThisRoundTook, fastestRoundMillis); // keep stats :) sumMillisTook += millisThisRoundTook; CRefTime now; CRefTime endFrame; now = 0; CSourceStream::m_pFilter->StreamTime(now); if((now > 0) && (now < previousFrameEndTime)) { // now > 0 to accomodate for if there is no reference graph clock at all...also at boot strap time to ignore it XXXX can negatives even ever happen anymore though? while(now < previousFrameEndTime) { // guarantees monotonicity too :P LocalOutput("sleeping because %llu < %llu", now, previousFrameEndTime); Sleep(1); CSourceStream::m_pFilter->StreamTime(now); } // avoid a tidge of creep since we sleep until [typically] just past the previous end. endFrame = previousFrameEndTime + m_rtFrameLength; previousFrameEndTime = endFrame; } else { // if there's no reference clock, it will "always" think it missed a frame if(show_performance) { if(now == 0) LocalOutput("probable none reference clock, streaming fastly"); else LocalOutput("it missed a frame--can't keep up %d %llu %llu", countMissed++, now, previousFrameEndTime); // we don't miss time typically I don't think, unless de-dupe is turned on, or aero, or slow computer, buffering problems downstream, etc. } // have to add a bit here, or it will always be "it missed a frame" for the next round...forever! endFrame = now + m_rtFrameLength; // most of this stuff I just made up because it "sounded right" //LocalOutput("checking to see if I can catch up again now: %llu previous end: %llu subtr: %llu %i", now, previousFrameEndTime, previousFrameEndTime - m_rtFrameLength, previousFrameEndTime - m_rtFrameLength); if(now > (previousFrameEndTime - (long long) m_rtFrameLength)) { // do I even need a long long cast? // let it pretend and try to catch up, it's not quite a frame behind previousFrameEndTime = previousFrameEndTime + m_rtFrameLength; } else { endFrame = now + m_rtFrameLength/2; // ?? seems to not hurt, at least...I guess previousFrameEndTime = endFrame; } } // accomodate for 0 to avoid startup negatives, which would kill our math on the next loop... previousFrameEndTime = max(0, previousFrameEndTime); pSample->SetTime((REFERENCE_TIME *) &now, (REFERENCE_TIME *) &endFrame); //pSample->SetMediaTime((REFERENCE_TIME *)&now, (REFERENCE_TIME *) &endFrame); LocalOutput("timestamping video packet as %lld -> %lld", now, endFrame); m_iFrameNumber++; // Set TRUE on every sample for uncompressed frames http://msdn.microsoft.com/en-us/library/windows/desktop/dd407021%28v=vs.85%29.aspx pSample->SetSyncPoint(TRUE); // only set discontinuous for the first...I think... pSample->SetDiscontinuity(m_iFrameNumber <= 1); #ifdef _DEBUG // the swprintf costs like 0.04ms (25000 fps LOL) double m_fFpsSinceBeginningOfTime = ((double) m_iFrameNumber)/(GetTickCount() - globalStart)*1000; swprintf(out, L"done video frame! total frames: %d this one %dx%d -> (%dx%d) took: %.02Lfms, %.02f ave fps (%.02f is the theoretical max fps based on this round, ave. possible fps %.02f, fastest round fps %.02f, negotiated fps %.06f), frame missed %d", m_iFrameNumber, m_iCaptureConfigHeight, m_iCaptureConfigWidth, getNegotiatedFinalWidth(), getNegotiatedFinalHeight(), millisThisRoundTook, m_fFpsSinceBeginningOfTime, 1.0*1000/millisThisRoundTook, /* average */ 1.0*1000*m_iFrameNumber/sumMillisTook, 1.0*1000/fastestRoundMillis, GetFps(), countMissed); LocalOutput(out); set_config_string_setting(L"frame_stats", out); #endif return S_OK; }
/* void ReadEIP(PEIP_RECORD pRecord) { W32 high, low, i, top; rdmsr(0x1da, low, high); top = low; for(i = 0; i < MAX_EIP_NUM; i++) { top = (top+i) % MAX_EIP_NUM; rdmsr(0x680+top, low, high); pRecord->eipFrom[i] = ((W64)high << 32) | low; rdmsr(0x6c0+top, low, high); pRecord->eipTo[i] = ((W64)high << 32) | low; } } */ int CollectSampling(void) { int cpuId; //W32 low, high; SAMPLE_RECORD record; PROFILING_RECORD profiling; unsigned long irqFlags; #ifdef DBG W32 i; #endif W64 *pointer; //if (counterPackage.eipNum > 0) //{ //stop branch recording // rdmsr(0x1d9, low, high); // low &= 0xfffffffe; // wrmsr(0x1d9, low, high); // //} cpuId = smp_processor_id(); #ifdef DBG printk("collect sampling on core %d\n", cpuId); #endif StopCounter(&counterPackage); //rdtsc(low, high); //record.sampleHeader.rdtsc = (((W64)high)<<32) | low; record.sampleHeader.rdtsc = __native_read_tsc(); record.sampleHeader.sampleId = sampleId; record.sampleHeader.cpuId = cpuId; ReadCounter(&counterPackage, &record); #ifdef DBG pointer = (W64*)(current->thread.sp0); printk("a-------------------------------------------------------------\n"); for(i = 0; i < 8; i++) { //eipRecord.eipFrom[i] = (*pointer); printk("Addr %p: %p\n", pointer, (*pointer)); pointer--; //eipRecord.eipTo[i] = (*pointer); printk("Addr %p: %p\n", pointer, (*pointer)); pointer--; } printk("b-------------------------------------------------------------\n"); //printk("rsp: %p\n",curThread.rsp); //printk("rsp0: %p\n",curThread.rsp0); #endif if (counterPackage.profiling > 0) { pointer = (W64*)(current->thread.sp0); profiling.pid = (W64)current->pid; pointer -= 5; profiling.eip = (*pointer); /* if(sampleId == 0) { printk("cpuId: %d eip: %p\n", cpuId, profiling.eip); printk("pid: %u\n", profiling.pid); } */ } spin_lock_irqsave(&buffer_lock, irqFlags); #ifdef DBG printk("%d cpu get spinlock and write %d bytes to buffer\n", cpuId, sizeof(SAMPLE_HEADER) + sizeof(W64) * counterPackage.usedNum); #endif AddSampleToBuff(&record, sizeof(SAMPLE_HEADER) + sizeof(W64) * counterPackage.usedNum); if (counterPackage.profiling > 0) { AddSampleToBuff(&profiling, sizeof(PROFILING_RECORD)); } spin_unlock_irqrestore(&buffer_lock, irqFlags); //start branch recording //rdmsr(0x1d9, low, high); //low |= 1; //wrmsr(0x1d9, low, high); // #ifdef USE_NMI WRITEMSR(INS_FIXED_COUNTER, COUNTER_OVERFLOW); #endif StartCounter(&counterPackage); return 0; }
void MotionCooccurrenceHistogram::Extract(const string& video_path, MotionCooccurrenceHistogram::eMotionCooccurrenceType cType, int nFrameSkip, int nFrameHistory) { vector<vector<double> > vHistNor; vector<vector<double> > vecMotionVel, vecMotionAngle; vector<vector<pair<int, int> > > vecMotionPosStart, vecMotionPosEnd; vector<int> vec_nFrameID; // Frame history value m_nFrameHistory = nFrameHistory; // Define the length of diagonal m_dDiagLength = 400; MotionVectorExtractor m; // Extract motion vector with respect to the given parameters m.Extract(video_path, MotionVectorExtractor::MOTION_OPTICAL_FLOW_BM, 0); // Get motion vectors to calculate histograms m.GetFeature(vecMotionVel, vecMotionAngle, vecMotionPosStart, vecMotionPosEnd, vec_nFrameID); /* // Write motion vectors to the file ofstream outMotionVel("outMotionVel.txt", iostream::app); ofstream outMotionAngle("outMotionAngle.txt", iostream::app); for (unsigned int i = 0; i < vecMotionVel.size(); i++) { for (unsigned int j = 0; j < vecMotionVel[i].size(); j++) { outMotionVel << vecMotionVel[i][j] << endl; outMotionAngle << vecMotionAngle[i][j] << endl; } } outMotionVel.close(); outMotionAngle.close(); */ StartCounter(); if (cType == MotionCooccurrenceHistogram::MOTION_COOCCURRENCE_ANGLE) { vector<map<pair<int, int>, int> > vPositionAngle; // Holds position and quantized angle bin for each frame vector<vector<double> > vHistTemp; int nAngleBin; for (unsigned int f = 0; f<vecMotionAngle.size(); f++) { map<pair<int, int>, int> mPositionAngleTemp; for (unsigned int m = 0; m<vecMotionAngle[f].size(); m++) { nAngleBin = QuantizeMotionAngle(vecMotionAngle[f][m]); mPositionAngleTemp.insert(pair<pair<int, int>, int>(vecMotionPosStart[f][m], nAngleBin)); } vPositionAngle.push_back(mPositionAngleTemp); } MotionAngleCooccurrence(vPositionAngle, nFrameSkip, vHistTemp); NormalizeHistogram(vHistTemp, vHistNor); } else if (cType == MotionCooccurrenceHistogram::MOTION_COOCCURRENCE_VELOCITY) { vector<map<pair<int, int>, int> > vPositionVelocity; // Holds position and quantized angle bin for each frame vector<vector<double> > vHistTemp; int nVelocityBin; double unitTime; unitTime = 0.04; for (unsigned int f = 0; f<vecMotionVel.size(); f++) { map<pair<int, int>, int> mPositionVelocityTemp; for (unsigned int m = 0; m<vecMotionVel[f].size(); m++) { nVelocityBin = QuantizeMotionVelocity(vecMotionVel[f][m], unitTime); mPositionVelocityTemp.insert(pair<pair<int, int>, int>(vecMotionPosStart[f][m], nVelocityBin)); } vPositionVelocity.push_back(mPositionVelocityTemp); } MotionVelocityCooccurrence(vPositionVelocity, nFrameSkip, vHistTemp); //vHistNor = vHistTemp; NormalizeHistogram(vHistTemp, vHistNor); } else if (cType == MotionCooccurrenceHistogram::MOTION_COOCCURRENCE_ANGLE_VELOCITY) { vector<vector<double> > vAngleHistTemp, vVelocityHistTemp; vector<vector<double> > vAngleHistNor, vVelocityHistNor; vector<map<pair<int, int>, int> > vPositionAngle, vPositionVelocity; int nAngleBin, nVelocityBin; double unitTime; unitTime = 0.04; // Quantize angle and velocity for (unsigned int f = 0; f<vecMotionAngle.size(); f++) { map<pair<int, int>, int> mPositionAngleTemp, mPositionVelocityTemp; for (unsigned int m = 0; m<vecMotionAngle[f].size(); m++) { nAngleBin = QuantizeMotionAngle(vecMotionAngle[f][m]); mPositionAngleTemp.insert(pair<pair<int, int>, int>(vecMotionPosStart[f][m], nAngleBin)); nVelocityBin = QuantizeMotionVelocity(vecMotionVel[f][m], unitTime); mPositionVelocityTemp.insert(pair<pair<int, int>, int>(vecMotionPosStart[f][m], nVelocityBin)); } vPositionAngle.push_back(mPositionAngleTemp); vPositionVelocity.push_back(mPositionVelocityTemp); } // Extract MCFs wrt position-angle and position-velocity MotionAngleCooccurrence(vPositionAngle, nFrameSkip, vAngleHistTemp); //vAngleHistNor = vAngleHistTemp; NormalizeHistogram(vAngleHistTemp, vAngleHistNor); MotionVelocityCooccurrence(vPositionVelocity, nFrameSkip, vVelocityHistTemp); //vVelocityHistNor = vVelocityHistTemp; NormalizeHistogram(vVelocityHistTemp, vVelocityHistNor); for (unsigned int j = 0; j<vAngleHistNor.size(); j++) { vector<double> vFeature; vFeature = vAngleHistNor[j]; vFeature.insert(vFeature.end(), vVelocityHistNor[j].begin(), vVelocityHistNor[j].end()); vHistNor.push_back(vFeature); } } m_vMCH_Video = vHistNor; m_vFrameID = vec_nFrameID; dElapsedTime = GetCounter(); }
void CEnvHudCounter::InputStartCounter( inputdata_t &inputdata ) { StartCounter(); m_OnCounterStarted.FireOutput( this, this ); }
void CEnvHudCounter::ResumeCounter() { m_bPaused = false; StartCounter( true ); }
// This is where we insert the DIB bits into the video stream. // FillBuffer is called once for every sample in the stream. HRESULT CPushPinDesktop::FillBuffer(IMediaSample *pSample) { __int64 startThisRound = StartCounter(); BYTE *pData; long cbData; CheckPointer(pSample, E_POINTER); // Access the sample's data buffer pSample->GetPointer(&pData); cbData = pSample->GetSize(); // Make sure that we're still using video format ASSERT(m_mt.formattype == FORMAT_VideoInfo); VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)m_mt.pbFormat; // Copy the DIB bits over into our filter's output buffer. // Since sample size may be larger than the image size, bound the copy size. int nSize = min(pVih->bmiHeader.biSizeImage, (DWORD) cbData); // cbData is the size of pData HDIB hDib = CopyScreenToBitmap(hScrDc, &m_rScreen, pData, (BITMAPINFO *) &(pVih->bmiHeader)); if (hDib) DeleteObject(hDib); // for some reason the timings are messed up initially, as there's no start time. // race condition? // so don't count them unless they seem valid... FILTER_STATE myState; CSourceStream::m_pFilter->GetState(INFINITE, &myState); bool fullyStarted = myState == State_Running; CRefTime now; CSourceStream::m_pFilter->StreamTime(now); // calculate how long it took before we add in our own arbitrary delay to enforce fps... long double millisThisRoundTook = GetCounterSinceStartMillis(startThisRound); // wait until we "should" send this frame out...TODO...more precise et al... if(m_iFrameNumber > 0 && (now > 0)) { // now > 0 to accomodate for if there is no clock at all... while(now < previousFrameEndTime) { // guarantees monotonicity too :P Sleep(1); CSourceStream::m_pFilter->StreamTime(now); } } REFERENCE_TIME endFrame = now + m_rtFrameLength; pSample->SetTime((REFERENCE_TIME *) &now, &endFrame); if(fullyStarted) m_iFrameNumber++; // Set TRUE on every sample for uncompressed frames pSample->SetSyncPoint(TRUE); // only set discontinuous for the first...I think... pSample->SetDiscontinuity(m_iFrameNumber == 1); double fpsSinceBeginningOfTime = ((double) m_iFrameNumber)/(GetTickCount() - globalStart)*1000; LocalOutput("end total frames %d %.020Lfms, total since beginning of time %f fps (theoretical max fps %f)", m_iFrameNumber, millisThisRoundTook, fpsSinceBeginningOfTime, 1.0*1000/millisThisRoundTook); previousFrameEndTime = endFrame; return S_OK; }
double Object::InitializeGPUArrays(bool _log) { if (m_bInitializedGPU) { Logw("Object::SetupGPUArrays(): ERROR: GPU arrays already initialized\n"); return (1.0); } __int64 t0 = StartCounter(); // Create and bind vertex array glGenVertexArrays(1, &m_vaoObject); glError("Object::SetupGPUArrays()", "glGenVertexArrays() m_vaoObject"); glBindVertexArray(m_vaoObject); glError("Object::SetupGPUArrays()", "glBindVertexArray() m_vaoObject"); // Create and bind vertex and index buffers (init with NULL) // vertex buffer glGenBuffers(1, &m_vboObjectVertices); glError("Object::SetupGPUArrays()", "glGenBuffers() m_vboObjectVertices"); glBindBuffer(GL_ARRAY_BUFFER, m_vboObjectVertices); glError("Object::SetupGPUArrays()", "glBindBuffer() m_vboObjectVertices"); glBufferData(GL_ARRAY_BUFFER, sizeof(GLvertex) * m_nVertices, NULL, GL_STATIC_DRAW); glError("Object::SetupGPUArrays()", "glBufferData() GL_ARRAY_BUFFER"); // index buffer glGenBuffers(1, &m_iboObject); glError("Object::SetupGPUArrays()", "glGenBuffers() m_iboObject"); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_iboObject); glError("Object::SetupGPUArrays()", "glBindBuffer() m_iboObject"); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * m_nIndices, NULL, GL_STATIC_DRAW); glError("Object::SetupGPUArrays()", "glBufferData() GL_ELEMENT_ARRAY_BUFFER"); // set vertex attributes according to shader flags // positions (default) if (m_vertexFlags & VERTEX_POSITION) { GLint aPos = m_pShaderProgram->GetAttribute("attributePosition"); glEnableVertexAttribArray(aPos); glVertexAttribPointer(aPos, 3, GL_FLOAT, GL_FALSE, sizeof(GLvertex), (GLvoid *)0); glError("Object::InitializeGPUArrays()", "glVertexAttribPointer(): VERTEX_POSITION"); } // normals if (m_vertexFlags & VERTEX_NORMAL) { GLint aNorm = m_pShaderProgram->GetAttribute("attributeNormal"); glEnableVertexAttribArray(aNorm); glVertexAttribPointer(aNorm, 3, GL_FLOAT, GL_FALSE, sizeof(GLvertex), (GLvoid *)offsetof(GLvertex, normal)); glError("Object::InitializeGPUArrays()", "glVertexAttribPointer(): VERTEX_TEXCOORD"); } // texture coordinates if (m_vertexFlags & VERTEX_TEXCOORD) { GLint aTexCoord = m_pShaderProgram->GetAttribute("attributeTexCoord"); glEnableVertexAttribArray(aTexCoord); glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, GL_FALSE, sizeof(GLvertex), (GLvoid *)offsetof(GLvertex, texCoord)); glError("Object::InitializeGPUArrays()", "glVertexAttribPointer(): VERTEX_TEXCOORD"); // is there a texture associated with this Object? if (m_texture.m_pTexture) { // setup basic texture parameters GLuint id; glGenTextures(1, &id); glError("Object::InitializeGPUArrays()", "glGenTextures() id"); glBindTexture(m_texture.m_eTextureType, id); glError("Object::InitializeGPUArrays()", "glBindTexture() id"); // update id in the texture (now set from Object instead of from Texture) m_texture.m_pTexture->SetTextureID(id); // trivial pixel format search GLtextureFormat format = m_texture.m_pTexture->TextureFormat(); //Logw("\nFormat = internal: %d (%s)\tserver: %d (%s)\n\n", format.texInternalFormat, (format.texInternalFormat == GL_RGB ? "GL_RGB" : "dunno"), format.texServerFormat, (format.texServerFormat == GL_RGB ? "GL_RGB" : "dunno")); // create an empty texture server-side of correct dimensions switch (m_texture.m_eTextureType) { case GL_TEXTURE_1D: glTexImage1D(m_texture.m_eTextureType, 0, format.texInternalFormat, m_texture.m_pTexture->TexWidth(), 0, format.texServerFormat, GL_UNSIGNED_BYTE, 0); glError("Object::SetupGPUArrays()", "glTexImage1D()"); break; case GL_TEXTURE_2D: glTexImage2D(m_texture.m_eTextureType, 0, format.texInternalFormat, m_texture.m_pTexture->TexWidth(), m_texture.m_pTexture->TexHeight(), 0, format.texServerFormat, GL_UNSIGNED_BYTE, 0); glError("Object::SetupGPUArrays()", "glTexImage2D()"); break; case GL_TEXTURE_3D: glTexImage3D(m_texture.m_eTextureType, 0, format.texInternalFormat, m_texture.m_pTexture->TexWidth(), m_texture.m_pTexture->TexHeight(), m_texture.m_pTexture->TexDepth(), 0, format.texServerFormat, GL_UNSIGNED_BYTE, 0); glError("Object::SetupGPUArrays()", "glTexImage3D()"); break; } // Set texture parameters GLtextureParameters param = m_texture.m_pTexture->TextureParameters(); glGenerateMipmap(m_texture.m_eTextureType); glError("Object::SetupGPUArrays()", "glGenerateMipmap()"); glTexParameteri(m_texture.m_eTextureType, GL_TEXTURE_WRAP_S, param.texParameterWrapS); glError("Object::SetupGPUArrays()", "glTexParameteri() param.texParameterWrapS"); if (m_texture.m_eTextureType == GL_TEXTURE_2D) { glTexParameteri(m_texture.m_eTextureType, GL_TEXTURE_WRAP_T, param.texParameterWrapT); glError("Object::SetupGPUArrays()", "glTexParameteri() param.texParameterWrapS"); } if (m_texture.m_eTextureType == GL_TEXTURE_3D) { glTexParameteri(m_texture.m_eTextureType, GL_TEXTURE_WRAP_T, param.texParameterWrapT); glError("Object::SetupGPUArrays()", "glTexParameteri() param.texParameterWrapT"); glTexParameteri(m_texture.m_eTextureType, GL_TEXTURE_WRAP_R, param.texParameterWrapR); glError("Object::SetupGPUArrays()", "glTexParameteri() param.texParameterWrapR"); } glTexParameteri(m_texture.m_eTextureType, GL_TEXTURE_MIN_FILTER, param.texParameterMinFilter); glError("Object::SetupGPUArrays()", "glTexParameteri() param.texParameterMinFilter"); glTexParameteri(m_texture.m_eTextureType, GL_TEXTURE_MAG_FILTER, param.texParameterMagFilter); glError("Object::SetupGPUArrays()", "glTexParameteri() param.texParameterMagFilter"); // unbind texture glBindTexture(m_texture.m_eTextureType, 0); } } // set flag m_bInitializedGPU = true; // update render function m_pRenderFunc = &Object::RenderVertices; if (_log) Logw("Object::SetupGPUArrays(): Frame %llu: GPU arrays and vertex attributes setup for object '%s' in %.4f ms\n", g_lFrame, m_objectName.c_str(), GetElapsed(t0)); // return execution time return (GetElapsed(t0)); } // end Object::SetupGPUArrays()
//....................................................................................... void vxCube::LoadThreaded(bool _log, ThreadStatus *_status) { _status->status = ThreadStatusEnum::THREAD_RUNNING; _status->message = "Object '" + m_objectName + "': initializing"; _status->progress = 0.0f; __int64 t0 = StartCounter(); // chech for vertex flags float normals = (m_vertexFlags & VERTEX_NORMAL ? 1.0f : 0.0f); float texcoords = (m_vertexFlags & VERTEX_TEXCOORD ? 1.0f : 0.0f); // vertex data GLvertex vertices[] = { // front GLvertex(Vector3f(-0.5f, -0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, -0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, -0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), // back GLvertex(Vector3f(-0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, 0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), // left GLvertex(Vector3f(-0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, -0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, 0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), // right GLvertex(Vector3f( 0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, -0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), // top GLvertex(Vector3f(-0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, 0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, 0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), // bottom GLvertex(Vector3f(-0.5f, -0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, -0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, -0.5f, -0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f(-0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords), GLvertex(Vector3f( 0.5f, -0.5f, 0.5f), Vector3f() * normals, Vector2f() * texcoords) }; unsigned int indices[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 }; // initialize vertices and indices m_nVertices = sizeof(vertices) / sizeof(GLvertex); m_nIndices = sizeof(indices) / sizeof(unsigned int); m_pVertices = (GLvertex *)malloc(sizeof(GLvertex) * m_nVertices); m_pIndices = (unsigned int *)malloc(sizeof(unsigned int) * m_nIndices); m_nVerticesLeft = m_nVertices; m_nIndicesLeft = m_nIndices; // set texture counters, if any if (m_texture.m_pTexture) { m_nTextureBytes = m_texture.m_pTexture->SizeBytes(); m_nTextureBytesLeft = m_nTextureBytes; } // copy the data memcpy(m_pVertices, vertices, sizeof(GLvertex) * m_nVertices); memcpy(m_pIndices, indices, sizeof(unsigned int) * m_nIndices); if (_log) { Logw("vxCube::LoadThreaded(): Frame %llu: vxCube intialized (%d vertices, %d indices) in %.4f ms\n", g_lFrame, m_nVertices, m_nIndices, GetElapsed(t0)); } // update flags m_bObjectLoadedRAM = true; // done _status->message = "Object '" + m_objectName + "': done"; _status->progress = 100.0f; _status->status = ThreadStatusEnum::THREAD_FINISHED; }
int Font::InitializeAtlas(const char *_filename, int _pixel_size) { __int64 t0 = StartCounter(); m_iPixelSize = _pixel_size; // Load the text rendering shaders if (m_bCreateShaders) { m_pProgram = new GLSLProgram("FontGLSL", "./GLSL/font_vertex.glsl", "./GLSL/font_fragment.glsl"); m_fontProgramID = m_pProgram->ProgramID(); } // Use program for initiation of shader attributes glUseProgram(m_fontProgramID); m_pProgram->AddVariable(GLSL_ATTRIBUTE, "attributeCoord", "coord"); m_pProgram->AddVariable(GLSL_UNIFORM, "uniformColor", "color"); m_pProgram->AddVariable(GLSL_UNIFORM, "uniformTex", "tex"); m_pProgram->FinalizeProgram(); m_attributeCoord = m_pProgram->GetLocation(GLSL_ATTRIBUTE, "attributeCoord"); m_uniformTex = m_pProgram->GetLocation(GLSL_UNIFORM, "uniformTex"); m_uniformColor = m_pProgram->GetLocation(GLSL_UNIFORM, "uniformColor"); // Init the FreeType lib if (m_bVerbose) Logw("Font::InitializeAtlas(): FreeType initialization "); if (FT_Init_FreeType(&m_ftLib)) { if (m_bVerbose) Logw("(FAILURE)\n"); //else Logw("Font::InitializeAtlas(): FreeType initialization failed.\n"); return (RETURN_FAILURE); } if (m_bVerbose) Logw("(SUCCESS)\n"); // Load the face if (m_bVerbose) Logw("Font::InitializeAtlas(): Loading %s ", _filename); if (FT_New_Face(m_ftLib, _filename, 0, &m_ftFace)) { if (m_bVerbose) Logw("(FAILURE)\n"); //else Logw("Font::InitializeAtlas(): Loading %s failed.\n", _filename); return (RETURN_FAILURE); } if (m_bVerbose) Logw("(SUCCESS)\n"); // Initialize variables before atlas creation FT_Set_Pixel_Sizes(m_ftFace, 0, m_iPixelSize); FT_GlyphSlot g = m_ftFace->glyph; m_sx = 2.0f / (float)g_vWindowDimensions.x; m_sy = 2.0f / (float)g_vWindowDimensions.y; int roww = 0; int rowh = 0; m_iTextureWidth = 0; m_iTextureHeight = 0; memset(m_sChars, 0, sizeof(character_info_s)); // Find the minimum size for a texture holding the // complete ASCII charset for (int i = 32; i < 128; i++) { if (FT_Load_Char(m_ftFace, i, FT_LOAD_RENDER)) { Logw("ERROR: Font::InitializeAtlas(): Could not load char %d.\n", i); continue; } if (roww + g->bitmap.width + 1 >= 1024) { m_iTextureWidth = MAX(m_iTextureWidth, roww); m_iTextureHeight += rowh; roww = 0; rowh = 0; } roww += g->bitmap.width + 1; rowh = MAX(rowh, g->bitmap.rows); } m_iTextureWidth = MAX(m_iTextureWidth, roww); m_iTextureHeight += rowh; // Setup swizzle mask for alpha texture shader rendering m_swizzleMask = (GLint *)malloc(sizeof(GLint) * 4); GLint mask[4] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; memcpy(m_swizzleMask, mask, sizeof(GLint) * 4); // Create a texture to hold the character set glActiveTexture(GL_TEXTURE1); glGenTextures(1, &m_atlasTextureID); glBindTexture(GL_TEXTURE_2D, m_atlasTextureID); glUniform1i(m_uniformTex, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_iTextureWidth, m_iTextureHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0); // 1 byte alignment glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Clamping to edges and linear filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, m_swizzleMask); // Paste glyphs bitmaps into the texture // int ox = 0; int oy = 0; rowh = 0; for (int i = 32; i < 128; i++) { if (FT_Load_Char(m_ftFace, i, FT_LOAD_RENDER)) { Logw("ERROR: Font::InitializeAtlas(): Could not load char bitmap into texture %d\n", i); continue; } if (ox + g->bitmap.width + 1 >= 1024) { oy += rowh; rowh = 0; ox = 0; } glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer); m_sChars[i].ax = (float)(g->advance.x >> 6); m_sChars[i].ay = (float)(g->advance.y >> 6); m_sChars[i].bw = (float)g->bitmap.width; m_sChars[i].bh = (float)g->bitmap.rows; m_sChars[i].bl = (float)g->bitmap_left; m_sChars[i].bt = (float)g->bitmap_top; m_sChars[i].tx = ox / (float)m_iTextureWidth; m_sChars[i].ty = oy / (float)m_iTextureHeight; rowh = MAX(rowh, g->bitmap.rows); ox += g->bitmap.width + 1; } //glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, m_swizzleMask); // Generate VAO glGenVertexArrays(1, &m_fontVAO); glError("Font::InitializeAtlas()", "glGenVertexArrays()"); glBindVertexArray(m_fontVAO); glError("Font::InitializeAtlas()", "glBindVertexArray()"); // Generate the VBO for fonts glGenBuffers(1, &m_fontVBO); glError("Font::InitializeAtlas()", "glGenBuffers()"); // unbind vertex array glBindVertexArray(0); // Always log this Logw("Font::InitializeAtlas(): Generated a %dx%d text atlas (%.1f kb) in %.4f ms\n", m_iTextureWidth, m_iTextureHeight, (float)(m_iTextureWidth * m_iTextureHeight) / 1024.0f, (double)(GetCounter() - t0) / PCFreq); return (RETURN_SUCCESS); } // end Font::InitializeAtlas()
int main(int argc,char** argv) { long usec; int port = -1; rfbScreenInfoPtr server = NULL; char* authData[2] = { NULL, NULL}; int width = -1; int height = -1; int left = -1; int top = -1; BOOL ro = TRUE; if((argc != 7) && (argc != 8)) { printf("Usage: WinLibVNCServer <left> <top> <width> <height> <port> <password> [/manage]"); return -1; } left = atoi(argv[1]); if(!left && strcmp(argv[1], "0")) left = -1; top = atoi(argv[2]); if(!top && strcmp(argv[2], "0")) top = -1; width = (atoi(argv[3]) / 4)*4; height = atoi(argv[4]); port = atoi(argv[5]); authData[0] = argv[6]; if((left < 0) || (top < 0) || (width <= 0) || (height <= 0) || (port <=0)) { printf("Invalid command line parameter(s)"); return -1; } if(8 == argc) { if(stricmp(argv[7], "/manage")) { printf("Invalid command line parameter(s)"); return -1; } else { ro = FALSE; } } if(!winInitScreenCapture(left, top, width, height)) return 0; server = rfbGetScreen(&argc, argv, width, height, 8, 3, BPP); if(!server) return 0; server->port = port; server->passwordCheck = rfbCheckPasswordByList; server->authPasswdData = authData; server->desktopName = "WinLibVNCServer"; server->frameBuffer = (char*)malloc(width*height*BPP); server->alwaysShared = (1==1); if(!ro) { winInitPointerHandler(rfbDefaultPtrAddEvent, left, top); server->ptrAddEvent = winPtrAddEvent; } /* Initialize the server */ rfbInitServer(server); StartCounter(); /* Loop, processing clients and taking pictures */ while (rfbIsActive(server)) { int picturetaken = 0; if (picturetaken = TimeToTakePicture()) { prevTimeSShot = GetCounter(); if (winTakePicture32((unsigned char *)server->frameBuffer)) rfbMarkRectAsModified(server, 0, 0, width, height); prevTimeStats = currTimeSShot = GetCounter(); fprintf(stderr,"Screen capture: %5.2f ms," " events: %5.2f ms," " printf(): %5.2f ms\r", currTimeSShot - prevTimeSShot, timeEvents, timeStats); timeStats = GetCounter() - prevTimeStats; } if(picturetaken) timeEvents = GetCounter(); usec = server->deferUpdateTime*1000; rfbProcessEvents(server,usec); if(picturetaken) timeEvents = GetCounter() - timeEvents; } winShutdownScreenCapture(); return(0); }
//....................................................................................... void vxQuad::LoadThreaded(bool _log, ThreadStatus *_status) { _status->status = ThreadStatusEnum::THREAD_RUNNING; _status->progress = 0.0f; _status->message = "Object '" + m_objectName + "': initializing"; __int64 t0 = StartCounter(); // check for vertex flags float normals = (m_vertexFlags & VERTEX_NORMAL ? 1.0f : 0.0f); float texcoords = (m_vertexFlags & VERTEX_TEXCOORD ? 1.0f : 0.0f); // data GLvertex vertices[] = { GLvertex(Vector3f(-0.5f, -0.5f, 0.0f), Vector3f() * normals, Vector2f(0.0f, 0.0f) * texcoords), GLvertex(Vector3f(-0.5f, 0.5f, 0.0f), Vector3f() * normals, Vector2f(0.0f, 1.0f) * texcoords), GLvertex(Vector3f( 0.5f, 0.5f, 0.0f), Vector3f() * normals, Vector2f(1.0f, 1.0f) * texcoords), GLvertex(Vector3f( 0.5f, -0.5f, 0.0f), Vector3f() * normals, Vector2f(1.0f, 0.0f) * texcoords), }; unsigned int indices[] = { 0, 2, 1, 0, 3, 2 }; // load texture if any if (VERTEX_TEXCOORD) { _status->progress = 50.0f; _status->message = "Object '" + m_objectName + "': loading texture"; m_texture.m_pTexture->LoadToRAM(_log); } // initialize vertices and indices m_nVertices = sizeof(vertices) / sizeof(GLvertex); m_nIndices = sizeof(indices) / sizeof(unsigned int); m_pVertices = (GLvertex *)malloc(sizeof(GLvertex) * m_nVertices); m_pIndices = (unsigned int *)malloc(sizeof(unsigned int) * m_nIndices); m_nVerticesLeft = m_nVertices; m_nIndicesLeft = m_nIndices; // check for texture if (m_texture.m_pTexture) { m_nTextureBytes = m_texture.m_pTexture->SizeBytes(); m_nTextureBytesLeft = m_nTextureBytes; } // copy the data memcpy(m_pVertices, vertices, sizeof(GLvertex) * m_nVertices); memcpy(m_pIndices, indices, sizeof(unsigned int) * m_nIndices); if (_log) { Logw("vxQuad::LoadThreaded(): Frame %llu: vxQuad intialized (%d vertices, %d indices) in %.4f ms\n", g_lFrame, m_nVertices, m_nIndices, GetElapsed(t0)); } // update flags and upload counters m_bObjectLoadedRAM = true; m_nVerticesLeft = m_nVertices; m_nIndicesLeft = m_nIndices; _status->progress = 100.0f; _status->message = "Object '" + m_objectName + "': Done"; _status->status = ThreadStatusEnum::THREAD_FINISHED; }
//....................................................................................... double Object::AsyncGPUupload(double _time, bool _log) { unsigned vertexUploaded = 0, indexUploaded = 0, textureUploaded = 0; // sanity check if (!m_bObjectLoadedRAM || !m_bInitializedGPU) { Logw("Object::AsyncGPUupload(): ERROR: could not upload object %d: %s.\n", m_objectID, (m_bObjectLoadedRAM ? "GPU buffers not initialized" : "Object not loaded to RAM")); return (1.0); } // start upload timer __int64 t0 = StartCounter(); // Upload texture if any if (m_texture.m_pTexture && !m_bTextureGPUupload) { // calculate number of bytes for upload this frame textureUploaded = GPUuploadTime(_time - 10.0, 1); textureUploaded = AsyncTextureUpload(textureUploaded); m_nTextureBytesLeft -= textureUploaded; if (m_nTextureBytesLeft == 0) m_bTextureGPUupload = true; } // Upload vertices if not done yet else if (!m_bVerticesGPUupload) { // calculate how many bytes to upload, leave 10 ms vertexUploaded = GPUuploadTime(_time - 10.0, sizeof(GLvertex)); //vertexUploaded = 100000; vertexUploaded = AsyncVertexUpload(vertexUploaded); // check for vertex upload complete m_nVerticesLeft -= vertexUploaded; if (m_nVerticesLeft == 0) { m_bVerticesGPUupload = true; m_pRenderFunc = &Object::RenderVertices; } } // upload indices else { // calculate how many bytes to upload, leave 10 ms indexUploaded = GPUuploadTime(_time - 10.0, sizeof(unsigned int)); //indexUploaded = 100000; indexUploaded = AsyncIndexUpload(indexUploaded); // check for upload complete m_nIndicesLeft -= indexUploaded; if (m_nIndicesLeft == 0) { // update flag and rendering function m_bObjectLoadedGPU = true; m_pRenderFunc = &Object::RenderIndices; } } // calc elapsed time double time = GetElapsed(t0); if (_log) Logw("Object::AsyncGPUupload(): Frame %llu: Uploaded %d bytes (%d vertices, %d indices, %d texture bytes) of object '%s' in %.4f ms\n", g_lFrame, sizeof(GLvertex)*vertexUploaded + sizeof(unsigned int)*indexUploaded + textureUploaded, vertexUploaded, indexUploaded, textureUploaded, m_objectName.c_str(), time); // return elapsed time return (time); } // end Object::AsyncGPUupload()
TimingCPU::TimingCPU() : cur_time_(0) { StartCounter(); }
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { LRESULT lResult = TRUE; switch(msg) { case WM_CREATE: lResult = OnCreate(hwnd, (CREATESTRUCT*)lp); break; case WM_COMMAND: switch (wp) { case IDOK: DestroyWindow(hwnd); break; case ID_NEWWINDOW: CreateMyWindow(hwnd); break; case ID_SETTEXT: SetDialogText(TEXT("AaBbYyZz")); break; case ID_GO: StartCounter(); break; case ID_CLOSEWINDOW: DestroyMyWindow(); break; case ID_BEEP: MakeTheBeep(); break; case ID_HIDE: g_dlg->Hide(); break; case ID_SHOW: g_dlg->Show(); break; case ID_DOFILESTUFF: DoFileStuff(hwnd); break; case ID_LIGHT: DoLight(); break; default: goto DoDefault; } break; case WM_PAINT: { HDC hdc; PAINTSTRUCT ps; RECT rect; hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rect); DrawText(hdc, g_szMessage, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); EndPaint (hwnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; DoDefault: default: lResult = DefWindowProc(hwnd, msg, wp, lp); break; } return(lResult); }