DXGI BY Freebasic

Windows specific questions.
Post Reply
xiaoyao
Posts: 121
Joined: May 05, 2020 2:01

DXGI BY Freebasic

Post by xiaoyao »

how to change this to freebasic?

DxgiGrab.h

Code: Select all

#pragma once

#ifdef _USRDLL
#define API_DECLSPEC  __declspec(dllexport)
#else
#define API_DECLSPEC  __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif
	API_DECLSPEC void	* dxgi_create(void);
	API_DECLSPEC void	  dxgi_destroy(void *);
	API_DECLSPEC int	  dxgi_get_size(void *);
	API_DECLSPEC int	  dxgi_get_width(void *);
	API_DECLSPEC int	  dxgi_get_height(void *);
	API_DECLSPEC bool	  dxgi_get_frame(void *, char *);
#ifdef __cplusplus
}
#endif
DxgiGrab.cpp

Code: Select all

/*
	作者:windpiaoxue
	联系方式:2977493715
*/

#include "DxgiGrab.h"
#include <d3d11.h>
#include <dxgi1_2.h>

#pragma comment(lib, "D3D11.lib")
#pragma comment(lib, "DXGI.lib")

#define RESET_OBJECT(obj)	{ if(obj) obj->Release(); obj = nullptr; }

struct DxgiInfo {
	DxgiInfo() {

	}

	~DxgiInfo() {
		RESET_OBJECT(m_pDevice);
		RESET_OBJECT(m_pContext);
		RESET_OBJECT(m_pDeskDupl);
	}

	ID3D11Device			* m_pDevice = nullptr;
	ID3D11DeviceContext		* m_pContext = nullptr;
	IDXGIOutputDuplication	* m_pDeskDupl = nullptr;
	int						  m_nWidth = 0;
	int						  m_nHeight = 0;
};

void * dxgi_create(void) {
	DxgiInfo * pDxgiInfo = new DxgiInfo;

	HRESULT hResult = -1;

	// Driver types supported
	D3D_DRIVER_TYPE DriverTypes[] =
	{
		D3D_DRIVER_TYPE_HARDWARE,
		D3D_DRIVER_TYPE_WARP,
		D3D_DRIVER_TYPE_REFERENCE,
	};
	UINT uNumDriverTypes = ARRAYSIZE(DriverTypes);

	// Feature levels supported
	D3D_FEATURE_LEVEL FeatureLevels[] =
	{
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0,
		D3D_FEATURE_LEVEL_9_1
	};
	UINT uNumFeatureLevels = ARRAYSIZE(FeatureLevels);

	D3D_FEATURE_LEVEL FeatureLevel;
	//
	// Create D3D device
	//
	for (UINT DriverTypeIndex = 0; DriverTypeIndex < uNumDriverTypes; ++DriverTypeIndex) {
		hResult = D3D11CreateDevice(
			nullptr,
			DriverTypes[DriverTypeIndex],
			nullptr,
			0,
			FeatureLevels,
			uNumFeatureLevels,
			D3D11_SDK_VERSION,
			&pDxgiInfo->m_pDevice,
			&FeatureLevel,
			&pDxgiInfo->m_pContext
		);
		if (SUCCEEDED(hResult)) {
			break;
		}
	}

	if (FAILED(hResult)) {
		delete pDxgiInfo;
		return nullptr;
	}


	//
	// Get DXGI device
	//
	IDXGIDevice * pDxgiDevice = nullptr;
	hResult = pDxgiInfo->m_pDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDxgiDevice));
	if (FAILED(hResult)) {
		delete pDxgiInfo;
		return nullptr;
	}

	//
	// Get DXGI adapter
	//
	IDXGIAdapter * pDxgiAdapter = nullptr;
	hResult = pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDxgiAdapter));
	RESET_OBJECT(pDxgiDevice);
	if (FAILED(hResult)) {
		delete pDxgiInfo;
		return nullptr;
	}

	//
	// Get output
	//
	INT nOutput = 0;
	IDXGIOutput * pDxgiOutput = nullptr;
	hResult = pDxgiAdapter->EnumOutputs(nOutput, &pDxgiOutput);
	RESET_OBJECT(pDxgiAdapter);
	if (FAILED(hResult)) {
		delete pDxgiInfo;
		return nullptr;
	}

	//
	// QI for Output 1
	//
	IDXGIOutput1 * pDxgiOutput1 = nullptr;
	hResult = pDxgiOutput->QueryInterface(__uuidof(pDxgiOutput1), reinterpret_cast<void**>(&pDxgiOutput1));
	RESET_OBJECT(pDxgiOutput);
	if (FAILED(hResult)) {
		delete pDxgiInfo;
		return nullptr;
	}

	//
	// Create desktop duplication
	//
	hResult = pDxgiOutput1->DuplicateOutput(pDxgiInfo->m_pDevice, &pDxgiInfo->m_pDeskDupl);
	RESET_OBJECT(pDxgiOutput1);

	if (FAILED(hResult)) {
		delete pDxgiInfo;
		return nullptr;
	}

	DXGI_OUTDUPL_DESC dxgiOutDesc;
	pDxgiInfo->m_pDeskDupl->GetDesc(&dxgiOutDesc);
	pDxgiInfo->m_nWidth = dxgiOutDesc.ModeDesc.Width;
	pDxgiInfo->m_nHeight = dxgiOutDesc.ModeDesc.Height;
	return pDxgiInfo;
}

void dxgi_destroy(void * pDxgi) {
	DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);

	delete pDxgiInfo;
}

int dxgi_get_size(void * pDxgi) {
	DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);
	return pDxgiInfo->m_nWidth * pDxgiInfo->m_nHeight * 4;
}

int dxgi_get_width(void * pDxgi) {
	DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);
	return pDxgiInfo->m_nWidth;
}

int dxgi_get_height(void * pDxgi) {
	DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);
	return pDxgiInfo->m_nHeight;
}

bool dxgi_get_frame(void * pDxgi, char * pOut) {
	DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);

	IDXGIResource * pDesktopResource = nullptr;
	DXGI_OUTDUPL_FRAME_INFO FrameInfo;

	pDxgiInfo->m_pDeskDupl->ReleaseFrame();
	HRESULT hResult = pDxgiInfo->m_pDeskDupl->AcquireNextFrame(0, &FrameInfo, &pDesktopResource);

	if (FAILED(hResult)) {
		return false;
	}

	//
	// query next frame staging buffer
	//
	ID3D11Texture2D * pAcquiredDesktopImage = nullptr;
	hResult = pDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&pAcquiredDesktopImage));
	RESET_OBJECT(pDesktopResource);

	if (FAILED(hResult)) {
		return false;
	}

	//
	// copy old description
	//
	D3D11_TEXTURE2D_DESC frameDescriptor;
	pAcquiredDesktopImage->GetDesc(&frameDescriptor);

	//
	// create a new staging buffer for fill frame image
	//
	ID3D11Texture2D *hNewDesktopImage = nullptr;
	frameDescriptor.Usage = D3D11_USAGE_STAGING;
	frameDescriptor.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
	frameDescriptor.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	frameDescriptor.BindFlags = 0;
	frameDescriptor.MiscFlags = 0;
	frameDescriptor.MipLevels = 1;
	frameDescriptor.ArraySize = 1;
	frameDescriptor.SampleDesc.Count = 1;
	hResult = pDxgiInfo->m_pDevice->CreateTexture2D(&frameDescriptor, nullptr, &hNewDesktopImage);

	if (FAILED(hResult)) {
		return false;
	}

	//
	// copy next staging buffer to new staging buffer
	//
	pDxgiInfo->m_pContext->CopyResource(hNewDesktopImage, pAcquiredDesktopImage);

	D3D11_MAPPED_SUBRESOURCE dsec = { 0 };
	hResult = pDxgiInfo->m_pContext->Map(hNewDesktopImage, 0, D3D11_MAP_READ, 0, &dsec);
	if (SUCCEEDED(hResult)) {
		if (dsec.pData != nullptr) {
			for (int y = 0; y < pDxgiInfo->m_nHeight; ++y) {
				memcpy(pOut + y * pDxgiInfo->m_nWidth * 4, (char*)dsec.pData + y * dsec.RowPitch, pDxgiInfo->m_nWidth * 4);
			}
		}
		pDxgiInfo->m_pContext->Unmap(hNewDesktopImage, 0);
	}

	RESET_OBJECT(hNewDesktopImage);
	RESET_OBJECT(pAcquiredDesktopImage);

	return dsec.pData != nullptr;
}
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: DXGI BY Freebasic

Post by D.J.Peters »

FreeBASIC comes with D3D9 include files but not D3D11 !

You should ask in the Windows forum section not here
Or a forum mod can move this post in the right section.

Joshy
Imortis
Moderator
Posts: 1923
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: DXGI BY Freebasic

Post by Imortis »

Moved.
adeyblue
Posts: 299
Joined: Nov 07, 2019 20:08

Re: DXGI BY Freebasic

Post by adeyblue »

I would say: while not this method, there's probably hundreds of versions of GDI screenshot code on this forum, but it doesn't look like anyone's ever done it. Until now

Code: Select all

#include once "windows.bi"
#include once "win/windowsx.bi"

Function GetScreenshot(ByRef bitmapInfo As BITMAPINFOHEADER) As Any Ptr

    dim hdc As HDC = GetDC(0)
    dim sWidth As Long = GetDeviceCaps(hdc, HORZRES)
    dim sHeight As Long = GetDeviceCaps(hdc, VERTRES)
    dim hdcCompat As HDC = CreateCompatibleDC(hdc)
    dim areaBytes As Long = (sWidth  * 4) * sHeight
    dim bmInfo As BITMAPINFO
    bmInfo.bmiHeader.biSize = SizeOf(bmInfo.bmiHeader)
    bmInfo.bmiHeader.biWidth = sWidth
    bmInfo.bmiHeader.biPlanes = 1
    bmInfo.bmiHeader.biHeight = sHeight
    bmInfo.bmiHeader.biBitCount = 32
    bmInfo.bmiHeader.biSizeImage = areaBytes
    bmInfo.bmiHeader.biCompression = BI_RGB
    dim hbm As HBITMAP = CreateDIBitmap(hdc, @bmInfo.bmiHeader, 0, 0, 0, DIB_RGB_COLORS)
    dim hBmOld As HBITMAP = SelectBitmap(hdcCompat, hbm)
    BitBlt(hdcCompat, 0, 0, sWidth, sHeight, hdc, 0, 0, SRCCOPY)
    ReleaseDC(0, hdc)
    SelectBitmap(hdcCompat, hbmOld)
    dim pBmBits As Any Ptr = CAllocate(areaBytes)
    GetBitmapBits(hbm, areaBytes, pBmBits)
    DeleteBitmap(hbm)
    DeleteDC(hdcCompat)
    bitmapInfo = bmInfo.bmiHeader
    Return pBmBits

End Function

Sub DrawToScreen(ByVal pBits As Any Ptr, ByRef bmInfoHeader As BITMAPINFOHEADER)

    dim hdc As HDC = GetDC(0)
    dim sWidth As Long = bmInfoHeader.biWidth
    dim sHeight As Long = Abs(bmInfoHeader.biHeight)
    dim hdcCompat As HDC = CreateCompatibleDC(hdc)
    dim bmInfo As BITMAPINFO
    bmInfo.bmiHeader = bmInfoHeader
    bmInfo.bmiHeader.biHeight = -bmInfo.bmiHeader.biHeight '' so it draws the right way around instead of upside down
    dim hbm As HBITMAP = CreateDIBitmap(hdc, @bmInfoHeader, CBM_INIT, pBits, @bmInfo, DIB_RGB_COLORS)
    dim hbmOld As HBITMAP = SelectBitmap(hdcCompat, hbm)
    BitBlt(hdc, 100, 100, sWidth, sHeight, hdcCompat, 0, 0, SRCCOPY)
    SelectBitmap(hdcCompat, hbmOld)
    DeleteDC(hdcCompat)
    DeleteBitmap(hbm)
    ReleaseDC(0, hdc)

End Sub

dim bmInfo As BITMAPINFOHEADER
dim pBits As Any Ptr = GetScreenshot(bmInfo)
'' do whatever with the raw pixels
'' copy them back to the screen as an example
DrawToScreen(pBits, bmInfo)
DeAllocate(pBits)
If you run this code as-is, you'll need to cause a redraw of the screen to get rid of all of the copied image
Post Reply