diff options
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 38 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 56 | ||||
-rw-r--r-- | src/opengl/qgl.h | 2 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 8 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject.cpp | 16 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_gl.cpp | 236 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_gl_p.h | 19 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 34 |
8 files changed, 311 insertions, 98 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index e166b54..fe70020 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -175,6 +175,8 @@ public: // Clipping & state stuff stolen from QOpenGLPaintEngine: void updateDepthClip(); uint use_system_clip : 1; + + QPaintEngine *last_engine; }; @@ -616,7 +618,6 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) const QPointF* const points = reinterpret_cast<const QPointF*>(path.points()); - // Check to see if there's any hints if (path.shape() == QVectorPath::RectangleHint) { QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y()); @@ -1034,6 +1035,14 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) qt_resolve_version_1_3_functions(d->ctx); qt_resolve_glsl_extensions(d->ctx); + d->last_engine = d->ctx->d_ptr->active_engine; + d->ctx->d_ptr->active_engine = this; + + if (d->last_engine) { + QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(d->last_engine); + static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr)->transferMode(DefaultMode); + } + if (!d->shaderManager) d->shaderManager = new QGLPEXShaderManager(d->ctx); @@ -1054,6 +1063,19 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->use_system_clip = !systemClip().isEmpty(); glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + + QGLPixmapData *source = d->drawable.copyOnBegin(); + if (source) { + d->transferMode(ImageDrawingMode); + + source->bind(); + + glDisable(GL_BLEND); + + QRect rect(0, 0, source->width(), source->height()); + d->drawTexture(QRectF(rect), QRectF(rect), rect.size()); + } updateClipRegion(QRegion(), Qt::NoClip); return true; @@ -1067,6 +1089,20 @@ bool QGL2PaintEngineEx::end() d->transferMode(DefaultMode); d->drawable.swapBuffers(); d->drawable.doneCurrent(); + d->ctx->d_ptr->active_engine = d->last_engine; + + if (d->last_engine) { + QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(d->last_engine); + QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + + glViewport(0, 0, p->width, p->height); + engine->setState(engine->state()); + p->updateDepthClip(); + } + return false; } diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index fc11d90..32531e7 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1295,6 +1295,7 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) eglContext = 0; #endif pbo = 0; + fbo = 0; crWin = false; initDone = false; sharing = false; @@ -1303,6 +1304,7 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) version_flags_cached = false; version_flags = QGLFormat::OpenGL_Version_None; current_fbo = 0; + active_engine = 0; } QGLContext* QGLContext::currentCtx = 0; @@ -1313,12 +1315,8 @@ QGLContext* QGLContext::currentCtx = 0; QGLFramebufferObject::toImage() */ -QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) +static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha) { - QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); - int w = size.width(); - int h = size.height(); - glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { // OpenGL gives RGBA; Qt wants ARGB uint *p = (uint*)img.bits(); @@ -1341,7 +1339,27 @@ QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB img = img.rgbSwapped(); } - return img.mirrored(); + img = img.mirrored(); +} + +QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) +{ + QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); + int w = size.width(); + int h = size.height(); + glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + convertFromGLImage(img, w, h, alpha_format, include_alpha); + return img; +} + +QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha) +{ + QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); + int w = size.width(); + int h = size.height(); + glGetTexImage(qt_gl_preferredTextureTarget(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + convertFromGLImage(img, w, h, alpha_format, include_alpha); + return img; } // returns the highest number closest to v, which is a power of 2 @@ -4235,6 +4253,15 @@ void QGLDrawable::setDevice(QPaintDevice *pdev) #ifdef Q_WS_QWS wsurf = 0; #endif + + if (pdev->devType() == QInternal::Pixmap) { + QPixmapData *data = static_cast<QPixmap *>(pdev)->pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::OpenGLClass); + pixmapData = static_cast<QGLPixmapData *>(data); + + fbo = pixmapData->fbo(); + } + if (pdev->devType() == QInternal::Widget) widget = static_cast<QGLWidget *>(pdev); else if (pdev->devType() == QInternal::Pbuffer) @@ -4261,7 +4288,9 @@ void QGLDrawable::swapBuffers() void QGLDrawable::makeCurrent() { - if (widget) + if (pixmapData) + pixmapData->beginPaint(); + else if (widget) widget->makeCurrent(); else if (buffer) buffer->makeCurrent(); @@ -4274,9 +4303,18 @@ void QGLDrawable::makeCurrent() } } +QGLPixmapData *QGLDrawable::copyOnBegin() const +{ + if (!pixmapData || pixmapData->isUninitialized()) + return 0; + return pixmapData; +} + void QGLDrawable::doneCurrent() { - if (fbo && !wasBound) + if (pixmapData) + pixmapData->endPaint(); + else if (fbo && !wasBound) fbo->release(); } @@ -4285,6 +4323,8 @@ QSize QGLDrawable::size() const if (widget) { return QSize(widget->d_func()->glcx->device()->width(), widget->d_func()->glcx->device()->height()); + } else if (pixmapData) { + return pixmapData->size(); } else if (buffer) { return buffer->size(); } else if (fbo) { diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index 32fbce2..19d779a 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -372,8 +372,8 @@ private: friend QGLContextPrivate *qt_phonon_get_dptr(const QGLContext *); #endif friend class QGLFramebufferObject; -#ifdef Q_WS_WIN friend class QGLFramebufferObjectPrivate; +#ifdef Q_WS_WIN friend bool qt_resolve_GLSL_functions(QGLContext *ctx); friend bool qt_createGLSLProgram(QGLContext *ctx, GLuint &program, const char *shader_src, GLuint &shader); #endif diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 8ab73d8..51c07b5 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -60,6 +60,7 @@ #include "QtCore/qthreadstorage.h" #include "QtCore/qhash.h" #include "private/qwidget_p.h" +#include "private/qpixmapdata_gl_p.h" #ifndef QT_OPENGL_ES_1_CL #define q_vertexType float @@ -238,6 +239,7 @@ public: QGLFormat glFormat; QGLFormat reqFormat; GLuint pbo; + GLuint fbo; uint valid : 1; uint sharing : 1; @@ -255,6 +257,7 @@ public: GLint max_texture_size; GLuint current_fbo; + QPaintEngine *active_engine; #ifdef Q_WS_WIN static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->extensionFuncs; } @@ -289,7 +292,7 @@ class QGLWindowSurface; class QGLDrawable { public: QGLDrawable() : widget(0), buffer(0), fbo(0) - , wsurf(0) + , wsurf(0), pixmapData(0) {} void setDevice(QPaintDevice *pdev); void swapBuffers(); @@ -303,6 +306,8 @@ public: QGLContext *context() const; bool autoFillBackground() const; + QGLPixmapData *copyOnBegin() const; + private: bool wasBound; QGLWidget *widget; @@ -313,6 +318,7 @@ private: #else QGLWindowSurface *wsurf; #endif + QGLPixmapData *pixmapData; }; // GL extension definitions diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 61d0f85..f86205a 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -475,7 +475,7 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At fbo_attachment = QGLFramebufferObject::NoAttachment; } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); if (!valid) { if (color_buffer) glDeleteRenderbuffersEXT(1, &color_buffer); @@ -825,18 +825,17 @@ bool QGLFramebufferObject::release() return false; Q_D(QGLFramebufferObject); QGL_FUNC_CONTEXT; - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - d->valid = d->checkFramebufferStatus(); d->bound = false; + const QGLContext *context = QGLContext::currentContext(); - if (d->valid && context) { + if (context) { // Restore the previous setting for stacked framebuffer objects. context->d_ptr->current_fbo = d->previous_fbo; - if (d->previous_fbo) - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, d->previous_fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, d->previous_fbo); d->previous_fbo = 0; } - return d->valid; + + return true; } /*! @@ -1148,8 +1147,7 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q tx0, ty0, tx1, ty1, buffers, filter); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); } QT_END_NAMESPACE diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index ec71fa6..0656880 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qpixmap.h" +#include "qglframebufferobject.h" #include <private/qpaintengine_raster_p.h> @@ -48,6 +49,12 @@ #include <private/qgl_p.h> #include <private/qdrawhelper_p.h> +#if 1 || defined(QT_OPENGL_ES_2) +#include <private/qpaintengineex_opengl2_p.h> +#else +#include <private/qpaintengine_opengl_p.h> +#endif + QT_BEGIN_NAMESPACE extern QGLWidget* qt_gl_share_widget(); @@ -89,48 +96,16 @@ private: QGLContext *m_ctx; }; -void qt_gl_convertFromGLImage(QImage *img) -{ - const int w = img->width(); - const int h = img->height(); - - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { - uint *p = (uint*)img->bits(); - uint *end = p + w*h; - - while (p < end) { - uint a = *p << 24; - *p = (*p >> 8) | a; - p++; - } - - *img = img->mirrored(); - } else { - // mirror image - uint *data = (uint *)img->bits(); - - const int mid = h/2; - - for (int y = 0; y < mid; ++y) { - uint *p = data + y * w; - uint *end = p + w; - uint *q = data + (h - y - 1) * w; - - while (p < end) - qSwap(*p++, *q++); - } - } -} - - static int qt_gl_pixmap_serial = 0; QGLPixmapData::QGLPixmapData(PixelType type) : QPixmapData(type, OpenGLClass) , m_width(0) , m_height(0) + , m_renderFbo(0) + , m_textureId(0) + , m_engine(0) , m_ctx(0) - , m_texture(0) , m_dirty(false) { setSerialNumber(++qt_gl_pixmap_serial); @@ -138,10 +113,11 @@ QGLPixmapData::QGLPixmapData(PixelType type) QGLPixmapData::~QGLPixmapData() { - if (m_texture && qt_gl_share_widget()) { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glDeleteTextures(1, &m_texture); - } + QGLWidget *shareWidget = qt_gl_share_widget(); + if (!shareWidget) + return; + QGLShareContextScope ctx(shareWidget->context()); + glDeleteTextures(1, &m_textureId); } bool QGLPixmapData::isValid() const @@ -166,6 +142,12 @@ void QGLPixmapData::resize(int width, int height) m_width = width; m_height = height; + if (m_textureId) { + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + glDeleteTextures(1, &m_textureId); + m_textureId = 0; + } + m_source = QImage(); m_dirty = isValid(); setSerialNumber(++qt_gl_pixmap_serial); @@ -184,24 +166,30 @@ void QGLPixmapData::ensureCreated() const const GLenum format = qt_gl_preferredTextureFormat(); const GLenum target = qt_gl_preferredTextureTarget(); - if (!m_texture) - glGenTextures(1, &m_texture); - - glBindTexture(target, m_texture); + if (!m_textureId) { + glGenTextures(1, &m_textureId); + glBindTexture(target, m_textureId); + glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, 0); + } - if (m_source.isNull()) { - glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, format, GL_UNSIGNED_BYTE, 0); - } else { + if (!m_source.isNull()) { const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format); - glBindTexture(target, m_texture); - glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, format, - GL_UNSIGNED_BYTE, tx.bits()); + glBindTexture(target, m_textureId); + glTexSubImage2D(target, 0, 0, 0, m_width, m_height, format, + GL_UNSIGNED_BYTE, tx.bits()); - m_source = QImage(); + if (useFramebufferObjects()) + m_source = QImage(); } } +QGLFramebufferObject *QGLPixmapData::fbo() const +{ + return m_renderFbo; +} + void QGLPixmapData::fromImage(const QImage &image, Qt::ImageConversionFlags) { @@ -220,6 +208,17 @@ bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) return false; } +void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect) +{ + if (data->classId() != QPixmapData::OpenGLClass) { + QPixmapData::copy(data, rect); + return; + } + + // can be optimized to do a framebuffer blit or similar ... + QPixmapData::copy(data, rect); +} + void QGLPixmapData::fill(const QColor &color) { if (!isValid()) @@ -246,7 +245,9 @@ QImage QGLPixmapData::toImage() const if (!isValid()) return QImage(); - if (!m_source.isNull()) + if (m_renderFbo) + return m_renderFbo->toImage().copy(0, m_renderFbo->height() - m_height, m_width, m_height); + else if (!m_source.isNull()) return m_source; else if (m_dirty) return QImage(m_width, m_height, QImage::Format_ARGB32_Premultiplied); @@ -254,21 +255,84 @@ QImage QGLPixmapData::toImage() const ensureCreated(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QImage img(m_width, m_height, QImage::Format_ARGB32_Premultiplied); + extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha); + glBindTexture(qt_gl_preferredTextureTarget(), m_textureId); + return qt_gl_read_texture(QSize(m_width, m_height), true, true); +} - GLenum format = qt_gl_preferredTextureFormat(); - GLenum target = qt_gl_preferredTextureTarget(); +struct TextureBuffer +{ + QGLFramebufferObject *fbo; + QGL2PaintEngineEx *engine; +}; - glBindTexture(target, m_texture); -#ifndef QT_OPENGL_ES - glGetTexImage(target, 0, format, GL_UNSIGNED_BYTE, img.bits()); -#else - // XXX - cannot download textures this way on OpenGL/ES. -#endif +static QVector<TextureBuffer> textureBufferStack; +static int currentTextureBuffer = 0; - qt_gl_convertFromGLImage(&img); +void QGLPixmapData::beginPaint() +{ + if (!isValid()) + return; - return img; + m_renderFbo->bind(); +} + +void QGLPixmapData::endPaint() +{ + if (!isValid()) + return; + + const QGLContext *share_ctx = qt_gl_share_widget()->context(); + QGLShareContextScope ctx(share_ctx); + + ensureCreated(); + + if (!ctx->d_ptr->fbo) + glGenFramebuffersEXT(1, &ctx->d_ptr->fbo); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + qt_gl_preferredTextureTarget(), m_textureId, 0); + + const int x0 = 0; + const int x1 = m_width; + const int y0 = 0; + const int y1 = m_height; + + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle()); + + glDisable(GL_SCISSOR_TEST); + + glBlitFramebufferEXT(x0, y0, x1, y1, + x0, y0, x1, y1, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + m_renderFbo->release(); + + --currentTextureBuffer; + + m_renderFbo = 0; + m_engine = 0; +} + +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() + && QGLFramebufferObject::hasOpenGLFramebufferBlit(); } QPaintEngine* QGLPixmapData::paintEngine() const @@ -276,23 +340,59 @@ QPaintEngine* QGLPixmapData::paintEngine() const if (!isValid()) return 0; - m_source = toImage(); - m_dirty = true; + if (m_engine) + return m_engine; + else if (!useFramebufferObjects()) { + m_dirty = true; + + if (m_source.size() != size()) + m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied); + return m_source.paintEngine(); + } - return m_source.paintEngine(); + extern QGLWidget* qt_gl_share_widget(); + + if (!QGLContext::currentContext()) + 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() < m_width || sz.height() < m_height) { + if (sz.width() < m_width) + sz.setWidth(qMax(m_width, qRound(sz.width() * 1.5))); + if (sz.height() < m_height) + sz.setHeight(qMax(m_height, qRound(sz.height() * 1.5))); + delete textureBufferStack.at(currentTextureBuffer).fbo; + textureBufferStack[currentTextureBuffer] = + createTextureBuffer(sz, textureBufferStack.at(currentTextureBuffer).engine); + qDebug() << "Creating new pixmap texture buffer:" << sz; + } + } + + m_renderFbo = textureBufferStack.at(currentTextureBuffer).fbo; + m_engine = textureBufferStack.at(currentTextureBuffer).engine; + + ++currentTextureBuffer; + + return m_engine; } GLuint QGLPixmapData::bind() const { ensureCreated(); - glBindTexture(qt_gl_preferredTextureTarget(), m_texture); - return m_texture; + + GLuint id = m_textureId; + glBindTexture(qt_gl_preferredTextureTarget(), id); + return id; } GLuint QGLPixmapData::textureId() const { ensureCreated(); - return m_texture; + return m_textureId; } extern int qt_defaultDpiX(); diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index 97f4959..b1b31f7 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE class QPaintEngine; +class QGLFramebufferObject; class QGLPixmapData : public QPixmapData { @@ -72,6 +73,7 @@ public: void resize(int width, int height); 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); @@ -87,6 +89,17 @@ public: void ensureCreated() const; + bool isUninitialized() const { return m_dirty && m_source.isNull(); } + + QSize size() const { return QSize(m_width, m_height); } + int width() const { return m_width; } + int height() const { return m_height; } + + QGLFramebufferObject *fbo() const; + + void beginPaint(); + void endPaint(); + protected: int metric(QPaintDevice::PaintDeviceMetric metric) const; @@ -94,11 +107,15 @@ private: QGLPixmapData(const QGLPixmapData &other); QGLPixmapData &operator=(const QGLPixmapData &other); + static bool useFramebufferObjects(); + int m_width; int m_height; + mutable QGLFramebufferObject *m_renderFbo; + mutable uint m_textureId; + mutable QPaintEngine *m_engine; mutable QGLContext *m_ctx; - mutable GLuint m_texture; mutable bool m_dirty; mutable QImage m_source; }; diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index c9d23d1..e0078bb 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -100,8 +100,8 @@ QGLGraphicsSystem::QGLGraphicsSystem() int i = 0; int spec[16]; spec[i++] = GLX_RGBA; -#if 0 spec[i++] = GLX_DOUBLEBUFFER; +#if 0 spec[i++] = GLX_DEPTH_SIZE; spec[i++] = 8; spec[i++] = GLX_STENCIL_SIZE; @@ -433,19 +433,35 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & size = parent->size(); } - ctx->makeCurrent(); -#ifdef Q_WS_MAC - ctx->updatePaintDevice(); -#endif - glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); if (d_ptr->fbo && QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit) { - QGLFramebufferObject::blitFramebuffer(0, rect, d_ptr->fbo, rect); - d_ptr->fbo->bind(); + const int h = d_ptr->fbo->height(); + + const int x0 = rect.left(); + const int x1 = rect.left() + rect.width(); + const int y0 = h - (rect.top() + rect.height()); + const int y1 = h - rect.top(); + + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + + glBlitFramebufferEXT(x0, y0, x1, y1, + x0, y0, x1, y1, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); } else { - if (d_ptr->fbo) + glDisable(GL_DEPTH_TEST); + + if (d_ptr->fbo) { d_ptr->fbo->release(); + } else { + ctx->makeCurrent(); +#ifdef Q_WS_MAC + ctx->updatePaintDevice(); +#endif + } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); |