]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
D3D11 updates.
authorToni Wilen <twilen@winuae.net>
Sun, 19 Nov 2017 14:57:02 +0000 (16:57 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 19 Nov 2017 14:57:02 +0000 (16:57 +0200)
od-win32/d3dx.h [new file with mode: 0644]
od-win32/direct3d.cpp
od-win32/direct3d.h
od-win32/direct3d11.cpp
od-win32/screenshot.cpp
od-win32/win32.cpp
od-win32/win32_scaler.cpp
od-win32/win32gfx.cpp

diff --git a/od-win32/d3dx.h b/od-win32/d3dx.h
new file mode 100644 (file)
index 0000000..b1187f9
--- /dev/null
@@ -0,0 +1,295 @@
+
+class D3DXMATRIX
+{
+public:
+       float _11, _12, _13, _14;
+       float _21, _22, _23, _24;
+       float _31, _32, _33, _34;
+       float _41, _42, _43, _44;
+};
+
+class D3DXVECTOR2
+{
+public:
+       float x, y;
+       D3DXVECTOR2()
+       {
+       }
+       D3DXVECTOR2(float x, float y)
+       {
+               this->x = x;
+               this->y = y;
+       }
+};
+
+class D3DXVECTOR3
+{
+public:
+       float x, y, z;
+       D3DXVECTOR3()
+       {
+       }
+       D3DXVECTOR3(float x, float y, float z)
+       {
+               this->x = x;
+               this->y = y;
+               this->z = z;
+       }
+       D3DXVECTOR3 operator +(const D3DXVECTOR3 &v) const
+       {
+               return D3DXVECTOR3(x + v.x, y + v.y, z + v.z);
+       }
+};
+
+
+static D3DXVECTOR3 *xD3DXVec3Cross(D3DXVECTOR3 *pOut, const D3DXVECTOR3 *A, const D3DXVECTOR3 *B)
+{
+       pOut->x = A->y * B->z - B->y * A->z;
+       pOut->y = A->z * B->x - B->z * A->x;
+       pOut->z = A->x * B->y - B->x * A->y;
+       return pOut;
+}
+
+static D3DXVECTOR3 *xD3DXVec3TransformCoord(D3DXVECTOR3 * pOut, const D3DXVECTOR3 * pV, const D3DXMATRIX * pM)
+{
+       pOut->x = pV->x * pM->_11 + pV->y * pM->_21 + pV->z * pM->_31 + pM->_41;
+       pOut->y = pV->x * pM->_12 + pV->y * pM->_22 + pV->z * pM->_32 + pM->_42;
+       pOut->z = pV->x * pM->_13 + pV->y * pM->_23 + pV->z * pM->_33 + pM->_43;
+       float w = pV->x * pM->_14 + pV->y * pM->_24 + pV->z * pM->_34 + pM->_44;
+
+       pOut->x /= w;
+       pOut->y /= w;
+       pOut->z /= w;
+
+       return pOut;
+}
+
+static D3DXVECTOR3 *xD3DXVec3Normalize(D3DXVECTOR3 *pOut)
+{
+       float length = pOut->x * pOut->x + pOut->z * pOut->z + pOut->y * pOut->y;
+
+       if (length > 0.0f) {
+               length = sqrtf(length);
+               pOut->x /= length;
+               pOut->y /= length;
+               pOut->z /= length;
+               return pOut;
+       } else {
+               return pOut;
+       }
+}
+
+static D3DXVECTOR3 *xD3DXVec3Normalize(D3DXVECTOR3 *pOut, const D3DXVECTOR3 *pV)
+{
+       float length = pV->x * pV->x + pV->z * pV->z + pV->y * pV->y;
+
+       if (length > 0.0f) {
+               length = sqrtf(length);
+               pOut->x = pV->x / length;
+               pOut->y = pV->y / length;
+               pOut->z = pV->z / length;
+               return pOut;
+       } else {
+               return pOut;
+       }
+}
+
+static float xD3DXVec3Dot(const D3DXVECTOR3 *a, const D3DXVECTOR3 *b)
+{
+       return a->x * b->x + a->y * b->y + a->z * b->z;
+}
+
+static D3DXMATRIX* xD3DXMatrixLookAtLH(D3DXMATRIX *pOut, const D3DXVECTOR3 *pEye, const D3DXVECTOR3 *pAt, const D3DXVECTOR3 *pUp)
+{
+       D3DXVECTOR3 x, y, z;
+       z.x = pAt->x - pEye->x;
+       z.y = pAt->y - pEye->y;
+       z.z = pAt->z - pEye->z;
+
+       xD3DXVec3Normalize(&z);
+
+       xD3DXVec3Cross(&x, pUp, &z);
+       xD3DXVec3Normalize(&x);
+
+       xD3DXVec3Cross(&y, &z, &x);
+
+       pOut->_11 = x.x;
+       pOut->_12 = y.x;
+       pOut->_13 = z.x;
+       pOut->_14 = 0.0f;
+
+       pOut->_21 = x.y;
+       pOut->_22 = y.y;
+       pOut->_23 = z.y;
+       pOut->_24 = 0.0f;
+
+       pOut->_31 = x.z;
+       pOut->_32 = y.z;
+       pOut->_33 = z.z;
+       pOut->_34 = 0.0f;
+
+       pOut->_41 = -xD3DXVec3Dot(&x, pEye);
+       pOut->_42 = -xD3DXVec3Dot(&y, pEye);
+       pOut->_43 = -xD3DXVec3Dot(&z, pEye);
+       pOut->_44 = 1.0f;
+
+       return pOut;
+}
+static D3DXMATRIX *xD3DXMatrixTranspose(D3DXMATRIX *pOut, const D3DXMATRIX *pM)
+{
+       pOut->_11 = pM->_11;
+       pOut->_12 = pM->_21;
+       pOut->_13 = pM->_31;
+       pOut->_14 = pM->_41;
+
+       pOut->_21 = pM->_12;
+       pOut->_22 = pM->_22;
+       pOut->_23 = pM->_32;
+       pOut->_24 = pM->_42;
+
+       pOut->_31 = pM->_13;
+       pOut->_32 = pM->_23;
+       pOut->_33 = pM->_33;
+       pOut->_34 = pM->_43;
+
+       pOut->_41 = pM->_14;
+       pOut->_42 = pM->_24;
+       pOut->_43 = pM->_34;
+       pOut->_44 = pM->_44;
+
+       return pOut;
+}
+
+static D3DXMATRIX *xD3DXMatrixIdentity(D3DXMATRIX *pOut)
+{
+       pOut->_11 = 1.0f;
+       pOut->_12 = 0.0f;
+       pOut->_13 = 0.0f;
+       pOut->_14 = 0.0f;
+
+       pOut->_21 = 0.0f;
+       pOut->_22 = 1.0f;
+       pOut->_23 = 0.0f;
+       pOut->_24 = 0.0f;
+
+       pOut->_31 = 0.0f;
+       pOut->_32 = 0.0f;
+       pOut->_33 = 1.0f;
+       pOut->_34 = 0.0f;
+
+       pOut->_41 = 0.0f;
+       pOut->_42 = 0.0f;
+       pOut->_43 = 0.0f;
+       pOut->_44 = 1.0f;
+
+       return pOut;
+}
+
+static D3DXMATRIX *xD3DXMatrixOrthoLH(D3DXMATRIX *pOut, float w, float h, float zn, float zf)
+{
+       float d = zf - zn;
+
+       xD3DXMatrixIdentity(pOut);
+       pOut->_11 = 2.0f / float(w);
+       pOut->_22 = 2.0f / float(h);
+       pOut->_33 = 1.0f / d;
+       pOut->_43 = -zn / d;
+
+       return pOut;
+}
+
+static D3DXMATRIX *xD3DXMatrixMultiply(D3DXMATRIX * pOut, const D3DXMATRIX * pM1, const D3DXMATRIX * pM2)
+{
+       if (pOut == NULL) {
+               pOut = xD3DXMatrixIdentity(pOut);
+       }
+
+       pOut->_11 = pM1->_11 * pM2->_11 + pM1->_12 * pM2->_21 + pM1->_13 * pM2->_31 + pM1->_14 * pM2->_41;
+       pOut->_12 = pM1->_11 * pM2->_12 + pM1->_12 * pM2->_22 + pM1->_13 * pM2->_32 + pM1->_14 * pM2->_42;
+       pOut->_13 = pM1->_11 * pM2->_13 + pM1->_12 * pM2->_23 + pM1->_13 * pM2->_33 + pM1->_14 * pM2->_43;
+       pOut->_14 = pM1->_11 * pM2->_14 + pM1->_12 * pM2->_24 + pM1->_13 * pM2->_34 + pM1->_14 * pM2->_44;
+       pOut->_21 = pM1->_21 * pM2->_11 + pM1->_22 * pM2->_21 + pM1->_23 * pM2->_31 + pM1->_24 * pM2->_41;
+       pOut->_22 = pM1->_21 * pM2->_12 + pM1->_22 * pM2->_22 + pM1->_23 * pM2->_32 + pM1->_24 * pM2->_42;
+       pOut->_23 = pM1->_21 * pM2->_13 + pM1->_22 * pM2->_23 + pM1->_23 * pM2->_33 + pM1->_24 * pM2->_43;
+       pOut->_24 = pM1->_21 * pM2->_14 + pM1->_22 * pM2->_24 + pM1->_23 * pM2->_34 + pM1->_24 * pM2->_44;
+       pOut->_31 = pM1->_31 * pM2->_11 + pM1->_32 * pM2->_21 + pM1->_33 * pM2->_31 + pM1->_34 * pM2->_41;
+       pOut->_32 = pM1->_31 * pM2->_12 + pM1->_32 * pM2->_22 + pM1->_33 * pM2->_32 + pM1->_34 * pM2->_42;
+       pOut->_33 = pM1->_31 * pM2->_13 + pM1->_32 * pM2->_23 + pM1->_33 * pM2->_33 + pM1->_34 * pM2->_43;
+       pOut->_34 = pM1->_31 * pM2->_14 + pM1->_32 * pM2->_24 + pM1->_33 * pM2->_34 + pM1->_34 * pM2->_44;
+       pOut->_41 = pM1->_41 * pM2->_11 + pM1->_42 * pM2->_21 + pM1->_43 * pM2->_31 + pM1->_44 * pM2->_41;
+       pOut->_42 = pM1->_41 * pM2->_12 + pM1->_42 * pM2->_22 + pM1->_43 * pM2->_32 + pM1->_44 * pM2->_42;
+       pOut->_43 = pM1->_41 * pM2->_13 + pM1->_42 * pM2->_23 + pM1->_43 * pM2->_33 + pM1->_44 * pM2->_43;
+       pOut->_44 = pM1->_41 * pM2->_14 + pM1->_42 * pM2->_24 + pM1->_43 * pM2->_34 + pM1->_44 * pM2->_44;
+
+       return pOut;
+}
+
+static D3DXMATRIX *xD3DXMatrixRotationX(D3DXMATRIX * pOut, float Angle)
+{
+       if (pOut == NULL) {
+               pOut = xD3DXMatrixIdentity(pOut);
+       } else {
+               xD3DXMatrixIdentity(pOut);
+       }
+
+       float cosAng = cosf(Angle);
+       float sinAng = sinf(Angle);
+
+       pOut->_22 = cosAng;
+       pOut->_33 = cosAng;
+       pOut->_23 = sinAng;
+       pOut->_32 = -sinAng;
+
+       return pOut;
+}
+
+static D3DXMATRIX *xD3DXMatrixRotationY(D3DXMATRIX * pOut, float Angle)
+{
+       if (pOut == NULL) {
+               pOut = xD3DXMatrixIdentity(pOut);
+       } else {
+               xD3DXMatrixIdentity(pOut);
+       }
+
+       float cosAng = cosf(Angle);
+       float sinAng = sinf(Angle);
+
+       pOut->_11 = cosAng;
+       pOut->_33 = cosAng;
+       pOut->_13 = -sinAng;
+       pOut->_31 = sinAng;
+
+       return pOut;
+}
+
+static D3DXMATRIX *xD3DXMatrixRotationZ(D3DXMATRIX * pOut, float Angle)
+{
+       if (pOut == NULL) {
+               pOut = xD3DXMatrixIdentity(pOut);
+       } else {
+               xD3DXMatrixIdentity(pOut);
+       }
+
+       float cosAng = cosf(Angle);
+       float sinAng = sinf(Angle);
+
+       pOut->_11 = cosAng;
+       pOut->_22 = cosAng;
+       pOut->_12 = sinAng;
+       pOut->_21 = -sinAng;
+
+       return pOut;
+}
+
+static D3DXMATRIX *xD3DXMatrixRotationYawPitchRoll(D3DXMATRIX *pout, FLOAT yaw, FLOAT pitch, FLOAT roll) {
+       D3DXMATRIX m, pout1, pout2, pout3;
+
+       xD3DXMatrixIdentity(&pout3);
+       xD3DXMatrixRotationZ(&m, roll);
+       xD3DXMatrixMultiply(&pout2, &pout3, &m);
+       xD3DXMatrixRotationX(&m, pitch);
+       xD3DXMatrixMultiply(&pout1, &pout2, &m);
+       xD3DXMatrixRotationY(&m, yaw);
+       xD3DXMatrixMultiply(pout, &pout1, &m);
+       return pout;
+}
index 68cbe8f1535504969ccae3438c9e0322c15a1a6b..5ed59d401ffeb35a97cb33868c6108d71e0ab3cc 100644 (file)
@@ -3553,11 +3553,14 @@ static double xD3D_getrefreshrate (void)
        return dmode.RefreshRate;
 }
 
-static void xD3D_guimode (bool guion)
+static void xD3D_guimode (int guion)
 {
        struct d3dstruct *d3d = &d3ddata[0];
        HRESULT hr;
 
+       if (guion != 0 && guion != 1)
+               return;
+
        waitfakemode (d3d);
        if (!isd3d (d3d))
                return;
@@ -3627,11 +3630,13 @@ static HDC xD3D_getDC (HDC hdc)
 static int xD3D_isenabled(void)
 {
        struct d3dstruct *d3d = &d3ddata[0];
-       return d3d->d3d_enabled;
+       return d3d->d3d_enabled ? 1 : 0;
 }
 
 LPDIRECT3DTEXTURE9 D3D_getcursorsurface(void)
 {
+       if (currprefs.gfx_api == 2)
+               return NULL;
        struct d3dstruct *d3d = &d3ddata[0];
        return d3d->cursorsurfaced3d;
 }
@@ -3660,6 +3665,7 @@ void d3d9_select(void)
        D3D_vblank_reset = xD3D_vblank_reset;
        D3D_restore = xD3D_restore;
        D3D_resize = NULL;
+       D3D_change = NULL;
 }
 
 #endif
index 250dd97e23cb7361e202c9f930cdf96d94464fee..e33594905bb4dd8dfbafce61031daecf7c4540b1 100644 (file)
@@ -9,7 +9,7 @@ extern void(*D3D_showframe_special)(int);
 extern uae_u8* (*D3D_locktexture)(int*, int*, bool);
 extern void(*D3D_unlocktexture)(void);
 extern void(*D3D_flushtexture)(int miny, int maxy);
-extern void(*D3D_guimode)(bool);
+extern void(*D3D_guimode)(int);
 extern HDC(*D3D_getDC)(HDC hdc);
 extern int(*D3D_isenabled)(void);
 extern void(*D3D_clear)(void);
@@ -21,9 +21,11 @@ extern double(*D3D_getrefreshrate)(void);
 extern void(*D3D_vblank_reset)(double freq);
 extern void(*D3D_restore)(void); 
 extern void(*D3D_resize)(int);
+extern void(*D3D_change)(int);
 
 extern LPDIRECT3DSURFACE9 D3D_capture(int*,int*,int*);
 extern LPDIRECT3DTEXTURE9 D3D_getcursorsurface(void);
+extern bool D3D11_capture(void**,int*, int*,int*);
 
 void D3D_getpixelformat(int depth, int *rb, int *gb, int *bb, int *rs, int *gs, int *bs, int *ab, int *as, int *a);
 
index f56e4592d583c6f4189b923f8d41a73fbb6bcf35..fb96ac8d64b1e893a5b2ef5236bfe1ed3572f288 100644 (file)
@@ -5,7 +5,6 @@
 #include <DXGI1_5.h>
 #include <d3d11.h>
 #include <D3Dcompiler.h>
-#include <d3dx9.h>
 
 #include <wrl/client.h>
 using Microsoft::WRL::ComPtr;
@@ -22,6 +21,10 @@ using Microsoft::WRL::ComPtr;
 #include "uae.h"
 #include "custom.h"
 #include "gfxfilter.h"
+#include "zfile.h"
+#include "statusline.h"
+
+#include "d3dx.h"
 
 void (*D3D_free)(bool immediate);
 const TCHAR* (*D3D_init)(HWND ahwnd, int w_w, int h_h, int depth, int *freq, int mmult);
@@ -33,7 +36,7 @@ void(*D3D_showframe_special)(int);
 uae_u8* (*D3D_locktexture)(int*, int*, bool);
 void (*D3D_unlocktexture)(void);
 void (*D3D_flushtexture)(int miny, int maxy);
-void (*D3D_guimode)(bool);
+void (*D3D_guimode)(int);
 HDC (*D3D_getDC)(HDC hdc);
 int (*D3D_isenabled)(void);
 void (*D3D_clear)(void);
@@ -45,12 +48,29 @@ double (*D3D_getrefreshrate)(void);
 void (*D3D_vblank_reset)(double freq);
 void(*D3D_restore)(void);
 void(*D3D_resize)(int);
+void (*D3D_change)(int);
 
 static HANDLE hd3d11, hdxgi, hd3dcompiler;
 
 static struct gfx_filterdata *filterd3d;
 static int filterd3didx;
 
+#define SHADERTYPE_BEFORE 1
+#define SHADERTYPE_AFTER 2
+#define SHADERTYPE_MIDDLE 3
+#define SHADERTYPE_MASK_BEFORE 3
+#define SHADERTYPE_MASK_AFTER 4
+#define SHADERTYPE_POST 10
+
+struct shaderdata11
+{
+       int type;
+       ID3D11ShaderResourceView *masktexturerv;
+       ID3D11Texture2D *masktexture;
+       int masktexture_w, masktexture_h;
+};
+#define MAX_SHADERS (2 * MAX_FILTERSHADERS + 2)
+
 struct d3d11struct
 {
        IDXGISwapChain1* m_swapChain;
@@ -68,29 +88,52 @@ struct d3d11struct
        float m_positionX, m_positionY, m_positionZ;
        float m_rotationX, m_rotationY, m_rotationZ;
        D3DXMATRIX m_viewMatrix;
-       ID3D11ShaderResourceView *texture;
+       ID3D11ShaderResourceView *texture2drv;
+       ID3D11ShaderResourceView *sltexturerv;
+       ID3D11ShaderResourceView *ledtexturerv;
        ID3D11Texture2D *texture2d, *texture2dstaging;
-       ID3D11VertexShader* m_vertexShader;
-       ID3D11PixelShader* m_pixelShader;
-       ID3D11SamplerState* m_sampleState;
-       ID3D11InputLayout* m_layout;
+       ID3D11Texture2D *sltexture, *mask2texture;
+       ID3D11Texture2D *screenshottexture;
+       ID3D11Texture2D *ledtexture;
+       ID3D11VertexShader *m_vertexShader;
+       ID3D11PixelShader *m_pixelShader, *m_pixelShaderSL, *m_pixelShaderMask;
+       ID3D11SamplerState *m_sampleState_point_clamp, *m_sampleState_linear_clamp;
+       ID3D11SamplerState *m_sampleState_point_wrap, *m_sampleState_linear_wrap;
+       ID3D11InputLayout *m_layout;
        int texturelocked;
        DXGI_FORMAT format;
        bool m_tearingSupport;
        int dmult;
        int xoffset, yoffset;
+       float xmult, ymult;
        DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
        DXGI_SWAP_CHAIN_FULLSCREEN_DESC  fsSwapChainDesc;
+       IDXGIOutput *outputAdapter;
        HWND ahwnd;
        int fsmode;
        bool fsmodechange;
        bool invalidmode;
+
+       float mask2texture_w, mask2texture_h, mask2texture_ww, mask2texture_wh;
+       float mask2texture_wwx, mask2texture_hhx, mask2texture_minusx, mask2texture_minusy;
+       float mask2texture_multx, mask2texture_multy, mask2texture_offsetw;
+       RECT mask2rect;
+
+       IDXGISurface1 *hdc_surface;
+
+       RECT sr2, dr2, zr2;
+       int guimode;
+       int ledwidth, ledheight;
+       int statusbar_hx, statusbar_vx;
+
+       struct shaderdata11 shaders[MAX_SHADERS];
 };
 
 struct VertexType
 {
        D3DXVECTOR3 position;
        D3DXVECTOR2 texture;
+       D3DXVECTOR2 sltexture;
 };
 
 struct MatrixBufferType
@@ -112,102 +155,313 @@ typedef HRESULT (WINAPI* D3DCOMPILEFROMFILE)(LPCWSTR pFileName,
        UINT Flags2,
        ID3DBlob** ppCode,
        ID3DBlob** ppErrorMsgs);
+typedef HRESULT(WINAPI* D3DCOMPILE)(LPCVOID pSrcData,
+       SIZE_T SrcDataSize,
+       LPCSTR pSourceName,
+       CONST D3D_SHADER_MACRO* pDefines,
+       ID3DInclude* pInclude,
+       LPCSTR pEntrypoint,
+       LPCSTR pTarget,
+       UINT Flags1,
+       UINT Flags2,
+       ID3DBlob** ppCode,
+       ID3DBlob** ppErrorMsgs);
 
 static PFN_D3D11_CREATE_DEVICE pD3D11CreateDevice;
 static CREATEDXGIFACTORY1 pCreateDXGIFactory1;
 static D3DCOMPILEFROMFILE pD3DCompileFromFile;
+static D3DCOMPILE ppD3DCompile;
 
-static D3DXMATRIX* MatrixOrthoOffCenterLH(D3DXMATRIXA16 *pOut, float l, float r, float b, float t, float zn, float zf)
+static const char *uae_shader_ps =
 {
-       pOut->_11 = 2.0f / r; pOut->_12 = 0.0f;   pOut->_13 = 0.0f;  pOut->_14 = 0.0f;
-       pOut->_21 = 0.0f;   pOut->_22 = 2.0f / t; pOut->_23 = 0.0f;  pOut->_24 = 0.0f;
-       pOut->_31 = 0.0f;   pOut->_32 = 0.0f;   pOut->_33 = 1.0f;  pOut->_34 = 0.0f;
-       pOut->_41 = -1.0f;  pOut->_42 = -1.0f;  pOut->_43 = 0.0f;  pOut->_44 = 1.0f;
-       return pOut;
-}
-
-static D3DXMATRIX* MatrixScaling(D3DXMATRIXA16 *pOut, float sx, float sy, float sz)
+       "Texture2D shaderTexture;\n"
+       "Texture2D maskTexture;\n"
+       "SamplerState SampleTypeClamp;\n"
+       "SamplerState SampleTypeWrap;\n"
+       "struct PixelInputType\n"
+       "{\n"
+       "       float4 position : SV_POSITION;\n"
+       "       float2 tex : TEXCOORD0;\n"
+       "       float2 sl : TEXCOORD1;\n"
+       "};\n"
+       "float4 PS_PostPlain(PixelInputType input) : SV_TARGET\n"
+       "{\n"
+       "       float4 textureColor = shaderTexture.Sample(SampleTypeClamp, input.tex);\n"
+       "       return textureColor;\n"
+       "}\n"
+       "float4 PS_PostMask(PixelInputType input) : SV_TARGET\n"
+       "{\n"
+       "       float4 textureColor = shaderTexture.Sample(SampleTypeClamp, input.tex);\n"
+       "       float4 maskColor = maskTexture.Sample(SampleTypeWrap, input.sl);\n"
+       "       return textureColor * maskColor;\n"
+       "}\n"
+       "float4 PS_PostAlpha(PixelInputType input) : SV_TARGET\n"
+       "{\n"
+       "       float4 textureColor = shaderTexture.Sample(SampleTypeClamp, input.tex);\n"
+       "       float4 maskColor = maskTexture.Sample(SampleTypeWrap, input.sl);\n"
+       "       return textureColor * (1 - maskColor.a) + (maskColor * maskColor.a);\n"
+       "}\n"
+};
+static const char *uae_shader_vs =
 {
-       pOut->_11 = sx;     pOut->_12 = 0.0f;   pOut->_13 = 0.0f;  pOut->_14 = 0.0f;
-       pOut->_21 = 0.0f;   pOut->_22 = sy;     pOut->_23 = 0.0f;  pOut->_24 = 0.0f;
-       pOut->_31 = 0.0f;   pOut->_32 = 0.0f;   pOut->_33 = sz;    pOut->_34 = 0.0f;
-       pOut->_41 = 0.0f;   pOut->_42 = 0.0f;   pOut->_43 = 0.0f;  pOut->_44 = 1.0f;
-       return pOut;
-}
+       "cbuffer MatrixBuffer\n"
+       "{\n"
+       "       matrix worldMatrix;\n"
+       "       matrix viewMatrix;\n"
+       "       matrix projectionMatrix;\n"
+       "};\n"
+       "struct VertexInputType\n"
+       "{\n"
+       "       float4 position : POSITION;\n"
+       "       float2 tex : TEXCOORD0;\n"
+       "       float2 sl : TEXCOORD1;\n"
+       "};\n"
+       "struct PixelInputType\n"
+       "{\n"
+       "       float4 position : SV_POSITION;\n"
+       "       float2 tex : TEXCOORD0;\n"
+       "       float2 sl : TEXCOORD1;\n"
+       "};\n"
+       "PixelInputType TextureVertexShader(VertexInputType input)\n"
+       "{\n"
+       "       PixelInputType output;\n"
+       "       input.position.w = 1.0f;\n"
+       "       output.position = mul(input.position, projectionMatrix);\n"
+       "       output.position.z = 0.0f;\n"
+       "       output.tex = input.tex;\n"
+       "       output.sl = input.sl;\n"
+       "       return output;\n"
+       "}\n"
+};
 
-static D3DXMATRIX* MatrixTranslation(D3DXMATRIXA16 *pOut, float tx, float ty, float tz)
+static int isfs(struct d3d11struct *d3d)
 {
-       pOut->_11 = 1.0f;   pOut->_12 = 0.0f;   pOut->_13 = 0.0f;  pOut->_14 = 0.0f;
-       pOut->_21 = 0.0f;   pOut->_22 = 1.0f;   pOut->_23 = 0.0f;  pOut->_24 = 0.0f;
-       pOut->_31 = 0.0f;   pOut->_32 = 0.0f;   pOut->_33 = 1.0f;  pOut->_34 = 0.0f;
-       pOut->_41 = tx;     pOut->_42 = ty;     pOut->_43 = tz;    pOut->_44 = 1.0f;
-       return pOut;
+       int fs = isfullscreen();
+       if (fs > 0 && d3d->guimode)
+               return -1;
+       return fs;
 }
 
-static void setupscenecoords(void)
+static bool UpdateBuffers(struct d3d11struct *d3d)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
+       float left, right, top, bottom;
+       VertexType* vertices;
+       D3D11_MAPPED_SUBRESOURCE mappedResource;
+       VertexType* verticesPtr;
+       HRESULT result;
+       int positionX, positionY;
+
+       positionX = (d3d->m_screenWidth - d3d->m_bitmapWidth) / 2 + d3d->xoffset;
+       positionY = (d3d->m_screenHeight - d3d->m_bitmapHeight) / 2 + d3d->yoffset;
+
+       // Calculate the screen coordinates of the left side of the bitmap.
+       left = (d3d->m_screenWidth + 1) / -2;
+       left += positionX;
 
-       d3d->xoffset = 0;
-       d3d->yoffset = 0;
+       // Calculate the screen coordinates of the right side of the bitmap.
+       right = left + d3d->m_bitmapWidth;
 
-       return;
+       // Calculate the screen coordinates of the top of the bitmap.
+       top = (d3d->m_screenHeight + 1) / 2;
+       top -= positionY;
 
-       RECT sr, dr, zr;
-       float w, h;
-       float dw, dh;
-       static RECT sr2, dr2, zr2;
+       // Calculate the screen coordinates of the bottom of the bitmap.
+       bottom = top - d3d->m_bitmapHeight;
+
+       float slleft = 0;
+       float sltop = 0;
+       float slright = (float)d3d->m_bitmapWidth / d3d->m_screenWidth * d3d->xmult;
+       float slbottom = (float)d3d->m_bitmapHeight / d3d->m_screenHeight * d3d->ymult;
+
+       slright = slleft + slright;
+       slbottom = sltop + slbottom;
+
+       left *= d3d->xmult;
+       right *= d3d->xmult;
+       top *= d3d->ymult;
+       bottom *= d3d->ymult;
+
+       write_log(_T("-> %f %f %f %f %f %f\n"), left, top, right, bottom, d3d->xmult, d3d->ymult);
+
+       // Create the vertex array.
+       vertices = new VertexType[d3d->m_vertexCount];
+       if (!vertices)
+       {
+               return false;
+       }
+
+       // Load the vertex array with data.
+       // First triangle.
+       vertices[0].position = D3DXVECTOR3(left, top, 0.0f);  // Top left.
+       vertices[0].texture = D3DXVECTOR2(0.0f, 0.0f);
+       vertices[0].sltexture = D3DXVECTOR2(slleft, sltop);
+
+       vertices[1].position = D3DXVECTOR3(right, bottom, 0.0f);  // Bottom right.
+       vertices[1].texture = D3DXVECTOR2(1.0f, 1.0f);
+       vertices[1].sltexture = D3DXVECTOR2(slright, slbottom);
 
-       d3d->dmult = 1;
+       vertices[2].position = D3DXVECTOR3(left, bottom, 0.0f);  // Bottom left.
+       vertices[2].texture = D3DXVECTOR2(0.0f, 1.0f);
+       vertices[2].sltexture = D3DXVECTOR2(slleft, slbottom);
+
+       // Second triangle.
+       vertices[3].position = D3DXVECTOR3(left, top, 0.0f);  // Top left.
+       vertices[3].texture = D3DXVECTOR2(0.0f, 0.0f);
+       vertices[3].sltexture = D3DXVECTOR2(slleft, sltop);
+
+       vertices[4].position = D3DXVECTOR3(right, top, 0.0f);  // Top right.
+       vertices[4].texture = D3DXVECTOR2(1.0f, 0.0f);
+       vertices[4].sltexture = D3DXVECTOR2(slright, sltop);
+
+       vertices[5].position = D3DXVECTOR3(right, bottom, 0.0f);  // Bottom right.
+       vertices[5].texture = D3DXVECTOR2(1.0f, 1.0f);
+       vertices[5].sltexture = D3DXVECTOR2(slright, slbottom);
+
+       // Lock the vertex buffer so it can be written to.
+       result = d3d->m_deviceContext->Map(d3d->m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+       if (FAILED(result))
+       {
+               write_log(_T("ID3D11DeviceContext map(vertex) %08x\n"), result);
+               return false;
+       }
+
+       // Get a pointer to the data in the vertex buffer.
+       verticesPtr = (VertexType*)mappedResource.pData;
+
+       // Copy the data into the vertex buffer.
+       memcpy(verticesPtr, (void*)vertices, (sizeof(VertexType) * d3d->m_vertexCount));
+
+       // Unlock the vertex buffer.
+       d3d->m_deviceContext->Unmap(d3d->m_vertexBuffer, 0);
+
+       // Release the vertex array as it is no longer needed.
+       delete[] vertices;
+       vertices = 0;
+
+       return true;
+}
+
+static void setupscenecoords(struct d3d11struct *d3d)
+{
+       RECT sr, dr, zr;
 
        getfilterrect2(&dr, &sr, &zr, d3d->m_screenWidth, d3d->m_screenHeight, d3d->m_bitmapWidth / d3d->dmult, d3d->m_bitmapHeight / d3d->dmult, d3d->dmult, d3d->m_bitmapWidth, d3d->m_bitmapHeight);
 
-       if (memcmp(&sr, &sr2, sizeof RECT) || memcmp(&dr, &dr2, sizeof RECT) || memcmp(&zr, &zr2, sizeof RECT)) {
+       if (!memcmp(&sr, &d3d->sr2, sizeof RECT) && !memcmp(&dr, &d3d->dr2, sizeof RECT) && !memcmp(&zr, &d3d->zr2, sizeof RECT)) {
+               return;
+       }
+       if (1) {
                write_log(_T("POS (%d %d %d %d) - (%d %d %d %d)[%d,%d] (%d %d)\n"),
                        dr.left, dr.top, dr.right, dr.bottom, sr.left, sr.top, sr.right, sr.bottom,
                        sr.right - sr.left, sr.bottom - sr.top,
                        zr.left, zr.top);
-               sr2 = sr;
-               dr2 = dr;
-               zr2 = zr;
        }
+       d3d->sr2 = sr;
+       d3d->dr2 = dr;
+       d3d->zr2 = zr;
 
-       dw = dr.right - dr.left;
-       dh = dr.bottom - dr.top;
-       w = sr.right - sr.left;
-       h = sr.bottom - sr.top;
+       float dw = dr.right - dr.left;
+       float dh = dr.bottom - dr.top;
+       float w = sr.right - sr.left;
+       float h = sr.bottom - sr.top;
 
-       //d3d->xoffset = -zr.left;
-       //d3d->yoffset = -zr.top;
+       int tx = dw * d3d->m_bitmapWidth / d3d->m_screenWidth / 2;
+       int ty = dh * d3d->m_bitmapHeight / d3d->m_screenHeight / 2;
 
-       //write_log(_T("%.1f %.1f\n"), d3d->xoffset, d3d->yoffset);
-}
+       float sw = dw / d3d->m_screenWidth;
+       float sh = dh / d3d->m_screenHeight;
+
+       int xshift = -zr.left - sr.left; // - (tin_w - 2 * zr.left - w),
+       int yshift = +zr.top + sr.top - (d3d->m_bitmapHeight - h);
+
+       xshift -= ((sr.right - sr.left) - d3d->m_screenWidth) / 2;
+       yshift -= ((sr.bottom - sr.top) - d3d->m_screenHeight) / 2;
+
+       d3d->xoffset = tx + xshift - d3d->m_screenWidth / 2;
+       d3d->yoffset = ty + yshift - d3d->m_screenHeight / 2;
+
+       d3d->xmult = d3d->m_screenWidth / w;
+       d3d->ymult = d3d->m_screenHeight / h;
 
+       write_log(_T("%d %d %.f %.f\n"), d3d->xoffset, d3d->yoffset, d3d->xmult, d3d->ymult);
 
-static void FreeTexture(void)
+       UpdateBuffers(d3d);
+}
+
+static void updateleds(struct d3d11struct *d3d)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
+       HRESULT hr;
+       D3D11_MAPPED_SUBRESOURCE map;
+       static uae_u32 rc[256], gc[256], bc[256], a[256];
+       static int done;
+
+       if (!done) {
+               for (int i = 0; i < 256; i++) {
+                       rc[i] = i << 16;
+                       gc[i] = i << 8;
+                       bc[i] = i << 0;
+                       a[i] = i << 24;
+               }
+               done = 1;
+       }
 
-       if (d3d->texture)
-               d3d->texture->Release();
-       d3d->texture = NULL;
+       hr = d3d->m_deviceContext->Map(d3d->ledtexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+       if (FAILED(hr)) {
+               write_log(_T("Led Map failed %08x\n"), hr);
+               return;
+       }
+       for (int y = 0; y < TD_TOTAL_HEIGHT * d3d->statusbar_vx; y++) {
+               uae_u8 *buf = (uae_u8*)map.pData + y * map.RowPitch;
+               statusline_single_erase(buf, 32 / 8, y, d3d->ledwidth * d3d->statusbar_hx);
+       }
+       statusline_render((uae_u8*)map.pData, 32 / 8, map.RowPitch, d3d->ledwidth, d3d->ledheight, rc, gc, bc, a);
+
+       int y = 0;
+       for (int yy = 0; yy < d3d->statusbar_vx * TD_TOTAL_HEIGHT; yy++) {
+               uae_u8 *buf = (uae_u8*)map.pData + yy * map.RowPitch;
+               draw_status_line_single(buf, 32 / 8, y, d3d->ledwidth, rc, gc, bc, a);
+               if ((yy % d3d->statusbar_vx) == 0)
+                       y++;
+       }
 
-       if (d3d->texture2d)
-               d3d->texture2d->Release();
-       d3d->texture2d = NULL;
-       if (d3d->texture2dstaging)
-               d3d->texture2dstaging->Release();
-       d3d->texture2dstaging = NULL;
+       d3d->m_deviceContext->Unmap(d3d->ledtexture, 0);
 }
 
-static bool CreateTexture(void)
+static void FreeTexture2D(ID3D11Texture2D **t, ID3D11ShaderResourceView **v)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
+       if (t && *t) {
+               (*t)->Release();
+               (*t) = NULL;
+       }
+       if (v && *v) {
+               (*v)->Release();
+               (*v) = NULL;
+       }
+}
+
+static void FreeTexture(struct d3d11struct *d3d)
+{
+       FreeTexture2D(&d3d->texture2d, &d3d->texture2drv);
+       FreeTexture2D(&d3d->texture2dstaging, NULL);
+       FreeTexture2D(&d3d->screenshottexture, NULL);
+       FreeTexture2D(&d3d->ledtexture, &d3d->ledtexturerv);
+
+       for (int i = 0; i < MAX_SHADERS; i++) {
+               FreeTexture2D(&d3d->shaders[i].masktexture, &d3d->shaders[i].masktexturerv);
+               memset(&d3d->shaders[i], 0, sizeof(struct shaderdata11));
+       }
+}
 
+static bool CreateTexture(struct d3d11struct *d3d)
+{
        D3D11_TEXTURE2D_DESC desc;
        HRESULT hr;
 
-       FreeTexture();
+       memset(&d3d->sr2, 0, sizeof(RECT));
+       memset(&d3d->dr2, 0, sizeof(RECT));
+       memset(&d3d->zr2, 0, sizeof(RECT));
+
+       FreeTexture(d3d);
 
        memset(&desc, 0, sizeof desc);
        desc.Width = d3d->m_bitmapWidth;
@@ -251,18 +505,573 @@ static bool CreateTexture(void)
        srvDesc.Texture2D.MipLevels = desc.MipLevels;
        srvDesc.Format = d3d->format;
 
-       hr = d3d->m_device->CreateShaderResourceView(d3d->texture2d, &srvDesc, &d3d->texture);
+       hr = d3d->m_device->CreateShaderResourceView(d3d->texture2d, &srvDesc, &d3d->texture2drv);
        if (FAILED(hr)) {
-               write_log(_T("CreateShaderResourceView failed: %08x\n"), hr);
+               write_log(_T("CreateShaderResourceView MAIN failed: %08x\n"), hr);
+               return false;
+       }
+
+       ID3D11Texture2D* pSurface;
+       hr = d3d->m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast< void** >(&pSurface));
+       if (SUCCEEDED(hr)) {
+               memset(&desc, 0, sizeof desc);
+               pSurface->GetDesc(&desc);
+               desc.BindFlags = 0;
+               desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+               desc.Usage = D3D11_USAGE_STAGING;
+
+               hr = d3d->m_device->CreateTexture2D(&desc, nullptr, &d3d->screenshottexture);
+               if (FAILED(hr)) {
+                       write_log(_T("CreateTexture2D (screenshot) failed: %08x\n"), hr);
+               }
+               pSurface->Release();
+       }
+
+       memset(&desc, 0, sizeof desc);
+       d3d->ledwidth = d3d->m_screenWidth;
+       d3d->ledheight = TD_TOTAL_HEIGHT;
+       if (d3d->statusbar_hx < 1)
+               d3d->statusbar_hx = 1;
+       if (d3d->statusbar_vx < 1)
+               d3d->statusbar_vx = 1;
+       desc.Width = d3d->ledwidth;
+       desc.Height = d3d->ledheight;
+       desc.MipLevels = 1;
+       desc.ArraySize = 1;
+       desc.Format = d3d->format;
+       desc.SampleDesc.Count = 1;
+       desc.SampleDesc.Quality = 0;
+       desc.Usage = D3D11_USAGE_DYNAMIC;
+       desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+       desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+       hr = d3d->m_device->CreateTexture2D(&desc, NULL, &d3d->ledtexture);
+       if (FAILED(hr)) {
+               write_log(_T("CreateTexture2D (led) failed: %08x\n"), hr);
+               return false;
+       }
+
+       hr = d3d->m_device->CreateShaderResourceView(d3d->ledtexture, &srvDesc, &d3d->ledtexturerv);
+       if (FAILED(hr)) {
+               write_log(_T("CreateShaderResourceView Led failed: %08x\n"), hr);
+               FreeTexture2D(&d3d->ledtexture, NULL);
                return false;
        }
 
        return true;
 }
 
+static bool createsltexture(struct d3d11struct *d3d)
+{
+       D3D11_TEXTURE2D_DESC desc;
+       HRESULT hr;
+
+       FreeTexture2D(&d3d->sltexture, &d3d->sltexturerv);
+
+       memset(&desc, 0, sizeof desc);
+       desc.Width = d3d->m_screenWidth;
+       desc.Height = d3d->m_screenHeight;
+       desc.MipLevels = 1;
+       desc.ArraySize = 1;
+       desc.Format = d3d->format;
+       desc.SampleDesc.Count = 1;
+       desc.SampleDesc.Quality = 0;
+       desc.Usage = D3D11_USAGE_DYNAMIC;
+       desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+       desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+       hr = d3d->m_device->CreateTexture2D(&desc, NULL, &d3d->sltexture);
+       if (FAILED(hr)) {
+               write_log(_T("CreateTexture2D (main) failed: %08x\n"), hr);
+               return false;
+       }
+
+       D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+       srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+       srvDesc.Texture2D.MostDetailedMip = 0;
+       srvDesc.Texture2D.MipLevels = desc.MipLevels;
+       srvDesc.Format = d3d->format;
+
+       hr = d3d->m_device->CreateShaderResourceView(d3d->sltexture, &srvDesc, &d3d->sltexturerv);
+       if (FAILED(hr)) {
+               write_log(_T("CreateShaderResourceView SL failed: %08x\n"), hr);
+               FreeTexture2D(&d3d->sltexture, NULL);
+               return false;
+       }
+
+       write_log(_T("SL %d*%d texture allocated\n"), desc.Width, desc.Height);
+       return true;
+}
+
+
+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)
+               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;
+       if (sl4 > 15)
+               sl4 = 15;
+       if (sl42 > 15)
+               sl42 = 15;
+       l1 = (filterd3d->gfx_filter_scanlineratio >> 0) & 15;
+       l2 = (filterd3d->gfx_filter_scanlineratio >> 4) & 15;
+
+       if (l1 + l2 <= 0)
+               return;
+
+       if (!d3d->sltexture) {
+               if (osl1 == 0 && osl3 == 0)
+                       return;
+               if (!createsltexture(d3d))
+                       return;
+       }
+
+       hr = d3d->m_deviceContext->Map(d3d->sltexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+       if (FAILED(hr)) {
+               write_log(_T("SL Map failed %08x\n"), hr);
+               return;
+       }
+       sld = (uae_u8*)map.pData;
+       for (y = 0; y < d3d->m_screenHeight; y++)
+               memset(sld + y * map.RowPitch, 0, d3d->m_screenWidth * bpp);
+       for (y = 1; y < d3d->m_screenHeight; y += l1 + l2) {
+               for (yy = 0; yy < l2 && y + yy < d3d->m_screenHeight; yy++) {
+                       for (x = 0; x < d3d->m_screenWidth; x++) {
+                               uae_u8 sll = sl42;
+                               p = &sld[(y + yy) * map.RowPitch + (x * bpp)];
+                               /* 32-bit, A8R8G8B8 */
+                               uae_u8 sll4 = sl4 | (sl4 << 4);
+                               uae_u8 sll2 = sll | (sll << 4);
+                               p[0] = sll2;
+                               p[1] = sll2;
+                               p[2] = sll2;
+                               p[3] = sll4;
+                       }
+               }
+       }
+       d3d->m_deviceContext->Unmap(d3d->sltexture, 0);
+}
+
+
+#include "png.h"
+
+struct uae_image
+{
+       uae_u8 *data;
+       int width, height, pitch;
+};
+
+struct png_cb
+{
+       uae_u8 *ptr;
+       int size;
+};
+
+static void __cdecl readcallback(png_structp png_ptr, png_bytep out, png_size_t count)
+{
+       png_voidp io_ptr = png_get_io_ptr(png_ptr);
+
+       if (!io_ptr)
+               return;
+       struct png_cb *cb = (struct png_cb*)io_ptr;
+       if (count > cb->size)
+               count = cb->size;
+       memcpy(out, cb->ptr, count);
+       cb->ptr += count;
+       cb->size -= count;
+}
+
+static bool load_png_image(struct zfile *zf, struct uae_image *img)
+{
+       extern unsigned char test_card_png[];
+       extern unsigned int test_card_png_len;
+       uae_u8 *b = test_card_png;
+       uae_u8 *bfree = NULL;
+       png_structp png_ptr;
+       png_infop info_ptr;
+       png_uint_32 width, height;
+       int depth, color_type;
+       struct png_cb cb;
+       png_bytepp row_pp;
+       png_size_t cols;
+       bool ok = false;
+
+       memset(img, 0, sizeof(struct uae_image));
+       int size;
+       uae_u8 *bb = zfile_getdata(zf, 0, -1, &size);
+       if (!bb)
+               goto end;
+       b = bb;
+       bfree = bb;
+
+       if (!png_check_sig(b, 8))
+               goto end;
+
+       png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+       if (!png_ptr)
+               goto end;
+       info_ptr = png_create_info_struct(png_ptr);
+       if (!info_ptr) {
+               png_destroy_read_struct(&png_ptr, 0, 0);
+               goto end;
+       }
+       cb.ptr = b;
+       cb.size = size;
+       png_set_read_fn(png_ptr, &cb, readcallback);
+
+       png_read_info(png_ptr, info_ptr);
+
+       png_get_IHDR(png_ptr, info_ptr, &width, &height, &depth, &color_type, 0, 0, 0);
+
+       if (color_type == PNG_COLOR_TYPE_PALETTE)
+               png_set_expand(png_ptr);
+       if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
+               png_set_expand(png_ptr);
+
+       if (depth > 8)
+               png_set_strip_16(png_ptr);
+       if (depth < 8)
+               png_set_packing(png_ptr);
+       if (!(color_type & PNG_COLOR_MASK_ALPHA))
+               png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+       cols = png_get_rowbytes(png_ptr, info_ptr);
+
+       img->pitch = width * 4;
+       img->width = width;
+       img->height = height;
+
+       row_pp = new png_bytep[height];
+
+       img->data = xcalloc(uae_u8, width * height * 4);
+
+       for (int i = 0; i < height; i++) {
+               row_pp[i] = (png_bytep)&img->data[i * img->pitch];
+       }
+
+       png_read_image(png_ptr, row_pp);
+       png_read_end(png_ptr, info_ptr);
+
+       png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+
+       delete[] row_pp;
+
+       ok = true;
+end:
+       xfree(bfree);
+
+       return ok;
+}
+
+static void free_uae_image(struct uae_image *img)
+{
+       if (!img)
+               return;
+       xfree(img->data);
+       img->data = NULL;
+}
+
+static int findedge(struct uae_image *img, int w, int h, int dx, int dy)
+{
+       int x = w / 2;
+       int y = h / 2;
+
+       if (dx != 0)
+               x = dx < 0 ? 0 : w - 1;
+       if (dy != 0)
+               y = dy < 0 ? 0 : h - 1;
+
+       for (;;) {
+               uae_u32 *p = (uae_u32*)(img->data + y * img->pitch + x * 4);
+               int alpha = (*p) >> 24;
+               if (alpha != 255)
+                       break;
+               x -= dx;
+               y -= dy;
+               if (x <= 0 || y <= 0)
+                       break;
+               if (x >= w - 1 || y >= h - 1)
+                       break;
+       }
+       if (dx)
+               return x;
+       return y;
+}
+
+static int createmask2texture(struct d3d11struct *d3d, const TCHAR *filename)
+{
+       struct zfile *zf;
+       HRESULT hr;
+       TCHAR tmp[MAX_DPATH];
+       ID3D11Texture2D *tx = NULL;
+
+       FreeTexture2D(&d3d->mask2texture, NULL);
+
+       if (filename[0] == 0 || WIN32GFX_IsPicassoScreen())
+               return 0;
+
+       zf = NULL;
+       for (int i = 0; i < 2; i++) {
+               if (i == 0) {
+                       get_plugin_path(tmp, sizeof tmp / sizeof(TCHAR), _T("overlays"));
+                       _tcscat(tmp, filename);
+               } else {
+                       _tcscpy(tmp, filename);
+               }
+               TCHAR tmp2[MAX_DPATH], tmp3[MAX_DPATH];
+               _tcscpy(tmp3, tmp);
+               TCHAR *s = _tcsrchr(tmp3, '.');
+               if (s) {
+                       TCHAR *s2 = s;
+                       while (s2 > tmp3) {
+                               TCHAR v = *s2;
+                               if (v == '_') {
+                                       s = s2;
+                                       break;
+                               }
+                               if (v == 'X' || v == 'x') {
+                                       s2--;
+                                       continue;
+                               }
+                               if (!_istdigit(v))
+                                       break;
+                               s2--;
+                       }
+                       _tcscpy(tmp2, s);
+                       _stprintf(s, _T("_%dx%d%s"), d3d->m_screenWidth, d3d->m_screenHeight, tmp2);
+                       zf = zfile_fopen(tmp3, _T("rb"), ZFD_NORMAL);
+                       if (zf)
+                               break;
+                       float aspect = (float)d3d->m_screenWidth / d3d->m_screenHeight;
+                       int ax = -1, ay = -1;
+                       if (abs(aspect - 16.0 / 10.0) <= 0.1)
+                               ax = 16, ay = 10;
+                       if (abs(aspect - 16.0 / 9.0) <= 0.1)
+                               ax = 16, ay = 9;
+                       if (abs(aspect - 4.0 / 3.0) <= 0.1)
+                               ax = 4, ay = 3;
+                       if (ax > 0 && ay > 0) {
+                               _stprintf(s, _T("_%dx%d%s"), ax, ay, tmp2);
+                               zf = zfile_fopen(tmp3, _T("rb"), ZFD_NORMAL);
+                               if (zf)
+                                       break;
+                       }
+               }
+               zf = zfile_fopen(tmp, _T("rb"), ZFD_NORMAL);
+               if (zf)
+                       break;
+       }
+       if (!zf) {
+               write_log(_T("Couldn't open overlay '%s'\n"), filename);
+               return 0;
+       }
+       struct uae_image img;
+       if (!load_png_image(zf, &img)) {
+               write_log(_T("Overlay texture load failed %08x\n"), hr);
+               goto end;
+       }
+       d3d->mask2texture_w = img.width;
+       d3d->mask2texture_h = img.height;
+       d3d->mask2texture = tx;
+       d3d->mask2rect.left = 0;
+       d3d->mask2rect.top = 0;
+       d3d->mask2rect.right = d3d->mask2texture_w;
+       d3d->mask2rect.bottom = d3d->mask2texture_h;
+
+       d3d->mask2rect.left = findedge(&img, d3d->mask2texture_w, d3d->mask2texture_h, -1, 0);
+       d3d->mask2rect.right = findedge(&img, d3d->mask2texture_w, d3d->mask2texture_h, 1, 0);
+       d3d->mask2rect.top = findedge(&img, d3d->mask2texture_w, d3d->mask2texture_h, 0, -1);
+       d3d->mask2rect.bottom = findedge(&img, d3d->mask2texture_w, d3d->mask2texture_h, 0, 1);
+       if (d3d->mask2rect.left >= d3d->mask2texture_w / 2 || d3d->mask2rect.top >= d3d->mask2texture_h / 2 ||
+               d3d->mask2rect.right <= d3d->mask2texture_w / 2 || d3d->mask2rect.bottom <= d3d->mask2texture_h / 2) {
+               d3d->mask2rect.left = 0;
+               d3d->mask2rect.top = 0;
+               d3d->mask2rect.right = d3d->mask2texture_w;
+               d3d->mask2rect.bottom = d3d->mask2texture_h;
+       }
+       d3d->mask2texture_multx = (float)d3d->m_screenWidth / d3d->mask2texture_w;
+       d3d->mask2texture_multy = (float)d3d->m_screenHeight / d3d->mask2texture_h;
+       d3d->mask2texture_offsetw = 0;
+
+       if (isfs(d3d) > 0) {
+               struct MultiDisplay *md = getdisplay(&currprefs);
+               float deskw = md->rect.right - md->rect.left;
+               float deskh = md->rect.bottom - md->rect.top;
+               //deskw = 800; deskh = 600;
+               float dstratio = deskw / deskh;
+               float srcratio = d3d->mask2texture_w / d3d->mask2texture_h;
+               d3d->mask2texture_multx *= srcratio / dstratio;
+       } else {
+               d3d->mask2texture_multx = d3d->mask2texture_multy;
+       }
+
+       d3d->mask2texture_wh = d3d->m_screenWidth;
+       d3d->mask2texture_ww = d3d->mask2texture_w * d3d->mask2texture_multx;
+
+       d3d->mask2texture_offsetw = (d3d->m_screenWidth - d3d->mask2texture_ww) / 2;
+
+#if 0
+       if (d3d->mask2texture_offsetw > 0) {
+               d3d->blanktexture = createtext(d3d, d3d->mask2texture_offsetw + 1, d3d->m_screenHeight, D3DFMT_X8R8G8B8);
+       }
+#endif
+
+       float xmult = d3d->mask2texture_multx;
+       float ymult = d3d->mask2texture_multy;
+
+       d3d->mask2rect.left *= xmult;
+       d3d->mask2rect.right *= xmult;
+       d3d->mask2rect.top *= ymult;
+       d3d->mask2rect.bottom *= ymult;
+       d3d->mask2texture_wwx = d3d->mask2texture_w * xmult;
+       if (d3d->mask2texture_wwx > d3d->m_screenWidth)
+               d3d->mask2texture_wwx = d3d->m_screenWidth;
+       if (d3d->mask2texture_wwx < d3d->mask2rect.right - d3d->mask2rect.left)
+               d3d->mask2texture_wwx = d3d->mask2rect.right - d3d->mask2rect.left;
+       if (d3d->mask2texture_wwx > d3d->mask2texture_ww)
+               d3d->mask2texture_wwx = d3d->mask2texture_ww;
+
+       d3d->mask2texture_minusx = -((d3d->m_screenWidth - d3d->mask2rect.right) + d3d->mask2rect.left);
+       if (d3d->mask2texture_offsetw > 0)
+               d3d->mask2texture_minusx += d3d->mask2texture_offsetw * xmult;
+
+
+       d3d->mask2texture_minusy = -(d3d->m_screenHeight - (d3d->mask2rect.bottom - d3d->mask2rect.top));
+
+       d3d->mask2texture_hhx = d3d->mask2texture_h * ymult;
+
+       write_log(_T("Overlay '%s' %.0f*%.0f (%d*%d - %d*%d) (%d*%d)\n"),
+               tmp, d3d->mask2texture_w, d3d->mask2texture_h,
+               d3d->mask2rect.left, d3d->mask2rect.top, d3d->mask2rect.right, d3d->mask2rect.bottom,
+               d3d->mask2rect.right - d3d->mask2rect.left, d3d->mask2rect.bottom - d3d->mask2rect.top);
+
+       return 1;
+end:
+       if (tx)
+               tx->Release();
+       return 0;
+}
+
+static int createmasktexture(struct d3d11struct *d3d, const TCHAR *filename, struct shaderdata11 *sd)
+{
+       struct zfile *zf;
+       HRESULT hr;
+       TCHAR tmp[MAX_DPATH];
+       int maskwidth, maskheight;
+       int idx = 0;// sd - &d3d->shaders[0];
+       D3D11_MAPPED_SUBRESOURCE map;
+       D3D11_TEXTURE2D_DESC desc;
+
+       if (filename[0] == 0)
+               return 0;
+       get_plugin_path(tmp, sizeof tmp / sizeof(TCHAR), _T("masks"));
+       _tcscat(tmp, filename);
+       zf = zfile_fopen(tmp, _T("rb"), ZFD_NORMAL);
+       if (!zf) {
+               zf = zfile_fopen(filename, _T("rb"), ZFD_NORMAL);
+               if (!zf) {
+                       write_log(_T("Couldn't open mask '%s':%d\n"), filename, idx);
+                       return 0;
+               }
+       }
+
+       struct uae_image img;
+       if (!load_png_image(zf, &img)) {
+               write_log(_T("Temp mask texture '%s' load failed:%d\n"), filename, idx);
+               goto end;
+       }
+
+       sd->masktexture_w = img.width;
+       sd->masktexture_h = img.height;
+
+       // both must be divisible by mask size
+       maskwidth = ((d3d->m_screenWidth + sd->masktexture_w - 1) / sd->masktexture_w) * sd->masktexture_w;
+       maskheight = ((d3d->m_screenHeight + sd->masktexture_h - 1) / sd->masktexture_h) * sd->masktexture_h;
+
+       memset(&desc, 0, sizeof desc);
+       desc.Width = maskwidth;
+       desc.Height = maskheight;
+       desc.MipLevels = 1;
+       desc.ArraySize = 1;
+       desc.Format = d3d->format;
+       desc.SampleDesc.Count = 1;
+       desc.SampleDesc.Quality = 0;
+       desc.Usage = D3D11_USAGE_DYNAMIC;
+       desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+       desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+       hr = d3d->m_device->CreateTexture2D(&desc, NULL, &sd->masktexture);
+       if (FAILED(hr)) {
+               write_log(_T("Mask texture creation failed: %s:%d\n"), hr, idx);
+               return false;
+       }
+
+       hr = d3d->m_deviceContext->Map(sd->masktexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+       if (SUCCEEDED(hr)) {
+               int x, y, sx, sy;
+               uae_u32 *sptr, *ptr;
+               sy = 0;
+               for (y = 0; y < maskheight; y++) {
+                       sx = 0;
+                       for (x = 0; x < maskwidth; x++) {
+                               uae_u32 v;
+                               sptr = (uae_u32*)((uae_u8*)img.data + sy * img.pitch + sx * 4);
+                               ptr = (uae_u32*)((uae_u8*)map.pData + y * map.RowPitch + x * 4);
+                               v = *sptr;
+                               *ptr = v;
+                               sx++;
+                               if (sx >= sd->masktexture_w)
+                                       sx = 0;
+                       }
+                       sy++;
+                       if (sy >= sd->masktexture_h)
+                               sy = 0;
+               }
+               d3d->m_deviceContext->Unmap(sd->masktexture, 0);
+       }
+       sd->masktexture_w = maskwidth;
+       sd->masktexture_h = maskheight;
+
+       D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+       srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+       srvDesc.Texture2D.MostDetailedMip = 0;
+       srvDesc.Texture2D.MipLevels = desc.MipLevels;
+       srvDesc.Format = d3d->format;
+
+       hr = d3d->m_device->CreateShaderResourceView(sd->masktexture, &srvDesc, &sd->masktexturerv);
+       if (FAILED(hr)) {
+               write_log(_T("CreateShaderResourceView MASK failed: %08x\n"), hr);
+               goto end;
+       }
+
+       write_log(_T("Mask %d*%d (%d*%d) %d*%d ('%s':%d) texture allocated\n"), sd->masktexture_w, sd->masktexture_h,
+               img.width, img.height, 0, 0, filename, idx);
+
+       free_uae_image(&img);
+       return 1;
+end:
+       FreeTexture2D(&sd->masktexture, NULL);
+       free_uae_image(&img);
+       return 0;
+}
+
 static void OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, TCHAR* shaderFilename)
 {
-       charcompileErrors;
+       char *compileErrors;
        unsigned long bufferSize;
 
        if (errorMessage) {
@@ -287,68 +1096,105 @@ static void OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, TCHAR*
        }
 }
 
-static bool TextureShaderClass_InitializeShader(ID3D11Device* device, HWND hwnd)
+static bool TextureShaderClass_InitializeShader(struct d3d11struct *d3d)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        HRESULT result;
        ID3D10Blob* errorMessage;
        ID3D10Blob* vertexShaderBuffer;
-       ID3D10Blob* pixelShaderBuffer;
-       D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
+       D3D11_INPUT_ELEMENT_DESC polygonLayout[3];
+       D3D11_SAMPLER_DESC samplerDesc;
        unsigned int numElements;
        D3D11_BUFFER_DESC matrixBufferDesc;
-       D3D11_SAMPLER_DESC samplerDesc;
        bool plugin_path;
        TCHAR tmp[MAX_DPATH], tmp2[MAX_DPATH];
 
        plugin_path = get_plugin_path(tmp, sizeof tmp / sizeof(TCHAR), _T("filtershaders\\direct3d11"));
-       if (!plugin_path) {
-               write_log(_T("Plugin path not found\n"));
-               return false;
-       }
 
        // Initialize the pointers this function will use to null.
        errorMessage = 0;
        vertexShaderBuffer = 0;
-       pixelShaderBuffer = 0;
 
        // Compile the vertex shader code.
-       _tcscpy(tmp2, tmp);
-       _tcscat(tmp2, _T("_winuae.vs"));
-       //result = D3DX11CompileFromFile(vsFilename, NULL, NULL, "TextureVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &vertexShaderBuffer, &errorMessage, NULL);
-       result = pD3DCompileFromFile(tmp2, NULL, NULL, "TextureVertexShader", "vs_5_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, &vertexShaderBuffer, &errorMessage);
-       if (FAILED(result))
-       {
-               OutputShaderErrorMessage(errorMessage, hwnd, tmp2);
-               return false;
+       result = E_FAIL;
+       if (plugin_path) {
+               _tcscpy(tmp2, tmp);
+               _tcscat(tmp2, _T("_winuae.vs"));
+               result = pD3DCompileFromFile(tmp2, NULL, NULL, "TextureVertexShader", "vs_5_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, &vertexShaderBuffer, &errorMessage);
        }
-
-       // Compile the pixel shader code.
-       _tcscpy(tmp2, tmp);
-       _tcscat(tmp2, _T("_winuae.ps"));
-       //result = D3DX11CompileFromFile(psFilename, NULL, NULL, "TexturePixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &pixelShaderBuffer, &errorMessage, NULL);
-       result = pD3DCompileFromFile(tmp2, NULL, NULL, "TexturePixelShader", "ps_5_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, &pixelShaderBuffer, &errorMessage);
        if (FAILED(result))
        {
-               OutputShaderErrorMessage(errorMessage, hwnd, tmp2);
-               return false;
+               if (plugin_path) {
+                       OutputShaderErrorMessage(errorMessage, d3d->ahwnd, tmp2);
+                       write_log(_T("Trying built-in shader.\n"));
+               }
+               result = ppD3DCompile(uae_shader_vs, strlen(uae_shader_vs), "uae_shader_vs", NULL, NULL, "TextureVertexShader", "vs_5_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, &vertexShaderBuffer, &errorMessage);
+               if (FAILED(result))
+               {
+                       OutputShaderErrorMessage(errorMessage, d3d->ahwnd, tmp2);
+                       return false;
+               }
        }
 
        // Create the vertex shader from the buffer.
-       result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &d3d->m_vertexShader);
+       result = d3d->m_device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &d3d->m_vertexShader);
        if (FAILED(result))
        {
                write_log(_T("ID3D11Device CreateVertexShader %08x\n"), result);
                return false;
        }
 
-       // Create the pixel shader from the buffer.
-       result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &d3d->m_pixelShader);
-       if (FAILED(result))
-       {
-               write_log(_T("ID3D11Device CreatePixelShader %08x\n"), result);
-               return false;
+       for (int i = 0; i < 3; i++) {
+               ID3D10Blob* pixelShaderBuffer = NULL;
+               ID3D11PixelShader **ps = NULL;
+               char *name;
+
+               switch (i)
+               {
+               case 0:
+                       name = "PS_PostPlain";
+                       ps = &d3d->m_pixelShader;
+                       break;
+               case 1:
+                       name = "PS_PostMask";
+                       ps = &d3d->m_pixelShaderMask;
+                       break;
+               case 2:
+                       name = "PS_PostAlpha";
+                       ps = &d3d->m_pixelShaderSL;
+                       break;
+               }
+               // Compile the pixel shader code.
+               result = E_FAIL;
+               if (plugin_path) {
+                       _tcscpy(tmp2, tmp);
+                       _tcscat(tmp2, _T("_winuae.ps"));
+                       result = pD3DCompileFromFile(tmp2, NULL, NULL, name, "ps_5_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, &pixelShaderBuffer, &errorMessage);
+               }
+               if (FAILED(result))
+               {
+                       if (plugin_path) {
+                               OutputShaderErrorMessage(errorMessage, d3d->ahwnd, tmp2);
+                               write_log(_T("Trying built-in shader.\n"));
+                       }
+                       result = ppD3DCompile(uae_shader_ps, strlen(uae_shader_ps), "uae_shader_ps", NULL, NULL, name, "ps_5_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, &pixelShaderBuffer, &errorMessage);
+                       if (FAILED(result)) {
+                               OutputShaderErrorMessage(errorMessage, d3d->ahwnd, tmp2);
+                               return false;
+                       }
+               }
+
+               // Create the pixel shader from the buffer.
+               result = d3d->m_device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, ps);
+               if (FAILED(result))
+               {
+                       write_log(_T("ID3D11Device CreatePixelShader %08x\n"), result);
+                       pixelShaderBuffer->Release();
+                       pixelShaderBuffer = 0;
+                       return false;
+               }
+
+               pixelShaderBuffer->Release();
+               pixelShaderBuffer = 0;
        }
 
        // Create the vertex input layout description.
@@ -369,11 +1215,19 @@ static bool TextureShaderClass_InitializeShader(ID3D11Device* device, HWND hwnd)
        polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
        polygonLayout[1].InstanceDataStepRate = 0;
 
+       polygonLayout[2].SemanticName = "TEXCOORD";
+       polygonLayout[2].SemanticIndex = 1;
+       polygonLayout[2].Format = DXGI_FORMAT_R32G32_FLOAT;
+       polygonLayout[2].InputSlot = 0;
+       polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
+       polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+       polygonLayout[2].InstanceDataStepRate = 0;
+
        // Get a count of the elements in the layout.
        numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);
 
        // Create the vertex input layout.
-       result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &d3d->m_layout);
+       result = d3d->m_device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &d3d->m_layout);
        if (FAILED(result))
        {
                write_log(_T("ID3D11Device CreateInputLayout %08x\n"), result);
@@ -384,9 +1238,6 @@ static bool TextureShaderClass_InitializeShader(ID3D11Device* device, HWND hwnd)
        vertexShaderBuffer->Release();
        vertexShaderBuffer = 0;
 
-       pixelShaderBuffer->Release();
-       pixelShaderBuffer = 0;
-
        // Setup the description of the dynamic matrix constant buffer that is in the vertex shader.
        matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
        matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType);
@@ -396,7 +1247,7 @@ static bool TextureShaderClass_InitializeShader(ID3D11Device* device, HWND hwnd)
        matrixBufferDesc.StructureByteStride = 0;
 
        // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class.
-       result = device->CreateBuffer(&matrixBufferDesc, NULL, &d3d->m_matrixBuffer);
+       result = d3d->m_device->CreateBuffer(&matrixBufferDesc, NULL, &d3d->m_matrixBuffer);
        if (FAILED(result))
        {
                write_log(_T("ID3D11Device CreateBuffer(matrix) %08x\n"), result);
@@ -404,7 +1255,7 @@ static bool TextureShaderClass_InitializeShader(ID3D11Device* device, HWND hwnd)
        }
 
        // Create a texture sampler state description.
-       samplerDesc.Filter = filterd3d->gfx_filter_bilinear ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT;
+       samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
        samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
        samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
        samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
@@ -419,20 +1270,47 @@ static bool TextureShaderClass_InitializeShader(ID3D11Device* device, HWND hwnd)
        samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
 
        // Create the texture sampler state.
-       result = device->CreateSamplerState(&samplerDesc, &d3d->m_sampleState);
+       result = d3d->m_device->CreateSamplerState(&samplerDesc, &d3d->m_sampleState_point_clamp);
+       if (FAILED(result))
+       {
+               write_log(_T("ID3D11Device CreateSamplerState1 %08x\n"), result);
+               return false;
+       }
+
+       samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+
+       result = d3d->m_device->CreateSamplerState(&samplerDesc, &d3d->m_sampleState_linear_clamp);
+       if (FAILED(result))
+       {
+               write_log(_T("ID3D11Device CreateSamplerState2 %08x\n"), result);
+               return false;
+       }
+
+       samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+       samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+       samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+       // Create the texture sampler state.
+       result = d3d->m_device->CreateSamplerState(&samplerDesc, &d3d->m_sampleState_point_wrap);
        if (FAILED(result))
        {
-               write_log(_T("ID3D11Device CreateSamplerState %08x\n"), result);
+               write_log(_T("ID3D11Device CreateSamplerState1 %08x\n"), result);
+               return false;
+       }
+
+       samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+
+       result = d3d->m_device->CreateSamplerState(&samplerDesc, &d3d->m_sampleState_linear_wrap);
+       if (FAILED(result))
+       {
+               write_log(_T("ID3D11Device CreateSamplerState2 %08x\n"), result);
                return false;
        }
 
        return true;
 }
 
-static bool InitializeBuffers(ID3D11Device* device)
+static bool InitializeBuffers(struct d3d11struct *d3d)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        VertexType* vertices;
        unsigned long* indices;
        D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
@@ -467,137 +1345,58 @@ static bool InitializeBuffers(ID3D11Device* device)
        // Load the index array with data.
        for (i = 0; i < d3d->m_indexCount; i++)
        {
-               indices[i] = i;
-       }
-
-       // Set up the description of the static vertex buffer.
-       vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
-       vertexBufferDesc.ByteWidth = sizeof(VertexType) * d3d->m_vertexCount;
-       vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-       vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-       vertexBufferDesc.MiscFlags = 0;
-       vertexBufferDesc.StructureByteStride = 0;
-
-       // Give the subresource structure a pointer to the vertex data.
-       vertexData.pSysMem = vertices;
-       vertexData.SysMemPitch = 0;
-       vertexData.SysMemSlicePitch = 0;
-
-       // Now create the vertex buffer.
-       result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &d3d->m_vertexBuffer);
-       if (FAILED(result))
-       {
-               write_log(_T("ID3D11Device CreateBuffer(vertex) %08x\n"), result);
-               return false;
-       }
-
-       // Set up the description of the static index buffer.
-       indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
-       indexBufferDesc.ByteWidth = sizeof(unsigned long) * d3d->m_indexCount;
-       indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
-       indexBufferDesc.CPUAccessFlags = 0;
-       indexBufferDesc.MiscFlags = 0;
-       indexBufferDesc.StructureByteStride = 0;
-
-       // Give the subresource structure a pointer to the index data.
-       indexData.pSysMem = indices;
-       indexData.SysMemPitch = 0;
-       indexData.SysMemSlicePitch = 0;
-
-       // Create the index buffer.
-       result = device->CreateBuffer(&indexBufferDesc, &indexData, &d3d->m_indexBuffer);
-       if (FAILED(result))
-       {
-               write_log(_T("ID3D11Device CreateBuffer(index) %08x\n"), result);
-               return false;
-       }
-
-       // Release the arrays now that the vertex and index buffers have been created and loaded.
-       delete[] vertices;
-       vertices = 0;
-
-       delete[] indices;
-       indices = 0;
-
-       return true;
-}
-
-
-static bool UpdateBuffers(ID3D11DeviceContext* deviceContext)
-{
-       struct d3d11struct *d3d = &d3d11data[0];
-
-       int left, right, top, bottom;
-       VertexType* vertices;
-       D3D11_MAPPED_SUBRESOURCE mappedResource;
-       VertexType* verticesPtr;
-       HRESULT result;
-       int positionX, positionY;
-
-       positionX = (d3d->m_screenWidth - d3d->m_bitmapWidth) / 2 + d3d->xoffset;
-       positionY = (d3d->m_screenHeight - d3d->m_bitmapHeight) / 2 + d3d->yoffset;
-
-       // Calculate the screen coordinates of the left side of the bitmap.
-       left = ((d3d->m_screenWidth + 1) / -2) + positionX;
-
-       // Calculate the screen coordinates of the right side of the bitmap.
-       right = left + d3d->m_bitmapWidth;
-
-       // Calculate the screen coordinates of the top of the bitmap.
-       top = ((d3d->m_screenHeight + 1) / 2) - positionY;
-
-       // Calculate the screen coordinates of the bottom of the bitmap.
-       bottom = top - d3d->m_bitmapHeight;
-
-       // Create the vertex array.
-       vertices = new VertexType[d3d->m_vertexCount];
-       if (!vertices)
-       {
-               return false;
-       }
-
-       // Load the vertex array with data.
-       // First triangle.
-       vertices[0].position = D3DXVECTOR3(left, top, 0.0f);  // Top left.
-       vertices[0].texture = D3DXVECTOR2(0.0f, 0.0f);
-
-       vertices[1].position = D3DXVECTOR3(right, bottom, 0.0f);  // Bottom right.
-       vertices[1].texture = D3DXVECTOR2(1.0f, 1.0f);
-
-       vertices[2].position = D3DXVECTOR3(left, bottom, 0.0f);  // Bottom left.
-       vertices[2].texture = D3DXVECTOR2(0.0f, 1.0f);
-
-       // Second triangle.
-       vertices[3].position = D3DXVECTOR3(left, top, 0.0f);  // Top left.
-       vertices[3].texture = D3DXVECTOR2(0.0f, 0.0f);
+               indices[i] = i;
+       }
 
-       vertices[4].position = D3DXVECTOR3(right, top, 0.0f);  // Top right.
-       vertices[4].texture = D3DXVECTOR2(1.0f, 0.0f);
+       // Set up the description of the static vertex buffer.
+       vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+       vertexBufferDesc.ByteWidth = sizeof(VertexType) * d3d->m_vertexCount;
+       vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+       vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+       vertexBufferDesc.MiscFlags = 0;
+       vertexBufferDesc.StructureByteStride = 0;
 
-       vertices[5].position = D3DXVECTOR3(right, bottom, 0.0f);  // Bottom right.
-       vertices[5].texture = D3DXVECTOR2(1.0f, 1.0f);
+       // Give the subresource structure a pointer to the vertex data.
+       vertexData.pSysMem = vertices;
+       vertexData.SysMemPitch = 0;
+       vertexData.SysMemSlicePitch = 0;
 
-       // Lock the vertex buffer so it can be written to.
-       result = deviceContext->Map(d3d->m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+       // Now create the vertex buffer.
+       result = d3d->m_device->CreateBuffer(&vertexBufferDesc, &vertexData, &d3d->m_vertexBuffer);
        if (FAILED(result))
        {
-               write_log(_T("ID3D11DeviceContext map(vertex) %08x\n"), result);
+               write_log(_T("ID3D11Device CreateBuffer(vertex) %08x\n"), result);
                return false;
        }
 
-       // Get a pointer to the data in the vertex buffer.
-       verticesPtr = (VertexType*)mappedResource.pData;
+       // Set up the description of the static index buffer.
+       indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
+       indexBufferDesc.ByteWidth = sizeof(unsigned long) * d3d->m_indexCount;
+       indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+       indexBufferDesc.CPUAccessFlags = 0;
+       indexBufferDesc.MiscFlags = 0;
+       indexBufferDesc.StructureByteStride = 0;
 
-       // Copy the data into the vertex buffer.
-       memcpy(verticesPtr, (void*)vertices, (sizeof(VertexType) * d3d->m_vertexCount));
+       // Give the subresource structure a pointer to the index data.
+       indexData.pSysMem = indices;
+       indexData.SysMemPitch = 0;
+       indexData.SysMemSlicePitch = 0;
 
-       // Unlock the vertex buffer.
-       deviceContext->Unmap(d3d->m_vertexBuffer, 0);
+       // Create the index buffer.
+       result = d3d->m_device->CreateBuffer(&indexBufferDesc, &indexData, &d3d->m_indexBuffer);
+       if (FAILED(result))
+       {
+               write_log(_T("ID3D11Device CreateBuffer(index) %08x\n"), result);
+               return false;
+       }
 
-       // Release the vertex array as it is no longer needed.
+       // Release the arrays now that the vertex and index buffers have been created and loaded.
        delete[] vertices;
        vertices = 0;
 
+       delete[] indices;
+       indices = 0;
+
        return true;
 }
 
@@ -666,10 +1465,10 @@ static bool initd3d(struct d3d11struct *d3d)
        d3d->m_deviceContext->RSSetViewports(1, &viewport);
 
        // Initialize the world matrix to the identity matrix.
-       D3DXMatrixIdentity(&d3d->m_worldMatrix);
+       xD3DXMatrixIdentity(&d3d->m_worldMatrix);
 
        // Create an orthographic projection matrix for 2D rendering.
-       D3DXMatrixOrthoLH(&d3d->m_orthoMatrix, (float)d3d->m_screenWidth, (float)d3d->m_bitmapHeight, 0.0f, 1.0f);
+       xD3DXMatrixOrthoLH(&d3d->m_orthoMatrix, (float)d3d->m_screenWidth, (float)d3d->m_screenHeight, 0.0f, 1.0f);
 
        d3d->m_positionX = 0.0f;
        d3d->m_positionY = 0.0f;
@@ -679,11 +1478,11 @@ static bool initd3d(struct d3d11struct *d3d)
        d3d->m_rotationY = 0.0f;
        d3d->m_rotationZ = 0.0f;
 
-       if (!TextureShaderClass_InitializeShader(d3d->m_device, d3d->ahwnd))
+       if (!TextureShaderClass_InitializeShader(d3d))
                return false;
-       if (!InitializeBuffers(d3d->m_device))
+       if (!InitializeBuffers(d3d))
                return false;
-       if (!UpdateBuffers(d3d->m_deviceContext))
+       if (!UpdateBuffers(d3d))
                return false;
 
        write_log(_T("D3D11 initd3d end\n"));
@@ -692,17 +1491,67 @@ static bool initd3d(struct d3d11struct *d3d)
 
 static void setswapchainmode(struct d3d11struct *d3d, int fs)
 {
+       struct apmode *apm = picasso_on ? &currprefs.gfx_apmode[APMODE_RTG] : &currprefs.gfx_apmode[APMODE_NATIVE];
        // It is recommended to always use the tearing flag when it is supported.
        d3d->swapChainDesc.Flags &= ~DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
-       d3d->swapChainDesc.Flags = d3d->m_tearingSupport ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
+       if (d3d->m_tearingSupport && (d3d->swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL || d3d->swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)) {
+               d3d->swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
+       }
+
        d3d->swapChainDesc.Flags &= ~DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
        if (fs) {
                d3d->swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+               if (apm->gfx_backbuffers > 0)
+                       d3d->swapChainDesc.Flags &= ~DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
        }
+
        d3d->fsSwapChainDesc.Windowed = TRUE;
 }
 
-static const bool xxD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *freq, int mmult)
+bool can_D3D11(bool checkdevice)
+{
+       if (!os_win7)
+               return false;
+
+       if (!hd3d11)
+               hd3d11 = LoadLibrary(_T("D3D11.dll"));
+       if (!hdxgi)
+               hdxgi = LoadLibrary(_T("Dxgi.dll"));
+       if (!hd3dcompiler)
+               hd3dcompiler = LoadLibrary(_T("D3DCompiler_47.dll"));
+
+       if (!hd3d11 || !hdxgi || !hd3dcompiler) {
+               write_log(_T("D3D11.dll=%p Dxgi.dll=%p D3DCompiler_47.dll=%p\n"), hd3d11, hdxgi, hd3dcompiler);
+               return false;
+       }
+
+       pD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(GetModuleHandle(_T("D3D11.dll")), "D3D11CreateDevice");
+       pCreateDXGIFactory1 = (CREATEDXGIFACTORY1)GetProcAddress(GetModuleHandle(_T("Dxgi.dll")), "CreateDXGIFactory1");
+       pD3DCompileFromFile = (D3DCOMPILEFROMFILE)GetProcAddress(GetModuleHandle(_T("D3DCompiler_47.dll")), "D3DCompileFromFile");
+       ppD3DCompile = (D3DCOMPILE)GetProcAddress(GetModuleHandle(_T("D3DCompiler_47.dll")), "D3DCompile");
+
+       if (!pD3D11CreateDevice || !pCreateDXGIFactory1 || !pD3DCompileFromFile || !ppD3DCompile) {
+               write_log(_T("pD3D11CreateDevice=%p pCreateDXGIFactory1=%p pD3DCompileFromFile=%p ppD3DCompile=%p\n"),
+                       pD3D11CreateDevice, pCreateDXGIFactory1, pD3DCompileFromFile, ppD3DCompile);
+               return false;
+       }
+
+       if (checkdevice) {
+               static const D3D_FEATURE_LEVEL levels0[] = { D3D_FEATURE_LEVEL_11_0 };
+               UINT cdflags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+               ID3D11Device *m_device;
+               ID3D11DeviceContext *m_deviceContext;
+               HRESULT hr = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, cdflags, levels0, 1, D3D11_SDK_VERSION, &m_device, NULL, &m_deviceContext);
+               if (FAILED(hr)) {
+                       return false;
+               }
+               m_deviceContext->Release();
+               m_device->Release();
+       }
+       return true;
+}
+
+static bool xxD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *freq, int mmult)
 {
        struct d3d11struct *d3d = &d3d11data[0];
        struct apmode *apm = picasso_on ? &currprefs.gfx_apmode[APMODE_RTG] : &currprefs.gfx_apmode[APMODE_NATIVE];
@@ -724,16 +1573,8 @@ static const bool xxD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *fre
        filterd3didx = picasso_on;
        filterd3d = &currprefs.gf[filterd3didx];
 
-       if (!hd3d11)
-               hd3d11 = LoadLibrary(_T("D3D11.dll"));
-       if (!hdxgi)
-               hdxgi = LoadLibrary(_T("Dxgi.dll"));
-       if (!hd3dcompiler)
-               hd3dcompiler = LoadLibrary(_T("D3DCompiler_47.dll"));
-
-       pD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(GetModuleHandle(_T("D3D11.dll")), "D3D11CreateDevice");
-       pCreateDXGIFactory1 = (CREATEDXGIFACTORY1)GetProcAddress(GetModuleHandle(_T("Dxgi.dll")), "CreateDXGIFactory1");
-       pD3DCompileFromFile = (D3DCOMPILEFROMFILE)GetProcAddress(GetModuleHandle(_T("D3DCompiler_47.dll")), "D3DCompileFromFile");
+       if (!can_D3D11(false))
+               return false;
 
        d3d->m_bitmapWidth = w_w;
        d3d->m_bitmapHeight = w_h;
@@ -850,9 +1691,9 @@ static const bool xxD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *fre
                        d3d->fsSwapChainDesc.Scaling = m->Scaling;
                        if (!hz)
                                break;
-                       if (isfullscreen() > 0) {
+                       if (isfs(d3d) > 0) {
                                double mhz = (double)m->RefreshRate.Numerator / m->RefreshRate.Denominator;
-                               if ((int)(mhz + 0.5) == hz) {
+                               if ((int)(mhz + 0.5) == hz || (int)(mhz) == hz) {
                                        d3d->fsSwapChainDesc.RefreshRate.Denominator = m->RefreshRate.Denominator;
                                        d3d->fsSwapChainDesc.RefreshRate.Numerator = m->RefreshRate.Numerator;
                                        break;
@@ -860,7 +1701,7 @@ static const bool xxD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *fre
                        }
                }
        }
-       if (isfullscreen() > 0 && (hz == 0 || (d3d->fsSwapChainDesc.RefreshRate.Denominator == 0 && d3d->fsSwapChainDesc.RefreshRate.Numerator == 0))) {
+       if (isfs(d3d) > 0 && (hz == 0 || (d3d->fsSwapChainDesc.RefreshRate.Denominator == 0 && d3d->fsSwapChainDesc.RefreshRate.Numerator == 0))) {
                DXGI_MODE_DESC1 md1 = { 0 }, md2;
                md1.Format = d3d->format;
                md1.Width = w_w;
@@ -878,44 +1719,70 @@ static const bool xxD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *fre
 
        // Get the adapter (video card) description.
        result = adapter->GetDesc(&adapterDesc);
-       if (FAILED(result))
-       {
+       if (FAILED(result)) {
+               write_log(_T("IDXGIAdapter1 GetDesc %08x\n"), result);
+               return false;
+       }
+
+       result = adapterOutput->GetDesc(&odesc);
+       if (FAILED(result)) {
                write_log(_T("IDXGIAdapter1 GetDesc %08x\n"), result);
                return false;
        }
 
+       write_log(_T("D3D11 Device: %s [%s] (%d,%d,%d,%d)\n"), adapterDesc.Description, odesc.DeviceName,
+               odesc.DesktopCoordinates.left, odesc.DesktopCoordinates.top,
+               odesc.DesktopCoordinates.right, odesc.DesktopCoordinates.bottom);
+
+
        // Release the display mode list.
        delete[] displayModeList;
        displayModeList = 0;
 
-       // Release the adapter output.
-       adapterOutput->Release();
-       adapterOutput = 0;
+       d3d->outputAdapter = adapterOutput;
 
        // Release the adapter.
        adapter->Release();
        adapter = 0;
 
-       static const D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0 };
+
+       static const D3D_FEATURE_LEVEL levels1[] = { D3D_FEATURE_LEVEL_11_1 };
        UINT cdflags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
 #ifdef _DEBUG
        cdflags |= D3D11_CREATE_DEVICE_DEBUG;
 #endif
-       result = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, cdflags, levels, 2, D3D11_SDK_VERSION, &d3d->m_device, NULL, &d3d->m_deviceContext);
+       result = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, cdflags, levels1, 1, D3D11_SDK_VERSION, &d3d->m_device, NULL, &d3d->m_deviceContext);
        if (FAILED(result)) {
-               write_log(_T("D3D11CreateDevice %08x\n"), result);
-               return false;
+               write_log(_T("D3D11CreateDevice LEVEL_11_1: %08x\n"), result);
+               if (result == E_INVALIDARG || result == DXGI_ERROR_UNSUPPORTED) {
+                       static const D3D_FEATURE_LEVEL levels0[] = { D3D_FEATURE_LEVEL_11_0 };
+                       result = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, cdflags, levels0, 1, D3D11_SDK_VERSION, &d3d->m_device, NULL, &d3d->m_deviceContext);
+               }
+               if (FAILED(result)) {
+                       D3D_FEATURE_LEVEL outlevel;
+                       result = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, cdflags, NULL, 0, D3D11_SDK_VERSION, &d3d->m_device, &outlevel, &d3d->m_deviceContext);
+                       if (FAILED(result)) {
+                               write_log(_T("D3D11CreateDevice %08x\n"), result);
+                       } else {
+                               d3d->m_deviceContext->Release();
+                               d3d->m_deviceContext = NULL;
+                               d3d->m_device->Release();
+                               d3d->m_device = NULL;
+                               gui_message(_T("Direct3D11 Level 11 capable hardware required\nDetected hardware level is: %d.%d"), outlevel >> 12, (outlevel >> 8) & 15);
+                       }
+                       return false;
+               }
        }
 
        ComPtr<IDXGIDevice1> dxgiDevice;
        result = d3d->m_device->QueryInterface(__uuidof(IDXGIDevice1), &dxgiDevice);
        if (FAILED(result)) {
                write_log(_T("QueryInterface IDXGIDevice1 %08x\n"), result);
-       }
-       else {
+       } else {
                result = dxgiDevice->SetMaximumFrameLatency(1);
-               if (FAILED(result))
+               if (FAILED(result)) {
                        write_log(_T("IDXGIDevice1 SetMaximumFrameLatency %08x\n"), result);
+               }
        }
 
        // Initialize the swap chain description.
@@ -935,20 +1802,21 @@ static const bool xxD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *fre
        // Set the usage of the back buffer.
        d3d->swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
 
-       d3d->swapChainDesc.BufferCount = 2;
+       d3d->swapChainDesc.BufferCount = apm->gfx_backbuffers + 1;
+       if (d3d->swapChainDesc.BufferCount < 2)
+               d3d->swapChainDesc.BufferCount = 2;
 
-       d3d->swapChainDesc.Scaling = os_vista ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
-
-       d3d->swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+       d3d->swapChainDesc.SwapEffect = os_win8 ? DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL : DXGI_SWAP_EFFECT_SEQUENTIAL;
 
        d3d->swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
 
-       setswapchainmode(d3d, isfullscreen() > 0);
+       setswapchainmode(d3d, isfs(d3d) > 0);
+
+       d3d->swapChainDesc.Scaling = d3d->swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
 
        // Create the swap chain, Direct3D device, and Direct3D device context.
-       result = factory2->CreateSwapChainForHwnd(d3d->m_device, ahwnd, &d3d->swapChainDesc, isfullscreen() > 0 ? &d3d->fsSwapChainDesc : NULL, NULL, &d3d->m_swapChain);
-       if (FAILED(result))
-       {
+       result = factory2->CreateSwapChainForHwnd(d3d->m_device, ahwnd, &d3d->swapChainDesc, isfs(d3d) > 0 ? &d3d->fsSwapChainDesc : NULL, NULL, &d3d->m_swapChain);
+       if (FAILED(result)) {
                write_log(_T("IDXGIFactory2 CreateSwapChainForHwnd %08x\n"), result);
                return false;
        }
@@ -960,7 +1828,7 @@ static const bool xxD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *fre
 
        d3d->invalidmode = false;
        d3d->fsmode = 0;
-       if (isfullscreen() > 0)
+       if (isfs(d3d) > 0)
                D3D_resize(1);
        D3D_resize(0);
 
@@ -973,14 +1841,12 @@ static void freed3d(struct d3d11struct *d3d)
        write_log(_T("D3D11 freed3d start\n"));
 
        // Before shutting down set to windowed mode or when you release the swap chain it will throw an exception.
-       if (d3d->m_rasterState)
-       {
+       if (d3d->m_rasterState) {
                d3d->m_rasterState->Release();
                d3d->m_rasterState = 0;
        }
 
-       if (d3d->m_renderTargetView)
-       {
+       if (d3d->m_renderTargetView) {
                d3d->m_renderTargetView->Release();
                d3d->m_renderTargetView = 0;
        }
@@ -997,11 +1863,32 @@ static void freed3d(struct d3d11struct *d3d)
                d3d->m_pixelShader->Release();
                d3d->m_pixelShader = NULL;
        }
+       if (d3d->m_pixelShaderMask) {
+               d3d->m_pixelShaderMask->Release();
+               d3d->m_pixelShaderMask = NULL;
+       }
+       if (d3d->m_pixelShaderSL) {
+               d3d->m_pixelShaderSL->Release();
+               d3d->m_pixelShaderSL = NULL;
+       }
 
-       if (d3d->m_sampleState) {
-               d3d->m_sampleState->Release();
-               d3d->m_sampleState = NULL;
+       if (d3d->m_sampleState_point_wrap) {
+               d3d->m_sampleState_point_wrap->Release();
+               d3d->m_sampleState_point_wrap = NULL;
+       }
+       if (d3d->m_sampleState_linear_wrap) {
+               d3d->m_sampleState_linear_wrap->Release();
+               d3d->m_sampleState_linear_wrap = NULL;
+       }
+       if (d3d->m_sampleState_point_clamp) {
+               d3d->m_sampleState_point_clamp->Release();
+               d3d->m_sampleState_point_clamp = NULL;
+       }
+       if (d3d->m_sampleState_linear_clamp) {
+               d3d->m_sampleState_linear_clamp->Release();
+               d3d->m_sampleState_linear_clamp = NULL;
        }
+
        if (d3d->m_indexBuffer) {
                d3d->m_indexBuffer->Release();
                d3d->m_indexBuffer = 0;
@@ -1015,10 +1902,10 @@ static void freed3d(struct d3d11struct *d3d)
                d3d->m_matrixBuffer = 0;
        }
 
-       FreeTexture();
+       FreeTexture(d3d);
+       FreeTexture2D(&d3d->sltexture, &d3d->sltexturerv);
 
-       if (d3d->m_deviceContext)
-       {
+       if (d3d->m_deviceContext) {
                d3d->m_deviceContext->ClearState();
        }
        write_log(_T("D3D11 freed3d end\n"));
@@ -1032,56 +1919,54 @@ static void xD3D11_free(bool immediate)
 
        freed3d(d3d);
 
-       if (d3d->m_swapChain)
-       {
+       if (d3d->m_swapChain) {
                d3d->m_swapChain->SetFullscreenState(false, NULL);
                d3d->m_swapChain->Release();
                d3d->m_swapChain = 0;
        }
-       if (d3d->m_deviceContext)
-       {
+       if (d3d->m_deviceContext) {
                d3d->m_deviceContext->ClearState();
                d3d->m_deviceContext->Flush();
                d3d->m_deviceContext->Release();
                d3d->m_deviceContext = 0;
        }
 
-       if (d3d->m_device)
-       {
+       if (d3d->m_device) {
                d3d->m_device->Release();
                d3d->m_device = 0;
        }
 
+       if (d3d->outputAdapter) {
+               d3d->outputAdapter->Release();
+               d3d->outputAdapter = NULL;
+       }
+
        write_log(_T("D3D11 free end\n"));
 }
 
-
 static const TCHAR *xD3D11_init(HWND ahwnd, int w_w, int w_h, int depth, int *freq, int mmult)
 {
+       if (!can_D3D11(false))
+               return false;
        if (xxD3D11_init(ahwnd, w_w, w_h, depth, freq, mmult))
                return NULL;
        xD3D11_free(true);
        return _T("D3D11 ERROR!");
 }
 
-static bool TextureShaderClass_SetShaderParameters(ID3D11DeviceContext* deviceContext, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix,
-       D3DXMATRIX projectionMatrix, ID3D11ShaderResourceView* texture)
+static bool TextureShaderClass_SetShaderParameters(struct d3d11struct *d3d, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix,D3DXMATRIX projectionMatrix)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        HRESULT result;
        D3D11_MAPPED_SUBRESOURCE mappedResource;
-       MatrixBufferType* dataPtr;
-       unsigned int bufferNumber;
-
+       MatrixBufferType *dataPtr;
 
        // Transpose the matrices to prepare them for the shader.
-       D3DXMatrixTranspose(&worldMatrix, &worldMatrix);
-       D3DXMatrixTranspose(&viewMatrix, &viewMatrix);
-       D3DXMatrixTranspose(&projectionMatrix, &projectionMatrix);
+       xD3DXMatrixTranspose(&worldMatrix, &worldMatrix);
+       xD3DXMatrixTranspose(&viewMatrix, &viewMatrix);
+       xD3DXMatrixTranspose(&projectionMatrix, &projectionMatrix);
 
        // Lock the constant buffer so it can be written to.
-       result = deviceContext->Map(d3d->m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+       result = d3d->m_deviceContext->Map(d3d->m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
        if (FAILED(result))
        {
                write_log(_T("ID3D11DeviceContext map(matrix) %08x\n"), result);
@@ -1097,49 +1982,49 @@ static bool TextureShaderClass_SetShaderParameters(ID3D11DeviceContext* deviceCo
        dataPtr->projection = projectionMatrix;
 
        // Unlock the constant buffer.
-       deviceContext->Unmap(d3d->m_matrixBuffer, 0);
-
-       // Set the position of the constant buffer in the vertex shader.
-       bufferNumber = 0;
+       d3d->m_deviceContext->Unmap(d3d->m_matrixBuffer, 0);
 
        // Now set the constant buffer in the vertex shader with the updated values.
-       deviceContext->VSSetConstantBuffers(bufferNumber, 1, &d3d->m_matrixBuffer);
+       d3d->m_deviceContext->VSSetConstantBuffers(0, 1, &d3d->m_matrixBuffer);
 
        // Set shader texture resource in the pixel shader.
-       deviceContext->PSSetShaderResources(0, 1, &texture);
-
+       d3d->m_deviceContext->PSSetShaderResources(0, 1, &d3d->texture2drv);
+       bool mask = false;
+       for (int i = 0; i < MAX_SHADERS; i++) {
+               if (d3d->shaders[i].type == SHADERTYPE_MASK_AFTER && d3d->shaders[i].masktexturerv) {
+                       d3d->m_deviceContext->PSSetShaderResources(1, 1, &d3d->shaders[i].masktexturerv);
+                       mask = true;
+               }
+       }
+       if (!mask && d3d->sltexturerv) {
+               d3d->m_deviceContext->PSSetShaderResources(1, 1, &d3d->sltexturerv);
+       }
        return true;
 }
 
-static void RenderBuffers(ID3D11DeviceContext* deviceContext)
+static void RenderBuffers(struct d3d11struct *d3d)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        unsigned int stride;
        unsigned int offset;
 
-
        // Set vertex buffer stride and offset.
        stride = sizeof(VertexType);
        offset = 0;
 
        // Set the vertex buffer to active in the input assembler so it can be rendered.
-       deviceContext->IASetVertexBuffers(0, 1, &d3d->m_vertexBuffer, &stride, &offset);
+       d3d->m_deviceContext->IASetVertexBuffers(0, 1, &d3d->m_vertexBuffer, &stride, &offset);
 
        // Set the index buffer to active in the input assembler so it can be rendered.
-       deviceContext->IASetIndexBuffer(d3d->m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
+       d3d->m_deviceContext->IASetIndexBuffer(d3d->m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
 
        // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
-       deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+       d3d->m_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
 }
 
-static void BeginScene(float red, float green, float blue, float alpha)
+static void BeginScene(struct d3d11struct *d3d, float red, float green, float blue, float alpha)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        float color[4];
 
-
        // Setup the color to clear the buffer to.
        color[0] = red;
        color[1] = green;
@@ -1153,21 +2038,20 @@ static void BeginScene(float red, float green, float blue, float alpha)
        d3d->m_deviceContext->ClearRenderTargetView(d3d->m_renderTargetView, color);
 }
 
-static void EndScene(void)
+static void EndScene(struct d3d11struct *d3d)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        HRESULT hr;
        UINT presentFlags = 0;
 
        struct apmode *apm = picasso_on ? &currprefs.gfx_apmode[APMODE_RTG] : &currprefs.gfx_apmode[APMODE_NATIVE];
        if (currprefs.turbo_emulation)
                presentFlags |= DXGI_PRESENT_DO_NOT_WAIT;
-       if (isfullscreen() > 0) {
+       if (isfs(d3d) > 0) {
                hr = d3d->m_swapChain->Present(apm->gfx_vflip == 0 ? 0 : 1, presentFlags);
        } else {
-               if (d3d->m_tearingSupport)
+               if (d3d->m_tearingSupport && (d3d->swapChainDesc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)) {
                        presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
+               }
                hr = d3d->m_swapChain->Present(0, presentFlags);
        }
        if (currprefs.turbo_emulation && hr == DXGI_ERROR_WAS_STILL_DRAWING)
@@ -1176,49 +2060,54 @@ static void EndScene(void)
                write_log(_T("D3D11 Present %08x\n"), hr);
 }
 
-static void TextureShaderClass_RenderShader(ID3D11DeviceContext* deviceContext, int indexCount)
+static void TextureShaderClass_RenderShader(struct d3d11struct *d3d, int indexCount)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        // Set the vertex input layout.
-       deviceContext->IASetInputLayout(d3d->m_layout);
+       d3d->m_deviceContext->IASetInputLayout(d3d->m_layout);
 
        // Set the vertex and pixel shaders that will be used to render this triangle.
-       deviceContext->VSSetShader(d3d->m_vertexShader, NULL, 0);
-       deviceContext->PSSetShader(d3d->m_pixelShader, NULL, 0);
+       d3d->m_deviceContext->VSSetShader(d3d->m_vertexShader, NULL, 0);
+       bool mask = false;
+       for (int i = 0; i < MAX_SHADERS; i++) {
+               if (d3d->shaders[i].type == SHADERTYPE_MASK_AFTER && d3d->shaders[i].masktexturerv) {
+                       mask = true;
+               }
+       }
+       if (mask) {
+               d3d->m_deviceContext->PSSetShader(d3d->m_pixelShaderMask, NULL, 0);
+       } else if (d3d->sltexture) {
+               d3d->m_deviceContext->PSSetShader(d3d->m_pixelShaderSL, NULL, 0);
+       } else {
+               d3d->m_deviceContext->PSSetShader(d3d->m_pixelShader, NULL, 0);
+       }
 
        // Set the sampler state in the pixel shader.
-       deviceContext->PSSetSamplers(0, 1, &d3d->m_sampleState);
+       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);
 
        // Render the triangle.
-       deviceContext->DrawIndexed(indexCount, 0, 0);
+       d3d->m_deviceContext->DrawIndexed(indexCount, 0, 0);
 }
 
-static bool TextureShaderClass_Render(ID3D11DeviceContext* deviceContext, int indexCount, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix,
-       D3DXMATRIX projectionMatrix, ID3D11ShaderResourceView* texture)
+static bool TextureShaderClass_Render(struct d3d11struct *d3d, int indexCount, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix, D3DXMATRIX projectionMatrix)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        bool result;
 
-
        // Set the shader parameters that it will use for rendering.
-       result = TextureShaderClass_SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture);
+       result = TextureShaderClass_SetShaderParameters(d3d, worldMatrix, viewMatrix, projectionMatrix);
        if (!result)
        {
                return false;
        }
 
        // Now render the prepared buffers with the shader.
-       TextureShaderClass_RenderShader(deviceContext, indexCount);
+       TextureShaderClass_RenderShader(d3d, indexCount);
 
        return true;
 }
 
-static void CameraClass_Render()
+static void CameraClass_Render(struct d3d11struct *d3d)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        D3DXVECTOR3 up, position, lookAt;
        float yaw, pitch, roll;
        D3DXMATRIX rotationMatrix;
@@ -1245,40 +2134,36 @@ static void CameraClass_Render()
        roll = d3d->m_rotationZ * 0.0174532925f;
 
        // Create the rotation matrix from the yaw, pitch, and roll values.
-       D3DXMatrixRotationYawPitchRoll(&rotationMatrix, yaw, pitch, roll);
+       xD3DXMatrixRotationYawPitchRoll(&rotationMatrix, yaw, pitch, roll);
 
        // Transform the lookAt and up vector by the rotation matrix so the view is correctly rotated at the origin.
-       D3DXVec3TransformCoord(&lookAt, &lookAt, &rotationMatrix);
-       D3DXVec3TransformCoord(&up, &up, &rotationMatrix);
+       xD3DXVec3TransformCoord(&lookAt, &lookAt, &rotationMatrix);
+       xD3DXVec3TransformCoord(&up, &up, &rotationMatrix);
 
        // Translate the rotated camera position to the location of the viewer.
        lookAt = position + lookAt;
 
        // Finally create the view matrix from the three updated vectors.
-       D3DXMatrixLookAtLH(&d3d->m_viewMatrix, &position, &lookAt, &up);
+       xD3DXMatrixLookAtLH(&d3d->m_viewMatrix, &position, &lookAt, &up);
 }
 
-static bool GraphicsClass_Render(float rotation)
+static bool GraphicsClass_Render(struct d3d11struct *d3d, float rotation)
 {
-       struct d3d11struct *d3d = &d3d11data[0];
-
        bool result;
 
-
        // Clear the buffers to begin the scene.
-       BeginScene(0.0f, 0.0f, 0.0f, 1.0f);
+       BeginScene(d3d, 0.0f, 0.0f, 0.0f, 1.0f);
 
-       setupscenecoords();
-       UpdateBuffers(d3d->m_deviceContext);
+       setupscenecoords(d3d);
 
        // Generate the view matrix based on the camera's position.
-       CameraClass_Render();
+       CameraClass_Render(d3d);
 
        // Put the bitmap vertex and index buffers on the graphics pipeline to prepare them for drawing.
-       RenderBuffers(d3d->m_deviceContext);
+       RenderBuffers(d3d);
 
        // Render the bitmap with the texture shader.
-       result = TextureShaderClass_Render(d3d->m_deviceContext, d3d->m_indexCount, d3d->m_worldMatrix, d3d->m_viewMatrix, d3d->m_orthoMatrix, d3d->texture);
+       result = TextureShaderClass_Render(d3d, d3d->m_indexCount, d3d->m_worldMatrix, d3d->m_viewMatrix, d3d->m_orthoMatrix);
        if (!result)
        {
                return false;
@@ -1297,11 +2182,43 @@ static bool xD3D11_renderframe(bool immediate)
        if (d3d->invalidmode)
                return false;
 
-       GraphicsClass_Render(0);
+       GraphicsClass_Render(d3d, 0);
 
        return true;
 }
 
+static struct shaderdata11 *allocshaderslot(struct d3d11struct *d3d, int type)
+{
+       for (int i = 0; i < MAX_SHADERS; i++) {
+               if (d3d->shaders[i].type == 0) {
+                       d3d->shaders[i].type = type;
+                       return &d3d->shaders[i];
+               }
+       }
+       return NULL;
+}
+
+static void restore(struct d3d11struct *d3d)
+{
+       createscanlines(d3d, 1);
+       for (int i = 0; i < MAX_FILTERSHADERS; i++) {
+               if (filterd3d->gfx_filtermask[i][0]) {
+                       struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_MASK_BEFORE);
+                       createmasktexture(d3d, filterd3d->gfx_filtermask[i], s);
+               }
+       }
+       if (filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS][0]) {
+               struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_MASK_AFTER);
+               createmasktexture(d3d, filterd3d->gfx_filtermask[2 * MAX_FILTERSHADERS], s);
+       }
+       for (int i = 0; i < MAX_FILTERSHADERS; i++) {
+               if (filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS][0]) {
+                       struct shaderdata11 *s = allocshaderslot(d3d, SHADERTYPE_MASK_AFTER);
+                       createmasktexture(d3d, filterd3d->gfx_filtermask[i + MAX_FILTERSHADERS], s);
+               }
+       }
+
+}
 
 static void xD3D11_showframe(void)
 {
@@ -1309,7 +2226,7 @@ static void xD3D11_showframe(void)
        if (d3d->invalidmode)
                return;
        // Present the rendered scene to the screen.
-       EndScene();
+       EndScene(d3d);
 }
 
 static void xD3D11_clear(void)
@@ -1317,11 +2234,14 @@ static void xD3D11_clear(void)
        struct d3d11struct *d3d = &d3d11data[0];
        if (d3d->invalidmode)
                return;
-       BeginScene(0, 0, 0, 0);
+       BeginScene(d3d, 0, 0, 0, 0);
 }
 
 static void xD3D11_refresh(void)
 {
+       struct d3d11struct *d3d = &d3d11data[0];
+
+       createscanlines(d3d, 0);
        if (xD3D11_renderframe(true)) {
                xD3D11_showframe();
        }
@@ -1330,13 +2250,19 @@ static void xD3D11_refresh(void)
 static bool xD3D11_alloctexture(int w, int h)
 {
        struct d3d11struct *d3d = &d3d11data[0];
+       bool v;
 
        if (d3d->invalidmode)
                return false;
        d3d->m_bitmapWidth = w;
        d3d->m_bitmapHeight = h;
-       UpdateBuffers(d3d->m_deviceContext);
-       return CreateTexture();
+       d3d->dmult = S2X_getmult();
+       v = CreateTexture(d3d);
+       if (!v)
+               return false;
+       restore(d3d);
+       setupscenecoords(d3d);
+       return true;
 }
 
 static uae_u8 *xD3D11_locktexture(int *pitch, int *height, bool fullupdate)
@@ -1368,6 +2294,12 @@ static void xD3D11_unlocktexture(void)
 
        d3d->m_deviceContext->Unmap(d3d->texture2dstaging, 0);
 
+#if 0
+       if (currprefs.leds_on_screen & (STATUSLINE_CHIPSET | STATUSLINE_RTG)) {
+               updateleds(d3d);
+       }
+#endif
+
        D3D11_BOX box;
        box.front = 0;
        box.back = 1;
@@ -1376,6 +2308,7 @@ static void xD3D11_unlocktexture(void)
        box.top = 0;
        box.bottom = d3d->m_bitmapHeight;
        d3d->m_deviceContext->CopySubresourceRegion(d3d->texture2d, 0, 0, 0, 0, d3d->texture2dstaging, 0, &box);
+
 }
 
 static void xD3D11_flushtexture(int miny, int maxy)
@@ -1385,12 +2318,10 @@ static void xD3D11_flushtexture(int miny, int maxy)
 
 static void xD3D11_restore(void)
 {
-       
-}
-
-static void xD3D11_guimode(bool guion)
-{
-
+       struct d3d11struct *d3d = &d3d11data[0];
+       if (!d3d->texture2d)
+               return;
+       createscanlines(d3d, 0);
 }
 
 static void xD3D11_vblank_reset(double freq)
@@ -1404,7 +2335,36 @@ static int xD3D11_canshaders(void)
 }
 static int xD3D11_goodenough(void)
 {
-       return 0;
+       return 1;
+}
+
+static void xD3D11_change(int temp)
+{
+       struct d3d11struct *d3d = &d3d11data[0];
+}
+
+static void resizemode(struct d3d11struct *d3d)
+{
+       if (!d3d->invalidmode) {
+               freed3d(d3d);
+               write_log(_T("D3D11 resize %d %d, %d %d\n"), d3d->m_screenWidth, d3d->m_screenHeight, d3d->m_bitmapWidth, d3d->m_bitmapHeight);
+               setswapchainmode(d3d, d3d->fsmode);
+               HRESULT hr = d3d->m_swapChain->ResizeBuffers(d3d->swapChainDesc.BufferCount, d3d->m_screenWidth, d3d->m_screenHeight, d3d->format, d3d->swapChainDesc.Flags);
+               if (FAILED(hr)) {
+                       write_log(_T("ResizeBuffers %08x\n"), hr);
+                       d3d->invalidmode = true;
+               }
+               if (!d3d->invalidmode) {
+                       if (!initd3d(d3d)) {
+                               xD3D11_free(true);
+                               currprefs.gfx_api = changed_prefs.gfx_api = 1;
+                               d3d->invalidmode = true;
+                               d3d9_select();
+                       } else {
+                               xD3D11_alloctexture(d3d->m_bitmapWidth, d3d->m_bitmapHeight);
+                       }
+               }
+       }
 }
 
 static void xD3D11_resize(int activate)
@@ -1413,6 +2373,11 @@ static void xD3D11_resize(int activate)
        HRESULT hr;
        struct d3d11struct *d3d = &d3d11data[0];
 
+       write_log(_T("D3D11_resize %d %d %d (%d)\n"), activate, d3d->fsmodechange, d3d->fsmode, d3d->guimode);
+
+       if (d3d->guimode && isfullscreen() > 0)
+               return;
+
        if (activate) {
                if (activate != d3d->fsmode) {
                        d3d->fsmode = activate;
@@ -1427,8 +2392,9 @@ static void xD3D11_resize(int activate)
 
        if (d3d->m_swapChain) {
                if (d3d->fsmodechange && d3d->fsmode > 0) {
+                       write_log(_T("D3D11_resize -> fullscreen\n"));
                        ShowWindow(d3d->ahwnd, SW_SHOWNORMAL);
-                       hr = d3d->m_swapChain->SetFullscreenState(TRUE, NULL);
+                       hr = d3d->m_swapChain->SetFullscreenState(TRUE, d3d->outputAdapter);
                        if (FAILED(hr)) {
                                write_log(_T("SetFullscreenState(TRUE) failed %08X\n"), hr);
                                toggle_fullscreen(10);
@@ -1438,6 +2404,7 @@ static void xD3D11_resize(int activate)
                        d3d->fsmodechange = 0;
                        d3d->invalidmode = false;
                } else if (d3d->fsmodechange && d3d->fsmode < 0) {
+                       write_log(_T("D3D11_resize -> window\n"));
                        hr = d3d->m_swapChain->SetFullscreenState(FALSE, NULL);
                        if (FAILED(hr))
                                write_log(_T("SetFullscreenState(FALSE) failed %08X\n"), hr);
@@ -1446,30 +2413,102 @@ static void xD3D11_resize(int activate)
                        d3d->invalidmode = true;
                        d3d->fsmodechange = 0;
                }
-               if (!d3d->invalidmode) {
-                       freed3d(d3d);
-                       write_log(_T("D3D11 resize %d %d, %d %d\n"), d3d->m_screenWidth, d3d->m_screenHeight, d3d->m_bitmapWidth, d3d->m_bitmapHeight);
-                       setswapchainmode(d3d, d3d->fsmode);
-                       HRESULT hr = d3d->m_swapChain->ResizeBuffers(d3d->swapChainDesc.BufferCount, d3d->m_screenWidth, d3d->m_screenHeight, d3d->format, d3d->swapChainDesc.Flags);
-                       if (FAILED(hr)) {
-                               write_log(_T("ResizeBuffers %08x\n"), hr);
-                               d3d->invalidmode = true;
-                       }
-                       if (!d3d->invalidmode) {
-                               if (!initd3d(d3d)) {
-                                       xD3D11_free(true);
-                                       changed_prefs.gfx_api = 1;
-                                       d3d->invalidmode = true;
-                               } else {
-                                       xD3D11_alloctexture(d3d->m_bitmapWidth, d3d->m_bitmapHeight);
-                               }
-                       }
-               }
+               resizemode(d3d);
        }
 
        recursive--;
 }
 
+static void xD3D11_guimode(int guion)
+{
+       struct d3d11struct *d3d = &d3d11data[0];
+
+       if (isfullscreen() <= 0)
+               return;
+
+       write_log(_T("guimode %d\n"), guion);
+       d3d->guimode = guion;
+       if (guion > 0) {
+               ;
+       } else if (guion == 0) {
+               d3d->fsmode = 0;
+               xD3D11_resize(1);
+               xD3D11_resize(0);
+       }
+       write_log(_T("guimode end\n"));
+}
+
+static int xD3D_isenabled(void)
+{
+       struct d3d11struct *d3d = &d3d11data[0];
+       return d3d->m_device != NULL ? 2 : 0;
+}
+
+static bool xD3D_getvblankpos(int *vp)
+{
+       *vp = 0;
+       return false;
+}
+
+static HDC xD3D_getDC(HDC hdc)
+{
+       struct d3d11struct *d3d = &d3d11data[0];
+       IDXGISurface1 *g_pSurface1 = NULL;
+       HRESULT hr;
+
+       if (hdc) {
+               RECT empty = { 0 };
+               g_pSurface1->ReleaseDC(&empty);
+               g_pSurface1->Release();
+               return NULL;
+       } else {
+               HDC g_hDC;
+               //Setup the device and and swapchain
+               hr = d3d->m_swapChain->GetBuffer(0, __uuidof(IDXGISurface1), (void**)&g_pSurface1);
+               if (FAILED(hr)) {
+                       write_log(_T("GetDC GetBuffer() %08x\n"), hr);
+                       return NULL;
+               }
+               hr = g_pSurface1->GetDC(FALSE, &g_hDC);
+               if (FAILED(hr)) {
+                       write_log(_T("GetDC GetDC() %08x\n"), hr);
+                       g_pSurface1->Release();
+                       return NULL;
+               }
+               d3d->hdc_surface = g_pSurface1;
+               return g_hDC;
+       }
+}
+
+bool D3D11_capture(void **data, int *w, int *h, int *pitch)
+{
+       struct d3d11struct *d3d = &d3d11data[0];
+       HRESULT hr;
+
+       if (!d3d->screenshottexture)
+               return false;
+
+       if (!w || !h) {
+               d3d->m_deviceContext->Unmap(d3d->screenshottexture, 0);
+               return true;
+       } else {
+               D3D11_MAPPED_SUBRESOURCE map;
+               ID3D11Resource* pSurface = NULL;
+               d3d->m_renderTargetView->GetResource(&pSurface);
+               d3d->m_deviceContext->CopyResource(d3d->screenshottexture, pSurface);
+               hr = d3d->m_deviceContext->Map(d3d->screenshottexture, 0, D3D11_MAP_READ, 0, &map);
+               if (FAILED(hr)) {
+                       return false;
+               }
+               pSurface->Release();
+               *data = map.pData;
+               *pitch = map.RowPitch;
+               *w = d3d->m_bitmapWidth;
+               *h = d3d->m_bitmapHeight;
+               return true;
+       }
+}
+
 void d3d11_select(void)
 {
        D3D_free = xD3D11_free;
@@ -1486,16 +2525,17 @@ void d3d11_select(void)
        D3D_showframe = xD3D11_showframe;
        D3D_showframe_special = NULL;
        D3D_guimode = xD3D11_guimode;
-       D3D_getDC = NULL;
-       D3D_isenabled = NULL;
+       D3D_getDC = xD3D_getDC;
+       D3D_isenabled = xD3D_isenabled;
        D3D_clear = xD3D11_clear;
        D3D_canshaders = xD3D11_canshaders;
        D3D_goodenough = xD3D11_goodenough;
        D3D_setcursor = NULL;
-       D3D_getvblankpos = NULL;
+       D3D_getvblankpos = xD3D_getvblankpos;
        D3D_getrefreshrate = NULL;
        D3D_vblank_reset = xD3D11_vblank_reset;
        D3D_resize = xD3D11_resize;
+       D3D_change = xD3D11_change;
 }
 
 void d3d_select(struct uae_prefs *p)
index a4220819d4d8dd0c6890fd30b15ad7a03971a60a..e08c834db092068484b7537144734646608c1d5d 100644 (file)
@@ -401,7 +401,50 @@ donormal:
                width = WIN32GFX_GetWidth ();
                height = WIN32GFX_GetHeight ();
 
-               if (D3D_isenabled()) {
+               if (D3D_isenabled() == 2) {
+                       int w, h, pitch, bits = 32;
+                       void *data;
+                       bool got = D3D11_capture(&data, &w, &h, &pitch);
+
+                       int dpitch = (((w * depth + 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 = depth;
+                       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 (got && lpvBits) {
+                               for (int y = 0; y < h; y++) {
+                                       uae_u8 *d = (uae_u8*)lpvBits + (h - y - 1) * dpitch;
+                                       uae_u32 *s = (uae_u32*)((uae_u8*)data + y * pitch);
+                                       for (int x = 0; x < w; x++) {
+                                               uae_u32 v = *s++;
+                                               d[0] = v >> 0;
+                                               d[1] = v >> 8;
+                                               d[2] = v >> 16;
+                                               if (depth == 32) {
+                                                       d[3] = v >> 24;
+                                                       d += 4;
+                                               } else {
+                                                       d += 3;
+                                               }
+                                       }
+                               }
+                       }
+                       if (got)
+                               D3D11_capture(NULL, NULL, NULL, NULL);
+                       d3dcaptured = true;
+
+               } else if (D3D_isenabled() == 1) {
                        int w, h, bits;
                        HRESULT hr;
                        D3DLOCKED_RECT l;
index d46ed40334d243e70776eda0cf9528fd26c6b631..3b83624b3090353eaec218849ae6c8c19b5f6e90 100644 (file)
@@ -530,7 +530,12 @@ void setminimized (void)
        if (!minimized)
                minimized = 1;
        set_inhibit_frame (IHF_WINDOWHIDDEN);
+       if (isfullscreen() > 0 && D3D_resize) {
+               write_log(_T("setminimized\n"));
+               D3D_resize(-1);
+       }
 }
+
 void unsetminimized (void)
 {
        if (minimized < 0)
@@ -1575,17 +1580,23 @@ static LRESULT CALLBACK AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam,
                        setminimized ();
                        winuae_inactive (hWnd, minimized);
                }
-               if (D3D_resize)
+               if (D3D_resize)  {
+                       if (isfullscreen() > 0 && wParam == SIZE_RESTORED) {
+                               write_log(_T("WM_SIZE restored\n"));
+                               D3D_resize(1);
+                       }
+                       write_log(_T("WM_SIZE\n"));
                        D3D_resize(0);
+               }
                break;
        case WM_ACTIVATE:
                //write_log (_T("active %d\n"), LOWORD(wParam));
-               if (LOWORD (wParam) == WA_INACTIVE) {
-                       if (HIWORD (wParam))
-                               setminimized ();
+               if (LOWORD(wParam) == WA_INACTIVE) {
+                       if (HIWORD(wParam))
+                               setminimized();
                        else
-                               unsetminimized ();
-                       winuae_inactive (hWnd, minimized);
+                               unsetminimized();
+                       winuae_inactive(hWnd, minimized);
                }
                dx_check ();
                break;
@@ -1595,9 +1606,11 @@ static LRESULT CALLBACK AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam,
                break;
        case WM_ACTIVATEAPP:
                D3D_restore ();
-               if (!wParam && isfullscreen() > 0 && D3D_resize) {
+               if (!wParam && isfullscreen() > 0 && D3D_resize && !gui_active) {
+                       write_log(_T("WM_ACTIVATEAPP inactive %p\n"), hWnd);
                        D3D_resize(-1);
-               } else if (wParam && isfullscreen() > 0 && D3D_resize) {
+               } else if (wParam && isfullscreen() > 0 && D3D_resize && !gui_active) {
+                       write_log(_T("WM_ACTIVATEAPP active %p\n"), hWnd);
                        D3D_resize(1);
                }
                if (!wParam && isfullscreen() <= 0 && currprefs.win32_minimize_inactive) {
@@ -5153,7 +5166,7 @@ static int betamessage (void)
        return 1;
 }
 
-int os_admin, os_64bit, os_win7, os_vista, cpu_number, os_touch;
+int os_admin, os_64bit, os_win7, os_win8, os_vista, cpu_number, os_touch;
 BOOL os_dwm_enabled;
 
 static int isadminpriv (void)
@@ -5235,6 +5248,8 @@ static int osdetect (void)
                        os_vista = 1;
                if (osVersion.dwMajorVersion >= 7 || (osVersion.dwMajorVersion == 6 && osVersion.dwMinorVersion >= 1))
                        os_win7 = 1;
+               if (osVersion.dwMajorVersion >= 7 || (osVersion.dwMajorVersion == 6 && osVersion.dwMinorVersion >= 2))
+                       os_win8 = 1;
                if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
                        os_64bit = 1;
        }
@@ -5286,7 +5301,8 @@ void create_afnewdir (int remove)
                _tcscpy (tmp, tmp2);
                _tcscat (tmp, _T("\\WinUAE"));
                if (remove) {
-                       if (GetFileAttributes (tmp) != INVALID_FILE_ATTRIBUTES) {
+                       DWORD attrs = GetFileAttributes(tmp);
+                       if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) && !(attrs & FILE_ATTRIBUTE_REPARSE_POINT)) {
                                RemoveDirectory (tmp);
                                RemoveDirectory (tmp2);
                        }
index 173491d75e70bf4f46ff41fbfc62046381c57977..976eff47808a5675d3de4e840547809b7e17cc32 100644 (file)
@@ -784,11 +784,12 @@ bool S2X_init (int dw, int dh, int dd)
        amiga_height2 = vb->outheight;
        amiga_depth2 = vb->pixbytes * 8;
 
-
        S2X_free ();
        d3d = currprefs.gfx_api;
-       changed_prefs.leds_on_screen |= STATUSLINE_TARGET;
-       currprefs.leds_on_screen |= STATUSLINE_TARGET;
+       if (d3d < 2) {
+               changed_prefs.leds_on_screen |= STATUSLINE_TARGET;
+               currprefs.leds_on_screen |= STATUSLINE_TARGET;
+       }
 
        if (d3d)
                dd = amiga_depth2;
index b640972416b545e63e5bd272eacf7a8d1088d70d..b5a13257c0d7baf20e5c2c4a43e54956433e8c50 100644 (file)
@@ -2092,7 +2092,7 @@ int check_prefs_changed_gfx (void)
                c |= gf->gfx_filter_vert_zoom_mult != gfc->gfx_filter_vert_zoom_mult ? (1) : 0;
 
                c |= gf->gfx_filter_filtermode != gfc->gfx_filter_filtermode ? (2|8) : 0;
-               c |= gf->gfx_filter_bilinear != gfc->gfx_filter_bilinear ? (2|8) : 0;
+               c |= gf->gfx_filter_bilinear != gfc->gfx_filter_bilinear ? (2|8|16) : 0;
                c |= gf->gfx_filter_noise != gfc->gfx_filter_noise ? (1) : 0;
                c |= gf->gfx_filter_blur != gfc->gfx_filter_blur ? (1) : 0;
 
@@ -3914,6 +3914,9 @@ double vblank_calibrate (double approx_vblank, bool waitonly)
        bool remembered = false;
        bool lace = false;
 
+       if (currprefs.gfx_api == 2)
+               goto fail;
+
        if (picasso_on) {
                width = picasso96_state.Width;
                height = picasso96_state.Height;
@@ -4648,15 +4651,22 @@ static BOOL doInit (void)
        if (currentmode->flags & DM_D3D) {
                const TCHAR *err = D3D_init (hAmigaWnd, currentmode->native_width, currentmode->native_height, currentmode->current_depth, &currentmode->freq, screen_is_picasso ? 1 : currprefs.gf[picasso_on].gfx_filter_filtermode + 1);
                if (err) {
-                       D3D_free (true);
-                       gui_message (err);
-                       changed_prefs.gfx_api = currprefs.gfx_api = 0;
-                       changed_prefs.gf[picasso_on].gfx_filter = currprefs.gf[picasso_on].gfx_filter = 0;
-                       currentmode->current_depth = currentmode->native_depth;
-                       gfxmode_reset ();
-                       DirectDraw_Start ();
-                       ret = -1;
-                       goto oops;
+                       if (currprefs.gfx_api == 2) {
+                               D3D_free(true);
+                               changed_prefs.gfx_api = currprefs.gfx_api = 1;
+                               err = D3D_init(hAmigaWnd, currentmode->native_width, currentmode->native_height, currentmode->current_depth, &currentmode->freq, screen_is_picasso ? 1 : currprefs.gf[picasso_on].gfx_filter_filtermode + 1);
+                       }
+                       if (err) {
+                               D3D_free(true);
+                               gui_message(err);
+                               changed_prefs.gfx_api = currprefs.gfx_api = 0;
+                               changed_prefs.gf[picasso_on].gfx_filter = currprefs.gf[picasso_on].gfx_filter = 0;
+                               currentmode->current_depth = currentmode->native_depth;
+                               gfxmode_reset();
+                               DirectDraw_Start();
+                               ret = -1;
+                               goto oops;
+                       }
                }
                target_graphics_buffer_update ();
                updatewinrect (true);