QImage QEglGLPixmapData::toImage() const { TRACE(); // We should not do so many toImage calls alltogether. This is what is slowing us down right now. // QWK should keep a cache of transformed images instead of re-doing it every frame. // FIXME make QWebKit not do so many QPixmap(QImage(pixmap.toImage).transform()) style transformations. if (!isValid()) return QImage(); if (!m_source.isNull()) { return m_source; } else if (m_dirty || m_hasFillColor) { m_source = fillImage(m_fillColor); return m_source; } else { ensureCreated(); } // read the image from the FBO to memory if(m_fbo) { // we read the data back from the fbo m_ctx->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); // this does glReadPixels - not very fast! QImage temp=qt_gl_read_framebuffer(QSize(w, h), true, true); glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); m_source=temp; m_ctx->doneCurrent(); return temp; } else if (m_texture.id) { // we read back from the texture by binding its id as a framebuffer // is this in the OpenGL standard? It seems to work m_ctx->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_texture.id); // this does glReadPixels - not very fast QImage temp=qt_gl_read_framebuffer(QSize(w, h), true, true); glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); // should we cache the fetched image locally to speed up future access? // m_source=temp; m_ctx->doneCurrent(); return temp; } else { QImage temp(w,h, QImage::Format_ARGB32_Premultiplied); // FIXME indicating something went wrong, neither of above cases worked - look out for yellow images temp.fill(Qt::yellow); m_source=temp; return temp; } }
/*! \fn QImage QGLFramebufferObject::toImage() const Returns the contents of this framebuffer object as a QImage. */ QImage QGLFramebufferObject::toImage() const { Q_D(const QGLFramebufferObject); if (!d->valid) return QImage(); // qt_gl_read_framebuffer doesn't work on a multisample FBO if (format().samples() != 0) { QGLFramebufferObject temp(size(), QGLFramebufferObjectFormat()); QRect rect(QPoint(0, 0), size()); blitFramebuffer(&temp, rect, const_cast<QGLFramebufferObject *>(this), rect); return temp.toImage(); } bool wasBound = isBound(); if (!wasBound) const_cast<QGLFramebufferObject *>(this)->bind(); QImage image = qt_gl_read_framebuffer(d->size, format().internalTextureFormat() != GL_RGB, true); if (!wasBound) const_cast<QGLFramebufferObject *>(this)->release(); return image; }
void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity) { m_context->markLayerComposited(); blitMultisampleFramebufferAndRestoreContext(); if (textureMapper->accelerationMode() == TextureMapper::OpenGLMode) { TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper); TextureMapperGL::Flags flags = TextureMapperGL::ShouldFlipTexture | (m_context->m_attrs.alpha ? TextureMapperGL::ShouldBlend : 0); IntSize textureSize(m_context->m_currentWidth, m_context->m_currentHeight); texmapGL->drawTexture(m_context->m_texture, flags, textureSize, targetRect, matrix, opacity); return; } // Alternatively read pixels to a memory buffer. GraphicsContext* context = textureMapper->graphicsContext(); QPainter* painter = context->platformContext(); painter->save(); painter->setTransform(matrix); painter->setOpacity(opacity); const int height = m_context->m_currentHeight; const int width = m_context->m_currentWidth; painter->beginNativePainting(); makeCurrentIfNeeded(); glBindFramebuffer(GL_FRAMEBUFFER, m_context->m_fbo); QImage offscreenImage = qt_gl_read_framebuffer(QSize(width, height), true, true); glBindFramebuffer(GL_FRAMEBUFFER, m_context->m_state.boundFBO); painter->endNativePainting(); painter->drawImage(targetRect, offscreenImage); painter->restore(); }
/*! Returns the contents of the pbuffer as a QImage. */ QImage QGLPixelBuffer::toImage() const { Q_D(const QGLPixelBuffer); if (d->invalid) return QImage(); const_cast<QGLPixelBuffer *>(this)->makeCurrent(); return qt_gl_read_framebuffer(d->req_size, d->format.alpha(), true); }
QImage QSGWindowsRenderLoop::grab(QQuickWindow *window) { RLDEBUG("grab"); if (!m_gl) return QImage(); m_gl->makeCurrent(window); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); d->polishItems(); d->syncSceneGraph(); d->renderSceneGraph(window->size()); QImage image = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), false, false); return image; }
QImage QSGWindowsRenderLoop::grab(QQuickWindow *window) { RLDEBUG("grab"); if (!m_gl) return QImage(); m_gl->makeCurrent(window); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); d->polishItems(); d->syncSceneGraph(); d->renderSceneGraph(window->size()); bool alpha = window->format().alphaBufferSize() > 0 && window->color().alpha() != 255; QImage image = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), alpha, alpha); return image; }
void QQuickTrivialWindowManager::renderWindow(QQuickWindow *window) { bool renderWithoutShowing = QQuickWindowPrivate::get(window)->renderWithoutShowing; if ((!window->isExposed() && !renderWithoutShowing) || !m_windows.contains(window)) return; WindowData &data = const_cast<WindowData &>(m_windows[window]); QQuickWindow *masterWindow = 0; if (!window->isVisible() && !renderWithoutShowing) { // Find a "proper surface" to bind... for (QHash<QQuickWindow *, WindowData>::const_iterator it = m_windows.constBegin(); it != m_windows.constEnd() && !masterWindow; ++it) { if (it.key()->isVisible()) masterWindow = it.key(); } } else { masterWindow = window; } if (!masterWindow) return; if (!QQuickWindowPrivate::get(masterWindow)->isRenderable()) { qWarning().nospace() << "Unable to find a renderable master window " << masterWindow << "when trying to render" << window << " (" << window->geometry() << ")."; return; } if (!gl) { gl = new QOpenGLContext(); gl->setFormat(masterWindow->requestedFormat()); gl->create(); if (!gl->makeCurrent(masterWindow)) qWarning("QQuickWindow: makeCurrent() failed..."); sg->initialize(gl); } else { gl->makeCurrent(masterWindow); } bool alsoSwap = data.updatePending; data.updatePending = false; QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); cd->polishItems(); int renderTime = 0, syncTime = 0; QTime renderTimer; if (qquick_render_timing()) renderTimer.start(); cd->syncSceneGraph(); if (qquick_render_timing()) syncTime = renderTimer.elapsed(); cd->renderSceneGraph(window->size()); if (qquick_render_timing()) renderTime = renderTimer.elapsed() - syncTime; if (data.grabOnly) { grabContent = qt_gl_read_framebuffer(window->size(), false, false); data.grabOnly = false; } if (alsoSwap && window->isVisible()) { gl->swapBuffers(window); cd->fireFrameSwapped(); } if (qquick_render_timing()) { static QTime lastFrameTime = QTime::currentTime(); const int swapTime = renderTimer.elapsed() - renderTime - syncTime; qDebug() << "- Breakdown of frame time; sync:" << syncTime << "ms render:" << renderTime << "ms swap:" << swapTime << "ms total:" << swapTime + renderTime + syncTime << "ms time since last frame:" << (lastFrameTime.msecsTo(QTime::currentTime())) << "ms"; lastFrameTime = QTime::currentTime(); } // Might have been set during syncSceneGraph() if (data.updatePending) maybeUpdate(window); }