From f0197006e0e17cf178bed979bf3d8c66ec3e953c Mon Sep 17 00:00:00 2001 From: Vladimir Dudnik Date: Sat, 16 May 2015 00:40:05 +0300 Subject: [PATCH] removed original samples and replace them with new ones. modified new samples (reduce code duplication, add cmd line params and short description) --- samples/directx/d3d10_interop.cpp | 375 ++++++++++++++++------- samples/directx/d3d10_opencl.cpp | 397 ------------------------- samples/directx/d3d11_interop.cpp | 386 +++++++++++++++++------- samples/directx/d3d11_opencl.cpp | 403 ------------------------- samples/directx/d3d9_interop.cpp | 376 ++++++++++++++++------- samples/directx/d3d9_opencl.cpp | 396 ------------------------- samples/directx/d3d9ex_interop.cpp | 384 ++++++++++++++++-------- samples/directx/d3d9ex_opencl.cpp | 396 ------------------------- samples/directx/d3d_base.inl.hpp | 458 ----------------------------- samples/directx/d3dsample.hpp | 185 ++++++++++++ samples/directx/winapp.hpp | 53 ++-- 11 files changed, 1281 insertions(+), 2528 deletions(-) delete mode 100644 samples/directx/d3d10_opencl.cpp delete mode 100644 samples/directx/d3d11_opencl.cpp delete mode 100644 samples/directx/d3d9_opencl.cpp delete mode 100644 samples/directx/d3d9ex_opencl.cpp delete mode 100644 samples/directx/d3d_base.inl.hpp create mode 100644 samples/directx/d3dsample.hpp diff --git a/samples/directx/d3d10_interop.cpp b/samples/directx/d3d10_interop.cpp index 7e23c4b806..2e860bb575 100644 --- a/samples/directx/d3d10_interop.cpp +++ b/samples/directx/d3d10_interop.cpp @@ -1,138 +1,299 @@ +#define WIN32_LEAN_AND_MEAN #include #include -#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" -IDXGISwapChain *swapchain = NULL; -ID3D10Device *dev = NULL; -ID3D10Texture2D *pBackBufferTexture = NULL; -ID3D10Texture2D *pCPUWriteTexture = NULL; -ID3D10Texture2D *pInputTexture = NULL; -ID3D10RenderTargetView *backbuffer = NULL; +#pragma comment (lib, "d3d10.lib") -#include "d3d_base.inl.hpp" -bool initDirect3D() +using namespace std; +using namespace cv; + +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) {} + + ~D3D10WinApp() {} - if (FAILED(swapchain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBufferTexture))) - { - return false; - } - 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.0f; - viewport.MaxDepth = 0.0f; - 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.0f; + viewport.MaxDepth = 0.0f; + + 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 + m_oclDevName = cv::ocl::useOpenCL() ? + cv::ocl::Context::getDefault().device(0).name() : + "No OpenCL device"; - SAFE_RELEASE(swapchain); - SAFE_RELEASE(pCPUWriteTexture); - SAFE_RELEASE(pInputTexture); - SAFE_RELEASE(pBackBufferTexture); - SAFE_RELEASE(backbuffer); - SAFE_RELEASE(dev); -} + return 0; + } // create() -void render(void) -{ - // check to make sure you have a valid Direct3D device - CV_Assert(dev); + // 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() + + + // 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); + + 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; +}; - renderToD3DObject(); - // switch the back buffer and the front buffer - swapchain->Present(0, 0); -} +// main func +ENTRY_POINT(D3D10WinApp, "D3D10 interop sample"); diff --git a/samples/directx/d3d10_opencl.cpp b/samples/directx/d3d10_opencl.cpp deleted file mode 100644 index 432c756446..0000000000 --- a/samples/directx/d3d10_opencl.cpp +++ /dev/null @@ -1,397 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include -#include -#include - -#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" - -#pragma comment (lib, "d3d10.lib") - - -class D3D10WinApp : public WinApp -{ -public: - D3D10WinApp(int width, int height, std::string& window_name, cv::VideoCapture& cap) : - WinApp(width, height, window_name) - { - m_shutdown = false; - m_mode = 0; - 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; - } - - ~D3D10WinApp() {} - - int onClose(void) - { - m_shutdown = true; - cleanup(); - ::DestroyWindow(m_hWnd); - return 0; - } - - virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) - { - switch (message) - { - case WM_CHAR: - if (wParam >= '0' && wParam <= '2') - { - m_mode = (char)wParam - '0'; - return 0; - } - else if (wParam == VK_SPACE) - { - m_disableProcessing = !m_disableProcessing; - return 0; - } - else if (wParam == VK_ESCAPE) - { - return onClose(); - } - break; - - case WM_CLOSE: - return onClose(); - - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - - return ::DefWindowProc(hWnd, message, wParam, lParam); - } - - static float getFps() - { - static std::queue 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(); - - return time_queue.size() * (float)cv::getTickFrequency() / (now - then); - } - - int init(void) - { - HRESULT r; - - 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 = 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)) - { - return -1; - } - - 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.0f; - viewport.MaxDepth = 0.0f; - - m_pD3D10Dev->RSSetViewports(1, &viewport); - - D3D10_TEXTURE2D_DESC desc = { 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; - - r = m_pD3D10Dev->CreateTexture2D(&desc, NULL, &m_pSurface); - if (FAILED(r)) - { - std::cerr << "Can't create texture with input image" << std::endl; - return -1; - } - - if (cv::ocl::haveOpenCL()) - { - m_oclCtx = cv::directx::ocl::initializeContextFromD3D10Device(m_pD3D10Dev); - } - - m_oclDevName = cv::ocl::useOpenCL() ? - cv::ocl::Context::getDefault().device(0).name() : - "No OpenCL device"; - - return 0; - } // init() - - - 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; - } - - - 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); - - 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; - } - - - 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 0: - // no processing - break; - - case 1: - { - // 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 2: - { - // 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; - } - } - - catch (cv::Exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - return 10; - } - - return 0; - } - - int cleanup(void) - { - SAFE_RELEASE(m_pSurface); - SAFE_RELEASE(m_pBackBuffer); - SAFE_RELEASE(m_pD3D10SwapChain); - SAFE_RELEASE(m_pRenderTarget); - SAFE_RELEASE(m_pD3D10Dev); - return 0; - } - -private: - bool m_shutdown; - int m_mode; - cv::String m_modeStr[3]; - int m_disableProcessing; - ID3D10Device* m_pD3D10Dev; - IDXGISwapChain* m_pD3D10SwapChain; - ID3D10Texture2D* m_pBackBuffer; - ID3D10Texture2D* m_pSurface; - ID3D10RenderTargetView* m_pRenderTarget; - cv::VideoCapture m_cap; - cv::Mat m_frame_bgr; - cv::Mat m_frame_rgba; - cv::ocl::Context m_oclCtx; - cv::String m_oclPlatformName; - cv::String m_oclDevName; -}; - - -using namespace cv; - -int main(int argc, char** argv) -{ - cv::VideoCapture cap; - - if (argc > 1) - { - cap.open(argv[1]); - } - else - cap.open(0); - - int width = (int)cap.get(CAP_PROP_FRAME_WIDTH); - int height = (int)cap.get(CAP_PROP_FRAME_HEIGHT); - std::string wndname = "D3D10 Window"; - - D3D10WinApp 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; - } -} diff --git a/samples/directx/d3d11_interop.cpp b/samples/directx/d3d11_interop.cpp index d4fca058e3..9a310237ef 100644 --- a/samples/directx/d3d11_interop.cpp +++ b/samples/directx/d3d11_interop.cpp @@ -1,143 +1,305 @@ +#define WIN32_LEAN_AND_MEAN #include #include -#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" -IDXGISwapChain *swapchain = NULL; -ID3D11Device *dev = NULL; -ID3D11DeviceContext *devcon = NULL; -ID3D11Texture2D *pBackBufferTexture = NULL; -ID3D11Texture2D *pCPUWriteTexture = NULL; -ID3D11Texture2D *pInputTexture = NULL; -ID3D11RenderTargetView *backbuffer = NULL; +#pragma comment (lib, "d3d11.lib") -#include "d3d_base.inl.hpp" -bool initDirect3D() +using namespace std; +using namespace cv; + +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) {} + + ~D3D11WinApp() {} - if (FAILED(swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBufferTexture))) - { - return false; - } - 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.0f; - viewport.MaxDepth = 0.0f; - 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.0f; + viewport.MaxDepth = 0.0f; + + 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 + m_oclDevName = cv::ocl::useOpenCL() ? + cv::ocl::Context::getDefault().device(0).name() : + "No OpenCL device"; - SAFE_RELEASE(swapchain); - SAFE_RELEASE(pCPUWriteTexture); - SAFE_RELEASE(pInputTexture); - SAFE_RELEASE(pBackBufferTexture); - SAFE_RELEASE(backbuffer); - SAFE_RELEASE(dev); - SAFE_RELEASE(devcon); -} + return 0; + } // create() -void render(void) -{ - // check to make sure you have a valid Direct3D device - CV_Assert(dev); + // 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() + + + // 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); + + 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; +}; - renderToD3DObject(); - // switch the back buffer and the front buffer - swapchain->Present(0, 0); -} +// main func +ENTRY_POINT(D3D11WinApp, "D3D11 interop sample"); diff --git a/samples/directx/d3d11_opencl.cpp b/samples/directx/d3d11_opencl.cpp deleted file mode 100644 index 2d87a34654..0000000000 --- a/samples/directx/d3d11_opencl.cpp +++ /dev/null @@ -1,403 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include -#include -#include - -#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" - -#pragma comment (lib, "d3d11.lib") - - -class D3D11WinApp : public WinApp -{ -public: - D3D11WinApp(int width, int height, std::string& window_name, cv::VideoCapture& cap) : - WinApp(width, height, window_name) - { - m_shutdown = false; - m_mode = 0; - 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; - } - - ~D3D11WinApp() {} - - int onClose(void) - { - m_shutdown = true; - cleanup(); - ::DestroyWindow(m_hWnd); - return 0; - } - - virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) - { - switch (message) - { - case WM_CHAR: - if (wParam >= '0' && wParam <= '2') - { - m_mode = (char)wParam - '0'; - return 0; - } - else if (wParam == VK_SPACE) - { - m_disableProcessing = !m_disableProcessing; - return 0; - } - else if (wParam == VK_ESCAPE) - { - return onClose(); - } - break; - - case WM_CLOSE: - return onClose(); - - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - - return ::DefWindowProc(hWnd, message, wParam, lParam); - } - - static float getFps() - { - static std::queue 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(); - - return time_queue.size() * (float)cv::getTickFrequency() / (now - then); - } - - int init(void) - { - HRESULT r; - - 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 = 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)) - { - return -1; - } - - 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.0f; - viewport.MaxDepth = 0.0f; - - m_pD3D11Ctx->RSSetViewports(1, &viewport); - - D3D11_TEXTURE2D_DESC desc = { 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; - - r = m_pD3D11Dev->CreateTexture2D(&desc, NULL, &m_pSurface); - if (FAILED(r)) - { - std::cerr << "Can't create texture with input image" << std::endl; - return -1; - } - - if (cv::ocl::haveOpenCL()) - { - m_oclCtx = cv::directx::ocl::initializeContextFromD3D11Device(m_pD3D11Dev); - } - - m_oclDevName = cv::ocl::useOpenCL() ? - cv::ocl::Context::getDefault().device(0).name() : - "No OpenCL device"; - - return 0; - } // init() - - - 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; - } - - - 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); - - 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; - } - - - 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 0: - // no processing - break; - - case 1: - { - // 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 2: - { - // 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; - } - } - - catch (cv::Exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - return 10; - } - - return 0; - } - - 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); - return 0; - } - -private: - bool m_shutdown; - int m_mode; - cv::String m_modeStr[3]; - int m_disableProcessing; - ID3D11Device* m_pD3D11Dev; - IDXGISwapChain* m_pD3D11SwapChain; - ID3D11DeviceContext* m_pD3D11Ctx; - ID3D11Texture2D* m_pBackBuffer; - ID3D11Texture2D* m_pSurface; - ID3D11RenderTargetView* m_pRenderTarget; - cv::VideoCapture m_cap; - cv::Mat m_frame_bgr; - cv::Mat m_frame_rgba; - cv::ocl::Context m_oclCtx; - cv::String m_oclPlatformName; - cv::String m_oclDevName; -}; - - -using namespace cv; - -int main(int argc, char** argv) -{ - cv::VideoCapture cap; - - if (argc > 1) - { - cap.open(argv[1]); - } - else - cap.open(0); - - int width = (int)cap.get(CAP_PROP_FRAME_WIDTH); - int height = (int)cap.get(CAP_PROP_FRAME_HEIGHT); - std::string wndname = "D3D11 Window"; - - D3D11WinApp 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; - } -} diff --git a/samples/directx/d3d9_interop.cpp b/samples/directx/d3d9_interop.cpp index fc9bdbdd33..f371f03247 100644 --- a/samples/directx/d3d9_interop.cpp +++ b/samples/directx/d3d9_interop.cpp @@ -1,149 +1,297 @@ +#define WIN32_LEAN_AND_MEAN #include #include -#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() {} - if (FAILED(dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer))) + int 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 + { + 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 << "Can't StretchRect()" << std::endl; + 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; + } + + 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); } - } - if (SUCCEEDED(dev -> BeginScene())) + 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) -{ - SAFE_RELEASE(pCPUWriteSurface); - SAFE_RELEASE(pReadOnlySurface); - SAFE_RELEASE(pSurface); - SAFE_RELEASE(pBackBuffer); - SAFE_RELEASE(dev); - SAFE_RELEASE(pD3D);} + +// main func +ENTRY_POINT(D3D9WinApp, "D3D9 interop sample"); diff --git a/samples/directx/d3d9_opencl.cpp b/samples/directx/d3d9_opencl.cpp deleted file mode 100644 index 538b185f01..0000000000 --- a/samples/directx/d3d9_opencl.cpp +++ /dev/null @@ -1,396 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include -#include -#include - -#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" - -#pragma comment (lib, "d3d9.lib") - - -class D3D9WinApp : public WinApp -{ -public: - D3D9WinApp(int width, int height, std::string& window_name, cv::VideoCapture& cap) : - WinApp(width, height, window_name) - { - m_shutdown = false; - m_mode = 0; - 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; - } - - ~D3D9WinApp() {} - - int onClose(void) - { - m_shutdown = true; - cleanup(); - ::DestroyWindow(m_hWnd); - return 0; - } - - virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) - { - switch (message) - { - case WM_CHAR: - if (wParam >= '0' && wParam <= '2') - { - m_mode = (char)wParam - '0'; - return 0; - } - else if (wParam == VK_SPACE) - { - m_disableProcessing = !m_disableProcessing; - return 0; - } - else if (wParam == VK_ESCAPE) - { - return onClose(); - } - break; - - case WM_CLOSE: - return onClose(); - - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - - return ::DefWindowProc(hWnd, message, wParam, lParam); - } - - static float getFps() - { - static std::queue 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(); - - return time_queue.size() * (float)cv::getTickFrequency() / (now - then); - } - - int init(void) - { - HRESULT r; - - m_pD3D9 = ::Direct3DCreate9(D3D_SDK_VERSION); - if (NULL == m_pD3D9) - { - return -1; - } - - 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)) - { - return -1; - } - - r = m_pD3D9Dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer); - if (FAILED(r)) - { - return -1; - } - - r = m_pD3D9Dev->CreateOffscreenPlainSurface(m_width, m_height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pSurface, NULL); - if (FAILED(r)) - { - std::cerr << "Can't create surface for result" << std::endl; - return -1; - } - - if (cv::ocl::haveOpenCL()) - { - m_oclCtx = cv::directx::ocl::initializeContextFromDirect3DDevice9(m_pD3D9Dev); - } - - m_oclDevName = cv::ocl::useOpenCL() ? - cv::ocl::Context::getDefault().device(0).name() : - "No OpenCL device"; - - return 0; - } // init() - - - int get_surface(LPDIRECT3DSURFACE9* ppSurface) - { - 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; - } - - - void print_info(LPDIRECT3DSURFACE9 pSurface, int mode, float fps, cv::String oclDevName) - { - HDC hDC; - - HRESULT r = pSurface->GetDC(&hDC); - if (FAILED(r)) - { - return; - } - - 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; - } - - - int render() - { - try - { - if (m_shutdown) - return 0; - - HRESULT r; - LPDIRECT3DSURFACE9 pSurface; - - r = get_surface(&pSurface); - if (FAILED(r)) - { - return -1; - } - - switch (m_mode) - { - case 0: - // no processing - break; - - case 1: - { - // 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 2: - { - // 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; - } - } - - catch (cv::Exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - return 10; - } - - return 0; - } - - int cleanup(void) - { - SAFE_RELEASE(m_pSurface); - SAFE_RELEASE(m_pBackBuffer); - SAFE_RELEASE(m_pD3D9Dev); - SAFE_RELEASE(m_pD3D9); - return 0; - } - -private: - bool m_shutdown; - int m_mode; - cv::String m_modeStr[3]; - int m_disableProcessing; - LPDIRECT3D9 m_pD3D9; - LPDIRECT3DDEVICE9 m_pD3D9Dev; - LPDIRECT3DSURFACE9 m_pBackBuffer; - LPDIRECT3DSURFACE9 m_pSurface; - cv::VideoCapture m_cap; - cv::Mat m_frame_bgr; - cv::Mat m_frame_rgba; - cv::ocl::Context m_oclCtx; - cv::String m_oclPlatformName; - cv::String m_oclDevName; -}; - - -using namespace cv; - -int main(int argc, char** argv) -{ - cv::VideoCapture cap; - - if (argc > 1) - { - cap.open(argv[1]); - } - else - cap.open(0); - - int width = (int)cap.get(CAP_PROP_FRAME_WIDTH); - int height = (int)cap.get(CAP_PROP_FRAME_HEIGHT); - std::string wndname = "D3D9 Window"; - - D3D9WinApp 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; - } -} diff --git a/samples/directx/d3d9ex_interop.cpp b/samples/directx/d3d9ex_interop.cpp index 38d23007b8..46f2c5f7ba 100644 --- a/samples/directx/d3d9ex_interop.cpp +++ b/samples/directx/d3d9ex_interop.cpp @@ -1,158 +1,298 @@ +#define WIN32_LEAN_AND_MEAN #include #include -#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() {} - if (FAILED(dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer))) + int 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)) + { + return -1; + } + + r = m_pD3D9DevEx->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer); + 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->CreateOffscreenPlainSurface(m_width, m_height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pSurface, NULL); + 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); + std::cerr << "Can't create surface for result" << std::endl; + return -1; } - else + + // initialize OpenCL context of OpenCV lib from DirectX + if (cv::ocl::haveOpenCL()) { - std::cerr << "Can't LockRect() on surface" << std::endl; + m_oclCtx = cv::directx::ocl::initializeContextFromDirect3DDevice9(m_pD3D9DevEx); } - pTmpSurface->Release(); - } - if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pCPUWriteSurface, NULL))) + 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; + } + + 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); } - } - if (SUCCEEDED(dev -> BeginScene())) + 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() - // present the back buffer contents to the display - dev->Present(NULL, NULL, NULL, NULL); -} +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; +}; -void cleanUp (void) -{ - SAFE_RELEASE(pCPUWriteSurface); - SAFE_RELEASE(pReadOnlySurface); - SAFE_RELEASE(pSurface); - SAFE_RELEASE(pBackBuffer); - SAFE_RELEASE(dev); - SAFE_RELEASE(pD3D); -} + +// main func +ENTRY_POINT(D3D9ExWinApp, "D3D9Ex interop sample"); diff --git a/samples/directx/d3d9ex_opencl.cpp b/samples/directx/d3d9ex_opencl.cpp deleted file mode 100644 index a4f6d312ab..0000000000 --- a/samples/directx/d3d9ex_opencl.cpp +++ /dev/null @@ -1,396 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include -#include -#include - -#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" - -#pragma comment (lib, "d3d9.lib") - - -class D3D9ExWinApp : public WinApp -{ -public: - D3D9ExWinApp(int width, int height, std::string& window_name, cv::VideoCapture& cap) : - WinApp(width, height, window_name) - { - m_shutdown = false; - m_mode = 0; - 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; - } - - ~D3D9ExWinApp() {} - - int onClose(void) - { - m_shutdown = true; - cleanup(); - ::DestroyWindow(m_hWnd); - return 0; - } - - virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) - { - switch (message) - { - case WM_CHAR: - if (wParam >= '0' && wParam <= '2') - { - m_mode = (char)wParam - '0'; - return 0; - } - else if (wParam == VK_SPACE) - { - m_disableProcessing = !m_disableProcessing; - return 0; - } - else if (wParam == VK_ESCAPE) - { - return onClose(); - } - break; - - case WM_CLOSE: - return onClose(); - - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - - return ::DefWindowProc(hWnd, message, wParam, lParam); - } - - static float getFps() - { - static std::queue 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(); - - return time_queue.size() * (float)cv::getTickFrequency() / (now - then); - } - - int init(void) - { - HRESULT r; - - r = ::Direct3DCreate9Ex(D3D_SDK_VERSION, &m_pD3D9Ex); - if (FAILED(r)) - { - return -1; - } - - 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)) - { - return -1; - } - - r = m_pD3D9DevEx->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer); - if (FAILED(r)) - { - return -1; - } - - r = m_pD3D9DevEx->CreateOffscreenPlainSurface(m_width, m_height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pSurface, NULL); - if (FAILED(r)) - { - std::cerr << "Can't create surface for result" << std::endl; - return -1; - } - - 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; - } // init() - - - int get_surface(LPDIRECT3DSURFACE9* ppSurface) - { - 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; - } - - - void print_info(LPDIRECT3DSURFACE9 pSurface, int mode, float fps, cv::String oclDevName) - { - HDC hDC; - - HRESULT r = pSurface->GetDC(&hDC); - if (FAILED(r)) - { - return; - } - - 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; - } - - - int render() - { - try - { - if (m_shutdown) - return 0; - - HRESULT r; - LPDIRECT3DSURFACE9 pSurface; - - r = get_surface(&pSurface); - if (FAILED(r)) - { - return -1; - } - - switch (m_mode) - { - case 0: - // no processing - break; - - case 1: - { - // 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 2: - { - // 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; - } - } - - catch (cv::Exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - return 10; - } - - return 0; - } - - int cleanup(void) - { - SAFE_RELEASE(m_pSurface); - SAFE_RELEASE(m_pBackBuffer); - SAFE_RELEASE(m_pD3D9DevEx); - SAFE_RELEASE(m_pD3D9Ex); - return 0; - } - -private: - bool m_shutdown; - int m_mode; - cv::String m_modeStr[3]; - int m_disableProcessing; - LPDIRECT3D9EX m_pD3D9Ex; - LPDIRECT3DDEVICE9EX m_pD3D9DevEx; - LPDIRECT3DSURFACE9 m_pBackBuffer; - LPDIRECT3DSURFACE9 m_pSurface; - cv::VideoCapture m_cap; - cv::Mat m_frame_bgr; - cv::Mat m_frame_rgba; - cv::ocl::Context m_oclCtx; - cv::String m_oclPlatformName; - cv::String m_oclDevName; -}; - - -using namespace cv; - -int main(int argc, char** argv) -{ - cv::VideoCapture cap; - - if (argc > 1) - { - cap.open(argv[1]); - } - else - cap.open(0); - - int width = (int)cap.get(CAP_PROP_FRAME_WIDTH); - int height = (int)cap.get(CAP_PROP_FRAME_HEIGHT); - std::string wndname = "D3D9Ex Window"; - - D3D9ExWinApp 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; - } -} diff --git a/samples/directx/d3d_base.inl.hpp b/samples/directx/d3d_base.inl.hpp deleted file mode 100644 index 0ba44eca15..0000000000 --- a/samples/directx/d3d_base.inl.hpp +++ /dev/null @@ -1,458 +0,0 @@ -// -// 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 -#include - -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 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(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; - } -} diff --git a/samples/directx/d3dsample.hpp b/samples/directx/d3dsample.hpp new file mode 100644 index 0000000000..d829f1c9ea --- /dev/null +++ b/samples/directx/d3dsample.hpp @@ -0,0 +1,185 @@ +#include +#include +#include + +#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 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((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; +}; + + +#define ENTRY_POINT(type, title) \ +static void help() \ +{ \ + printf( \ + "\nSample 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 }" \ +}; \ + \ + \ +int main(int argc, char** argv) \ +{ \ + cv::CommandLineParser parser(argc, argv, keys); \ + bool useCamera = parser.has("camera"); \ + string file = parser.get("file"); \ + bool showHelp = parser.get("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; \ + \ + type 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; \ + } \ +} diff --git a/samples/directx/winapp.hpp b/samples/directx/winapp.hpp index b7ca9f6e41..15e87788cf 100644 --- a/samples/directx/winapp.hpp +++ b/samples/directx/winapp.hpp @@ -5,8 +5,6 @@ #define WINCLASS "WinAppWnd" -#define SAFE_RELEASE(p) if (p) { p->Release(); p = NULL; } - class WinApp { public: @@ -16,14 +14,13 @@ public: m_height = height; m_window_name = window_name; m_hInstance = ::GetModuleHandle(NULL); + m_hWnd = 0; } - virtual ~WinApp() - { - ::UnregisterClass(WINCLASS, m_hInstance); - } + virtual ~WinApp() {} + - int Create() + virtual int create() { WNDCLASSEX wcex; @@ -41,9 +38,12 @@ public: wcex.hIconSm = 0; ATOM wc = ::RegisterClassEx(&wcex); + if (!wc) + return -1; RECT rc = { 0, 0, m_width, m_height }; - ::AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false); + if(!::AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false)) + return -1; m_hWnd = ::CreateWindow( (LPCTSTR)wc, m_window_name.c_str(), @@ -58,10 +58,9 @@ public: ::UpdateWindow(m_hWnd); ::SetFocus(m_hWnd); - return init(); - } + return 0; + } // create() - virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) = 0; int run() { @@ -78,23 +77,32 @@ public: } else { - render(); + idle(); } } return static_cast(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 = ((LPCREATESTRUCT)lParam); - pWnd = (WinApp*)(pCreateStruct->lpCreateParams); - ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pWnd); + LPCREATESTRUCT pCreateStruct = reinterpret_cast(lParam); + pWnd = static_cast(pCreateStruct->lpCreateParams); + ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(pWnd)); } pWnd = GetObjectFromWindow(hWnd); @@ -103,15 +111,14 @@ protected: 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); - } + inline static WinApp* GetObjectFromWindow(HWND hWnd) { return (WinApp*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); } - virtual int init() = 0; - virtual int render() = 0; + // 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;