Qt+OpenCV use cv::ogl::texture2D::copyFrom( cv::cuda::GpuMat) to get texture directly

I am writing a module which gets cv::cuda::GpuMat data on gpu and draw it on QOpenGLWidget. To accelarate the speed, I want to avoid downloading data from device to host.

This is the main code

void MyPainter::drawImage(QMatrix4x4 transform_matrix, const cv::Mat &img)
{
    if(parent->context() == 0){
        parent->makeCurrent();
    }

    shader_program->bind();

    cv::cuda::GpuMat gpumat_img;
    qDebug() << "upload img....";
    gpumat_img.upload(img);      //  for test, because other modules are unfished
    qDebug() << gpumat_img.empty() << gpumat_img.type() << "Finish upload";
    qDebug() << gpumat_img.size().width << gpumat_img.size().height;

    cv::ogl::Texture2D test_texture;
    qDebug() << "copy to texture memory....";
    test_texture.copyFrom(gpumat_img);  // here raise an error. 

    qDebug() << "Finish copy";

    test_texture.bind();
    vbo.bind();

    qDebug() << test_texture.size().width << test_texture.size().height;
    shader_program->setUniformValue("matrix", transform_matrix);
    shader_program->enableAttributeArray(MYSHADER_VERTEX_ATTRIBUTE);
    shader_program->enableAttributeArray(MYSHADER_TEXCOORD_ATTRIBUTE);
    shader_program->setAttributeBuffer(MYSHADER_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 2);
    shader_program->setAttributeBuffer(MYSHADER_TEXCOORD_ATTRIBUTE, GL_FLOAT, 0, 2);

    QOpenGLFunctions *gl_function_ptr = QOpenGLContext::currentContext()->functions();
    gl_function_ptr->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    shader_program->release();
    test_texture.release();
    vbo.release();

}

The error tells “OpenCV(4.6.0) Error: Gpu API call (OS call failed or operation not supported on this OS) in `anonymous-namespace’::CudaResource::registerBuffer, file D:\lib\opencv_my\source\opencv-4.6.0\modules\core\src\opengl.cpp, line 176”

But if I use the cv::ogl::texture2D::copyFrom(cv::Mat) instead of cv::ogl::texture2D::copyFrom(cv::cuda::GpuMat), it can work well.

I read some source code of opencv and find the error is appear at here:

    void CudaResource::registerBuffer(GLuint buffer)
    {
        CV_DbgAssert( buffer != 0 );

        if (buffer_ == buffer)
            return;

        cudaGraphicsResource_t resource;
        cudaSafeCall( cudaGraphicsGLRegisterBuffer(&resource, buffer, cudaGraphicsMapFlagsNone) );                   // here raise the error

        release();

        resource_ = resource;
        buffer_ = buffer;
    }

But i can’t find cudaGraphicsGLRegisterBuffer().

My environment

Qt 7.0.0
OpenCV 4.6.0
CUDA 11.6

Apologize for my poor English.

1 Like