35 : m_lock{lock}, m_dvpFormat{dvpFormat}, m_name{
name} {}
38 NvDvpFormat m_dvpFormat{};
39 const char* m_name{
"DVP-GL"};
43 QOpenGLContext* m_glCtx{};
45 NvDvpContextHandle m_dvpCtx{};
46 NvDvpResourceHandle m_dvpTex{};
47 QRhiTexture* m_ownTexture{};
48 bool m_threadStarted{};
50 static constexpr int kMaxFailures = 8;
54 static constexpr std::size_t kSlotCount = 3;
58 NvDvpResourceHandle dvpBuf{};
61 std::array<Slot, kSlotCount> m_slots{};
63 uint32_t m_sysmemBytes{};
64 uint32_t m_sysmemStrideBytes{};
68 const char*
name() const noexcept
override {
return m_name; }
77 =
static_cast<const QRhiGles2NativeHandles*
>(cfg.rhi->nativeHandles());
78 if(!native || !native->context)
80 m_glCtx = native->context;
87 if(!cfg.state || !cfg.state->surface)
89 qWarning() <<
"DVP-IN(GL): no offscreen surface available to bind the "
90 "GL context; cannot init DVP";
93 if(!m_glCtx->makeCurrent(cfg.state->surface))
95 qWarning() <<
"DVP-IN(GL): makeCurrent() failed; cannot bind DVP to "
104 m_texW = texSize.width();
105 m_texH = texSize.height();
106 m_sysmemStrideBytes =
static_cast<uint32_t
>(m_texW) * 4u;
107 m_sysmemBytes = m_sysmemStrideBytes *
static_cast<uint32_t
>(m_texH);
111 qWarning() <<
"DVP-IN(GL): texture byte size" << m_sysmemBytes
122 = cfg.rhi->newTexture(cfg.
outputTexture->format(), texSize, 1,
123 QRhiTexture::RenderTarget);
124 if(!m_ownTexture || !m_ownTexture->create())
126 qWarning() <<
"DVP-IN(GL): could not create render-target texture";
128 m_ownTexture =
nullptr;
132 auto nt = m_ownTexture->nativeTexture();
136 m_ownTexture =
nullptr;
139 const uint32_t glTexId = uint32_t(nt.object);
141 qDebug() <<
"DVP-IN(GL): loading dvp.dll...";
142 if(nv_dvp_init_gl(&m_dvpCtx) != NV_DVP_SUCCESS || !m_dvpCtx)
144 qWarning() <<
"DVP-IN(GL): init failed:"
145 << nv_dvp_get_error_string(m_dvpCtx);
151 m_ownTexture =
nullptr;
154 if(nv_dvp_thread_begin(m_dvpCtx) != NV_DVP_SUCCESS)
159 m_threadStarted =
true;
160 qDebug() <<
"DVP-IN(GL): dvp.dll loaded + GL context bound";
162 const NvDvpFormat dvpFmt = m_dvpFormat;
164 if(nv_dvp_register_gl_texture(
165 m_dvpCtx, glTexId, dvpFmt, uint32_t(m_texW), uint32_t(m_texH),
169 qWarning() <<
"DVP-IN(GL): register_gl_texture failed:"
170 << nv_dvp_get_error_string(m_dvpCtx);
175 for(
auto& slot : m_slots)
177 slot.sysmem = nv_dvp_aligned_alloc(m_sysmemBytes);
183 std::memset(slot.sysmem, 0, m_sysmemBytes);
184 if(!m_lock.lock(slot.sysmem, m_sysmemBytes))
189 slot.dmaLocked =
true;
190 if(nv_dvp_register_sysmem_buffer(
191 m_dvpCtx, slot.sysmem, dvpFmt, uint32_t(m_texW),
192 uint32_t(m_texH), m_sysmemStrideBytes, &slot.dvpBuf)
208 if(!qEnvironmentVariableIsSet(
"SCORE_GFX_DVP_NO_PROBE"))
210 if(m_slots[0].dvpBuf && m_dvpTex
211 && nv_dvp_copy_buffer_to_texture(m_dvpCtx, m_slots[0].dvpBuf, m_dvpTex)
214 qWarning() <<
"DVP-IN(GL): probe transfer failed:"
215 << nv_dvp_get_error_string(m_dvpCtx)
216 <<
"- DVP capture unusable here, falling back";
224 void release()
override
228 if(m_dvpCtx && m_glCtx && cfg.state && cfg.state->surface
229 && QOpenGLContext::currentContext() != m_glCtx)
230 m_glCtx->makeCurrent(cfg.state->surface);
234 for(
auto& slot : m_slots)
238 nv_dvp_unregister(m_dvpCtx, slot.dvpBuf);
239 slot.dvpBuf =
nullptr;
243 m_lock.unlock(slot.sysmem, m_sysmemBytes);
244 slot.dmaLocked =
false;
248 nv_dvp_aligned_free(slot.sysmem);
249 slot.sysmem =
nullptr;
254 nv_dvp_unregister(m_dvpCtx, m_dvpTex);
259 nv_dvp_thread_end(m_dvpCtx);
260 m_threadStarted =
false;
262 nv_dvp_shutdown(m_dvpCtx);
269 m_ownTexture =
nullptr;
273 std::size_t
slotCount() const noexcept
override {
return kSlotCount; }
276 return i < kSlotCount ? m_slots[i].sysmem :
nullptr;
290 if(!m_slots[i].dvpBuf || !m_dvpTex)
292 m_publisher.publish(i);
303 if(!m_dvpCtx || !m_dvpTex)
308 if(
const int i = m_publisher.
consume(); i >= 0)
312 if(nv_dvp_copy_buffer_to_texture(m_dvpCtx, m_slots[i].dvpBuf, m_dvpTex)
318 if(++m_failures <= 3)
319 qWarning() <<
"DVP-IN(GL): copy_buffer_to_texture failed:"
320 << nv_dvp_get_error_string(m_dvpCtx);
321 if(m_failures == kMaxFailures)
324 qWarning() <<
"DVP-IN(GL): giving up after" << kMaxFailures
325 <<
"consecutive failures; the DVP capture rung is "
326 "unusable on this setup";
336 void releaseAfterRender()
override { }
340 bool healthy() const noexcept {
return !m_dead; }