bool OpenGL2Common::testGL() { QOpenGLContext glCtx; if ((isOK = glCtx.create())) { QOffscreenSurface offscreenSurface; offscreenSurface.create(); if ((isOK = glCtx.makeCurrent(&offscreenSurface))) testGLInternal(); } return isOK; }
void QuickMozView::clearThreadRenderObject() { QOpenGLContext* ctx = QOpenGLContext::currentContext(); Q_ASSERT(ctx != NULL && ctx->makeCurrent(ctx->surface())); if (gSGRenderer != NULL) { delete gSGRenderer; gSGRenderer = NULL; } QQuickWindow *win = window(); if (!win) return; connect(win, SIGNAL(beforeSynchronizing()), this, SLOT(createThreadRenderObject()), Qt::DirectConnection); }
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); }
void tst_QOpenGL::openGLPaintDevice() { #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__) QSKIP("QTBUG-22617"); #endif QFETCH(int, surfaceClass); QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext ctx; ctx.create(); QSurfaceFormat format = ctx.format(); if (format.majorVersion() < 2) QSKIP("This test requires at least OpenGL 2.0"); ctx.makeCurrent(surface.data()); QImage image(128, 128, QImage::Format_RGB32); QPainter p(&image); p.fillRect(0, 0, image.width() / 2, image.height() / 2, Qt::red); p.fillRect(image.width() / 2, 0, image.width() / 2, image.height() / 2, Qt::green); p.fillRect(image.width() / 2, image.height() / 2, image.width() / 2, image.height() / 2, Qt::blue); p.fillRect(0, image.height() / 2, image.width() / 2, image.height() / 2, Qt::white); p.end(); QOpenGLFramebufferObject fbo(128, 128); fbo.bind(); QOpenGLPaintDevice device(128, 128); p.begin(&device); p.fillRect(0, 0, image.width() / 2, image.height() / 2, Qt::red); p.fillRect(image.width() / 2, 0, image.width() / 2, image.height() / 2, Qt::green); p.fillRect(image.width() / 2, image.height() / 2, image.width() / 2, image.height() / 2, Qt::blue); p.fillRect(0, image.height() / 2, image.width() / 2, image.height() / 2, Qt::white); p.end(); QCOMPARE(image, fbo.toImage().convertToFormat(QImage::Format_RGB32)); p.begin(&device); p.fillRect(0, 0, image.width(), image.height(), Qt::black); p.drawImage(0, 0, image); p.end(); QCOMPARE(image, fbo.toImage().convertToFormat(QImage::Format_RGB32)); p.begin(&device); p.fillRect(0, 0, image.width(), image.height(), Qt::black); p.fillRect(0, 0, image.width(), image.height(), QBrush(image)); p.end(); QCOMPARE(image, fbo.toImage().convertToFormat(QImage::Format_RGB32)); }
GraphicsSurfaceToken ImageBufferDataPrivateAccelerated::graphicsSurfaceToken() const { if (!m_graphicsSurface) { QOpenGLContext *previousContext = QOpenGLContext::currentContext(); GLSharedContext::makeCurrent(); m_graphicsSurface = GraphicsSurface::create(m_fbo->size(), graphicsSurfaceFlags(), QOpenGLContext::currentContext()); previousContext->makeCurrent(previousContext->surface()); } return m_graphicsSurface->exportToken(); }
uint32_t ImageBufferDataPrivateAccelerated::copyToGraphicsSurface() { QOpenGLContext *previousContext = QOpenGLContext::currentContext(); GLSharedContext::makeCurrent(); if (!m_graphicsSurface) { m_graphicsSurface = GraphicsSurface::create(m_fbo->size(), graphicsSurfaceFlags(), QOpenGLContext::currentContext()); } commitChanges(); m_graphicsSurface->copyFromTexture(m_fbo->texture(), IntRect(IntPoint(), m_fbo->size())); previousContext->makeCurrent(previousContext->surface()); return m_graphicsSurface->frontBuffer(); }
void ImageBufferDataPrivateAccelerated::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity) { if (textureMapper->accelerationMode() != TextureMapper::OpenGLMode) { return; } QOpenGLContext *previousContext = QOpenGLContext::currentContext(); GLSharedContext::makeCurrent(); commitChanges(); previousContext->makeCurrent(previousContext->surface()); static_cast<TextureMapperGL*>(textureMapper)->drawTexture(m_fbo->texture(), TextureMapperGL::ShouldFlipTexture | TextureMapperGL::ShouldBlend, m_fbo->size(), targetRect, matrix, opacity); }
bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { qWarning() << "Too many concurrent web views to create new view"; return false; } qDebug() << "Building web surface"; ++_currentWebCount; // Save the original GL context, because creating a QML surface will create a new context QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/controls/")); _webSurface->load("WebView.qml"); _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _sourceUrl); _webSurface->getRootContext()->setContextProperty("desktop", QVariant()); _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _texture = textureId; }); // Restore the original GL context currentContext->makeCurrent(currentSurface); auto forwardPointerEvent = [=](const EntityItemID& entityItemID, const PointerEvent& event) { if (entityItemID == getID()) { handlePointerEvent(event); } }; _mousePressConnection = QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardPointerEvent); _mouseReleaseConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardPointerEvent); _mouseMoveConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardPointerEvent); _hoverLeaveConnection = QObject::connect(renderer, &EntityTreeRenderer::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const PointerEvent& event) { if (this->_pressed && this->getID() == entityItemID) { // If the user mouses off the entity while the button is down, simulate a touch end. QTouchEvent::TouchPoint point; point.setId(event.getID()); point.setState(Qt::TouchPointReleased); glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); QPointF windowPoint(windowPos.x, windowPos.y); point.setPos(windowPoint); QList<QTouchEvent::TouchPoint> touchPoints; touchPoints.push_back(point); QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, Qt::NoModifier, Qt::TouchPointReleased, touchPoints); QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); } }); return true; }
QString openGlContext() { QString result; QTextStream str(&result); QOpenGLContext context; if (context.create()) { # ifdef QT_OPENGL_DYNAMIC str << "Dynamic GL "; # endif switch (context.openGLModuleType()) { case QOpenGLContext::LibGL: str << "LibGL"; break; case QOpenGLContext::LibGLES: str << "LibGLES"; break; } QWindow window; if (QGuiApplication::platformName() == QLatin1String("greenisland")) window.setFlags(Qt::Desktop); window.setSurfaceType(QSurface::OpenGLSurface); //window.setScreen(QGuiApplication::primaryScreen()); window.create(); if (context.makeCurrent(&window)) { QOpenGLFunctions functions(&context); str << " Vendor: " << reinterpret_cast<const char *>(functions.glGetString(GL_VENDOR)) << "\nRenderer: " << reinterpret_cast<const char *>(functions.glGetString(GL_RENDERER)) << "\nVersion: " << reinterpret_cast<const char *>(functions.glGetString(GL_VERSION)) << "\nGLSL version: " << reinterpret_cast<const char *>(functions.glGetString(GL_SHADING_LANGUAGE_VERSION)) << "\nFormat: " << context.format(); QList<QByteArray> extensionList = context.extensions().toList(); std::sort(extensionList.begin(), extensionList.end()); QByteArray extensions = extensionList.join(' '); str << " \nFound " << extensionList.size() << " extensions:\n"; str << wordWrap(extensions, 78); context.doneCurrent(); } window.destroy(); } else { str << "Unable to create an Open GL context.\n"; } return result; }
void WebView::CreateGLContext() { QOpenGLContext* context = window_->GLContext(); context->makeCurrent(window_); static bool firstClearDone = false; if (!firstClearDone) { QOpenGLFunctions* functions = context->functions(); Q_ASSERT(functions); functions->glClearColor(1.0, 1.0, 1.0, 0.0); functions->glClear(GL_COLOR_BUFFER_BIT); context->swapBuffers(window_); firstClearDone = true; } }
void TestWindow::initGl() { _glContext.setFormat(format()); if (!_glContext.create() || !_glContext.makeCurrent(this)) { qFatal("Unable to intialize Window GL context"); } gl::initModuleGl(); _glf.initializeOpenGLFunctions(); _glf.glGenFramebuffers(1, &_fbo); if (!_sharedContext.create(&_glContext) || !_sharedContext.makeCurrent()) { qFatal("Unable to intialize Shared GL context"); } hifi::qml::OffscreenSurface::setSharedContext(_sharedContext.getContext()); _discardLamdba = hifi::qml::OffscreenSurface::getDiscardLambda(); }
void TestWindow::draw() { if (_aboutToQuit) { return; } // Attempting to draw before we're visible and have a valid size will // produce GL errors. if (!isVisible() || _size.width() <= 0 || _size.height() <= 0) { return; } static std::once_flag once; std::call_once(once, [&] { initGl(); }); if (!_glContext.makeCurrent(this)) { return; } updateSurfaces(); auto size = this->geometry().size(); auto incrementX = size.width() / DIVISIONS_X; auto incrementY = size.height() / DIVISIONS_Y; _glf.glViewport(0, 0, size.width(), size.height()); _glf.glClearColor(1, 0, 0, 1); _glf.glClear(GL_COLOR_BUFFER_BIT); for (uint32_t x = 0; x < DIVISIONS_X; ++x) { for (uint32_t y = 0; y < DIVISIONS_Y; ++y) { auto& qmlInfo = _surfaces[x][y]; if (!qmlInfo.surface || !qmlInfo.texture) { continue; } _glf.glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo); _glf.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, qmlInfo.texture, 0); _glf.glBlitFramebuffer( // src coordinates 0, 0, _qmlSize.width() - 1, _qmlSize.height() - 1, // dst coordinates incrementX * x, incrementY * y, incrementX * (x + 1), incrementY * (y + 1), // blit mask and filter GL_COLOR_BUFFER_BIT, GL_NEAREST); } } _glf.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); _glf.glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); _glContext.swapBuffers(this); }
// NOTE: This tests that CombinedDepthStencil attachment works by assuming the // GL2 engine is being used and is implemented the same way as it was when // this autotest was written. If this is not the case, there may be some // false-positives: I.e. The test passes when either the depth or stencil // buffer is actually missing. But that's probably ok anyway. void tst_QOpenGL::fboRendering() { #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__) QSKIP("QTBUG-22617"); #endif QFETCH(int, surfaceClass); QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext ctx; QVERIFY(ctx.create()); QVERIFY(ctx.makeCurrent(surface.data())); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); // No multisample with combined depth/stencil attachment: QOpenGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); // Uncomplicate things by using NPOT: const QSize size(256, 128); QOpenGLFramebufferObject fbo(size, fboFormat); if (fbo.attachment() != QOpenGLFramebufferObject::CombinedDepthStencil) QSKIP("FBOs missing combined depth~stencil support"); QVERIFY(fbo.bind()); QPainter fboPainter; QOpenGLPaintDevice device(fbo.width(), fbo.height()); bool painterBegun = fboPainter.begin(&device); QVERIFY(painterBegun); qt_opengl_draw_test_pattern(&fboPainter, fbo.width(), fbo.height()); fboPainter.end(); const QImage fb = fbo.toImage().convertToFormat(QImage::Format_RGB32); QCOMPARE(fb.size(), size); qt_opengl_check_test_pattern(fb); }
void Web3DOverlay::render(RenderArgs* args) { if (!_visible || !getParentVisible()) { return; } QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); if (!_webSurface) { _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); _webSurface->load("WebEntity.qml"); _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _url); _webSurface->resize(QSize(_resolution.x, _resolution.y)); _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _texture = textureId; }); currentContext->makeCurrent(currentSurface); } vec2 size = _resolution / _dpi * INCHES_TO_METERS; vec2 halfSize = size / 2.0f; vec4 color(toGlm(getColor()), getAlpha()); applyTransformTo(_transform, true); Transform transform = _transform; if (glm::length2(getDimensions()) != 1.0f) { transform.postScale(vec3(getDimensions(), 1.0f)); } Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; if (_texture) { batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); } else { batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture()); } batch.setModelTransform(transform); DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, true, false, false, true); DependencyManager::get<GeometryCache>()->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color); batch.setResourceTexture(0, args->_whiteTexture); // restore default white color after me }
void tst_QOpenGL::aboutToBeDestroyed() { QWindow window; window.setSurfaceType(QWindow::OpenGLSurface); window.setGeometry(0, 0, 128, 128); window.create(); QOpenGLContext *context = new QOpenGLContext; QSignalSpy spy(context, SIGNAL(aboutToBeDestroyed())); context->create(); context->makeCurrent(&window); QCOMPARE(spy.size(), 0); delete context; QCOMPARE(spy.size(), 1); }
void tst_QOpenGL::multiGroupSharedResourceCleanup() { QFETCH(int, surfaceClass); QScopedPointer<QSurface> surface(createSurface(surfaceClass)); for (int i = 0; i < 10; ++i) { QOpenGLContext *gl = new QOpenGLContext(); gl->create(); gl->makeCurrent(surface.data()); { // Cause QOpenGLMultiGroupSharedResource instantiation. QOpenGLFunctions func(gl); } delete gl; // Cause context group's deleteLater() to be processed. QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); } // Shouldn't crash when application exits. }
void tst_QOpenGL::fboTextureOwnership() { QFETCH(int, surfaceClass); QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext ctx; QVERIFY(ctx.create()); ctx.makeCurrent(surface.data()); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); QOpenGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QOpenGLFramebufferObject::NoAttachment); QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(200, 100, fboFormat); QVERIFY(fbo->texture() != 0); fbo->bind(); // pull out the texture GLuint texture = fbo->takeTexture(); QVERIFY(texture != 0); QVERIFY(fbo->texture() == 0); // verify that the next bind() creates a new texture fbo->bind(); QVERIFY(fbo->texture() != 0 && fbo->texture() != texture); glClearColor(1.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFinish(); QImage fb = fbo->toImage().convertToFormat(QImage::Format_RGB32); QImage reference(fb.size(), QImage::Format_RGB32); reference.fill(0xffff0000); QFUZZY_COMPARE_IMAGES(fb, reference); glDeleteTextures(1, &texture); delete fbo; }
void ImageBufferDataPrivateAccelerated::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode, bool useLowQualityScale, bool ownContext) { if (destContext->isAcceleratedContext()) { QOpenGLContext *previousContext = QOpenGLContext::currentContext(); GLSharedContext::makeCurrent(); commitChanges(); previousContext->makeCurrent(previousContext->surface()); QOpenGL2PaintEngineEx* acceleratedPaintEngine = static_cast<QOpenGL2PaintEngineEx*>(destContext->platformContext()->paintEngine()); FloatRect flippedSrc = srcRect; flippedSrc.setY(m_fbo->size().height() - flippedSrc.height() - flippedSrc.y()); acceleratedPaintEngine->drawTexture(destRect, m_fbo->texture(), m_fbo->size(), flippedSrc); } else { RefPtr<Image> image = StillImage::create(QPixmap::fromImage(toQImage())); destContext->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, blendMode, DoNotRespectImageOrientation, useLowQualityScale); } }
void tst_QOpenGL::multiGroupSharedResourceCleanupCustom() { QFETCH(int, surfaceClass); QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext *ctx = new QOpenGLContext(); ctx->create(); ctx->makeCurrent(surface.data()); QOpenGLMultiGroupSharedResource multiGroupSharedResource; SharedResource *resource = multiGroupSharedResource.value<SharedResource>(ctx); SharedResourceTracker tracker; resource->tracker = &tracker; delete ctx; QCOMPARE(tracker.invalidateResourceCalls, 1); QCOMPARE(tracker.freeResourceCalls, 0); QCOMPARE(tracker.destructorCalls, 1); }
QImage QFramebufferPaintDevice::toImage() const { QOpenGLContext* currentContext = QOpenGLContext::currentContext(); QSurface* currentSurface = currentContext ? currentContext->surface() : 0; context()->makeCurrent(m_surface); #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) QImage image = m_framebufferObject.toImage(false); #else QImage image = m_framebufferObject.toImage(); #endif if (currentContext) currentContext->makeCurrent(currentSurface); else context()->doneCurrent(); return image; }
void OpenGLWindow::Init() { // OpenGL //auto surface = new QOffscreenSurface(); //surface->setFormat(format); //surface->create(); //setSwapInterval QSurfaceFormat format; format.setVersion(4, 0); format.setSwapInterval(0); format.setProfile(QSurfaceFormat::CoreProfile); setFormat(format); auto glfwCTX = glfwGetWGLContext(Engine::Window->window); auto window = glfwGetWin32Window(Engine::Window->window); auto newNative = new QWGLNativeContext(glfwCTX, window); QOpenGLContext* qtctx = new QOpenGLContext(); //qtctx->setFormat(format); qtctx->setNativeHandle(QVariant::fromValue<QWGLNativeContext>(*newNative)); bool created = qtctx->create(); bool value = qtctx->makeCurrent(this); // Test auto nativeHandle = qtctx->nativeHandle(); auto windowsNative = nativeHandle.value<QWGLNativeContext>(); // Share context qtGLContext = new QOpenGLContext(this); //qtGLContext->setFormat(format); qtGLContext->setShareContext(qtctx); bool success = qtGLContext->create(); nativeHandle = qtGLContext->nativeHandle(); windowsNative = nativeHandle.value<QWGLNativeContext>(); bool sharing = qtGLContext->areSharing(qtctx, qtGLContext); bool sharing2 = qtGLContext->shareContext(); }
OpenGLInfo::OpenGLInfo() { QOpenGLContext context; QOffscreenSurface surface; surface.create(); if (!context.create()) { qCritical() << "Could not create QOpenGLContext"; return; } if (context.makeCurrent(&surface)) { KWin::GLPlatform *platform = KWin::GLPlatform::instance(); if (context.isOpenGLES() || !QX11Info::isPlatformX11()) { platform->detect(KWin::EglPlatformInterface); } else { platform->detect(KWin::GlxPlatformInterface); } if (platform->glRendererString().isEmpty()) { qCritical() << "Neither GLX or EGL detection worked!"; } openGLRenderer = QString::fromUtf8(platform->glRendererString()); openGLVersion = QString::fromUtf8(platform->glVersionString()); mesaVersion = KWin::GLPlatform::versionToString(platform->mesaVersion()); if (platform->driver() == KWin::Driver::Driver_Unknown) { kwinDriver = platform->glVendorString(); } else { kwinDriver = KWin::GLPlatform::driverToString(platform->driver()); } displayServerVersion = KWin::GLPlatform::versionToString(platform->serverVersion()); } else { qCritical() <<"Error: makeCurrent() failed\n"; } context.doneCurrent(); }
bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { qWarning() << "Too many concurrent web views to create new view"; return false; } qDebug() << "Building web surface"; ++_currentWebCount; // Save the original GL context, because creating a QML surface will create a new context QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); _webSurface->load("WebEntity.qml"); _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _sourceUrl); _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _texture = textureId; }); // Restore the original GL context currentContext->makeCurrent(currentSurface); auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event) { // Ignore mouse interaction if we're locked if (this->getLocked()) { return; } if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonPress) { const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); _lastPress = toGlm(mouseEvent->pos()); } } if (intersection.entityID == getID()) { if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonRelease) { const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); ivec2 dist = glm::abs(toGlm(mouseEvent->pos()) - _lastPress); if (!glm::any(glm::greaterThan(dist, ivec2(1)))) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack"); }); } _lastPress = ivec2(INT_MIN); } return; } // FIXME doesn't work... double click events not received if (event->type() == QEvent::MouseButtonDblClick) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); } if (event->button() == Qt::MouseButton::MiddleButton) { if (event->type() == QEvent::MouseButtonRelease) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); } return; } // Map the intersection point to an actual offscreen pixel glm::vec3 point = intersection.intersection; glm::vec3 dimensions = getDimensions(); point -= getPosition(); point = glm::inverse(getRotation()) * point; point /= dimensions; point += 0.5f; point.y = 1.0f - point.y; point *= dimensions * (METERS_TO_INCHES * DPI); if (event->button() == Qt::MouseButton::LeftButton) { if (event->type() == QEvent::MouseButtonPress) { this->_pressed = true; this->_lastMove = ivec2((int)point.x, (int)point.y); } else if (event->type() == QEvent::MouseButtonRelease) { this->_pressed = false; } } if (event->type() == QEvent::MouseMove) { this->_lastMove = ivec2((int)point.x, (int)point.y); } // Forward the mouse event. QMouseEvent mappedEvent(event->type(), QPoint((int)point.x, (int)point.y), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); } }; _mousePressConnection = QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent); _mouseReleaseConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent); _mouseMoveConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent); _hoverLeaveConnection = QObject::connect(renderer, &EntityTreeRenderer::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) { if (this->_pressed && this->getID() == entityItemID) { // If the user mouses off the entity while the button is down, simulate a mouse release QMouseEvent mappedEvent(QEvent::MouseButtonRelease, QPoint(_lastMove.x, _lastMove.y), Qt::MouseButton::LeftButton, Qt::MouseButtons(), Qt::KeyboardModifiers()); QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); } }); return true; }
void Web3DOverlay::render(RenderArgs* args) { QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); if (!_webSurface) { _webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(pickURL()); // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // and the current rendering load) if (_currentMaxFPS != _desiredMaxFPS) { setMaxFPS(_desiredMaxFPS); } loadSourceURL(); _webSurface->resume(); _webSurface->resize(QSize(_resolution.x, _resolution.y)); _webSurface->getRootItem()->setProperty("url", _url); _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); currentContext->makeCurrent(currentSurface); auto selfOverlayID = getOverlayID(); std::weak_ptr<Web3DOverlay> weakSelf = std::dynamic_pointer_cast<Web3DOverlay>(qApp->getOverlays().getOverlay(selfOverlayID)); auto forwardPointerEvent = [=](OverlayID overlayID, const PointerEvent& event) { auto self = weakSelf.lock(); if (self && overlayID == selfOverlayID) { self->handlePointerEvent(event); } }; auto overlays = &(qApp->getOverlays()); QObject::connect(overlays, &Overlays::mousePressOnOverlay, this, forwardPointerEvent); QObject::connect(overlays, &Overlays::mouseReleaseOnOverlay, this, forwardPointerEvent); QObject::connect(overlays, &Overlays::mouseMoveOnOverlay, this, forwardPointerEvent); QObject::connect(overlays, &Overlays::hoverLeaveOverlay, this, [=](OverlayID overlayID, const PointerEvent& event) { auto self = weakSelf.lock(); if (!self) { return; } if (overlayID == selfOverlayID && (self->_pressed || (!self->_activeTouchPoints.empty() && self->_touchBeginAccepted))) { PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(), event.getButton(), event.getButtons(), event.getKeyboardModifiers()); forwardPointerEvent(overlayID, endEvent); } }); QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent); QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived); } else { if (_currentMaxFPS != _desiredMaxFPS) { setMaxFPS(_desiredMaxFPS); } } if (_mayNeedResize) { _mayNeedResize = false; _webSurface->resize(QSize(_resolution.x, _resolution.y)); } if (!_visible || !getParentVisible()) { return; } vec2 halfSize = getSize() / 2.0f; vec4 color(toGlm(getColor()), getAlpha()); Transform transform = getTransform(); // FIXME: applyTransformTo causes tablet overlay to detach from tablet entity. // Perhaps rather than deleting the following code it should be run only if isFacingAvatar() is true? /* applyTransformTo(transform, true); setTransform(transform); */ if (glm::length2(getDimensions()) != 1.0f) { transform.postScale(vec3(getDimensions(), 1.0f)); } if (!_texture) { auto webSurface = _webSurface; _texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); _texture->setSource(__FUNCTION__); } OffscreenQmlSurface::TextureAndFence newTextureAndFence; bool newTextureAvailable = _webSurface->fetchTexture(newTextureAndFence); if (newTextureAvailable) { _texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second); } Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; batch.setResourceTexture(0, _texture); batch.setModelTransform(transform); auto geometryCache = DependencyManager::get<GeometryCache>(); if (color.a < OPAQUE_ALPHA_THRESHOLD) { geometryCache->bindTransparentWebBrowserProgram(batch, _isAA); } else { geometryCache->bindOpaqueWebBrowserProgram(batch, _isAA); } geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color, _geometryId); batch.setResourceTexture(0, nullptr); // restore default white color after me }
void ResultRecorder::startResults(const QString &id) { // sub process will get all this. // safer that way, as then we keep OpenGL (and QGuiApplication) out of the host if (!Options::instance.isSubProcess) return; m_results["id"] = id; QString prettyProductName = #if QT_VERSION >= 0x050400 QSysInfo::prettyProductName(); #else # if defined(Q_OS_IOS) QStringLiteral("iOS"); # elif defined(Q_OS_OSX) QString::fromLatin1("OSX %d").arg(QSysInfo::macVersion()); # elif defined(Q_OS_WIN) QString::fromLatin1("Windows %d").arg(QSysInfo::windowsVersion()); # elif defined(Q_OS_LINUX) QStringLiteral("Linux"); # elif defined(Q_OS_ANDROID) QStringLiteral("Android"); # else QStringLiteral("unknown"); # endif #endif QVariantMap osMap; osMap["prettyProductName"] = prettyProductName; osMap["platformPlugin"] = QGuiApplication::platformName(); m_results["os"] = osMap; m_results["qt"] = QT_VERSION_STR; m_results["command-line"] = qApp->arguments().join(' '); // The following code makes the assumption that an OpenGL context the GUI // thread will get the same capabilities as the render thread's OpenGL // context. Not 100% accurate, but it works... QOpenGLContext context; context.create(); QOffscreenSurface surface; // In very odd cases, we can get incompatible configs here unless we pass the // GL context's format on to the offscreen format. surface.setFormat(context.format()); surface.create(); if (!context.makeCurrent(&surface)) { qWarning() << "failed to acquire GL context to get version info."; return; } QOpenGLFunctions *func = context.functions(); #if QT_VERSION >= 0x050300 const char *vendor = (const char *) func->glGetString(GL_VENDOR); const char *renderer = (const char *) func->glGetString(GL_RENDERER); const char *version = (const char *) func->glGetString(GL_VERSION); #else Q_UNUSED(func); const char *vendor = (const char *) glGetString(GL_VENDOR); const char *renderer = (const char *) glGetString(GL_RENDERER); const char *version = (const char *) glGetString(GL_VERSION); #endif if (!Options::instance.printJsonToStdout) { std::cout << "ID: " << id.toStdString() << std::endl; std::cout << "OS: " << prettyProductName.toStdString() << std::endl; std::cout << "QPA: " << QGuiApplication::platformName().toStdString() << std::endl; std::cout << "GL_VENDOR: " << vendor << std::endl; std::cout << "GL_RENDERER: " << renderer << std::endl; std::cout << "GL_VERSION: " << version << std::endl; } QVariantMap glInfo; glInfo["vendor"] = vendor; glInfo["renderer"] = renderer; glInfo["version"] = version; m_results["opengl"] = glInfo; context.doneCurrent(); }
void RenderableWebEntityItem::render(RenderArgs* args) { QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); if (!_webSurface) { _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); _webSurface->load("WebEntity.qml"); _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _sourceUrl); _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _webSurface->lockTexture(textureId); assert(!glGetError()); // TODO change to atomic<GLuint>? withLock(_textureLock, [&] { std::swap(_texture, textureId); }); if (textureId) { _webSurface->releaseTexture(textureId); } if (_texture) { _webSurface->makeCurrent(); glBindTexture(GL_TEXTURE_2D, _texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); _webSurface->doneCurrent(); } }); auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { // Ignore mouse interaction if we're locked if (this->getLocked()) { return; } if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonPress) { const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); _lastPress = toGlm(mouseEvent->pos()); } } if (intersection.entityID == getID()) { if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonRelease) { const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); ivec2 dist = glm::abs(toGlm(mouseEvent->pos()) - _lastPress); if (!glm::any(glm::greaterThan(dist, ivec2(1)))) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack"); }); } _lastPress = ivec2(INT_MIN); } return; } // FIXME doesn't work... double click events not received if (event->type() == QEvent::MouseButtonDblClick) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); } if (event->button() == Qt::MouseButton::MiddleButton) { if (event->type() == QEvent::MouseButtonRelease) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); } return; } // Map the intersection point to an actual offscreen pixel glm::vec3 point = intersection.intersection; point -= getPosition(); point = glm::inverse(getRotation()) * point; point /= getDimensions(); point += 0.5f; point.y = 1.0f - point.y; point *= getDimensions() * METERS_TO_INCHES * DPI; // Forward the mouse event. QMouseEvent mappedEvent(event->type(), QPoint((int)point.x, (int)point.y), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); } }; EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer); QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent); QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent); QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent); } glm::vec2 dims = glm::vec2(getDimensions()); dims *= METERS_TO_INCHES * DPI; // The offscreen surface is idempotent for resizes (bails early // if it's a no-op), so it's safe to just call resize every frame // without worrying about excessive overhead. _webSurface->resize(QSize(dims.x, dims.y)); currentContext->makeCurrent(currentSurface); PerformanceTimer perfTimer("RenderableWebEntityItem::render"); Q_ASSERT(getType() == EntityTypes::Web); static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; batch.setModelTransform(getTransformToCenter()); bool textured = false, culled = false, emissive = false; if (_texture) { batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); textured = emissive = true; } DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, textured, culled, emissive); DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f)); }
void tst_QOpenGL::QTBUG15621_triangulatingStrokerDivZero() { #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__) QSKIP("QTBUG-22617"); #endif QWindow window; window.setSurfaceType(QWindow::OpenGLSurface); window.setGeometry(0, 0, 128, 128); window.create(); QOpenGLContext ctx; ctx.create(); ctx.makeCurrent(&window); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); QOpenGLFramebufferObject fbo(128, 128); fbo.bind(); QOpenGLPaintDevice device(128, 128); // QTBUG-15621 is only a problem when qreal is double, but do the test anyway. qreal delta = sizeof(qreal) == sizeof(float) ? 1e-4 : 1e-8; QVERIFY(128 != 128 + delta); QPainterPath path; path.moveTo(16 + delta, 16); path.moveTo(16, 16); path.lineTo(16 + delta, 16); // Short lines to check for division by zero. path.lineTo(112 - delta, 16); path.lineTo(112, 16); path.quadTo(112, 16, 112, 16 + delta); path.quadTo(112, 64, 112, 112 - delta); path.quadTo(112, 112, 112, 112); path.cubicTo(112, 112, 112, 112, 112 - delta, 112); path.cubicTo(80, 112, 48, 112, 16 + delta, 112); path.cubicTo(16 + delta, 112, 16 + delta, 112, 16, 112); path.closeSubpath(); QPen pen(Qt::red, 28, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); QPainter p(&device); p.fillRect(QRect(0, 0, 128, 128), Qt::blue); p.strokePath(path, pen); p.end(); QImage image = fbo.toImage().convertToFormat(QImage::Format_RGB32); const QRgb red = 0xffff0000; const QRgb blue = 0xff0000ff; QCOMPARE(image.pixel(8, 8), red); QCOMPARE(image.pixel(119, 8), red); QCOMPARE(image.pixel(8, 119), red); QCOMPARE(image.pixel(119, 119), red); QCOMPARE(image.pixel(0, 0), blue); QCOMPARE(image.pixel(127, 0), blue); QCOMPARE(image.pixel(0, 127), blue); QCOMPARE(image.pixel(127, 127), blue); QCOMPARE(image.pixel(32, 32), blue); QCOMPARE(image.pixel(95, 32), blue); QCOMPARE(image.pixel(32, 95), blue); QCOMPARE(image.pixel(95, 95), blue); }
void OculusWin32DisplayPlugin::preRender() { ovr_GetEyePoses(_hmd, 0, _eyeOffsets, _eyePoses, nullptr); bool result = _context->makeCurrent(_window); Q_ASSERT(result); }
void Thumbnail::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *widget) { QRectF parentRect = parentItem()->sceneBoundingRect(); // Skip drawing thumbnails outside their parents if (!sceneBoundingRect().intersects(parentRect)) return; prePaint(painter, widget); // Draw image if(!img.isNull()) { auto imgRect = QRectF(img.rect()); imgRect.moveCenter(rect.center()); painter->drawImage(imgRect.topLeft(), img); } // Draw 3D mesh if(mesh.points.size() || auxMeshes.size()) { if (img.isNull() || isTempImage) { auto glwidget = (Viewer*)widget; if (glwidget) { QOpenGLContext context; context.setShareContext(glwidget->context()); context.setFormat(glwidget->format()); context.create(); QOffscreenSurface m_offscreenSurface; m_offscreenSurface.setFormat(context.format()); m_offscreenSurface.create(); context.makeCurrent(&m_offscreenSurface); QOpenGLFramebufferObjectFormat fboformat; fboformat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); QOpenGLFramebufferObject renderFbo(rect.width() * 2, rect.height() * 2, fboformat); renderFbo.bind(); glwidget->glEnable(GL_DEPTH_TEST); glwidget->glEnable(GL_BLEND); glwidget->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glwidget->glCullFace(GL_BACK); glwidget->glClearColor(0,0,0,0); glwidget->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glwidget->glViewport(0, 0, renderFbo.size().width(), renderFbo.size().height()); if(mesh.points.size()) glwidget->drawTriangles(mesh.color, mesh.points, mesh.normals, pvm); // Draw aux meshes for (auto auxmesh : auxMeshes) glwidget->drawTriangles(auxmesh.color, auxmesh.points, auxmesh.normals, pvm); glwidget->glDisable(GL_DEPTH_TEST); glwidget->glFlush(); renderFbo.release(); this->setImage( renderFbo.toImage().scaledToWidth(rect.width(), Qt::SmoothTransformation) ); // Thanks for sharing! glwidget->makeCurrent(); } /*painter->beginNativePainting(); auto glwidget = (Viewer*)widget; if (glwidget) { // Draw mesh auto r = sceneBoundingRect(); auto v = scene()->views().first(); QPoint viewDelta = v->mapFromScene(r.topLeft()); if (viewDelta.manhattanLength() > 5) r.moveTopLeft(viewDelta); glwidget->eyePos = eye; glwidget->pvm = pvm; glwidget->glViewport(r.left(), v->height() - r.height() - r.top(), r.width(), r.height()); // Clipping OpenGL glwidget->glEnable(GL_SCISSOR_TEST); glwidget->glScissor(parentRect.x(), v->height() - parentRect.height() - parentRect.top(), parentRect.width(), parentRect.height()); glwidget->glClear(GL_DEPTH_BUFFER_BIT); glwidget->drawTriangles(mesh.color, mesh.points, mesh.normals, pvm); // Draw aux meshes for (auto auxmesh : auxMeshes) { glwidget->drawTriangles(auxmesh.color, auxmesh.points, auxmesh.normals, pvm); } glwidget->glDisable(GL_SCISSOR_TEST); } painter->endNativePainting();*/ } } // Draw the caption if(caption.size()) { painter->setPen(QPen(Qt::white,1)); auto textRect = rect; textRect.setHeight(painter->fontMetrics().height() * 1.25); textRect.moveBottom(rect.height() - textRect.height() * 0.5); painter->drawText(textRect, caption, Qt::AlignVCenter | Qt::AlignHCenter); } postPaint(painter, widget); }
void makeCurrent() { QOpenGLContext* glContext = QOpenGLContext::currentContext(); if (m_surface && glContext) glContext->makeCurrent(m_surface.get()); }