Exemplo n.º 1
0
void TApplication::initializeGL() {

    // Init shaders
    if (!Shader.addShaderFromSourceFile(QGLShader::Vertex, "vert.glsl")) {
        qFatal("failed to load shader vert.glsl");
    }
    if (!Shader.addShaderFromSourceFile(QGLShader::Fragment, "frag.glsl")) {
        qFatal("failed to load shader frag.glsl");
    }
    if (!Shader.link()) {
        qFatal("failed to link shader planet");
    }
    if (!Shader.bind()) {
        qFatal("failed to bind shader");
    }

    // Init framebuffers
    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    format.setSamples(8);
    Fbo.reset(new QOpenGLFramebufferObject(WINDOW_WIDTH, WINDOW_HEIGHT, format));

    QOpenGLFramebufferObjectFormat format1;
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    Fbo1.reset(new QOpenGLFramebufferObject(WINDOW_WIDTH, WINDOW_HEIGHT, format1));


    // Load model and textures

    Obj = LoadJsonModel("model.json");
    ObjectSize = Obj.size();

    VertexBuff.reset(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
    VertexBuff->create();
    VertexBuff->bind();
    VertexBuff->setUsagePattern(QOpenGLBuffer::StaticDraw);
    VertexBuff->allocate(Obj.data(), Obj.size() * sizeof(TVertex));
    VertexBuff->release();

    Texture.reset(new QOpenGLTexture(QImage("diffuse.jpg")));
    Texture->bind();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    Texture->release();

    NormalMap.reset(new QOpenGLTexture(QImage("normal.jpg")));
    NormalMap->bind();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    NormalMap->release();

    // Initial angles
    AngleX = 0;
    AngleY = 0;
    AngleZ = 0;

    Paused = false;
}
Exemplo n.º 2
0
 QOpenGLFramebufferObject *createFramebufferObject(const QSize &size)
 {
     QOpenGLFramebufferObjectFormat format;
     format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
     format.setSamples(4);
     return new QOpenGLFramebufferObject(size, format);
 }
void tst_QOpenGL::fboSimpleRendering()
{
    QFETCH(int, surfaceClass);
    QScopedPointer<QSurface> surface(createSurface(surfaceClass));

    QOpenGLContext ctx;
    ctx.create();

    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::NoAttachment);

    QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(200, 100, fboFormat);

    fbo->bind();

    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);

    delete fbo;
}
Exemplo n.º 4
0
void RenderSurface::render(QPainter *painter)
{
    Q_UNUSED(painter);

    QOpenGLFramebufferObjectFormat fboFormat;
    fboFormat.setSamples(1);
    fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);

    const QRect drawRect(0, 0, m_outWidth, m_outHeight);
    const QSize drawRectSize = drawRect.size();
    QOpenGLFramebufferObject fbo(drawRectSize, fboFormat);
    fbo.bind();

    glViewport(0, 0, m_outWidth, m_outHeight);

    glClear(GL_COLOR_BUFFER_BIT);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glEnable(GL_BLEND); 
    glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ZERO, GL_ONE);

    m_program->bind();

    int texCount = 0;
    for (size_t i = 0; i < sp.size(); ++i) {
      if (sp[i].bind == ShaderParameter::BindTextureSampler) {
        textures[sp[i].name].obj->bind(texCount);
        m_program->setUniformValue(sp[i].name.c_str(), texCount);
        texCount++;
      } else if (sp[i].bind == ShaderParameter::BindTextureResolution) {
        const QImage& image = textures[sp[i].texture].image;
        m_program->setUniformValue(sp[i].name.c_str(), QVector2D(image.width(),image.height()));
      } else if (sp[i].bind == ShaderParameter::BindGlobalTime) {
        m_program->setUniformValue(sp[i].name.c_str(), m_globalTime);
      } else if (sp[i].bind == ShaderParameter::BindOutputResolution) {
        m_program->setUniformValue(sp[i].name.c_str(), QVector2D(m_outWidth,m_outHeight));
      }
    }

    GLfloat vertices[] = {
      -1.0f,  -1.0f, 0.0f,
      1.0f, -1.0f, 0.0f,
      -1.0f, 1.0f, 0.0f,
      1.0f, 1.0f, 0.0f
    };

    glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices);

    glEnableVertexAttribArray(0);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableVertexAttribArray(0);

    m_program->release();

    imageFrame = fbo.toImage();
}
QOpenGLFramebufferObject* QQuickMapboxGLRenderer::createFramebufferObject(const QSize &size)
{
    m_map->resize(size);

    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);

    return new QOpenGLFramebufferObject(size, format);
}
Exemplo n.º 6
0
bool QGLPixelBuffer::makeCurrent()
{
    Q_D(QGLPixelBuffer);
    if (d->invalid)
        return false;
    d->qctx->makeCurrent();
    if (!d->fbo) {
        QOpenGLFramebufferObjectFormat format;
        if (d->req_format.stencil())
            format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
        else if (d->req_format.depth())
            format.setAttachment(QOpenGLFramebufferObject::Depth);
        if (d->req_format.sampleBuffers())
            format.setSamples(d->req_format.samples());
        d->fbo = new QOpenGLFramebufferObject(d->req_size, format);
        d->fbo->bind();
    }
    return true;
}
Exemplo n.º 7
0
QOpenGLFramebufferObject* COglRenderer::createFramebufferObject(const QSize &size)
{
    // create opengl FBO
    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    format.setSamples(4);
    m_oglFBO = new QOpenGLFramebufferObject(size, format);

    // return opengl FBO
    return m_oglFBO;
}
Exemplo n.º 8
0
bool QGLPixelBuffer::makeCurrent()
{
    Q_D(QGLPixelBuffer);
    if (d->invalid)
        return false;
    d->qctx->makeCurrent();
    if (!d->fbo) {
        QOpenGLFramebufferObjectFormat format;
        if (d->req_format.stencil())
            format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
        else if (d->req_format.depth())
            format.setAttachment(QOpenGLFramebufferObject::Depth);
        if (d->req_format.sampleBuffers())
            format.setSamples(d->req_format.samples());
        d->fbo = new QOpenGLFramebufferObject(d->req_size, format);
        d->fbo->bind();
        d->glDevice.setFbo(d->fbo->handle());
        QOpenGLContext::currentContext()->functions()->glViewport(0, 0, d->req_size.width(), d->req_size.height());
    }
    return true;
}
Exemplo n.º 9
0
std::unique_ptr<QOpenGLFramebufferObject>
_createMultisampledFBO( const QSize& size )
{
    QOpenGLFramebufferObjectFormat format;
    format.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil );
    format.setSamples( MULTI_SAMPLE_ANTI_ALIASING_SAMPLES );

    auto fbo = make_unique<QOpenGLFramebufferObject>( size, format );
    fbo->bind();
    auto gl = QOpenGLContext::currentContext()->functions();
    gl->glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    gl->glClear( GL_COLOR_BUFFER_BIT );
    fbo->release();

    return fbo;
}
// 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);
}
Exemplo n.º 11
0
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);
    }
}
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;
}
static PyObject *meth_QOpenGLFramebufferObjectFormat_setAttachment(PyObject *sipSelf, PyObject *sipArgs)
{
    PyObject *sipParseErr = NULL;

    {
        QOpenGLFramebufferObject::Attachment a0;
        QOpenGLFramebufferObjectFormat *sipCpp;

        if (sipParseArgs(&sipParseErr, sipArgs, "BE", &sipSelf, sipType_QOpenGLFramebufferObjectFormat, &sipCpp, sipType_QOpenGLFramebufferObject_Attachment, &a0))
        {
            sipCpp->setAttachment(a0);

            Py_INCREF(Py_None);
            return Py_None;
        }
    }

    /* Raise an exception if the arguments couldn't be parsed. */
    sipNoMethod(sipParseErr, sipName_QOpenGLFramebufferObjectFormat, sipName_setAttachment, doc_QOpenGLFramebufferObjectFormat_setAttachment);

    return NULL;
}
Exemplo n.º 14
0
void GLImageProcessor::initialize()
{
	initializeOpenGLFunctions();

	texture.reset(new QOpenGLTexture(image.mirrored()));
	texture->setWrapMode(QOpenGLTexture::WrapMode::ClampToEdge);
	texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
	texture->setMagnificationFilter(QOpenGLTexture::Linear);

	program.reset(buildProgram());
	program->release();

	plotProgram.reset(buildPassthorughProgram());
	plotProgram->release();

	vao.create();
	vao.bind();
	vbo.reset(buildQuadTextured());
	vao.release();

	QOpenGLFramebufferObjectFormat format;
	format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
	renderFbo.reset(new QOpenGLFramebufferObject(image.size(), format));
}
Exemplo n.º 15
0
int indexAt( /*GLuint *buffer,*/ NifModel * model, Scene * scene, QList<DrawFunc> drawFunc, int cycle, const QPoint & pos, int & furn )
{
	Q_UNUSED( model ); Q_UNUSED( cycle );
	// Color Key O(1) selection
	//	Open GL 3.0 says glRenderMode is deprecated
	//	ATI OpenGL API implementation of GL_SELECT corrupts NifSkope memory
	//
	// Create FBO for sharp edges and no shading.
	// Texturing, blending, dithering, lighting and smooth shading should be disabled.
	// The FBO can be used for the drawing operations to keep the drawing operations invisible to the user.

	GLint viewport[4];
	glGetIntegerv( GL_VIEWPORT, viewport );

	// Create new FBO with multisampling disabled
	QOpenGLFramebufferObjectFormat fboFmt;
	fboFmt.setTextureTarget( GL_TEXTURE_2D );
	fboFmt.setInternalTextureFormat( GL_RGB32F_ARB );
	fboFmt.setAttachment( QOpenGLFramebufferObject::Attachment::CombinedDepthStencil );

	QOpenGLFramebufferObject fbo( viewport[2], viewport[3], fboFmt );
	fbo.bind();

	glEnable( GL_LIGHTING );
	glDisable( GL_MULTISAMPLE );
	glDisable( GL_MULTISAMPLE_ARB );
	glDisable( GL_LINE_SMOOTH );
	glDisable( GL_POINT_SMOOTH );
	glDisable( GL_POLYGON_SMOOTH );
	glDisable( GL_TEXTURE_1D );
	glDisable( GL_TEXTURE_2D );
	glDisable( GL_TEXTURE_3D );
	glDisable( GL_BLEND );
	glDisable( GL_DITHER );
	glDisable( GL_FOG );
	glDisable( GL_LIGHTING );
	glShadeModel( GL_FLAT );
	glEnable( GL_DEPTH_TEST );
	glDepthFunc( GL_LEQUAL );
	glClearColor( 0, 0, 0, 1 );
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	// Rasterize the scene
	Node::SELECTING = 1;
	for ( DrawFunc df : drawFunc ) {
		(scene->*df)();
	}
	Node::SELECTING = 0;

	fbo.release();

	QImage img( fbo.toImage() );
	QColor pixel = img.pixel( pos );

#ifndef QT_NO_DEBUG
	img.save( "fbo.png" );
#endif

	// Encode RGB to Int
	int a = 0;
	a |= pixel.red()   << 0;
	a |= pixel.green() << 8;
	a |= pixel.blue()  << 16;

	// Decode:
	// R = (id & 0x000000FF) >> 0
	// G = (id & 0x0000FF00) >> 8
	// B = (id & 0x00FF0000) >> 16

	int choose = COLORKEY2ID( a );

	// Pick BSFurnitureMarker
	if ( choose > 0 ) {
		auto furnBlock = model->getBlock( model->index( 3, 0, model->getBlock( choose & 0x0ffff ) ), "BSFurnitureMarker" );

		if ( furnBlock.isValid() ) {
			furn = choose >> 16;
			choose &= 0x0ffff;
		}
 QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override {
     m_heightMapRenderer.setAspectRatio(size.width(), size.height());
     QOpenGLFramebufferObjectFormat format;
     format.setAttachment(QOpenGLFramebufferObject::Depth);
     return new QOpenGLFramebufferObject(size, format);
 }
Exemplo n.º 17
0
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'.
}
Exemplo n.º 18
0
int main(int argc, char **argv)
{
#ifdef CONSOLE_APPLICATION
    QApplication app(argc, argv, QApplication::Tty);
#else
    QApplication app(argc, argv);
#endif
#ifdef DO_QWS_DEBUGGING
    qt_show_painter_debug_output = false;
#endif

    DeviceType type = WidgetType;
    bool checkers_background = true;

    QImage::Format imageFormat = QImage::Format_ARGB32_Premultiplied;

    QLocale::setDefault(QLocale::c());

    QStringList files;

    bool interactive = false;
    bool printdlg = false;
    bool highres = false;
    bool show_cmp = false;
    int width = 800, height = 800;
    int scaledWidth = width, scaledHeight = height;
    qreal scalefactor = 1.0;
    bool verboseMode = false;

#ifndef QT_NO_OPENGL
    QGLFormat f = QGLFormat::defaultFormat();
    f.setSampleBuffers(true);
    f.setStencil(true);
    f.setAlpha(true);
    f.setAlphaBufferSize(8);
    QGLFormat::setDefaultFormat(f);
#endif

    char *arg;
    for (int i=1; i<argc; ++i) {
        arg = argv[i];
        if (*arg == '-') {
            QString option = QString(arg + 1).toLower();
            if (option == "widget")
                type = WidgetType;
            else if (option == "bitmap")
                type = BitmapType;
            else if (option == "pixmap")
                type = PixmapType;
            else if (option == "image")
                type = ImageType;
            else if (option == "imageformat") {
                Q_ASSERT_X(i + 1 < argc, "main", "-imageformat must be followed by a value");
                QString format = QString(argv[++i]).toLower();

                imageFormat = QImage::Format_Invalid;
                static const int formatCount =
                    sizeof(imageFormats) / sizeof(imageFormats[0]);
                for (int ff = 0; ff < formatCount; ++ff) {
                    if (QLatin1String(imageFormats[ff].name) == format) {
                        imageFormat = imageFormats[ff].format;
                        break;
                    }
                }

                if (imageFormat == QImage::Format_Invalid) {
                    printf("Invalid image format.  Available formats are:\n");
                    for (int ff = 0; ff < formatCount; ++ff)
                        printf("\t%s\n", imageFormats[ff].name);
                    return -1;
                }
            } else if (option == "imagemono")
                type = ImageMonoType;
            else if (option == "imagewidget")
                type = ImageWidgetType;
#ifndef QT_NO_OPENGL
            else if (option == "opengl")
                type = OpenGLType;
            else if (option == "glbuffer")
                type = OpenGLBufferType;
#endif
#ifdef USE_CUSTOM_DEVICE
            else if (option == "customdevice")
                type = CustomDeviceType;
            else if (option == "customwidget")
                type = CustomWidgetType;
#endif
            else if (option == "pdf")
                type = PdfType;
            else if (option == "ps")
                type = PsType;
            else if (option == "picture")
                type = PictureType;
            else if (option == "printer")
                type = PrinterType;
            else if (option == "highres") {
                type = PrinterType;
                highres = true;
            } else if (option == "printdialog") {
                type = PrinterType;
                printdlg = true;
            }
            else if (option == "grab")
                type = GrabType;
            else if (option == "i")
                interactive = true;
            else if (option == "v")
                verboseMode = true;
            else if (option == "commands") {
                displayCommands();
                return 0;
            } else if (option == "w") {
                Q_ASSERT_X(i + 1 < argc, "main", "-w must be followed by a value");
                width = atoi(argv[++i]);
            } else if (option == "h") {
                Q_ASSERT_X(i + 1 < argc, "main", "-h must be followed by a value");
                height = atoi(argv[++i]);
            } else if (option == "scalefactor") {
                Q_ASSERT_X(i + 1 < argc, "main", "-scalefactor must be followed by a value");
                scalefactor = atof(argv[++i]);
            } else if (option == "cmp") {
                show_cmp = true;
            } else if (option == "bg-white") {
                checkers_background = false;
            }
        } else {
#if defined (Q_WS_WIN)
            QString input = QString::fromLocal8Bit(argv[i]);
            if (input.indexOf('*') >= 0) {
                QFileInfo info(input);
                QDir dir = info.dir();
                QFileInfoList infos = dir.entryInfoList(QStringList(info.fileName()));
                for (int ii=0; ii<infos.size(); ++ii)
                    files.append(infos.at(ii).absoluteFilePath());
            } else {
                files.append(input);
            }
#else
            files.append(QString(argv[i]));
#endif
        }
    }
    scaledWidth = width * scalefactor;
    scaledHeight = height * scalefactor;

    PaintCommands pcmd(QStringList(), 800, 800);
    pcmd.setVerboseMode(verboseMode);
    pcmd.setType(type);
    pcmd.setCheckersBackground(checkers_background);

    QWidget *activeWidget = 0;

    if (interactive) {
        runInteractive();
        if (!files.isEmpty())
            interactive_widget->load(files.at(0));
    } else if (files.isEmpty()) {
        printHelp();
        return 0;
    } else {
        for (int j=0; j<files.size(); ++j) {
            const QString &fileName = files.at(j);
            QStringList content;

            QFile file(fileName);
            QFileInfo fileinfo(file);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream textFile(&file);
                QString script = textFile.readAll();
                content = script.split("\n", QString::SkipEmptyParts);
            } else {
                printf("failed to read file: '%s'\n", qPrintable(fileinfo.absoluteFilePath()));
                continue;
            }
            pcmd.setContents(content);

            if (show_cmp) {
                QString pmFile = QString(files.at(j)).replace(".qps", "_qps") + ".png";
                qDebug() << pmFile << QFileInfo(pmFile).exists();
                QPixmap pixmap(pmFile);
                if (!pixmap.isNull()) {
                    QLabel *label = createLabel();
                    label->setWindowTitle("VERIFY: " + pmFile);
                    label->setPixmap(pixmap);
                    label->show();
                }
            }

            switch (type) {

            case WidgetType:
            {
                OnScreenWidget<QWidget> *qWidget =
                    new OnScreenWidget<QWidget>(files.at(j));
                qWidget->setVerboseMode(verboseMode);
                qWidget->setType(type);
                qWidget->setCheckersBackground(checkers_background);
                qWidget->m_commands = content;
                qWidget->resize(width, height);
                qWidget->show();
                activeWidget = qWidget;
                break;
            }

            case ImageWidgetType:
            {
                OnScreenWidget<QWidget> *qWidget = new OnScreenWidget<QWidget>(files.at(j));
                qWidget->setVerboseMode(verboseMode);
                qWidget->setType(type);
                qWidget->setCheckersBackground(checkers_background);
                qWidget->m_commands = content;
                qWidget->resize(width, height);
                qWidget->show();
                activeWidget = qWidget;
                break;

            }
#ifndef QT_NO_OPENGL
            case OpenGLBufferType:
            {
                QWindow win;
                win.setSurfaceType(QSurface::OpenGLSurface);
                win.create();
                QOpenGLFramebufferObjectFormat fmt;
                fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
                fmt.setSamples(4);
                QOpenGLContext ctx;
                ctx.create();
                ctx.makeCurrent(&win);
                QOpenGLFramebufferObject fbo(width, height, fmt);
                fbo.bind();
                QOpenGLPaintDevice pdev(width, height);

                QPainter pt(&pdev);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();

                QImage image = fbo.toImage();

                QLabel *label = createLabel();
                label->setPixmap(QPixmap::fromImage(image));
                label->resize(label->sizeHint());
                label->show();
                activeWidget = label;
                break;
            }
            case OpenGLType:
            {
                OnScreenWidget<QGLWidget> *qGLWidget = new OnScreenWidget<QGLWidget>(files.at(j));
                qGLWidget->setVerboseMode(verboseMode);
                qGLWidget->setType(type);
                qGLWidget->setCheckersBackground(checkers_background);
                qGLWidget->m_commands = content;
                qGLWidget->resize(width, height);
                qGLWidget->show();
                activeWidget = qGLWidget;
                break;
            }
#else
            case OpenGLType:
            case OpenGLBufferType:
            {
                printf("OpenGL type not supported in this Qt build\n");
                break;
            }
#endif
#ifdef USE_CUSTOM_DEVICE
            case CustomDeviceType:
            {
                CustomPaintDevice custom(width, height);
                QPainter pt;
                pt.begin(&custom);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();
                QImage *img = custom.image();
                if (img) {
                    QLabel *label = createLabel();
                    label->setPixmap(QPixmap::fromImage(*img));
                    label->resize(label->sizeHint());
                    label->show();
                    activeWidget = label;
                    img->save("custom_output_pixmap.png", "PNG");
                } else {
                    custom.save("custom_output_pixmap.png", "PNG");
                }
                break;
            }
            case CustomWidgetType:
            {
                OnScreenWidget<CustomWidget> *cWidget = new OnScreenWidget<CustomWidget>;
                cWidget->setVerboseMode(verboseMode);
                cWidget->setType(type);
                cWidget->setCheckersBackground(checkers_background);
                cWidget->m_filename = files.at(j);
                cWidget->setWindowTitle(fileinfo.filePath());
                cWidget->m_commands = content;
                cWidget->resize(width, height);
                cWidget->show();
                activeWidget = cWidget;
                break;
            }
#endif
            case PixmapType:
            {
                QPixmap pixmap(scaledWidth, scaledHeight);
                pixmap.setDevicePixelRatio(scalefactor);
                pixmap.fill(Qt::white);
                QPainter pt(&pixmap);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();
                pixmap.save("output_pixmap.png", "PNG");
                break;
            }

            case BitmapType:
            {
                QBitmap bitmap(scaledWidth, scaledHeight);
                bitmap.setDevicePixelRatio(scalefactor);
                QPainter pt(&bitmap);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();
                bitmap.save("output_bitmap.png", "PNG");

                QLabel *label = createLabel();
                label->setPixmap(bitmap);
                label->resize(label->sizeHint());
                label->show();
                activeWidget = label;
                break;
            }

            case ImageMonoType:
            case ImageType:
            {
                qDebug() << "Creating image";
                QImage image(scaledWidth, scaledHeight, type == ImageMonoType
                             ? QImage::Format_MonoLSB
                             : imageFormat);
                image.setDevicePixelRatio(scalefactor);
                image.fill(0);
                QPainter pt(&image);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();
                image.convertToFormat(QImage::Format_ARGB32).save("output_image.png", "PNG");
                image.setDevicePixelRatio(1.0); // reset scale factor: display "large" image.
#ifndef CONSOLE_APPLICATION
                QLabel *label = createLabel();
                label->setPixmap(QPixmap::fromImage(image));
                label->resize(label->sizeHint());
                label->show();
                activeWidget = label;
#endif
                break;
            }

            case PictureType:
            {
                QPicture pic;
                QPainter pt(&pic);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();

                QImage image(width, height, QImage::Format_ARGB32_Premultiplied);
                image.fill(0);
                pt.begin(&image);
                pt.drawPicture(0, 0, pic);
                pt.end();
                QLabel *label = createLabel();
                label->setWindowTitle(fileinfo.absolutePath());
                label->setPixmap(QPixmap::fromImage(image));
                label->resize(label->sizeHint());
                label->show();
                activeWidget = label;
                break;
            }

            case PrinterType:
            {
#ifndef QT_NO_PRINTER
                PaintCommands pcmd(QStringList(), 800, 800);
                pcmd.setVerboseMode(verboseMode);
                pcmd.setType(type);
                pcmd.setCheckersBackground(checkers_background);
                pcmd.setContents(content);
                QString file = QString(files.at(j)).replace(".", "_") + ".ps";

                QPrinter p(highres ? QPrinter::HighResolution : QPrinter::ScreenResolution);
                if (printdlg) {
                    QPrintDialog printDialog(&p, 0);
                    if (printDialog.exec() != QDialog::Accepted)
                        break;
                } else {
                    p.setOutputFileName(file);
                }

                QPainter pt(&p);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();

                if (!printdlg) {
                    printf("wrote file: %s\n", qPrintable(file));
                }

                Q_ASSERT(!p.paintingActive());
#endif
                break;
            }
            case PsType:
            case PdfType:
            {
#ifndef QT_NO_PRINTER
                PaintCommands pcmd(QStringList(), 800, 800);
                pcmd.setVerboseMode(verboseMode);
                pcmd.setType(type);
                pcmd.setCheckersBackground(checkers_background);
                pcmd.setContents(content);
                QPrinter p(highres ? QPrinter::HighResolution : QPrinter::ScreenResolution);
                QFileInfo input(files.at(j));
                const QString file = input.baseName() + QLatin1Char('_')
                                     + input.suffix() + QStringLiteral(".pdf");
                p.setOutputFormat(QPrinter::PdfFormat);
                p.setOutputFileName(file);
                p.setPageSize(QPrinter::A4);
                QPainter pt(&p);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();

                printf("write file: %s\n", qPrintable(file));
#endif
                break;
            }
            case GrabType:
            {
                QImage image(width, height, QImage::Format_ARGB32_Premultiplied);
                image.fill(QColor(Qt::white).rgb());
                QPainter pt(&image);
                pcmd.setPainter(&pt);
                pcmd.setFilePath(fileinfo.absolutePath());
                pcmd.runCommands();
                pt.end();
                QImage image1(width, height, QImage::Format_RGB32);
                image1.fill(QColor(Qt::white).rgb());
                QPainter pt1(&image1);
                pt1.drawImage(QPointF(0, 0), image);
                pt1.end();

                QString filename = QString(files.at(j)).replace(".qps", "_qps") + ".png";
                image1.save(filename, "PNG");
                printf("%s grabbed to %s\n", qPrintable(files.at(j)), qPrintable(filename));
                break;
            }
            default:
                break;
            }
        }
    }
#ifndef CONSOLE_APPLICATION
    if (activeWidget || interactive) {
        QObject::connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
        app.exec();
    }
    delete activeWidget;
#endif
    delete interactive_widget;
    return 0;
}
Exemplo n.º 19
0
QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
{
    QQuickContext2DTexture::beginPainting();

    if (m_canvasWindow.size().isEmpty()) {
        delete m_fbo;
        delete m_multisampledFbo;
        delete m_paint_device;
        m_fbo = 0;
        m_multisampledFbo = 0;
        m_paint_device = 0;
        return 0;
    } else if (!m_fbo || m_canvasWindowChanged) {
        delete m_fbo;
        delete m_multisampledFbo;
        delete m_paint_device;
        m_paint_device = 0;

        m_fboSize = npotAdjustedSize(m_canvasWindow.size() * m_canvasDevicePixelRatio);
        m_canvasWindowChanged = false;

        if (doMultisampling()) {
            {
                QOpenGLFramebufferObjectFormat format;
                format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
                format.setSamples(8);
                m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format);
            }
            {
                QOpenGLFramebufferObjectFormat format;
                format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
                m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
            }
        } else {
            QOpenGLFramebufferObjectFormat format;
            format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
            QSize s = m_fboSize;
            if (m_antialiasing) { // do supersampling since multisampling is not available
                GLint max;
                QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
                if (s.width() * 2 <= max && s.height() * 2 <= max)
                    s = s * 2;
            }
            m_fbo = new QOpenGLFramebufferObject(s, format);
        }
    }

    if (doMultisampling())
        m_multisampledFbo->bind();
    else
        m_fbo->bind();

    if (!m_paint_device) {
        QOpenGLPaintDevice *gl_device = new QOpenGLPaintDevice(m_fbo->size());
        gl_device->setPaintFlipped(true);
        gl_device->setSize(m_fbo->size());
        gl_device->setDevicePixelRatio(m_canvasDevicePixelRatio);
        qCDebug(lcCanvas, "%s size %.1lf x %.1lf painting with size %d x %d DPR %.1lf",
                (m_item->objectName().isEmpty() ? "Canvas" : qPrintable(m_item->objectName())),
                m_item->width(), m_item->height(), m_fbo->size().width(), m_fbo->size().height(), m_canvasDevicePixelRatio);
        m_paint_device = gl_device;
    }

    return m_paint_device;
}
Exemplo n.º 20
0
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);
}
Exemplo n.º 21
0
void ExploreLiveView::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget * widget)
{
    if(!isReady) return;

	prePaint(painter);

	postPaint(painter);

	auto glwidget = (Viewer*)widget;
    if (glwidget && meshes.size())
	{
		QRectF parentRect = parentItem()->sceneBoundingRect();

        if (isCacheImage && cachedImage.isNull())
        {
            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(cacheImageSize*1.5, cacheImageSize, 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, cacheImageSize*1.5, cacheImageSize);

	// XXX Fix
            // glwidget->glPointSize(10);	

            // Draw aux meshes
            for (auto mesh : meshes)
            {
                if (mesh.isPoints)
                    glwidget->drawOrientedPoints(mesh.points, mesh.normals, mesh.color, glwidget->pvm);
                else
                    glwidget->drawTriangles(mesh.color, mesh.points, mesh.normals, glwidget->pvm);
            }

            glwidget->glDisable(GL_DEPTH_TEST);
            glwidget->glFlush();

            renderFbo.release();

            cachedImage = renderFbo.toImage();
            isReady = true;

            // Thanks for sharing!
            glwidget->makeCurrent();
        }

        // Draw as image
        if(isCacheImage)
        {
            int w = shapeRect.width();
            painter->drawImage(w * -0.5, w * -0.5, cachedImage.scaledToWidth(w));
        }

        if(!isCacheImage)
        {
            auto r = shapeRect;

            // scale view
            double s = 1.5;
            r.setWidth(r.width() * s);
            r.setHeight(r.height() * s);

            r.moveCenter(this->mapToScene(boundingRect().center()));

            painter->beginNativePainting();

            auto v = scene()->views().first();
            QPoint viewDelta = v->mapFromScene(r.topLeft());
            if (viewDelta.manhattanLength() > 5) r.moveTopLeft(viewDelta);

            auto camera = ExploreProcess::defaultCamera(document->extent().length());

            glwidget->eyePos = camera.first;
            glwidget->pvm = camera.second;
            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);

	// FIX  XXX
            // glwidget->glPointSize(2);

            // Draw aux meshes
            for (auto mesh : meshes)
            {
                if (mesh.isPoints)
                    glwidget->drawOrientedPoints(mesh.points, mesh.normals, mesh.color, glwidget->pvm);
                else
                    glwidget->drawTriangles(mesh.color, mesh.points, mesh.normals, glwidget->pvm);
            }

            glwidget->glDisable(GL_SCISSOR_TEST);

            painter->endNativePainting();
        }
	}
}
void QSGPainterNode::updateRenderTarget()
{
    if (!m_extensionsChecked) {
        const QSet<QByteArray> extensions = m_context->openglContext()->extensions();
        m_multisamplingSupported = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample"))
            && extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit"));
        m_extensionsChecked = true;
    }

    m_dirtyContents = true;

    QQuickPaintedItem::RenderTarget oldTarget = m_actualRenderTarget;
    if (m_preferredRenderTarget == QQuickPaintedItem::Image) {
        m_actualRenderTarget = QQuickPaintedItem::Image;
    } else {
        if (!m_multisamplingSupported && m_smoothPainting)
            m_actualRenderTarget = QQuickPaintedItem::Image;
        else
            m_actualRenderTarget = m_preferredRenderTarget;
    }
    if (oldTarget != m_actualRenderTarget) {
        m_image = QImage();
        delete m_fbo;
        delete m_multisampledFbo;
        delete m_gl_device;
        m_fbo = m_multisampledFbo = 0;
        m_gl_device = 0;
    }

    if (m_actualRenderTarget == QQuickPaintedItem::FramebufferObject ||
            m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject) {
        const QOpenGLContext *ctx = m_context->openglContext();
        if (m_fbo && !m_dirtyGeometry && (!ctx->format().samples() || !m_multisamplingSupported))
            return;

        if (m_fboSize.isEmpty())
            updateFBOSize();

        delete m_fbo;
        delete m_multisampledFbo;
        m_fbo = m_multisampledFbo = 0;
        if (m_gl_device)
            m_gl_device->setSize(m_fboSize);

        if (m_smoothPainting && ctx->format().samples() && m_multisamplingSupported) {
            {
                QOpenGLFramebufferObjectFormat format;
                format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
                format.setSamples(8);
                m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format);
            }
            {
                QOpenGLFramebufferObjectFormat format;
                format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
                m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
            }
        } else {
            QOpenGLFramebufferObjectFormat format;
            format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
            m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
        }
    } else {
        if (!m_image.isNull() && !m_dirtyGeometry)
            return;

        m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
        m_image.fill(Qt::transparent);
    }

    QSGPainterTexture *texture = new QSGPainterTexture;
    if (m_actualRenderTarget == QQuickPaintedItem::Image) {
        texture->setOwnsTexture(true);
        texture->setTextureSize(m_size);
    } else {
        texture->setTextureId(m_fbo->texture());
        texture->setOwnsTexture(false);
        texture->setTextureSize(m_fboSize);
    }

    if (m_texture)
        delete m_texture;

    texture->setTextureSize(m_size);
    m_texture = texture;
}