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; }