diff options
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/gl2paintengineex/qglengineshadermanager_p.h | 2 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 10 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtriangulator.cpp | 21 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 8 | ||||
-rw-r--r-- | src/opengl/qgl_egl.cpp | 4 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 6 | ||||
-rw-r--r-- | src/opengl/qglextensions_p.h | 23 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject.cpp | 23 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer.cpp | 4 | ||||
-rw-r--r-- | src/opengl/qglpixmapfilter.cpp | 6 | ||||
-rw-r--r-- | src/opengl/qpaintengine_opengl.cpp | 2 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_gl.cpp | 4 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_gl_p.h | 1 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 140 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl_p.h | 1 |
15 files changed, 142 insertions, 113 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index e5ababf..d24f302 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -455,7 +455,7 @@ public: AttributeOpacity }; - // There are optimisations we can do, depending on the brush transform: + // There are optimizations we can do, depending on the brush transform: // 1) May not have to apply perspective-correction // 2) Can use lower precision for matrix void optimiseForBrushTransform(QTransform::TransformationType transformType); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 025731d..14c26b9 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -102,7 +102,7 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled; extern bool qt_applefontsmoothing_enabled; #endif -extern QImage qt_imageForBrush(int brushStyle, bool invert); +Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); ////////////////////////////////// Private Methods ////////////////////////////////////////// @@ -825,7 +825,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo); - if (glSupportsElementIndexUint) + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint32) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW); else glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint16) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW); @@ -836,7 +836,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW); #else cache->vertices = (float *) qMalloc(sizeof(float) * polys.vertices.size()); - if (glSupportsElementIndexUint) { + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { cache->indices = (quint32 *) qMalloc(sizeof(quint32) * polys.indices.size()); memcpy(cache->indices, polys.indices.data(), sizeof(quint32) * polys.indices.size()); } else { @@ -853,7 +853,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo); setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0); - if (glSupportsElementIndexUint) + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, 0); else glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, 0); @@ -861,7 +861,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glBindBuffer(GL_ARRAY_BUFFER, 0); #else setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, cache->vertices); - if (glSupportsElementIndexUint) + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, (qint32 *)cache->indices); else glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, (qint16 *)cache->indices); diff --git a/src/opengl/gl2paintengineex/qtriangulator.cpp b/src/opengl/gl2paintengineex/qtriangulator.cpp index b839b00..85f604a 100644 --- a/src/opengl/gl2paintengineex/qtriangulator.cpp +++ b/src/opengl/gl2paintengineex/qtriangulator.cpp @@ -58,7 +58,6 @@ #include <math.h> #include <private/qgl_p.h> -#include <private/qglextensions_p.h> QT_BEGIN_NAMESPACE @@ -3014,10 +3013,8 @@ void QTriangulator<T>::MonotoneToTriangles::decompose() QTriangleSet qTriangulate(const qreal *polygon, int count, uint hint, const QTransform &matrix) { - QGLContext *ctx = 0; // Not really used but needs to be introduced for glSupportsElementIndexUint - QTriangleSet triangleSet; - if (glSupportsElementIndexUint) { + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { QTriangulator<quint32> triangulator; triangulator.initialize(polygon, count, hint, matrix); QVertexSet<quint32> vertexSet = triangulator.triangulate(); @@ -3037,10 +3034,8 @@ QTriangleSet qTriangulate(const qreal *polygon, QTriangleSet qTriangulate(const QVectorPath &path, const QTransform &matrix, qreal lod) { - QGLContext *ctx = 0; // Not really used but needs to be introduced for glSupportsElementIndexUint - QTriangleSet triangleSet; - if (glSupportsElementIndexUint) { + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { QTriangulator<quint32> triangulator; triangulator.initialize(path, matrix, lod); QVertexSet<quint32> vertexSet = triangulator.triangulate(); @@ -3059,10 +3054,8 @@ QTriangleSet qTriangulate(const QVectorPath &path, QTriangleSet qTriangulate(const QPainterPath &path, const QTransform &matrix, qreal lod) { - QGLContext *ctx = 0; // Not really used but needs to be introduced for glSupportsElementIndexUint - QTriangleSet triangleSet; - if (glSupportsElementIndexUint) { + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { QTriangulator<quint32> triangulator; triangulator.initialize(path, matrix, lod); QVertexSet<quint32> vertexSet = triangulator.triangulate(); @@ -3081,10 +3074,8 @@ QTriangleSet qTriangulate(const QPainterPath &path, QPolylineSet qPolyline(const QVectorPath &path, const QTransform &matrix, qreal lod) { - QGLContext *ctx = 0; // Not really used but needs to be introduced for glSupportsElementIndexUint - QPolylineSet polyLineSet; - if (glSupportsElementIndexUint) { + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { QTriangulator<quint32> triangulator; triangulator.initialize(path, matrix, lod); QVertexSet<quint32> vertexSet = triangulator.polyline(); @@ -3103,10 +3094,8 @@ QPolylineSet qPolyline(const QVectorPath &path, QPolylineSet qPolyline(const QPainterPath &path, const QTransform &matrix, qreal lod) { - QGLContext *ctx = 0; // Not really used but needs to be introduced for glSupportsElementIndexUint - QPolylineSet polyLineSet; - if (glSupportsElementIndexUint) { + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { QTriangulator<quint32> triangulator; triangulator.initialize(path, matrix, lod); QVertexSet<quint32> vertexSet = triangulator.polyline(); diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 66b146d..f316db6 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2128,7 +2128,7 @@ void QGLContextPrivate::syncGlState() #undef ctx #ifdef QT_NO_EGL -void QGLContextPrivate::swapRegion(const QRegion *) +void QGLContextPrivate::swapRegion(const QRegion &) { Q_Q(QGLContext); q->swapBuffers(); @@ -5363,6 +5363,12 @@ QGLExtensions::Extensions QGLExtensions::currentContextExtensions() #if defined(QT_OPENGL_ES) if (extensions.match("GL_OES_packed_depth_stencil")) glExtensions |= PackedDepthStencil; + if (extensions.match("GL_OES_element_index_uint")) + glExtensions |= ElementIndexUint; + if (extensions.match("GL_OES_depth24")) + glExtensions |= Depth24; +#else + glExtensions |= ElementIndexUint; #endif if (extensions.match("GL_ARB_framebuffer_object")) { // ARB_framebuffer_object also includes EXT_framebuffer_blit. diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index c79c4cd..27f7ad9 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -276,12 +276,12 @@ EGLSurface QGLContextPrivate::eglSurfaceForDevice() const return eglSurface; } -void QGLContextPrivate::swapRegion(const QRegion *region) +void QGLContextPrivate::swapRegion(const QRegion ®ion) { if (!valid || !eglContext) return; - eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), region); + eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), ®ion); } void QGLWidget::setMouseTracking(bool enable) diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 0a5c649..8c7f15c 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -286,7 +286,9 @@ public: DDSTextureCompression = 0x00008000, ETC1TextureCompression = 0x00010000, PVRTCTextureCompression = 0x00020000, - FragmentShader = 0x00040000 + FragmentShader = 0x00040000, + ElementIndexUint = 0x00080000, + Depth24 = 0x00100000 }; Q_DECLARE_FLAGS(Extensions, Extension) @@ -345,7 +347,7 @@ public: void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true); void syncGlState(); // Makes sure the GL context's state is what we think it is - void swapRegion(const QRegion *region); + void swapRegion(const QRegion ®ion); #if defined(Q_WS_WIN) void updateFormatVersion(); diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index bf1dbbc..ffbc472 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -346,17 +346,6 @@ struct QGLExtensionFuncs qt_glEGLImageTargetTexture2DOES = 0; qt_glEGLImageTargetRenderbufferStorageOES = 0; #endif - - // OES_element_index_uint -#if !defined(QT_OPENGL_ES) - qt_glSupportsElementIndexUint = true; -#else - QString extensions = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)); - if (extensions.contains("GL_OES_element_index_uint")) - qt_glSupportsElementIndexUint = true; - else - qt_glSupportsElementIndexUint = false; -#endif } @@ -483,8 +472,6 @@ struct QGLExtensionFuncs _glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES; _glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES; #endif - - bool qt_glSupportsElementIndexUint; }; @@ -576,6 +563,14 @@ struct QGLExtensionFuncs #define GL_TEXTURE1 0x84C1 #endif +#ifndef GL_DEPTH_COMPONENT16 +#define GL_DEPTH_COMPONENT16 0x81A5 +#endif + +#ifndef GL_DEPTH_COMPONENT24_OES +#define GL_DEPTH_COMPONENT24_OES 0x81A6 +#endif + #ifndef GL_EXT_framebuffer_object #define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 #define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 @@ -883,8 +878,6 @@ struct QGLExtensionFuncs #define glEGLImageTargetRenderbufferStorageOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetRenderbufferStorageOES #endif -#define glSupportsElementIndexUint QGLContextPrivate::extensionFuncs(ctx).qt_glSupportsElementIndexUint - extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx); bool Q_OPENGL_EXPORT qt_resolve_buffer_extensions(QGLContext *ctx); diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 5d78ac0..6881678 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -508,17 +508,26 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, Q_ASSERT(glIsRenderbuffer(depth_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES -#define GL_DEPTH_COMPONENT16 0x81A5 - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, - GL_DEPTH_COMPONENT16, size.width(), size.height()); + if (QGLExtensions::glExtensions() & QGLExtensions::Depth24) { + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, + GL_DEPTH_COMPONENT24_OES, size.width(), size.height()); + } else { + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, + GL_DEPTH_COMPONENT16, size.width(), size.height()); + } #else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } else { #ifdef QT_OPENGL_ES -#define GL_DEPTH_COMPONENT16 0x81A5 - glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height()); + if (QGLExtensions::glExtensions() & QGLExtensions::Depth24) { + glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_OES, + size.width(), size.height()); + } else { + glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, + size.width(), size.height()); + } #else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif @@ -1169,8 +1178,8 @@ void QGLFramebufferObject::drawTexture(const QPointF &point, QMacCompatGLuint te } #endif -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_DECL_IMPORT extern int qt_defaultDpiX(); +Q_DECL_IMPORT extern int qt_defaultDpiY(); /*! \reimp */ int QGLFramebufferObject::metric(PaintDeviceMetric metric) const diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 2ec345d..261d567 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -424,8 +424,8 @@ QPaintEngine *QGLPixelBuffer::paintEngine() const #endif } -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_DECL_IMPORT extern int qt_defaultDpiX(); +Q_DECL_IMPORT extern int qt_defaultDpiY(); /*! \reimp */ int QGLPixelBuffer::metric(PaintDeviceMetric metric) const diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 68586c1..73d698c 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -63,8 +63,8 @@ QT_BEGIN_NAMESPACE // qpixmapfilter.cpp -void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); -QImage qt_halfScaled(const QImage &source); +Q_DECL_IMPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); +Q_DECL_IMPORT QImage qt_halfScaled(const QImage &source); void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const { @@ -425,7 +425,7 @@ static inline uint nextMultiple(uint x, uint multiplier) return x + multiplier - mod; } -void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride, +Q_DECL_IMPORT void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride, quint32 *dest, int dstStride); bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 2f17aa6..74b6b9a 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -79,7 +79,7 @@ QT_BEGIN_NAMESPACE -extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp +Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp #ifdef QT_MAC_USE_COCOA extern void *qt_current_nsopengl_context(); // qgl_mac.mm #endif diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 89000bb..cd7f0c2 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -739,8 +739,8 @@ QGLTexture* QGLPixmapData::texture() const return &m_texture; } -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_DECL_IMPORT extern int qt_defaultDpiX(); +Q_DECL_IMPORT extern int qt_defaultDpiY(); int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const { diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index f000993..c0b223f 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -169,6 +169,7 @@ private: friend class QGLPixmapGLPaintDevice; friend class QMeeGoPixmapData; + friend class QMeeGoLivePixmapData; }; QT_END_NAMESPACE diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 29c4477..47f36dd 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -194,7 +194,7 @@ public: widget = new QGLWidget(QGLFormat(QGL::SingleBuffer | QGL::NoDepthBuffer | QGL::NoStencilBuffer)); widget->resize(1, 1); - // We dont need this internal widget to appear in QApplication::topLevelWidgets() + // We don't need this internal widget to appear in QApplication::topLevelWidgets() if (QWidgetPrivate::allWidgets) QWidgetPrivate::allWidgets->remove(widget); initializing = false; @@ -275,6 +275,8 @@ struct QGLWindowSurfacePrivate QRegion paintedRegion; QSize size; + QSize textureSize; + QList<QImage> buffers; QGLWindowSurfaceGLPaintDevice glDevice; QGLWindowSurface* q_ptr; @@ -316,6 +318,7 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window) d_ptr->pb = 0; d_ptr->fbo = 0; d_ptr->ctx = 0; + d_ptr->tex_id = 0; #if defined (QT_OPENGL_ES_2) d_ptr->tried_fbo = true; d_ptr->tried_pb = true; @@ -435,7 +438,7 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, void QGLWindowSurface::beginPaint(const QRegion &) { - if (! context()) + if (!context()) return; int clearFlags = 0; @@ -459,13 +462,42 @@ void QGLWindowSurface::endPaint(const QRegion &rgn) d_ptr->buffers.clear(); } -void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) +static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport, const QSize &texSize, const QRect &targetRect, const QRect &sourceRect) { - if (context() && widget != window()) { - qWarning("No native child widget support in GL window surface without FBOs or pixel buffers"); - return; - } + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + + glViewport(0, 0, viewport.width(), viewport.height()); + + QGLShaderProgram *blitProgram = + QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram(); + blitProgram->bind(); + blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); + + // The shader manager's blit program does not multiply the + // vertices by the pmv matrix, so we need to do the effect + // of the orthographic projection here ourselves. + QRectF r; + qreal w = viewport.width(); + qreal h = viewport.height(); + r.setLeft((targetRect.left() / w) * 2.0f - 1.0f); + if (targetRect.right() == (viewport.width() - 1)) + r.setRight(1.0f); + else + r.setRight((targetRect.right() / w) * 2.0f - 1.0f); + r.setBottom((targetRect.top() / h) * 2.0f - 1.0f); + if (targetRect.bottom() == (viewport.height() - 1)) + r.setTop(1.0f); + else + r.setTop((targetRect.bottom() / w) * 2.0f - 1.0f); + + drawTexture(r, texture, texSize, sourceRect); +} + +void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) +{ //### Find out why d_ptr->geometry_updated isn't always false. // flush() should not be called when d_ptr->geometry_updated is true. It assumes that either // d_ptr->fbo or d_ptr->pb is allocated and has the correct size. @@ -541,12 +573,29 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & } } #endif - if (hasPartialUpdateSupport() && - d_ptr->paintedRegion.boundingRect().width() * d_ptr->paintedRegion.boundingRect().height() < - geometry().width() * geometry().height() * 0.2) { - context()->d_func()->swapRegion(&d_ptr->paintedRegion); - } else - context()->swapBuffers(); + bool doingPartialUpdate = hasPartialUpdateSupport() && br.width() * br.height() < parent->geometry().width() * parent->geometry().height() * 0.2; + QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext); + if (widget != window()) { + if (initializeOffscreenTexture(window()->size())) + qWarning() << "QGLWindowSurface: Flushing to native child widget, may lead to significant performance loss"; + glBindTexture(target, d_ptr->tex_id); + + const uint bottom = window()->height() - (br.y() + br.height()); + glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height()); + + glBindTexture(target, 0); + + ctx->makeCurrent(); + if (doingPartialUpdate) + blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), rect, br); + else + blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), parent->rect(), parent->rect().translated(offset + wOffset)); + } + + if (doingPartialUpdate) + ctx->d_func()->swapRegion(br); + else + ctx->swapBuffers(); d_ptr->paintedRegion = QRegion(); } else { @@ -672,38 +721,10 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & else if (d_ptr->fbo) { Q_UNUSED(target); - GLuint texture = d_ptr->fbo->texture(); - - glDisable(GL_DEPTH_TEST); - if (d_ptr->fbo->isBound()) d_ptr->fbo->release(); - glViewport(0, 0, size.width(), size.height()); - - QGLShaderProgram *blitProgram = - QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram(); - blitProgram->bind(); - blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); - - // The shader manager's blit program does not multiply the - // vertices by the pmv matrix, so we need to do the effect - // of the orthographic projection here ourselves. - QRectF r; - qreal w = size.width() ? size.width() : 1.0f; - qreal h = size.height() ? size.height() : 1.0f; - r.setLeft((rect.left() / w) * 2.0f - 1.0f); - if (rect.right() == (size.width() - 1)) - r.setRight(1.0f); - else - r.setRight((rect.right() / w) * 2.0f - 1.0f); - r.setBottom((rect.top() / h) * 2.0f - 1.0f); - if (rect.bottom() == (size.height() - 1)) - r.setTop(1.0f); - else - r.setTop((rect.bottom() / w) * 2.0f - 1.0f); - - drawTexture(r, texture, window()->size(), br); + blitTexture(ctx, d_ptr->fbo->texture(), size, window()->size(), rect, br); } #endif @@ -758,11 +779,8 @@ void QGLWindowSurface::updateGeometry() { if (d_ptr->ctx) { #ifndef QT_OPENGL_ES_2 - if (d_ptr->destructive_swap_buffers) { - glBindTexture(target, d_ptr->tex_id); - glTexImage2D(target, 0, GL_RGBA, surfSize.width(), surfSize.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - glBindTexture(target, 0); - } + if (d_ptr->destructive_swap_buffers) + initializeOffscreenTexture(surfSize); #endif return; } @@ -842,15 +860,8 @@ void QGLWindowSurface::updateGeometry() { ctx->makeCurrent(); #ifndef QT_OPENGL_ES_2 - if (d_ptr->destructive_swap_buffers) { - glGenTextures(1, &d_ptr->tex_id); - glBindTexture(target, d_ptr->tex_id); - glTexImage2D(target, 0, GL_RGBA, surfSize.width(), surfSize.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - - glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glBindTexture(target, 0); - } + if (d_ptr->destructive_swap_buffers) + initializeOffscreenTexture(surfSize); #endif qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;; @@ -858,6 +869,23 @@ void QGLWindowSurface::updateGeometry() { d_ptr->ctx->d_ptr->internal_context = true; } +bool QGLWindowSurface::initializeOffscreenTexture(const QSize &size) +{ + if (size == d_ptr->textureSize) + return false; + + glGenTextures(1, &d_ptr->tex_id); + glBindTexture(GL_TEXTURE_2D, d_ptr->tex_id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, 0); + + d_ptr->textureSize = size; + return true; +} + bool QGLWindowSurface::scroll(const QRegion &area, int dx, int dy) { // this code randomly fails currently for unknown reasons diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h index ca73bad..4f4ec92 100644 --- a/src/opengl/qwindowsurface_gl_p.h +++ b/src/opengl/qwindowsurface_gl_p.h @@ -113,6 +113,7 @@ private slots: private: void hijackWindow(QWidget *widget); + bool initializeOffscreenTexture(const QSize &size); QGLWindowSurfacePrivate *d_ptr; }; |