Esempio n. 1
0
    GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext = 0)
        : m_display(0)
        , m_xPixmap(0)
        , m_glxPixmap(0)
        , m_glContext(0)
        , m_detachedContext(0)
        , m_detachedSurface(0)
        , m_textureIsYInverted(false)
        , m_hasAlpha(false)
    {
        GLXContext shareContextObject = 0;
        m_display = XOpenDisplay(0);

#if PLATFORM(QT)
        if (shareContext) {
#if 0
            // This code path requires QXcbNativeInterface::nativeResourceForContext() which is not availble in Qt5 on the build bots yet.
            QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface();
            shareContextObject = static_cast<GLXContext>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("glxcontext"), shareContext));
            if (!shareContextObject)
                return;
#else
            // This code path should be removed as soon as QXcbNativeInterface::nativeResourceForContext() can provide the GLXContext.
            QOpenGLContext* previousContext = QOpenGLContext::currentContext();
            QSurface* previousSurface = previousContext->surface();
            QSurface* currentSurface = shareContext->surface();
            shareContext->makeCurrent(currentSurface);

            shareContextObject = glXGetCurrentContext();

            previousContext->makeCurrent(previousSurface);
#endif
        }
#endif

        m_display = m_offScreenWindow.display();
        int attributes[] = {
            GLX_LEVEL, 0,
            GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
            GLX_RENDER_TYPE,   GLX_RGBA_BIT,
            GLX_RED_SIZE,      1,
            GLX_GREEN_SIZE,    1,
            GLX_BLUE_SIZE,     1,
            GLX_DOUBLEBUFFER,  True,
            None
        };

        int numReturned;
        m_fbConfigs = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &numReturned);
        // Create a GLX context for OpenGL rendering
        m_glContext = glXCreateNewContext(m_display, m_fbConfigs[0], GLX_RGBA_TYPE, shareContextObject, true);
    }
Esempio n. 2
0
void GLWidget::makeObject()
{
    static const int coords[6][4][3] = {
        { { +1, -1, -1 }, { -1, -1, -1 }, { -1, +1, -1 }, { +1, +1, -1 } },
        { { +1, +1, -1 }, { -1, +1, -1 }, { -1, +1, +1 }, { +1, +1, +1 } },
        { { +1, -1, +1 }, { +1, -1, -1 }, { +1, +1, -1 }, { +1, +1, +1 } },
        { { -1, -1, -1 }, { -1, -1, +1 }, { -1, +1, +1 }, { -1, +1, -1 } },
        { { +1, -1, +1 }, { -1, -1, +1 }, { -1, -1, -1 }, { +1, -1, -1 } },
        { { -1, -1, +1 }, { +1, -1, +1 }, { +1, +1, +1 }, { -1, +1, +1 } }
    };

    QElapsedTimer timer;
    timer.start();
#ifndef DISABLED_OPENMAX
    //loadWithOmx();

    QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface();
    Q_ASSERT(nativeInterface);
    EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay");
    EGLContext eglContext = nativeInterface->nativeResourceForContext("eglcontext", QOpenGLContext::currentContext());
#if 0
    eglImageVideo = getEGLImage(1920, 1080, eglDisplay, eglContext, textures[0]);
#endif
    for (int i = 0; i < 5; i++)
        textures[i] = 0;
    //QtConcurrent::run(video_decode_test, videoPath, eglImageVideo, eglDisplay);
    m_videoProc = new OMX_VideoProcessor(eglDisplay, eglContext, m_provider);
    connect(m_videoProc, SIGNAL(textureReady(uint)), this, SLOT(onTextureChanged(uint)));
    m_videoProc->setVideoPath("/home/pi/out.h264");
    m_videoProc->play();
#else
    for (int i = 0; i < 6; i++) {
        QPixmap pixmap(QString("%1%2.jpg").arg(prefix).arg(i));
        if (pixmap.isNull())
            LOG_ERROR(LOG_TAG, "Failed to load image!");
        textures[i] = bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA);
    }
#endif
    LOG_INFORMATION(LOG_TAG, "Elapsed: %lld.", timer.elapsed());

    for (int i = 0; i < 6; ++i) {
        for (int j = 0; j < 4; ++j) {
            texCoords.append
                (QVector2D(j == 0 || j == 3, j == 0 || j == 1));
            vertices.append
                (QVector3D(0.2 * coords[i][j][0], 0.2 * coords[i][j][1],
                           0.2 * coords[i][j][2]));
        }
    }
}
Esempio n. 3
0
OMX_TextureData* OMX_TextureProviderQGLWidget::instantiateTexture(QSize size)
{
    // TODO: Reimplement.
#if 0
    m_parent->makeCurrent();
    QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface();
    Q_ASSERT(nativeInterface);
    EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay");
    EGLContext eglContext = nativeInterface->nativeResourceForContext("eglcontext", QOpenGLContext::currentContext());
    GLuint texture;
    eglImageVideo = getEGLImage(size.width(), size.height(), eglDisplay, eglContext, texture);
    return texture;
#endif
    return 0;
}
Esempio n. 4
0
/*------------------------------------------------------------------------------
|    get_egl_context
+-----------------------------------------------------------------------------*/
EGLContext get_global_egl_context()
{
   QOpenGLContext* c = QOpenGLContext::globalShareContext();
   if (!c)
      return (void*)log_warn("Cannot get an OpenGL context.");

   QPlatformNativeInterface* nativeInterface =
         QGuiApplicationPrivate::platformIntegration()->nativeInterface();
   Q_ASSERT(nativeInterface);

   EGLContext eglc =
         nativeInterface->nativeResourceForContext("eglcontext", c);
   if (!eglc)
      log_warn("Couldn't get EGL context from currrent OpenGL context.");

   return eglc;
}
Esempio n. 5
0
void GLWidget::loadWithOmx()
{
    LOG_VERBOSE(LOG_TAG, "Loading with OMX.");
    QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface();
    Q_ASSERT(nativeInterface);
    EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay");
    EGLContext eglContext = nativeInterface->nativeResourceForContext("eglcontext", QOpenGLContext::currentContext());

    for (int i = 5; i < 6; i++) {
        QString fileAbsPath = QString("%1%2.jpg").arg(prefix).arg(i);
        OpenMAXILTextureLoader* omTextureLoader = OpenMAXILTextureLoader::intance();
        if (!omTextureLoader->loadTextureFromImage(fileAbsPath, eglDisplay, eglContext, textures[i])) {
            LOG_ERROR(LOG_TAG, "Failed to load image.");
        }
        else {
            LOG_INFORMATION(LOG_TAG, "Image %s successfully decoded and loaded.", qPrintable(fileAbsPath));
        }
    }
}
Esempio n. 6
0
    GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext = 0)
        : m_display(m_offScreenWindow.display())
        , m_xPixmap(0)
        , m_glxPixmap(0)
        , m_surface(0)
        , m_glxSurface(0)
        , m_glContext(0)
        , m_detachedContext(0)
        , m_detachedSurface(0)
        , m_fbConfig(0)
        , m_textureIsYInverted(false)
        , m_hasAlpha(false)
        , m_isReceiver(false)
    {
        GLXContext shareContextObject = 0;

#if PLATFORM(QT)
        if (shareContext) {
            QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface();
            shareContextObject = static_cast<GLXContext>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("glxcontext"), shareContext));
            if (!shareContextObject)
                return;
        }
#else
        UNUSED_PARAM(shareContext);
#endif

        int numReturned;
        GLXFBConfig* fbConfigs = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &numReturned);

        // Make sure that we choose a configuration that supports an alpha mask.
        m_fbConfig = findFBConfigWithAlpha(fbConfigs, numReturned);

        XFree(fbConfigs);

        // Create a GLX context for OpenGL rendering
        m_glContext = glXCreateNewContext(m_display, m_fbConfig, GLX_RGBA_TYPE, shareContextObject, true);
    }
Esempio n. 7
0
QSGNode* OMX_MediaProcessorElement::updatePaintNode(QSGNode*, UpdatePaintNodeData*)
{
    if (!m_texProvider) {
        m_texProvider = new OMX_TextureProviderQQuickItem(this);
        m_mediaProc   = new OMX_MediaProcessor(m_texProvider);
        connect(m_mediaProc, SIGNAL(playbackCompleted()), this, SIGNAL(playbackCompleted()));
        connect(m_mediaProc, SIGNAL(playbackStarted()), this, SIGNAL(playbackStarted()));

        // Open if filepath is set.
        // TODO: Handle errors.
        if (!m_source.isNull()) {
            //if (QFile(m_source).exists()) {
                if (openMedia(m_source))
                    m_mediaProc->play();
            //}
            //else {
                LOG_WARNING(LOG_TAG, "File does not exist.");
            //}
        }
    }

    return NULL;

#if 0
    QSGGeometryNode* node = 0;
    QSGGeometry* geometry = 0;

    if (!oldNode) {
        // Create the node.
        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
        geometry->setDrawingMode(GL_TRIANGLE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);

        // TODO: Who is freeing this?
        // TODO: I cannot know the texture size here.
        QSGOpaqueTextureMaterial* material = new QSGOpaqueTextureMaterial;
        m_sgtexture = new OMX_SGTexture(m_texture, QSize(1920, 1080));
        material->setTexture(m_sgtexture);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);

#ifdef ENABLE_VIDEO_PROCESSOR
        QPlatformNativeInterface* nativeInterface =
                QGuiApplicationPrivate::platformIntegration()->nativeInterface();
        Q_ASSERT(nativeInterface);
        EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay");
        EGLContext eglContext = nativeInterface->nativeResourceForContext(
                    "eglcontext",
                    QOpenGLContext::currentContext()
                    );
#endif

        // Provider MUST be built in this thread.
        m_provider  = new OMX_TextureProviderQQuickItem(this);
#ifdef ENABLE_VIDEO_PROCESSOR
        m_videoProc = new OMX_VideoProcessor(eglDisplay, eglContext, m_provider);
        connect(m_videoProc, SIGNAL(textureReady(uint)), this, SLOT(onTextureChanged(uint)));
        if (!m_source.isNull())
            m_videoProc->setVideoPath(m_source);
        if (m_playScheduled) {
            m_timer->start(30);
            m_videoProc->play();
        }
#elif ENABLE_MEDIA_PROCESSOR
        LOG_VERBOSE(LOG_TAG, "Starting video using media processor...");
        m_mediaProc = new OMX_MediaProcessor(m_provider);
        m_mediaProc->setFilename("/home/pi/usb/Cars2.mkv", m_texture);
        //if (m_playScheduled) {
            m_timer->start(40);
            m_mediaProc->play();
        //}
#else
        LOG_VERBOSE(LOG_TAG, "Starting video...");
        QtConcurrent::run(&startVideo, m_provider, this);
        m_timer->start(30);
#endif
    }
    else {
        node = static_cast<QSGGeometryNode*>(oldNode);
        geometry = node->geometry();
        geometry->allocate(4);

        // Update texture in the node if needed.
        QSGOpaqueTextureMaterial* material = (QSGOpaqueTextureMaterial*)node->material();
        if (m_texture != (GLuint)material->texture()->textureId()) {
            // TODO: Does setTextureId frees the prev texture?
            // TODO: I should the given the texture size.
            LOG_ERROR(LOG_TAG, "Updating texture to %u!", m_texture);
            material = new QSGOpaqueTextureMaterial;
            m_sgtexture->setTexture(m_texture, QSize(1920, 1080));
        }
    }

    // Create the vertices and map to texture.
    QRectF bounds = boundingRect();
    QSGGeometry::TexturedPoint2D* vertices = geometry->vertexDataAsTexturedPoint2D();
    vertices[0].set(bounds.x(), bounds.y() + bounds.height(), 0.0f, 0.0f);
    vertices[1].set(bounds.x() + bounds.width(), bounds.y() + bounds.height(), 1.0f, 0.0f);
    vertices[2].set(bounds.x(), bounds.y(), 0.0f, 1.0f);
    vertices[3].set(bounds.x() + bounds.width(), bounds.y(), 1.0f, 1.0f);
    return node;
#endif
}
void D3DPresentEngine::createOffscreenTexture()
{
    // First, check if we have a context on this thread
    QOpenGLContext *currentContext = QOpenGLContext::currentContext();

    if (!currentContext) {
        //Create OpenGL context and set share context from surface
        QOpenGLContext *shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>());
        if (!shareContext)
            return;

        m_offscreenSurface = new QWindow;
        m_offscreenSurface->setSurfaceType(QWindow::OpenGLSurface);
        //Needs geometry to be a valid surface, but size is not important
        m_offscreenSurface->setGeometry(-1, -1, 1, 1);
        m_offscreenSurface->create();

        m_glContext = new QOpenGLContext;
        m_glContext->setFormat(m_offscreenSurface->requestedFormat());
        m_glContext->setShareContext(shareContext);

        if (!m_glContext->create()) {
            delete m_glContext;
            delete m_offscreenSurface;
            m_glContext = 0;
            m_offscreenSurface = 0;
            return;
        }

        currentContext = m_glContext;
    }

    if (m_glContext)
        m_glContext->makeCurrent(m_offscreenSurface);

    if (!m_egl)
        m_egl = new EGLWrapper;

    QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
    m_eglDisplay = static_cast<EGLDisplay*>(
                nativeInterface->nativeResourceForContext("eglDisplay", currentContext));
    m_eglConfig = static_cast<EGLConfig*>(
                nativeInterface->nativeResourceForContext("eglConfig", currentContext));

    currentContext->functions()->glGenTextures(1, &m_glTexture);

    int w = m_surfaceFormat.frameWidth();
    int h = m_surfaceFormat.frameHeight();
    bool hasAlpha = currentContext->format().hasAlpha();

    EGLint attribs[] = {
        EGL_WIDTH, w,
        EGL_HEIGHT, h,
        EGL_TEXTURE_FORMAT, hasAlpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB,
        EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
        EGL_NONE
    };

    EGLSurface pbuffer = m_egl->createPbufferSurface(m_eglDisplay, m_eglConfig, attribs);

    HANDLE share_handle = 0;
    PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE =
            reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(m_egl->getProcAddress("eglQuerySurfacePointerANGLE"));
    Q_ASSERT(eglQuerySurfacePointerANGLE);
    eglQuerySurfacePointerANGLE(
                m_eglDisplay,
                pbuffer,
                EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle);


    m_device->CreateTexture(w, h, 1,
                            D3DUSAGE_RENDERTARGET,
                            hasAlpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8,
                            D3DPOOL_DEFAULT,
                            &m_texture,
                            &share_handle);

    m_eglSurface = pbuffer;

    if (m_glContext)
        m_glContext->doneCurrent();
}
Esempio n. 9
0
    GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext, const IntSize& size, GraphicsSurface::Flags flags)
        : m_context(0)
        , m_size(size)
        , m_frontBufferTexture(0)
        , m_frontBufferReadTexture(0)
        , m_backBufferTexture(0)
        , m_backBufferReadTexture(0)
        , m_readFbo(0)
        , m_drawFbo(0)
    {
#if PLATFORM(QT)
        QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface();
        CGLContextObj shareContextObject = static_cast<CGLContextObj>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("cglContextObj"), shareContext));
        if (!shareContextObject)
            return;

        CGLPixelFormatObj pixelFormatObject = CGLGetPixelFormat(shareContextObject);
        if (kCGLNoError != CGLCreateContext(pixelFormatObject, shareContextObject, &m_context))
            return;

        CGLRetainContext(m_context);
#endif

        unsigned pixelFormat = 'BGRA';
        unsigned bytesPerElement = 4;
        int width = m_size.width();
        int height = m_size.height();

        unsigned long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, width * bytesPerElement);
        if (!bytesPerRow)
            return;

        unsigned long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, height * bytesPerRow);
        if (!allocSize)
            return;

        const void *keys[6];
        const void *values[6];
        keys[0] = kIOSurfaceWidth;
        values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
        keys[1] = kIOSurfaceHeight;
        values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
        keys[2] = kIOSurfacePixelFormat;
        values[2] = CFNumberCreate(0, kCFNumberIntType, &pixelFormat);
        keys[3] = kIOSurfaceBytesPerElement;
        values[3] = CFNumberCreate(0, kCFNumberIntType, &bytesPerElement);
        keys[4] = kIOSurfaceBytesPerRow;
        values[4] = CFNumberCreate(0, kCFNumberLongType, &bytesPerRow);
        keys[5] = kIOSurfaceAllocSize;
        values[5] = CFNumberCreate(0, kCFNumberLongType, &allocSize);

        CFDictionaryRef dict = CFDictionaryCreate(0, keys, values, 6, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
        for (unsigned i = 0; i < 6; i++)
            CFRelease(values[i]);

        m_frontBuffer = IOSurfaceCreate(dict);
        m_backBuffer = IOSurfaceCreate(dict);

        if (!(flags & GraphicsSurface::SupportsSharing))
            return;

        m_token = GraphicsSurfaceToken(IOSurfaceCreateMachPort(m_frontBuffer), IOSurfaceCreateMachPort(m_backBuffer));
    }
Esempio n. 10
0
bool EGLInteropResource::ensureD3D9EGL(int w, int h) {
    if (surface9 && res[0].w == w && res[0].h == h)
        return true;
#if QTAV_HAVE(GUI_PRIVATE)
    QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
    egl->dpy = static_cast<EGLDisplay>(nativeInterface->nativeResourceForContext("eglDisplay", QOpenGLContext::currentContext()));
    EGLConfig egl_cfg = static_cast<EGLConfig>(nativeInterface->nativeResourceForContext("eglConfig", QOpenGLContext::currentContext()));
#else
#ifdef Q_OS_WIN
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
#ifdef _MSC_VER
#pragma message("ANGLE version in Qt<5.5 does not support eglQueryContext. You must upgrade your runtime ANGLE libraries")
#else
#warning "ANGLE version in Qt<5.5 does not support eglQueryContext. You must upgrade your runtime ANGLE libraries"
#endif //_MSC_VER
#endif
#endif //Q_OS_WIN
    // eglQueryContext() added (Feb 2015): https://github.com/google/angle/commit/8310797003c44005da4143774293ea69671b0e2a
    egl->dpy = eglGetCurrentDisplay();
    qDebug("EGL version: %s, client api: %s", eglQueryString(egl->dpy, EGL_VERSION), eglQueryString(egl->dpy, EGL_CLIENT_APIS));
    // TODO: check runtime egl>=1.4 for eglGetCurrentContext()
    EGLint cfg_id = 0;
    EGL_ENSURE(eglQueryContext(egl->dpy, eglGetCurrentContext(), EGL_CONFIG_ID , &cfg_id) == EGL_TRUE, false);
    qDebug("egl config id: %d", cfg_id);
    EGLint nb_cfg = 0;
    EGL_ENSURE(eglGetConfigs(egl->dpy, NULL, 0, &nb_cfg) == EGL_TRUE, false);
    qDebug("eglGetConfigs number: %d", nb_cfg);
    QVector<EGLConfig> cfgs(nb_cfg); //check > 0
    EGL_ENSURE(eglGetConfigs(egl->dpy, cfgs.data(), cfgs.size(), &nb_cfg) == EGL_TRUE, false);
    EGLConfig egl_cfg = NULL;
    for (int i = 0; i < nb_cfg; ++i) {
        EGLint id = 0;
        eglGetConfigAttrib(egl->dpy, cfgs[i], EGL_CONFIG_ID, &id);
        if (id == cfg_id) {
            egl_cfg = cfgs[i];
            break;
        }
    }
#endif
    qDebug("egl display:%p config: %p", egl->dpy, egl_cfg);
    // check extensions
    QList<QByteArray> extensions = QByteArray(eglQueryString(egl->dpy, EGL_EXTENSIONS)).split(' ');
    // ANGLE_d3d_share_handle_client_buffer will be used if possible
    const bool kEGL_ANGLE_d3d_share_handle_client_buffer = extensions.contains("EGL_ANGLE_d3d_share_handle_client_buffer");
    const bool kEGL_ANGLE_query_surface_pointer = extensions.contains("EGL_ANGLE_query_surface_pointer");
    if (!kEGL_ANGLE_d3d_share_handle_client_buffer && !kEGL_ANGLE_query_surface_pointer) {
        qWarning("EGL extension 'kEGL_ANGLE_query_surface_pointer' or 'ANGLE_d3d_share_handle_client_buffer' is required!");
        return false;
    }
    GLint has_alpha = 1; //QOpenGLContext::currentContext()->format().hasAlpha()
    eglGetConfigAttrib(egl->dpy, egl_cfg, EGL_BIND_TO_TEXTURE_RGBA, &has_alpha); //EGL_ALPHA_SIZE
    EGLint attribs[] = {
        EGL_WIDTH, w,
        EGL_HEIGHT, h,
        EGL_TEXTURE_FORMAT, has_alpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB,
        EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
        EGL_NONE
    };

    HANDLE share_handle = NULL;
    if (!kEGL_ANGLE_d3d_share_handle_client_buffer && kEGL_ANGLE_query_surface_pointer) {
        EGL_ENSURE((egl->surface = eglCreatePbufferSurface(egl->dpy, egl_cfg, attribs)) != EGL_NO_SURFACE, false);
        qDebug("pbuffer surface: %p", egl->surface);
        PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE = reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(eglGetProcAddress("eglQuerySurfacePointerANGLE"));
        if (!eglQuerySurfacePointerANGLE) {
            qWarning("EGL_ANGLE_query_surface_pointer is not supported");
            return false;
        }
        EGL_ENSURE(eglQuerySurfacePointerANGLE(egl->dpy, egl->surface, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle), false);
    }

    SafeRelease(&surface9);
    SafeRelease(&texture9);
    // _A8 for a yuv plane
    /*
     * d3d resource share requires windows >= vista: https://msdn.microsoft.com/en-us/library/windows/desktop/bb219800(v=vs.85).aspx
     * from extension files:
     * d3d9: level must be 1, dimensions must match EGL surface's
     * d3d9ex or d3d10:
     */
    DX_ENSURE(device9->CreateTexture(w, h, 1,
                                        D3DUSAGE_RENDERTARGET,
                                        has_alpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8,
                                        D3DPOOL_DEFAULT,
                                        &texture9,
                                        &share_handle) , false);
    DX_ENSURE(texture9->GetSurfaceLevel(0, &surface9), false);

    if (kEGL_ANGLE_d3d_share_handle_client_buffer) {
        // requires extension EGL_ANGLE_d3d_share_handle_client_buffer
        // egl surface size must match d3d texture's
        // d3d9ex or d3d10 is required
        EGL_ENSURE((egl->surface = eglCreatePbufferFromClientBuffer(egl->dpy, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, share_handle, egl_cfg, attribs)), false);
        qDebug("pbuffer surface from client buffer: %p", egl->surface);
    }
    return true;
}