예제 #1
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);
    }
}
예제 #2
0
  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;
  }