void CombinedTexture::create() { if (m_framebuffer) delete m_framebuffer; QOpenGLFramebufferObjectFormat format; format.setMipmap(true); m_framebuffer = new QOpenGLFramebufferObject(m_width, m_height, format); m_framebuffer->bind(); glViewport(0, 0, m_width, m_height); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glEnable(GL_ALPHA_TEST); for (int i = 0; i < m_textures.size(); i++) { Texture *texture = m_textures.at(i).first; float *position = m_textures.at(i).second; texture->bind(); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(position[0], position[1], 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(position[2], position[1], 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(position[2], position[3], 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(position[0], position[3], 0.0f); glEnd(); } m_framebuffer->release(); glBindTexture(GL_TEXTURE_2D, m_framebuffer->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); QOpenGLFunctions gl(QOpenGLContext::currentContext()); gl.initializeOpenGLFunctions(); gl.glGenerateMipmap(GL_TEXTURE_2D); m_created = true; }
void QQuickContext2DFBOTile::setRect(const QRect& r) { if (m_rect == r) return; m_rect = r; m_dirty = true; if (!m_fbo || m_fbo->size() != r.size()) { QOpenGLFramebufferObjectFormat format; format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); format.setInternalTextureFormat(GL_RGBA); format.setMipmap(false); if (m_painter.isActive()) m_painter.end(); delete m_fbo; m_fbo = new QOpenGLFramebufferObject(r.size(), format); } }
static PyObject *meth_QOpenGLFramebufferObjectFormat_setMipmap(PyObject *sipSelf, PyObject *sipArgs) { PyObject *sipParseErr = NULL; { bool a0; QOpenGLFramebufferObjectFormat *sipCpp; if (sipParseArgs(&sipParseErr, sipArgs, "Bb", &sipSelf, sipType_QOpenGLFramebufferObjectFormat, &sipCpp, &a0)) { sipCpp->setMipmap(a0); Py_INCREF(Py_None); return Py_None; } } /* Raise an exception if the arguments couldn't be parsed. */ sipNoMethod(sipParseErr, sipName_QOpenGLFramebufferObjectFormat, sipName_setMipmap, doc_QOpenGLFramebufferObjectFormat_setMipmap); return NULL; }
void SSGQuickLayer::grab() { if (!m_item || m_size.isNull()) { delete m_fbo; delete m_secondaryFbo; m_fbo = m_secondaryFbo = 0; m_depthStencilBuffer.clear(); m_dirtyTexture = false; return; } QSGNode *root = m_item; while (root->firstChild() && root->type() != QSGNode::RootNodeType) root = root->firstChild(); if (root->type() != QSGNode::RootNodeType) return; if (!m_renderer) { m_renderer = m_context->createRenderer(); connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture())); } m_renderer->setDevicePixelRatio(m_device_pixel_ratio); m_renderer->setRootNode(static_cast<QSGRootNode *>(root)); QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); bool deleteFboLater = false; if (!m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format || (!m_fbo->format().mipmap() && m_mipmap)) { if (!m_multisamplingChecked) { if (m_context->openglContext()->format().samples() <= 1) { m_multisampling = false; } else { const QSet<QByteArray> extensions = m_context->openglContext()->extensions(); m_multisampling = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample")) && extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit")); } m_multisamplingChecked = true; } if (m_multisampling) { // Don't delete the FBO right away in case it is used recursively. deleteFboLater = true; delete m_secondaryFbo; QOpenGLFramebufferObjectFormat format; format.setInternalTextureFormat(m_format); format.setSamples(m_context->openglContext()->format().samples()); m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format); m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo); } else { QOpenGLFramebufferObjectFormat format; format.setInternalTextureFormat(m_format); format.setMipmap(m_mipmap); if (m_recursive) { deleteFboLater = true; delete m_secondaryFbo; m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format); funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture()); updateBindOptions(true); m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo); } else { delete m_fbo; delete m_secondaryFbo; m_fbo = new QOpenGLFramebufferObject(m_size, format); m_secondaryFbo = 0; funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); updateBindOptions(true); m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_fbo); } } } if (m_recursive && !m_secondaryFbo) { // m_fbo already created, m_recursive was just set. Q_ASSERT(m_fbo); Q_ASSERT(!m_multisampling); m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format()); funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture()); updateBindOptions(true); } // Render texture. root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update. m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update. #ifdef QSG_DEBUG_FBO_OVERLAY if (qmlFboOverlay()) { if (!m_debugOverlay) m_debugOverlay = new QSGSimpleRectNode(); m_debugOverlay->setRect(QRectF(0, 0, m_size.width(), m_size.height())); m_debugOverlay->setColor(QColor(0xff, 0x00, 0x80, 0x40)); root->appendChildNode(m_debugOverlay); } #endif m_dirtyTexture = false; m_renderer->setDeviceRect(m_size); m_renderer->setViewportRect(m_size); QRectF mirrored(m_mirrorHorizontal ? m_rect.right() : m_rect.left(), m_mirrorVertical ? m_rect.bottom() : m_rect.top(), m_mirrorHorizontal ? -m_rect.width() : m_rect.width(), m_mirrorVertical ? -m_rect.height() : m_rect.height()); m_renderer->setProjectionMatrixToRect(mirrored); m_renderer->setClearColor(Qt::transparent); if (m_multisampling) { m_renderer->renderScene(BindableFbo(m_secondaryFbo, m_depthStencilBuffer.data())); if (deleteFboLater) { delete m_fbo; QOpenGLFramebufferObjectFormat format; format.setInternalTextureFormat(m_format); format.setAttachment(QOpenGLFramebufferObject::NoAttachment); format.setMipmap(m_mipmap); format.setSamples(0); m_fbo = new QOpenGLFramebufferObject(m_size, format); funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); updateBindOptions(true); } QRect r(QPoint(), m_size); QOpenGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r); } else { if (m_recursive) { m_renderer->renderScene(BindableFbo(m_secondaryFbo, m_depthStencilBuffer.data())); if (deleteFboLater) { delete m_fbo; QOpenGLFramebufferObjectFormat format; format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); format.setInternalTextureFormat(m_format); format.setMipmap(m_mipmap); m_fbo = new QOpenGLFramebufferObject(m_size, format); funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); updateBindOptions(true); } qSwap(m_fbo, m_secondaryFbo); } else { m_renderer->renderScene(BindableFbo(m_fbo, m_depthStencilBuffer.data())); } } if (m_mipmap) { funcs->glBindTexture(GL_TEXTURE_2D, textureId()); funcs->glGenerateMipmap(GL_TEXTURE_2D); } root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update. #ifdef QSG_DEBUG_FBO_OVERLAY if (qmlFboOverlay()) root->removeChildNode(m_debugOverlay); #endif if (m_recursive) markDirtyTexture(); // Continuously update if 'live' and 'recursive'. }