static IDirectDrawSurface* GetBlitSurface() { IDirectDrawSurface* blitSurface; if(PrimarySurfaceVersion < 4) { IDirectDrawSurface *surf = (IDirectDrawSurface *) PrimarySurface; DDSURFACEDESC ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if(FAILED(surf->GetSurfaceDesc(&ddsd))) printLog("video: can't get surface desc\n"); else { ddsd.dwWidth = captureWidth; ddsd.dwHeight = captureHeight; ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; IDirectDraw *dd = (IDirectDraw *) PrimaryDDraw; if(FAILED(dd->CreateSurface(&ddsd,&blitSurface,0))) printLog("video: could not create blit target\n"); } } else { IDirectDrawSurface4 *srf4 = (IDirectDrawSurface4 *) PrimarySurface; DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if(FAILED(srf4->GetSurfaceDesc(&ddsd))) printLog("video: can't get surface desc\n"); else { ddsd.dwWidth = captureWidth; ddsd.dwHeight = captureHeight; ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.ddsCaps.dwCaps2 = 0; IDirectDraw4 *dd = (IDirectDraw4 *) PrimaryDDraw; if(FAILED(dd->CreateSurface(&ddsd,(IDirectDrawSurface4 **) &blitSurface,0))) printLog("video: could not create blit target\n"); } } return blitSurface; }
bool SetFormatFromSurface(IUnknown *surfPtr) { IDirectDrawSurface *surf = (IDirectDrawSurface *) surfPtr; DDPIXELFORMAT fmt; ZeroMemory(&fmt,sizeof(fmt)); fmt.dwSize = sizeof(fmt); if(FAILED(surf->GetPixelFormat(&fmt))) { printLog("video: can't get pixel format\n"); return false; } SetFormat(&fmt); if(IsPaletted()) UpdatePalette(); return true; }
static void PrimarySurfaceCreated(IUnknown *ddraw,IUnknown *srfp,int ver) { PrimaryDDraw = ddraw; PrimarySurface = srfp; PrimarySurfaceVersion = ver; if(PrimarySurfaceVersion < 4) { IDirectDrawSurface *surf = (IDirectDrawSurface *) PrimarySurface; DDSURFACEDESC ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if(FAILED(surf->GetSurfaceDesc(&ddsd))) printLog("video: can't get surface desc\n"); else { if(captureWidth != ddsd.dwWidth || captureHeight != ddsd.dwHeight) setCaptureResolution(ddsd.dwWidth,ddsd.dwHeight); } } else { IDirectDrawSurface4 *srf4 = (IDirectDrawSurface4 *) PrimarySurface; DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if(FAILED(srf4->GetSurfaceDesc(&ddsd))) printLog("video: can't get surface desc\n"); else { if(captureWidth != ddsd.dwWidth || captureHeight != ddsd.dwHeight) setCaptureResolution(ddsd.dwWidth,ddsd.dwHeight); } } graphicsInitTiming(); }
static void ImplementFlip(IUnknown *surf,int version) { IDirectDrawSurface *back = 0; videoNeedEncoder(); if(params.CaptureVideo) { if(version < 4) { DDSCAPS caps; ZeroMemory(&caps,sizeof(caps)); caps.dwCaps = DDSCAPS_BACKBUFFER; ((IDirectDrawSurface *) surf)->GetAttachedSurface(&caps,&back); } else { DDSCAPS2 caps; ZeroMemory(&caps,sizeof(caps)); caps.dwCaps = DDSCAPS_BACKBUFFER; ((IDirectDrawSurface4 *) surf)->GetAttachedSurface(&caps,(IDirectDrawSurface4 **) &back); } if(back) { VideoCaptureDataLock lock; if(Blitter.BlitSurfaceToCapture(back,version)) encoder->WriteFrame(captureData); back->Release(); } } nextFrame(); }
//////////////////////////////////////////////////////////////////////////// // // @mfunc | CVisRefCntMemBlock | ~CVisRefCntMemBlock | // // Destructor called when this object is destroyed. If this // object allocated memory in its constructor, that memory // will be freed when the destructor is called. The destructor // is virtual so that other classes can be derived from this // class. // //////////////////////////////////////////////////////////////////////////// CVisRefCntMemBlock::~CVisRefCntMemBlock(void) { #ifdef _DEBUG if (m_pbData != 0) { // Decrement the count of blocks of this type. if ((m_evismemblock != evismemblockAllocFileMapping) && (m_evismemblock != evismemblockAllocGlobalAlloc) #ifdef VIS_MEMBLOCK_USE_IMALLOC && (m_evismemblock != evismemblockAllocIMalloc) #endif // VIS_MEMBLOCK_USE_IMALLOC && (m_evismemblock != evismemblockAllocNewDouble)) { -- s_cBlockExternal; s_cbExternalTotal -= m_cbData; } else { assert((m_evismemblock > 0) && (m_evismemblock <= cMemBlockAllocators)); -- s_cBlockAlloc[m_evismemblock]; s_cbAllocTotal[m_evismemblock] -= m_cbData; } // Ref count may not be zero if delete is used to destroy this // object. s_cAddRefTotal -= m_cRef; // Remove this memory block to the globals list of all memory blocks // currently in use. HANDLE hMutex = CreateMutex(0, FALSE, "CVisRefCntMemBlockDebugMutex"); assert(hMutex != 0); VisWaitForSingleObject(hMutex, INFINITE); CVisRefCntMemBlock *pRefCntMemBlockPrev = 0; CVisRefCntMemBlock *pRefCntMemBlock = s_pRefCntMemBlockFirst; while ((pRefCntMemBlock != this) && (pRefCntMemBlock != 0)) { pRefCntMemBlockPrev = pRefCntMemBlock; pRefCntMemBlock = pRefCntMemBlock->m_pRefCntMemBlockNext; } if (pRefCntMemBlock != 0) { if (pRefCntMemBlockPrev == 0) { s_pRefCntMemBlockFirst = m_pRefCntMemBlockNext; m_pRefCntMemBlockNext = 0; } else { pRefCntMemBlockPrev->m_pRefCntMemBlockNext = m_pRefCntMemBlockNext; m_pRefCntMemBlockNext = 0; } } ReleaseMutex(hMutex); CloseHandle(hMutex); } #endif // _DEBUG if (m_evismemblock == evismemblockAllocFileMapping) { // Free memory allocated using CreateFileMapping. assert(m_pbData != 0); UnmapViewOfFile(m_pbData); CloseHandle(m_hFileMapping); m_hFileMapping = 0; } else if (m_evismemblock == evismemblockAllocNewDouble) { // Free memory allocated using operator new. delete [] (double *) m_pbData; } else if (m_evismemblock == evismemblockAllocGlobalAlloc) { // Free memory allocated using GlobalAlloc. GlobalFree(m_pbData); } #ifdef VIS_MEMBLOCK_USE_IMALLOC else if (m_evismemblock == evismemblockAllocIMalloc) { // Allocate memory using the OLE task allocator. CoTaskMemFree(m_pbData); } #endif // VIS_MEMBLOCK_USE_IMALLOC else if (m_evismemblock == evismemblockAllocDirectDrawSurface) { // Release memory allocated using DirectDrawSurface assert(m_pvUser != 0); IDirectDrawSurface* pDDS = (IDirectDrawSurface *)m_pvUser; pDDS->Release(); } else if (m_pfnCallback != 0) { m_pfnCallback(m_pbData, m_pvUser); } m_pbData = 0; }
void update_screen() { IDirectDrawSurface *dst; RECT dstRect; RECT srcRect; HRESULT hr; POINT pt; // NTS: dx_bitmap.is_valid() is not a valid test because base==canvas==NULL unless surface is locked if (ddsurfaceBMP == NULL) return; // NTS: We must provide a source rect, else Windows XP in 24bpp mode will conveniently choose to render the // right half (where extra padding+junk exist) rather than from the left side. Provide a source rect // to make it 100% clear which part of the surface we want blitted to screen. pt.x = pt.y = 0; ClientToScreen(hwndMain,&pt); GetClientRect(hwndMain,&dstRect); OffsetRect(&dstRect,pt.x,pt.y); srcRect.top = srcRect.left = 0; srcRect.right = dx_bitmap.width; srcRect.bottom = dx_bitmap.height; if (ddsurfaceGDI != NULL) dst = ddsurfaceGDI; else if (ddsurfacePrimary != NULL) dst = ddsurfacePrimary; else dst = NULL; if (dst != NULL) hr = dst->Blt(&dstRect,ddsurfaceBMP,&srcRect,0,NULL); else hr = DD_OK; if (hr == DDERR_SURFACELOST) { fprintf(stderr,"Whoops, the primary surface was lost.\n"); if ((hr=dst->Restore()) != DD_OK) { fprintf(stderr,"Unable to restore surface hr=0x%08lx.\n",hr); unlock_bitmap(); free_bitmap(); free_dx_primary_surface(); init_dx_primary_surface(); RECT rct; GetClientRect(hwndMain,&rct); if (!init_bitmap(rct.right,rct.bottom)) fprintf(stderr,"WARNING WM_RESIZE init_bitmap(%u,%u) failed\n", (unsigned int)rct.right,(unsigned int)rct.bottom); if (lock_bitmap()) { render_pattern(dx_bitmap); unlock_bitmap(); } InvalidateRect(hwndMain,NULL,FALSE); // DWM compositor-based versions set WM_PAINT such that only the affected area will repaint } } else if (hr != DD_OK) { fprintf(stderr,"DirectX blit failed, HR=0x%08lx\n",hr); } }
bool BlitSurfaceToCapture(IDirectDrawSurface *surf,int version) { IDirectDrawSurface* blitSurface = GetBlitSurface(); if(!blitSurface || !SetFormatFromSurface(surf)) return false; // blit backbuffer to our readback surface RECT rc; rc.left = 0; rc.top = 0; rc.right = captureWidth; rc.bottom = captureHeight; if(FAILED(blitSurface->Blt(&rc,surf,&rc,DDBLT_WAIT,0))) { printLog("video: blit failed\n"); return false; } LPBYTE surface; DWORD pitch; if(version < 4) { DDSURFACEDESC ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if(FAILED(blitSurface->Lock(0,&ddsd,DDLOCK_WAIT,0))) { printLog("video: can't lock surface\n"); return false; } surface = (LPBYTE) ddsd.lpSurface; pitch = ddsd.lPitch; } else { IDirectDrawSurface4 *srf4 = (IDirectDrawSurface4 *) blitSurface; DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if(FAILED(srf4->Lock(0,&ddsd,DDLOCK_WAIT,0))) { printLog("video: can't lock surface\n"); return false; } surface = (LPBYTE) ddsd.lpSurface; pitch = ddsd.lPitch; } // blit individual lines for(int y=0;y<captureHeight;y++) { unsigned char *src = surface + (captureHeight-1-y) * pitch; unsigned char *dst = captureData + y * captureWidth * 3; BlitOneLine(src,dst,captureWidth); } blitSurface->Unlock(surface); blitSurface->Release(); return true; }