diff options
Diffstat (limited to 'src/opengl/qglpixelbuffer.cpp')
-rw-r--r-- | src/opengl/qglpixelbuffer.cpp | 117 |
1 files changed, 106 insertions, 11 deletions
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index d9480c4994..135f2edd01 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -92,7 +92,10 @@ \sa {opengl/pbuffers}{Pbuffers Example} */ +#include <private/qopenglextensions_p.h> + #include <QtCore/qglobal.h> +#include <QtGui/qopenglframebufferobject.h> #include "gl2paintengineex/qpaintengineex_opengl2_p.h" @@ -129,16 +132,7 @@ void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &form req_format = format; req_shareWidget = shareWidget; invalid = false; - qctx = new QGLContext(format); - qctx->d_func()->sharing = (shareWidget != 0); - if (shareWidget != 0 && shareWidget->d_func()->glcx) { - QGLContextGroup::addShare(qctx, shareWidget->d_func()->glcx); - shareWidget->d_func()->glcx->d_func()->sharing = true; - } - glDevice.setPBuffer(q); - qctx->d_func()->paintDevice = q; - qctx->d_func()->valid = true; } } @@ -198,7 +192,6 @@ QGLPixelBuffer::~QGLPixelBuffer() if (current != d->qctx) makeCurrent(); d->cleanup(); - delete d->qctx; if (current && current != d->qctx) current->makeCurrent(); } @@ -217,6 +210,17 @@ bool QGLPixelBuffer::makeCurrent() 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; } @@ -306,14 +310,39 @@ bool QGLPixelBuffer::doneCurrent() void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const { Q_D(const QGLPixelBuffer); - if (d->invalid) + if (d->invalid || !d->fbo) + return; + + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (!ctx) return; + +#undef glBindFramebuffer + +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER 0x8CA8 +#endif + +#ifndef GL_DRAW_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#endif + + QOpenGLExtensions extensions(ctx); + + if (d->blit_fbo) { + QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo); + extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle()); + } + glBindTexture(GL_TEXTURE_2D, texture_id); #ifndef QT_OPENGL_ES glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, d->req_size.width(), d->req_size.height(), 0); #else glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0); #endif + + if (d->blit_fbo) + extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->d_func()->current_fbo); } /*! @@ -521,4 +550,70 @@ QGLFormat QGLPixelBuffer::format() const \internal */ +bool QGLPixelBufferPrivate::init(const QSize &, const QGLFormat &f, QGLWidget *shareWidget) +{ + widget = new QGLWidget(f, 0, shareWidget); + widget->resize(1, 1); + qctx = const_cast<QGLContext *>(widget->context()); + return widget->isValid(); +} + +bool QGLPixelBufferPrivate::cleanup() +{ + delete fbo; + fbo = 0; + delete blit_fbo; + blit_fbo = 0; + delete widget; + widget = 0; + return true; +} + +bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id) +{ + Q_UNUSED(texture_id); + return false; +} + +void QGLPixelBuffer::releaseFromDynamicTexture() +{ +} + +GLuint QGLPixelBuffer::generateDynamicTexture() const +{ + Q_D(const QGLPixelBuffer); + if (!d->fbo) + return 0; + + if (d->fbo->format().samples() > 0 + && QOpenGLExtensions(QOpenGLContext::currentContext()) + .hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit)) + { + if (!d->blit_fbo) + const_cast<QOpenGLFramebufferObject *&>(d->blit_fbo) = new QOpenGLFramebufferObject(d->req_size); + } else { + return d->fbo->texture(); + } + + GLuint texture; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0, + GL_RGBA, GL_UNSIGNED_BYTE, 0); + + return texture; +} + +bool QGLPixelBuffer::hasOpenGLPbuffers() +{ + return QOpenGLFramebufferObject::hasOpenGLFramebufferObjects(); +} + QT_END_NAMESPACE |