summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp24
-rw-r--r--src/opengl/qglframebufferobject.cpp9
-rw-r--r--src/opengl/qglframebufferobject_p.h3
-rw-r--r--src/opengl/qglpaintdevice.cpp29
-rw-r--r--src/opengl/qglpaintdevice_p.h4
-rw-r--r--src/opengl/qpixmapdata_gl.cpp116
-rw-r--r--src/opengl/qpixmapdata_gl_p.h52
7 files changed, 152 insertions, 85 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index c280803..e028e63 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1321,7 +1321,6 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->ctx->d_ptr->active_engine = this;
d->last_created_state = 0;
- d->device->beginPaint();
QSize sz = d->device->size();
d->width = sz.width();
d->height = sz.height();
@@ -1333,8 +1332,6 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->shaderManager = new QGLEngineShaderManager(d->ctx);
- glViewport(0, 0, d->width, d->height);
-
d->brushTextureDirty = true;
d->brushUniformsDirty = true;
d->matrixDirty = true;
@@ -1343,10 +1340,12 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->simpleShaderDepthUniformDirty = true;
d->depthUniformDirty = true;
d->opacityUniformDirty = true;
- d->needsSync = false;
-
+ d->needsSync = true;
d->use_system_clip = !systemClip().isEmpty();
+
+ d->device->beginPaint();
+
if (!d->inRenderText) {
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
@@ -1358,21 +1357,6 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
glDisable(GL_MULTISAMPLE);
#endif
-// QGLPixmapData *source = d->drawable.copyOnBegin();
-// if (source) {
-// QGLContext *ctx = d->ctx;
-//
-// d->transferMode(ImageDrawingMode);
-//
-// glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
-// source->bind(false);
-//
-// QRect rect(0, 0, source->width(), source->height());
-// d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
-// d->drawTexture(QRectF(rect), QRectF(rect), rect.size(), true);
-// }
-
- d->systemStateChanged();
return true;
}
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index f60eb62..9dbf5c8 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -299,6 +299,12 @@ bool QGLFramebufferObjectFormat::operator!=(const QGLFramebufferObjectFormat& ot
return !(*this == other);
}
+void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f)
+{
+ fbo = f;
+ m_thisFBO = fbo->d_func()->fbo; // This shouldn't be needed
+}
+
void QGLFBOGLPaintDevice::ensureActiveTarget()
{
QGLContext* ctx = const_cast<QGLContext*>(QGLContext::currentContext());
@@ -377,6 +383,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
ctx = QGLContextPrivate::contextGroup(currentContext);
glDevice.setFBO(q);
+
bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(currentContext)))
return;
@@ -389,6 +396,8 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo);
+ glDevice.setFBO(q);
+
QT_CHECK_GLERROR();
// init texture
if (samples == 0) {
diff --git a/src/opengl/qglframebufferobject_p.h b/src/opengl/qglframebufferobject_p.h
index 65fcf54..58e6505 100644
--- a/src/opengl/qglframebufferobject_p.h
+++ b/src/opengl/qglframebufferobject_p.h
@@ -110,11 +110,12 @@ public:
virtual QPaintEngine* paintEngine() const {return fbo->paintEngine();}
virtual QSize size() const {return fbo->size();}
virtual QGLContext* context() const {return const_cast<QGLContext *>(QGLContext::currentContext());}
- void setFBO(QGLFramebufferObject* f) {fbo = f; }
virtual void ensureActiveTarget();
virtual void beginPaint();
virtual void endPaint();
+ void setFBO(QGLFramebufferObject* f);
+
private:
bool wasBound;
QGLFramebufferObject* fbo;
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
index 4cdeb76..15ea217 100644
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -44,8 +44,10 @@
#include <private/qglpixelbuffer_p.h>
#include <private/qglframebufferobject_p.h>
#include <private/qwindowsurface_gl_p.h>
+#include <private/qpixmapdata_gl_p.h>
QGLPaintDevice::QGLPaintDevice()
+ : m_thisFBO(0)
{
}
@@ -56,14 +58,17 @@ QGLPaintDevice::~QGLPaintDevice()
void QGLPaintDevice::beginPaint()
{
- // Record the currently bound FBO so we can restore it again
- // in endPaint()
+ // Make sure our context is the current one:
QGLContext *ctx = context();
- ctx->makeCurrent();
+ if (ctx != QGLContext::currentContext())
+ ctx->makeCurrent();
+
+ // Record the currently bound FBO so we can restore it again
+ // in endPaint() and bind this device's FBO
m_previousFBO = ctx->d_func()->current_fbo;
- if (m_previousFBO != 0) {
- ctx->d_ptr->current_fbo = 0;
- glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ if (m_previousFBO != m_thisFBO) {
+ ctx->d_ptr->current_fbo = m_thisFBO;
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO);
}
}
@@ -73,8 +78,10 @@ void QGLPaintDevice::ensureActiveTarget()
if (ctx != QGLContext::currentContext())
ctx->makeCurrent();
- if (ctx->d_ptr->current_fbo != 0)
- glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ if (ctx->d_ptr->current_fbo != m_thisFBO) {
+ ctx->d_ptr->current_fbo = m_thisFBO;
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO);
+ }
}
void QGLPaintDevice::endPaint()
@@ -193,6 +200,12 @@ QGLPaintDevice* QGLPaintDevice::getDevice(QPaintDevice* pd)
case QInternal::FramebufferObject:
glpd = &(static_cast<QGLFramebufferObject*>(pd)->d_func()->glDevice);
break;
+ case QInternal::Pixmap: {
+ QPixmapData* pmd = static_cast<QPixmap*>(pd)->pixmapData();
+ Q_ASSERT(pmd->classId() == QPixmapData::OpenGLClass);
+ glpd = static_cast<QGLPixmapData*>(pmd)->glDevice();
+ break;
+ }
default:
qWarning("QGLPaintDevice::getDevice() - Unknown device type %d", pd->devType());
break;
diff --git a/src/opengl/qglpaintdevice_p.h b/src/opengl/qglpaintdevice_p.h
index b0e8826..a175b8c 100644
--- a/src/opengl/qglpaintdevice_p.h
+++ b/src/opengl/qglpaintdevice_p.h
@@ -84,10 +84,10 @@ public:
protected:
// Inline?
// void setContext(QGLContext* c);
-
+ GLuint m_previousFBO;
+ GLuint m_thisFBO;
private:
// QGLContext* m_context;
- GLuint m_previousFBO;
};
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index a394716..ae616a8 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -127,6 +127,76 @@ void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
m_fbos << fbo;
}
+
+QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const
+{
+ return data->paintEngine();
+}
+
+void QGLPixmapGLPaintDevice::beginPaint()
+{
+ if (!data->isValid())
+ return;
+
+ // QGLPaintDevice::beginPaint will store the current binding and replace
+ // it with m_thisFBO:
+ m_thisFBO = data->m_renderFbo->handle();
+ QGLPaintDevice::beginPaint();
+
+ Q_ASSERT(data->paintEngine()->type() == QPaintEngine::OpenGL2);
+
+ // QPixmap::fill() is deferred until now, where we actually need to do the fill:
+ if (data->needsFill()) {
+ const QColor &c = data->fillColor();
+ float alpha = c.alphaF();
+ glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+ else if (!data->isUninitialized()) {
+ // If the pixmap (GL Texture) has valid content (it has been
+ // uploaded from an image or rendered into before), we need to
+ // copy it from the texture to the render FBO.
+
+ // Pass false to tell bind to _not_ copy the FBO into the texture!
+ GLuint texId = data->bind(false);
+
+ QGL2PaintEngineEx* pe = static_cast<QGL2PaintEngineEx*>(data->paintEngine());
+ QRect rect(0, 0, data->width(), data->height());
+ pe->drawTexture(QRectF(rect), texId, rect.size(), QRectF(rect));
+ }
+}
+
+void QGLPixmapGLPaintDevice::endPaint()
+{
+ if (!data->isValid())
+ return;
+
+ data->copyBackFromRenderFbo(false);
+
+ data->m_renderFbo->release();
+ qgl_fbo_pool()->release(data->m_renderFbo);
+ data->m_renderFbo = 0;
+
+ // Base's endPaint will restore the previous FBO binding
+ QGLPaintDevice::endPaint();
+}
+
+QGLContext* QGLPixmapGLPaintDevice::context() const
+{
+ data->ensureCreated();
+ return data->m_ctx;
+}
+
+QSize QGLPixmapGLPaintDevice::size() const
+{
+ return data->size();
+}
+
+void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d)
+{
+ data = d;
+}
+
static int qt_gl_pixmap_serial = 0;
QGLPixmapData::QGLPixmapData(PixelType type)
@@ -139,6 +209,7 @@ QGLPixmapData::QGLPixmapData(PixelType type)
, m_hasAlpha(false)
{
setSerialNumber(++qt_gl_pixmap_serial);
+ m_glDevice.setPixmapData(this);
}
QGLPixmapData::~QGLPixmapData()
@@ -232,11 +303,6 @@ void QGLPixmapData::ensureCreated() const
m_texture.options &= ~QGLContext::MemoryManagedBindOption;
}
-QGLFramebufferObject *QGLPixmapData::fbo() const
-{
- return m_renderFbo;
-}
-
void QGLPixmapData::fromImage(const QImage &image,
Qt::ImageConversionFlags)
{
@@ -412,31 +478,6 @@ void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const
glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
}
-void QGLPixmapData::swapBuffers()
-{
- if (!isValid())
- return;
-
- copyBackFromRenderFbo(false);
- m_renderFbo->release();
-
- qgl_fbo_pool()->release(m_renderFbo);
-
- m_renderFbo = 0;
-}
-
-void QGLPixmapData::makeCurrent()
-{
- if (isValid() && m_renderFbo)
- m_renderFbo->bind();
-}
-
-void QGLPixmapData::doneCurrent()
-{
- if (isValid() && m_renderFbo)
- m_renderFbo->release();
-}
-
bool QGLPixmapData::useFramebufferObjects()
{
return QGLFramebufferObject::hasOpenGLFramebufferObjects()
@@ -485,6 +526,10 @@ QPaintEngine* QGLPixmapData::paintEngine() const
return m_source.paintEngine();
}
+
+// If copyBack is true, bind will copy the contents of the render
+// FBO to the texture (which is not bound to the texture, as it's
+// a multisample FBO).
GLuint QGLPixmapData::bind(bool copyBack) const
{
if (m_renderFbo && copyBack) {
@@ -504,12 +549,6 @@ GLuint QGLPixmapData::bind(bool copyBack) const
return id;
}
-GLuint QGLPixmapData::textureId() const
-{
- ensureCreated();
- return m_texture.id;
-}
-
QGLTexture* QGLPixmapData::texture() const
{
return &m_texture;
@@ -548,4 +587,9 @@ int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
}
}
+QGLPaintDevice *QGLPixmapData::glDevice() const
+{
+ return &m_glDevice;
+}
+
QT_END_NAMESPACE
diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h
index ab1ff47..31ae7c7 100644
--- a/src/opengl/qpixmapdata_gl_p.h
+++ b/src/opengl/qpixmapdata_gl_p.h
@@ -57,12 +57,14 @@
#include "qgl.h"
#include "private/qpixmapdata_p.h"
+#include "private/qglpaintdevice_p.h"
QT_BEGIN_NAMESPACE
class QPaintEngine;
class QGLFramebufferObject;
class QGLFramebufferObjectFormat;
+class QGLPixmapData;
class QGLFramebufferObjectPool
{
@@ -76,31 +78,50 @@ private:
QGLFramebufferObjectPool* qgl_fbo_pool();
+
+class QGLPixmapGLPaintDevice : public QGLPaintDevice
+{
+public:
+ QPaintEngine* paintEngine() const;
+
+ void beginPaint();
+ void endPaint();
+ QGLContext* context() const;
+ QSize size() const;
+
+ void setPixmapData(QGLPixmapData*);
+private:
+ QGLPixmapData *data;
+};
+
+
class QGLPixmapData : public QPixmapData
{
public:
QGLPixmapData(PixelType type);
~QGLPixmapData();
- bool isValid() const;
-
+ // Re-implemented from QPixmapData:
void resize(int width, int height);
- void fromImage(const QImage &image,
- Qt::ImageConversionFlags flags);
+ void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
void copy(const QPixmapData *data, const QRect &rect);
-
bool scroll(int dx, int dy, const QRect &rect);
-
void fill(const QColor &color);
bool hasAlphaChannel() const;
QImage toImage() const;
QPaintEngine *paintEngine() const;
+ int metric(QPaintDevice::PaintDeviceMetric metric) const;
+ // For accessing as a target:
+ QGLPaintDevice *glDevice() const;
+
+ // For accessing as a source:
+ bool isValidContext(const QGLContext *ctx) const;
GLuint bind(bool copyBack = true) const;
- GLuint textureId() const;
QGLTexture *texture() const;
- bool isValidContext(const QGLContext *ctx) const;
+private:
+ bool isValid() const;
void ensureCreated() const;
@@ -109,22 +130,13 @@ public:
bool needsFill() const { return m_hasFillColor; }
QColor fillColor() const { return m_fillColor; }
- QSize size() const { return QSize(w, h); }
-
- QGLFramebufferObject *fbo() const;
- void makeCurrent();
- void doneCurrent();
- void swapBuffers();
-protected:
- int metric(QPaintDevice::PaintDeviceMetric metric) const;
-
-private:
QGLPixmapData(const QGLPixmapData &other);
QGLPixmapData &operator=(const QGLPixmapData &other);
void copyBackFromRenderFbo(bool keepCurrentFboBound) const;
+ QSize size() const { return QSize(w, h); }
static bool useFramebufferObjects();
@@ -145,6 +157,10 @@ private:
mutable bool m_hasFillColor;
mutable bool m_hasAlpha;
+
+ mutable QGLPixmapGLPaintDevice m_glDevice;
+
+ friend class QGLPixmapGLPaintDevice;
};
QT_END_NAMESPACE