void SVG::renderToTexture(const QRectF& textureRect, QGLFramebufferObjectPtr targetFbo) { saveGLState(); // generate and set view box in logical coordinates QRectF viewbox(svgExtents_.x() + textureRect.x() * svgExtents_.width(), svgExtents_.y() + textureRect.y() * svgExtents_.height(), textureRect.width() * svgExtents_.width(), textureRect.height() * svgExtents_.height()); svgRenderer_.setViewBox(viewbox); // Multisampled FBO for anti-aliased rendering QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setSamples(MULTI_SAMPLE_ANTI_ALIASING_SAMPLES); QGLFramebufferObjectPtr renderFbo( new QGLFramebufferObject( targetFbo->size(), format )); // Render to multisampled FBO QPainter painter(renderFbo.get()); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); svgRenderer_.render(&painter); painter.end(); // Copy to texture FBO QGLFramebufferObject::blitFramebuffer( targetFbo.get(), QRect(0, 0, renderFbo->width(), renderFbo->height()), renderFbo.get(), QRect(0, 0, renderFbo->width(), renderFbo->height())); glBindTexture(GL_TEXTURE_2D, targetFbo->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); restoreGLState(); }
void FBORenderStrategy::createFBOs(const QSize& size) { if (multisampleFBO && resolveFBO && resolveFBO->size() == size) return; // Create a multisample FBO and an FBO to resolve into QGLFramebufferObjectFormat fboFormat; fboFormat.setSamples(4); fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); delete multisampleFBO; multisampleFBO = new QGLFramebufferObject(size, fboFormat); delete resolveFBO; resolveFBO = new QGLFramebufferObject(size); }
QPaintEngine* QGLPixmapData::paintEngine() const { if (!isValid()) return 0; if (m_renderFbo) return m_engine; if (useFramebufferObjects()) { extern QGLWidget* qt_gl_share_widget(); if (!QGLContext::currentContext()) qt_gl_share_widget()->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setSamples(4); format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB)); m_renderFbo = qgl_fbo_pool()->acquire(size(), format); if (m_renderFbo) { if (!m_engine) m_engine = new QGL2PaintEngineEx; return m_engine; } qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine"; } // If the application wants to paint into the QPixmap, we first // force it to QImage format and then paint into that. // This is simpler than juggling multiple GL contexts. const_cast<QGLPixmapData *>(this)->forceToImage(); if (m_hasFillColor) { m_source.fill(PREMUL(m_fillColor.rgba())); m_hasFillColor = false; } return m_source.paintEngine(); }
QPaintEngine* QGLPixmapData::paintEngine() const { if (!isValid()) return 0; if (m_renderFbo) return m_engine; if (useFramebufferObjects()) { extern QGLWidget* qt_gl_share_widget(); if (!QGLContext::currentContext()) const_cast<QGLContext *>(qt_gl_share_context())->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_context()); QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setSamples(4); format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB)); m_renderFbo = qgl_fbo_pool()->acquire(size(), format); if (m_renderFbo) { if (!m_engine) m_engine = new QGL2PaintEngineEx; return m_engine; } qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine"; } m_dirty = true; if (m_source.size() != size()) m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied); if (m_hasFillColor) { m_source.fill(PREMUL(m_fillColor.rgba())); m_hasFillColor = false; } return m_source.paintEngine(); }
static PyObject *meth_QGLFramebufferObjectFormat_setSamples(PyObject *sipSelf, PyObject *sipArgs) { PyObject *sipParseErr = NULL; { int a0; QGLFramebufferObjectFormat *sipCpp; if (sipParseArgs(&sipParseErr, sipArgs, "Bi", &sipSelf, sipType_QGLFramebufferObjectFormat, &sipCpp, &a0)) { Py_BEGIN_ALLOW_THREADS sipCpp->setSamples(a0); Py_END_ALLOW_THREADS Py_INCREF(Py_None); return Py_None; } } /* Raise an exception if the arguments couldn't be parsed. */ sipNoMethod(sipParseErr, sipName_QGLFramebufferObjectFormat, sipName_setSamples, doc_QGLFramebufferObjectFormat_setSamples); return NULL; }
GLWidget::GLWidget(QWidget *parent) : QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::AlphaChannel), parent) { setWindowTitle(tr("OpenGL framebuffer objects")); makeCurrent(); if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) { QGLFramebufferObjectFormat format; format.setSamples(4); format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); render_fbo = new QGLFramebufferObject(512, 512, format); texture_fbo = new QGLFramebufferObject(512, 512); } else { render_fbo = new QGLFramebufferObject(1024, 1024); texture_fbo = render_fbo; } rot_x = rot_y = rot_z = 0.0f; scale = 0.1f; anim = new QTimeLine(750, this); anim->setUpdateInterval(20); connect(anim, SIGNAL(valueChanged(qreal)), SLOT(animate(qreal))); connect(anim, SIGNAL(finished()), SLOT(animFinished())); svg_renderer = new QSvgRenderer(QLatin1String(":/res/bubbles.svg"), this); connect(svg_renderer, SIGNAL(repaintNeeded()), this, SLOT(draw())); logo = QImage(":/res/designer.png"); logo = logo.convertToFormat(QImage::Format_ARGB32); tile_list = glGenLists(1); glNewList(tile_list, GL_COMPILE); glBegin(GL_QUADS); { glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); } glEnd(); glEndList(); wave = new GLfloat[logo.width()*logo.height()]; memset(wave, 0, logo.width()*logo.height()); startTimer(30); // wave timer }
void Layer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QtPainter *qvpainter = NULL; #ifdef QT_OPENGL_LIB QPainter *fboPainter; QGLFramebufferObject *fbo = NULL; QGLWidget *qglWidget = qobject_cast<QGLWidget *>(widget); if (qglWidget) { // on-screen OpenGL QGLContext *context = const_cast<QGLContext *>(qglWidget->context()); qvpainter = new OpenGLPainter(painter, context); } else if (cacheMode() != QGraphicsItem::NoCache && QGLFramebufferObject::hasOpenGLFramebufferObjects()) { // caching, try FBO // if we have direct rendering and FBO support, make use of // FBO, but this could still just be in software // NOTE: In Qt 4.6, 'painter' would already target an FBO, if we // were using the 'OpenGL2' paint engine. We have decided to stick // with the original engine for now, as the OpenGL2 engine relies // heavily on shaders, which is slow for our use case. // Apparently, we must use the QGLContext associated with // the view being painted. Thus, PlotView tracks whether it is // inside a paintEvent, so we can get the current QGLWidget. OverlayScene *overlayScene = qobject_cast<OverlayScene *>(scene()); if (overlayScene) qglWidget = qobject_cast<QGLWidget *>(overlayScene->view()->viewport()); else { QList<QGraphicsView *> views = scene()->views(); for (int i = 0; i < views.size() && !qglWidget; i++) { PlotView *view = qobject_cast<PlotView *>(views[i]); if (view && view->isPainting()) qglWidget = qobject_cast<QGLWidget *>(view->viewport()); } } if (qglWidget) { QSize size(painter->device()->width(), painter->device()->height()); QGLContext *context = const_cast<QGLContext *>(qglWidget->context()); // GC during paint callback may have reset this if (qglWidget->context() != QGLContext::currentContext()) qglWidget->makeCurrent(); // NOTE: need Qt 4.6 for antialiasing to work with FBOs #if QT_VERSION >= 0x40600 if (!fboMultisamplingFailed) { QGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); fboFormat.setSamples(4); // 4X antialiasing should be enough? qInstallMsgHandler(fboDebugMsgCatcher); fbo = new QGLFramebufferObject(size, fboFormat); qInstallMsgHandler(0); if (fboMultisamplingFailed) { delete fbo; fbo = NULL; } } #endif if (!fbo) fbo = new QGLFramebufferObject(size); // clear the FBO fboPainter = new QPainter(fbo); fboPainter->setCompositionMode(QPainter::CompositionMode_Source); fboPainter->fillRect(0, 0, size.width(), size.height(), Qt::transparent); fboPainter->setCompositionMode(QPainter::CompositionMode_SourceOver); qvpainter = new OpenGLPainter(fboPainter, context); qvpainter->setTransform(painter->worldTransform()); } } #endif if (!qvpainter) // fallback to Qt renderer qvpainter = new QtPainter(painter); // NOTE: in QT 4.6 exposedRect will just be the bounding rect, by default paintPlot(qvpainter, option->exposedRect); delete qvpainter; #ifdef QT_OPENGL_LIB if (fbo) { // silliness: download to image, only to upload to texture painter->setWorldMatrixEnabled(false); qglWidget->makeCurrent(); // gc during callback may have cleared this // need to tell Qt that 'fboImage' is actually premultiplied QImage fboImage = fbo->toImage(); const uchar *data = fboImage.bits(); // no deep copy QImage premultImage = QImage(data, fboImage.width(), fboImage.height(), QImage::Format_ARGB32_Premultiplied); // Not sure why this can't be (0, 0)... painter->drawImage(QPointF(1, -1), premultImage); delete fboPainter; delete fbo; } #endif }
void MouseMagnifyingGlassInteractorComponent::generateMagnifyingGlassTexture(const Coord &magnifyingGlassCenterScr) { bool antialiased = false; bool canUseMultisampleFbo = OpenGlConfigManager::getInst().isExtensionSupported("GL_EXT_framebuffer_multisample"); if (QGLFramebufferObject::hasOpenGLFramebufferBlit() && canUseMultisampleFbo) { antialiased = true; } int fboSize = static_cast<int>(radius * 2); // instantiate fbo if needed if (fbo == NULL) { QGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); if (antialiased) { fboFormat.setSamples(OpenGlConfigManager::getInst().maxNumberOfSamples()); } fbo = new QGLFramebufferObject(fboSize, fboSize, fboFormat); if (antialiased) { fbo2 = new QGLFramebufferObject(fboSize, fboSize); } if (!antialiased) { GlTextureManager::getInst().registerExternalTexture(textureName, fbo->texture()); } else { GlTextureManager::getInst().registerExternalTexture(textureName, fbo2->texture()); } } Vector<int, 4> viewport = glWidget->getScene()->getViewport(); // get the magnifying glass bounding box in screen space BoundingBox boundingBox; boundingBox[0] = Coord(magnifyingGlassCenterScr.getX() - radius, magnifyingGlassCenterScr.getY() - radius); boundingBox[1] = Coord(magnifyingGlassCenterScr.getX() + radius, magnifyingGlassCenterScr.getY() + radius); // compute the zoom factor to apply to scene's camera to get the area under the magnifying glass displayed entirely in the viewport float bbWidthScreen = boundingBox[1][0] - boundingBox[0][0]; float bbHeightScreen = boundingBox[1][1] - boundingBox[0][1]; float startSize = glWidget->screenToViewport(min(glWidget->width(), glWidget->height())); float endSize = max(bbHeightScreen, bbWidthScreen); float zoomFactor = startSize / endSize; // backup current camera parameters float sceneRadiusBak = camera->getSceneRadius(); float zoomFactorBak = camera->getZoomFactor(); Coord eyesBak = camera->getEyes(); Coord centerBak = camera->getCenter(); Coord upBak = camera->getUp(); Coord move = boxCenter - centerBak; camera->setCenter(camera->getCenter() + move); camera->setEyes(camera->getEyes() + move); camera->setZoomFactor(magnifyPower * zoomFactor * zoomFactorBak); glPushAttrib(GL_ALL_ATTRIB_BITS); glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); // resize the viewport to the size of fbo and render the scene into this last one GlScene *scene = glWidget->getScene(); scene->setViewport(0, 0, fboSize, fboSize); fbo->bind(); Color color = scene->getBackgroundColor(); glClearColor(color.getRGL(), color.getGGL(), color.getBGL(), color.getAGL()); glClear(GL_COLOR_BUFFER_BIT); scene->draw(); fbo->release(); if (antialiased) { QGLFramebufferObject::blitFramebuffer(fbo2, QRect(0,0,fboSize, fboSize), fbo, QRect(0,0,fboSize, fboSize)); } // restore original camera parameters scene->setViewport(viewport[0], viewport[1], viewport[2], viewport[3]); camera->setSceneRadius(sceneRadiusBak); camera->setZoomFactor(zoomFactorBak); camera->setEyes(eyesBak); camera->setCenter(centerBak); camera->setUp(upBak); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); // need to call this explicitely otherwise we have to redraw the scene glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); }
void QwtPlotGLCanvas::paintGL() { const bool hasFocusIndicator = hasFocus() && focusIndicator() == CanvasFocusIndicator; QPainter painter; #if QT_VERSION < 0x040600 painter.begin( this ); draw( &painter ); #else if ( testPaintAttribute( QwtPlotGLCanvas::BackingStore ) ) { if ( d_data->fbo == NULL || d_data->fbo->size() != size() ) { invalidateBackingStore(); const int numSamples = 16; QGLFramebufferObjectFormat format; format.setSamples( numSamples ); format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); QGLFramebufferObject fbo( size(), format ); QPainter fboPainter( &fbo ); draw( &fboPainter); fboPainter.end(); d_data->fbo = new QGLFramebufferObject( size() ); QRect rect(0, 0, width(), height()); QGLFramebufferObject::blitFramebuffer(d_data->fbo, rect, &fbo, rect); } // drawTexture( QRectF( -1.0, 1.0, 2.0, -2.0 ), d_data->fbo->texture() ); if ( hasFocusIndicator ) painter.begin( this ); glBindTexture(GL_TEXTURE_2D, d_data->fbo->texture()); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); } else { painter.begin( this ); draw( &painter ); } #endif if ( hasFocus() && focusIndicator() == CanvasFocusIndicator ) drawFocusIndicator( &painter ); }