ScreenBuffer - DirectX screen capture

Post your working scripts, libraries and tools.

Turisas
Posts: 6
Joined: 04 Jul 2020, 15:21

Re: ScreenBuffer - DirectX screen capture

Post by Turisas » 20 May 2022, 18:22

Thanks for your help :thumbup: .

Sorry for the late answer but i try since 3 Days to do it by myself. But i think im complitly on the wrong way.

This is what i have.

Code: Select all

setbatchlines -1
; Load GDI+
DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0) ; sizeof(GdiplusStartupInput) = 16, 24
NumPut(0x1, si, "uint")
DllCall("gdiplus\GdiplusStartup", "ptr*", pToken:=0, "ptr", &si, "ptr", 0)
extension := "png"
DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", count:=0, "uint*", size:=0)
VarSetCapacity(ci, size)
DllCall("gdiplus\GdipGetImageEncoders", "uint", count, "uint", size, "ptr", &ci)
if !(count && size)
   throw Exception("Could not get a list of image codec encoders on this system.")
Loop % count
   EncoderExtensions := StrGet(NumGet(ci, (idx:=(48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize, "uptr"), "UTF-16")
      until InStr(EncoderExtensions, "*." extension)
if !(pCodec := &ci + idx)
   throw Exception("Could not find a matching encoder for the specified file format.")

IDXGIFactory := CreateDXGIFactory()
if !IDXGIFactory
{
   MsgBox, 16, Error, Create IDXGIFactory failed.
   ExitApp
}
loop
{
   IDXGIFactory_EnumAdapters(IDXGIFactory, A_Index-1, IDXGIAdapter)
   loop
   {
      hr := IDXGIAdapter_EnumOutputs(IDXGIAdapter, A_Index-1, IDXGIOutput)
      if (hr = "DXGI_ERROR_NOT_FOUND")
         break
      VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
      IDXGIOutput_GetDesc(IDXGIOutput, &DXGI_OUTPUT_DESC)
      Width := NumGet(DXGI_OUTPUT_DESC, 72, "int")
      Height := NumGet(DXGI_OUTPUT_DESC, 76, "int")
      AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, "int")
      if (AttachedToDesktop = 1)
         break 2         
   }
}
if (AttachedToDesktop != 1)
{
   MsgBox, 16, Error, No adapter attached to desktop
   ExitApp
}
D3D11CreateDevice(IDXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN := 0, 0, 0, 0, 0, D3D11_SDK_VERSION := 7, d3d_device, 0, d3d_context)
IDXGIOutput1 := IDXGIOutput1_Query(IDXGIOutput)
IDXGIOutput1_DuplicateOutput(IDXGIOutput1, d3d_device, Duplication)
VarSetCapacity(DXGI_OUTDUPL_DESC, 36, 0)
IDXGIOutputDuplication_GetDesc(Duplication, &DXGI_OUTDUPL_DESC)
DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, "uint")
sleep 50   ; As I understand - need some sleep for successful connecting to IDXGIOutputDuplication interface

VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
NumPut(width, D3D11_TEXTURE2D_DESC, 0, "uint")   ; Width
NumPut(height, D3D11_TEXTURE2D_DESC, 4, "uint")   ; Height
NumPut(1, D3D11_TEXTURE2D_DESC, 8, "uint")   ; MipLevels
NumPut(1, D3D11_TEXTURE2D_DESC, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, "uint")   ; Format
NumPut(1, D3D11_TEXTURE2D_DESC, 20, "uint")   ; SampleDescCount
NumPut(0, D3D11_TEXTURE2D_DESC, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, "uint")   ; Usage
NumPut(0, D3D11_TEXTURE2D_DESC, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, "uint")   ; CPUAccessFlags
NumPut(0, D3D11_TEXTURE2D_DESC, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &D3D11_TEXTURE2D_DESC, 0, staging_tex)
;-----------------------------------------------------------------------------------------------------------------------------
VarSetCapacity(D3D11_SMALLER_TEXTURE2D_DESC, 44, 0)
width2 := Round(width / 2)
height2 := Round(height / 2)
NumPut(width2, D3D11_SMALLER_TEXTURE2D_DESC, 0, "uint")   ; Width
NumPut(height2, D3D11_SMALLER_TEXTURE2D_DESC, 4, "uint")   ; Height
NumPut(4, D3D11_SMALLER_TEXTURE2D_DESC, 8, "uint")   ; MipLevels
NumPut(1, D3D11_SMALLER_TEXTURE2D_DESC, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_SMALLER_TEXTURE2D_DESC, 16, "uint")   ; Format
NumPut(1, D3D11_SMALLER_TEXTURE2D_DESC, 20, "uint")   ; SampleDescCount
NumPut(0, D3D11_SMALLER_TEXTURE2D_DESC, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 0, D3D11_SMALLER_TEXTURE2D_DESC, 28, "uint")   ; Usage
NumPut(D3D11_BIND_RENDER_TARGET := 0x20, D3D11_SMALLER_TEXTURE2D_DESC, "uint")   ; BindFlags
NumPut(0, D3D11_SMALLER_TEXTURE2D_DESC, 36, "uint")   ; CPUAccessFlags
NumPut(D3D11_RESOURCE_MISC_GENERATE_MIPS := 0x1, D3D11_SMALLER_TEXTURE2D_DESC, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &D3D11_SMALLER_TEXTURE2D_DESC, 0, smaller_tex)
D3DX11CreateShaderResourceViewFromResourceA(d3d_device, smaller_tex, smallerTextureView)
;-----------------------------------------------------------------------------------------------------------------------------

loop 1
{
   tooltip % A_Index
   VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
   if (A_Index = 1)
   {
      loop
      {
         AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, -1, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
         LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, "int64")
         if (LastPresentTime > 0)
            break
         ObjRelease(desktop_resource)
         IDXGIOutputDuplication_ReleaseFrame(duplication)
      }
   }
   else
   {
      AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, 0, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
      LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, "int64")
   }
   if (AcquireNextFrame != "DXGI_ERROR_WAIT_TIMEOUT")
   {
      if (LastPresentTime > 0)
      {
         if (DesktopImageInSystemMemory = 1)
         {
            VarSetCapacity(DXGI_MAPPED_RECT, A_PtrSize*2, 0)
            IDXGIOutputDuplication_MapDesktopSurface(Duplication, &DXGI_MAPPED_RECT)
            pitch := NumGet(DXGI_MAPPED_RECT, 0, "int")
            pBits := NumGet(DXGI_MAPPED_RECT, A_PtrSize, "ptr")
         }
         else
         {
            tex := ID3D11Texture2D_Query(desktop_resource)
			ID3D11DeviceContext_CopySubresourceRegion(d3d_device, smaller_tex, 0, 0, 0, 0, tex, 0, 0)
            VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
			ID3D11DeviceContext_CopySubresourceRegion(d3d_device, staging_tex, 1, 0, 0, 0, smaller_tex, 0, 0)
			ID3D11DeviceContext_Map(d3d_context, staging_tex, 0, D3D11_MAP_READ := 1, 0, &D3D11_MAPPED_SUBRESOURCE)
            pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
            pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
         }
      }
   }
   DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width, "int", height, "int", pitch, "int", 0xE200B, "ptr", pBits, "ptr*", pBitmap:=0)
   DllCall("gdiplus\GdipSaveImageToFile", "ptr", pBitmap, "wstr", A_Index ".png", "ptr", pCodec, "uint", 0)
   DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
   if (AcquireNextFrame != "DXGI_ERROR_WAIT_TIMEOUT")
   {
      if (LastPresentTime > 0)
      {
         if (DesktopImageInSystemMemory = 1)
            IDXGIOutputDuplication_UnMapDesktopSurface(Duplication)
         else
         {
            ID3D11DeviceContext_Unmap(d3d_context, staging_tex, 0)
            ObjRelease(tex)
         }
      }
      ObjRelease(desktop_resource)
      IDXGIOutputDuplication_ReleaseFrame(duplication)
   }
}
tooltip
Release(staging_tex)
Release(smaller_tex)
Release(tex)
Release(d3d_device)
Release(d3d_context)
Release(duplication)
Release(IDXGIAdapter)
Release(IDXGIOutput)
Release(IDXGIOutput1)
Release(IDXGIFactory)
;msgbox % DesktopImageInSystemMemory
ExitApp




CreateDXGIFactory()
{
   if !DllCall("GetModuleHandle","str","DXGI")
      DllCall("LoadLibrary","str","DXGI")
   if !DllCall("GetModuleHandle","str","D3D11")
      DllCall("LoadLibrary","str","D3D11")
   GUID(riid, "{7b7166ec-21c7-44ae-b21a-c9ae321ae369}")
   hr := DllCall("DXGI\CreateDXGIFactory1", "ptr", &riid, "ptr*", ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return ppFactory
}

IDXGIFactory_EnumAdapters(this, Adapter, ByRef ppAdapter)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Adapter, "ptr*", ppAdapter)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIAdapter_EnumOutputs(this, Output, ByRef ppOutput)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Output, "ptr*", ppOutput)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0002   ; DXGI_ERROR_NOT_FOUND
         return "DXGI_ERROR_NOT_FOUND"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

D3DX11CreateShaderResourceViewFromResourceA(this, pDesc, ByRef ppSRView)
{
   hr := DllCall(NumGet(NumGet(this+0)+21*A_PtrSize), "ptr", this, "ptr", pDesc, "ptr*", ppSRView)
   if hr or ErrorLevel
	  _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIAdapter_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_GetDesc(this, pDesc)
{
   DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_AcquireNextFrame(this, TimeoutInMilliseconds, pFrameInfo, ByRef ppDesktopResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint", TimeoutInMilliseconds, "ptr", pFrameInfo, "ptr*", ppDesktopResource)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0027   ; DXGI_ERROR_WAIT_TIMEOUT
         return "DXGI_ERROR_WAIT_TIMEOUT"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ByRef ppDevice, ByRef pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall("D3D11\D3D11CreateDevice", "ptr", pAdapter, "int", DriverType, "ptr", Software, "uint", Flags, "ptr", pFeatureLevels, "uint", FeatureLevels, "uint", SDKVersion, "ptr*", ppDevice, "ptr*", pFeatureLevel, "ptr*", ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_CreateTexture2D(this, pDesc, pInitialData, ByRef ppTexture2D)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", pDesc, "ptr", pInitialData, "ptr*", ppTexture2D)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_MapDesktopSurface(this, pLockedRect)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr", pLockedRect)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0004   ; DXGI_ERROR_UNSUPPORTED
         return "DXGI_ERROR_UNSUPPORTED"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IDXGIOutputDuplication_UnMapDesktopSurface(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_ReleaseFrame(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput1_DuplicateOutput(this, pDevice, ByRef ppOutputDuplication)
{
   hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), "ptr", this, "ptr", pDevice, "ptr*", ppOutputDuplication)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput1_Query(IDXGIOutput)
{ 
   hr := ComObjQuery(IDXGIOutput, "{00cddea8-939b-4b83-a340-a685226666cc}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

ID3D11Texture2D_Query(desktop_resource)
{ 
   hr := ComObjQuery(desktop_resource, "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), "ptr", this, "ptr", pDstResource, "ptr", pSrcResource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_CopySubresourceRegion(this, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox)
{
   hr := DllCall(NumGet(NumGet(this+0)+46*A_PtrSize), "ptr", this, "ptr", pDstResource, "uint", DstSubresource, "uint", DstX, "uint", DstY, "uint", DstZ, "ptr", pSrcResource, "uint", SrcSubresource, "ptr", pSrcBox)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource, "uint", MapType, "uint", MapFlags, "ptr", pMappedResource)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Unmap(this, pResource, Subresource)
{
   hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

Release(this)
{
   DllCall(NumGet(NumGet(this+0)+2*A_PtrSize), "ptr", this)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

_Error(val)
{
   msgbox % val
   ExitApp
}
I become every time the error message:

"device_createtexture2d error -2147024809
ErrorLevel: 0"

I dont know where is the problem.

Can someone give me another tip to halve the main texture?

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: ScreenBuffer - DirectX screen capture

Post by malcev » 21 May 2022, 14:57

This part You need do it like this

Code: Select all

VarSetCapacity(textureDesc, 44, 0)
NumPut(width/2, textureDesc, 0, "uint")   ; Width
NumPut(height/2, textureDesc, 4, "uint")   ; Height
NumPut(1, textureDesc, 8, "uint")   ; MipLevels
NumPut(1, textureDesc, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, textureDesc, 16, "uint")   ; Format
NumPut(1, textureDesc, 20, "uint")   ; SampleDescCount
NumPut(0, textureDesc, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, textureDesc, 28, "uint")   ; Usage
NumPut(0, textureDesc, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, textureDesc, 36, "uint")   ; CPUAccessFlags
NumPut(0, textureDesc, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &textureDesc, 0, staging_tex)

VarSetCapacity(smallerTextureDesc, 44, 0)
NumPut(width, smallerTextureDesc, 0, "uint")   ; Width
NumPut(height, smallerTextureDesc, 4, "uint")   ; Height
NumPut(4, smallerTextureDesc, 8, "uint")   ; MipLevels
NumPut(1, smallerTextureDesc, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, smallerTextureDesc, 16, "uint")   ; Format
NumPut(1, smallerTextureDesc, 20, "uint")   ; SampleDescCount
NumPut(0, smallerTextureDesc, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_DEFAULT := 0, smallerTextureDesc, 28, "uint")   ; Usage
NumPut((D3D11_BIND_RENDER_TARGET := 0x20)|(D3D11_BIND_SHADER_RESOURCE := 0x8), smallerTextureDesc, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_NONE := 0, smallerTextureDesc, 36, "uint")   ; CPUAccessFlags
NumPut(D3D11_RESOURCE_MISC_GENERATE_MIPS := 0x1, smallerTextureDesc, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &smallerTextureDesc, 0, smallerTexture)

hr := DllCall(NumGet(NumGet(d3d_device+0)+7*A_PtrSize), "ptr", d3d_device, "ptr", smallerTexture, "ptr", 0, "ptr*", smallerTextureView)   ; ID3D11Device::CreateShaderResourceView
if hr or ErrorLevel
   _Error("CreateShaderResourceView error: " hr "`nErrorLevel: " ErrorLevel)

msgbox % smallerTextureView
Here is header:
https://github.com/apitrace/dxsdk/blob/master/Include/d3d11.h

Turisas
Posts: 6
Joined: 04 Jul 2020, 15:21

Re: ScreenBuffer - DirectX screen capture

Post by Turisas » 23 May 2022, 18:14

Hey, thanks for all your help but I'm facing another problem and I hope you want to help me one last time.

I don't understand how to create the "ID3D11DeviceContext::GenerateMips" function.

Without this I get the screenshot saved but only half of the actual screen.

Code: Select all

setbatchlines -1
; Load GDI+
DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0) ; sizeof(GdiplusStartupInput) = 16, 24
NumPut(0x1, si, "uint")
DllCall("gdiplus\GdiplusStartup", "ptr*", pToken:=0, "ptr", &si, "ptr", 0)
extension := "png"
DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", count:=0, "uint*", size:=0)
VarSetCapacity(ci, size)
DllCall("gdiplus\GdipGetImageEncoders", "uint", count, "uint", size, "ptr", &ci)
if !(count && size)
   throw Exception("Could not get a list of image codec encoders on this system.")
Loop % count
   EncoderExtensions := StrGet(NumGet(ci, (idx:=(48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize, "uptr"), "UTF-16")
      until InStr(EncoderExtensions, "*." extension)
if !(pCodec := &ci + idx)
   throw Exception("Could not find a matching encoder for the specified file format.")

IDXGIFactory := CreateDXGIFactory()
if !IDXGIFactory
{
   MsgBox, 16, Error, Create IDXGIFactory failed.
   ExitApp
}
loop
{
   IDXGIFactory_EnumAdapters(IDXGIFactory, A_Index-1, IDXGIAdapter)
   loop
   {
      hr := IDXGIAdapter_EnumOutputs(IDXGIAdapter, A_Index-1, IDXGIOutput)
      if (hr = "DXGI_ERROR_NOT_FOUND")
         break
      VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
      IDXGIOutput_GetDesc(IDXGIOutput, &DXGI_OUTPUT_DESC)
      Width := NumGet(DXGI_OUTPUT_DESC, 72, "int")
      Height := NumGet(DXGI_OUTPUT_DESC, 76, "int")
      AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, "int")
      if (AttachedToDesktop = 1)
         break 2         
   }
}
if (AttachedToDesktop != 1)
{
   MsgBox, 16, Error, No adapter attached to desktop
   ExitApp
}
D3D11CreateDevice(IDXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN := 0, 0, 0, 0, 0, D3D11_SDK_VERSION := 7, d3d_device, 0, d3d_context)
IDXGIOutput1 := IDXGIOutput1_Query(IDXGIOutput)
IDXGIOutput1_DuplicateOutput(IDXGIOutput1, d3d_device, Duplication)
VarSetCapacity(DXGI_OUTDUPL_DESC, 36, 0)
IDXGIOutputDuplication_GetDesc(Duplication, &DXGI_OUTDUPL_DESC)
DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, "uint")
sleep 50   ; As I understand - need some sleep for successful connecting to IDXGIOutputDuplication interface

VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
NumPut(width/2, D3D11_TEXTURE2D_DESC, 0, "uint")   ; Width
NumPut(height/2, D3D11_TEXTURE2D_DESC, 4, "uint")   ; Height
NumPut(1, D3D11_TEXTURE2D_DESC, 8, "uint")   ; MipLevels
NumPut(1, D3D11_TEXTURE2D_DESC, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, "uint")   ; Format
NumPut(1, D3D11_TEXTURE2D_DESC, 20, "uint")   ; SampleDescCount
NumPut(0, D3D11_TEXTURE2D_DESC, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, "uint")   ; Usage
NumPut(0, D3D11_TEXTURE2D_DESC, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, "uint")   ; CPUAccessFlags
NumPut(0, D3D11_TEXTURE2D_DESC, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &D3D11_TEXTURE2D_DESC, 0, staging_tex)
;-----------------------------------------------------------------------------------------------------------------------------
VarSetCapacity(D3D11_SMALLER_TEXTURE2D_DESC, 44, 0)
NumPut(width, D3D11_SMALLER_TEXTURE2D_DESC, 0, "uint")   ; Width
NumPut(height, D3D11_SMALLER_TEXTURE2D_DESC, 4, "uint")   ; Height
NumPut(4, D3D11_SMALLER_TEXTURE2D_DESC, 8, "uint")   ; MipLevels
NumPut(1, D3D11_SMALLER_TEXTURE2D_DESC, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_SMALLER_TEXTURE2D_DESC, 16, "uint")   ; Format
NumPut(1, D3D11_SMALLER_TEXTURE2D_DESC, 20, "uint")   ; SampleDescCount
NumPut(0, D3D11_SMALLER_TEXTURE2D_DESC, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 0, D3D11_SMALLER_TEXTURE2D_DESC, 28, "uint")   ; Usage
NumPut((D3D11_BIND_RENDER_TARGET := 0x20)|(D3D11_BIND_SHADER_RESOURCE := 0x8), D3D11_SMALLER_TEXTURE2D_DESC, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_NONE := 0, D3D11_SMALLER_TEXTURE2D_DESC, 36, "uint")   ; CPUAccessFlags
NumPut(D3D11_RESOURCE_MISC_GENERATE_MIPS := 0x1, D3D11_SMALLER_TEXTURE2D_DESC, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &D3D11_SMALLER_TEXTURE2D_DESC, 0, smaller_tex)
ID3D11Device_CreateShaderResourceView(d3d_device, smaller_tex, 0, smallerTextureView)
;-----------------------------------------------------------------------------------------------------------------------------


loop 1
{
   tooltip % A_Index
   VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
   if (A_Index = 1)
   {
      loop
      {
         AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, -1, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
         LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, "int64")
         if (LastPresentTime > 0)
            break
         ObjRelease(desktop_resource)
         IDXGIOutputDuplication_ReleaseFrame(duplication)
      }
   }
   else
   {
      AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, 0, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
      LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, "int64")
   }
   if (AcquireNextFrame != "DXGI_ERROR_WAIT_TIMEOUT")
   {
      if (LastPresentTime > 0)
      {
         if (DesktopImageInSystemMemory = 1)
         {
            VarSetCapacity(DXGI_MAPPED_RECT, A_PtrSize*2, 0)
            IDXGIOutputDuplication_MapDesktopSurface(Duplication, &DXGI_MAPPED_RECT)
            pitch := NumGet(DXGI_MAPPED_RECT, 0, "int")
            pBits := NumGet(DXGI_MAPPED_RECT, A_PtrSize, "ptr")
         }
         else
         {
            tex := ID3D11Texture2D_Query(desktop_resource)
			ID3D11DeviceContext_CopySubresourceRegion(d3d_context, smaller_tex, 0, 0, 0, 0, tex, 0, 0)
			;ID3D11DeviceContext::GenerateMips
			ID3D11DeviceContext_CopySubresourceRegion(d3d_context, staging_tex, 0, 0, 0, 0, smaller_tex, 0, 0)
			VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
			ID3D11DeviceContext_Map(d3d_context, staging_tex, 0, D3D11_MAP_READ := 1, 0, &D3D11_MAPPED_SUBRESOURCE)
            pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
            pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
         }
      }
   }
   DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width/2, "int", height/2, "int", pitch, "int", 0xE200B, "ptr", pBits, "ptr*", pBitmap:=0)
   DllCall("gdiplus\GdipSaveImageToFile", "ptr", pBitmap, "wstr", A_Index ".png", "ptr", pCodec, "uint", 0)
   DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
   if (AcquireNextFrame != "DXGI_ERROR_WAIT_TIMEOUT")
   {
      if (LastPresentTime > 0)
      {
         if (DesktopImageInSystemMemory = 1)
            IDXGIOutputDuplication_UnMapDesktopSurface(Duplication)
         else
         {
            ID3D11DeviceContext_Unmap(d3d_context, staging_tex, 0)
            ObjRelease(tex)
         }
      }
      ObjRelease(desktop_resource)
      IDXGIOutputDuplication_ReleaseFrame(duplication)
   }
}
tooltip
Release(staging_tex)
Release(smaller_tex)
Release(tex)
Release(d3d_device)
Release(d3d_context)
Release(duplication)
Release(IDXGIAdapter)
Release(IDXGIOutput)
Release(IDXGIOutput1)
Release(IDXGIFactory)
;msgbox % DesktopImageInSystemMemory
ExitApp




CreateDXGIFactory()
{
   if !DllCall("GetModuleHandle","str","DXGI")
      DllCall("LoadLibrary","str","DXGI")
   if !DllCall("GetModuleHandle","str","D3D11")
      DllCall("LoadLibrary","str","D3D11")
   GUID(riid, "{7b7166ec-21c7-44ae-b21a-c9ae321ae369}")
   hr := DllCall("DXGI\CreateDXGIFactory1", "ptr", &riid, "ptr*", ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return ppFactory
}

IDXGIFactory_EnumAdapters(this, Adapter, ByRef ppAdapter)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Adapter, "ptr*", ppAdapter)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIAdapter_EnumOutputs(this, Output, ByRef ppOutput)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Output, "ptr*", ppOutput)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0002   ; DXGI_ERROR_NOT_FOUND
         return "DXGI_ERROR_NOT_FOUND"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IDXGIAdapter_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_GetDesc(this, pDesc)
{
   DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_AcquireNextFrame(this, TimeoutInMilliseconds, pFrameInfo, ByRef ppDesktopResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint", TimeoutInMilliseconds, "ptr", pFrameInfo, "ptr*", ppDesktopResource)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0027   ; DXGI_ERROR_WAIT_TIMEOUT
         return "DXGI_ERROR_WAIT_TIMEOUT"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ByRef ppDevice, ByRef pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall("D3D11\D3D11CreateDevice", "ptr", pAdapter, "int", DriverType, "ptr", Software, "uint", Flags, "ptr", pFeatureLevels, "uint", FeatureLevels, "uint", SDKVersion, "ptr*", ppDevice, "ptr*", pFeatureLevel, "ptr*", ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_CreateTexture2D(this, pDesc, pInitialData, ByRef ppTexture2D)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", pDesc, "ptr", pInitialData, "ptr*", ppTexture2D)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_CreateShaderResourceView(this, pResource, pDesc, ByRef ppSRView)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pResource, "ptr", pDesc, "ptr*", ppSRView)
   if hr or ErrorLevel
	  _Error("CreateShaderResourceView error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_MapDesktopSurface(this, pLockedRect)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr", pLockedRect)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0004   ; DXGI_ERROR_UNSUPPORTED
         return "DXGI_ERROR_UNSUPPORTED"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IDXGIOutputDuplication_UnMapDesktopSurface(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_ReleaseFrame(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput1_DuplicateOutput(this, pDevice, ByRef ppOutputDuplication)
{
   hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), "ptr", this, "ptr", pDevice, "ptr*", ppOutputDuplication)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput1_Query(IDXGIOutput)
{ 
   hr := ComObjQuery(IDXGIOutput, "{00cddea8-939b-4b83-a340-a685226666cc}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

ID3D11Texture2D_Query(desktop_resource)
{ 
   hr := ComObjQuery(desktop_resource, "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), "ptr", this, "ptr", pDstResource, "ptr", pSrcResource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_CopySubresourceRegion(this, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox)
{
   hr := DllCall(NumGet(NumGet(this+0)+46*A_PtrSize), "ptr", this, "ptr", pDstResource, "uint", DstSubresource, "uint", DstX, "uint", DstY, "uint", DstZ, "ptr", pSrcResource, "uint", SrcSubresource, "ptr", pSrcBox)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource, "uint", MapType, "uint", MapFlags, "ptr", pMappedResource)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Unmap(this, pResource, Subresource)
{
   hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

Release(this)
{
   DllCall(NumGet(NumGet(this+0)+2*A_PtrSize), "ptr", this)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

_Error(val)
{
   msgbox % val
   ExitApp
}
Can you help me to create the "ID3D11DeviceContext::GenerateMips" function?
Or I'm doing something else wrong.

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: ScreenBuffer - DirectX screen capture

Post by malcev » 23 May 2022, 18:20

Code: Select all

DllCall(NumGet(NumGet(d3d_context+0)+54*A_PtrSize), "ptr", d3d_context, "ptr", smallerTextureView)   ; ID3D11DeviceContext::GenerateMips

Turisas
Posts: 6
Joined: 04 Jul 2020, 15:21

Re: ScreenBuffer - DirectX screen capture

Post by Turisas » 23 May 2022, 19:30

It works out! Thank you very much for your help!

Code: Select all

setbatchlines -1
; Load GDI+
DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0) ; sizeof(GdiplusStartupInput) = 16, 24
NumPut(0x1, si, "uint")
DllCall("gdiplus\GdiplusStartup", "ptr*", pToken:=0, "ptr", &si, "ptr", 0)
extension := "png"
DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", count:=0, "uint*", size:=0)
VarSetCapacity(ci, size)
DllCall("gdiplus\GdipGetImageEncoders", "uint", count, "uint", size, "ptr", &ci)
if !(count && size)
   throw Exception("Could not get a list of image codec encoders on this system.")
Loop % count
   EncoderExtensions := StrGet(NumGet(ci, (idx:=(48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize, "uptr"), "UTF-16")
      until InStr(EncoderExtensions, "*." extension)
if !(pCodec := &ci + idx)
   throw Exception("Could not find a matching encoder for the specified file format.")

IDXGIFactory := CreateDXGIFactory()
if !IDXGIFactory
{
   MsgBox, 16, Error, Create IDXGIFactory failed.
   ExitApp
}
loop
{
   IDXGIFactory_EnumAdapters(IDXGIFactory, A_Index-1, IDXGIAdapter)
   loop
   {
      hr := IDXGIAdapter_EnumOutputs(IDXGIAdapter, A_Index-1, IDXGIOutput)
      if (hr = "DXGI_ERROR_NOT_FOUND")
         break
      VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
      IDXGIOutput_GetDesc(IDXGIOutput, &DXGI_OUTPUT_DESC)
      Width := NumGet(DXGI_OUTPUT_DESC, 72, "int")
      Height := NumGet(DXGI_OUTPUT_DESC, 76, "int")
      AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, "int")
      if (AttachedToDesktop = 1)
         break 2         
   }
}
if (AttachedToDesktop != 1)
{
   MsgBox, 16, Error, No adapter attached to desktop
   ExitApp
}
D3D11CreateDevice(IDXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN := 0, 0, 0, 0, 0, D3D11_SDK_VERSION := 7, d3d_device, 0, d3d_context)
IDXGIOutput1 := IDXGIOutput1_Query(IDXGIOutput)
IDXGIOutput1_DuplicateOutput(IDXGIOutput1, d3d_device, Duplication)
VarSetCapacity(DXGI_OUTDUPL_DESC, 36, 0)
IDXGIOutputDuplication_GetDesc(Duplication, &DXGI_OUTDUPL_DESC)
DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, "uint")
sleep 50   ; As I understand - need some sleep for successful connecting to IDXGIOutputDuplication interface

VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
NumPut(width/2, D3D11_TEXTURE2D_DESC, 0, "uint")   ; Width
NumPut(height/2, D3D11_TEXTURE2D_DESC, 4, "uint")   ; Height
NumPut(1, D3D11_TEXTURE2D_DESC, 8, "uint")   ; MipLevels
NumPut(1, D3D11_TEXTURE2D_DESC, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, "uint")   ; Format
NumPut(1, D3D11_TEXTURE2D_DESC, 20, "uint")   ; SampleDescCount
NumPut(0, D3D11_TEXTURE2D_DESC, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, "uint")   ; Usage
NumPut(0, D3D11_TEXTURE2D_DESC, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, "uint")   ; CPUAccessFlags
NumPut(0, D3D11_TEXTURE2D_DESC, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &D3D11_TEXTURE2D_DESC, 0, staging_tex)
;-----------------------------------------------------------------------------------------------------------------------------
VarSetCapacity(D3D11_SMALLER_TEXTURE2D_DESC, 44, 0)
NumPut(width, D3D11_SMALLER_TEXTURE2D_DESC, 0, "uint")   ; Width
NumPut(height, D3D11_SMALLER_TEXTURE2D_DESC, 4, "uint")   ; Height
NumPut(4, D3D11_SMALLER_TEXTURE2D_DESC, 8, "uint")   ; MipLevels
NumPut(1, D3D11_SMALLER_TEXTURE2D_DESC, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_SMALLER_TEXTURE2D_DESC, 16, "uint")   ; Format
NumPut(1, D3D11_SMALLER_TEXTURE2D_DESC, 20, "uint")   ; SampleDescCount
NumPut(0, D3D11_SMALLER_TEXTURE2D_DESC, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 0, D3D11_SMALLER_TEXTURE2D_DESC, 28, "uint")   ; Usage
NumPut((D3D11_BIND_RENDER_TARGET := 0x20)|(D3D11_BIND_SHADER_RESOURCE := 0x8), D3D11_SMALLER_TEXTURE2D_DESC, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_NONE := 0, D3D11_SMALLER_TEXTURE2D_DESC, 36, "uint")   ; CPUAccessFlags
NumPut(D3D11_RESOURCE_MISC_GENERATE_MIPS := 0x1, D3D11_SMALLER_TEXTURE2D_DESC, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &D3D11_SMALLER_TEXTURE2D_DESC, 0, smaller_tex)
ID3D11Device_CreateShaderResourceView(d3d_device, smaller_tex, 0, smallerTextureView)
;-----------------------------------------------------------------------------------------------------------------------------


loop 10
{
   tooltip % A_Index
   VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
   if (A_Index = 1)
   {
      loop
      {
         AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, -1, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
         LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, "int64")
         if (LastPresentTime > 0)
            break
         ObjRelease(desktop_resource)
         IDXGIOutputDuplication_ReleaseFrame(duplication)
      }
   }
   else
   {
      AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, 0, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
      LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, "int64")
   }
   if (AcquireNextFrame != "DXGI_ERROR_WAIT_TIMEOUT")
   {
      if (LastPresentTime > 0)
      {
         if (DesktopImageInSystemMemory = 1)
         {
            VarSetCapacity(DXGI_MAPPED_RECT, A_PtrSize*2, 0)
            IDXGIOutputDuplication_MapDesktopSurface(Duplication, &DXGI_MAPPED_RECT)
            pitch := NumGet(DXGI_MAPPED_RECT, 0, "int")
            pBits := NumGet(DXGI_MAPPED_RECT, A_PtrSize, "ptr")
         }
         else
         {
            tex := ID3D11Texture2D_Query(desktop_resource)
			ID3D11DeviceContext_CopySubresourceRegion(d3d_context, smaller_tex, 0, 0, 0, 0, tex, 0, 0)
			ID3D11DeviceContext_GenerateMips(d3d_context, smallerTextureView)
			ID3D11DeviceContext_CopySubresourceRegion(d3d_context, staging_tex, 0, 1, 0, 0, smaller_tex, 1, 0)
			VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
			ID3D11DeviceContext_Map(d3d_context, staging_tex, 0, D3D11_MAP_READ := 1, 0, &D3D11_MAPPED_SUBRESOURCE)
            pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
            pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
         }
      }
   }
   DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width/2, "int", height/2, "int", pitch, "int", 0xE200B, "ptr", pBits, "ptr*", pBitmap:=0)
   DllCall("gdiplus\GdipSaveImageToFile", "ptr", pBitmap, "wstr", A_Index ".png", "ptr", pCodec, "uint", 0)
   DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
   if (AcquireNextFrame != "DXGI_ERROR_WAIT_TIMEOUT")
   {
      if (LastPresentTime > 0)
      {
         if (DesktopImageInSystemMemory = 1)
            IDXGIOutputDuplication_UnMapDesktopSurface(Duplication)
         else
         {
            ID3D11DeviceContext_Unmap(d3d_context, staging_tex, 0)
            ObjRelease(tex)
         }
      }
      ObjRelease(desktop_resource)
      IDXGIOutputDuplication_ReleaseFrame(duplication)
   }
}
tooltip
Release(staging_tex)
Release(smaller_tex)
Release(d3d_device)
Release(d3d_context)
Release(duplication)
Release(IDXGIAdapter)
Release(IDXGIOutput)
Release(IDXGIOutput1)
Release(IDXGIFactory)
ExitApp




CreateDXGIFactory()
{
   if !DllCall("GetModuleHandle","str","DXGI")
      DllCall("LoadLibrary","str","DXGI")
   if !DllCall("GetModuleHandle","str","D3D11")
      DllCall("LoadLibrary","str","D3D11")
   GUID(riid, "{7b7166ec-21c7-44ae-b21a-c9ae321ae369}")
   hr := DllCall("DXGI\CreateDXGIFactory1", "ptr", &riid, "ptr*", ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return ppFactory
}

IDXGIFactory_EnumAdapters(this, Adapter, ByRef ppAdapter)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Adapter, "ptr*", ppAdapter)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIAdapter_EnumOutputs(this, Output, ByRef ppOutput)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Output, "ptr*", ppOutput)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0002   ; DXGI_ERROR_NOT_FOUND
         return "DXGI_ERROR_NOT_FOUND"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IDXGIAdapter_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_GetDesc(this, pDesc)
{
   DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_AcquireNextFrame(this, TimeoutInMilliseconds, pFrameInfo, ByRef ppDesktopResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint", TimeoutInMilliseconds, "ptr", pFrameInfo, "ptr*", ppDesktopResource)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0027   ; DXGI_ERROR_WAIT_TIMEOUT
         return "DXGI_ERROR_WAIT_TIMEOUT"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ByRef ppDevice, ByRef pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall("D3D11\D3D11CreateDevice", "ptr", pAdapter, "int", DriverType, "ptr", Software, "uint", Flags, "ptr", pFeatureLevels, "uint", FeatureLevels, "uint", SDKVersion, "ptr*", ppDevice, "ptr*", pFeatureLevel, "ptr*", ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_CreateTexture2D(this, pDesc, pInitialData, ByRef ppTexture2D)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", pDesc, "ptr", pInitialData, "ptr*", ppTexture2D)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_CreateShaderResourceView(this, pResource, pDesc, ByRef ppSRView)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pResource, "ptr", pDesc, "ptr*", ppSRView)
   if hr or ErrorLevel
	  _Error("CreateShaderResourceView error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_MapDesktopSurface(this, pLockedRect)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr", pLockedRect)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0004   ; DXGI_ERROR_UNSUPPORTED
         return "DXGI_ERROR_UNSUPPORTED"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IDXGIOutputDuplication_UnMapDesktopSurface(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_ReleaseFrame(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput1_DuplicateOutput(this, pDevice, ByRef ppOutputDuplication)
{
   hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), "ptr", this, "ptr", pDevice, "ptr*", ppOutputDuplication)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput1_Query(IDXGIOutput)
{ 
   hr := ComObjQuery(IDXGIOutput, "{00cddea8-939b-4b83-a340-a685226666cc}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

ID3D11Texture2D_Query(desktop_resource)
{ 
   hr := ComObjQuery(desktop_resource, "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), "ptr", this, "ptr", pDstResource, "ptr", pSrcResource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_CopySubresourceRegion(this, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox)
{
   hr := DllCall(NumGet(NumGet(this+0)+46*A_PtrSize), "ptr", this, "ptr", pDstResource, "uint", DstSubresource, "uint", DstX, "uint", DstY, "uint", DstZ, "ptr", pSrcResource, "uint", SrcSubresource, "ptr", pSrcBox)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_GenerateMips(this, pShaderResourceView)
{
	hr := DllCall(NumGet(NumGet(this+0)+54*A_PtrSize), "ptr", this, "ptr", pShaderResourceView)
	if ErrorLevel
	   _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource, "uint", MapType, "uint", MapFlags, "ptr", pMappedResource)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Unmap(this, pResource, Subresource)
{
   hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

Release(this)
{
   DllCall(NumGet(NumGet(this+0)+2*A_PtrSize), "ptr", this)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

_Error(val)
{
   msgbox % val
   ExitApp
}

Post Reply

Return to “Scripts and Functions (v2)”