QPlatformOpenGLContext *EglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
    QPlatformOpenGLContext *pctx = egl_device_integration()->createPlatformOpenGLContext(context);
    if (pctx)
        return pctx;

    // If there is a "root" window into which raster and QOpenGLWidget content is
    // composited, all other contexts must share with its context.
    QOpenGLContext *compositingContext = OpenGLCompositor::instance()->context();
    EGLDisplay dpy = context->screen() ? static_cast<EglFSScreen *>(context->screen()->handle())->display() : display();
    QPlatformOpenGLContext *share = compositingContext ? compositingContext->handle() : context->shareHandle();
    QVariant nativeHandle = context->nativeHandle();

    EglFSContext *ctx;
    QSurfaceFormat adjustedFormat = egl_device_integration()->surfaceFormatFor(context->format());
    if (nativeHandle.isNull()) {
        EGLConfig config = EglFSIntegration::chooseConfig(dpy, adjustedFormat);
        ctx = new EglFSContext(adjustedFormat, share, dpy, &config, QVariant());
    } else {
        ctx = new EglFSContext(adjustedFormat, share, dpy, 0, nativeHandle);
    }
    nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), dpy));

    context->setNativeHandle(nativeHandle);
    return ctx;
}
QPlatformOffscreenSurface *EglFSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
{
    EGLDisplay dpy = surface->screen() ? static_cast<EglFSScreen *>(surface->screen()->handle())->display() : display();
    QSurfaceFormat fmt = egl_device_integration()->surfaceFormatFor(surface->requestedFormat());
    if (egl_device_integration()->supportsPBuffers())
        return new EGLPbuffer(dpy, fmt, surface);
    else
        return new EglFSOffscreenWindow(dpy, fmt, surface);
    // Never return null. Multiple QWindows are not supported by this plugin.
}
EglFSOffscreenWindow::~EglFSOffscreenWindow()
{
    if (m_surface != EGL_NO_SURFACE)
        eglDestroySurface(m_display, m_surface);
    if (m_window)
        egl_device_integration()->destroyNativeWindow(m_window);
}
EGLConfig EglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
{
    class Chooser : public EglConfigChooser {
    public:
        Chooser(EGLDisplay display)
            : EglConfigChooser(display) { }
        bool filterConfig(EGLConfig config) const Q_DECL_OVERRIDE {
            return egl_device_integration()->filterConfig(display(), config)
                    && EglConfigChooser::filterConfig(config);
        }
    };
QPlatformBackingStore *EglFSIntegration::createPlatformBackingStore(QWindow *window) const
{
    QPlatformBackingStore *pbs = egl_device_integration()->createPlatformBackingStore(window);
    if (pbs)
        return pbs;

    OpenGLCompositorBackingStore *bs = new OpenGLCompositorBackingStore(window);
    if (!window->handle())
        window->create();
    static_cast<EglFSWindow *>(window->handle())->setBackingStore(bs);
    return bs;
}
bool EglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
    // We assume that devices will have more and not less capabilities
    if (egl_device_integration()->hasCapability(cap))
        return true;

    switch (cap) {
    case ThreadedPixmaps: return true;
    case OpenGL: return true;
    case ThreadedOpenGL: return true;
    case WindowManagement: return false;
    case RasterGLSurface: return true;
    default: return QPlatformIntegration::hasCapability(cap);
    }
}
QPlatformWindow *EglFSIntegration::createPlatformWindow(QWindow *window) const
{
    QWindowSystemInterface::flushWindowSystemEvents();

    QPlatformWindow *w = egl_device_integration()->createPlatformWindow(window);
    if (!w) {
        w = new EglFSWindow(window);
        static_cast<EglFSWindow *>(w)->create();
    }

    // Activate only the compositor window for the primary screen in order to
    // make keyboard input work
    if (window->type() != Qt::ToolTip && window->screen() == QGuiApplication::primaryScreen())
        w->requestActivateWindow();

    return w;
}
EglFSOffscreenWindow::EglFSOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface)
    : QPlatformOffscreenSurface(offscreenSurface)
    , m_format(format)
    , m_display(display)
    , m_surface(EGL_NO_SURFACE)
    , m_window(0)
{
    m_window = egl_device_integration()->createNativeOffscreenWindow(format);
    if (!m_window) {
        qCWarning(lcDeviceIntegration, "EglFSOffscreenWindow: Failed to create native window");
        return;
    }
    EGLConfig config = EglUtils::configFromGLFormat(m_display, m_format);
    m_surface = eglCreateWindowSurface(m_display, config, m_window, 0);
    if (m_surface != EGL_NO_SURFACE)
        m_format = EglUtils::glFormatFromConfig(m_display, config);
}
void *EglFSIntegration::nativeResourceForIntegration(const QByteArray &resource)
{
    void *result = 0;

    switch (resourceType(resource)) {
    case EglDisplay:
        result = display();
        break;
    case NativeDisplay:
        result = reinterpret_cast<void*>(nativeDisplay());
        break;
    case WaylandDisplay:
        result = egl_device_integration()->wlDisplay();
        break;
    default:
        break;
    }

    return result;
}