diff options
author | Tom Cooksey <thomas.cooksey@nokia.com> | 2009-08-27 14:08:20 (GMT) |
---|---|---|
committer | Tom Cooksey <thomas.cooksey@nokia.com> | 2009-09-08 16:36:13 (GMT) |
commit | 7c59abc1883a24e54ac3bb2193acc2cac5ad416a (patch) | |
tree | 589ab0cedd22197bace46f8b616998de5127b40c | |
parent | 5a3d0e73121e191fe2f1337ac8f6761c35868b66 (diff) | |
download | Qt-7c59abc1883a24e54ac3bb2193acc2cac5ad416a.zip Qt-7c59abc1883a24e54ac3bb2193acc2cac5ad416a.tar.gz Qt-7c59abc1883a24e54ac3bb2193acc2cac5ad416a.tar.bz2 |
Replace QGLDrawable with a new QGLPaintDevice
This patch adds a new abstract base class which inherits from
QPaintDevice called QGLPaintDevice. This base class will contain
everything the GL paint engines need to know about the surface they are
drawing onto. As such, new surfaces can be targeted by the GL paint
engines without having to modify QtOpenGL. This is very useful for
plugins, specifically QGraphicsSystem plugins.
To unify things a little, the GL paint engines will use the same
QGLPaintDevice API to render into existing target surfaces (QGLWidget,
QGLPixelBuffer & QGLFrameBufferObject). Ideally we'd make QGLPaintDevice
a common ancestor for these surfaces, but obviously that wil break B/C.
This patch only implements QGLWidget using the new interface. Rendering
to other surfaces will be fixed in following patches.
-rw-r--r-- | src/corelib/global/qnamespace.h | 3 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 65 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 3 | ||||
-rw-r--r-- | src/opengl/opengl.pro | 6 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 5 | ||||
-rw-r--r-- | src/opengl/qgl.h | 2 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 7 | ||||
-rw-r--r-- | src/opengl/qgl_x11.cpp | 3 | ||||
-rw-r--r-- | src/opengl/qglpaintdevice.cpp | 192 | ||||
-rw-r--r-- | src/opengl/qglpaintdevice_p.h | 168 | ||||
-rw-r--r-- | src/opengl/qpaintengine_opengl.cpp | 113 |
11 files changed, 483 insertions, 84 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 8f34e30..93de911 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1655,7 +1655,8 @@ public: FramebufferObject = 0x07, // GL framebuffer object CustomRaster = 0x08, MacQuartz = 0x09, - PaintBuffer = 0x0a + PaintBuffer = 0x0a, + OpenGL = 0x0b }; enum RelayoutType { RelayoutNormal, diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index e24539b..8fee83d 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -710,7 +710,7 @@ void QGL2PaintEngineEx::beginNativePainting() { mtx.dx(), mtx.dy(), 0, mtx.m33() } }; - const QSize sz = d->drawable.size(); + const QSize sz = d->device->size(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -1308,21 +1308,28 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) Q_D(QGL2PaintEngineEx); // qDebug("QGL2PaintEngineEx::begin()"); - d->drawable.setDevice(pdev); - d->ctx = d->drawable.context(); + if (pdev->devType() == QInternal::OpenGL) + d->device = static_cast<QGLPaintDevice*>(pdev); + else + d->device = QGLPaintDevice::getDevice(pdev); + + if (!d->device) + return false; + + d->ctx = d->device->context(); if (d->ctx->d_ptr->active_engine) { QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(d->ctx->d_ptr->active_engine); QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr.data()); p->transferMode(BrushDrawingMode); - p->drawable.doneCurrent(); + p->device->context()->doneCurrent(); } d->ctx->d_ptr->active_engine = this; d->last_created_state = 0; - d->drawable.makeCurrent(); - QSize sz = d->drawable.size(); + d->device->beginPaint(); + QSize sz = d->device->size(); d->width = sz.width(); d->height = sz.height(); d->mode = BrushDrawingMode; @@ -1358,28 +1365,29 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) glDisable(GL_MULTISAMPLE); #endif - QGLPixmapData *source = d->drawable.copyOnBegin(); - if (d->drawable.context()->d_func()->clear_on_painter_begin && d->drawable.autoFillBackground()) { - if (d->drawable.hasTransparentBackground()) +// QGLPixmapData *source = d->drawable.copyOnBegin(); + if (d->ctx->d_func()->clear_on_painter_begin && d->device->autoFillBackground()) { + if (d->device->hasTransparentBackground()) glClearColor(0.0, 0.0, 0.0, 0.0); else { - const QColor &c = d->drawable.backgroundColor(); + const QColor &c = d->device->backgroundColor(); float alpha = c.alphaF(); glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha); } glClear(GL_COLOR_BUFFER_BIT); - } else 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); } +// else 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; @@ -1394,14 +1402,15 @@ bool QGL2PaintEngineEx::end() if (engine && engine->isActive()) { QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr.data()); p->transferMode(BrushDrawingMode); - p->drawable.doneCurrent(); + p->device->context()->doneCurrent(); } - d->drawable.makeCurrent(); + d->device->context()->makeCurrent(); } glUseProgram(0); d->transferMode(BrushDrawingMode); - d->drawable.swapBuffers(); + d->device->endPaint(); + #if defined(Q_WS_X11) // On some (probably all) drivers, deleting an X pixmap which has been bound to a texture // before calling glFinish/swapBuffers renders garbage. Presumably this is because X deletes @@ -1410,7 +1419,6 @@ bool QGL2PaintEngineEx::end() // them here, after swapBuffers, where they can be safely deleted. ctx->d_func()->boundPixmaps.clear(); #endif - d->drawable.doneCurrent(); d->ctx->d_ptr->active_engine = 0; d->resetGLState(); @@ -1431,15 +1439,14 @@ void QGL2PaintEngineEx::ensureActive() if (engine && engine->isActive()) { QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr.data()); p->transferMode(BrushDrawingMode); - p->drawable.doneCurrent(); + p->device->context()->doneCurrent(); } - d->drawable.context()->makeCurrent(); - d->drawable.makeCurrent(); + d->device->context()->makeCurrent(); ctx->d_ptr->active_engine = this; d->needsSync = true; } else { - d->drawable.context()->makeCurrent(); + d->device->context()->makeCurrent(); } if (d->needsSync) { diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index cb23b11..2fbee1b 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -58,6 +58,7 @@ #include <private/qpaintengineex_p.h> #include <private/qglengineshadermanager_p.h> #include <private/qgl2pexvertexarray_p.h> +#include <private/qglpaintdevice_p.h> enum EngineMode { ImageDrawingMode, @@ -199,7 +200,7 @@ public: static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; } QGL2PaintEngineEx* q; - QGLDrawable drawable; + QGLPaintDevice* device; int width, height; QGLContext *ctx; EngineMode mode; diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 560d31f..2aefe41 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -22,13 +22,17 @@ HEADERS += qgl.h \ qglpixelbuffer.h \ qglpixelbuffer_p.h \ qglframebufferobject.h \ - qglextensions_p.h + qglextensions_p.h \ + qglpaintdevice_p.h \ + SOURCES += qgl.cpp \ qglcolormap.cpp \ qglpixelbuffer.cpp \ qglframebufferobject.cpp \ qglextensions.cpp \ + qglpaintdevice.cpp \ + !contains(QT_CONFIG, opengles2) { HEADERS += qpaintengine_opengl_p.h diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 02bb8f9..ad54298 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4815,6 +4815,8 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi { Q_Q(QGLWidget); + glDevice.setWidget(q); + QGLExtensions::init(); glcx = 0; autoSwap = true; @@ -4850,6 +4852,7 @@ Q_OPENGL_EXPORT const QString qt_gl_library_name() } #endif +#if 0 void QGLDrawable::setDevice(QPaintDevice *pdev) { wasBound = false; @@ -5084,7 +5087,7 @@ bool QGLDrawable::autoFillBackground() const else return false; } - +#endif bool QGLShareRegister::checkSharing(const QGLContext *context1, const QGLContext *context2) { bool sharing = (context1 && context2 && context1->d_ptr->group == context2->d_ptr->group); diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index b110665..46efe23 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -542,6 +542,8 @@ private: friend class QGLContext; friend class QGLOverlayWidget; friend class QOpenGLPaintEngine; + friend class QGLPaintDevice; + friend class QGLWidgetGLPaintDevice; }; diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index f8158a0..03532c8 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -62,6 +62,7 @@ #include "QtCore/qatomic.h" #include "private/qwidget_p.h" #include "qcache.h" +#include "qglpaintdevice_p.h" #ifndef QT_OPENGL_ES_1_CL #define q_vertexType float @@ -189,7 +190,8 @@ public: bool renderCxPm(QPixmap *pixmap); void cleanupColormaps(); - QGLContext *glcx; + QGLContext *glcx; // ### Keep for compatability with QGLDrawable (if that gets left in) + QGLWidgetGLPaintDevice glDevice; bool autoSwap; QGLColormap cmap; @@ -337,6 +339,7 @@ Q_SIGNALS: void aboutToDestroyContext(const QGLContext *context); }; +#if 0 class QGLPixelBuffer; class QGLFramebufferObject; class QWSGLWindowSurface; @@ -388,6 +391,8 @@ private: int previous_fbo; }; +#endif + // GL extension definitions class QGLExtensions { public: diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index 81985cd..5da128d 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -41,6 +41,7 @@ #include "qgl.h" #include "qgl_p.h" +#include "qglpaintdevice_p.h" #include "qmap.h" #include "qapplication.h" @@ -1307,7 +1308,7 @@ void QGLWidget::setContext(QGLContext *context, d->glcx->doneCurrent(); QGLContext* oldcx = d->glcx; d->glcx = context; - + d->glDevice.setContext(context); // ### Do this for all platforms if (parentWidget()) { // force creation of delay-created widgets diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp new file mode 100644 index 0000000..f7bd2a3 --- /dev/null +++ b/src/opengl/qglpaintdevice.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qglpaintdevice_p.h> +#include <private/qgl_p.h> + +QGLPaintDevice::QGLPaintDevice() + : m_context(0) +{ +} + +QGLPaintDevice::~QGLPaintDevice() +{ +} + +//extern QPaintEngine* qt_gl_engine(); // in qgl.cpp +//extern QPaintEngine* qt_gl_2_engine(); // in qgl.cpp + +//inline bool qt_gl_preferGL2Engine() +//{ +//#if defined(QT_OPENGL_ES_2) +// return true; +//#else +// return (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) +// && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty(); +//#endif +//} + +//QPaintEngine* QGLPaintDevice::paintEngine() const +//{ +//#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL) +// return qt_gl_engine(); +//#elif defined(QT_OPENGL_ES_2) +// return qt_gl_2_engine(); +//#else +// if (!qt_gl_preferGL2Engine()) +// return qt_gl_engine(); +// else +// return qt_gl_2_engine(); +//#endif +//} + +void QGLPaintDevice::beginPaint() +{ + m_context->makeCurrent(); +} + +void QGLPaintDevice::endPaint() +{ +} + +QColor QGLPaintDevice::backgroundColor() const +{ + return QColor(); +} + +bool QGLPaintDevice::autoFillBackground() const +{ + return false; +} + +bool QGLPaintDevice::hasTransparentBackground() const +{ + return false; +} + +QGLContext* QGLPaintDevice::context() const +{ + return m_context; +} + +QGLFormat QGLPaintDevice::format() const +{ + return m_context->format(); +} + +QSize QGLPaintDevice::size() const +{ + return QSize(); +} + +void QGLPaintDevice::setContext(QGLContext* c) +{ + m_context = c; +} + + + +QGLWidgetGLPaintDevice::QGLWidgetGLPaintDevice() +{ +} + +QPaintEngine* QGLWidgetGLPaintDevice::paintEngine() const +{ + return glWidget->paintEngine(); +} + +QColor QGLWidgetGLPaintDevice::backgroundColor() const +{ + return glWidget->palette().brush(glWidget->backgroundRole()).color(); +} + +bool QGLWidgetGLPaintDevice::autoFillBackground() const +{ + return glWidget->autoFillBackground(); +} + +bool QGLWidgetGLPaintDevice::hasTransparentBackground() const +{ + return glWidget->testAttribute(Qt::WA_TranslucentBackground); +} + +void QGLWidgetGLPaintDevice::setWidget(QGLWidget* w) +{ + glWidget = w; +} + +//void QGLWidgetGLPaintDevice::beginPaint() +//{ +// glWidget->makeCurrent(); +//} + +void QGLWidgetGLPaintDevice::endPaint() +{ + if (glWidget->autoBufferSwap()) + glWidget->swapBuffers(); +} + + +QSize QGLWidgetGLPaintDevice::size() const +{ + return glWidget->size(); +} + +// returns the QGLPaintDevice for the given QPaintDevice +QGLPaintDevice* QGLPaintDevice::getDevice(QPaintDevice* pd) +{ + QGLPaintDevice* glpd = 0; + + switch(pd->devType()) { + case QInternal::Widget: + // Should not be called on a non-gl widget: + Q_ASSERT(qobject_cast<QGLWidget*>(static_cast<QWidget*>(pd))); + glpd = &(static_cast<QGLWidget*>(pd)->d_func()->glDevice); + break; + default: + qWarning("QGLPaintDevice::getDevice() - Unknown device type %d", pd->devType()); + break; + } + + return glpd; +} + + diff --git a/src/opengl/qglpaintdevice_p.h b/src/opengl/qglpaintdevice_p.h new file mode 100644 index 0000000..ad680a9 --- /dev/null +++ b/src/opengl/qglpaintdevice_p.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLPAINTDEVICE_P_H +#define QGLPAINTDEVICE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QtOpenGL module. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <qpaintdevice.h> +#include <qgl.h> + +class QGLPaintDevice : public QPaintDevice +{ +public: + QGLPaintDevice(); + virtual ~QGLPaintDevice(); + + virtual void beginPaint(); + virtual void endPaint(); + + virtual QColor backgroundColor() const; + virtual bool autoFillBackground() const; + virtual bool hasTransparentBackground() const; + + // inline these? + QGLContext* context() const; + QGLFormat format() const; + virtual QSize size() const; + + // returns the QGLPaintDevice for the given QPaintDevice + static QGLPaintDevice* getDevice(QPaintDevice*); + +protected: + // Inline? + void setContext(QGLContext* c); + +private: + QGLContext* m_context; +}; + + +// Wraps a QGLWidget +class QGLWidget; +class QGLWidgetGLPaintDevice : public QGLPaintDevice +{ +public: + QGLWidgetGLPaintDevice(); + + virtual QPaintEngine* paintEngine() const; + + virtual QColor backgroundColor() const; + virtual bool autoFillBackground() const; + virtual bool hasTransparentBackground() const; + + // QGLWidgets need to do swapBufers in endPaint: + virtual void endPaint(); + virtual QSize size() const; + + void setWidget(QGLWidget*); + +private: + friend class QGLWidget; + QGLWidget *glWidget; +}; + + + +/* +Replaces: + +class QGLPixelBuffer; +class QGLFramebufferObject; +class QWSGLWindowSurface; +class QGLWindowSurface; +class QGLPixmapData; +class QGLDrawable { +public: + QGLDrawable() : widget(0), buffer(0), fbo(0) +#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)) + , wsurf(0) +#endif +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) + , pixmapData(0) +#endif + {} + void setDevice(QPaintDevice *pdev); + void swapBuffers(); + void makeCurrent(); + void doneCurrent(); + QSize size() const; + QGLFormat format() const; + GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA); + GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA); + QColor backgroundColor() const; + QGLContext *context() const; + bool autoFillBackground() const; + bool hasTransparentBackground() const; + +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) + QGLPixmapData *copyOnBegin() const; +#endif + +private: + bool wasBound; + QGLWidget *widget; + QGLPixelBuffer *buffer; + QGLFramebufferObject *fbo; +#ifdef Q_WS_QWS + QWSGLWindowSurface *wsurf; +#elif !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) + QGLWindowSurface *wsurf; +#endif + +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) + QGLPixmapData *pixmapData; +#endif + int previous_fbo; +}; +*/ + +#endif // QGLPAINTDEVICE_P_H diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index bf4d4b9..634067d 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -49,6 +49,7 @@ #include "qbrush.h" #include "qgl.h" #include <private/qgl_p.h> +#include <private/qglpaintdevice_p.h> #include <private/qpainter_p.h> #include "qmap.h" #include <private/qpaintengine_opengl_p.h> @@ -75,7 +76,7 @@ #include "qgl_cl_p.h" #endif -#define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(drawable.context()); +#define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(device->context()); #include <stdlib.h> #include "qpaintengine_opengl_p.h" @@ -286,7 +287,8 @@ public Q_SLOTS: } private: - QGLDrawable drawable; +// QGLDrawable drawable; + QGLPaintDevice* device; QGLFramebufferObject *offscreen; QGLContext *ctx; @@ -305,7 +307,13 @@ private: inline void QGLOffscreen::setDevice(QPaintDevice *pdev) { - drawable.setDevice(pdev); + if (pdev->devType() == QInternal::OpenGL) + device = static_cast<QGLPaintDevice*>(pdev); + else + device = QGLPaintDevice::getDevice(pdev); + + if (!device) + return; drawable_fbo = (pdev->devType() == QInternal::FramebufferObject); } @@ -329,12 +337,12 @@ void QGLOffscreen::initialize() activated = true; initialized = true; - int dim = qMax(2048, static_cast<int>(qt_next_power_of_two(qMax(drawable.size().width(), drawable.size().height())))); + int dim = qMax(2048, static_cast<int>(qt_next_power_of_two(qMax(device->size().width(), device->size().height())))); - bool shared_context = qgl_share_reg()->checkSharing(drawable.context(), ctx); + bool shared_context = qgl_share_reg()->checkSharing(device->context(), ctx); bool would_fail = last_failed_size.isValid() && - (drawable.size().width() >= last_failed_size.width() || - drawable.size().height() >= last_failed_size.height()); + (device->size().width() >= last_failed_size.width() || + device->size().height() >= last_failed_size.height()); bool needs_refresh = dim > mask_dim || !shared_context; if (needs_refresh && !would_fail) { @@ -348,13 +356,13 @@ void QGLOffscreen::initialize() delete offscreen; offscreen = 0; mask_dim = 0; - last_failed_size = drawable.size(); + last_failed_size = device->size(); } } qt_mask_texture_cache()->setOffscreenSize(offscreenSize()); - qt_mask_texture_cache()->setDrawableSize(drawable.size()); - ctx = drawable.context(); + qt_mask_texture_cache()->setDrawableSize(device->size()); + ctx = device->context(); #endif } @@ -428,11 +436,11 @@ inline void QGLOffscreen::release() DEBUG_ONCE_STR("QGLOffscreen: releasing offscreen"); if (drawable_fbo) - drawable.makeCurrent(); + device->context()->makeCurrent(); //### else offscreen->release(); - QSize sz(drawable.size()); + QSize sz(device->size()); glViewport(0, 0, sz.width(), sz.height()); glMatrixMode(GL_PROJECTION); @@ -455,7 +463,7 @@ inline bool QGLOffscreen::isBound() const inline QSize QGLOffscreen::drawableSize() const { - return drawable.size(); + return device->size(); } inline QSize QGLOffscreen::offscreenSize() const @@ -757,7 +765,8 @@ public: GLubyte pen_color[4]; GLubyte brush_color[4]; QTransform::TransformationType txop; - QGLDrawable drawable; +// QGLDrawable drawable; + QGLPaintDevice* device; QGLOffscreen offscreen; qreal inverseScale; @@ -1167,7 +1176,7 @@ void QOpenGLPaintEnginePrivate::createGradientPaletteTexture(const QGradient& g) #ifdef QT_OPENGL_ES //### Q_UNUSED(g); #else - GLuint texId = qt_opengl_gradient_cache()->getBuffer(g, opacity, drawable.context()); + GLuint texId = qt_opengl_gradient_cache()->getBuffer(g, opacity, device->context()); glBindTexture(GL_TEXTURE_1D, texId); grad_palette = texId; if (g.spread() == QGradient::RepeatSpread || g.type() == QGradient::ConicalGradient) @@ -1236,12 +1245,19 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) { Q_D(QOpenGLPaintEngine); - d->drawable.setDevice(pdev); + if (pdev->devType() == QInternal::OpenGL) + d->device = static_cast<QGLPaintDevice*>(pdev); + else + d->device = QGLPaintDevice::getDevice(pdev); + + if (!d->device) + return false; + d->offscreen.setDevice(pdev); d->has_fast_pen = false; d->inverseScale = 1; d->opacity = 1; - d->drawable.makeCurrent(); + d->device->beginPaint(); d->matrix = QTransform(); d->has_antialiasing = false; d->high_quality_antialiasing = false; @@ -1256,7 +1272,7 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) bool has_frag_program = (QGLExtensions::glExtensions & QGLExtensions::FragmentProgram) && (pdev->devType() != QInternal::Pixmap); - QGLContext *ctx = const_cast<QGLContext *>(d->drawable.context()); + QGLContext *ctx = const_cast<QGLContext *>(d->device->context()); if (!ctx) { qWarning() << "QOpenGLPaintEngine: paint device doesn't have a valid GL context."; return false; @@ -1265,9 +1281,9 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) if (has_frag_program) has_frag_program = qt_resolve_frag_program_extensions(ctx) && qt_resolve_version_1_3_functions(ctx); - d->use_stencil_method = d->drawable.format().stencil() + d->use_stencil_method = d->device->format().stencil() && (QGLExtensions::glExtensions & QGLExtensions::StencilWrap); - if (d->drawable.format().directRendering() + if (d->device->format().directRendering() && (d->use_stencil_method && QGLExtensions::glExtensions & QGLExtensions::StencilTwoSide)) d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx); @@ -1333,12 +1349,12 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) d->offscreen.begin(); - if (d->drawable.context()->d_func()->clear_on_painter_begin && d->drawable.autoFillBackground()) { + if (d->device->context()->d_func()->clear_on_painter_begin && d->device->autoFillBackground()) { - if (d->drawable.hasTransparentBackground()) + if (d->device->hasTransparentBackground()) glClearColor(0.0, 0.0, 0.0, 0.0); else { - const QColor &c = d->drawable.backgroundColor(); + const QColor &c = d->device->backgroundColor(); glClearColor(c.redF(), c.greenF(), c.blueF(), 1.0); } @@ -1349,7 +1365,7 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) glClear(clearBits); } - QSize sz(d->drawable.size()); + QSize sz(d->device->size()); glViewport(0, 0, sz.width(), sz.height()); // XXX (Embedded): We need a solution for GLWidgets that draw in a part or a bigger surface... glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -1366,7 +1382,7 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) #ifdef QT_OPENGL_ES d->max_texture_size = ctx->d_func()->maxTextureSize(); #else - bool shared_ctx = qgl_share_reg()->checkSharing(d->drawable.context(), d->shader_ctx); + bool shared_ctx = qgl_share_reg()->checkSharing(d->device->context(), d->shader_ctx); if (shared_ctx) { d->max_texture_size = d->shader_ctx->d_func()->maxTextureSize(); @@ -1382,7 +1398,7 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) glDeleteTextures(1, &d->drawable_texture); ctx->makeCurrent(); } - d->shader_ctx = d->drawable.context(); + d->shader_ctx = d->device->context(); glGenTextures(1, &d->grad_palette); qt_mask_texture_cache()->clearCache(); @@ -1417,7 +1433,7 @@ bool QOpenGLPaintEngine::end() Q_D(QOpenGLPaintEngine); d->flushDrawQueue(); d->offscreen.end(); - QGLContext *ctx = const_cast<QGLContext *>(d->drawable.context()); + QGLContext *ctx = const_cast<QGLContext *>(d->device->context()); if (!ctx->d_ptr->internal_context) { glMatrixMode(GL_TEXTURE); glPopMatrix(); @@ -1434,8 +1450,7 @@ bool QOpenGLPaintEngine::end() glPopClientAttrib(); } #endif - d->drawable.swapBuffers(); - d->drawable.doneCurrent(); + d->device->endPaint(); qt_mask_texture_cache()->maintainCache(); return true; @@ -1961,7 +1976,7 @@ void QOpenGLPaintEnginePrivate::fillVertexArray(Qt::FillRule fillRule) const int left = rect.left(); const int width = rect.width(); - const int bottom = drawable.size().height() - (rect.bottom() + 1); + const int bottom = device->size().height() - (rect.bottom() + 1); const int height = rect.height(); glScissor(left, bottom, width, height); @@ -2242,7 +2257,7 @@ void QOpenGLPaintEnginePrivate::updateDepthClip() const int left = fastClip.left(); const int width = fastClip.width(); - const int bottom = drawable.size().height() - (fastClip.bottom() + 1); + const int bottom = device->size().height() - (fastClip.bottom() + 1); const int height = fastClip.height(); glScissor(left, bottom, width, height); @@ -2325,7 +2340,7 @@ void QOpenGLPaintEngine::updateClipRegion(const QRegion &clipRegion, Qt::ClipOpe // clipping is only supported when a stencil or depth buffer is // available - if (!d->drawable.format().depth()) + if (!d->device->format().depth()) return; d->use_system_clip = false; @@ -2362,7 +2377,7 @@ void QOpenGLPaintEngine::updateClipRegion(const QRegion &clipRegion, Qt::ClipOpe path.addRect(untransformedRects[0]); path = d->matrix.map(path); - if (path.contains(QRectF(QPointF(), d->drawable.size()))) + if (path.contains(QRectF(QPointF(), d->device->size()))) isScreenClip = true; } } @@ -3369,7 +3384,7 @@ void QOpenGLPaintEnginePrivate::drawOffscreenPath(const QPainterPath &path) disableClipping(); - GLuint program = qt_gl_program_cache()->getProgram(drawable.context(), + GLuint program = qt_gl_program_cache()->getProgram(device->context(), FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, 0, true); QGLPathMaskGenerator maskGenerator(path, matrix, offscreen, program); addItem(qt_mask_texture_cache()->getMask(maskGenerator, this)); @@ -3506,7 +3521,7 @@ void QOpenGLPaintEngine::drawRects(const QRectF *rects, int rectCount) if (d->has_brush) { d->disableClipping(); - GLuint program = qt_gl_program_cache()->getProgram(d->drawable.context(), + GLuint program = qt_gl_program_cache()->getProgram(d->device->context(), FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, 0, true); if (d->matrix.type() >= QTransform::TxProject) { @@ -3916,7 +3931,7 @@ void QOpenGLPaintEnginePrivate::strokeLines(const QPainterPath &path) qreal penWidth = cpen.widthF(); - GLuint program = qt_gl_program_cache()->getProgram(drawable.context(), + GLuint program = qt_gl_program_cache()->getProgram(device->context(), FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, 0, true); QGLLineMaskGenerator maskGenerator(path, matrix, penWidth == 0 ? 1.0 : penWidth, offscreen, program); @@ -4302,7 +4317,7 @@ void QOpenGLPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QR else { GLenum target = qt_gl_preferredTextureTarget(); d->flushDrawQueue(); - d->drawable.bindTexture(pm, target); + d->device->context()->bindTexture(pm, target); drawTextureRect(pm.width(), pm.height(), r, sr, target); } } @@ -4336,9 +4351,9 @@ void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, con d->flushDrawQueue(); if (scaled.isNull()) - d->drawable.bindTexture(pm); + d->device->context()->bindTexture(pm); else - d->drawable.bindTexture(scaled); + d->device->context()->bindTexture(scaled); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, d->use_smooth_pixmap_transform); #ifndef QT_OPENGL_ES @@ -4404,7 +4419,7 @@ void QOpenGLPaintEngine::drawImage(const QRectF &r, const QImage &image, const Q else { GLenum target = qt_gl_preferredTextureTarget(); d->flushDrawQueue(); - d->drawable.bindTexture(image, target); + d->device->context()->bindTexture(image, target); drawTextureRect(image.width(), image.height(), r, sr, target); } } @@ -4871,7 +4886,7 @@ void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); // make sure the glyphs we want to draw are in the cache - qt_glyph_cache()->cacheGlyphs(d->drawable.context(), ti, glyphs); + qt_glyph_cache()->cacheGlyphs(d->device->context(), ti, glyphs); d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops qt_glColor4ubv(d->pen_color); @@ -4949,7 +4964,7 @@ void QOpenGLPaintEngine::drawEllipse(const QRectF &rect) glPushMatrix(); glLoadIdentity(); - GLuint program = qt_gl_program_cache()->getProgram(d->drawable.context(), + GLuint program = qt_gl_program_cache()->getProgram(d->device->context(), FRAGMENT_PROGRAM_MASK_ELLIPSE_AA, 0, true); QGLEllipseMaskGenerator maskGenerator(rect, d->matrix, @@ -5084,10 +5099,10 @@ void QOpenGLPaintEnginePrivate::copyDrawable(const QRectF &rect) QRectF screen_rect = rect.adjusted(-1, -1, 1, 1); int left = qMax(0, static_cast<int>(screen_rect.left())); - int width = qMin(drawable.size().width() - left, static_cast<int>(screen_rect.width()) + 1); + int width = qMin(device->size().width() - left, static_cast<int>(screen_rect.width()) + 1); - int bottom = qMax(0, static_cast<int>(drawable.size().height() - screen_rect.bottom())); - int height = qMin(drawable.size().height() - bottom, static_cast<int>(screen_rect.height()) + 1); + int bottom = qMax(0, static_cast<int>(device->size().height() - screen_rect.bottom())); + int height = qMin(device->size().height() - bottom, static_cast<int>(screen_rect.height()) + 1); glBindTexture(GL_TEXTURE_2D, drawable_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, left, bottom, width, height); @@ -5181,9 +5196,9 @@ void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const q_vertexType * glActiveTexture(GL_TEXTURE0 + brush_texture_location); if (current_style == Qt::TexturePattern) - drawable.bindTexture(cbrush.textureImage()); + device->context()->bindTexture(cbrush.textureImage()); else - drawable.bindTexture(qt_imageForBrush(current_style, true)); + device->context()->bindTexture(qt_imageForBrush(current_style, true)); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform); } @@ -5191,7 +5206,7 @@ void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const q_vertexType * glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); glEnable(GL_FRAGMENT_PROGRAM_ARB); - GLuint program = qt_gl_program_cache()->getProgram(drawable.context(), + GLuint program = qt_gl_program_cache()->getProgram(device->context(), fragment_brush, fragment_composition_mode, false); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program); @@ -5263,7 +5278,7 @@ void QOpenGLPaintEnginePrivate::drawItem(const QDrawQueueItem &item) setGradientOps(item.brush, item.location.screen_rect); composite(item.location.screen_rect, item.location.rect.topLeft() - item.location.screen_rect.topLeft() - - QPoint(0, offscreen.offscreenSize().height() - drawable.size().height())); + - QPoint(0, offscreen.offscreenSize().height() - device->size().height())); } void QOpenGLPaintEnginePrivate::flushDrawQueue() |