From 73a269e8609bb5f7d87f82ca7c7e5734009df96f Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 22 Sep 2018 20:27:24 +0300 Subject: [PATCH] Fix hardware RTG board screenshot/capture. Multimonitor scanline native/RTG fix. --- od-win32/avioutput.cpp | 55 ++++++++++------- od-win32/direct3d.cpp | 128 ++++++++++++++++++++++------------------ od-win32/direct3d.h | 4 +- od-win32/direct3d11.cpp | 109 ++++++++++++++++++++-------------- od-win32/screenshot.cpp | 57 +++++++++++------- 5 files changed, 207 insertions(+), 146 deletions(-) diff --git a/od-win32/avioutput.cpp b/od-win32/avioutput.cpp index 12492f30..6e49ac6e 100644 --- a/od-win32/avioutput.cpp +++ b/od-win32/avioutput.cpp @@ -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 diff --git a/od-win32/direct3d.cpp b/od-win32/direct3d.cpp index bcb78623..229d5dda 100644 --- a/od-win32/direct3d.cpp +++ b/od-win32/direct3d.cpp @@ -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) diff --git a/od-win32/direct3d.h b/od-win32/direct3d.h index 850f23e7..c8cc5985 100644 --- a/od-win32/direct3d.h +++ b/od-win32/direct3d.h @@ -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); diff --git a/od-win32/direct3d11.cpp b/od-win32/direct3d11.cpp index f2fefeea..f87862d7 100644 --- a/od-win32/direct3d11.cpp +++ b/od-win32/direct3d11.cpp @@ -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; diff --git a/od-win32/screenshot.cpp b/od-win32/screenshot.cpp index c68bd8e5..da7d7e8b 100644 --- a/od-win32/screenshot.cpp +++ b/od-win32/screenshot.cpp @@ -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; } -- 2.47.3