summaryrefslogtreecommitdiffstats
path: root/src/opengl/qpixmapdata_gl.cpp
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2009-07-28 10:25:55 (GMT)
committerSamuel Rødal <sroedal@trolltech.com>2009-07-28 12:19:18 (GMT)
commitdbdc54791e585f3c6bf62c1a091ef844a66483ba (patch)
tree75b5f14c4b1a8176b53b23d93f0b6f7dcc688365 /src/opengl/qpixmapdata_gl.cpp
parent610aa1737a206fe97628a3375a543400ea0761fa (diff)
parent0431548ddffc56f74cc60e7d341ade3920adefb1 (diff)
downloadQt-dbdc54791e585f3c6bf62c1a091ef844a66483ba.zip
Qt-dbdc54791e585f3c6bf62c1a091ef844a66483ba.tar.gz
Qt-dbdc54791e585f3c6bf62c1a091ef844a66483ba.tar.bz2
Merge commit 'qt-graphics-team/pixmapfilters-redux' into kinetic-graphicseffect
Conflicts: src/opengl/gl2paintengineex/qglengineshadermanager.cpp src/opengl/gl2paintengineex/qglengineshadermanager_p.h src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h Merge custom shader / GL blur pixmap filter implementation from graphics team repo with implementation from kinetic graphics-team repo.
Diffstat (limited to 'src/opengl/qpixmapdata_gl.cpp')
-rw-r--r--src/opengl/qpixmapdata_gl.cpp134
1 files changed, 93 insertions, 41 deletions
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index e3ee2b2..c0eed4d 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -55,6 +55,85 @@ QT_BEGIN_NAMESPACE
extern QGLWidget* qt_gl_share_widget();
+/*!
+ \class QGLFramebufferObjectPool
+ \since 4.6
+
+ \brief The QGLFramebufferObject class provides a pool of framebuffer
+ objects for offscreen rendering purposes.
+
+ When requesting an FBO of a given size and format, an FBO of the same
+ format and a size at least as big as the requested size will be returned.
+
+ \internal
+*/
+
+static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
+{
+ return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
+}
+
+QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat)
+{
+ QGLFramebufferObject *chosen = 0;
+ QGLFramebufferObject *candidate = 0;
+ for (int i = 0; !chosen && i < m_fbos.size(); ++i) {
+ QGLFramebufferObject *fbo = m_fbos.at(i);
+
+ QGLFramebufferObjectFormat format = fbo->format();
+ if (format.samples() == requestFormat.samples()
+ && format.attachment() == requestFormat.attachment()
+ && format.textureTarget() == requestFormat.textureTarget()
+ && format.internalFormat() == requestFormat.internalFormat())
+ {
+ // choose the fbo with a matching format and the closest size
+ if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo))
+ candidate = fbo;
+ }
+
+ if (candidate) {
+ m_fbos.removeOne(candidate);
+
+ const QSize fboSize = candidate->size();
+ QSize sz = fboSize;
+
+ if (sz.width() < requestSize.width())
+ sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5)));
+ if (sz.height() < requestSize.height())
+ sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5)));
+
+ // wasting too much space?
+ if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 2.5)
+ sz = requestSize;
+
+ if (sz != fboSize) {
+ delete candidate;
+ qDebug() << "Resizing fbo in pool:" << sz;
+ candidate = new QGLFramebufferObject(sz, requestFormat);
+ }
+
+ chosen = candidate;
+ }
+ }
+
+ if (!chosen) {
+ qDebug() << "Creating new fbo in pool:" << requestSize;
+ chosen = new QGLFramebufferObject(requestSize, requestFormat);
+ }
+
+ if (!chosen->isValid()) {
+ delete chosen;
+ chosen = 0;
+ }
+
+ return chosen;
+}
+
+void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
+{
+ m_fbos << fbo;
+}
+
class QGLShareContextScope
{
public:
@@ -332,8 +411,11 @@ struct TextureBuffer
QGL2PaintEngineEx *engine;
};
-static QVector<TextureBuffer> textureBufferStack;
-static int currentTextureBuffer = 0;
+Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool)
+QGLFramebufferObjectPool* qgl_fbo_pool()
+{
+ return _qgl_fbo_pool();
+}
void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const
{
@@ -380,7 +462,8 @@ void QGLPixmapData::swapBuffers()
copyBackFromRenderFbo(false);
m_renderFbo->release();
- --currentTextureBuffer;
+ qgl_fbo_pool()->release(m_renderFbo);
+ delete m_engine;
m_renderFbo = 0;
m_engine = 0;
@@ -398,19 +481,6 @@ void QGLPixmapData::doneCurrent()
m_renderFbo->release();
}
-static TextureBuffer createTextureBuffer(const QSize &size, QGL2PaintEngineEx *engine = 0)
-{
- TextureBuffer buffer;
- QGLFramebufferObjectFormat fmt;
- fmt.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
- fmt.setSamples(4);
-
- buffer.fbo = new QGLFramebufferObject(size, fmt);
- buffer.engine = engine ? engine : new QGL2PaintEngineEx;
-
- return buffer;
-}
-
bool QGLPixmapData::useFramebufferObjects()
{
return QGLFramebufferObject::hasOpenGLFramebufferObjects()
@@ -433,33 +503,15 @@ QPaintEngine* QGLPixmapData::paintEngine() const
qt_gl_share_widget()->makeCurrent();
QGLShareContextScope ctx(qt_gl_share_widget()->context());
- if (textureBufferStack.size() <= currentTextureBuffer) {
- textureBufferStack << createTextureBuffer(size());
- } else {
- QSize sz = textureBufferStack.at(currentTextureBuffer).fbo->size();
- if (sz.width() < w || sz.height() < h) {
- if (sz.width() < w)
- sz.setWidth(qMax(w, qRound(sz.width() * 1.5)));
- if (sz.height() < h)
- sz.setHeight(qMax(h, qRound(sz.height() * 1.5)));
-
- // wasting too much space?
- if (sz.width() * sz.height() > w * h * 2.5)
- sz = QSize(w, h);
-
- delete textureBufferStack.at(currentTextureBuffer).fbo;
- textureBufferStack[currentTextureBuffer] =
- createTextureBuffer(sz, textureBufferStack.at(currentTextureBuffer).engine);
- qDebug() << "Creating new pixmap texture buffer:" << sz;
- }
- }
-
- if (textureBufferStack.at(currentTextureBuffer).fbo->isValid()) {
- m_renderFbo = textureBufferStack.at(currentTextureBuffer).fbo;
- m_engine = textureBufferStack.at(currentTextureBuffer).engine;
+ QGLFramebufferObjectFormat format;
+ format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ format.setSamples(4);
+ format.setInternalFormat(m_hasAlpha ? GL_RGBA : GL_RGB);
- ++currentTextureBuffer;
+ m_renderFbo = qgl_fbo_pool()->acquire(size(), format);
+ if (m_renderFbo) {
+ m_engine = new QGL2PaintEngineEx;
return m_engine;
}