/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qopenglcontextwindow.h" #include #include #include #include #include #include #include QOpenGLContextWindow::QOpenGLContextWindow() : m_blitter(0) { setSurfaceType(OpenGLSurface); m_context = new QOpenGLContext(this); m_context->setFormat(requestedFormat()); m_context->create(); m_image = QImage(QStringLiteral("qticon64.png")).convertToFormat(QImage::Format_RGBA8888); Q_ASSERT(!m_image.isNull()); create(); // to make sure format() returns something real createForeignContext(); } QOpenGLContextWindow::~QOpenGLContextWindow() { if (m_blitter) { m_blitter->destroy(); // the dtor does not call this for some reason delete m_blitter; } } void QOpenGLContextWindow::render() { if (!m_context->makeCurrent(this)) qFatal("makeCurrent() failed"); QOpenGLFunctions *f = m_context->functions(); f->glViewport(0, 0, dWidth(), dHeight()); f->glClearColor(0, 0, 0, 1); f->glClear(GL_COLOR_BUFFER_BIT); if (!m_blitter) { m_blitter = new QOpenGLTextureBlitter; m_blitter->create(); } // Draw the image. If nothing gets shown, then something went wrong with the context // adoption or sharing was not successfully enabled. m_blitter->bind(); QRectF r(0, 0, dWidth(), dHeight()); QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRectF(100, 100, 100, 100), r.toRect()); m_blitter->blit(m_textureId, target, QOpenGLTextureBlitter::OriginTopLeft); m_blitter->release(); m_context->swapBuffers(this); } void QOpenGLContextWindow::exposeEvent(QExposeEvent *) { if (isExposed()) render(); } void QOpenGLContextWindow::createForeignContext() { // Here a context will be created manually. This context will share with m_context's // underlying native context. This way the texture, that belongs to the context // created here, will be accessible from m_context too. EGLContext shareCtx = m_context->nativeHandle().value().context(); Q_ASSERT(shareCtx != EGL_NO_CONTEXT); EGLDisplay dpy = (EGLDisplay) qGuiApp->platformNativeInterface()->nativeResourceForWindow( QByteArrayLiteral("egldisplay"), this); Q_ASSERT(dpy != EGL_NO_DISPLAY); QSurfaceFormat fmt = format(); EGLConfig config = q_configFromGLFormat(dpy, fmt); QVector contextAttrs; contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); contextAttrs.append(fmt.majorVersion()); contextAttrs.append(EGL_NONE); switch (fmt.renderableType()) { #ifdef EGL_VERSION_1_4 case QSurfaceFormat::OpenGL: eglBindAPI(EGL_OPENGL_API); break; #endif // EGL_VERSION_1_4 default: eglBindAPI(EGL_OPENGL_ES_API); break; } EGLContext ctx = eglCreateContext(dpy, config, shareCtx, contextAttrs.constData()); Q_ASSERT(ctx != EGL_NO_CONTEXT); // Wrap ctx into a QOpenGLContext. QOpenGLContext *ctxWrap = new QOpenGLContext; ctxWrap->setNativeHandle(QVariant::fromValue(QEGLNativeContext(ctx, dpy))); ctxWrap->setShareContext(m_context); // only needed for correct bookkeeping if (!ctxWrap->create()) qFatal("Failed to created wrapping context"); Q_ASSERT(ctxWrap->nativeHandle().value().context() == ctx); QOffscreenSurface surface; surface.setFormat(fmt); surface.create(); if (!ctxWrap->makeCurrent(&surface)) qFatal("Failed to make pbuffer surface current"); // Create the texture. QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); GLuint textureId = 0; f->glGenTextures(1, &textureId); f->glBindTexture(GL_TEXTURE_2D, textureId); f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, m_image.constBits()); Q_ASSERT(f->glGetError() == GL_NO_ERROR); ctxWrap->doneCurrent(); delete ctxWrap; // ctx is not destroyed eglDestroyContext(dpy, ctx); // resources like the texture stay alive until any context on the share list is alive Q_ASSERT(eglGetError() == EGL_SUCCESS); m_textureId = textureId; }