Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
8e392251
Commit
8e392251
authored
May 22, 2015
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4016 from vladimir-dudnik:directx-opencl-sample
parents
ef8182e1
c64a1529
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1433 additions
and
910 deletions
+1433
-910
d3d10_interop.cpp
samples/directx/d3d10_interop.cpp
+280
-107
d3d11_interop.cpp
samples/directx/d3d11_interop.cpp
+286
-112
d3d9_interop.cpp
samples/directx/d3d9_interop.cpp
+273
-113
d3d9ex_interop.cpp
samples/directx/d3d9ex_interop.cpp
+272
-120
d3d_base.inl.hpp
samples/directx/d3d_base.inl.hpp
+0
-458
d3dsample.hpp
samples/directx/d3dsample.hpp
+190
-0
winapp.hpp
samples/directx/winapp.hpp
+132
-0
No files found.
samples/directx/d3d10_interop.cpp
View file @
8e392251
/*
// Sample demonstrating interoperability of OpenCV UMat with Direct X surface
// At first, the data obtained from video file or camera and
// placed onto Direct X surface,
// following mapping of this Direct X surface to OpenCV UMat and call cv::Blur
// function. The result is mapped back to Direct X surface and rendered through
// Direct X API.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d10.h>
#pragma comment (lib, "d3d10.lib")
#define USE_D3D10
#define WINDOW_NAME "OpenCV Direct3D 10 Sample"
#include "opencv2/core.hpp"
#include "opencv2/core/directx.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "d3dsample.hpp"
#pragma comment (lib, "d3d10.lib")
IDXGISwapChain
*
swapchain
=
NULL
;
ID3D10Device
*
dev
=
NULL
;
ID3D10Texture2D
*
pBackBufferTexture
=
NULL
;
ID3D10Texture2D
*
pCPUWriteTexture
=
NULL
;
ID3D10Texture2D
*
pInputTexture
=
NULL
;
ID3D10RenderTargetView
*
backbuffer
=
NULL
;
#include "d3d_base.inl.hpp"
using
namespace
std
;
using
namespace
cv
;
bool
initDirect3D
()
class
D3D10WinApp
:
public
D3DSample
{
DXGI_SWAP_CHAIN_DESC
scd
;
ZeroMemory
(
&
scd
,
sizeof
(
DXGI_SWAP_CHAIN_DESC
));
scd
.
BufferCount
=
1
;
// one back buffer
scd
.
BufferDesc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
// use 32-bit color
scd
.
BufferDesc
.
Width
=
WIDTH
;
// set the back buffer width
scd
.
BufferDesc
.
Height
=
HEIGHT
;
// set the back buffer height
scd
.
BufferUsage
=
DXGI_USAGE_RENDER_TARGET_OUTPUT
;
// how swap chain is to be used
scd
.
OutputWindow
=
hWnd
;
// the window to be used
scd
.
SampleDesc
.
Count
=
1
;
// how many multisamples
scd
.
Windowed
=
TRUE
;
// windowed/full-screen mode
scd
.
SwapEffect
=
DXGI_SWAP_EFFECT_DISCARD
;
scd
.
Flags
=
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
// allow full-screen switching
if
(
FAILED
(
D3D10CreateDeviceAndSwapChain
(
NULL
,
D3D10_DRIVER_TYPE_HARDWARE
,
NULL
,
0
,
D3D10_SDK_VERSION
,
&
scd
,
&
swapchain
,
&
dev
)))
{
return
false
;
}
public
:
D3D10WinApp
(
int
width
,
int
height
,
std
::
string
&
window_name
,
cv
::
VideoCapture
&
cap
)
:
D3DSample
(
width
,
height
,
window_name
,
cap
)
{}
if
(
FAILED
(
swapchain
->
GetBuffer
(
0
,
__uuidof
(
ID3D10Texture2D
),
(
LPVOID
*
)
&
pBackBufferTexture
)))
{
return
false
;
}
~
D3D10WinApp
()
{}
if
(
FAILED
(
dev
->
CreateRenderTargetView
(
pBackBufferTexture
,
NULL
,
&
backbuffer
)))
int
create
(
void
)
{
return
false
;
}
// base initialization
D3DSample
::
create
();
dev
->
OMSetRenderTargets
(
1
,
&
backbuffer
,
NULL
);
// initialize DirectX
HRESULT
r
;
D3D10_VIEWPORT
viewport
;
ZeroMemory
(
&
viewport
,
sizeof
(
D3D10_VIEWPORT
));
viewport
.
Width
=
WIDTH
;
viewport
.
Height
=
HEIGHT
;
viewport
.
MinDepth
=
0.0
f
;
viewport
.
MaxDepth
=
0.0
f
;
dev
->
RSSetViewports
(
1
,
&
viewport
);
DXGI_SWAP_CHAIN_DESC
scd
;
return
true
;
}
ZeroMemory
(
&
scd
,
sizeof
(
DXGI_SWAP_CHAIN_DESC
));
bool
initDirect3DTextures
()
{
{
// Create texture for demo 0
D3D10_TEXTURE2D_DESC
desc
=
{
0
};
desc
.
Width
=
WIDTH
;
desc
.
Height
=
HEIGHT
;
desc
.
MipLevels
=
desc
.
ArraySize
=
1
;
desc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
desc
.
SampleDesc
.
Count
=
1
;
desc
.
BindFlags
=
D3D10_BIND_SHADER_RESOURCE
;
desc
.
Usage
=
D3D10_USAGE_DYNAMIC
;
desc
.
CPUAccessFlags
=
D3D10_CPU_ACCESS_WRITE
;
if
(
FAILED
(
dev
->
CreateTexture2D
(
&
desc
,
NULL
,
&
pCPUWriteTexture
)))
scd
.
BufferCount
=
1
;
// one back buffer
scd
.
BufferDesc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
// use 32-bit color
scd
.
BufferDesc
.
Width
=
m_width
;
// set the back buffer width
scd
.
BufferDesc
.
Height
=
m_height
;
// set the back buffer height
scd
.
BufferUsage
=
DXGI_USAGE_RENDER_TARGET_OUTPUT
;
// how swap chain is to be used
scd
.
OutputWindow
=
m_hWnd
;
// the window to be used
scd
.
SampleDesc
.
Count
=
1
;
// how many multisamples
scd
.
Windowed
=
TRUE
;
// windowed/full-screen mode
scd
.
SwapEffect
=
DXGI_SWAP_EFFECT_DISCARD
;
scd
.
Flags
=
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
// allow full-screen switching
r
=
::
D3D10CreateDeviceAndSwapChain
(
NULL
,
D3D10_DRIVER_TYPE_HARDWARE
,
NULL
,
0
,
D3D10_SDK_VERSION
,
&
scd
,
&
m_pD3D10SwapChain
,
&
m_pD3D10Dev
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
r
=
m_pD3D10SwapChain
->
GetBuffer
(
0
,
__uuidof
(
ID3D10Texture2D
),
(
LPVOID
*
)
&
m_pBackBuffer
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
r
=
m_pD3D10Dev
->
CreateRenderTargetView
(
m_pBackBuffer
,
NULL
,
&
m_pRenderTarget
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't create texture for CPU write sample"
<<
std
::
endl
;
return
false
;
return
-
1
;
}
}
{
// Create Read-only texture
cv
::
Mat
inputMat
=
getInputTexture
();
m_pD3D10Dev
->
OMSetRenderTargets
(
1
,
&
m_pRenderTarget
,
NULL
);
D3D10_VIEWPORT
viewport
;
ZeroMemory
(
&
viewport
,
sizeof
(
D3D10_VIEWPORT
));
viewport
.
Width
=
m_width
;
viewport
.
Height
=
m_height
;
viewport
.
MinDepth
=
0.0
f
;
viewport
.
MaxDepth
=
0.0
f
;
m_pD3D10Dev
->
RSSetViewports
(
1
,
&
viewport
);
D3D10_TEXTURE2D_DESC
desc
=
{
0
};
desc
.
Width
=
inputMat
.
size
().
width
;
desc
.
Height
=
inputMat
.
size
().
height
;
desc
.
MipLevels
=
desc
.
ArraySize
=
1
;
desc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
desc
.
SampleDesc
.
Count
=
1
;
desc
.
BindFlags
=
D3D10_BIND_SHADER_RESOURCE
;
desc
.
Usage
=
D3D10_USAGE_IMMUTABLE
;
desc
.
CPUAccessFlags
=
cv
::
ocl
::
useOpenCL
()
?
0
:
D3D10_CPU_ACCESS_READ
;
D3D10_SUBRESOURCE_DATA
srInitData
;
srInitData
.
pSysMem
=
inputMat
.
ptr
();
srInitData
.
SysMemPitch
=
(
UINT
)
inputMat
.
step
[
0
];
desc
.
Width
=
m_width
;
desc
.
Height
=
m_height
;
desc
.
MipLevels
=
1
;
desc
.
ArraySize
=
1
;
desc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
desc
.
SampleDesc
.
Count
=
1
;
desc
.
BindFlags
=
D3D10_BIND_SHADER_RESOURCE
;
desc
.
Usage
=
D3D10_USAGE_DYNAMIC
;
desc
.
CPUAccessFlags
=
D3D10_CPU_ACCESS_WRITE
;
if
(
FAILED
(
dev
->
CreateTexture2D
(
&
desc
,
&
srInitData
,
&
pInputTexture
)))
r
=
m_pD3D10Dev
->
CreateTexture2D
(
&
desc
,
NULL
,
&
m_pSurface
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't create texture with input image"
<<
std
::
endl
;
return
false
;
return
-
1
;
}
}
return
true
;
}
// initialize OpenCL context of OpenCV lib from DirectX
if
(
cv
::
ocl
::
haveOpenCL
())
{
m_oclCtx
=
cv
::
directx
::
ocl
::
initializeContextFromD3D10Device
(
m_pD3D10Dev
);
}
void
cleanUp
(
void
)
{
if
(
swapchain
)
swapchain
->
SetFullscreenState
(
FALSE
,
NULL
);
// switch to windowed mode
SAFE_RELEASE
(
swapchain
);
SAFE_RELEASE
(
pCPUWriteTexture
);
SAFE_RELEASE
(
pInputTexture
);
SAFE_RELEASE
(
pBackBufferTexture
);
SAFE_RELEASE
(
backbuffer
);
SAFE_RELEASE
(
dev
);
}
m_oclDevName
=
cv
::
ocl
::
useOpenCL
()
?
cv
::
ocl
::
Context
::
getDefault
().
device
(
0
).
name
()
:
"No OpenCL device"
;
return
0
;
}
// create()
// get media data on DX surface for further processing
int
get_surface
(
ID3D10Texture2D
**
ppSurface
)
{
HRESULT
r
;
if
(
!
m_cap
.
read
(
m_frame_bgr
))
return
-
1
;
cv
::
cvtColor
(
m_frame_bgr
,
m_frame_rgba
,
CV_RGB2BGRA
);
UINT
subResource
=
::
D3D10CalcSubresource
(
0
,
0
,
1
);
D3D10_MAPPED_TEXTURE2D
mappedTex
;
r
=
m_pSurface
->
Map
(
subResource
,
D3D10_MAP_WRITE_DISCARD
,
0
,
&
mappedTex
);
if
(
FAILED
(
r
))
{
return
r
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
mappedTex
.
pData
,
(
int
)
mappedTex
.
RowPitch
);
// copy video frame data to surface
m_frame_rgba
.
copyTo
(
m
);
m_pSurface
->
Unmap
(
subResource
);
*
ppSurface
=
m_pSurface
;
return
0
;
}
// get_surface()
void
render
(
void
)
{
// check to make sure you have a valid Direct3D device
CV_Assert
(
dev
);
renderToD3DObject
();
// process and render media data
int
render
()
{
try
{
if
(
m_shutdown
)
return
0
;
HRESULT
r
;
ID3D10Texture2D
*
pSurface
;
r
=
get_surface
(
&
pSurface
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
switch
(
m_mode
)
{
case
MODE_NOP
:
// no processing
break
;
case
MODE_CPU
:
{
// process video frame on CPU
UINT
subResource
=
::
D3D10CalcSubresource
(
0
,
0
,
1
);
D3D10_MAPPED_TEXTURE2D
mappedTex
;
r
=
m_pSurface
->
Map
(
subResource
,
D3D10_MAP_WRITE_DISCARD
,
0
,
&
mappedTex
);
if
(
FAILED
(
r
))
{
return
r
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
mappedTex
.
pData
,
(
int
)
mappedTex
.
RowPitch
);
if
(
!
m_disableProcessing
)
{
// blur D3D10 surface with OpenCV on CPU
cv
::
blur
(
m
,
m
,
cv
::
Size
(
15
,
15
),
cv
::
Point
(
-
7
,
-
7
));
}
m_pSurface
->
Unmap
(
subResource
);
break
;
}
case
MODE_GPU
:
{
// process video frame on GPU
cv
::
UMat
u
;
cv
::
directx
::
convertFromD3D10Texture2D
(
pSurface
,
u
);
if
(
!
m_disableProcessing
)
{
// blur D3D9 surface with OpenCV on GPU with OpenCL
cv
::
blur
(
u
,
u
,
cv
::
Size
(
15
,
15
),
cv
::
Point
(
-
7
,
-
7
));
}
cv
::
directx
::
convertToD3D10Texture2D
(
u
,
pSurface
);
break
;
}
}
// switch
print_info
(
pSurface
,
m_mode
,
getFps
(),
m_oclDevName
);
// traditional DX render pipeline:
// BitBlt surface to backBuffer and flip backBuffer to frontBuffer
m_pD3D10Dev
->
CopyResource
(
m_pBackBuffer
,
pSurface
);
// present the back buffer contents to the display
// switch the back buffer and the front buffer
r
=
m_pD3D10SwapChain
->
Present
(
0
,
0
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
}
// try
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Exception: "
<<
e
.
what
()
<<
std
::
endl
;
return
10
;
}
return
0
;
}
// render()
void
print_info
(
ID3D10Texture2D
*
pSurface
,
int
mode
,
float
fps
,
cv
::
String
oclDevName
)
{
HRESULT
r
;
UINT
subResource
=
::
D3D10CalcSubresource
(
0
,
0
,
1
);
D3D10_MAPPED_TEXTURE2D
mappedTex
;
r
=
pSurface
->
Map
(
subResource
,
D3D10_MAP_WRITE_DISCARD
,
0
,
&
mappedTex
);
if
(
FAILED
(
r
))
{
return
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
mappedTex
.
pData
,
(
int
)
mappedTex
.
RowPitch
);
// switch the back buffer and the front buffer
swapchain
->
Present
(
0
,
0
);
cv
::
String
strMode
=
cv
::
format
(
"%s"
,
m_modeStr
[
mode
].
c_str
());
cv
::
String
strFPS
=
cv
::
format
(
"%2.1f"
,
fps
);
cv
::
String
strDevName
=
cv
::
format
(
"%s"
,
oclDevName
.
c_str
());
cv
::
putText
(
m
,
strMode
,
cv
::
Point
(
0
,
16
),
1
,
0.8
,
cv
::
Scalar
(
0
,
0
,
0
));
cv
::
putText
(
m
,
strFPS
,
cv
::
Point
(
0
,
32
),
1
,
0.8
,
cv
::
Scalar
(
0
,
0
,
0
));
cv
::
putText
(
m
,
strDevName
,
cv
::
Point
(
0
,
48
),
1
,
0.8
,
cv
::
Scalar
(
0
,
0
,
0
));
m_pSurface
->
Unmap
(
subResource
);
return
;
}
// print_info()
int
cleanup
(
void
)
{
SAFE_RELEASE
(
m_pSurface
);
SAFE_RELEASE
(
m_pBackBuffer
);
SAFE_RELEASE
(
m_pD3D10SwapChain
);
SAFE_RELEASE
(
m_pRenderTarget
);
SAFE_RELEASE
(
m_pD3D10Dev
);
D3DSample
::
cleanup
();
return
0
;
}
// cleanup()
private
:
ID3D10Device
*
m_pD3D10Dev
;
IDXGISwapChain
*
m_pD3D10SwapChain
;
ID3D10Texture2D
*
m_pBackBuffer
;
ID3D10Texture2D
*
m_pSurface
;
ID3D10RenderTargetView
*
m_pRenderTarget
;
cv
::
ocl
::
Context
m_oclCtx
;
cv
::
String
m_oclPlatformName
;
cv
::
String
m_oclDevName
;
};
// main func
int
main
(
int
argc
,
char
**
argv
)
{
std
::
string
title
=
"D3D10 interop sample"
;
return
d3d_app
<
D3D10WinApp
>
(
argc
,
argv
,
title
);
}
samples/directx/d3d11_interop.cpp
View file @
8e392251
/*
// Sample demonstrating interoperability of OpenCV UMat with Direct X surface
// At first, the data obtained from video file or camera and
// placed onto Direct X surface,
// following mapping of this Direct X surface to OpenCV UMat and call cv::Blur
// function. The result is mapped back to Direct X surface and rendered through
// Direct X API.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d11.h>
#pragma comment (lib, "d3d11.lib")
#define USE_D3D11
#define WINDOW_NAME "OpenCV Direct3D 11 Sample"
#include "opencv2/core.hpp"
#include "opencv2/core/directx.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "d3dsample.hpp"
#pragma comment (lib, "d3d11.lib")
IDXGISwapChain
*
swapchain
=
NULL
;
ID3D11Device
*
dev
=
NULL
;
ID3D11DeviceContext
*
devcon
=
NULL
;
ID3D11Texture2D
*
pBackBufferTexture
=
NULL
;
ID3D11Texture2D
*
pCPUWriteTexture
=
NULL
;
ID3D11Texture2D
*
pInputTexture
=
NULL
;
ID3D11RenderTargetView
*
backbuffer
=
NULL
;
#include "d3d_base.inl.hpp"
using
namespace
std
;
using
namespace
cv
;
bool
initDirect3D
()
class
D3D11WinApp
:
public
D3DSample
{
DXGI_SWAP_CHAIN_DESC
scd
;
ZeroMemory
(
&
scd
,
sizeof
(
DXGI_SWAP_CHAIN_DESC
));
scd
.
BufferCount
=
1
;
// one back buffer
scd
.
BufferDesc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
// use 32-bit color
scd
.
BufferDesc
.
Width
=
WIDTH
;
// set the back buffer width
scd
.
BufferDesc
.
Height
=
HEIGHT
;
// set the back buffer height
scd
.
BufferUsage
=
DXGI_USAGE_RENDER_TARGET_OUTPUT
;
// how swap chain is to be used
scd
.
OutputWindow
=
hWnd
;
// the window to be used
scd
.
SampleDesc
.
Count
=
1
;
// how many multisamples
scd
.
Windowed
=
TRUE
;
// windowed/full-screen mode
scd
.
SwapEffect
=
DXGI_SWAP_EFFECT_DISCARD
;
scd
.
Flags
=
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
// allow full-screen switching
if
(
FAILED
(
D3D11CreateDeviceAndSwapChain
(
NULL
,
D3D_DRIVER_TYPE_HARDWARE
,
NULL
,
0
,
NULL
,
0
,
D3D11_SDK_VERSION
,
&
scd
,
&
swapchain
,
&
dev
,
NULL
,
&
devcon
)))
{
return
false
;
}
public
:
D3D11WinApp
(
int
width
,
int
height
,
std
::
string
&
window_name
,
cv
::
VideoCapture
&
cap
)
:
D3DSample
(
width
,
height
,
window_name
,
cap
)
{}
if
(
FAILED
(
swapchain
->
GetBuffer
(
0
,
__uuidof
(
ID3D11Texture2D
),
(
LPVOID
*
)
&
pBackBufferTexture
)))
{
return
false
;
}
~
D3D11WinApp
()
{}
if
(
FAILED
(
dev
->
CreateRenderTargetView
(
pBackBufferTexture
,
NULL
,
&
backbuffer
)))
int
create
(
void
)
{
return
false
;
}
// base initialization
D3DSample
::
create
();
devcon
->
OMSetRenderTargets
(
1
,
&
backbuffer
,
NULL
);
// initialize DirectX
HRESULT
r
;
D3D11_VIEWPORT
viewport
=
{
0
};
viewport
.
Width
=
WIDTH
;
viewport
.
Height
=
HEIGHT
;
viewport
.
MinDepth
=
0.0
f
;
viewport
.
MaxDepth
=
0.0
f
;
devcon
->
RSSetViewports
(
1
,
&
viewport
);
DXGI_SWAP_CHAIN_DESC
scd
;
return
true
;
}
ZeroMemory
(
&
scd
,
sizeof
(
DXGI_SWAP_CHAIN_DESC
));
bool
initDirect3DTextures
()
{
{
// Create texture for demo 0
D3D11_TEXTURE2D_DESC
desc
=
{
0
};
desc
.
Width
=
WIDTH
;
desc
.
Height
=
HEIGHT
;
desc
.
MipLevels
=
desc
.
ArraySize
=
1
;
desc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
desc
.
SampleDesc
.
Count
=
1
;
desc
.
BindFlags
=
D3D11_BIND_SHADER_RESOURCE
;
desc
.
Usage
=
D3D11_USAGE_DYNAMIC
;
desc
.
CPUAccessFlags
=
D3D11_CPU_ACCESS_WRITE
;
if
(
FAILED
(
dev
->
CreateTexture2D
(
&
desc
,
NULL
,
&
pCPUWriteTexture
)))
scd
.
BufferCount
=
1
;
// one back buffer
scd
.
BufferDesc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
// use 32-bit color
scd
.
BufferDesc
.
Width
=
m_width
;
// set the back buffer width
scd
.
BufferDesc
.
Height
=
m_height
;
// set the back buffer height
scd
.
BufferUsage
=
DXGI_USAGE_RENDER_TARGET_OUTPUT
;
// how swap chain is to be used
scd
.
OutputWindow
=
m_hWnd
;
// the window to be used
scd
.
SampleDesc
.
Count
=
1
;
// how many multisamples
scd
.
Windowed
=
TRUE
;
// windowed/full-screen mode
scd
.
SwapEffect
=
DXGI_SWAP_EFFECT_DISCARD
;
scd
.
Flags
=
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
// allow full-screen switching
r
=
::
D3D11CreateDeviceAndSwapChain
(
NULL
,
D3D_DRIVER_TYPE_HARDWARE
,
NULL
,
0
,
NULL
,
0
,
D3D11_SDK_VERSION
,
&
scd
,
&
m_pD3D11SwapChain
,
&
m_pD3D11Dev
,
NULL
,
&
m_pD3D11Ctx
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
r
=
m_pD3D11SwapChain
->
GetBuffer
(
0
,
__uuidof
(
ID3D11Texture2D
),
(
LPVOID
*
)
&
m_pBackBuffer
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
r
=
m_pD3D11Dev
->
CreateRenderTargetView
(
m_pBackBuffer
,
NULL
,
&
m_pRenderTarget
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't create texture for CPU write sample"
<<
std
::
endl
;
return
false
;
return
-
1
;
}
}
{
// Create Read-only texture
cv
::
Mat
inputMat
=
getInputTexture
();
m_pD3D11Ctx
->
OMSetRenderTargets
(
1
,
&
m_pRenderTarget
,
NULL
);
D3D11_VIEWPORT
viewport
;
ZeroMemory
(
&
viewport
,
sizeof
(
D3D11_VIEWPORT
));
viewport
.
Width
=
(
float
)
m_width
;
viewport
.
Height
=
(
float
)
m_height
;
viewport
.
MinDepth
=
0.0
f
;
viewport
.
MaxDepth
=
0.0
f
;
m_pD3D11Ctx
->
RSSetViewports
(
1
,
&
viewport
);
D3D11_TEXTURE2D_DESC
desc
=
{
0
};
desc
.
Width
=
inputMat
.
size
().
width
;
desc
.
Height
=
inputMat
.
size
().
height
;
desc
.
MipLevels
=
desc
.
ArraySize
=
1
;
desc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
desc
.
SampleDesc
.
Count
=
1
;
desc
.
BindFlags
=
D3D11_BIND_SHADER_RESOURCE
;
desc
.
Usage
=
D3D11_USAGE_IMMUTABLE
;
desc
.
CPUAccessFlags
=
cv
::
ocl
::
useOpenCL
()
?
0
:
D3D11_CPU_ACCESS_READ
;
D3D11_SUBRESOURCE_DATA
srInitData
;
srInitData
.
pSysMem
=
inputMat
.
ptr
();
srInitData
.
SysMemPitch
=
(
UINT
)
inputMat
.
step
[
0
];
desc
.
Width
=
m_width
;
desc
.
Height
=
m_height
;
desc
.
MipLevels
=
1
;
desc
.
ArraySize
=
1
;
desc
.
Format
=
DXGI_FORMAT_R8G8B8A8_UNORM
;
desc
.
SampleDesc
.
Count
=
1
;
desc
.
BindFlags
=
D3D11_BIND_SHADER_RESOURCE
;
desc
.
Usage
=
D3D11_USAGE_DYNAMIC
;
desc
.
CPUAccessFlags
=
D3D11_CPU_ACCESS_WRITE
;
if
(
FAILED
(
dev
->
CreateTexture2D
(
&
desc
,
&
srInitData
,
&
pInputTexture
)))
r
=
m_pD3D11Dev
->
CreateTexture2D
(
&
desc
,
NULL
,
&
m_pSurface
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't create texture with input image"
<<
std
::
endl
;
return
false
;
return
-
1
;
}
}
return
true
;
}
// initialize OpenCL context of OpenCV lib from DirectX
if
(
cv
::
ocl
::
haveOpenCL
())
{
m_oclCtx
=
cv
::
directx
::
ocl
::
initializeContextFromD3D11Device
(
m_pD3D11Dev
);
}
void
cleanUp
(
void
)
{
if
(
swapchain
)
swapchain
->
SetFullscreenState
(
FALSE
,
NULL
);
// switch to windowed mode
SAFE_RELEASE
(
swapchain
);
SAFE_RELEASE
(
pCPUWriteTexture
);
SAFE_RELEASE
(
pInputTexture
);
SAFE_RELEASE
(
pBackBufferTexture
);
SAFE_RELEASE
(
backbuffer
);
SAFE_RELEASE
(
dev
);
SAFE_RELEASE
(
devcon
);
}
m_oclDevName
=
cv
::
ocl
::
useOpenCL
()
?
cv
::
ocl
::
Context
::
getDefault
().
device
(
0
).
name
()
:
"No OpenCL device"
;
return
0
;
}
// create()
// get media data on DX surface for further processing
int
get_surface
(
ID3D11Texture2D
**
ppSurface
)
{
HRESULT
r
;
if
(
!
m_cap
.
read
(
m_frame_bgr
))
return
-
1
;
cv
::
cvtColor
(
m_frame_bgr
,
m_frame_rgba
,
CV_RGB2BGRA
);
UINT
subResource
=
::
D3D11CalcSubresource
(
0
,
0
,
1
);
D3D11_MAPPED_SUBRESOURCE
mappedTex
;
r
=
m_pD3D11Ctx
->
Map
(
m_pSurface
,
subResource
,
D3D11_MAP_WRITE_DISCARD
,
0
,
&
mappedTex
);
if
(
FAILED
(
r
))
{
return
r
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
mappedTex
.
pData
,
(
int
)
mappedTex
.
RowPitch
);
// copy video frame data to surface
m_frame_rgba
.
copyTo
(
m
);
m_pD3D11Ctx
->
Unmap
(
m_pSurface
,
subResource
);
*
ppSurface
=
m_pSurface
;
return
0
;
}
// get_surface()
void
render
(
void
)
{
// check to make sure you have a valid Direct3D device
CV_Assert
(
dev
);
renderToD3DObject
();
// process and render media data
int
render
()
{
try
{
if
(
m_shutdown
)
return
0
;
HRESULT
r
;
ID3D11Texture2D
*
pSurface
;
r
=
get_surface
(
&
pSurface
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
switch
(
m_mode
)
{
case
MODE_NOP
:
// no processing
break
;
case
MODE_CPU
:
{
// process video frame on CPU
UINT
subResource
=
::
D3D11CalcSubresource
(
0
,
0
,
1
);
D3D11_MAPPED_SUBRESOURCE
mappedTex
;
r
=
m_pD3D11Ctx
->
Map
(
m_pSurface
,
subResource
,
D3D11_MAP_WRITE_DISCARD
,
0
,
&
mappedTex
);
if
(
FAILED
(
r
))
{
return
r
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
mappedTex
.
pData
,
(
int
)
mappedTex
.
RowPitch
);
if
(
!
m_disableProcessing
)
{
// blur D3D10 surface with OpenCV on CPU
cv
::
blur
(
m
,
m
,
cv
::
Size
(
15
,
15
),
cv
::
Point
(
-
7
,
-
7
));
}
m_pD3D11Ctx
->
Unmap
(
m_pSurface
,
subResource
);
break
;
}
case
MODE_GPU
:
{
// process video frame on GPU
cv
::
UMat
u
;
cv
::
directx
::
convertFromD3D11Texture2D
(
pSurface
,
u
);
if
(
!
m_disableProcessing
)
{
// blur D3D9 surface with OpenCV on GPU with OpenCL
cv
::
blur
(
u
,
u
,
cv
::
Size
(
15
,
15
),
cv
::
Point
(
-
7
,
-
7
));
}
cv
::
directx
::
convertToD3D11Texture2D
(
u
,
pSurface
);
break
;
}
}
// switch
print_info
(
pSurface
,
m_mode
,
getFps
(),
m_oclDevName
);
// traditional DX render pipeline:
// BitBlt surface to backBuffer and flip backBuffer to frontBuffer
m_pD3D11Ctx
->
CopyResource
(
m_pBackBuffer
,
pSurface
);
// present the back buffer contents to the display
// switch the back buffer and the front buffer
r
=
m_pD3D11SwapChain
->
Present
(
0
,
0
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
}
// try
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Exception: "
<<
e
.
what
()
<<
std
::
endl
;
return
10
;
}
return
0
;
}
// render()
void
print_info
(
ID3D11Texture2D
*
pSurface
,
int
mode
,
float
fps
,
cv
::
String
oclDevName
)
{
HRESULT
r
;
UINT
subResource
=
::
D3D11CalcSubresource
(
0
,
0
,
1
);
D3D11_MAPPED_SUBRESOURCE
mappedTex
;
r
=
m_pD3D11Ctx
->
Map
(
pSurface
,
subResource
,
D3D11_MAP_WRITE_DISCARD
,
0
,
&
mappedTex
);
if
(
FAILED
(
r
))
{
return
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
mappedTex
.
pData
,
(
int
)
mappedTex
.
RowPitch
);
// switch the back buffer and the front buffer
swapchain
->
Present
(
0
,
0
);
cv
::
String
strMode
=
cv
::
format
(
"%s"
,
m_modeStr
[
mode
].
c_str
());
cv
::
String
strFPS
=
cv
::
format
(
"%2.1f"
,
fps
);
cv
::
String
strDevName
=
cv
::
format
(
"%s"
,
oclDevName
.
c_str
());
cv
::
putText
(
m
,
strMode
,
cv
::
Point
(
0
,
16
),
1
,
0.8
,
cv
::
Scalar
(
0
,
0
,
0
));
cv
::
putText
(
m
,
strFPS
,
cv
::
Point
(
0
,
32
),
1
,
0.8
,
cv
::
Scalar
(
0
,
0
,
0
));
cv
::
putText
(
m
,
strDevName
,
cv
::
Point
(
0
,
48
),
1
,
0.8
,
cv
::
Scalar
(
0
,
0
,
0
));
m_pD3D11Ctx
->
Unmap
(
pSurface
,
subResource
);
return
;
}
// printf_info()
int
cleanup
(
void
)
{
SAFE_RELEASE
(
m_pSurface
);
SAFE_RELEASE
(
m_pBackBuffer
);
SAFE_RELEASE
(
m_pD3D11SwapChain
);
SAFE_RELEASE
(
m_pRenderTarget
);
SAFE_RELEASE
(
m_pD3D11Dev
);
SAFE_RELEASE
(
m_pD3D11Ctx
);
D3DSample
::
cleanup
();
return
0
;
}
// cleanup()
private
:
ID3D11Device
*
m_pD3D11Dev
;
IDXGISwapChain
*
m_pD3D11SwapChain
;
ID3D11DeviceContext
*
m_pD3D11Ctx
;
ID3D11Texture2D
*
m_pBackBuffer
;
ID3D11Texture2D
*
m_pSurface
;
ID3D11RenderTargetView
*
m_pRenderTarget
;
cv
::
ocl
::
Context
m_oclCtx
;
cv
::
String
m_oclPlatformName
;
cv
::
String
m_oclDevName
;
};
// main func
int
main
(
int
argc
,
char
**
argv
)
{
std
::
string
title
=
"D3D11 interop sample"
;
return
d3d_app
<
D3D11WinApp
>
(
argc
,
argv
,
title
);
}
samples/directx/d3d9_interop.cpp
View file @
8e392251
/*
// Sample demonstrating interoperability of OpenCV UMat with Direct X surface
// At first, the data obtained from video file or camera and
// placed onto Direct X surface,
// following mapping of this Direct X surface to OpenCV UMat and call cv::Blur
// function. The result is mapped back to Direct X surface and rendered through
// Direct X API.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d9.h>
#pragma comment (lib, "d3d9.lib")
#define USE_D3D9
#define WINDOW_NAME "OpenCV Direct3D 9 Sample"
#include "opencv2/core.hpp"
#include "opencv2/core/directx.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "d3dsample.hpp"
IDirect3D9
*
pD3D
=
NULL
;
IDirect3DDevice9
*
dev
=
NULL
;
IDirect3DSurface9
*
pBackBuffer
=
NULL
;
IDirect3DSurface9
*
pCPUWriteSurface
=
NULL
;
// required name
IDirect3DSurface9
*
pReadOnlySurface
=
NULL
;
// required name
HANDLE
readOnlySurfaceShared
=
0
;
// required name
IDirect3DSurface9
*
pSurface
=
NULL
;
// required name
HANDLE
surfaceShared
=
0
;
// required name
#pragma comment (lib, "d3d9.lib")
#include "d3d_base.inl.hpp"
bool
initDirect3D
(
void
)
using
namespace
std
;
using
namespace
cv
;
class
D3D9WinApp
:
public
D3DSample
{
if
(
NULL
==
(
pD3D
=
Direct3DCreate9
(
D3D_SDK_VERSION
)))
{
return
false
;
}
D3DPRESENT_PARAMETERS
d3dpp
;
ZeroMemory
(
&
d3dpp
,
sizeof
(
D3DPRESENT_PARAMETERS
));
DWORD
flags
=
D3DCREATE_HARDWARE_VERTEXPROCESSING
|
D3DCREATE_PUREDEVICE
|
D3DCREATE_NOWINDOWCHANGES
|
D3DCREATE_MULTITHREADED
;
d3dpp
.
Windowed
=
true
;
d3dpp
.
Flags
=
0
;
d3dpp
.
BackBufferCount
=
0
;
d3dpp
.
BackBufferFormat
=
D3DFMT_A8R8G8B8
;
d3dpp
.
BackBufferHeight
=
HEIGHT
;
d3dpp
.
BackBufferWidth
=
WIDTH
;
d3dpp
.
MultiSampleType
=
D3DMULTISAMPLE_NONE
;
d3dpp
.
SwapEffect
=
D3DSWAPEFFECT_DISCARD
;
d3dpp
.
hDeviceWindow
=
hWnd
;
d3dpp
.
PresentationInterval
=
D3DPRESENT_INTERVAL_IMMEDIATE
;
d3dpp
.
FullScreen_RefreshRateInHz
=
D3DPRESENT_RATE_DEFAULT
;
if
(
FAILED
(
pD3D
->
CreateDevice
(
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
hWnd
,
flags
,
&
d3dpp
,
&
dev
)))
{
return
false
;
}
public
:
D3D9WinApp
(
int
width
,
int
height
,
std
::
string
&
window_name
,
cv
::
VideoCapture
&
cap
)
:
D3DSample
(
width
,
height
,
window_name
,
cap
)
{}
~
D3D9WinApp
()
{}
i
f
(
FAILED
(
dev
->
GetBackBuffer
(
0
,
0
,
D3DBACKBUFFER_TYPE_MONO
,
&
pBackBuffer
))
)
i
nt
create
(
void
)
{
return
false
;
}
// base initialization
D3DSample
::
create
();
return
true
;
}
// initialize DirectX
HRESULT
r
;
bool
initDirect3DTextures
()
{
// Note: sharing is not supported on some platforms
if
(
FAILED
(
dev
->
CreateOffscreenPlainSurface
(
WIDTH
,
HEIGHT
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
pSurface
,
NULL
/*&surfaceShared*/
)))
{
std
::
cerr
<<
"Can't create surface for result"
<<
std
::
endl
;
return
false
;
}
m_pD3D9
=
::
Direct3DCreate9
(
D3D_SDK_VERSION
);
if
(
NULL
==
m_pD3D9
)
{
return
-
1
;
}
// Note: sharing is not supported on some platforms
if
(
FAILED
(
dev
->
CreateOffscreenPlainSurface
(
WIDTH
,
HEIGHT
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
pReadOnlySurface
,
NULL
/*&readOnlySurfaceShared*/
)))
{
std
::
cerr
<<
"Can't create read only surface"
<<
std
::
endl
;
return
false
;
}
else
{
IDirect3DSurface9
*
pTmpSurface
;
if
(
FAILED
(
dev
->
CreateOffscreenPlainSurface
(
WIDTH
,
HEIGHT
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
pTmpSurface
,
NULL
)))
DWORD
flags
=
D3DCREATE_HARDWARE_VERTEXPROCESSING
|
D3DCREATE_PUREDEVICE
|
D3DCREATE_NOWINDOWCHANGES
|
D3DCREATE_MULTITHREADED
|
D3DCREATE_FPU_PRESERVE
;
D3DPRESENT_PARAMETERS
d3dpp
;
::
ZeroMemory
(
&
d3dpp
,
sizeof
(
D3DPRESENT_PARAMETERS
));
d3dpp
.
Windowed
=
true
;
d3dpp
.
Flags
=
0
;
d3dpp
.
BackBufferCount
=
0
;
d3dpp
.
BackBufferFormat
=
D3DFMT_A8R8G8B8
;
d3dpp
.
BackBufferHeight
=
m_height
;
d3dpp
.
BackBufferWidth
=
m_width
;
d3dpp
.
MultiSampleType
=
D3DMULTISAMPLE_NONE
;
d3dpp
.
SwapEffect
=
D3DSWAPEFFECT_DISCARD
;
d3dpp
.
hDeviceWindow
=
m_hWnd
;
d3dpp
.
PresentationInterval
=
D3DPRESENT_INTERVAL_IMMEDIATE
;
d3dpp
.
FullScreen_RefreshRateInHz
=
D3DPRESENT_RATE_DEFAULT
;
r
=
m_pD3D9
->
CreateDevice
(
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
m_hWnd
,
flags
,
&
d3dpp
,
&
m_pD3D9Dev
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't create temp surface for CPU write"
<<
std
::
endl
;
return
false
;
return
-
1
;
}
D3DLOCKED_RECT
memDesc
=
{
0
,
NULL
};
RECT
rc
=
{
0
,
0
,
WIDTH
,
HEIGHT
};
if
(
SUCCEEDED
(
pTmpSurface
->
LockRect
(
&
memDesc
,
&
rc
,
0
)))
r
=
m_pD3D9Dev
->
GetBackBuffer
(
0
,
0
,
D3DBACKBUFFER_TYPE_MONO
,
&
m_pBackBuffer
);
if
(
FAILED
(
r
))
{
cv
::
Mat
m
(
cv
::
Size
(
WIDTH
,
HEIGHT
),
CV_8UC4
,
memDesc
.
pBits
,
(
int
)
memDesc
.
Pitch
);
getInputTexture
().
copyTo
(
m
);
pTmpSurface
->
UnlockRect
();
dev
->
StretchRect
(
pTmpSurface
,
NULL
,
pReadOnlySurface
,
NULL
,
D3DTEXF_NONE
);
return
-
1
;
}
else
r
=
m_pD3D9Dev
->
CreateOffscreenPlainSurface
(
m_width
,
m_height
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
m_pSurface
,
NULL
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't LockRect() on surface"
<<
std
::
endl
;
std
::
cerr
<<
"Can't create surface for result"
<<
std
::
endl
;
return
-
1
;
}
pTmpSurface
->
Release
();
}
if
(
FAILED
(
dev
->
CreateOffscreenPlainSurface
(
WIDTH
,
HEIGHT
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
pCPUWriteSurface
,
NULL
)))
{
std
::
cerr
<<
"Can't create surface for CPU write"
<<
std
::
endl
;
return
false
;
}
// initialize OpenCL context of OpenCV lib from DirectX
if
(
cv
::
ocl
::
haveOpenCL
())
{
m_oclCtx
=
cv
::
directx
::
ocl
::
initializeContextFromDirect3DDevice9
(
m_pD3D9Dev
)
;
}
return
true
;
}
m_oclDevName
=
cv
::
ocl
::
useOpenCL
()
?
cv
::
ocl
::
Context
::
getDefault
().
device
(
0
).
name
()
:
"No OpenCL device"
;
void
render
(
void
)
{
// check to make sure you have a valid Direct3D device
CV_Assert
(
dev
);
return
0
;
}
// create()
renderToD3DObject
();
if
(
g_sampleType
==
0
)
// get media data on DX surface for further processing
int
get_surface
(
LPDIRECT3DSURFACE9
*
ppSurface
)
{
// nothing
}
else
if
(
g_sampleType
==
1
)
HRESULT
r
;
if
(
!
m_cap
.
read
(
m_frame_bgr
))
return
-
1
;
cv
::
cvtColor
(
m_frame_bgr
,
m_frame_rgba
,
CV_RGB2RGBA
);
D3DLOCKED_RECT
memDesc
=
{
0
,
NULL
};
RECT
rc
=
{
0
,
0
,
m_width
,
m_height
};
r
=
m_pSurface
->
LockRect
(
&
memDesc
,
&
rc
,
0
);
if
(
FAILED
(
r
))
{
return
r
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
memDesc
.
pBits
,
memDesc
.
Pitch
);
// copy video frame data to surface
m_frame_rgba
.
copyTo
(
m
);
r
=
m_pSurface
->
UnlockRect
();
if
(
FAILED
(
r
))
{
return
r
;
}
*
ppSurface
=
m_pSurface
;
return
0
;
}
// get_surface()
// process and render media data
int
render
()
{
if
(
FAILED
(
dev
->
StretchRect
(
pCPUWriteSurface
,
NULL
,
pBackBuffer
,
NULL
,
D3DTEXF_NONE
)))
try
{
std
::
cerr
<<
"Can't StretchRect()"
<<
std
::
endl
;
if
(
m_shutdown
)
return
0
;
HRESULT
r
;
LPDIRECT3DSURFACE9
pSurface
;
r
=
get_surface
(
&
pSurface
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
switch
(
m_mode
)
{
case
MODE_NOP
:
// no processing
break
;
case
MODE_CPU
:
{
// process video frame on CPU
D3DLOCKED_RECT
memDesc
=
{
0
,
NULL
};
RECT
rc
=
{
0
,
0
,
m_width
,
m_height
};
r
=
pSurface
->
LockRect
(
&
memDesc
,
&
rc
,
0
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
memDesc
.
pBits
,
memDesc
.
Pitch
);
if
(
!
m_disableProcessing
)
{
// blur D3D9 surface with OpenCV on CPU
cv
::
blur
(
m
,
m
,
cv
::
Size
(
15
,
15
),
cv
::
Point
(
-
7
,
-
7
));
}
r
=
pSurface
->
UnlockRect
();
if
(
FAILED
(
r
))
{
return
-
1
;
}
break
;
}
case
MODE_GPU
:
{
// process video frame on GPU
cv
::
UMat
u
;
cv
::
directx
::
convertFromDirect3DSurface9
(
pSurface
,
u
);
if
(
!
m_disableProcessing
)
{
// blur D3D9 surface with OpenCV on GPU with OpenCL
cv
::
blur
(
u
,
u
,
cv
::
Size
(
15
,
15
),
cv
::
Point
(
-
7
,
-
7
));
}
cv
::
directx
::
convertToDirect3DSurface9
(
u
,
pSurface
);
break
;
}
}
// switch
print_info
(
pSurface
,
m_mode
,
getFps
(),
m_oclDevName
);
// traditional DX render pipeline:
// BitBlt surface to backBuffer and flip backBuffer to frontBuffer
r
=
m_pD3D9Dev
->
StretchRect
(
pSurface
,
NULL
,
m_pBackBuffer
,
NULL
,
D3DTEXF_NONE
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
// present the back buffer contents to the display
r
=
m_pD3D9Dev
->
Present
(
NULL
,
NULL
,
NULL
,
NULL
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
}
// try
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Exception: "
<<
e
.
what
()
<<
std
::
endl
;
return
10
;
}
}
else
return
0
;
}
// render()
void
print_info
(
LPDIRECT3DSURFACE9
pSurface
,
int
mode
,
float
fps
,
cv
::
String
oclDevName
)
{
if
(
FAILED
(
dev
->
StretchRect
(
pSurface
,
NULL
,
pBackBuffer
,
NULL
,
D3DTEXF_NONE
)))
HDC
hDC
;
HRESULT
r
=
pSurface
->
GetDC
(
&
hDC
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't StretchRect()"
<<
std
::
endl
;
return
;
}
}
if
(
SUCCEEDED
(
dev
->
BeginScene
()))
HFONT
hFont
=
(
HFONT
)
::
GetStockObject
(
SYSTEM_FONT
);
HFONT
hOldFont
=
(
HFONT
)
::
SelectObject
(
hDC
,
hFont
);
if
(
hOldFont
)
{
TEXTMETRIC
tm
;
::
GetTextMetrics
(
hDC
,
&
tm
);
char
buf
[
256
];
int
y
=
0
;
buf
[
0
]
=
0
;
sprintf
(
buf
,
"Mode: %s"
,
m_modeStr
[
mode
].
c_str
());
::
TextOut
(
hDC
,
0
,
y
,
buf
,
(
int
)
strlen
(
buf
));
y
+=
tm
.
tmHeight
;
buf
[
0
]
=
0
;
sprintf
(
buf
,
"FPS: %2.1f"
,
fps
);
::
TextOut
(
hDC
,
0
,
y
,
buf
,
(
int
)
strlen
(
buf
));
y
+=
tm
.
tmHeight
;
buf
[
0
]
=
0
;
sprintf
(
buf
,
"OpenCL device: %s"
,
oclDevName
.
c_str
());
::
TextOut
(
hDC
,
0
,
y
,
buf
,
(
int
)
strlen
(
buf
));
::
SelectObject
(
hDC
,
hOldFont
);
}
r
=
pSurface
->
ReleaseDC
(
hDC
);
return
;
}
// print_info()
int
cleanup
(
void
)
{
// end the scene
dev
->
EndScene
();
}
SAFE_RELEASE
(
m_pSurface
);
SAFE_RELEASE
(
m_pBackBuffer
);
SAFE_RELEASE
(
m_pD3D9Dev
);
SAFE_RELEASE
(
m_pD3D9
);
D3DSample
::
cleanup
();
return
0
;
}
// cleanup()
// present the back buffer contents to the display
dev
->
Present
(
NULL
,
NULL
,
NULL
,
NULL
);
}
private
:
LPDIRECT3D9
m_pD3D9
;
LPDIRECT3DDEVICE9
m_pD3D9Dev
;
LPDIRECT3DSURFACE9
m_pBackBuffer
;
LPDIRECT3DSURFACE9
m_pSurface
;
cv
::
ocl
::
Context
m_oclCtx
;
cv
::
String
m_oclPlatformName
;
cv
::
String
m_oclDevName
;
};
void
cleanUp
(
void
)
// main func
int
main
(
int
argc
,
char
**
argv
)
{
SAFE_RELEASE
(
pCPUWriteSurface
);
SAFE_RELEASE
(
pReadOnlySurface
);
SAFE_RELEASE
(
pSurface
);
SAFE_RELEASE
(
pBackBuffer
);
SAFE_RELEASE
(
dev
);
SAFE_RELEASE
(
pD3D
);}
std
::
string
title
=
"D3D9 interop sample"
;
return
d3d_app
<
D3D9WinApp
>
(
argc
,
argv
,
title
);
}
samples/directx/d3d9ex_interop.cpp
View file @
8e392251
/*
// Sample demonstrating interoperability of OpenCV UMat with Direct X surface
// At first, the data obtained from video file or camera and
// placed onto Direct X surface,
// following mapping of this Direct X surface to OpenCV UMat and call cv::Blur
// function. The result is mapped back to Direct X surface and rendered through
// Direct X API.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d9.h>
#pragma comment (lib, "d3d9.lib")
#define USE_D3DEX
#define WINDOW_NAME "OpenCV Direct3D 9 Ex Sample"
#include "opencv2/core.hpp"
#include "opencv2/core/directx.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "d3dsample.hpp"
IDirect3D9Ex
*
pD3D
=
NULL
;
IDirect3DDevice9Ex
*
dev
=
NULL
;
IDirect3DSurface9
*
pBackBuffer
=
NULL
;
IDirect3DSurface9
*
pCPUWriteSurface
=
NULL
;
// required name
IDirect3DSurface9
*
pReadOnlySurface
=
NULL
;
// required name
HANDLE
readOnlySurfaceShared
=
0
;
// required name
IDirect3DSurface9
*
pSurface
=
NULL
;
// required name
HANDLE
surfaceShared
=
0
;
// required name
#pragma comment (lib, "d3d9.lib")
#include "d3d_base.inl.hpp"
bool
initDirect3D
(
void
)
using
namespace
std
;
using
namespace
cv
;
class
D3D9ExWinApp
:
public
D3DSample
{
if
(
FAILED
(
Direct3DCreate9Ex
(
D3D_SDK_VERSION
,
&
pD3D
)))
{
return
false
;
}
D3DDISPLAYMODEEX
ddm
;
ZeroMemory
(
&
ddm
,
sizeof
(
ddm
));
ddm
.
Size
=
sizeof
(
D3DDISPLAYMODEEX
);
D3DDISPLAYROTATION
rotation
;
if
(
FAILED
(
pD3D
->
GetAdapterDisplayModeEx
(
D3DADAPTER_DEFAULT
,
&
ddm
,
&
rotation
)))
{
return
false
;
}
D3DPRESENT_PARAMETERS
d3dpp
;
ZeroMemory
(
&
d3dpp
,
sizeof
(
D3DPRESENT_PARAMETERS
));
DWORD
flags
=
D3DCREATE_HARDWARE_VERTEXPROCESSING
|
D3DCREATE_PUREDEVICE
|
D3DCREATE_NOWINDOWCHANGES
|
D3DCREATE_MULTITHREADED
;
d3dpp
.
Windowed
=
true
;
d3dpp
.
Flags
=
0
;
d3dpp
.
BackBufferCount
=
0
;
d3dpp
.
BackBufferFormat
=
ddm
.
Format
;
d3dpp
.
BackBufferHeight
=
HEIGHT
;
d3dpp
.
BackBufferWidth
=
WIDTH
;
d3dpp
.
MultiSampleType
=
D3DMULTISAMPLE_NONE
;
d3dpp
.
SwapEffect
=
D3DSWAPEFFECT_DISCARD
;
d3dpp
.
hDeviceWindow
=
hWnd
;
d3dpp
.
PresentationInterval
=
D3DPRESENT_INTERVAL_IMMEDIATE
;
d3dpp
.
FullScreen_RefreshRateInHz
=
D3DPRESENT_RATE_DEFAULT
;
if
(
FAILED
(
pD3D
->
CreateDeviceEx
(
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
hWnd
,
flags
,
&
d3dpp
,
NULL
,
&
dev
)))
{
return
false
;
}
public
:
D3D9ExWinApp
(
int
width
,
int
height
,
std
::
string
&
window_name
,
cv
::
VideoCapture
&
cap
)
:
D3DSample
(
width
,
height
,
window_name
,
cap
)
{}
~
D3D9ExWinApp
()
{}
i
f
(
FAILED
(
dev
->
GetBackBuffer
(
0
,
0
,
D3DBACKBUFFER_TYPE_MONO
,
&
pBackBuffer
))
)
i
nt
create
(
void
)
{
return
false
;
}
// base initialization
D3DSample
::
create
();
return
true
;
}
// initialize DirectX
HRESULT
r
;
bool
initDirect3DTextures
()
{
if
(
FAILED
(
dev
->
CreateOffscreenPlainSurface
(
WIDTH
,
HEIGHT
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
pSurface
,
&
surfaceShared
)))
{
std
::
cerr
<<
"Can't create surface for result"
<<
std
::
endl
;
return
false
;
}
r
=
::
Direct3DCreate9Ex
(
D3D_SDK_VERSION
,
&
m_pD3D9Ex
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
if
(
FAILED
(
dev
->
CreateOffscreenPlainSurface
(
WIDTH
,
HEIGHT
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
pReadOnlySurface
,
&
readOnlySurfaceShared
)))
{
std
::
cerr
<<
"Can't create read only surface"
<<
std
::
endl
;
return
false
;
}
else
{
IDirect3DSurface9
*
pTmpSurface
;
if
(
FAILED
(
dev
->
CreateOffscreenPlainSurface
(
WIDTH
,
HEIGHT
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
pTmpSurface
,
NULL
)))
DWORD
flags
=
D3DCREATE_HARDWARE_VERTEXPROCESSING
|
D3DCREATE_PUREDEVICE
|
D3DCREATE_NOWINDOWCHANGES
|
D3DCREATE_MULTITHREADED
|
D3DCREATE_FPU_PRESERVE
;
D3DPRESENT_PARAMETERS
d3dpp
;
::
ZeroMemory
(
&
d3dpp
,
sizeof
(
D3DPRESENT_PARAMETERS
));
d3dpp
.
Windowed
=
true
;
d3dpp
.
Flags
=
0
;
d3dpp
.
BackBufferCount
=
0
;
d3dpp
.
BackBufferFormat
=
D3DFMT_A8R8G8B8
;
d3dpp
.
BackBufferHeight
=
m_height
;
d3dpp
.
BackBufferWidth
=
m_width
;
d3dpp
.
MultiSampleType
=
D3DMULTISAMPLE_NONE
;
d3dpp
.
SwapEffect
=
D3DSWAPEFFECT_DISCARD
;
d3dpp
.
hDeviceWindow
=
m_hWnd
;
d3dpp
.
PresentationInterval
=
D3DPRESENT_INTERVAL_IMMEDIATE
;
d3dpp
.
FullScreen_RefreshRateInHz
=
D3DPRESENT_RATE_DEFAULT
;
r
=
m_pD3D9Ex
->
CreateDeviceEx
(
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
m_hWnd
,
flags
,
&
d3dpp
,
NULL
,
&
m_pD3D9DevEx
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't create temp surface for CPU write"
<<
std
::
endl
;
return
false
;
return
-
1
;
}
D3DLOCKED_RECT
memDesc
=
{
0
,
NULL
};
RECT
rc
=
{
0
,
0
,
WIDTH
,
HEIGHT
};
if
(
SUCCEEDED
(
pTmpSurface
->
LockRect
(
&
memDesc
,
&
rc
,
0
)))
r
=
m_pD3D9DevEx
->
GetBackBuffer
(
0
,
0
,
D3DBACKBUFFER_TYPE_MONO
,
&
m_pBackBuffer
);
if
(
FAILED
(
r
))
{
cv
::
Mat
m
(
cv
::
Size
(
WIDTH
,
HEIGHT
),
CV_8UC4
,
memDesc
.
pBits
,
(
int
)
memDesc
.
Pitch
);
getInputTexture
().
copyTo
(
m
);
pTmpSurface
->
UnlockRect
();
dev
->
StretchRect
(
pTmpSurface
,
NULL
,
pReadOnlySurface
,
NULL
,
D3DTEXF_NONE
);
return
-
1
;
}
else
r
=
m_pD3D9DevEx
->
CreateOffscreenPlainSurface
(
m_width
,
m_height
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
m_pSurface
,
NULL
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't LockRect() on surface"
<<
std
::
endl
;
std
::
cerr
<<
"Can't create surface for result"
<<
std
::
endl
;
return
-
1
;
}
pTmpSurface
->
Release
();
}
if
(
FAILED
(
dev
->
CreateOffscreenPlainSurface
(
WIDTH
,
HEIGHT
,
D3DFMT_A8R8G8B8
,
D3DPOOL_DEFAULT
,
&
pCPUWriteSurface
,
NULL
)))
// initialize OpenCL context of OpenCV lib from DirectX
if
(
cv
::
ocl
::
haveOpenCL
())
{
m_oclCtx
=
cv
::
directx
::
ocl
::
initializeContextFromDirect3DDevice9
(
m_pD3D9DevEx
);
}
m_oclDevName
=
cv
::
ocl
::
useOpenCL
()
?
cv
::
ocl
::
Context
::
getDefault
().
device
(
0
).
name
()
:
"No OpenCL device"
;
return
0
;
}
// create()
// get media data on DX surface for further processing
int
get_surface
(
LPDIRECT3DSURFACE9
*
ppSurface
)
{
std
::
cerr
<<
"Can't create surface for CPU write"
<<
std
::
endl
;
return
false
;
}
HRESULT
r
;
return
true
;
}
if
(
!
m_cap
.
read
(
m_frame_bgr
))
return
-
1
;
cv
::
cvtColor
(
m_frame_bgr
,
m_frame_rgba
,
CV_RGB2RGBA
);
void
render
(
void
)
{
// check to make sure you have a valid Direct3D device
CV_Assert
(
dev
);
D3DLOCKED_RECT
memDesc
=
{
0
,
NULL
};
RECT
rc
=
{
0
,
0
,
m_width
,
m_height
};
renderToD3DObject
();
r
=
m_pSurface
->
LockRect
(
&
memDesc
,
&
rc
,
0
);
if
(
FAILED
(
r
))
{
return
r
;
}
if
(
g_sampleType
==
0
)
{
// nothing
}
else
if
(
g_sampleType
==
1
)
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
memDesc
.
pBits
,
memDesc
.
Pitch
);
// copy video frame data to surface
m_frame_rgba
.
copyTo
(
m
);
r
=
m_pSurface
->
UnlockRect
();
if
(
FAILED
(
r
))
{
return
r
;
}
*
ppSurface
=
m_pSurface
;
return
0
;
}
// get_surface()
// process and render media data
int
render
()
{
if
(
FAILED
(
dev
->
StretchRect
(
pCPUWriteSurface
,
NULL
,
pBackBuffer
,
NULL
,
D3DTEXF_NONE
)))
try
{
std
::
cerr
<<
"Can't StretchRect()"
<<
std
::
endl
;
if
(
m_shutdown
)
return
0
;
HRESULT
r
;
LPDIRECT3DSURFACE9
pSurface
;
r
=
get_surface
(
&
pSurface
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
switch
(
m_mode
)
{
case
MODE_NOP
:
// no processing
break
;
case
MODE_CPU
:
{
// process video frame on CPU
D3DLOCKED_RECT
memDesc
=
{
0
,
NULL
};
RECT
rc
=
{
0
,
0
,
m_width
,
m_height
};
r
=
pSurface
->
LockRect
(
&
memDesc
,
&
rc
,
0
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
cv
::
Mat
m
(
m_height
,
m_width
,
CV_8UC4
,
memDesc
.
pBits
,
memDesc
.
Pitch
);
if
(
!
m_disableProcessing
)
{
// blur D3D9 surface with OpenCV on CPU
cv
::
blur
(
m
,
m
,
cv
::
Size
(
15
,
15
),
cv
::
Point
(
-
7
,
-
7
));
}
r
=
pSurface
->
UnlockRect
();
if
(
FAILED
(
r
))
{
return
-
1
;
}
break
;
}
case
MODE_GPU
:
{
// process video frame on GPU
cv
::
UMat
u
;
cv
::
directx
::
convertFromDirect3DSurface9
(
pSurface
,
u
);
if
(
!
m_disableProcessing
)
{
// blur D3D9 surface with OpenCV on GPU with OpenCL
cv
::
blur
(
u
,
u
,
cv
::
Size
(
15
,
15
),
cv
::
Point
(
-
7
,
-
7
));
}
cv
::
directx
::
convertToDirect3DSurface9
(
u
,
pSurface
);
break
;
}
}
// switch
print_info
(
pSurface
,
m_mode
,
getFps
(),
m_oclDevName
);
// traditional DX render pipeline:
// BitBlt surface to backBuffer and flip backBuffer to frontBuffer
r
=
m_pD3D9DevEx
->
StretchRect
(
pSurface
,
NULL
,
m_pBackBuffer
,
NULL
,
D3DTEXF_NONE
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
// present the back buffer contents to the display
r
=
m_pD3D9DevEx
->
Present
(
NULL
,
NULL
,
NULL
,
NULL
);
if
(
FAILED
(
r
))
{
return
-
1
;
}
}
// try
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Exception: "
<<
e
.
what
()
<<
std
::
endl
;
return
10
;
}
}
else
return
0
;
}
// render()
void
print_info
(
LPDIRECT3DSURFACE9
pSurface
,
int
mode
,
float
fps
,
cv
::
String
oclDevName
)
{
if
(
FAILED
(
dev
->
StretchRect
(
pSurface
,
NULL
,
pBackBuffer
,
NULL
,
D3DTEXF_NONE
)))
HDC
hDC
;
HRESULT
r
=
pSurface
->
GetDC
(
&
hDC
);
if
(
FAILED
(
r
))
{
std
::
cerr
<<
"Can't StretchRect()"
<<
std
::
endl
;
return
;
}
}
if
(
SUCCEEDED
(
dev
->
BeginScene
()))
HFONT
hFont
=
(
HFONT
)
::
GetStockObject
(
SYSTEM_FONT
);
HFONT
hOldFont
=
(
HFONT
)
::
SelectObject
(
hDC
,
hFont
);
if
(
hOldFont
)
{
TEXTMETRIC
tm
;
::
GetTextMetrics
(
hDC
,
&
tm
);
char
buf
[
256
];
int
y
=
0
;
buf
[
0
]
=
0
;
sprintf
(
buf
,
"Mode: %s"
,
m_modeStr
[
mode
].
c_str
());
::
TextOut
(
hDC
,
0
,
y
,
buf
,
(
int
)
strlen
(
buf
));
y
+=
tm
.
tmHeight
;
buf
[
0
]
=
0
;
sprintf
(
buf
,
"FPS: %2.1f"
,
fps
);
::
TextOut
(
hDC
,
0
,
y
,
buf
,
(
int
)
strlen
(
buf
));
y
+=
tm
.
tmHeight
;
buf
[
0
]
=
0
;
sprintf
(
buf
,
"OpenCL device: %s"
,
oclDevName
.
c_str
());
::
TextOut
(
hDC
,
0
,
y
,
buf
,
(
int
)
strlen
(
buf
));
::
SelectObject
(
hDC
,
hOldFont
);
}
r
=
pSurface
->
ReleaseDC
(
hDC
);
return
;
}
// print_info()
int
cleanup
(
void
)
{
// end the scene
dev
->
EndScene
();
}
SAFE_RELEASE
(
m_pSurface
);
SAFE_RELEASE
(
m_pBackBuffer
);
SAFE_RELEASE
(
m_pD3D9DevEx
);
SAFE_RELEASE
(
m_pD3D9Ex
);
D3DSample
::
cleanup
();
return
0
;
}
// cleanup()
private
:
LPDIRECT3D9EX
m_pD3D9Ex
;
LPDIRECT3DDEVICE9EX
m_pD3D9DevEx
;
LPDIRECT3DSURFACE9
m_pBackBuffer
;
LPDIRECT3DSURFACE9
m_pSurface
;
cv
::
ocl
::
Context
m_oclCtx
;
cv
::
String
m_oclPlatformName
;
cv
::
String
m_oclDevName
;
};
// present the back buffer contents to the display
dev
->
Present
(
NULL
,
NULL
,
NULL
,
NULL
);
}
void
cleanUp
(
void
)
// main func
int
main
(
int
argc
,
char
**
argv
)
{
SAFE_RELEASE
(
pCPUWriteSurface
);
SAFE_RELEASE
(
pReadOnlySurface
);
SAFE_RELEASE
(
pSurface
);
SAFE_RELEASE
(
pBackBuffer
);
SAFE_RELEASE
(
dev
);
SAFE_RELEASE
(
pD3D
);
std
::
string
title
=
"D3D9Ex interop sample"
;
return
d3d_app
<
D3D9ExWinApp
>
(
argc
,
argv
,
title
);
}
samples/directx/d3d_base.inl.hpp
deleted
100644 → 0
View file @
ef8182e1
//
// Don't use as a standalone file
//
#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp" // cv::format
#include "opencv2/imgproc.hpp" // cvtColor
#include "opencv2/imgproc/types_c.h" // cvtColor
#include "opencv2/highgui.hpp" // imread
#include "opencv2/core/directx.hpp"
#include "opencv2/imgcodecs.hpp"
#include <iostream>
#include <queue>
using
namespace
cv
;
using
namespace
cv
::
directx
;
static
const
int
fontFace
=
cv
::
FONT_HERSHEY_DUPLEX
;
#if !defined(USE_D3D9) && !defined(USE_D3DEX)
const
cv
::
Scalar
frameColor
(
255
,
128
,
0
,
255
);
#else
const
cv
::
Scalar
frameColor
(
0
,
128
,
255
,
255
);
// BGRA for D3D9
#endif
#define SAFE_RELEASE(p) if (p) { p->Release(); p = NULL; }
const
int
WIDTH
=
1024
;
const
int
HEIGHT
=
768
;
HINSTANCE
hInstance
;
HWND
hWnd
;
// external declaration
bool
initDirect3D
(
void
);
bool
initDirect3DTextures
(
void
);
void
render
(
void
);
void
cleanUp
(
void
);
#define USAGE_DESCRIPTION_0 "1 - CPU write via LockRect/Map"
#define USAGE_DESCRIPTION_1 "2* - Mat->D3D"
#define USAGE_DESCRIPTION_2 "3* - D3D->UMat / change UMat / UMat->D3D"
#define USAGE_DESCRIPTION_3 "0 - show input texture without any processing"
#define USAGE_DESCRIPTION_SPACE "SPACE - toggle frame processing (only data transfers)"
static
int
g_sampleType
=
0
;
static
int
g_disableProcessing
=
false
;
// forward declaration
static
LRESULT
CALLBACK
WndProc
(
HWND
,
UINT
,
WPARAM
,
LPARAM
);
static
bool
initWindow
()
{
WNDCLASSEX
wcex
;
wcex
.
cbSize
=
sizeof
(
WNDCLASSEX
);
wcex
.
style
=
CS_HREDRAW
|
CS_VREDRAW
;
wcex
.
lpfnWndProc
=
WndProc
;
wcex
.
cbClsExtra
=
0
;
wcex
.
cbWndExtra
=
0
;
wcex
.
hInstance
=
hInstance
;
wcex
.
hIcon
=
LoadIcon
(
0
,
IDI_APPLICATION
);
wcex
.
hCursor
=
LoadCursor
(
0
,
IDC_ARROW
);
wcex
.
hbrBackground
=
0
;
wcex
.
lpszMenuName
=
0L
;
wcex
.
lpszClassName
=
"OpenCVDirectX"
;
wcex
.
hIconSm
=
0
;
RegisterClassEx
(
&
wcex
);
RECT
rc
=
{
0
,
0
,
WIDTH
,
HEIGHT
};
AdjustWindowRect
(
&
rc
,
WS_OVERLAPPEDWINDOW
,
false
);
hWnd
=
CreateWindow
(
"OpenCVDirectX"
,
WINDOW_NAME
,
WS_OVERLAPPEDWINDOW
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
rc
.
right
-
rc
.
left
,
rc
.
bottom
-
rc
.
top
,
NULL
,
NULL
,
hInstance
,
NULL
);
if
(
!
hWnd
)
return
false
;
ShowWindow
(
hWnd
,
SW_SHOW
);
UpdateWindow
(
hWnd
);
return
true
;
}
static
LRESULT
CALLBACK
WndProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
switch
(
message
)
{
case
WM_DESTROY
:
PostQuitMessage
(
0
);
return
0
;
case
WM_CHAR
:
if
(
wParam
>=
'0'
&&
wParam
<=
'3'
)
{
g_sampleType
=
(
char
)
wParam
-
'0'
;
return
0
;
}
else
if
(
wParam
==
' '
)
{
g_disableProcessing
=
!
g_disableProcessing
;
return
0
;
}
else
if
(
wParam
==
VK_ESCAPE
)
{
DestroyWindow
(
hWnd
);
return
0
;
}
break
;
}
return
DefWindowProc
(
hWnd
,
message
,
wParam
,
lParam
);
}
static
float
getFps
()
{
static
std
::
queue
<
int64
>
time_queue
;
int64
now
=
cv
::
getTickCount
(),
then
=
0
;
time_queue
.
push
(
now
);
if
(
time_queue
.
size
()
>=
2
)
then
=
time_queue
.
front
();
if
(
time_queue
.
size
()
>=
25
)
time_queue
.
pop
();
return
time_queue
.
size
()
*
(
float
)
cv
::
getTickFrequency
()
/
(
now
-
then
);
}
static
int
bgColor
[
4
]
=
{
0
,
0
,
0
,
0
};
static
cv
::
Mat
*
inputMat
=
NULL
;
static
void
renderToD3DObject
(
void
)
{
static
int
frame
=
0
;
const
float
fps
=
getFps
();
String
deviceName
=
cv
::
ocl
::
useOpenCL
()
?
cv
::
ocl
::
Context
::
getDefault
().
device
(
0
).
name
()
:
"No OpenCL device"
;
if
((
frame
%
std
::
max
(
1
,
(
int
)(
fps
/
25
)))
==
0
)
{
String
msg
=
format
(
"%s%s: %s, Sample %d, Frame %d, fps %g (%g ms)"
,
g_disableProcessing
?
"(FRAME PROCESSING DISABLED) "
:
""
,
WINDOW_NAME
,
deviceName
.
c_str
(),
g_sampleType
,
frame
,
fps
,
(
int
(
10
*
1000.0
/
fps
))
*
0.1
);
SetWindowText
(
hWnd
,
msg
.
c_str
());
}
// 0..255
int
c
[
4
]
=
{
std
::
abs
((
frame
&
0x1ff
)
-
0x100
),
std
::
abs
(((
frame
*
2
)
&
0x1ff
)
-
0x100
),
std
::
abs
(((
frame
/
2
)
&
0x1ff
)
-
0x100
),
0
};
int
c1
=
c
[
0
]
/
2
-
0x40
-
bgColor
[
0
];
int
c2
=
c
[
1
]
/
2
-
0x40
-
bgColor
[
1
];
int
c3
=
c
[
2
]
/
2
-
0x40
-
bgColor
[
2
];
switch
(
g_sampleType
)
{
case
0
:
#if defined(USE_D3D9) || defined (USE_D3DEX)
if
(
FAILED
(
dev
->
StretchRect
(
pReadOnlySurface
,
NULL
,
pBackBuffer
,
NULL
,
D3DTEXF_NONE
)))
{
std
::
cerr
<<
"Can't StretchRect()"
<<
std
::
endl
;
}
#elif defined(USE_D3D10)
dev
->
CopyResource
(
pBackBufferTexture
,
pInputTexture
);
#elif defined(USE_D3D11)
devcon
->
CopyResource
(
pBackBufferTexture
,
pInputTexture
);
#else
#error "Invalid USE_D3D value"
#endif
break
;
case
1
:
{
int
BOXSIZE
=
50
;
int
x
=
std
::
abs
(((
frame
*
1
)
%
(
2
*
(
WIDTH
-
BOXSIZE
)))
-
(
WIDTH
-
BOXSIZE
));
int
y
=
std
::
abs
(((
frame
/
2
)
%
(
2
*
(
HEIGHT
-
BOXSIZE
)))
-
(
HEIGHT
-
BOXSIZE
));
cv
::
Rect
boxRect
(
x
,
y
,
BOXSIZE
,
BOXSIZE
);
#if defined(USE_D3D9) || defined (USE_D3DEX)
D3DLOCKED_RECT
memDesc
=
{
0
,
NULL
};
RECT
rc
=
{
0
,
0
,
WIDTH
,
HEIGHT
};
if
(
SUCCEEDED
(
pCPUWriteSurface
->
LockRect
(
&
memDesc
,
&
rc
,
0
)))
{
if
(
!
g_disableProcessing
)
{
Mat
m
(
Size
(
WIDTH
,
HEIGHT
),
CV_8UC4
,
memDesc
.
pBits
,
(
int
)
memDesc
.
Pitch
);
inputMat
->
copyTo
(
m
);
m
(
boxRect
).
setTo
(
Scalar
(
c
[
0
],
c
[
1
],
c
[
2
],
255
));
}
pCPUWriteSurface
->
UnlockRect
();
}
else
{
std
::
cerr
<<
"Can't LockRect() on surface"
<<
std
::
endl
;
}
#elif defined(USE_D3D10)
D3D10_MAPPED_TEXTURE2D
mappedTex
;
if
(
SUCCEEDED
(
pCPUWriteTexture
->
Map
(
D3D10CalcSubresource
(
0
,
0
,
1
),
D3D10_MAP_WRITE_DISCARD
,
0
,
&
mappedTex
)))
{
if
(
!
g_disableProcessing
)
{
Mat
m
(
Size
(
WIDTH
,
HEIGHT
),
CV_8UC4
,
mappedTex
.
pData
,
(
int
)
mappedTex
.
RowPitch
);
inputMat
->
copyTo
(
m
);
m
(
boxRect
).
setTo
(
Scalar
(
c
[
0
],
c
[
1
],
c
[
2
],
255
));
}
pCPUWriteTexture
->
Unmap
(
D3D10CalcSubresource
(
0
,
0
,
1
));
dev
->
CopyResource
(
pBackBufferTexture
,
pCPUWriteTexture
);
}
else
{
std
::
cerr
<<
"Can't Map() texture"
<<
std
::
endl
;
}
#elif defined(USE_D3D11)
D3D11_MAPPED_SUBRESOURCE
mappedTex
;
if
(
SUCCEEDED
(
devcon
->
Map
(
pCPUWriteTexture
,
D3D11CalcSubresource
(
0
,
0
,
1
),
D3D11_MAP_WRITE_DISCARD
,
0
,
&
mappedTex
)))
{
if
(
!
g_disableProcessing
)
{
Mat
m
(
Size
(
WIDTH
,
HEIGHT
),
CV_8UC4
,
mappedTex
.
pData
,
(
int
)
mappedTex
.
RowPitch
);
inputMat
->
copyTo
(
m
);
m
(
boxRect
).
setTo
(
Scalar
(
c
[
0
],
c
[
1
],
c
[
2
],
255
));
}
devcon
->
Unmap
(
pCPUWriteTexture
,
D3D11CalcSubresource
(
0
,
0
,
1
));
devcon
->
CopyResource
(
pBackBufferTexture
,
pCPUWriteTexture
);
}
else
{
std
::
cerr
<<
"Can't Map() texture"
<<
std
::
endl
;
}
#else
#error "Invalid USE_D3D value"
#endif
break
;
}
case
2
:
{
static
Mat
m
;
if
(
!
g_disableProcessing
)
{
#if 1
cv
::
add
(
*
inputMat
,
Scalar
(
c1
,
c2
,
c3
,
255
),
m
);
#else
inputMat
->
copyTo
(
m
);
#endif
cv
::
putText
(
m
,
cv
::
format
(
"Frame %d, fps %g (%g ms)"
,
frame
,
fps
,
(
int
(
10
*
1000.0
/
fps
))
*
0.1
),
cv
::
Point
(
8
,
80
),
fontFace
,
1
,
frameColor
,
2
);
}
else
{
m
.
create
(
Size
(
WIDTH
,
HEIGHT
),
CV_8UC4
);
}
try
{
#if defined(USE_D3D9) || defined (USE_D3DEX)
convertToDirect3DSurface9
(
m
,
pSurface
,
(
void
*
)
surfaceShared
);
#elif defined(USE_D3D10)
convertToD3D10Texture2D
(
m
,
pBackBufferTexture
);
#elif defined(USE_D3D11)
convertToD3D11Texture2D
(
m
,
pBackBufferTexture
);
#else
#error "Invalid USE_D3D value"
#endif
}
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Can't convert to D3D object: exception: "
<<
e
.
what
()
<<
std
::
endl
;
}
catch
(...)
{
std
::
cerr
<<
"Can't convert to D3D object"
<<
std
::
endl
;
}
break
;
}
case
3
:
{
static
UMat
tmp
;
try
{
#if defined(USE_D3D9) || defined (USE_D3DEX)
convertFromDirect3DSurface9
(
pReadOnlySurface
,
tmp
,
(
void
*
)
readOnlySurfaceShared
);
#elif defined(USE_D3D10)
convertFromD3D10Texture2D
(
pInputTexture
,
tmp
);
#elif defined(USE_D3D11)
convertFromD3D11Texture2D
(
pInputTexture
,
tmp
);
#else
#error "Invalid USE_D3D value"
#endif
}
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Can't convert from D3D object: exception: "
<<
e
.
what
()
<<
std
::
endl
;
}
catch
(...)
{
std
::
cerr
<<
"Can't convert from D3D object"
<<
std
::
endl
;
}
static
UMat
res
;
if
(
!
g_disableProcessing
)
{
cv
::
add
(
tmp
,
Scalar
(
c1
,
c2
,
c3
,
255
),
res
);
}
else
{
res
=
tmp
;
}
try
{
#if defined(USE_D3D9) || defined (USE_D3DEX)
convertToDirect3DSurface9
(
res
,
pSurface
,
(
void
*
)
surfaceShared
);
#elif defined(USE_D3D10)
convertToD3D10Texture2D
(
res
,
pBackBufferTexture
);
#elif defined(USE_D3D11)
convertToD3D11Texture2D
(
res
,
pBackBufferTexture
);
#else
#error "Invalid USE_D3D value"
#endif
}
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Can't convert to D3D object: exception: "
<<
e
.
what
()
<<
std
::
endl
;
}
catch
(...)
{
std
::
cerr
<<
"Can't convert to D3D object"
<<
std
::
endl
;
}
break
;
}
}
frame
++
;
}
static
cv
::
Mat
getInputTexture
()
{
cv
::
Mat
inputMat
=
cv
::
imread
(
"input.bmp"
,
cv
::
IMREAD_COLOR
);
if
(
inputMat
.
depth
()
!=
CV_8U
)
{
inputMat
.
convertTo
(
inputMat
,
CV_8U
);
}
if
(
inputMat
.
type
()
==
CV_8UC3
)
{
cv
::
cvtColor
(
inputMat
,
inputMat
,
CV_RGB2BGRA
);
}
if
(
inputMat
.
type
()
!=
CV_8UC4
||
inputMat
.
size
().
area
()
==
0
)
{
std
::
cerr
<<
"Invalid input image format. Generate other"
<<
std
::
endl
;
inputMat
.
create
(
cv
::
Size
(
WIDTH
,
HEIGHT
),
CV_8UC4
);
inputMat
.
setTo
(
cv
::
Scalar
(
0
,
0
,
255
,
255
));
bgColor
[
0
]
=
-
128
;
bgColor
[
1
]
=
-
128
;
bgColor
[
2
]
=
127
;
bgColor
[
3
]
=
-
128
;
}
if
(
inputMat
.
size
().
width
!=
WIDTH
||
inputMat
.
size
().
height
!=
HEIGHT
)
{
cv
::
resize
(
inputMat
,
inputMat
,
cv
::
Size
(
WIDTH
,
HEIGHT
));
}
String
deviceName
=
cv
::
ocl
::
useOpenCL
()
?
cv
::
ocl
::
Context
::
getDefault
().
device
(
0
).
name
()
:
"No OpenCL device"
;
cv
::
Scalar
color
(
64
,
255
,
64
,
255
);
cv
::
putText
(
inputMat
,
cv
::
format
(
"OpenCL Device name: %s"
,
deviceName
.
c_str
()),
cv
::
Point
(
8
,
32
),
fontFace
,
1
,
color
);
cv
::
putText
(
inputMat
,
WINDOW_NAME
,
cv
::
Point
(
50
,
HEIGHT
-
32
),
fontFace
,
1
,
color
);
cv
::
putText
(
inputMat
,
USAGE_DESCRIPTION_0
,
cv
::
Point
(
30
,
128
),
fontFace
,
1
,
color
);
cv
::
putText
(
inputMat
,
USAGE_DESCRIPTION_1
,
cv
::
Point
(
30
,
192
),
fontFace
,
1
,
color
);
cv
::
putText
(
inputMat
,
USAGE_DESCRIPTION_2
,
cv
::
Point
(
30
,
256
),
fontFace
,
1
,
color
);
cv
::
putText
(
inputMat
,
USAGE_DESCRIPTION_3
,
cv
::
Point
(
30
,
320
),
fontFace
,
1
,
color
);
cv
::
putText
(
inputMat
,
USAGE_DESCRIPTION_SPACE
,
cv
::
Point
(
30
,
448
),
fontFace
,
1
,
color
);
#if defined(USE_D3D9) || defined (USE_D3DEX)
cv
::
cvtColor
(
inputMat
,
inputMat
,
CV_RGBA2BGRA
);
std
::
swap
(
bgColor
[
0
],
bgColor
[
2
]);
#endif
// Make a global copy
::
inputMat
=
new
cv
::
Mat
(
inputMat
);
return
inputMat
;
}
static
int
mainLoop
()
{
hInstance
=
GetModuleHandle
(
NULL
);
if
(
!
initWindow
())
CV_Error
(
cv
::
Error
::
StsError
,
"Can't create window"
);
if
(
!
initDirect3D
())
CV_Error
(
cv
::
Error
::
StsError
,
"Can't create D3D object"
);
if
(
cv
::
ocl
::
haveOpenCL
())
{
#if defined(USE_D3D9)
cv
::
ocl
::
Context
&
ctx
=
cv
::
directx
::
ocl
::
initializeContextFromDirect3DDevice9
(
dev
);
#elif defined (USE_D3DEX)
cv
::
ocl
::
Context
&
ctx
=
cv
::
directx
::
ocl
::
initializeContextFromDirect3DDevice9Ex
(
dev
);
#elif defined(USE_D3D10)
cv
::
ocl
::
Context
&
ctx
=
cv
::
directx
::
ocl
::
initializeContextFromD3D10Device
(
dev
);
#elif defined(USE_D3D11)
cv
::
ocl
::
Context
&
ctx
=
cv
::
directx
::
ocl
::
initializeContextFromD3D11Device
(
dev
);
#else
#error "Invalid USE_D3D value"
#endif
std
::
cout
<<
"Selected device: "
<<
ctx
.
device
(
0
).
name
().
c_str
()
<<
std
::
endl
;
g_sampleType
=
2
;
}
else
{
std
::
cerr
<<
"OpenCL is not available. DirectX - OpenCL interop will not work"
<<
std
::
endl
;
}
if
(
!
initDirect3DTextures
())
CV_Error
(
cv
::
Error
::
StsError
,
"Can't create D3D texture object"
);
MSG
msg
;
ZeroMemory
(
&
msg
,
sizeof
(
msg
));
while
(
msg
.
message
!=
WM_QUIT
)
{
if
(
PeekMessage
(
&
msg
,
NULL
,
0U
,
0U
,
PM_REMOVE
))
{
TranslateMessage
(
&
msg
);
DispatchMessage
(
&
msg
);
}
else
{
render
();
}
}
cleanUp
();
return
static_cast
<
int
>
(
msg
.
wParam
);
}
int
main
(
int
/*argc*/
,
char
**
/*argv*/
)
{
try
{
return
mainLoop
();
}
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Exception: "
<<
e
.
what
()
<<
std
::
endl
;
return
10
;
}
catch
(...)
{
std
::
cerr
<<
"FATAL ERROR: Unknown exception"
<<
std
::
endl
;
return
11
;
}
}
samples/directx/d3dsample.hpp
0 → 100644
View file @
8e392251
/*
// Sample demonstrating interoperability of OpenCV UMat with Direct X surface
// Base class for Direct X application
*/
#include <string>
#include <iostream>
#include <queue>
#include "opencv2/core.hpp"
#include "opencv2/core/directx.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "winapp.hpp"
#define SAFE_RELEASE(p) if (p) { p->Release(); p = NULL; }
class
D3DSample
:
public
WinApp
{
public
:
enum
MODE
{
MODE_NOP
,
MODE_CPU
,
MODE_GPU
};
D3DSample
(
int
width
,
int
height
,
std
::
string
&
window_name
,
cv
::
VideoCapture
&
cap
)
:
WinApp
(
width
,
height
,
window_name
)
{
m_shutdown
=
false
;
m_mode
=
MODE_NOP
;
m_modeStr
[
0
]
=
cv
::
String
(
"No processing"
);
m_modeStr
[
1
]
=
cv
::
String
(
"Processing on CPU"
);
m_modeStr
[
2
]
=
cv
::
String
(
"Processing on GPU"
);
m_disableProcessing
=
false
;
m_cap
=
cap
;
}
~
D3DSample
()
{}
virtual
int
create
()
{
return
WinApp
::
create
();
}
virtual
int
render
()
=
0
;
virtual
int
cleanup
()
{
m_shutdown
=
true
;
return
WinApp
::
cleanup
();
}
static
float
getFps
()
{
static
std
::
queue
<
int64
>
time_queue
;
int64
now
=
cv
::
getTickCount
();
int64
then
=
0
;
time_queue
.
push
(
now
);
if
(
time_queue
.
size
()
>=
2
)
then
=
time_queue
.
front
();
if
(
time_queue
.
size
()
>=
25
)
time_queue
.
pop
();
size_t
sz
=
time_queue
.
size
();
float
fps
=
sz
*
(
float
)
cv
::
getTickFrequency
()
/
(
now
-
then
);
return
fps
;
}
protected
:
virtual
LRESULT
CALLBACK
WndProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
switch
(
message
)
{
case
WM_CHAR
:
if
(
wParam
>=
'0'
&&
wParam
<=
'2'
)
{
m_mode
=
static_cast
<
MODE
>
((
char
)
wParam
-
'0'
);
return
0
;
}
else
if
(
wParam
==
VK_SPACE
)
{
m_disableProcessing
=
!
m_disableProcessing
;
return
0
;
}
else
if
(
wParam
==
VK_ESCAPE
)
{
return
cleanup
();
}
break
;
case
WM_CLOSE
:
return
cleanup
();
case
WM_DESTROY
:
::
PostQuitMessage
(
0
);
return
0
;
}
return
::
DefWindowProc
(
hWnd
,
message
,
wParam
,
lParam
);
}
// do render at idle
virtual
int
idle
()
{
return
render
();
}
protected
:
bool
m_shutdown
;
bool
m_disableProcessing
;
MODE
m_mode
;
cv
::
String
m_modeStr
[
3
];
cv
::
VideoCapture
m_cap
;
cv
::
Mat
m_frame_bgr
;
cv
::
Mat
m_frame_rgba
;
};
static
void
help
()
{
printf
(
"
\n
Sample demonstrating interoperability of DirectX and OpenCL with OpenCV.
\n
"
"Hot keys:
\n
"
" 0 - no processing
\n
"
" 1 - blur DX surface on CPU through OpenCV
\n
"
" 2 - blur DX surface on GPU through OpenCV using OpenCL
\n
"
" ESC - exit
\n\n
"
);
}
static
const
char
*
keys
=
{
"{c camera | true | use camera or not}"
"{f file | | movie file name }"
"{h help | false | print help info }"
};
template
<
typename
TApp
>
int
d3d_app
(
int
argc
,
char
**
argv
,
std
::
string
&
title
)
{
cv
::
CommandLineParser
parser
(
argc
,
argv
,
keys
);
\
bool
useCamera
=
parser
.
has
(
"camera"
);
\
string
file
=
parser
.
get
<
string
>
(
"file"
);
\
bool
showHelp
=
parser
.
get
<
bool
>
(
"help"
);
\
if
(
showHelp
)
help
();
parser
.
printMessage
();
cv
::
VideoCapture
cap
;
if
(
useCamera
)
cap
.
open
(
0
);
else
cap
.
open
(
file
.
c_str
());
if
(
!
cap
.
isOpened
())
{
printf
(
"can not open camera or video file
\n
"
);
return
-
1
;
}
int
width
=
(
int
)
cap
.
get
(
CAP_PROP_FRAME_WIDTH
);
int
height
=
(
int
)
cap
.
get
(
CAP_PROP_FRAME_HEIGHT
);
std
::
string
wndname
=
title
;
TApp
app
(
width
,
height
,
wndname
,
cap
);
try
{
app
.
create
();
return
app
.
run
();
}
catch
(
cv
::
Exception
&
e
)
{
std
::
cerr
<<
"Exception: "
<<
e
.
what
()
<<
std
::
endl
;
return
10
;
}
catch
(...)
{
std
::
cerr
<<
"FATAL ERROR: Unknown exception"
<<
std
::
endl
;
return
11
;
}
}
samples/directx/winapp.hpp
0 → 100644
View file @
8e392251
/*
// Sample demonstrating interoperability of OpenCV UMat with Direct X surface
// Base class for Windows application
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
#define WINCLASS "WinAppWnd"
class
WinApp
{
public
:
WinApp
(
int
width
,
int
height
,
std
::
string
&
window_name
)
{
m_width
=
width
;
m_height
=
height
;
m_window_name
=
window_name
;
m_hInstance
=
::
GetModuleHandle
(
NULL
);
m_hWnd
=
0
;
}
virtual
~
WinApp
()
{}
virtual
int
create
()
{
WNDCLASSEX
wcex
;
wcex
.
cbSize
=
sizeof
(
WNDCLASSEX
);
wcex
.
style
=
CS_HREDRAW
|
CS_VREDRAW
;
wcex
.
lpfnWndProc
=
&
WinApp
::
StaticWndProc
;
wcex
.
cbClsExtra
=
0
;
wcex
.
cbWndExtra
=
0
;
wcex
.
hInstance
=
m_hInstance
;
wcex
.
hIcon
=
LoadIcon
(
0
,
IDI_APPLICATION
);
wcex
.
hCursor
=
LoadCursor
(
0
,
IDC_ARROW
);
wcex
.
hbrBackground
=
0
;
wcex
.
lpszMenuName
=
0L
;
wcex
.
lpszClassName
=
WINCLASS
;
wcex
.
hIconSm
=
0
;
ATOM
wc
=
::
RegisterClassEx
(
&
wcex
);
if
(
!
wc
)
return
-
1
;
RECT
rc
=
{
0
,
0
,
m_width
,
m_height
};
if
(
!::
AdjustWindowRect
(
&
rc
,
WS_OVERLAPPEDWINDOW
,
false
))
return
-
1
;
m_hWnd
=
::
CreateWindow
(
(
LPCTSTR
)
wc
,
m_window_name
.
c_str
(),
WS_OVERLAPPEDWINDOW
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
rc
.
right
-
rc
.
left
,
rc
.
bottom
-
rc
.
top
,
NULL
,
NULL
,
m_hInstance
,
(
void
*
)
this
);
if
(
!
m_hWnd
)
return
-
1
;
::
ShowWindow
(
m_hWnd
,
SW_SHOW
);
::
UpdateWindow
(
m_hWnd
);
::
SetFocus
(
m_hWnd
);
return
0
;
}
// create()
int
run
()
{
MSG
msg
;
::
ZeroMemory
(
&
msg
,
sizeof
(
msg
));
while
(
msg
.
message
!=
WM_QUIT
)
{
if
(
::
PeekMessage
(
&
msg
,
NULL
,
0U
,
0U
,
PM_REMOVE
))
{
::
TranslateMessage
(
&
msg
);
::
DispatchMessage
(
&
msg
);
}
else
{
idle
();
}
}
return
static_cast
<
int
>
(
msg
.
wParam
);
}
// run()
virtual
int
cleanup
()
{
::
DestroyWindow
(
m_hWnd
);
::
UnregisterClass
(
WINCLASS
,
m_hInstance
);
return
0
;
}
// cleanup()
protected
:
// dispatch message handling to method of class
static
LRESULT
CALLBACK
StaticWndProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
WinApp
*
pWnd
;
if
(
message
==
WM_NCCREATE
)
{
LPCREATESTRUCT
pCreateStruct
=
reinterpret_cast
<
LPCREATESTRUCT
>
(
lParam
);
pWnd
=
static_cast
<
WinApp
*>
(
pCreateStruct
->
lpCreateParams
);
::
SetWindowLongPtr
(
hWnd
,
GWLP_USERDATA
,
reinterpret_cast
<
LONG_PTR
>
(
pWnd
));
}
pWnd
=
GetObjectFromWindow
(
hWnd
);
if
(
pWnd
)
return
pWnd
->
WndProc
(
hWnd
,
message
,
wParam
,
lParam
);
else
return
::
DefWindowProc
(
hWnd
,
message
,
wParam
,
lParam
);
}
// StaticWndProc()
inline
static
WinApp
*
GetObjectFromWindow
(
HWND
hWnd
)
{
return
(
WinApp
*
)
::
GetWindowLongPtr
(
hWnd
,
GWLP_USERDATA
);
}
// actual wnd message handling
virtual
LRESULT
CALLBACK
WndProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
=
0
;
// idle processing
virtual
int
idle
()
=
0
;
HINSTANCE
m_hInstance
;
HWND
m_hWnd
;
int
m_width
;
int
m_height
;
std
::
string
m_window_name
;
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment