]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Fix hardware RTG board screenshot/capture. Multimonitor scanline native/RTG fix.
authorToni Wilen <twilen@winuae.net>
Sat, 22 Sep 2018 17:27:24 +0000 (20:27 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 22 Sep 2018 17:27:24 +0000 (20:27 +0300)
od-win32/avioutput.cpp
od-win32/direct3d.cpp
od-win32/direct3d.h
od-win32/direct3d11.cpp
od-win32/screenshot.cpp

index 12492f30cb643ee550909f7d48cb1f5b4fd8471c..6e49ac6e93b7858f0aa41d10874d7b5ff3a87b98 100644 (file)
@@ -542,18 +542,24 @@ static int AVIOutput_AllocateVideo (void)
                } else {
                        freertgbuffer(0, getrtgbuffer(0, &avioutput_width, &avioutput_height, &pitch, &avioutput_bits, NULL));
                }
-               aviout_width_out = avioutput_width + 15;
-               aviout_width_out &= ~15;
-               aviout_height_out = avioutput_height + 1;
-               aviout_height_out &= ~1;
        }
 
        if (avioutput_width == 0 || avioutput_height == 0 || avioutput_bits == 0) {
                avioutput_width = WIN32GFX_GetWidth(mon);
                avioutput_height = WIN32GFX_GetHeight(mon);
                avioutput_bits = WIN32GFX_GetDepth(mon, 0);
+               if (WIN32GFX_IsPicassoScreen(mon) && avioutput_originalsize) {
+                       struct picasso96_state_struct *state = &picasso96_state[aviout_monid];
+                       avioutput_width = state->Width;
+                       avioutput_height = state->Height;
+               }
        }
 
+       aviout_width_out = avioutput_width + 15;
+       aviout_width_out &= ~15;
+       aviout_height_out = avioutput_height + 1;
+       aviout_height_out &= ~1;
+
        AVIOutput_Initialize ();
        AVIOutput_ReleaseVideo ();
        if (avioutput_width == 0 || avioutput_height == 0) {
@@ -949,19 +955,19 @@ static void AVIOuput_WAVWriteAudio (uae_u8 *sndbuffer, int sndbufsize)
        fwrite (sndbuffer, 1, sndbufsize, wavfile);
 }
 
-static int getFromRenderTarget11(struct avientry *avie)
+static int getFromRenderTarget11(struct avientry *avie, bool renderTarget)
 {
        int ok = 0;
        int w, h, pitch, bits = 32;
        void *data;
 
-       bool got = D3D11_capture(aviout_monid, &data, &w, &h, &pitch);
+       bool got = D3D11_capture(aviout_monid, &data, &w, &h, &pitch, renderTarget);
        if (got) {
                int dpitch = ((aviout_width_out * avioutput_bits + 31) & ~31) / 8;
-               for (int y = 0; y < h; y++) {
-                       uae_u8 *d = (uae_u8*)avie->lpVideo + (h - y - 1) * dpitch;
+               for (int y = 0; y < h && y < aviout_height_out; y++) {
+                       uae_u8 *d = (uae_u8*)avie->lpVideo + (aviout_height_out - y - 1) * dpitch;
                        uae_u32 *s = (uae_u32*)((uae_u8*)data + y * pitch);
-                       for (int x = 0; x < w; x++) {
+                       for (int x = 0; x < w && x < aviout_width_out; x++) {
                                uae_u32 v = *s++;
                                d[0] = v >> 0;
                                d[1] = v >> 8;
@@ -974,28 +980,28 @@ static int getFromRenderTarget11(struct avientry *avie)
                                }
                        }
                }
-               D3D11_capture(aviout_monid, NULL, NULL, NULL, NULL);
+               D3D11_capture(aviout_monid, NULL, NULL, NULL, NULL, renderTarget);
                ok = 1;
        }
        return ok;
 }
 
-static int getFromRenderTarget(struct avientry *avie)
+static int getFromRenderTarget(struct avientry *avie, bool renderTarget)
 {
        int ok = 0;
        int w, h, bits;
        HRESULT hr;
        D3DLOCKED_RECT l;
-       LPDIRECT3DSURFACE9 s = D3D_capture(aviout_monid, &w, &h, &bits);
+       LPDIRECT3DSURFACE9 s = D3D_capture(aviout_monid, &w, &h, &bits, renderTarget);
        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;
+                               for (int y = 0; y < h && y < aviout_height_out; y++) {
+                                       uae_u8 *d = (uae_u8*)avie->lpVideo + (aviout_height_out - y - 1) * dpitch;
                                        uae_u32 *s = (uae_u32*)((uae_u8*)l.pBits + y * l.Pitch);
-                                       for (int x = 0; x < w; x++) {
+                                       for (int x = 0; x < w && x < aviout_width_out; x++) {
                                                uae_u32 v = *s++;
                                                d[0] = v >> 0;
                                                d[1] = v >> 8;
@@ -1009,10 +1015,10 @@ static int getFromRenderTarget(struct avientry *avie)
                                        }
                                }
                        } else if (bits == 16 || bits == 15) {
-                               for (int y = 0; y < h; y++) {
-                                       uae_u8 *d = (uae_u8*)avie->lpVideo + (h - y - 1) * dpitch;
+                               for (int y = 0; y < h && y < aviout_height_out; y++) {
+                                       uae_u8 *d = (uae_u8*)avie->lpVideo + (aviout_height_out - y - 1) * dpitch;
                                        uae_u16 *s = (uae_u16*)((uae_u8*)l.pBits + y * l.Pitch);
-                                       for (int x = 0; x < w; x++) {
+                                       for (int x = 0; x < w && x < aviout_width_out; x++) {
                                                uae_u16 v = s[x];
                                                uae_u16 v2 = v;
                                                if (bits == 16) {
@@ -1200,17 +1206,26 @@ static void AVIOutput_WriteVideo(void)
                dorestart ();
        waitqueuefull ();
        ae = allocavientry_video();
+       lockrtg();
        if (avioutput_originalsize || WIN32GFX_IsPicassoScreen(mon)) {
                v = getFromBuffer (ae, 1);
+               if (!v) {
+                       if (D3D_isenabled(0) == 2) {
+                               v = getFromRenderTarget11(ae, false);
+                       } else if (D3D_isenabled(0) == 1) {
+                               v = getFromRenderTarget(ae, false);
+                       }
+               }
        } else {
                if (D3D_isenabled(0) == 2) {
-                       v = getFromRenderTarget11(ae);
+                       v = getFromRenderTarget11(ae, true);
                } else if (D3D_isenabled(0) == 1) {
-                       v = getFromRenderTarget(ae);
+                       v = getFromRenderTarget(ae, true);
                } else {
                        v = getFromDC (ae);
                }
        }
+       unlockrtg();
        if (v)
                queueavientry (ae);
        else
index bcb78623f6a258f7fedd84b5e5c6e44c966f73f3..229d5dda2d5b76f75d906f05e211ac53cdd19c55 100644 (file)
@@ -43,8 +43,6 @@ int forcedframelatency = -1;
 #include "direct3d.h"
 
 static TCHAR *D3DHEAD = _T("-");
-static struct gfx_filterdata *filterd3d;
-static int filterd3didx;
 
 static bool showoverlay = true;
 static int slicecnt;
@@ -195,6 +193,10 @@ struct d3dstruct
        bool cursor_v, cursor_scale;
        int statusbar_vx, statusbar_hx;
 
+       struct gfx_filterdata *filterd3d;
+       int filterd3didx;
+       int scanline_osl1, scanline_osl2, scanline_osl3;
+
        D3DXHANDLE postSourceTextureHandle;
        D3DXHANDLE postMaskTextureHandle;
        D3DXHANDLE postTechnique, postTechniquePlain, postTechniqueAlpha;
@@ -1428,33 +1430,34 @@ static void createscanlines (struct d3dstruct *d3d, int force)
 {
        HRESULT hr;
        D3DLOCKED_RECT locked;
-       static int osl1, osl2, osl3;
        int sl4, sl42;
        int l1, l2;
        int x, y, yy;
        uae_u8 *sld, *p;
        int bpp;
 
-       if (osl1 == filterd3d->gfx_filter_scanlines && osl3 == filterd3d->gfx_filter_scanlinelevel && osl2 == filterd3d->gfx_filter_scanlineratio && !force)
+       if (d3d->scanline_osl1 == d3d->filterd3d->gfx_filter_scanlines &&
+               d3d->scanline_osl3 == d3d->filterd3d->gfx_filter_scanlinelevel &&
+               d3d->scanline_osl2 == d3d->filterd3d->gfx_filter_scanlineratio && !force)
                return;
        bpp = d3d->t_depth < 32 ? 2 : 4;
-       osl1 = filterd3d->gfx_filter_scanlines;
-       osl3 = filterd3d->gfx_filter_scanlinelevel;
-       osl2 = filterd3d->gfx_filter_scanlineratio;
-       sl4 = filterd3d->gfx_filter_scanlines * 16 / 100;
-       sl42 = filterd3d->gfx_filter_scanlinelevel * 16 / 100;
+       d3d->scanline_osl1 = d3d->filterd3d->gfx_filter_scanlines;
+       d3d->scanline_osl3 = d3d->filterd3d->gfx_filter_scanlinelevel;
+       d3d->scanline_osl2 = d3d->filterd3d->gfx_filter_scanlineratio;
+       sl4 = d3d->filterd3d->gfx_filter_scanlines * 16 / 100;
+       sl42 = d3d->filterd3d->gfx_filter_scanlinelevel * 16 / 100;
        if (sl4 > 15)
                sl4 = 15;
        if (sl42 > 15)
                sl42 = 15;
-       l1 = (filterd3d->gfx_filter_scanlineratio >> 0) & 15;
-       l2 = (filterd3d->gfx_filter_scanlineratio >> 4) & 15;
+       l1 = (d3d->filterd3d->gfx_filter_scanlineratio >> 0) & 15;
+       l2 = (d3d->filterd3d->gfx_filter_scanlineratio >> 4) & 15;
 
        if (l1 + l2 <= 0)
                return;
 
        if (!d3d->sltexture) {
-               if (osl1 == 0 && osl3 == 0)
+               if (d3d->scanline_osl1 == 0 && d3d->scanline_osl3 == 0)
                        return;
                if (!createsltexture (d3d))
                        return;
@@ -1719,7 +1722,6 @@ static int createmask2texture (struct d3dstruct *d3d, const TCHAR *filename)
 {
        struct AmigaMonitor *mon = &AMonitors[d3d - d3ddata];
        struct zfile *zf;
-       int size;
        LPDIRECT3DTEXTURE9 tx;
        HRESULT hr;
        TCHAR tmp[MAX_DPATH];
@@ -2464,51 +2466,51 @@ static int restoredeviceobjects (struct d3dstruct *d3d)
                        break;
                }
                for (int i = 0; i < MAX_FILTERSHADERS; i++) {
-                       if (filterd3d->gfx_filtershader[i][0]) {
+                       if (d3d->filterd3d->gfx_filtershader[i][0]) {
                                struct shaderdata *s = allocshaderslot (d3d, SHADERTYPE_BEFORE);
-                               if (!psEffect_LoadEffect (d3d, filterd3d->gfx_filtershader[i], true, s, i)) {
-                                       filterd3d->gfx_filtershader[i][0] = changed_prefs.gf[filterd3didx].gfx_filtershader[i][0] = 0;
+                               if (!psEffect_LoadEffect (d3d, d3d->filterd3d->gfx_filtershader[i], true, s, i)) {
+                                       d3d->filterd3d->gfx_filtershader[i][0] = changed_prefs.gf[d3d->filterd3didx].gfx_filtershader[i][0] = 0;
                                        break;
                                }
                        }
-                       if (filterd3d->gfx_filtermask[i][0]) {
+                       if (d3d->filterd3d->gfx_filtermask[i][0]) {
                                struct shaderdata *s = allocshaderslot (d3d, SHADERTYPE_MASK_BEFORE);
-                               createmasktexture (d3d, filterd3d->gfx_filtermask[i], s);
+                               createmasktexture (d3d, d3d->filterd3d->gfx_filtermask[i], s);
                        }
                }
-               if (filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS][0]) {
+               if (d3d->filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS][0]) {
                        struct shaderdata *s = allocshaderslot (d3d, SHADERTYPE_MIDDLE);
-                       if (!psEffect_LoadEffect (d3d, filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS], true, s, 2 * MAX_FILTERSHADERS)) {
-                               filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS][0] = changed_prefs.gf[filterd3didx].gfx_filtershader[2 * MAX_FILTERSHADERS][0] = 0;
+                       if (!psEffect_LoadEffect (d3d, d3d->filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS], true, s, 2 * MAX_FILTERSHADERS)) {
+                               d3d->filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS][0] = changed_prefs.gf[d3d->filterd3didx].gfx_filtershader[2 * MAX_FILTERSHADERS][0] = 0;
                        }
                }
-               if (filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS][0]) {
+               if (d3d->filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS][0]) {
                        struct shaderdata *s = allocshaderslot (d3d, SHADERTYPE_MASK_AFTER);
-                       createmasktexture (d3d, filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS], s);
+                       createmasktexture (d3d, d3d->filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS], s);
                }
                for (int i = 0; i < MAX_FILTERSHADERS; i++) {
-                       if (filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS][0]) {
+                       if (d3d->filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS][0]) {
                                struct shaderdata *s = allocshaderslot (d3d, SHADERTYPE_AFTER);
-                               if (!psEffect_LoadEffect (d3d, filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS], true, s, i + MAX_FILTERSHADERS)) {
-                                       filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS][0] = changed_prefs.gf[filterd3didx].gfx_filtershader[i + MAX_FILTERSHADERS][0] = 0;
+                               if (!psEffect_LoadEffect (d3d, d3d->filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS], true, s, i + MAX_FILTERSHADERS)) {
+                                       d3d->filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS][0] = changed_prefs.gf[d3d->filterd3didx].gfx_filtershader[i + MAX_FILTERSHADERS][0] = 0;
                                        break;
                                }
                        }
-                       if (filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS][0]) {
+                       if (d3d->filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS][0]) {
                                struct shaderdata *s = allocshaderslot (d3d, SHADERTYPE_MASK_AFTER);
-                               createmasktexture (d3d, filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS], s);
+                               createmasktexture (d3d, d3d->filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS], s);
                        }
                }
                break;
        }
-       if (filterd3d->gfx_filter_scanlines > 0) {
+       if (d3d->filterd3d->gfx_filter_scanlines > 0) {
                createsltexture(d3d);
                createscanlines(d3d, 1);
        }
        if (wasshader && !shaderon)
                write_log (_T("Falling back to non-shader mode\n"));
 
-       createmask2texture (d3d, filterd3d->gfx_filteroverlay);
+       createmask2texture (d3d, d3d->filterd3d->gfx_filteroverlay);
 
        createledtexture (d3d);
 
@@ -2659,8 +2661,8 @@ static const TCHAR *D3D_init2 (struct d3dstruct *d3d, HWND ahwnd, int w_w, int w
        struct apmode ap;
        D3DADAPTER_IDENTIFIER9 did;
 
-       filterd3didx = ad->picasso_on;
-       filterd3d = &currprefs.gf[filterd3didx];
+       d3d->filterd3didx = ad->picasso_on;
+       d3d->filterd3d = &currprefs.gf[d3d->filterd3didx];
 
        D3D_free2 (d3d);
        if (!currprefs.gfx_api) {
@@ -2956,11 +2958,11 @@ static const TCHAR *D3D_init2 (struct d3dstruct *d3d, HWND ahwnd, int w_w, int w
 
        d3d->required_sl_texture_w = w_w;
        d3d->required_sl_texture_h = w_h;
-       if (filterd3d->gfx_filter_scanlines > 0 && (d3d->max_texture_w < w_w || d3d->max_texture_h < w_h)) {
+       if (d3d->filterd3d->gfx_filter_scanlines > 0 && (d3d->max_texture_w < w_w || d3d->max_texture_h < w_h)) {
                gui_message (_T("%s: %d * %d or bigger texture support required for scanlines (max is only %d * %d)\n"),
                        D3DHEAD, _T("Scanlines disabled."),
                        d3d->required_sl_texture_w, d3d->required_sl_texture_h, d3d->max_texture_w, d3d->max_texture_h);
-               changed_prefs.gf[filterd3didx].gfx_filter_scanlines = filterd3d->gfx_filter_scanlines = 0;
+               changed_prefs.gf[d3d->filterd3didx].gfx_filter_scanlines = d3d->filterd3d->gfx_filter_scanlines = 0;
        }
 
        switch (depth)
@@ -3015,7 +3017,7 @@ static const TCHAR *D3D_init2 (struct d3dstruct *d3d, HWND ahwnd, int w_w, int w
 
        hr = d3d->d3ddev->CreateOffscreenPlainSurface(w_w, w_h, d3d->tformat, D3DPOOL_SYSTEMMEM, &d3d->screenshotsurface, NULL);
        if (FAILED(hr)) {
-               write_log(_T("%s: CreateOffscreenPlainSurface failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
+               write_log(_T("%s: CreateOffscreenPlainSurface RT failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
        }
 
        return 0;
@@ -3475,7 +3477,7 @@ static void D3D_render2(struct d3dstruct *d3d, int mode)
                        if (FAILED (hr = postEffect->SetTechnique (d3d->postTechniquePlain)))
                                write_log (_T("%s: SetTechnique(postTechniquePlain) failed: %s\n"), D3DHEAD, D3D_ErrorString (hr));
                }
-               hr = postEffect->SetInt (d3d->postFilterMode, filterd3d->gfx_filter_bilinear ? D3DTEXF_LINEAR : D3DTEXF_POINT);
+               hr = postEffect->SetInt (d3d->postFilterMode, d3d->filterd3d->gfx_filter_bilinear ? D3DTEXF_LINEAR : D3DTEXF_POINT);
 
                if (FAILED (hr = postEffect->SetTexture (d3d->postSourceTextureHandle, srctex)))
                        write_log (_T("%s: SetTexture(srctex) failed: %s\n"), D3DHEAD, D3D_ErrorString (hr));
@@ -3549,7 +3551,7 @@ static void D3D_render2(struct d3dstruct *d3d, int mode)
                hr = d3d->d3ddev->SetTransform (D3DTS_WORLD, &d3d->m_matWorld);
                hr = d3d->d3ddev->SetTexture (0, srctex);
                hr = d3d->d3ddev->DrawPrimitive (D3DPT_TRIANGLESTRIP, 0, 2);
-               int bl = filterd3d->gfx_filter_bilinear ? D3DTEXF_LINEAR : D3DTEXF_POINT;
+               int bl = d3d->filterd3d->gfx_filter_bilinear ? D3DTEXF_LINEAR : D3DTEXF_POINT;
                hr = d3d->d3ddev->SetSamplerState(0, D3DSAMP_MINFILTER, bl);
                hr = d3d->d3ddev->SetSamplerState(0, D3DSAMP_MAGFILTER, bl);
                hr = d3d->d3ddev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
@@ -3612,20 +3614,20 @@ static void D3D_render2(struct d3dstruct *d3d, int mode)
                        MatrixScaling (&t, w, h, 0);
 
                        v.x = 0;
-                       if (filterd3d->gfx_filteroverlay_pos.x == -1)
+                       if (d3d->filterd3d->gfx_filteroverlay_pos.x == -1)
                                v.x = (d3d->window_w - (d3d->mask2texture_w * w)) / 2;
-                       else if (filterd3d->gfx_filteroverlay_pos.x > -24000)
-                               v.x = filterd3d->gfx_filteroverlay_pos.x;
+                       else if (d3d->filterd3d->gfx_filteroverlay_pos.x > -24000)
+                               v.x = d3d->filterd3d->gfx_filteroverlay_pos.x;
                        else
-                               v.x = (d3d->window_w - (d3d->mask2texture_w * w)) / 2 + (-filterd3d->gfx_filteroverlay_pos.x - 30100) * d3d->window_w / 100.0;
+                               v.x = (d3d->window_w - (d3d->mask2texture_w * w)) / 2 + (-d3d->filterd3d->gfx_filteroverlay_pos.x - 30100) * d3d->window_w / 100.0;
 
                        v.y = 0;
-                       if (filterd3d->gfx_filteroverlay_pos.y == -1)
+                       if (d3d->filterd3d->gfx_filteroverlay_pos.y == -1)
                                v.y = (d3d->window_h - (d3d->mask2texture_h * h)) / 2;
-                       else if (filterd3d->gfx_filteroverlay_pos.y > -24000)
-                               v.y = filterd3d->gfx_filteroverlay_pos.y;
+                       else if (d3d->filterd3d->gfx_filteroverlay_pos.y > -24000)
+                               v.y = d3d->filterd3d->gfx_filteroverlay_pos.y;
                        else
-                               v.y = (d3d->window_h - (d3d->mask2texture_h * h)) / 2 + (-filterd3d->gfx_filteroverlay_pos.y - 30100) * d3d->window_h / 100.0;
+                               v.y = (d3d->window_h - (d3d->mask2texture_h * h)) / 2 + (-d3d->filterd3d->gfx_filteroverlay_pos.y - 30100) * d3d->window_h / 100.0;
 
                        v.x /= w;
                        v.y /= h;
@@ -3992,30 +3994,40 @@ static void xD3D_guimode(int monid, int guion)
        d3d->guimode = guion;
 }
 
-LPDIRECT3DSURFACE9 D3D_capture(int monid, int *w, int *h, int *bits)
+LPDIRECT3DSURFACE9 D3D_capture(int monid, int *w, int *h, int *bits, bool rendertarget)
 {
        struct d3dstruct *d3d = &d3ddata[monid];
-       LPDIRECT3DSURFACE9 rt;
        HRESULT hr;
+       LPDIRECT3DSURFACE9 ret = NULL;
 
        waitfakemode(d3d);
        if (!isd3d(d3d))
                return NULL;
-       hr = d3d->d3ddev->GetRenderTarget(0, &rt);
-       if (FAILED(hr)) {
-               write_log(_T("%s: GetRenderTarget() failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
-               return NULL;
-       }
-       hr = d3d->d3ddev->GetRenderTargetData(rt, d3d->screenshotsurface);
-       rt->Release();
-       if (FAILED(hr)) {
-               write_log(_T("%s: GetRenderTargetData() failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
-               return NULL;
+       if (rendertarget) {
+               LPDIRECT3DSURFACE9 rt;
+               hr = d3d->d3ddev->GetRenderTarget(0, &rt);
+               if (FAILED(hr)) {
+                       write_log(_T("%s: D3D_capture() GetRenderTarget() failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
+                       return NULL;
+               }
+               hr = d3d->d3ddev->GetRenderTargetData(rt, d3d->screenshotsurface);
+               rt->Release();
+               if (FAILED(hr)) {
+                       write_log(_T("%s: D3D_capture() GetRenderTargetData() failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
+                       return NULL;
+               }
+               ret = d3d->screenshotsurface;
+       } else {
+               hr = d3d->texture->GetSurfaceLevel(0, &ret);
+               if (FAILED(hr)) {
+                       write_log(_T("%s: D3D_capture() GetSurfaceLevel() failed: %s\n"), D3DHEAD, D3D_ErrorString(hr));
+                       return NULL;
+               }
        }
        *w = d3d->window_w;
        *h = d3d->window_h;
        *bits = d3d->t_depth;
-       return d3d->screenshotsurface;
+       return ret;
 }
 
 static HDC xD3D_getDC(int monid, HDC hdc)
index 850f23e7835e15becbc1b8aa8d70cbb4274a2c28..c8cc598571778479c57cfa7b99d9affb0a61aa3d 100644 (file)
@@ -27,8 +27,8 @@ extern int(*D3D_debug)(int, int);
 extern void(*D3D_led)(int, int, int);
 extern bool(*D3D_getscanline)(int*, bool*);
 
-extern LPDIRECT3DSURFACE9 D3D_capture(int, int*,int*,int*);
-extern bool D3D11_capture(int, void**,int*, int*,int*);
+extern LPDIRECT3DSURFACE9 D3D_capture(int, int*,int*,int*,bool);
+extern bool D3D11_capture(int, void**,int*, int*,int*,bool);
 
 void D3D_getpixelformat(int depth, int *rb, int *gb, int *bb, int *rs, int *gs, int *bs, int *ab, int *as, int *a);
 
index f2fefeeadc8a75a7249a2c256cd68797ff266292..f87862d7a7962cff8ac2b87324aadb94292b58b6 100644 (file)
@@ -71,8 +71,6 @@ static HMODULE hd3d11, hdxgi, hd3dcompiler, dwmapi;
 
 static int d3d11_feature_level;
 
-static struct gfx_filterdata *filterd3d;
-static int filterd3didx;
 static int leds[LED_MAX];
 static int debugcolors;
 static bool cannoclear;
@@ -232,7 +230,7 @@ struct d3d11struct
        ID3D11ShaderResourceView *sltexturerv;
        ID3D11Texture2D *texture2d, *texture2dstaging;
        ID3D11Texture2D *sltexture;
-       ID3D11Texture2D *screenshottexture;
+       ID3D11Texture2D *screenshottexturert, *screenshottexturetx;
        ID3D11VertexShader *m_vertexShader;
        ID3D11PixelShader *m_pixelShader, *m_pixelShaderSL, *m_pixelShaderMask;
        ID3D11SamplerState *m_sampleState_point_clamp, *m_sampleState_linear_clamp;
@@ -295,6 +293,10 @@ struct d3d11struct
        float cursor_x, cursor_y;
        bool cursor_v, cursor_scale;
 
+       struct gfx_filterdata *filterd3d;
+       int filterd3didx;
+       int scanline_osl1, scanline_osl2, scanline_osl3;
+
        struct shaderdata11 shaders[MAX_SHADERS];
        ID3DX11EffectTechnique *technique;
        ID3DX11EffectPass *effectpass;
@@ -1716,7 +1718,8 @@ static void FreeTextures(struct d3d11struct *d3d)
 {
        FreeTexture2D(&d3d->texture2d, &d3d->texture2drv);
        FreeTexture2D(&d3d->texture2dstaging, NULL);
-       FreeTexture2D(&d3d->screenshottexture, NULL);
+       FreeTexture2D(&d3d->screenshottexturetx, NULL);
+       FreeTexture2D(&d3d->screenshottexturert, NULL);
 
        freesprite(&d3d->osd);
        freesprite(&d3d->hwsprite);
@@ -1927,6 +1930,14 @@ static bool CreateTexture(struct d3d11struct *d3d)
                return false;
        }
 
+       desc.Width = d3d->m_screenWidth;
+       desc.Height = d3d->m_screenHeight;
+       desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+       hr = d3d->m_device->CreateTexture2D(&desc, nullptr, &d3d->screenshottexturetx);
+       if (FAILED(hr)) {
+               write_log(_T("CreateTexture2D (screenshot tx) failed: %08x\n"), hr);
+       }
+
        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
        srvDesc.Texture2D.MostDetailedMip = 0;
        srvDesc.Texture2D.MipLevels = desc.MipLevels;
@@ -1947,9 +1958,9 @@ static bool CreateTexture(struct d3d11struct *d3d)
                desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
                desc.Usage = D3D11_USAGE_STAGING;
 
-               hr = d3d->m_device->CreateTexture2D(&desc, nullptr, &d3d->screenshottexture);
+               hr = d3d->m_device->CreateTexture2D(&desc, nullptr, &d3d->screenshottexturert);
                if (FAILED(hr)) {
-                       write_log(_T("CreateTexture2D (screenshot) failed: %08x\n"), hr);
+                       write_log(_T("CreateTexture2D (screenshot rt) failed: %08x\n"), hr);
                }
                pSurface->Release();
        }
@@ -2130,33 +2141,34 @@ static void createscanlines(struct d3d11struct *d3d, int force)
 {
        HRESULT hr;
        D3D11_MAPPED_SUBRESOURCE map;
-       static int osl1, osl2, osl3;
        int sl4, sl42;
        int l1, l2;
        int x, y, yy;
        uae_u8 *sld, *p;
        int bpp;
 
-       if (osl1 == filterd3d->gfx_filter_scanlines && osl3 == filterd3d->gfx_filter_scanlinelevel && osl2 == filterd3d->gfx_filter_scanlineratio && !force)
+       if (d3d->scanline_osl1 == d3d->filterd3d->gfx_filter_scanlines &&
+               d3d->scanline_osl3 == d3d->filterd3d->gfx_filter_scanlinelevel &&
+               d3d->scanline_osl2 == d3d->filterd3d->gfx_filter_scanlineratio && !force)
                return;
        bpp = 4;
-       osl1 = filterd3d->gfx_filter_scanlines;
-       osl3 = filterd3d->gfx_filter_scanlinelevel;
-       osl2 = filterd3d->gfx_filter_scanlineratio;
-       sl4 = filterd3d->gfx_filter_scanlines * 16 / 100;
-       sl42 = filterd3d->gfx_filter_scanlinelevel * 16 / 100;
+       d3d->scanline_osl1 = d3d->filterd3d->gfx_filter_scanlines;
+       d3d->scanline_osl3 = d3d->filterd3d->gfx_filter_scanlinelevel;
+       d3d->scanline_osl2 = d3d->filterd3d->gfx_filter_scanlineratio;
+       sl4 = d3d->filterd3d->gfx_filter_scanlines * 16 / 100;
+       sl42 = d3d->filterd3d->gfx_filter_scanlinelevel * 16 / 100;
        if (sl4 > 15)
                sl4 = 15;
        if (sl42 > 15)
                sl42 = 15;
-       l1 = (filterd3d->gfx_filter_scanlineratio >> 0) & 15;
-       l2 = (filterd3d->gfx_filter_scanlineratio >> 4) & 15;
+       l1 = (d3d->filterd3d->gfx_filter_scanlineratio >> 0) & 15;
+       l2 = (d3d->filterd3d->gfx_filter_scanlineratio >> 4) & 15;
 
        if (l1 + l2 <= 0)
                return;
 
        if (!d3d->sltexture) {
-               if (osl1 == 0 && osl3 == 0)
+               if (d3d->scanline_osl1 == 0 && d3d->scanline_osl3 == 0)
                        return;
                if (!createsltexture(d3d))
                        return;
@@ -3250,8 +3262,8 @@ static int xxD3D11_init2(HWND ahwnd, int monid, int w_w, int w_h, int t_w, int t
 
        write_log(_T("D3D11 init start. (%d*%d) (%d*%d) RTG=%d Depth=%d.\n"), w_w, w_h, t_w, t_h, ad->picasso_on, depth);
 
-       filterd3didx = ad->picasso_on;
-       filterd3d = &currprefs.gf[filterd3didx];
+       d3d->filterd3didx = ad->picasso_on;
+       d3d->filterd3d = &currprefs.gf[d3d->filterd3didx];
 
        d3d->delayedfs = 0;
        d3d->device_errors = 0;
@@ -3945,8 +3957,8 @@ static void TextureShaderClass_RenderShader(struct d3d11struct *d3d)
        }
 
        // Set the sampler state in the pixel shader.
-       d3d->m_deviceContext->PSSetSamplers(0, 1, filterd3d->gfx_filter_bilinear ? &d3d->m_sampleState_linear_clamp : &d3d->m_sampleState_point_clamp);
-       d3d->m_deviceContext->PSSetSamplers(1, 1, filterd3d->gfx_filter_bilinear ? &d3d->m_sampleState_linear_wrap : &d3d->m_sampleState_point_wrap);
+       d3d->m_deviceContext->PSSetSamplers(0, 1, d3d->filterd3d->gfx_filter_bilinear ? &d3d->m_sampleState_linear_clamp : &d3d->m_sampleState_point_clamp);
+       d3d->m_deviceContext->PSSetSamplers(1, 1, d3d->filterd3d->gfx_filter_bilinear ? &d3d->m_sampleState_linear_wrap : &d3d->m_sampleState_point_wrap);
 
        // Render the triangle.
        d3d->m_deviceContext->DrawIndexed(INDEXCOUNT, 0, 0);
@@ -4290,46 +4302,46 @@ static struct shaderdata11 *allocshaderslot(struct d3d11struct *d3d, int type)
 static bool restore(struct d3d11struct *d3d)
 {
        for (int i = 0; i < MAX_FILTERSHADERS; i++) {
-               if (filterd3d->gfx_filtershader[i][0]) {
+               if (d3d->filterd3d->gfx_filtershader[i][0]) {
                        struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_BEFORE);
-                       if (!psEffect_LoadEffect(d3d, filterd3d->gfx_filtershader[i], s, i)) {
+                       if (!psEffect_LoadEffect(d3d, d3d->filterd3d->gfx_filtershader[i], s, i)) {
                                freeshaderdata(s);
-                               filterd3d->gfx_filtershader[i][0] = changed_prefs.gf[filterd3didx].gfx_filtershader[i][0] = 0;
+                               d3d->filterd3d->gfx_filtershader[i][0] = changed_prefs.gf[d3d->filterd3didx].gfx_filtershader[i][0] = 0;
                                break;
                        }
                }
-               if (filterd3d->gfx_filtermask[i][0]) {
+               if (d3d->filterd3d->gfx_filtermask[i][0]) {
                        struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_MASK_BEFORE);
-                       if (!createmasktexture(d3d, filterd3d->gfx_filtermask[i], s)) {
+                       if (!createmasktexture(d3d, d3d->filterd3d->gfx_filtermask[i], s)) {
                                freeshaderdata(s);
                        }
                }
        }
-       if (filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS][0]) {
+       if (d3d->filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS][0]) {
                struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_MIDDLE);
-               if (!psEffect_LoadEffect(d3d, filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS], s, 2 * MAX_FILTERSHADERS)) {
+               if (!psEffect_LoadEffect(d3d, d3d->filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS], s, 2 * MAX_FILTERSHADERS)) {
                        freeshaderdata(s);
-                       filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS][0] = changed_prefs.gf[filterd3didx].gfx_filtershader[2 * MAX_FILTERSHADERS][0] = 0;
+                       d3d->filterd3d->gfx_filtershader[2 * MAX_FILTERSHADERS][0] = changed_prefs.gf[d3d->filterd3didx].gfx_filtershader[2 * MAX_FILTERSHADERS][0] = 0;
                }
        }
-       if (filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS][0]) {
+       if (d3d->filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS][0]) {
                struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_MASK_AFTER);
-               if (!createmasktexture(d3d, filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS], s)) {
+               if (!createmasktexture(d3d, d3d->filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS], s)) {
                        freeshaderdata(s);
                }
        }
        for (int i = 0; i < MAX_FILTERSHADERS; i++) {
-               if (filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS][0]) {
+               if (d3d->filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS][0]) {
                        struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_AFTER);
-                       if (!psEffect_LoadEffect(d3d, filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS], s, i + MAX_FILTERSHADERS)) {
+                       if (!psEffect_LoadEffect(d3d, d3d->filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS], s, i + MAX_FILTERSHADERS)) {
                                freeshaderdata(s);
-                               filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS][0] = changed_prefs.gf[filterd3didx].gfx_filtershader[i + MAX_FILTERSHADERS][0] = 0;
+                               d3d->filterd3d->gfx_filtershader[i + MAX_FILTERSHADERS][0] = changed_prefs.gf[d3d->filterd3didx].gfx_filtershader[i + MAX_FILTERSHADERS][0] = 0;
                                break;
                        }
                }
-               if (filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS][0]) {
+               if (d3d->filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS][0]) {
                        struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_MASK_AFTER);
-                       if (!createmasktexture(d3d, filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS], s)) {
+                       if (!createmasktexture(d3d, d3d->filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS], s)) {
                                freeshaderdata(s);
                        }
                }
@@ -4337,7 +4349,7 @@ static bool restore(struct d3d11struct *d3d)
 
 
        createscanlines(d3d, 1);
-       createmask2texture(d3d, filterd3d->gfx_filteroverlay);
+       createmask2texture(d3d, d3d->filterd3d->gfx_filteroverlay);
 
        int w = d3d->m_bitmapWidth;
        int h = d3d->m_bitmapHeight;
@@ -4841,31 +4853,40 @@ static HDC xD3D_getDC(int monid, HDC hdc)
        }
 }
 
-bool D3D11_capture(int monid, void **data, int *w, int *h, int *pitch)
+bool D3D11_capture(int monid, void **data, int *w, int *h, int *pitch, bool rendertarget)
 {
        struct d3d11struct *d3d = &d3d11data[monid];
        HRESULT hr;
+       ID3D11Texture2D *screenshottexture = rendertarget ? d3d->screenshottexturert : d3d->screenshottexturetx;
 
-       if (!d3d->screenshottexture)
+       if (!screenshottexture)
                return false;
 
        if (!w || !h) {
-               d3d->m_deviceContext->Unmap(d3d->screenshottexture, 0);
+               d3d->m_deviceContext->Unmap(screenshottexture, 0);
                return true;
        } else {
                D3D11_MAPPED_SUBRESOURCE map;
                ID3D11Resource* pSurface = NULL;
-               d3d->m_renderTargetView->GetResource(&pSurface);
+               ID3D11Resource* pSurfaceRelease = NULL;
+               if (rendertarget) {
+                       d3d->m_renderTargetView->GetResource(&pSurface);
+                       pSurfaceRelease = pSurface;
+               } else {
+                       pSurface = d3d->texture2dstaging;
+               }
                if (pSurface) {
-                       d3d->m_deviceContext->CopyResource(d3d->screenshottexture, pSurface);
                        D3D11_TEXTURE2D_DESC desc;
-                       d3d->screenshottexture->GetDesc(&desc);
-                       hr = d3d->m_deviceContext->Map(d3d->screenshottexture, 0, D3D11_MAP_READ, 0, &map);
+                       d3d->m_deviceContext->CopyResource(screenshottexture, pSurface);
+                       screenshottexture->GetDesc(&desc);
+                       hr = d3d->m_deviceContext->Map(screenshottexture, 0, D3D11_MAP_READ, 0, &map);
                        if (FAILED(hr)) {
                                write_log(_T("Screenshot DeviceContext->Map() failed %08x\n"), hr);
                                return false;
                        }
-                       pSurface->Release();
+                       if (pSurfaceRelease) {
+                               pSurfaceRelease->Release();
+                       }
                        *data = map.pData;
                        *pitch = map.RowPitch;
                        *w = desc.Width;
index c68bd8e5a4fefa745e67e95d5014a5fda776be0b..da7d7e8b141fef7a5c09c4a847a4022de8611b27 100644 (file)
@@ -21,6 +21,7 @@
 #include "drawing.h"
 #include "fsdb.h"
 #include "zfile.h"
+#include "picasso96_win.h"
 
 #include "png.h"
 
@@ -116,6 +117,9 @@ static int screenshot_prepare(int monid, int imagemode, struct vidbuffer *vb, bo
        HGDIOBJ hgdiobj;
        int bits;
        int depth = usealpha() ? 32 : 24;
+       bool renderTarget = true;
+
+       lockrtg();
 
        screenshot_free ();
 
@@ -177,8 +181,11 @@ static int screenshot_prepare(int monid, int imagemode, struct vidbuffer *vb, bo
                        rgb_rs2 = rgb_rs;
                        rgb_as2 = rgb_as;
                }
-               if (src == NULL)
+               if (src == NULL) {
+                       if (WIN32GFX_IsPicassoScreen(mon))
+                               renderTarget = false;
                        goto donormal;
+               }
                if (width == 0 || height == 0) {
                        if (needfree) {
                                if (WIN32GFX_IsPicassoScreen(mon))
@@ -413,19 +420,23 @@ donormal:
                bool d3dcaptured = false;
                width = WIN32GFX_GetWidth(mon);
                height = WIN32GFX_GetHeight(mon);
-
+               if (!renderTarget && WIN32GFX_IsPicassoScreen(mon)) {
+                       struct picasso96_state_struct *state = &picasso96_state[monid];
+                       width = state->Width;
+                       height = state->Height;
+               }
                if (D3D_isenabled(0) == 2) {
                        int w, h, pitch, bits = 32;
                        void *data;
-                       bool got = D3D11_capture(monid, &data, &w, &h, &pitch);
+                       bool got = D3D11_capture(monid, &data, &w, &h, &pitch, renderTarget);
 
-                       int dpitch = (((w * depth + 31) & ~31) / 8);
-                       lpvBits = xmalloc(uae_u8, dpitch * h);
+                       int dpitch = (((width * depth + 31) & ~31) / 8);
+                       lpvBits = xmalloc(uae_u8, dpitch * height);
 
                        ZeroMemory(bi, sizeof(bi));
                        bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-                       bi->bmiHeader.biWidth = w;
-                       bi->bmiHeader.biHeight = h;
+                       bi->bmiHeader.biWidth = width;
+                       bi->bmiHeader.biHeight = height;
                        bi->bmiHeader.biPlanes = 1;
                        bi->bmiHeader.biBitCount = depth;
                        bi->bmiHeader.biCompression = BI_RGB;
@@ -436,10 +447,10 @@ donormal:
                        bi->bmiHeader.biClrImportant = 0;
 
                        if (got && lpvBits) {
-                               for (int y = 0; y < h; y++) {
-                                       uae_u8 *d = (uae_u8*)lpvBits + (h - y - 1) * dpitch;
+                               for (int y = 0; y < h && y < height; y++) {
+                                       uae_u8 *d = (uae_u8*)lpvBits + (height - y - 1) * dpitch;
                                        uae_u32 *s = (uae_u32*)((uae_u8*)data + y * pitch);
-                                       for (int x = 0; x < w; x++) {
+                                       for (int x = 0; x < w && x < width; x++) {
                                                uae_u32 v = *s++;
                                                d[0] = v >> 0;
                                                d[1] = v >> 8;
@@ -454,24 +465,24 @@ donormal:
                                }
                        }
                        if (got)
-                               D3D11_capture(monid, NULL, NULL, NULL, NULL);
+                               D3D11_capture(monid, NULL, NULL, NULL, NULL, renderTarget);
                        d3dcaptured = true;
 
                } else if (D3D_isenabled(0) == 1) {
                        int w, h, bits;
                        HRESULT hr;
                        D3DLOCKED_RECT l;
-                       LPDIRECT3DSURFACE9 s = D3D_capture(monid, &w, &h, &bits);
+                       LPDIRECT3DSURFACE9 s = D3D_capture(monid, &w, &h, &bits, renderTarget);
                        if (s) {
                                hr = s->LockRect(&l, NULL, D3DLOCK_READONLY);
                                if (SUCCEEDED(hr)) {
-                                       int dpitch = (((w * depth + 31) & ~31) / 8);
-                                       lpvBits = xmalloc(uae_u8, dpitch * h); 
+                                       int dpitch = (((width * depth + 31) & ~31) / 8);
+                                       lpvBits = xmalloc(uae_u8, dpitch * height); 
 
                                        ZeroMemory(bi, sizeof(bi));
                                        bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-                                       bi->bmiHeader.biWidth = w;
-                                       bi->bmiHeader.biHeight = h;
+                                       bi->bmiHeader.biWidth = width;
+                                       bi->bmiHeader.biHeight = height;
                                        bi->bmiHeader.biPlanes = 1;
                                        bi->bmiHeader.biBitCount = depth;
                                        bi->bmiHeader.biCompression = BI_RGB;
@@ -483,10 +494,10 @@ donormal:
 
                                        if (lpvBits) {
                                                if (bits == 32) {
-                                                       for (int y = 0; y < h; y++) {
-                                                               uae_u8 *d = (uae_u8*)lpvBits + (h - y - 1) * dpitch;
+                                                       for (int y = 0; y < h && y < height; y++) {
+                                                               uae_u8 *d = (uae_u8*)lpvBits + (height - y - 1) * dpitch;
                                                                uae_u32 *s = (uae_u32*)((uae_u8*)l.pBits + y * l.Pitch);
-                                                               for (int x = 0; x < w; x++) {
+                                                               for (int x = 0; x < w && x < width; x++) {
                                                                        uae_u32 v = *s++;
                                                                        d[0] = v >> 0;
                                                                        d[1] = v >> 8;
@@ -500,10 +511,10 @@ donormal:
                                                                }
                                                        }
                                                } else if (bits == 16 || bits == 15) {
-                                                       for (int y = 0; y < h; y++) {
-                                                               uae_u8 *d = (uae_u8*)lpvBits + (h - y - 1) * dpitch;
+                                                       for (int y = 0; y < h && y < height; y++) {
+                                                               uae_u8 *d = (uae_u8*)lpvBits + (height - y - 1) * dpitch;
                                                                uae_u16 *s = (uae_u16*)((uae_u8*)l.pBits + y * l.Pitch);
-                                                               for (int x = 0; x < w; x++) {
+                                                               for (int x = 0; x < w && x < width; x++) {
                                                                        uae_u16 v = s[x];
                                                                        uae_u16 v2 = v;
                                                                        if (bits == 16) {
@@ -579,11 +590,13 @@ donormal:
                if (!lpvBits)
                        goto oops;
        }
+       unlockrtg();
        screenshot_prepared = TRUE;
        return 1;
 
 oops:
        screenshot_free ();
+       unlockrtg();
        return 0;
 }