bool EGLInteropResource::map(IDirect3DSurface9* surface, GLuint tex, int w, int h, int)
{
    D3DSURFACE_DESC dxvaDesc;
    surface->GetDesc(&dxvaDesc);
    if (!ensureSurface(w, h)) {
        releaseEGL();
        releaseDX();
        return false;
    }
    DYGL(glBindTexture(GL_TEXTURE_2D, tex));
    const RECT src = { 0, 0, w, h};
    if (SUCCEEDED(d3ddev->StretchRect(surface, &src, dx_surface, NULL, D3DTEXF_NONE))) {
        if (dx_query) {
            // Flush the draw command now. Ideally, this should be done immediately before the draw call that uses the texture. Flush it once here though.
            dx_query->Issue(D3DISSUE_END);
            // ensure data is copied to egl surface. Solution and comment is from chromium
            // The DXVA decoder has its own device which it uses for decoding. ANGLE has its own device which we don't have access to.
            // The above code attempts to copy the decoded picture into a surface which is owned by ANGLE.
            // As there are multiple devices involved in this, the StretchRect call above is not synchronous.
            // We attempt to flush the batched operations to ensure that the picture is copied to the surface owned by ANGLE.
            // We need to do this in a loop and call flush multiple times.
            // We have seen the GetData call for flushing the command buffer fail to return success occassionally on multi core machines, leading to an infinite loop.
            // Workaround is to have an upper limit of 10 on the number of iterations to wait for the Flush to finish.
            int k = 0;
            while ((dx_query->GetData(NULL, 0, D3DGETDATA_FLUSH) == FALSE) && ++k < 10) {
                Sleep(1);
            }
        }
        eglBindTexImage(egl->dpy, egl->surface, EGL_BACK_BUFFER);
    }
    DYGL(glBindTexture(GL_TEXTURE_2D, 0));
    return true;
}
void QWaylandCursor::setupPixmapCursor(QCursor *cursor)
{
    if (!cursor) {
        delete mBuffer;
        mBuffer = 0;
        return;
    }
    ensureSurface(cursor->pixmap().size());
    QImage src = cursor->pixmap().toImage().convertToFormat(QImage::Format_ARGB32);
    for (int y = 0; y < src.height(); ++y)
        memcpy(mBuffer->image()->scanLine(y), src.scanLine(y), src.bytesPerLine());
    mDisplay->setCursor(mSurface, cursor->hotSpot().x(), cursor->hotSpot().y());
}
void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window)
{
    const struct pointer_image *p;

    if (window == NULL)
        return;

    p = NULL;
    bool isBitmap = false;

    switch (cursor->shape()) {
    case Qt::ArrowCursor:
        p = &pointer_images[cursor->shape()];
        break;
    case Qt::UpArrowCursor:
    case Qt::CrossCursor:
    case Qt::WaitCursor:
        break;
    case Qt::IBeamCursor:
        p = &pointer_images[cursor->shape()];
        break;
    case Qt::SizeVerCursor:	/* 5 */
    case Qt::SizeHorCursor:
    case Qt::SizeBDiagCursor:
    case Qt::SizeFDiagCursor:
    case Qt::SizeAllCursor:
    case Qt::BlankCursor:	/* 10 */
        break;
    case Qt::SplitVCursor:
    case Qt::SplitHCursor:
    case Qt::PointingHandCursor:
        p = &pointer_images[cursor->shape()];
        break;
    case Qt::ForbiddenCursor:
    case Qt::WhatsThisCursor:	/* 15 */
    case Qt::BusyCursor:
        break;
    case Qt::OpenHandCursor:
    case Qt::ClosedHandCursor:
    case Qt::DragCopyCursor:
    case Qt::DragMoveCursor: /* 20 */
    case Qt::DragLinkCursor:
        p = &pointer_images[cursor->shape()];
        break;

    case Qt::BitmapCursor:
        isBitmap = true;
        break;

    default:
        break;
    }

    if (!p && !isBitmap) {
        p = &pointer_images[0];
        qWarning("unhandled cursor %d", cursor->shape());
    }

    if (isBitmap && !cursor->pixmap().isNull()) {
        setupPixmapCursor(cursor);
    } else if (isBitmap && cursor->bitmap()) {
        qWarning("unsupported QBitmap cursor");
    } else {
        QImageReader reader(p->filename);
        if (!reader.canRead())
            return;
        ensureSurface(reader.size());
        reader.read(mBuffer->image());
        mDisplay->setCursor(mSurface, p->hotspot_x, p->hotspot_y);
    }
}