summaryrefslogtreecommitdiffstats
path: root/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp')
-rw-r--r--src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp434
1 files changed, 237 insertions, 197 deletions
diff --git a/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp b/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp
index 96c7836cf..cc14cd419 100644
--- a/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp
+++ b/src/plugins/multimedia/windows/evr/evrd3dpresentengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "evrd3dpresentengine_p.h"
@@ -50,8 +14,7 @@
#include <d3d11_1.h>
-#include <private/qrhi_p.h>
-#include <private/qrhid3d11_p.h>
+#include <rhi/qrhi.h>
#if QT_CONFIG(opengl)
# include <qopenglcontext.h>
@@ -61,19 +24,18 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(qLcEvrD3DPresentEngine, "qt.multimedia.evrd3dpresentengine")
+static Q_LOGGING_CATEGORY(qLcEvrD3DPresentEngine, "qt.multimedia.evrd3dpresentengine")
class IMFSampleVideoBuffer: public QAbstractVideoBuffer
{
public:
- IMFSampleVideoBuffer(QWindowsIUPointer<IDirect3DDevice9Ex> device,
- IMFSample *sample, QRhi *rhi, QVideoFrame::HandleType type = QVideoFrame::NoHandle)
+ IMFSampleVideoBuffer(ComPtr<IDirect3DDevice9Ex> device,
+ const ComPtr<IMFSample> &sample, QRhi *rhi, QVideoFrame::HandleType type = QVideoFrame::NoHandle)
: QAbstractVideoBuffer(type, rhi)
, m_device(device)
+ , m_sample(sample)
, m_mapMode(QVideoFrame::NotMapped)
{
- sample->AddRef();
- m_sample.reset(sample);
}
~IMFSampleVideoBuffer() override
@@ -95,24 +57,24 @@ public:
return {};
} else {
- QWindowsIUPointer<IMFMediaBuffer> buffer;
- HRESULT hr = m_sample->GetBufferByIndex(0, buffer.address());
+ ComPtr<IMFMediaBuffer> buffer;
+ HRESULT hr = m_sample->GetBufferByIndex(0, buffer.GetAddressOf());
if (FAILED(hr))
return {};
- QWindowsIUPointer<IDirect3DSurface9> surface;
- hr = MFGetService(buffer.get(), MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void **)(surface.address()));
+ ComPtr<IDirect3DSurface9> surface;
+ hr = MFGetService(buffer.Get(), MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void **)(surface.GetAddressOf()));
if (FAILED(hr))
return {};
if (FAILED(surface->GetDesc(&desc)))
return {};
- if (FAILED(m_device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, m_memSurface.address(), nullptr)))
+ if (FAILED(m_device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, m_memSurface.GetAddressOf(), nullptr)))
return {};
- if (FAILED(m_device->GetRenderTargetData(surface.get(), m_memSurface.get()))) {
- m_memSurface.reset();
+ if (FAILED(m_device->GetRenderTargetData(surface.Get(), m_memSurface.Get()))) {
+ m_memSurface.Reset();
return {};
}
}
@@ -142,76 +104,114 @@ public:
}
protected:
- QWindowsIUPointer<IDirect3DDevice9Ex> m_device;
- QWindowsIUPointer<IMFSample> m_sample;
+ ComPtr<IDirect3DDevice9Ex> m_device;
+ ComPtr<IMFSample> m_sample;
private:
- QWindowsIUPointer<IDirect3DSurface9> m_memSurface;
+ ComPtr<IDirect3DSurface9> m_memSurface;
QVideoFrame::MapMode m_mapMode;
};
+class QVideoFrameD3D11Textures: public QVideoFrameTextures
+{
+public:
+ QVideoFrameD3D11Textures(std::unique_ptr<QRhiTexture> &&tex, ComPtr<ID3D11Texture2D> &&d3d11tex)
+ : m_tex(std::move(tex))
+ , m_d3d11tex(std::move(d3d11tex))
+ {}
+
+ QRhiTexture *texture(uint plane) const override
+ {
+ return plane == 0 ? m_tex.get() : nullptr;
+ };
+
+private:
+ std::unique_ptr<QRhiTexture> m_tex;
+ ComPtr<ID3D11Texture2D> m_d3d11tex;
+};
+
class D3D11TextureVideoBuffer: public IMFSampleVideoBuffer
{
public:
- D3D11TextureVideoBuffer(QWindowsIUPointer<IDirect3DDevice9Ex> device, IMFSample *sample,
- QWindowsIUPointer<ID3D11Texture2D> d2d11tex, QRhi *rhi)
- : IMFSampleVideoBuffer(device, sample, rhi, QVideoFrame::RhiTextureHandle)
- , m_d2d11tex(d2d11tex)
+ D3D11TextureVideoBuffer(ComPtr<IDirect3DDevice9Ex> device, const ComPtr<IMFSample> &sample,
+ HANDLE sharedHandle, QRhi *rhi)
+ : IMFSampleVideoBuffer(std::move(device), sample, rhi, QVideoFrame::RhiTextureHandle)
+ , m_sharedHandle(sharedHandle)
{}
- std::unique_ptr<QRhiTexture> texture(int plane) const override
+ std::unique_ptr<QVideoFrameTextures> mapTextures(QRhi *rhi) override
{
- if (!m_rhi || !m_d2d11tex || plane > 0)
+ if (!rhi || rhi->backend() != QRhi::D3D11)
return {};
- D3D11_TEXTURE2D_DESC desc = {};
- m_d2d11tex->GetDesc(&desc);
- QRhiTexture::Format format;
- if (desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM)
- format = QRhiTexture::BGRA8;
- else if (desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM)
- format = QRhiTexture::RGBA8;
- else
+
+ auto nh = static_cast<const QRhiD3D11NativeHandles*>(rhi->nativeHandles());
+ if (!nh)
+ return {};
+
+ auto dev = reinterpret_cast<ID3D11Device *>(nh->dev);
+ if (!dev)
return {};
- std::unique_ptr<QRhiTexture> tex(m_rhi->newTexture(format, QSize{int(desc.Width), int(desc.Height)}, 1, {}));
- tex->createFrom({quint64(m_d2d11tex.get()), 0});
- return tex;
+ ComPtr<ID3D11Texture2D> d3d11tex;
+ HRESULT hr = dev->OpenSharedResource(m_sharedHandle, __uuidof(ID3D11Texture2D), (void**)(d3d11tex.GetAddressOf()));
+ if (SUCCEEDED(hr)) {
+ D3D11_TEXTURE2D_DESC desc = {};
+ d3d11tex->GetDesc(&desc);
+ QRhiTexture::Format format;
+ if (desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM)
+ format = QRhiTexture::BGRA8;
+ else if (desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM)
+ format = QRhiTexture::RGBA8;
+ else
+ return {};
+
+ std::unique_ptr<QRhiTexture> tex(rhi->newTexture(format, QSize{int(desc.Width), int(desc.Height)}, 1, {}));
+ tex->createFrom({quint64(d3d11tex.Get()), 0});
+ return std::make_unique<QVideoFrameD3D11Textures>(std::move(tex), std::move(d3d11tex));
+
+ } else {
+ qCDebug(qLcEvrD3DPresentEngine) << "Failed to obtain D3D11Texture2D from D3D9Texture2D handle";
+ }
+ return {};
}
private:
- QWindowsIUPointer<ID3D11Texture2D> m_d2d11tex;
+ HANDLE m_sharedHandle = nullptr;
};
#if QT_CONFIG(opengl)
-class OpenGlVideoBuffer: public IMFSampleVideoBuffer
+class QVideoFrameOpenGlTextures : public QVideoFrameTextures
{
+ struct InterOpHandles {
+ GLuint textureName = 0;
+ HANDLE device = nullptr;
+ HANDLE texture = nullptr;
+ };
+
public:
- OpenGlVideoBuffer(QWindowsIUPointer<IDirect3DDevice9Ex> device, IMFSample *sample,
- const WglNvDxInterop &wglNvDxInterop, HANDLE sharedHandle, QRhi *rhi)
- : IMFSampleVideoBuffer(device, sample, rhi, QVideoFrame::RhiTextureHandle)
- , m_sharedHandle(sharedHandle)
- , m_wgl(wglNvDxInterop)
- {}
+ Q_DISABLE_COPY(QVideoFrameOpenGlTextures);
- ~OpenGlVideoBuffer() override
- {
- if (!m_d3dglHandle)
- return;
+ QVideoFrameOpenGlTextures(std::unique_ptr<QRhiTexture> &&tex, const WglNvDxInterop &wgl, InterOpHandles &handles)
+ : m_tex(std::move(tex))
+ , m_wgl(wgl)
+ , m_handles(handles)
+ {}
+ ~QVideoFrameOpenGlTextures() override {
if (QOpenGLContext::currentContext()) {
- if (m_glHandle) {
- if (!m_wgl.wglDXUnlockObjectsNV(m_d3dglHandle, 1, &m_glHandle))
- qCDebug(qLcEvrD3DPresentEngine) << "Failed to unlock OpenGL texture";
- if (!m_wgl.wglDXUnregisterObjectNV(m_d3dglHandle, m_glHandle))
- qCDebug(qLcEvrD3DPresentEngine) << "Failed to unregister OpenGL texture";
-
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- if (funcs)
- funcs->glDeleteTextures(1, &m_glTextureName);
- else
- qCDebug(qLcEvrD3DPresentEngine) << "Could not delete texture, OpenGL context functions missing";
- }
- if (!m_wgl.wglDXCloseDeviceNV(m_d3dglHandle))
+ if (!m_wgl.wglDXUnlockObjectsNV(m_handles.device, 1, &m_handles.texture))
+ qCDebug(qLcEvrD3DPresentEngine) << "Failed to unlock OpenGL texture";
+
+ if (!m_wgl.wglDXUnregisterObjectNV(m_handles.device, m_handles.texture))
+ qCDebug(qLcEvrD3DPresentEngine) << "Failed to unregister OpenGL texture";
+
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ if (funcs)
+ funcs->glDeleteTextures(1, &m_handles.textureName);
+ else
+ qCDebug(qLcEvrD3DPresentEngine) << "Could not delete texture, OpenGL context functions missing";
+
+ if (!m_wgl.wglDXCloseDeviceNV(m_handles.device))
qCDebug(qLcEvrD3DPresentEngine) << "Failed to close D3D-GL device";
} else {
@@ -219,87 +219,106 @@ public:
}
}
- void mapTextures() override
+ static std::unique_ptr<QVideoFrameOpenGlTextures> create(const WglNvDxInterop &wgl, QRhi *rhi,
+ IDirect3DDevice9Ex *device, IDirect3DTexture9 *texture,
+ HANDLE sharedHandle)
{
- if (!QOpenGLContext::currentContext())
- return;
-
- if (m_d3dglHandle)
- return;
-
- QWindowsIUPointer<IMFMediaBuffer> buffer;
- HRESULT hr = m_sample->GetBufferByIndex(0, buffer.address());
- if (FAILED(hr))
- return;
-
- QWindowsIUPointer<IDirect3DSurface9> surface;
- hr = MFGetService(buffer.get(), MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void **)(surface.address()));
- if (FAILED(hr))
- return;
+ if (!rhi || rhi->backend() != QRhi::OpenGLES2)
+ return {};
- hr = surface->GetContainer(IID_IDirect3DTexture9, (void **)m_texture.address());
- if (FAILED(hr))
- return;
+ if (!QOpenGLContext::currentContext())
+ return {};
- m_d3dglHandle = m_wgl.wglDXOpenDeviceNV(m_device.get());
- if (!m_d3dglHandle) {
- m_texture.reset();
+ InterOpHandles handles = {};
+ handles.device = wgl.wglDXOpenDeviceNV(device);
+ if (!handles.device) {
qCDebug(qLcEvrD3DPresentEngine) << "Failed to open D3D device";
- return;
+ return {};
}
- m_wgl.wglDXSetResourceShareHandleNV(m_texture.get(), m_sharedHandle);
+ wgl.wglDXSetResourceShareHandleNV(texture, sharedHandle);
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
if (funcs) {
- funcs->glGenTextures(1, &m_glTextureName);
- m_glHandle = m_wgl.wglDXRegisterObjectNV(m_d3dglHandle, m_texture.get(), m_glTextureName,
- GL_TEXTURE_2D, WglNvDxInterop::WGL_ACCESS_READ_ONLY_NV);
- if (m_glHandle) {
- if (m_wgl.wglDXLockObjectsNV(m_d3dglHandle, 1, &m_glHandle))
- return;
+ funcs->glGenTextures(1, &handles.textureName);
+ handles.texture = wgl.wglDXRegisterObjectNV(handles.device, texture, handles.textureName,
+ GL_TEXTURE_2D, WglNvDxInterop::WGL_ACCESS_READ_ONLY_NV);
+ if (handles.texture) {
+ if (wgl.wglDXLockObjectsNV(handles.device, 1, &handles.texture)) {
+ D3DSURFACE_DESC desc;
+ texture->GetLevelDesc(0, &desc);
+ QRhiTexture::Format format;
+ if (desc.Format == D3DFMT_A8R8G8B8)
+ format = QRhiTexture::BGRA8;
+ else if (desc.Format == D3DFMT_A8B8G8R8)
+ format = QRhiTexture::RGBA8;
+ else
+ return {};
+
+ std::unique_ptr<QRhiTexture> tex(rhi->newTexture(format, QSize{int(desc.Width), int(desc.Height)}, 1, {}));
+ tex->createFrom({quint64(handles.textureName), 0});
+ return std::make_unique<QVideoFrameOpenGlTextures>(std::move(tex), wgl, handles);
+ }
qCDebug(qLcEvrD3DPresentEngine) << "Failed to lock OpenGL texture";
- m_wgl.wglDXUnregisterObjectNV(m_d3dglHandle, m_glHandle);
- m_glHandle = nullptr;
+ wgl.wglDXUnregisterObjectNV(handles.device, handles.texture);
} else {
qCDebug(qLcEvrD3DPresentEngine) << "Could not register D3D9 texture in OpenGL";
}
- funcs->glDeleteTextures(1, &m_glTextureName);
- m_glTextureName = 0;
+ funcs->glDeleteTextures(1, &handles.textureName);
} else {
qCDebug(qLcEvrD3DPresentEngine) << "Failed generate texture names, OpenGL context functions missing";
}
+ return {};
}
- std::unique_ptr<QRhiTexture> texture(int plane) const override
+ QRhiTexture *texture(uint plane) const override
{
- if (!m_rhi || !m_texture || plane > 0)
- return {};
+ return plane == 0 ? m_tex.get() : nullptr;
+ };
+private:
+ std::unique_ptr<QRhiTexture> m_tex;
+ WglNvDxInterop m_wgl;
+ InterOpHandles m_handles;
+};
- D3DSURFACE_DESC desc;
- m_texture->GetLevelDesc(0, &desc);
- QRhiTexture::Format format;
- if (desc.Format == D3DFMT_A8R8G8B8)
- format = QRhiTexture::BGRA8;
- else if (desc.Format == D3DFMT_A8B8G8R8)
- format = QRhiTexture::RGBA8;
- else
- return {};
+class OpenGlVideoBuffer: public IMFSampleVideoBuffer
+{
+public:
+ OpenGlVideoBuffer(ComPtr<IDirect3DDevice9Ex> device, const ComPtr<IMFSample> &sample,
+ const WglNvDxInterop &wglNvDxInterop, HANDLE sharedHandle, QRhi *rhi)
+ : IMFSampleVideoBuffer(std::move(device), sample, rhi, QVideoFrame::RhiTextureHandle)
+ , m_sharedHandle(sharedHandle)
+ , m_wgl(wglNvDxInterop)
+ {}
+
+ std::unique_ptr<QVideoFrameTextures> mapTextures(QRhi *rhi) override
+ {
+ if (!m_texture) {
+ ComPtr<IMFMediaBuffer> buffer;
+ HRESULT hr = m_sample->GetBufferByIndex(0, buffer.GetAddressOf());
+ if (FAILED(hr))
+ return {};
+
+ ComPtr<IDirect3DSurface9> surface;
+ hr = MFGetService(buffer.Get(), MR_BUFFER_SERVICE, IID_IDirect3DSurface9,
+ (void **)(surface.GetAddressOf()));
+ if (FAILED(hr))
+ return {};
- std::unique_ptr<QRhiTexture> tex(m_rhi->newTexture(format, QSize{int(desc.Width), int(desc.Height)}, 1, {}));
- tex->createFrom({quint64(m_glTextureName), 0});
- return tex;
+ hr = surface->GetContainer(IID_IDirect3DTexture9, (void **)m_texture.GetAddressOf());
+ if (FAILED(hr))
+ return {};
+ }
+
+ return QVideoFrameOpenGlTextures::create(m_wgl, rhi, m_device.Get(), m_texture.Get(), m_sharedHandle);
}
private:
- GLuint m_glTextureName = 0;
- HANDLE m_d3dglHandle = nullptr;
- HANDLE m_glHandle = nullptr;
HANDLE m_sharedHandle = nullptr;
WglNvDxInterop m_wgl;
- QWindowsIUPointer<IDirect3DTexture9> m_texture;
+ ComPtr<IDirect3DTexture9> m_texture;
};
#endif
@@ -323,9 +342,9 @@ void D3DPresentEngine::setSink(QVideoSink *sink)
m_sink = sink;
releaseResources();
- m_device.reset();
- m_devices.reset();
- m_D3D9.reset();
+ m_device.Reset();
+ m_devices.Reset();
+ m_D3D9.Reset();
if (!m_sink)
return;
@@ -343,10 +362,10 @@ void D3DPresentEngine::setSink(QVideoSink *sink)
HRESULT D3DPresentEngine::initializeD3D()
{
- HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, m_D3D9.address());
+ HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, m_D3D9.GetAddressOf());
if (SUCCEEDED(hr))
- hr = DXVA2CreateDirect3DDeviceManager9(&m_deviceResetToken, m_devices.address());
+ hr = DXVA2CreateDirect3DDeviceManager9(&m_deviceResetToken, m_devices.GetAddressOf());
return hr;
}
@@ -391,8 +410,16 @@ static bool readWglNvDxInteropProc(WglNvDxInterop &f)
return false;
}
- auto dc = ::GetDC(::GetShellWindow());
- if (!strstr(wglGetExtensionsStringARB(dc), "WGL_NV_DX_interop")) {
+ HWND hwnd = ::GetShellWindow();
+ auto dc = ::GetDC(hwnd);
+
+ const char *wglExtString = wglGetExtensionsStringARB(dc);
+ if (!wglExtString)
+ qCDebug(qLcEvrD3DPresentEngine) << "WGL extensions missing (wglGetExtensionsStringARB returned null)";
+
+ bool hasExtension = wglExtString && strstr(wglExtString, "WGL_NV_DX_interop");
+ ReleaseDC(hwnd, dc);
+ if (!hasExtension) {
qCDebug(qLcEvrD3DPresentEngine) << "WGL_NV_DX_interop missing";
return false;
}
@@ -407,6 +434,20 @@ static bool readWglNvDxInteropProc(WglNvDxInterop &f)
}
#endif
+namespace {
+
+bool hwTextureRenderingEnabled() {
+ // add possibility for an user to opt-out HW video rendering
+ // using the same env. variable as for FFmpeg backend
+ static bool isDisableConversionSet = false;
+ static const int disableHwConversion = qEnvironmentVariableIntValue(
+ "QT_DISABLE_HW_TEXTURES_CONVERSION", &isDisableConversionSet);
+
+ return !isDisableConversionSet || !disableHwConversion;
+}
+
+}
+
HRESULT D3DPresentEngine::createD3DDevice()
{
if (!m_D3D9 || !m_devices)
@@ -414,23 +455,26 @@ HRESULT D3DPresentEngine::createD3DDevice()
m_useTextureRendering = false;
UINT adapterID = 0;
- QRhi *rhi = m_sink ? m_sink->rhi() : nullptr;
- if (rhi) {
- if (rhi->backend() == QRhi::D3D11) {
- m_useTextureRendering = findD3D11AdapterID(*rhi, m_D3D9.get(), adapterID);
+
+ if (hwTextureRenderingEnabled()) {
+ QRhi *rhi = m_sink ? m_sink->rhi() : nullptr;
+ if (rhi) {
+ if (rhi->backend() == QRhi::D3D11) {
+ m_useTextureRendering = findD3D11AdapterID(*rhi, m_D3D9.Get(), adapterID);
#if QT_CONFIG(opengl)
- } else if (rhi->backend() == QRhi::OpenGLES2) {
- m_useTextureRendering = readWglNvDxInteropProc(m_wglNvDxInterop);
+ } else if (rhi->backend() == QRhi::OpenGLES2) {
+ m_useTextureRendering = readWglNvDxInteropProc(m_wglNvDxInterop);
#endif
+ } else {
+ qCDebug(qLcEvrD3DPresentEngine) << "Not supported RHI backend type";
+ }
} else {
- qCDebug(qLcEvrD3DPresentEngine) << "Not supported RHI backend type";
+ qCDebug(qLcEvrD3DPresentEngine) << "No RHI associated with this sink";
}
- } else {
- qCDebug(qLcEvrD3DPresentEngine) << "No RHI associated with this sink";
- }
- if (!m_useTextureRendering)
- qCDebug(qLcEvrD3DPresentEngine) << "Could not find compatible RHI adapter, zero copy disabled";
+ if (!m_useTextureRendering)
+ qCDebug(qLcEvrD3DPresentEngine) << "Could not find compatible RHI adapter, zero copy disabled";
+ }
D3DCAPS9 ddCaps;
ZeroMemory(&ddCaps, sizeof(ddCaps));
@@ -458,7 +502,7 @@ HRESULT D3DPresentEngine::createD3DDevice()
pp.Flags = D3DPRESENTFLAG_VIDEO;
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
- QWindowsIUPointer<IDirect3DDevice9Ex> device;
+ ComPtr<IDirect3DDevice9Ex> device;
hr = m_D3D9->CreateDeviceEx(
adapterID,
@@ -467,7 +511,7 @@ HRESULT D3DPresentEngine::createD3DDevice()
vp | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
&pp,
NULL,
- device.address()
+ device.GetAddressOf()
);
if (FAILED(hr))
return hr;
@@ -476,7 +520,7 @@ HRESULT D3DPresentEngine::createD3DDevice()
if (FAILED(hr))
return hr;
- hr = m_devices->ResetDevice(device.get(), m_deviceResetToken);
+ hr = m_devices->ResetDevice(device.Get(), m_deviceResetToken);
if (FAILED(hr))
return hr;
@@ -486,7 +530,7 @@ HRESULT D3DPresentEngine::createD3DDevice()
bool D3DPresentEngine::isValid() const
{
- return m_device.get() != nullptr;
+ return m_device.Get() != nullptr;
}
void D3DPresentEngine::releaseResources()
@@ -502,7 +546,7 @@ HRESULT D3DPresentEngine::getService(REFGUID, REFIID riid, void** ppv)
if (!m_devices) {
hr = MF_E_UNSUPPORTED_SERVICE;
} else {
- *ppv = m_devices.get();
+ *ppv = m_devices.Get();
m_devices->AddRef();
}
} else {
@@ -548,7 +592,9 @@ HRESULT D3DPresentEngine::checkFormat(D3DFORMAT format)
return ok ? S_OK : D3DERR_NOTAVAILABLE;
}
-HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList<IMFSample*> &videoSampleQueue)
+HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format,
+ QList<ComPtr<IMFSample>> &videoSampleQueue,
+ QSize frameSize)
{
if (!format || !m_device)
return MF_E_UNEXPECTED;
@@ -561,6 +607,11 @@ HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList<IMFSamp
if (FAILED(hr))
return hr;
+ if (frameSize.isValid() && !frameSize.isEmpty()) {
+ width = frameSize.width();
+ height = frameSize.height();
+ }
+
DWORD d3dFormat = 0;
hr = qt_evr_getFourCC(format, &d3dFormat);
if (FAILED(hr))
@@ -575,24 +626,24 @@ HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList<IMFSamp
for (int i = 0; i < PRESENTER_BUFFER_COUNT; i++) {
// texture ref cnt is increased by GetSurfaceLevel()/MFCreateVideoSampleFromSurface()
// below, so it will be destroyed only when the sample pool is released.
- QWindowsIUPointer<IDirect3DTexture9> texture;
+ ComPtr<IDirect3DTexture9> texture;
HANDLE sharedHandle = nullptr;
- hr = m_device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)d3dFormat, D3DPOOL_DEFAULT, texture.address(), &sharedHandle);
+ hr = m_device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)d3dFormat, D3DPOOL_DEFAULT, texture.GetAddressOf(), &sharedHandle);
if (FAILED(hr))
break;
- QWindowsIUPointer<IDirect3DSurface9> surface;
- hr = texture->GetSurfaceLevel(0, surface.address());
+ ComPtr<IDirect3DSurface9> surface;
+ hr = texture->GetSurfaceLevel(0, surface.GetAddressOf());
if (FAILED(hr))
break;
- QWindowsIUPointer<IMFSample> videoSample;
- hr = MFCreateVideoSampleFromSurface(surface.get(), videoSample.address());
+ ComPtr<IMFSample> videoSample;
+ hr = MFCreateVideoSampleFromSurface(surface.Get(), videoSample.GetAddressOf());
if (FAILED(hr))
break;
- m_sampleTextureHandle[i] = {videoSample.get(), sharedHandle};
- videoSampleQueue.append(videoSample.release());
+ m_sampleTextureHandle[i] = {videoSample.Get(), sharedHandle};
+ videoSampleQueue.append(videoSample);
}
if (SUCCEEDED(hr)) {
@@ -604,32 +655,21 @@ HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList<IMFSamp
return hr;
}
-QVideoFrame D3DPresentEngine::makeVideoFrame(IMFSample *sample)
+QVideoFrame D3DPresentEngine::makeVideoFrame(const ComPtr<IMFSample> &sample)
{
if (!sample)
return {};
HANDLE sharedHandle = nullptr;
for (const auto &p : m_sampleTextureHandle)
- if (p.first == sample)
+ if (p.first == sample.Get())
sharedHandle = p.second;
QAbstractVideoBuffer *vb = nullptr;
QRhi *rhi = m_sink ? m_sink->rhi() : nullptr;
if (m_useTextureRendering && sharedHandle && rhi) {
if (rhi->backend() == QRhi::D3D11) {
- auto nh = static_cast<const QRhiD3D11NativeHandles*>(rhi->nativeHandles());
- if (nh) {
- auto dev = reinterpret_cast<ID3D11Device *>(nh->dev);
- if (dev) {
- QWindowsIUPointer<ID3D11Texture2D> d3d11tex;
- HRESULT hr = dev->OpenSharedResource(sharedHandle, __uuidof(ID3D11Texture2D), (void**)(d3d11tex.address()));
- if (SUCCEEDED(hr))
- vb = new D3D11TextureVideoBuffer(m_device, sample, d3d11tex, rhi);
- else
- qCDebug(qLcEvrD3DPresentEngine) << "Failed to obtain D3D11Texture2D from D3D9Texture2D handle";
- }
- }
+ vb = new D3D11TextureVideoBuffer(m_device, sample, sharedHandle, rhi);
#if QT_CONFIG(opengl)
} else if (rhi->backend() == QRhi::OpenGLES2) {
vb = new OpenGlVideoBuffer(m_device, sample, m_wglNvDxInterop, sharedHandle, rhi);