]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Faster screenshot/avioutput capture in after filtering mode.
authorToni Wilen <twilen@winuae.net>
Sun, 24 Apr 2016 12:31:13 +0000 (15:31 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 24 Apr 2016 12:31:13 +0000 (15:31 +0300)
od-win32/avioutput.cpp
od-win32/direct3d.cpp
od-win32/direct3d.h
od-win32/screenshot.cpp

index 76cbb80a43068e6dba42cddc668d0da34101492d..8676e41d6d5390433ce3d2361cbc71d2bcc8517a 100644 (file)
@@ -919,6 +919,57 @@ static void AVIOuput_WAVWriteAudio (uae_u8 *sndbuffer, int sndbufsize)
        fwrite (sndbuffer, 1, sndbufsize, wavfile);
 }
 
+static int getFromRenderTarget(struct avientry *avie)
+{
+       int ok = 0;
+       int w, h, bits;
+       HRESULT hr;
+       D3DLOCKED_RECT l;
+       LPDIRECT3DSURFACE9 s = D3D_capture(&w, &h, &bits);
+       if (s) {
+               hr = s->LockRect(&l, NULL, D3DLOCK_READONLY);
+               if (SUCCEEDED(hr)) {
+                       int dpitch = ((aviout_width_out * avioutput_bits + 31) & ~31) / 8;
+                       if (bits == 32) {
+                               for (int y = 0; y < h; y++) {
+                                       uae_u8 *d = (uae_u8*)avie->lpVideo + (h - y - 1) * dpitch;
+                                       uae_u32 *s = (uae_u32*)((uae_u8*)l.pBits + y * l.Pitch);
+                                       for (int x = 0; x < w; x++) {
+                                               uae_u32 v = *s++;
+                                               d[0] = v >> 0;
+                                               d[1] = v >> 8;
+                                               d[2] = v >> 16;
+                                               d += 3;
+                                       }
+                               }
+                       } else if (bits == 16 || bits == 15) {
+                               for (int y = 0; y < h; y++) {
+                                       uae_u8 *d = (uae_u8*)avie->lpVideo + (h - y - 1) * dpitch;
+                                       uae_u16 *s = (uae_u16*)((uae_u8*)l.pBits + y * l.Pitch);
+                                       for (int x = 0; x < w; x++) {
+                                               uae_u16 v = s[x];
+                                               uae_u16 v2 = v;
+                                               if (bits == 16) {
+                                                       v2 = v & 31;
+                                                       v2 |= ((v & (31 << 5)) << 1) | (((v >> 5) & 1) << 5);
+                                                       v2 |= (v & (31 << 10)) << 1;
+                                               } else {
+                                                       v2 = v & 31;
+                                                       v2 |= (v >> 1) & (31 << 5);
+                                                       v2 |= (v >> 1) & (31 << 10);
+                                               }
+                                               ((uae_u16*)d)[0] = v2;
+                                               d += 2;
+                                       }
+                               }
+                       }
+                       s->UnlockRect();
+               }
+               ok = 1;
+       }
+       return ok;
+}
+
 static int getFromDC (struct avientry *avie)
 {
        HDC hdc;
@@ -1083,7 +1134,11 @@ void AVIOutput_WriteVideo (void)
        if (avioutput_originalsize || WIN32GFX_IsPicassoScreen ()) {
                v = getFromBuffer (ae, 1);
        } else {
-               v = getFromDC (ae);
+               if (D3D_isenabled()) {
+                       v = getFromRenderTarget(ae);
+               } else {
+                       v = getFromDC (ae);
+               }
        }
        if (v)
                queueavientry (ae);
index 7ea2036ed56da03dad2d4f8eea09dac51e9aa622..b2fcbd0682fae928310f5fac559e6a3df3d157f3 100644 (file)
@@ -2620,7 +2620,7 @@ static const TCHAR *D3D_init2 (HWND ahwnd, int w_w, int w_h, int depth, int *fre
                        write_log (_T("%s: SetMaximumFrameLatency() failed: %s\n"), D3DHEAD, D3D_ErrorString (hr));
        }
 
-       hr = d3ddev->CreateOffscreenPlainSurface(w_w, w_h, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &screenshotsurface, NULL);
+       hr = d3ddev->CreateOffscreenPlainSurface(w_w, w_h, tformat, D3DPOOL_SYSTEMMEM, &screenshotsurface, NULL);
        if (FAILED(hr)) {
                write_log(_T("%s: CreateOffscreenPlainSurface failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
        }
@@ -3470,6 +3470,31 @@ void D3D_guimode (bool guion)
        guimode = guion;
 }
 
+LPDIRECT3DSURFACE9 D3D_capture(int *w, int *h, int *bits)
+{
+       LPDIRECT3DSURFACE9 rt;
+       HRESULT hr;
+
+       waitfakemode();
+       if (!isd3d())
+               return NULL;
+       hr = d3ddev->GetRenderTarget(0, &rt);
+       if (FAILED(hr)) {
+               write_log(_T("%s: GetRenderTarget() failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
+               return NULL;
+       }
+       hr = d3ddev->GetRenderTargetData(rt, screenshotsurface);
+       rt->Release();
+       if (FAILED(hr)) {
+               write_log(_T("%s: GetRenderTargetData() failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
+               return NULL;
+       }
+       *w = window_w;
+       *h = window_h;
+       *bits = t_depth;
+       return screenshotsurface;
+}
+
 HDC D3D_getDC (HDC hdc)
 {
        static LPDIRECT3DSURFACE9 bb;
index 77a5555cc1ec7a18ffef71bf750c3579785a2383..891189ba07cbaef959d9b19c96074c83dc0c7120 100644 (file)
@@ -22,6 +22,7 @@ extern double D3D_getrefreshrate (void);
 extern void D3D_vblank_reset (double freq);
 extern void D3D_restore (void);
 extern LPDIRECT3DTEXTURE9 cursorsurfaced3d;
+extern LPDIRECT3DSURFACE9 D3D_capture(int*,int*,int*);
 
 #define CURSORMAXWIDTH 64
 #define CURSORMAXHEIGHT 64
index 81f49ad4380615098b5e4de7b40c5bd61619a44f..2fa47a2802214cd5d3a94e746c6370fa565d0a60 100644 (file)
@@ -369,51 +369,119 @@ donormal:
                width = WIN32GFX_GetWidth ();
                height = WIN32GFX_GetHeight ();
 
-               surface_dc = gethdc ();
-               if (surface_dc == NULL)
-                       goto oops;
-
-               // need a HBITMAP to convert it to a DIB
-               if ((offscreen_bitmap = CreateCompatibleBitmap (surface_dc, width, height)) == NULL)
-                       goto oops; // error
-
-               // The bitmap is empty, so let's copy the contents of the surface to it.
-               // For that we need to select it into a device context.
-               if ((offscreen_dc = CreateCompatibleDC (surface_dc)) == NULL)
-                       goto oops; // error
-
-               // select offscreen_bitmap into offscreen_dc
-               hgdiobj = SelectObject (offscreen_dc, offscreen_bitmap);
-
-               // now we can copy the contents of the surface to the offscreen bitmap
-               BitBlt (offscreen_dc, 0, 0, width, height, surface_dc, 0, 0, SRCCOPY);
-
-               // de-select offscreen_bitmap
-               SelectObject (offscreen_dc, hgdiobj);
-
-               ZeroMemory (bi, sizeof(bi));
-               bi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
-               bi->bmiHeader.biWidth = width;
-               bi->bmiHeader.biHeight = height;
-               bi->bmiHeader.biPlanes = 1;
-               bi->bmiHeader.biBitCount = 24;
-               bi->bmiHeader.biCompression = BI_RGB;
-               bi->bmiHeader.biSizeImage = (((bi->bmiHeader.biWidth * bi->bmiHeader.biBitCount + 31) & ~31) / 8) * bi->bmiHeader.biHeight;
-               bi->bmiHeader.biXPelsPerMeter = 0;
-               bi->bmiHeader.biYPelsPerMeter = 0;
-               bi->bmiHeader.biClrUsed = 0;
-               bi->bmiHeader.biClrImportant = 0;
+               if (D3D_isenabled()) {
+                       int w, h, bits;
+                       HRESULT hr;
+                       D3DLOCKED_RECT l;
+                       LPDIRECT3DSURFACE9 s = D3D_capture(&w, &h, &bits);
+                       if (s) {
+                               hr = s->LockRect(&l, NULL, D3DLOCK_READONLY);
+                               if (SUCCEEDED(hr)) {
+                                       int dpitch = (((w * 24 + 31) & ~31) / 8);
+                                       lpvBits = xmalloc(uae_u8, dpitch * h); 
+
+                                       ZeroMemory(bi, sizeof(bi));
+                                       bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+                                       bi->bmiHeader.biWidth = w;
+                                       bi->bmiHeader.biHeight = h;
+                                       bi->bmiHeader.biPlanes = 1;
+                                       bi->bmiHeader.biBitCount = 24;
+                                       bi->bmiHeader.biCompression = BI_RGB;
+                                       bi->bmiHeader.biSizeImage = dpitch * bi->bmiHeader.biHeight;
+                                       bi->bmiHeader.biXPelsPerMeter = 0;
+                                       bi->bmiHeader.biYPelsPerMeter = 0;
+                                       bi->bmiHeader.biClrUsed = 0;
+                                       bi->bmiHeader.biClrImportant = 0;
+
+                                       if (lpvBits) {
+                                               if (bits == 32) {
+                                                       for (int y = 0; y < h; y++) {
+                                                               uae_u8 *d = (uae_u8*)lpvBits + (h - y - 1) * dpitch;
+                                                               uae_u32 *s = (uae_u32*)((uae_u8*)l.pBits + y * l.Pitch);
+                                                               for (int x = 0; x < w; x++) {
+                                                                       uae_u32 v = *s++;
+                                                                       d[0] = v >> 0;
+                                                                       d[1] = v >> 8;
+                                                                       d[2] = v >> 16;
+                                                                       d += 3;
+                                                               }
+                                                       }
+                                               } else if (bits == 16 || bits == 15) {
+                                                       for (int y = 0; y < h; y++) {
+                                                               uae_u8 *d = (uae_u8*)lpvBits + (h - y - 1) * dpitch;
+                                                               uae_u16 *s = (uae_u16*)((uae_u8*)l.pBits + y * l.Pitch);
+                                                               for (int x = 0; x < w; x++) {
+                                                                       uae_u16 v = s[x];
+                                                                       uae_u16 v2 = v;
+                                                                       if (bits == 16) {
+                                                                               v2 = v & 31;
+                                                                               v2 |= ((v & (31 << 5)) << 1) | (((v >> 5) & 1) << 5);
+                                                                               v2 |= (v & (31 << 10)) << 1;
+                                                                       } else {
+                                                                               v2 = v & 31;
+                                                                               v2 |= (v >> 1) & (31 << 5);
+                                                                               v2 |= (v >> 1) & (31 << 10);
+                                                                       }
+                                                                       ((uae_u16*)d)[0] = v2;
+                                                                       d += 2;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       s->UnlockRect();
+                               }
+                       }
 
-               // Reserve memory for bitmap bits
-               if (!(lpvBits = xmalloc (uae_u8, bi->bmiHeader.biSizeImage)))
-                       goto oops; // out of memory
+               } else {
+                       surface_dc = gethdc ();
+                       if (surface_dc == NULL)
+                               goto oops;
 
-               // Have GetDIBits convert offscreen_bitmap to a DIB (device-independent bitmap):
-               if (!GetDIBits (offscreen_dc, offscreen_bitmap, 0, bi->bmiHeader.biHeight, lpvBits, bi, DIB_RGB_COLORS))
-                       goto oops; // GetDIBits FAILED
+                       // need a HBITMAP to convert it to a DIB
+                       if ((offscreen_bitmap = CreateCompatibleBitmap (surface_dc, width, height)) == NULL)
+                               goto oops; // error
+
+                       // The bitmap is empty, so let's copy the contents of the surface to it.
+                       // For that we need to select it into a device context.
+                       if ((offscreen_dc = CreateCompatibleDC (surface_dc)) == NULL)
+                               goto oops; // error
+
+                       // select offscreen_bitmap into offscreen_dc
+                       hgdiobj = SelectObject (offscreen_dc, offscreen_bitmap);
+
+                       // now we can copy the contents of the surface to the offscreen bitmap
+                       BitBlt (offscreen_dc, 0, 0, width, height, surface_dc, 0, 0, SRCCOPY);
+
+                       // de-select offscreen_bitmap
+                       SelectObject (offscreen_dc, hgdiobj);
+
+                       ZeroMemory (bi, sizeof(bi));
+                       bi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+                       bi->bmiHeader.biWidth = width;
+                       bi->bmiHeader.biHeight = height;
+                       bi->bmiHeader.biPlanes = 1;
+                       bi->bmiHeader.biBitCount = 24;
+                       bi->bmiHeader.biCompression = BI_RGB;
+                       bi->bmiHeader.biSizeImage = (((bi->bmiHeader.biWidth * bi->bmiHeader.biBitCount + 31) & ~31) / 8) * bi->bmiHeader.biHeight;
+                       bi->bmiHeader.biXPelsPerMeter = 0;
+                       bi->bmiHeader.biYPelsPerMeter = 0;
+                       bi->bmiHeader.biClrUsed = 0;
+                       bi->bmiHeader.biClrImportant = 0;
+
+                       // Reserve memory for bitmap bits
+                       if (!(lpvBits = xmalloc (uae_u8, bi->bmiHeader.biSizeImage)))
+                               goto oops; // out of memory
+
+                       // Have GetDIBits convert offscreen_bitmap to a DIB (device-independent bitmap):
+                       if (!GetDIBits (offscreen_dc, offscreen_bitmap, 0, bi->bmiHeader.biHeight, lpvBits, bi, DIB_RGB_COLORS))
+                               goto oops; // GetDIBits FAILED
+
+                       releasehdc (surface_dc);
+                       surface_dc = NULL;
+               }
 
-               releasehdc (surface_dc);
-               surface_dc = NULL;
+               if (!lpvBits)
+                       goto oops;
        }
        screenshot_prepared = TRUE;
        return 1;