From 0d5170256c1658b0f6e0d3f6c736de01655b29d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 16 Aug 2011 12:53:04 +0200 Subject: Get rid of OpenGL 1.x engine and platform code from QtOpenGL. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I646b8e26d5e7214432a044866764d57cc11b2390 Reviewed-on: http://codereview.qt.nokia.com/3006 Reviewed-by: Qt Sanity Bot Reviewed-by: Jørgen Lind --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 9 - .../gl2paintengineex/qpaintengineex_opengl2_p.h | 8 - .../gl2paintengineex/qtextureglyphcache_gl.cpp | 4 - src/opengl/opengl.pro | 120 +- src/opengl/qgl.cpp | 610 +-- src/opengl/qgl.h | 91 - src/opengl/qgl_egl.cpp | 350 -- src/opengl/qgl_egl_p.h | 69 - src/opengl/qgl_mac.mm | 996 ---- src/opengl/qgl_p.h | 137 - src/opengl/qgl_win.cpp | 1601 ------ src/opengl/qgl_wince.cpp | 636 --- src/opengl/qgl_x11.cpp | 1904 ------- src/opengl/qgl_x11egl.cpp | 548 -- src/opengl/qglbuffer.cpp | 10 - src/opengl/qglextensions.cpp | 11 - src/opengl/qglextensions_p.h | 36 - src/opengl/qglframebufferobject.cpp | 110 +- src/opengl/qglframebufferobject.h | 19 - src/opengl/qglfunctions.h | 20 +- src/opengl/qglpixelbuffer.cpp | 106 +- src/opengl/qglpixelbuffer.h | 12 - src/opengl/qglpixelbuffer_egl.cpp | 224 - src/opengl/qglpixelbuffer_mac.mm | 331 -- src/opengl/qglpixelbuffer_p.h | 103 - src/opengl/qglpixelbuffer_win.cpp | 403 -- src/opengl/qglpixelbuffer_x11.cpp | 290 - src/opengl/qglpixmapfilter.cpp | 619 --- src/opengl/qglpixmapfilter_p.h | 94 - src/opengl/qglshaderprogram.cpp | 84 - src/opengl/qglshaderprogram.h | 26 - src/opengl/qgraphicsshadereffect.cpp | 2 - src/opengl/qpaintengine_opengl.cpp | 5635 -------------------- src/opengl/qpaintengine_opengl_p.h | 158 - 34 files changed, 53 insertions(+), 15323 deletions(-) delete mode 100644 src/opengl/qgl_egl.cpp delete mode 100644 src/opengl/qgl_egl_p.h delete mode 100644 src/opengl/qgl_mac.mm delete mode 100644 src/opengl/qgl_win.cpp delete mode 100644 src/opengl/qgl_wince.cpp delete mode 100644 src/opengl/qgl_x11.cpp delete mode 100644 src/opengl/qgl_x11egl.cpp delete mode 100644 src/opengl/qglpixelbuffer_egl.cpp delete mode 100644 src/opengl/qglpixelbuffer_mac.mm delete mode 100644 src/opengl/qglpixelbuffer_win.cpp delete mode 100644 src/opengl/qglpixelbuffer_x11.cpp delete mode 100644 src/opengl/qglpixmapfilter.cpp delete mode 100644 src/opengl/qglpixmapfilter_p.h delete mode 100644 src/opengl/qpaintengine_opengl.cpp delete mode 100644 src/opengl/qpaintengine_opengl_p.h (limited to 'src') diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 58b9002222..1be243a3f9 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -2047,20 +2047,11 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) bool QGL2PaintEngineEx::end() { Q_D(QGL2PaintEngineEx); - QGLContext *ctx = d->ctx; glUseProgram(0); d->transferMode(BrushDrawingMode); 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 - // the pixmap behind the driver's back before it's had a chance to use it. To fix this, we - // reference all QPixmaps which have been bound to stop them being deleted and only deref - // them here, after swapBuffers, where they can be safely deleted. - ctx->d_func()->boundPixmaps.clear(); -#endif d->ctx->d_ptr->active_engine = 0; d->resetGLState(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 2895d5a9b0..dbf760929c 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -153,8 +152,6 @@ public: void invalidateState(); - QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype); - void setRenderTextActive(bool); bool isNativePaintingActive() const; @@ -302,11 +299,6 @@ public: QTriangulatingStroker stroker; QDashedStrokeProcessor dasher; - QScopedPointer convolutionFilter; - QScopedPointer colorizeFilter; - QScopedPointer blurFilter; - QScopedPointer dropShadowFilter; - QSet pathCaches; QVector unusedVBOSToClean; QVector unusedIBOSToClean; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index dbed354dfb..4838ab09e7 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -43,10 +43,6 @@ #include "qpaintengineex_opengl2_p.h" #include "private/qglengineshadersource_p.h" -#if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL) -#include "private/qeglcontext_p.h" -#endif - QT_BEGIN_NAMESPACE #ifdef Q_WS_WIN diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 7c1c0ce5fd..52429c80b0 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -47,95 +47,35 @@ SOURCES += qgl.cpp \ qglpaintdevice.cpp \ qglbuffer.cpp \ - -!contains(QT_CONFIG, opengles2) { - HEADERS += qpaintengine_opengl_p.h - SOURCES += qpaintengine_opengl.cpp -} - -!contains(QT_CONFIG, opengles1) { - HEADERS += qglshaderprogram.h \ - qglpixmapfilter_p.h \ - qgraphicsshadereffect_p.h \ - gl2paintengineex/qglgradientcache_p.h \ - gl2paintengineex/qglengineshadermanager_p.h \ - gl2paintengineex/qgl2pexvertexarray_p.h \ - gl2paintengineex/qpaintengineex_opengl2_p.h \ - gl2paintengineex/qglengineshadersource_p.h \ - gl2paintengineex/qglcustomshaderstage_p.h \ - gl2paintengineex/qtriangulatingstroker_p.h \ - gl2paintengineex/qtriangulator_p.h \ - gl2paintengineex/qrbtree_p.h \ - gl2paintengineex/qtextureglyphcache_gl_p.h \ - gl2paintengineex/qglshadercache_p.h \ - gl2paintengineex/qglshadercache_meego_p.h - - SOURCES += qglshaderprogram.cpp \ - qglpixmapfilter.cpp \ - qgraphicsshadereffect.cpp \ - gl2paintengineex/qglgradientcache.cpp \ - gl2paintengineex/qglengineshadermanager.cpp \ - gl2paintengineex/qgl2pexvertexarray.cpp \ - gl2paintengineex/qpaintengineex_opengl2.cpp \ - gl2paintengineex/qglcustomshaderstage.cpp \ - gl2paintengineex/qtriangulatingstroker.cpp \ - gl2paintengineex/qtriangulator.cpp \ - gl2paintengineex/qtextureglyphcache_gl.cpp - -} - -qpa { - SOURCES += qgl_qpa.cpp \ - qglpixelbuffer_stub.cpp -} - -x11 { - contains(QT_CONFIG, egl) { - SOURCES += qgl_x11egl.cpp \ - qglpixelbuffer_egl.cpp \ - qgl_egl.cpp - - HEADERS += qgl_egl_p.h - - } else { - SOURCES += qgl_x11.cpp \ - qglpixelbuffer_x11.cpp - } - - contains(QT_CONFIG, fontconfig) { - contains(QT_CONFIG, system-freetype) { - # pull in the proper freetype2 include directory - include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) - LIBS_PRIVATE += -lfreetype - } else { - ### Note: how does this compile with a non-system freetype? - # This probably does not compile - } - } else { - DEFINES *= QT_NO_FREETYPE - } - - LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD -} - -mac:!qpa { - OBJECTIVE_SOURCES += qgl_mac.mm \ - qglpixelbuffer_mac.mm - LIBS_PRIVATE += -framework AppKit -framework Carbon -} -win32:!wince*: { - DEFINES += QT_NO_EGL - !qpa { - SOURCES += qgl_win.cpp \ - qglpixelbuffer_win.cpp - } -} -wince*: { - SOURCES += qgl_wince.cpp \ - qglpixelbuffer_egl.cpp \ - qgl_egl.cpp - - HEADERS += qgl_egl_p.h -} +HEADERS += qglshaderprogram.h \ + qgraphicsshadereffect_p.h \ + gl2paintengineex/qglgradientcache_p.h \ + gl2paintengineex/qglengineshadermanager_p.h \ + gl2paintengineex/qgl2pexvertexarray_p.h \ + gl2paintengineex/qpaintengineex_opengl2_p.h \ + gl2paintengineex/qglengineshadersource_p.h \ + gl2paintengineex/qglcustomshaderstage_p.h \ + gl2paintengineex/qtriangulatingstroker_p.h \ + gl2paintengineex/qtriangulator_p.h \ + gl2paintengineex/qrbtree_p.h \ + gl2paintengineex/qtextureglyphcache_gl_p.h \ + gl2paintengineex/qglshadercache_p.h \ + gl2paintengineex/qglshadercache_meego_p.h + +SOURCES += qglshaderprogram.cpp \ + qgraphicsshadereffect.cpp \ + gl2paintengineex/qglgradientcache.cpp \ + gl2paintengineex/qglengineshadermanager.cpp \ + gl2paintengineex/qgl2pexvertexarray.cpp \ + gl2paintengineex/qpaintengineex_opengl2.cpp \ + gl2paintengineex/qglcustomshaderstage.cpp \ + gl2paintengineex/qtriangulatingstroker.cpp \ + gl2paintengineex/qtriangulator.cpp \ + gl2paintengineex/qtextureglyphcache_gl.cpp + +SOURCES += qgl_qpa.cpp \ + qglpixelbuffer_stub.cpp + +DEFINES += QT_NO_EGL INCLUDEPATH += ../3rdparty/harfbuzz/src diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 4f9f5a9414..25adf0bade 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -45,21 +45,6 @@ #include #include -#if defined(Q_WS_X11) -#include "private/qt_x11_p.h" -#include "private/qpixmap_x11_p.h" -#define INT32 dummy_INT32 -#define INT8 dummy_INT8 -#ifdef QT_NO_EGL -# include -#endif -#undef INT32 -#undef INT8 -#include "qx11info_x11.h" -#elif defined(Q_WS_MAC) -# include -#endif - #include #include // malloc @@ -68,17 +53,9 @@ #include "qimage.h" #include "qgl_p.h" -#if !defined(QT_OPENGL_ES_1) #include "gl2paintengineex/qpaintengineex_opengl2_p.h" -#endif -#ifndef QT_OPENGL_ES_2 -#include -#endif - -#ifdef Q_WS_QPA #include -#endif #include #include @@ -92,21 +69,11 @@ #include "qlibrary.h" #include -#if defined(QT_OPENGL_ES) && !defined(QT_NO_EGL) -#include -#endif - // #define QT_GL_CONTEXT_RESOURCE_DEBUG QT_BEGIN_NAMESPACE -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs; -#endif - -#ifdef Q_WS_X11 -extern const QX11Info *qt_x11Info(const QPaintDevice *pd); -#endif struct QGLThreadContext { ~QGLThreadContext() { @@ -116,10 +83,6 @@ struct QGLThreadContext { QGLContext *context; }; -#ifndef Q_WS_QPA -static QThreadStorage qgl_context_storage; -#endif - Q_GLOBAL_STATIC(QGLFormat, qgl_default_format) class QGLDefaultOverlayFormat: public QGLFormat @@ -146,71 +109,6 @@ QGLSignalProxy *QGLSignalProxy::instance() } -class QGLEngineSelector -{ -public: - QGLEngineSelector() : engineType(QPaintEngine::MaxUser) - { - } - - void setPreferredPaintEngine(QPaintEngine::Type type) { - if (type == QPaintEngine::OpenGL || type == QPaintEngine::OpenGL2) - engineType = type; - } - - QPaintEngine::Type preferredPaintEngine() { -#ifdef Q_WS_MAC - // The ATI X1600 driver for Mac OS X does not support return - // values from functions in GLSL. Since working around this in - // the GL2 engine would require a big, ugly rewrite, we're - // falling back to the GL 1 engine.. - static bool mac_x1600_check_done = false; - if (!mac_x1600_check_done) { - QGLTemporaryContext *tmp = 0; - if (!QGLContext::currentContext()) - tmp = new QGLTemporaryContext(); - if (strstr((char *) glGetString(GL_RENDERER), "X1600")) - engineType = QPaintEngine::OpenGL; - if (tmp) - delete tmp; - mac_x1600_check_done = true; - } -#endif - if (engineType == QPaintEngine::MaxUser) { - // No user-set engine - use the defaults -#if defined(QT_OPENGL_ES_2) - engineType = QPaintEngine::OpenGL2; -#else - // We can't do this in the constructor for this object because it - // needs to be called *before* the QApplication constructor. - // Also check for the FragmentShader extension in conjunction with - // the 2.0 version flag, to cover the case where we export the display - // from an old GL 1.1 server to a GL 2.x client. In that case we can't - // use GL 2.0. - if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) - && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader) - && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty()) - engineType = QPaintEngine::OpenGL2; - else - engineType = QPaintEngine::OpenGL; -#endif - } - return engineType; - } - -private: - QPaintEngine::Type engineType; -}; - -Q_GLOBAL_STATIC(QGLEngineSelector, qgl_engine_selector) - - -bool qt_gl_preferGL2Engine() -{ - return qgl_engine_selector()->preferredPaintEngine() == QPaintEngine::OpenGL2; -} - - /*! \namespace QGL \inmodule QtOpenGL @@ -257,32 +155,6 @@ bool qt_gl_preferGL2Engine() \sa {Sample Buffers Example} */ -/*! - \fn void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType) - - \since 4.6 - - Sets the preferred OpenGL paint engine that is used to draw onto - QGLWidget, QGLPixelBuffer and QGLFramebufferObject targets with QPainter - in Qt. - - The \a engineType parameter specifies which of the GL engines to - use. Only \c QPaintEngine::OpenGL and \c QPaintEngine::OpenGL2 are - valid parameters to this function. All other values are ignored. - - By default, the \c QPaintEngine::OpenGL2 engine is used if GL/GLES - version 2.0 is available, otherwise \c QPaintEngine::OpenGL is - used. - - \warning This function must be called before the QApplication - constructor is called. -*/ -void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType) -{ - qgl_engine_selector()->setPreferredPaintEngine(engineType); -} - - /***************************************************************************** QGLFormat implementation *****************************************************************************/ @@ -1680,35 +1552,8 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) glFormat = reqFormat = format; valid = false; q->setDevice(dev); -#if defined(Q_WS_X11) - pbuf = 0; - gpm = 0; - vi = 0; - screen = QX11Info::appScreen(); -#endif -#if defined(Q_WS_WIN) - dc = 0; - win = 0; - threadId = 0; - pixelFormatId = 0; - cmap = 0; - hbitmap = 0; - hbitmap_hdc = 0; -#endif -#if defined(Q_WS_MAC) -# ifndef QT_MAC_USE_COCOA - update = false; -# endif - vi = 0; -#endif -#if defined(Q_WS_QPA) + guiGlContext = 0; -#endif -#if !defined(QT_NO_EGL) - ownsEglContext = false; - eglContext = 0; - eglSurface = EGL_NO_SURFACE; -#endif fbo = 0; crWin = false; initDone = false; @@ -1802,7 +1647,7 @@ QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alp QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); int w = size.width(); int h = size.height(); -#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) +#if !defined(QT_OPENGL_ES_2) //### glGetTexImage not in GL ES 2.0, need to do something else here! glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); #endif @@ -1912,13 +1757,6 @@ void QGLTextureCache::cleanupBeforePixmapDestruction(QPlatformPixmap* pmd) { // Remove any bound textures first: cleanupTexturesForPixampData(pmd); - -#if defined(Q_WS_X11) - if (pmd->classId() == QPlatformPixmap::X11Class) { - Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken - QGLContextPrivate::destroyGlSurfaceForPixmap(pmd); - } -#endif } QGLTextureCache *QGLTextureCache::instance() @@ -2139,13 +1977,11 @@ void QGLContextPrivate::syncGlState() } #undef ctx -#ifdef QT_NO_EGL void QGLContextPrivate::swapRegion(const QRegion &) { Q_Q(QGLContext); q->swapBuffers(); } -#endif /*! \overload @@ -2290,12 +2126,10 @@ static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum textu } } -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *) { return qt_extensionFuncs; } -#endif QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format) @@ -2594,39 +2428,6 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, } } -#if defined(Q_WS_X11) - // Try to use texture_from_pixmap - const QX11Info *xinfo = qt_x11Info(paintDevice); - if (pd->classId() == QPlatformPixmap::X11Class && pd->pixelType() == QPlatformPixmap::PixmapType - && xinfo && xinfo->screen() == pixmap.x11Info().screen() - && target == GL_TEXTURE_2D - && QApplication::instance()->thread() == QThread::currentThread()) - { - if (!workaround_brokenTextureFromPixmap_init) { - workaround_brokenTextureFromPixmap_init = true; - - const QByteArray versionString(reinterpret_cast(glGetString(GL_VERSION))); - const int pos = versionString.indexOf("NVIDIA "); - - if (pos >= 0) { - const QByteArray nvidiaVersionString = versionString.mid(pos + strlen("NVIDIA ")); - - if (nvidiaVersionString.startsWith("195") || nvidiaVersionString.startsWith("256")) - workaround_brokenTextureFromPixmap = true; - } - } - - if (!workaround_brokenTextureFromPixmap) { - texture = bindTextureFromNativePixmap(const_cast(&pixmap), key, options); - if (texture) { - texture->options |= QGLContext::MemoryManagedBindOption; - texture->boundPixmap = pd; - boundPixmaps.insert(pd, QPixmap(pixmap)); - } - } - } -#endif - if (!texture) { QImage image = pixmap.toImage(); // If the system depth is 16 and the pixmap doesn't have an alpha channel @@ -2745,31 +2546,6 @@ GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, return texture->id; } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format) -{ - if (image.isNull()) - return 0; - - Q_D(QGLContext); - QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), DefaultBindOption); - return texture->id; -} - -/*! \internal */ -GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format, - BindOptions options) -{ - if (image.isNull()) - return 0; - - Q_D(QGLContext); - QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), options); - return texture->id; -} -#endif - /*! \overload Generates and binds a 2D GL texture based on \a pixmap. @@ -2801,30 +2577,6 @@ GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint forma return texture->id; } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format) -{ - if (pixmap.isNull()) - return 0; - - Q_D(QGLContext); - QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption); - return texture->id; -} -/*! \internal */ -GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format, - BindOptions options) -{ - if (pixmap.isNull()) - return 0; - - Q_D(QGLContext); - QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options); - return texture->id; -} -#endif - /*! Removes the texture identified by \a id from the texture cache, and calls glDeleteTextures() to delete the texture from the @@ -2839,14 +2591,6 @@ void QGLContext::deleteTexture(GLuint id) glDeleteTextures(1, &id); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLContext::deleteTexture(QMacCompatGLuint id) -{ - return deleteTexture(GLuint(id)); -} -#endif - void qt_add_rect_to_array(const QRectF &r, GLfloat *array) { qreal left = r.left(); @@ -2986,14 +2730,6 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text #endif } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLContext::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget) -{ - drawTexture(target, GLuint(textureId), GLenum(textureTarget)); -} -#endif - /*! \since 4.4 @@ -3057,15 +2793,6 @@ void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum text #endif } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLContext::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget) -{ - drawTexture(point, GLuint(textureId), GLenum(textureTarget)); -} -#endif - - /*! This function sets the limit for the texture cache to \a size, expressed in kilobytes. @@ -3295,11 +3022,7 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex bool QGLContext::create(const QGLContext* shareContext) { Q_D(QGLContext); -#ifdef Q_WS_QPA if (!d->paintDevice && !d->guiGlContext) -#else - if (!d->paintDevice) -#endif return false; reset(); @@ -3308,10 +3031,6 @@ bool QGLContext::create(const QGLContext* shareContext) QWidgetPrivate *wd = qt_widget_private(static_cast(d->paintDevice)); wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer(); } -#ifndef Q_WS_QPA //We do this in choose context->setupSharing() - if (d->sharing) // ok, we managed to share - QGLContextGroup::addShare(this, shareContext); -#endif return d->valid; } @@ -3385,37 +3104,15 @@ void QGLContext::setInitialized(bool on) const QGLContext* QGLContext::currentContext() { -#ifdef Q_WS_QPA if (const QGuiGLContext *threadContext = QGuiGLContext::currentContext()) { return QGLContext::fromGuiGLContext(const_cast(threadContext)); } return 0; -#else - QGLThreadContext *threadContext = qgl_context_storage.localData(); - if (threadContext) - return threadContext->context; - return 0; -#endif //Q_WS_QPA } void QGLContextPrivate::setCurrentContext(QGLContext *context) { -#ifdef Q_WS_QPA Q_UNUSED(context); -#else - QGLThreadContext *threadContext = qgl_context_storage.localData(); - if (!threadContext) { - if (!QThread::currentThread()) { - // We don't have a current QThread, so just set the static. - QGLContext::currentCtx = context; - return; - } - threadContext = new QGLThreadContext; - qgl_context_storage.setLocalData(threadContext); - } - threadContext->context = context; - QGLContext::currentCtx = context; // XXX: backwards-compat, not thread-safe -#endif } /*! @@ -3727,11 +3424,6 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) on a QGLWidget and the widget's rendering context is current in another thread, it will fail. - Note that under X11 it is necessary to set the - Qt::AA_X11InitThreads application attribute to make the X11 - library and GLX calls thread safe, otherwise the above scenarios - will fail. - In addition to this, rendering using raw GL calls in a separate thread is supported. @@ -3872,30 +3564,9 @@ QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, const QGLWidget *shar QGLWidget::~QGLWidget() { Q_D(QGLWidget); -#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT) - bool doRelease = (glcx && glcx->windowCreated()); -#endif delete d->glcx; d->glcx = 0; -#if defined(Q_WS_WIN) - delete d->olcx; - d->olcx = 0; -#endif -#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT) - if (doRelease) - glXReleaseBuffersMESA(x11Display(), winId()); -#endif d->cleanupColormaps(); - -#ifdef Q_WS_MAC - QWidget *current = parentWidget(); - while (current) { - qt_widget_private(current)->glWidgets.removeAll(QWidgetPrivate::GlWidgetInfo(this)); - if (current->isWindow()) - break; - current = current->parentWidget(); - }; -#endif } /*! @@ -4241,125 +3912,6 @@ void QGLWidget::resizeOverlayGL(int, int) { } -/*! \fn bool QGLWidget::event(QEvent *e) - \reimp -*/ -#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA) -bool QGLWidget::event(QEvent *e) -{ - Q_D(QGLWidget); - - if (e->type() == QEvent::Paint) { - QPoint offset; - QPaintDevice *redirectedDevice = d->redirected(&offset); - if (redirectedDevice && redirectedDevice->devType() == QInternal::Pixmap) { - d->restoreRedirected(); - QPixmap pixmap = renderPixmap(); - d->setRedirected(redirectedDevice, offset); - QPainter p(redirectedDevice); - p.drawPixmap(-offset, pixmap); - return true; - } - } - -#if defined(Q_WS_X11) - if (e->type() == QEvent::ParentChange) { - // if we've reparented a window that has the current context - // bound, we need to rebind that context to the new window id - if (d->glcx == QGLContext::currentContext()) - makeCurrent(); - - if (d->glcx->d_func()->screen != d->xinfo.screen() || testAttribute(Qt::WA_TranslucentBackground)) { - setContext(new QGLContext(d->glcx->requestedFormat(), this)); - // ### recreating the overlay isn't supported atm - } - } - -#ifndef QT_NO_EGL - // A re-parent is likely to destroy the X11 window and re-create it. It is important - // that we free the EGL surface _before_ the winID changes - otherwise we can leak. - if (e->type() == QEvent::ParentAboutToChange) - d->glcx->d_func()->destroyEglSurfaceForDevice(); - - if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) { - // The window may have been re-created during re-parent or state change - if so, the EGL - // surface will need to be re-created. - d->recreateEglSurface(); - } -#endif -#elif defined(Q_WS_WIN) - if (e->type() == QEvent::ParentChange) { - QGLContext *newContext = new QGLContext(d->glcx->requestedFormat(), this); - setContext(newContext, d->glcx); - - // the overlay needs to be recreated as well - delete d->olcx; - if (isValid() && context()->format().hasOverlay()) { - d->olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), this); - if (!d->olcx->create(isSharing() ? d->glcx : 0)) { - delete d->olcx; - d->olcx = 0; - d->glcx->d_func()->glFormat.setOverlay(false); - } - } else { - d->olcx = 0; - } - } else if (e->type() == QEvent::Show) { - if (!format().rgba()) - d->updateColormap(); - } -#elif defined(Q_WS_MAC) - if (e->type() == QEvent::MacGLWindowChange -#if 0 //(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - && ((QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && isWindow()) - || QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4) -#endif - ) { - if (d->needWindowChange) { - d->needWindowChange = false; - d->glcx->updatePaintDevice(); - update(); - } - return true; -# if defined(QT_MAC_USE_COCOA) - } else if (e->type() == QEvent::MacGLClearDrawable) { - d->glcx->d_ptr->clearDrawable(); -# endif - } -#elif defined(Q_OS_SYMBIAN) - // prevents errors on some systems, where we get a flush to a - // hidden widget - if (e->type() == QEvent::Hide) { - makeCurrent(); - glFinish(); - doneCurrent(); - } else if (e->type() == QEvent::ParentChange) { - // if we've reparented a window that has the current context - // bound, we need to rebind that context to the new window id - if (d->glcx == QGLContext::currentContext()) - makeCurrent(); - - if (testAttribute(Qt::WA_TranslucentBackground)) - setContext(new QGLContext(d->glcx->requestedFormat(), this)); - } - - // A re-parent is likely to destroy the Symbian window and re-create it. It is important - // that we free the EGL surface _before_ the winID changes - otherwise we can leak. - if (e->type() == QEvent::ParentAboutToChange) - d->glcx->d_func()->destroyEglSurfaceForDevice(); - - if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) { - // The window may have been re-created during re-parent or state change - if so, the EGL - // surface will need to be re-created. - d->recreateEglSurface(); - } - -#endif - - return QWidget::event(e); -} -#endif - /*! \fn void QGLWidget::paintEvent(QPaintEvent *event) @@ -4433,28 +3985,7 @@ QPixmap QGLWidget::renderPixmap(int w, int h, bool useContext) if ((w > 0) && (h > 0)) sz = QSize(w, h); -#if defined(Q_WS_X11) - extern int qt_x11_preferred_pixmap_depth; - int old_depth = qt_x11_preferred_pixmap_depth; - qt_x11_preferred_pixmap_depth = x11Info().depth(); - - QPlatformPixmap *data = new QX11PlatformPixmap(QPlatformPixmap::PixmapType); - data->resize(sz.width(), sz.height()); - QPixmap pm(data); - qt_x11_preferred_pixmap_depth = old_depth; - QX11Info xinfo = x11Info(); - - // make sure we use a pixmap with the same depth/visual as the widget - if (xinfo.visual() != QX11Info::appVisual()) { - QX11InfoData* xd = pm.x11Info().getX11Data(true); - xd->depth = xinfo.depth(); - xd->visual = static_cast(xinfo.visual()); - const_cast(pm.x11Info()).setX11Data(xd); - } - -#else QPixmap pm(sz); -#endif d->glcx->doneCurrent(); @@ -4466,9 +3997,6 @@ QPixmap QGLWidget::renderPixmap(int w, int h, bool useContext) QGLFormat fmt = d->glcx->requestedFormat(); fmt.setDirectRendering(false); // Direct is unlikely to work fmt.setDoubleBuffer(false); // We don't need dbl buf -#ifdef Q_WS_MAC // crash prevention on the Mac - it's unlikely to work anyway - fmt.setSampleBuffers(false); -#endif QGLContext* ocx = d->glcx; ocx->doneCurrent(); @@ -4486,13 +4014,6 @@ QPixmap QGLWidget::renderPixmap(int w, int h, bool useContext) ocx->makeCurrent(); if (success) { -#if defined(Q_WS_X11) - if (xinfo.visual() != QX11Info::appVisual()) { - QImage image = pm.toImage(); - QPixmap p = QPixmap::fromImage(image); - return p; - } -#endif return pm; } return QPixmap(); @@ -4512,21 +4033,8 @@ QImage QGLWidget::grabFrameBuffer(bool withAlpha) QImage res; int w = width(); int h = height(); - if (format().rgba()) { + if (format().rgba()) res = qt_gl_read_framebuffer(QSize(w, h), format().alpha(), withAlpha); - } else { -#if defined (Q_WS_WIN) && !defined(QT_OPENGL_ES) - res = QImage(w, h, QImage::Format_Indexed8); - glReadPixels(0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, res.bits()); - const QVector pal = QColormap::instance().colormap(); - if (pal.size()) { - res.setColorCount(pal.size()); - for (int i = 0; i < pal.size(); i++) - res.setColor(i, pal.at(i).rgb()); - } - res = res.mirrored(); -#endif - } return res; } @@ -4561,11 +4069,6 @@ void QGLWidget::glDraw() Q_D(QGLWidget); if (!isValid()) return; -#ifdef Q_OS_SYMBIAN - // Crashes on Symbian if trying to render to invisible surfaces - if (!isVisible() && d->glcx->device()->devType() == QInternal::Widget) - return; -#endif makeCurrent(); #ifndef QT_OPENGL_ES if (d->glcx->deviceIsPixmap()) @@ -4884,10 +4387,8 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int height = d->glcx->device()->height(); bool auto_swap = autoBufferSwap(); - QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine(); - QPaintEngine *engine = paintEngine(); - if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) { + if (engine && engine->isActive()) { qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is" " active on the same device is not allowed."); return; @@ -4939,7 +4440,6 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, setAutoBufferSwap(auto_swap); d->disable_clear_on_painter_begin = false; } - qgl_engine_selector()->setPreferredPaintEngine(oldEngineType); #else // QT_OPENGL_ES Q_UNUSED(x); Q_UNUSED(y); @@ -4987,10 +4487,9 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con &win_x, &win_y, &win_z); win_y = height - win_y; // y is inverted - QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine(); QPaintEngine *engine = paintEngine(); - if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) { + if (engine && engine->isActive()) { qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is" " active on the same device is not allowed."); return; @@ -5043,7 +4542,6 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con setAutoBufferSwap(auto_swap); d->disable_clear_on_painter_begin = false; } - qgl_engine_selector()->setPreferredPaintEngine(oldEngineType); #else // QT_OPENGL_ES Q_UNUSED(x); Q_UNUSED(y); @@ -5116,28 +4614,6 @@ GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format) -{ - if (image.isNull()) - return 0; - - Q_D(QGLWidget); - return d->glcx->bindTexture(image, GLenum(target), GLint(format), QGLContext::DefaultBindOption); -} - -GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format, - QGLContext::BindOptions options) -{ - if (image.isNull()) - return 0; - - Q_D(QGLWidget); - return d->glcx->bindTexture(image, GLenum(target), GLint(format), options); -} -#endif - /*! Calls QGLContext:::bindTexture(\a pixmap, \a target, \a format) on the currently set context. @@ -5170,23 +4646,6 @@ GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format return d->glcx->bindTexture(pixmap, target, format, options); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format) -{ - Q_D(QGLWidget); - return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption); -} - -GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format, - QGLContext::BindOptions options) -{ - Q_D(QGLWidget); - return d->glcx->bindTexture(pixmap, target, format, options); -} -#endif - - /*! \overload Calls QGLContext::bindTexture(\a fileName) on the currently set context. @@ -5211,15 +4670,6 @@ void QGLWidget::deleteTexture(GLuint id) d->glcx->deleteTexture(id); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLWidget::deleteTexture(QMacCompatGLuint id) -{ - Q_D(QGLWidget); - d->glcx->deleteTexture(GLuint(id)); -} -#endif - /*! \since 4.4 @@ -5233,15 +4683,6 @@ void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textu d->glcx->drawTexture(target, textureId, textureTarget); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLWidget::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget) -{ - Q_D(QGLWidget); - d->glcx->drawTexture(target, GLint(textureId), GLenum(textureTarget)); -} -#endif - /*! \since 4.4 @@ -5255,42 +4696,17 @@ void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textu d->glcx->drawTexture(point, textureId, textureTarget); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget) -{ - Q_D(QGLWidget); - d->glcx->drawTexture(point, GLuint(textureId), GLenum(textureTarget)); -} -#endif - -#ifndef QT_OPENGL_ES_1 Q_GLOBAL_STATIC(QGLEngineThreadStorage, qt_gl_2_engine) -#endif - -#ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QGLEngineThreadStorage, qt_gl_engine) -#endif Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine() { -#if defined(QT_OPENGL_ES_1) - return qt_gl_engine()->engine(); -#elif defined(QT_OPENGL_ES_2) return qt_gl_2_engine()->engine(); -#else - if (qt_gl_preferGL2Engine()) - return qt_gl_2_engine()->engine(); - else - return qt_gl_engine()->engine(); -#endif } /*! \internal - Returns the GL widget's paint engine. This is normally a - QOpenGLPaintEngine. + Returns the GL widget's paint engine. */ QPaintEngine *QGLWidget::paintEngine() const { @@ -5458,10 +4874,6 @@ QGLExtensions::Extensions QGLExtensions::currentContextExtensions() glExtensions |= GenerateMipmap; glExtensions |= FragmentShader; #endif -#if defined(QT_OPENGL_ES_1) - if (extensions.match("GL_OES_framebuffer_object")) - glExtensions |= FramebufferObject; -#endif #if defined(QT_OPENGL_ES) if (extensions.match("GL_OES_packed_depth_stencil")) glExtensions |= PackedDepthStencil; @@ -5554,7 +4966,6 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi glcx = new QGLContext(QGLFormat::defaultFormat(), q); } -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) Q_GLOBAL_STATIC(QString, qt_gl_lib_name) Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name) @@ -5565,21 +4976,14 @@ Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name) Q_OPENGL_EXPORT const QString qt_gl_library_name() { if (qt_gl_lib_name()->isNull()) { -#ifdef Q_WS_MAC - return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"); -#else -# if defined(QT_OPENGL_ES_1) - return QLatin1String("GLES_CM"); -# elif defined(QT_OPENGL_ES_2) +# if defined(QT_OPENGL_ES_2) return QLatin1String("GLESv2"); # else return QLatin1String("GL"); # endif -#endif // defined Q_WS_MAC } return *qt_gl_lib_name(); } -#endif void QGLContextGroup::addShare(const QGLContext *context, const QGLContext *share) { Q_ASSERT(context && share); diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index e08e2d234f..3446e29029 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -58,18 +58,6 @@ QT_BEGIN_HEADER #if defined(Q_OS_MAC) # include -#elif defined(QT_OPENGL_ES_1) -# if defined(Q_OS_MAC) -# include -# else -# include -# endif -# ifndef GL_DOUBLE -# define GL_DOUBLE GL_FLOAT -# endif -# ifndef GLdouble -typedef GLfloat GLdouble; -# endif #elif defined(QT_OPENGL_ES_2) # if defined(Q_OS_MAC) # include @@ -94,31 +82,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(OpenGL) -#if defined(Q_WS_MAC) && defined (QT_BUILD_OPENGL_LIB) && !defined(QT_MAC_USE_COCOA) && !defined(QDOC) -#define Q_MAC_COMPAT_GL_FUNCTIONS - -template -struct QMacGLCompatTypes -{ - typedef long CompatGLint; - typedef unsigned long CompatGLuint; - typedef unsigned long CompatGLenum; -}; - -template <> -struct QMacGLCompatTypes -{ - typedef int CompatGLint; - typedef unsigned int CompatGLuint; - typedef unsigned int CompatGLenum; -}; - -typedef QMacGLCompatTypes::CompatGLint QMacCompatGLint; -typedef QMacGLCompatTypes::CompatGLuint QMacCompatGLuint; -typedef QMacGLCompatTypes::CompatGLenum QMacCompatGLenum; - -#endif - #ifdef QT3_SUPPORT #define QGL_VERSION 460 #define QGL_VERSION_STR "4.6" @@ -132,9 +95,6 @@ class QGLCmap; #endif class QPixmap; -#if defined(Q_WS_X11) && !defined(QT_OPENGL_ES) -class QGLOverlayWidget; -#endif class QGLWidgetPrivate; class QGLContextPrivate; @@ -371,22 +331,6 @@ public: void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D); void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D); -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS - GLuint bindTexture(const QImage &image, QMacCompatGLenum = GL_TEXTURE_2D, - QMacCompatGLint format = GL_RGBA); - GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum = GL_TEXTURE_2D, - QMacCompatGLint format = GL_RGBA); - GLuint bindTexture(const QImage &image, QMacCompatGLenum, QMacCompatGLint format, - BindOptions); - GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum, QMacCompatGLint format, - BindOptions); - - void deleteTexture(QMacCompatGLuint tx_id); - - void drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D); - void drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D); -#endif - static void setTextureCacheLimit(int size); static int textureCacheLimit(); @@ -396,25 +340,12 @@ public: static const QGLContext* currentContext(); -#ifdef Q_WS_QPA static QGLContext *fromGuiGLContext(QGuiGLContext *platformContext); QGuiGLContext *contextHandle() const; -#endif protected: virtual bool chooseContext(const QGLContext* shareContext = 0); -#if defined(Q_WS_WIN) - virtual int choosePixelFormat(void* pfd, HDC pdc); -#endif -#if defined(Q_WS_X11) && defined(QT_NO_EGL) - virtual void* tryVisual(const QGLFormat& f, int bufDepth = 1); - virtual void* chooseVisual(); -#endif -#if defined(Q_WS_MAC) - virtual void* chooseMacVisual(GDHandle); -#endif - bool deviceIsPixmap() const; bool windowCreated() const; void setWindowCreated(bool on); @@ -430,9 +361,7 @@ protected: static QGLContext* currentCtx; private: -#ifdef Q_WS_QPA QGLContext(QGuiGLContext *windowContext); -#endif QScopedPointer d_ptr; @@ -441,12 +370,9 @@ private: friend class QGLWidget; friend class QGLWidgetPrivate; friend class QGLGlyphCache; - friend class QOpenGLPaintEngine; - friend class QOpenGLPaintEnginePrivate; friend class QGL2PaintEngineEx; friend class QGL2PaintEngineExPrivate; friend class QGLEngineShaderManager; - friend class QGLPixmapFilterBase; friend class QGLTextureGlyphCache; friend struct QGLGlyphTexture; friend class QGLContextGroup; @@ -553,22 +479,6 @@ public: void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D); void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D); -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS - GLuint bindTexture(const QImage &image, QMacCompatGLenum = GL_TEXTURE_2D, - QMacCompatGLint format = GL_RGBA); - GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum = GL_TEXTURE_2D, - QMacCompatGLint format = GL_RGBA); - GLuint bindTexture(const QImage &image, QMacCompatGLenum, QMacCompatGLint format, - QGLContext::BindOptions); - GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum, QMacCompatGLint format, - QGLContext::BindOptions); - - void deleteTexture(QMacCompatGLuint tx_id); - - void drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D); - void drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D); -#endif - public Q_SLOTS: virtual void updateGL(); virtual void updateOverlayGL(); @@ -610,7 +520,6 @@ private: friend class QGLContext; friend class QGLContextPrivate; friend class QGLOverlayWidget; - friend class QOpenGLPaintEngine; friend class QGLPaintDevice; friend class QGLWidgetGLPaintDevice; }; diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp deleted file mode 100644 index dcf340fb10..0000000000 --- a/src/opengl/qgl_egl.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include "qgl_p.h" -#include "qgl_egl_p.h" -#include "qglpixelbuffer_p.h" - -#ifdef Q_WS_X11 -#include -#endif - -QT_BEGIN_NAMESPACE - -QEglProperties *QGLContextPrivate::extraWindowSurfaceCreationProps = NULL; - -void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat) -{ - int redSize = glFormat.redBufferSize(); - int greenSize = glFormat.greenBufferSize(); - int blueSize = glFormat.blueBufferSize(); - int alphaSize = glFormat.alphaBufferSize(); - int depthSize = glFormat.depthBufferSize(); - int stencilSize = glFormat.stencilBufferSize(); - int sampleCount = glFormat.samples(); - - // QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that - // type has been requested. So we must check QGLFormat's booleans too if size is -1: - if (glFormat.alpha() && alphaSize <= 0) - alphaSize = 1; - if (glFormat.depth() && depthSize <= 0) - depthSize = 1; - if (glFormat.stencil() && stencilSize <= 0) - stencilSize = 1; - if (glFormat.sampleBuffers() && sampleCount <= 0) - sampleCount = 1; - - // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide - // the best performance. The EGL config selection algorithm is a bit stange in this regard: - // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard - // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. - // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort - // order is special and described as "by larger _total_ number of color bits.". So EGL will - // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on - // to say "If the requested number of bits in attrib_list for a particular component is 0, - // then the number of bits for that component is not considered". This part of the spec also - // seems to imply that setting the red/green/blue bits to zero means none of the components - // are considered and EGL disregards the entire sorting rule. It then looks to the next - // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being - // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are - // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, - // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that - // if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will - // probably get a 32-bit config, even when there's an RGB565 config available. Oh well. - - // Now normalize the values so -1 becomes 0 - redSize = redSize > 0 ? redSize : 0; - greenSize = greenSize > 0 ? greenSize : 0; - blueSize = blueSize > 0 ? blueSize : 0; - alphaSize = alphaSize > 0 ? alphaSize : 0; - depthSize = depthSize > 0 ? depthSize : 0; - stencilSize = stencilSize > 0 ? stencilSize : 0; - sampleCount = sampleCount > 0 ? sampleCount : 0; - - eglProperties.setValue(EGL_RED_SIZE, redSize); - eglProperties.setValue(EGL_GREEN_SIZE, greenSize); - eglProperties.setValue(EGL_BLUE_SIZE, blueSize); - eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize); - eglProperties.setValue(EGL_DEPTH_SIZE, depthSize); - eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize); - eglProperties.setValue(EGL_SAMPLES, sampleCount); - eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0); -} - -// Updates "format" with the parameters of the selected configuration. -void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config) -{ - EGLint redSize = 0; - EGLint greenSize = 0; - EGLint blueSize = 0; - EGLint alphaSize = 0; - EGLint depthSize = 0; - EGLint stencilSize = 0; - EGLint sampleCount = 0; - EGLint level = 0; - - EGLDisplay display = QEgl::display(); - eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize); - eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize); - eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize); - eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize); - eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize); - eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize); - eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount); - eglGetConfigAttrib(display, config, EGL_LEVEL, &level); - - format.setRedBufferSize(redSize); - format.setGreenBufferSize(greenSize); - format.setBlueBufferSize(blueSize); - format.setAlphaBufferSize(alphaSize); - format.setDepthBufferSize(depthSize); - format.setStencilBufferSize(stencilSize); - format.setSamples(sampleCount); - format.setPlane(level); - format.setDirectRendering(true); // All EGL contexts are direct-rendered - format.setRgba(true); // EGL doesn't support colour index rendering - format.setStereo(false); // EGL doesn't support stereo buffers - format.setAccumBufferSize(0); // EGL doesn't support accululation buffers - format.setDoubleBuffer(true); // We don't support single buffered EGL contexts - - // Clear the EGL error state because some of the above may - // have errored out because the attribute is not applicable - // to the surface type. Such errors don't matter. - eglGetError(); -} - -bool QGLFormat::hasOpenGL() -{ - return true; -} - -void QGLContext::reset() -{ - Q_D(QGLContext); - if (!d->valid) - return; - d->cleanup(); - doneCurrent(); - if (d->eglContext && d->ownsEglContext) { - d->destroyEglSurfaceForDevice(); - delete d->eglContext; - } - d->ownsEglContext = false; - d->eglContext = 0; - d->eglSurface = EGL_NO_SURFACE; - d->crWin = false; - d->sharing = false; - d->valid = false; - d->transpColor = QColor(); - d->initDone = false; - QGLContextGroup::removeShare(this); -} - -void QGLContext::makeCurrent() -{ - Q_D(QGLContext); - if (!d->valid || !d->eglContext || d->eglSurfaceForDevice() == EGL_NO_SURFACE) { - qWarning("QGLContext::makeCurrent(): Cannot make invalid context current"); - return; - } - - if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) { - QGLContextPrivate::setCurrentContext(this); - if (!d->workaroundsCached) { - d->workaroundsCached = true; - const char *renderer = reinterpret_cast(glGetString(GL_RENDERER)); - if (renderer && (strstr(renderer, "SGX") || strstr(renderer, "MBX"))) { - // PowerVR MBX/SGX chips needs to clear all buffers when starting to render - // a new frame, otherwise there will be a performance penalty to pay for - // each frame. - qDebug() << "Found SGX/MBX driver, enabling FullClearOnEveryFrame"; - d->workaround_needsFullClearOnEveryFrame = true; - - // Older PowerVR SGX drivers (like the one in the N900) have a - // bug which prevents glCopyTexSubImage2D() to work with a POT - // or GL_ALPHA texture bound to an FBO. The only way to - // identify that driver is to check the EGL version number for it. - const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION); - - if (egl_version && strstr(egl_version, "1.3")) { - qDebug() << "Found v1.3 driver, enabling brokenFBOReadBack"; - d->workaround_brokenFBOReadBack = true; - } else if (egl_version && strstr(egl_version, "1.4")) { - qDebug() << "Found v1.4 driver, enabling brokenTexSubImage"; - d->workaround_brokenTexSubImage = true; - - // this is a bit complicated; 1.4 version SGX drivers from - // Nokia have fixed the brokenFBOReadBack problem, but - // official drivers from TI haven't, meaning that things - // like the beagleboard are broken unless we hack around it - // - but at the same time, we want to not reduce performance - // by not enabling this elsewhere. - // - // so, let's check for a Nokia-specific addon, and only - // enable if it isn't present. - // (see MeeGo bug #5616) - if (!QEgl::hasExtension("EGL_NOK_image_shared")) { - // no Nokia extension, this is probably a standard SGX - // driver, so enable the workaround - qDebug() << "Found non-Nokia v1.4 driver, enabling brokenFBOReadBack"; - d->workaround_brokenFBOReadBack = true; - } - } - } - } - } -} - -void QGLContext::doneCurrent() -{ - Q_D(QGLContext); - if (d->eglContext) - d->eglContext->doneCurrent(); - - QGLContextPrivate::setCurrentContext(0); -} - - -void QGLContext::swapBuffers() const -{ - Q_D(const QGLContext); - if (!d->valid || !d->eglContext) - return; - - d->eglContext->swapBuffers(d->eglSurfaceForDevice()); -} - -void QGLContextPrivate::destroyEglSurfaceForDevice() -{ - if (eglSurface != EGL_NO_SURFACE) { -#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN) - // Make sure we don't call eglDestroySurface on a surface which - // was created for a different winId. This applies only to QGLWidget - // paint device, so make sure this is the one we're operating on. - if (paintDevice && paintDevice->devType() == QInternal::Widget) { - QWidget *w = static_cast(paintDevice); - if (QGLWidget *wgl = qobject_cast(w)) { - if (wgl->d_func()->eglSurfaceWindowId != wgl->winId()) { - qWarning("WARNING: Potential EGL surface leak! Not destroying surface."); - eglSurface = EGL_NO_SURFACE; - return; - } - } - } -#endif - eglDestroySurface(eglContext->display(), eglSurface); - eglSurface = EGL_NO_SURFACE; - } -} - -EGLSurface QGLContextPrivate::eglSurfaceForDevice() const -{ - // If a QPlatformPixmap had to create the QGLContext, we don't have a paintDevice - if (!paintDevice) - return eglSurface; - -#ifdef Q_WS_X11 - if (paintDevice->devType() == QInternal::Pixmap) { - QPlatformPixmap *pmd = static_cast(paintDevice)->data_ptr().data(); - if (pmd->classId() == QPlatformPixmap::X11Class) { - QX11PlatformPixmap* x11PlatformPixmap = static_cast(pmd); - return (EGLSurface)x11PlatformPixmap->gl_surface; - } - } -#endif - - if (paintDevice->devType() == QInternal::Pbuffer) { - QGLPixelBuffer* pbuf = static_cast(paintDevice); - return pbuf->d_func()->pbuf; - } - - return eglSurface; -} - -void QGLContextPrivate::swapRegion(const QRegion ®ion) -{ - if (!valid || !eglContext) - return; - - eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), ®ion); -} - -void QGLContextPrivate::setExtraWindowSurfaceCreationProps(QEglProperties *props) -{ - extraWindowSurfaceCreationProps = props; -} - -void QGLWidget::setMouseTracking(bool enable) -{ - QWidget::setMouseTracking(enable); -} - -QColor QGLContext::overlayTransparentColor() const -{ - return d_func()->transpColor; -} - -uint QGLContext::colorIndex(const QColor &c) const -{ - Q_UNUSED(c); - return 0; -} - -void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase) -{ - Q_UNUSED(fnt); - Q_UNUSED(listBase); -} - -void *QGLContext::getProcAddress(const QString &proc) const -{ - return (void*)eglGetProcAddress(reinterpret_cast(proc.toLatin1().data())); -} - -bool QGLWidgetPrivate::renderCxPm(QPixmap*) -{ - return false; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qgl_egl_p.h b/src/opengl/qgl_egl_p.h deleted file mode 100644 index 2522fca822..0000000000 --- a/src/opengl/qgl_egl_p.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGL_EGL_P_H -#define QGL_EGL_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 QGLWidget class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QGLFormat; - -void qt_eglproperties_set_glformat(QEglProperties& props, const QGLFormat& format); -void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config); - -QT_END_NAMESPACE - -#endif // QGL_EGL_P_H diff --git a/src/opengl/qgl_mac.mm b/src/opengl/qgl_mac.mm deleted file mode 100644 index d4b2a40e93..0000000000 --- a/src/opengl/qgl_mac.mm +++ /dev/null @@ -1,996 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgl.h" - -// There are functions that are deprecated in 10.5, but really there's no way around them -// for Carbon, so just undefine them. -#undef DEPRECATED_ATTRIBUTE -#define DEPRECATED_ATTRIBUTE -#if defined(Q_WS_MAC) -#ifndef QT_MAC_USE_COCOA -#ifdef qDebug -# undef qDebug -# include -# include -# include -# ifdef QT_NO_DEBUG -# define qDebug qt_noop(),1?(void)0:qDebug -# endif -#else -# include -# include -# include -#endif -#else -#include -#endif - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE -#ifdef QT_MAC_USE_COCOA -QT_END_NAMESPACE - -QT_FORWARD_DECLARE_CLASS(QWidget) -QT_FORWARD_DECLARE_CLASS(QWidgetPrivate) -QT_FORWARD_DECLARE_CLASS(QGLWidgetPrivate) - -QT_BEGIN_NAMESPACE - -void *qt_current_nsopengl_context() -{ - return [NSOpenGLContext currentContext]; -} - -static GLint attribValue(NSOpenGLPixelFormat *fmt, NSOpenGLPixelFormatAttribute attrib) -{ - GLint res; - [fmt getValues:&res forAttribute:attrib forVirtualScreen:0]; - return res; -} - -static int def(int val, int defVal) -{ - return val != -1 ? val : defVal; -} -#else -QRegion qt_mac_get_widget_rgn(const QWidget *widget); -#endif - -extern quint32 *qt_mac_pixmap_get_base(const QPixmap *); -extern int qt_mac_pixmap_get_bytes_per_line(const QPixmap *); -extern RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp -extern void qt_mac_dispose_rgn(RgnHandle); //qregion_mac.cpp -extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp -extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); //qglobal.cpp - -/* - QGLTemporaryContext implementation -*/ - -class QGLTemporaryContextPrivate -{ -public: -#ifndef QT_MAC_USE_COCOA - AGLContext ctx; -#else - NSOpenGLContext *ctx; -#endif -}; - -QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) - : d(new QGLTemporaryContextPrivate) -{ - d->ctx = 0; -#ifndef QT_MAC_USE_COCOA - GLint attribs[] = {AGL_RGBA, AGL_NONE}; - AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs); - if (!fmt) { - qDebug("QGLTemporaryContext: Couldn't find any RGB visuals"); - return; - } - d->ctx = aglCreateContext(fmt, 0); - if (!d->ctx) - qDebug("QGLTemporaryContext: Unable to create context"); - else - aglSetCurrentContext(d->ctx); - aglDestroyPixelFormat(fmt); -#else - QMacCocoaAutoReleasePool pool; - NSOpenGLPixelFormatAttribute attribs[] = { 0 }; - NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; - if (!fmt) { - qWarning("QGLTemporaryContext: Cannot find any visuals"); - return; - } - - d->ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0]; - if (!d->ctx) - qWarning("QGLTemporaryContext: Cannot create context"); - else - [d->ctx makeCurrentContext]; - [fmt release]; -#endif -} - -QGLTemporaryContext::~QGLTemporaryContext() -{ - if (d->ctx) { -#ifndef QT_MAC_USE_COCOA - aglSetCurrentContext(0); - aglDestroyContext(d->ctx); -#else - [NSOpenGLContext clearCurrentContext]; - [d->ctx release]; -#endif - } -} - -bool QGLFormat::hasOpenGL() -{ - return true; -} - -bool QGLFormat::hasOpenGLOverlays() -{ - return false; -} - -bool QGLContext::chooseContext(const QGLContext *shareContext) -{ - QMacCocoaAutoReleasePool pool; - Q_D(QGLContext); - d->cx = 0; - d->vi = chooseMacVisual(0); - if (!d->vi) - return false; - -#ifndef QT_MAC_USE_COCOA - AGLPixelFormat fmt = (AGLPixelFormat)d->vi; - GLint res; - aglDescribePixelFormat(fmt, AGL_LEVEL, &res); - d->glFormat.setPlane(res); - if (deviceIsPixmap()) - res = 0; - else - aglDescribePixelFormat(fmt, AGL_DOUBLEBUFFER, &res); - d->glFormat.setDoubleBuffer(res); - aglDescribePixelFormat(fmt, AGL_DEPTH_SIZE, &res); - d->glFormat.setDepth(res); - if (d->glFormat.depth()) - d->glFormat.setDepthBufferSize(res); - aglDescribePixelFormat(fmt, AGL_RGBA, &res); - d->glFormat.setRgba(res); - aglDescribePixelFormat(fmt, AGL_RED_SIZE, &res); - d->glFormat.setRedBufferSize(res); - aglDescribePixelFormat(fmt, AGL_GREEN_SIZE, &res); - d->glFormat.setGreenBufferSize(res); - aglDescribePixelFormat(fmt, AGL_BLUE_SIZE, &res); - d->glFormat.setBlueBufferSize(res); - aglDescribePixelFormat(fmt, AGL_ALPHA_SIZE, &res); - d->glFormat.setAlpha(res); - if (d->glFormat.alpha()) - d->glFormat.setAlphaBufferSize(res); - aglDescribePixelFormat(fmt, AGL_ACCUM_RED_SIZE, &res); - // Bug in Apple OpenGL (rdr://5015603), when we don't have an accumulation - // buffer, it still claims that we have a 16-bit one (which is pretty rare). - // So, we just assume we can never have a buffer that small. - d->glFormat.setAccum(res > 5); - if (d->glFormat.accum()) - d->glFormat.setAccumBufferSize(res); - aglDescribePixelFormat(fmt, AGL_STENCIL_SIZE, &res); - d->glFormat.setStencil(res); - if (d->glFormat.stencil()) - d->glFormat.setStencilBufferSize(res); - aglDescribePixelFormat(fmt, AGL_STEREO, &res); - d->glFormat.setStereo(res); - aglDescribePixelFormat(fmt, AGL_SAMPLE_BUFFERS_ARB, &res); - d->glFormat.setSampleBuffers(res); - if (d->glFormat.sampleBuffers()) { - aglDescribePixelFormat(fmt, AGL_SAMPLES_ARB, &res); - d->glFormat.setSamples(res); - } -#else - NSOpenGLPixelFormat *fmt = static_cast(d->vi); - - d->glFormat = QGLFormat(); - - // ### make sure to reset other options - d->glFormat.setDoubleBuffer(attribValue(fmt, NSOpenGLPFADoubleBuffer)); - - int depthSize = attribValue(fmt, NSOpenGLPFADepthSize); - d->glFormat.setDepth(depthSize > 0); - if (depthSize > 0) - d->glFormat.setDepthBufferSize(depthSize); - - int alphaSize = attribValue(fmt, NSOpenGLPFAAlphaSize); - d->glFormat.setAlpha(alphaSize > 0); - if (alphaSize > 0) - d->glFormat.setAlphaBufferSize(alphaSize); - - int accumSize = attribValue(fmt, NSOpenGLPFAAccumSize); - d->glFormat.setAccum(accumSize > 0); - if (accumSize > 0) - d->glFormat.setAccumBufferSize(accumSize); - - int stencilSize = attribValue(fmt, NSOpenGLPFAStencilSize); - d->glFormat.setStencil(stencilSize > 0); - if (stencilSize > 0) - d->glFormat.setStencilBufferSize(stencilSize); - - d->glFormat.setStereo(attribValue(fmt, NSOpenGLPFAStereo)); - - int sampleBuffers = attribValue(fmt, NSOpenGLPFASampleBuffers); - d->glFormat.setSampleBuffers(sampleBuffers); - if (sampleBuffers > 0) - d->glFormat.setSamples(attribValue(fmt, NSOpenGLPFASamples)); -#endif - if (shareContext && (!shareContext->isValid() || !shareContext->d_func()->cx)) { - qWarning("QGLContext::chooseContext: Cannot share with invalid context"); - shareContext = 0; - } - - // sharing between rgba and color-index will give wrong colors - if (shareContext && (format().rgba() != shareContext->format().rgba())) - shareContext = 0; - -#ifndef QT_MAC_USE_COCOA - AGLContext ctx = aglCreateContext(fmt, (AGLContext) (shareContext ? shareContext->d_func()->cx : 0)); -#else - NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:fmt - shareContext:(shareContext ? static_cast(shareContext->d_func()->cx) - : 0)]; -#endif - if (!ctx) { -#ifndef QT_MAC_USE_COCOA - GLenum err = aglGetError(); - if (err == AGL_BAD_MATCH || err == AGL_BAD_CONTEXT) { - if (shareContext && shareContext->d_func()->cx) { - qWarning("QGLContext::chooseContext(): Context sharing mismatch!"); - if (!(ctx = aglCreateContext(fmt, 0))) - return false; - shareContext = 0; - } - } -#else - if (shareContext) { - ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0]; - if (ctx) { - qWarning("QGLContext::chooseContext: Context sharing mismatch"); - shareContext = 0; - } - } -#endif - if (!ctx) { - qWarning("QGLContext::chooseContext: Unable to create QGLContext"); - return false; - } - } - d->cx = ctx; - if (shareContext && shareContext->d_func()->cx) { - QGLContext *share = const_cast(shareContext); - d->sharing = true; - share->d_func()->sharing = true; - } - if (deviceIsPixmap()) - updatePaintDevice(); - - // vblank syncing - GLint interval = d->reqFormat.swapInterval(); - if (interval != -1) { -#ifndef QT_MAC_USE_COCOA - aglSetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval); - if (interval != 0) - aglEnable((AGLContext)d->cx, AGL_SWAP_INTERVAL); - else - aglDisable((AGLContext)d->cx, AGL_SWAP_INTERVAL); -#else - [ctx setValues:&interval forParameter:NSOpenGLCPSwapInterval]; -#endif - } -#ifndef QT_MAC_USE_COCOA - aglGetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval); -#else - [ctx getValues:&interval forParameter:NSOpenGLCPSwapInterval]; -#endif - d->glFormat.setSwapInterval(interval); - return true; -} - -void *QGLContextPrivate::tryFormat(const QGLFormat &format) -{ - static const int Max = 40; -#ifndef QT_MAC_USE_COCOA - GLint attribs[Max], cnt = 0; - bool device_is_pixmap = (paintDevice->devType() == QInternal::Pixmap); - - attribs[cnt++] = AGL_RGBA; - attribs[cnt++] = AGL_BUFFER_SIZE; - attribs[cnt++] = device_is_pixmap ? static_cast(paintDevice)->depth() : 32; - attribs[cnt++] = AGL_LEVEL; - attribs[cnt++] = format.plane(); - - if (format.redBufferSize() != -1) { - attribs[cnt++] = AGL_RED_SIZE; - attribs[cnt++] = format.redBufferSize(); - } - if (format.greenBufferSize() != -1) { - attribs[cnt++] = AGL_GREEN_SIZE; - attribs[cnt++] = format.greenBufferSize(); - } - if (format.blueBufferSize() != -1) { - attribs[cnt++] = AGL_BLUE_SIZE; - attribs[cnt++] = format.blueBufferSize(); - } - if (device_is_pixmap) { - attribs[cnt++] = AGL_PIXEL_SIZE; - attribs[cnt++] = static_cast(paintDevice)->depth(); - attribs[cnt++] = AGL_OFFSCREEN; - if (!format.alpha()) { - attribs[cnt++] = AGL_ALPHA_SIZE; - attribs[cnt++] = 8; - } - } else { - if (format.doubleBuffer()) - attribs[cnt++] = AGL_DOUBLEBUFFER; - } - - if (format.stereo()) - attribs[cnt++] = AGL_STEREO; - if (format.alpha()) { - attribs[cnt++] = AGL_ALPHA_SIZE; - attribs[cnt++] = format.alphaBufferSize() == -1 ? 8 : format.alphaBufferSize(); - } - if (format.stencil()) { - attribs[cnt++] = AGL_STENCIL_SIZE; - attribs[cnt++] = format.stencilBufferSize() == -1 ? 8 : format.stencilBufferSize(); - } - if (format.depth()) { - attribs[cnt++] = AGL_DEPTH_SIZE; - attribs[cnt++] = format.depthBufferSize() == -1 ? 32 : format.depthBufferSize(); - } - if (format.accum()) { - attribs[cnt++] = AGL_ACCUM_RED_SIZE; - attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize(); - attribs[cnt++] = AGL_ACCUM_BLUE_SIZE; - attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize(); - attribs[cnt++] = AGL_ACCUM_GREEN_SIZE; - attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize(); - attribs[cnt++] = AGL_ACCUM_ALPHA_SIZE; - attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize(); - } - if (format.sampleBuffers()) { - attribs[cnt++] = AGL_SAMPLE_BUFFERS_ARB; - attribs[cnt++] = 1; - attribs[cnt++] = AGL_SAMPLES_ARB; - attribs[cnt++] = format.samples() == -1 ? 4 : format.samples(); - } - - attribs[cnt] = AGL_NONE; - Q_ASSERT(cnt < Max); - return aglChoosePixelFormat(0, 0, attribs); -#else - NSOpenGLPixelFormatAttribute attribs[Max]; - int cnt = 0; - int devType = paintDevice->devType(); - bool device_is_pixmap = (devType == QInternal::Pixmap); - int depth = device_is_pixmap ? static_cast(paintDevice)->depth() : 32; - - attribs[cnt++] = NSOpenGLPFAColorSize; - attribs[cnt++] = depth; - - if (device_is_pixmap) { - attribs[cnt++] = NSOpenGLPFAOffScreen; - } else { - if (format.doubleBuffer()) - attribs[cnt++] = NSOpenGLPFADoubleBuffer; - } - if (glFormat.stereo()) - attribs[cnt++] = NSOpenGLPFAStereo; - if (device_is_pixmap || format.alpha()) { - attribs[cnt++] = NSOpenGLPFAAlphaSize; - attribs[cnt++] = def(format.alphaBufferSize(), 8); - } - if (format.stencil()) { - attribs[cnt++] = NSOpenGLPFAStencilSize; - attribs[cnt++] = def(format.stencilBufferSize(), 8); - } - if (format.depth()) { - attribs[cnt++] = NSOpenGLPFADepthSize; - attribs[cnt++] = def(format.depthBufferSize(), 32); - } - if (format.accum()) { - attribs[cnt++] = NSOpenGLPFAAccumSize; - attribs[cnt++] = def(format.accumBufferSize(), 1); - } - if (format.sampleBuffers()) { - attribs[cnt++] = NSOpenGLPFASampleBuffers; - attribs[cnt++] = 1; - attribs[cnt++] = NSOpenGLPFASamples; - attribs[cnt++] = def(format.samples(), 4); - } - - if (format.directRendering()) - attribs[cnt++] = NSOpenGLPFAAccelerated; - - if (devType == QInternal::Pbuffer) - attribs[cnt++] = NSOpenGLPFAPixelBuffer; - - attribs[cnt] = 0; - Q_ASSERT(cnt < Max); - return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; -#endif -} - -void QGLContextPrivate::clearDrawable() -{ - [static_cast(cx) clearDrawable]; -} - -/*! - \bold{Mac OS X only:} This virtual function tries to find a visual that - matches the format, reducing the demands if the original request - cannot be met. - - The algorithm for reducing the demands of the format is quite - simple-minded, so override this method in your subclass if your - application has spcific requirements on visual selection. - - The \a handle argument is always zero and is not used - - \sa chooseContext() -*/ - -void *QGLContext::chooseMacVisual(GDHandle /* handle */) -{ - Q_D(QGLContext); - - void *fmt = d->tryFormat(d->glFormat); - if (!fmt && d->glFormat.stereo()) { - d->glFormat.setStereo(false); - fmt = d->tryFormat(d->glFormat); - } - if (!fmt && d->glFormat.sampleBuffers()) { - d->glFormat.setSampleBuffers(false); - fmt = d->tryFormat(d->glFormat); - } - if (!fmt) - qWarning("QGLContext::chooseMacVisual: Unable to choose a pixel format"); - return fmt; -} - -void QGLContext::reset() -{ - Q_D(QGLContext); - if (!d->valid) - return; - d->cleanup(); - doneCurrent(); -#ifndef QT_MAC_USE_COCOA - if (d->cx) - aglDestroyContext((AGLContext)d->cx); -#else - QMacCocoaAutoReleasePool pool; - [static_cast(d->cx) release]; -#endif - d->cx = 0; -#ifndef QT_MAC_USE_COCOA - if (d->vi) - aglDestroyPixelFormat((AGLPixelFormat)d->vi); -#else - [static_cast(d->vi) release]; -#endif - d->vi = 0; - d->crWin = false; - d->sharing = false; - d->valid = false; - d->transpColor = QColor(); - d->initDone = false; - QGLContextGroup::removeShare(this); -} - -void QGLContext::makeCurrent() -{ - Q_D(QGLContext); - - if (!d->valid) { - qWarning("QGLContext::makeCurrent: Cannot make invalid context current"); - return; - } -#ifndef QT_MAC_USE_COCOA - aglSetCurrentContext((AGLContext)d->cx); - if (d->update) - updatePaintDevice(); -#else - [static_cast(d->cx) makeCurrentContext]; -#endif - QGLContextPrivate::setCurrentContext(this); -} - -#ifndef QT_MAC_USE_COCOA -/* - Returns the effective scale factor for a widget. For this value to be - different than 1, the following must be true: - - The system scale factor must be greater than 1. - - The widget window must have WA_MacFrameworkScaled set. -*/ -float qt_mac_get_scale_factor(QWidget *widget) -{ - if (!widget | !widget->window()) - return 1; - - if (widget->window()->testAttribute(Qt::WA_MacFrameworkScaled) == false) - return 1; - - float systemScale = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 ? HIGetScaleFactor() : 1; - if (systemScale == float(1)) - return 1; - - return systemScale; -} -#endif - -/*! \internal -*/ -void QGLContext::updatePaintDevice() -{ - Q_D(QGLContext); -#ifndef QT_MAC_USE_COCOA - d->update = false; - if (d->paintDevice->devType() == QInternal::Widget) { - //get control information - QWidget *w = (QWidget *)d->paintDevice; - HIViewRef hiview = (HIViewRef)w->winId(); - WindowRef window = HIViewGetWindow(hiview); -#ifdef DEBUG_OPENGL_REGION_UPDATE - static int serial_no_gl = 0; - qDebug("[%d] %p setting on %s::%s %p/%p [%s]", ++serial_no_gl, w, - w->metaObject()->className(), w->objectName().toLatin1().constData(), - hiview, window, w->handle() ? "Inside" : "Outside"); -#endif - - //update drawable - if (0 && w->isWindow() && w->isFullScreen()) { - aglSetDrawable((AGLContext)d->cx, 0); - aglSetFullScreen((AGLContext)d->cx, w->width(), w->height(), 0, QApplication::desktop()->screenNumber(w)); - w->hide(); - } else { - AGLDrawable old_draw = aglGetDrawable((AGLContext)d->cx), new_draw = GetWindowPort(window); - if (old_draw != new_draw) - aglSetDrawable((AGLContext)d->cx, new_draw); - } - - float scale = qt_mac_get_scale_factor(w); - - if (!w->isWindow()) { - QRegion clp = qt_mac_get_widget_rgn(w); //get drawable area - -#ifdef DEBUG_OPENGL_REGION_UPDATE - if (clp.isEmpty()) { - qDebug(" Empty area!"); - } else { - QVector rs = clp.rects(); - for(int i = 0; i < rs.count(); i++) - qDebug(" %d %d %d %d", rs[i].x(), rs[i].y(), rs[i].width(), rs[i].height()); - } -#endif - //update the clip - if (!aglIsEnabled((AGLContext)d->cx, AGL_BUFFER_RECT)) - aglEnable((AGLContext)d->cx, AGL_BUFFER_RECT); - if (clp.isEmpty()) { - GLint offs[4] = { 0, 0, 0, 0 }; - aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs); - if (aglIsEnabled((AGLContext)d->cx, AGL_CLIP_REGION)) - aglDisable((AGLContext)d->cx, AGL_CLIP_REGION); - } else { - HIPoint origin = { 0., 0. }; - HIViewConvertPoint(&origin, HIViewRef(w->winId()), 0); - const GLint offs[4] = { qRound(origin.x), - w->window()->frameGeometry().height() * scale - - (qRound(origin.y) + w->height() * scale), - w->width() * scale, w->height() * scale}; - - RgnHandle region = clp.handle(true); - - if (scale != float(1)) { - // Sacle the clip region by the scale factor - Rect regionBounds; - GetRegionBounds(region, ®ionBounds); - Rect regionBoundsDest = regionBounds; - regionBoundsDest.bottom *= scale; - regionBoundsDest.right *= scale; - MapRgn(region, ®ionBounds, ®ionBoundsDest); - } - - aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs); - aglSetInteger((AGLContext)d->cx, AGL_CLIP_REGION, (const GLint *)region); - if (!aglIsEnabled((AGLContext)d->cx, AGL_CLIP_REGION)) - aglEnable((AGLContext)d->cx, AGL_CLIP_REGION); - } - } else { - // Set the buffer rect for top-level gl contexts when scaled. - if (scale != float(1)) { - aglEnable((AGLContext)d->cx, AGL_BUFFER_RECT); - const GLint offs[4] = { 0, 0, w->width() * scale , w->height() * scale}; - aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs); - } - } - } else if (d->paintDevice->devType() == QInternal::Pixmap) { - QPixmap *pm = reinterpret_cast(d->paintDevice); - - unsigned long qdformat = k32ARGBPixelFormat; - if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) - qdformat = k32BGRAPixelFormat; - Rect rect; - SetRect(&rect, 0, 0, pm->width(), pm->height()); - - GWorldPtr gworld; - NewGWorldFromPtr(&gworld, qdformat, &rect, 0, 0, 0, - reinterpret_cast(qt_mac_pixmap_get_base(pm)), - qt_mac_pixmap_get_bytes_per_line(pm)); - - PixMapHandle pixmapHandle = GetGWorldPixMap(gworld); - aglSetOffScreen(reinterpret_cast(d->cx), pm->width(), pm->height(), - GetPixRowBytes(pixmapHandle), GetPixBaseAddr(pixmapHandle)); - } else { - qWarning("QGLContext::updatePaintDevice(): Not sure how to render OpenGL on this device!"); - } - aglUpdateContext((AGLContext)d->cx); - -#else - QMacCocoaAutoReleasePool pool; - - if (d->paintDevice->devType() == QInternal::Widget) { - //get control information - QWidget *w = (QWidget *)d->paintDevice; - NSView *view = qt_mac_nativeview_for(w); - - // Trying to attach the GL context to the NSView will fail with - // "invalid drawable" if done too soon, but we have to make sure - // the connection is made before the first paint event. Using - // the NSView do to this check fails as the NSView is visible - // before it's safe to connect, and using the NSWindow fails as - // the NSWindow will become visible after the first paint event. - // This leaves us with the QWidget, who's visible state seems - // to match the point in time when it's safe to connect. - if (!w || !w->isVisible()) - return; // Not safe to attach GL context to view yet - - if ([static_cast(d->cx) view] != view && ![view isHidden]) - [static_cast(d->cx) setView:view]; - } else if (d->paintDevice->devType() == QInternal::Pixmap) { - const QPixmap *pm = static_cast(d->paintDevice); - [static_cast(d->cx) setOffScreen:qt_mac_pixmap_get_base(pm) - width:pm->width() - height:pm->height() - rowbytes:qt_mac_pixmap_get_bytes_per_line(pm)]; - } else { - qWarning("QGLContext::updatePaintDevice: Not sure how to render OpenGL on this device"); - } - [static_cast(d->cx) update]; -#endif -} - -void QGLContext::doneCurrent() -{ - - if ( -#ifndef QT_MAC_USE_COCOA - aglGetCurrentContext() != (AGLContext) d_func()->cx -#else - [NSOpenGLContext currentContext] != d_func()->cx -#endif - ) - return; - - QGLContextPrivate::setCurrentContext(0); -#ifndef QT_MAC_USE_COCOA - aglSetCurrentContext(0); -#else - [NSOpenGLContext clearCurrentContext]; -#endif -} - -void QGLContext::swapBuffers() const -{ - Q_D(const QGLContext); - if (!d->valid) - return; -#ifndef QT_MAC_USE_COCOA - aglSwapBuffers((AGLContext)d->cx); -#else - [static_cast(d->cx) flushBuffer]; -#endif -} - -QColor QGLContext::overlayTransparentColor() const -{ - return QColor(0, 0, 0); // Invalid color -} - -#ifndef QT_MAC_USE_COCOA -static QColor cmap[256]; -static bool cmap_init = false; -#endif -uint QGLContext::colorIndex(const QColor &c) const -{ -#ifndef QT_MAC_USE_COCOA - int ret = -1; - if(!cmap_init) { - cmap_init = true; - for(int i = 0; i < 256; i++) - cmap[i] = QColor(); - } else { - for(int i = 0; i < 256; i++) { - if(cmap[i].isValid() && cmap[i] == c) { - ret = i; - break; - } - } - } - if(ret == -1) { - for(ret = 0; ret < 256; ret++) - if(!cmap[ret].isValid()) - break; - if(ret == 256) { - ret = -1; - qWarning("QGLContext::colorIndex(): Internal error!"); - } else { - cmap[ret] = c; - - GLint vals[4]; - vals[0] = ret; - vals[1] = c.red(); - vals[2] = c.green(); - vals[3] = c.blue(); - aglSetInteger((AGLContext)d_func()->cx, AGL_COLORMAP_ENTRY, vals); - } - } - return (uint)(ret == -1 ? 0 : ret); -#else - Q_UNUSED(c); - return 0; -#endif -} - -void QGLContext::generateFontDisplayLists(const QFont & /* fnt */, int /* listBase */) -{ -} - -static CFBundleRef qt_getOpenGLBundle() -{ - CFBundleRef bundle = 0; - CFStringRef urlString = QCFString::toCFStringRef(QLatin1String("/System/Library/Frameworks/OpenGL.framework")); - QCFType url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, - urlString, kCFURLPOSIXPathStyle, false); - if (url) - bundle = CFBundleCreate(kCFAllocatorDefault, url); - CFRelease(urlString); - return bundle; -} - -void *QGLContext::getProcAddress(const QString &proc) const -{ - CFStringRef procName = QCFString(proc).toCFStringRef(proc); - void *result = CFBundleGetFunctionPointerForName(QCFType(qt_getOpenGLBundle()), - procName); - CFRelease(procName); - return result; -} -#ifndef QT_MAC_USE_COCOA -/***************************************************************************** - QGLWidget AGL-specific code - *****************************************************************************/ - -/**************************************************************************** - Hacks to glue AGL to an HIView - ***************************************************************************/ -QRegion qt_mac_get_widget_rgn(const QWidget *widget) -{ - if(!widget->isVisible() || widget->isMinimized()) - return QRegion(); - const QRect wrect = QRect(qt_mac_posInWindow(widget), widget->size()); - if(!wrect.isValid()) - return QRegion(); - - RgnHandle macr = qt_mac_get_rgn(); - GetControlRegion((HIViewRef)widget->winId(), kControlStructureMetaPart, macr); - OffsetRgn(macr, wrect.x(), wrect.y()); - QRegion ret = qt_mac_convert_mac_region(macr); - - QPoint clip_pos = wrect.topLeft(); - for(const QWidget *last_clip = 0, *clip = widget; clip; last_clip = clip, clip = clip->parentWidget()) { - if(clip != widget) { - GetControlRegion((HIViewRef)clip->winId(), kControlStructureMetaPart, macr); - OffsetRgn(macr, clip_pos.x(), clip_pos.y()); - ret &= qt_mac_convert_mac_region(macr); - } - const QObjectList &children = clip->children(); - for(int i = children.size()-1; i >= 0; --i) { - if(QWidget *child = qobject_cast(children.at(i))) { - if(child == last_clip) - break; - - // This check may seem weird, but when we are using a unified toolbar - // The widget is actually being owned by that toolbar and not by Qt. - // This means that the geometry it reports will be wrong - // and will accidentally cause problems when calculating the region - // So, it is better to skip these widgets since they aren't the hierarchy - // anyway. - if (HIViewGetSuperview(HIViewRef(child->winId())) != HIViewRef(clip->winId())) - continue; - - if(child->isVisible() && !child->isMinimized() && !child->isTopLevel()) { - const QRect childRect = QRect(clip_pos+child->pos(), child->size()); - if(childRect.isValid() && wrect.intersects(childRect)) { - GetControlRegion((HIViewRef)child->winId(), kControlStructureMetaPart, macr); - OffsetRgn(macr, childRect.x(), childRect.y()); - ret -= qt_mac_convert_mac_region(macr); - } - } - } - } - if(clip->isWindow()) - break; - clip_pos -= clip->pos(); - } - qt_mac_dispose_rgn(macr); - return ret; -} - -#endif - -void QGLWidget::setMouseTracking(bool enable) -{ - QWidget::setMouseTracking(enable); -} - -void QGLWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QGLWidget); - if (!isValid()) - return; -#ifndef QT_MAC_USE_COCOA - if (!isWindow()) - d->glcx->d_func()->update = true; -#endif - makeCurrent(); - if (!d->glcx->initialized()) - glInit(); -#ifdef QT_MAC_USE_COCOA - d->glcx->updatePaintDevice(); -#endif -#ifndef QT_MAC_USE_COCOA - float scale = qt_mac_get_scale_factor(this); - resizeGL(width() * scale, height() * scale); -#else - resizeGL(width(), height()); -#endif -} - -const QGLContext* QGLWidget::overlayContext() const -{ - return 0; -} - -void QGLWidget::makeOverlayCurrent() -{ -} - -void QGLWidget::updateOverlayGL() -{ -} - -void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext) -{ - Q_D(QGLWidget); - if (context == 0) { - qWarning("QGLWidget::setContext: Cannot set null context"); - return; - } - - if (d->glcx) - d->glcx->doneCurrent(); - QGLContext* oldcx = d->glcx; - d->glcx = context; - if (!d->glcx->isValid()) - d->glcx->create(shareContext ? shareContext : oldcx); - if (deleteOldContext && oldcx) - delete oldcx; -} - -void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget) -{ - Q_Q(QGLWidget); - - initContext(context, shareWidget); - - QWidget *current = q; - while (current) { - qt_widget_private(current)->glWidgets.append(QWidgetPrivate::GlWidgetInfo(q)); - if (current->isWindow()) - break; - current = current->parentWidget(); - } -} - -bool QGLWidgetPrivate::renderCxPm(QPixmap*) -{ - return false; -} - -void QGLWidgetPrivate::cleanupColormaps() -{ -} - -const QGLColormap & QGLWidget::colormap() const -{ - return d_func()->cmap; -} - -void QGLWidget::setColormap(const QGLColormap &) -{ -} - -void QGLWidgetPrivate::updatePaintDevice() -{ - Q_Q(QGLWidget); - glcx->updatePaintDevice(); - q->update(); -} - -#endif - -QT_END_NAMESPACE diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index f418008203..d132b97260 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -64,20 +64,13 @@ #include "qcache.h" #include "qglpaintdevice_p.h" -#ifndef QT_NO_EGL -#include -#endif - -#if defined(Q_WS_QPA) #include -#endif QT_BEGIN_NAMESPACE class QGLContext; class QGLOverlayWidget; class QPixmap; -class QPixmapFilter; #ifdef Q_WS_MAC # ifdef qDebug # define old_qDebug qDebug @@ -96,10 +89,6 @@ QT_END_INCLUDE_NAMESPACE class QMacWindowChangeEvent; #endif -#ifndef QT_NO_EGL -class QEglContext; -#endif - QT_BEGIN_INCLUDE_NAMESPACE #include QT_END_INCLUDE_NAMESPACE @@ -161,15 +150,6 @@ class Q_OPENGL_EXPORT QGLWidgetPrivate : public QWidgetPrivate public: QGLWidgetPrivate() : QWidgetPrivate() , disable_clear_on_painter_begin(false) -#if defined(Q_WS_QWS) - , wsurf(0) -#endif -#if defined(Q_WS_X11) && !defined(QT_NO_EGL) - , eglSurfaceWindowId(0) -#endif -#if defined(Q_OS_SYMBIAN) - , eglSurfaceWindowId(0) -#endif { isGLWidget = 1; } @@ -195,24 +175,6 @@ public: #endif bool disable_clear_on_painter_begin; - -#if defined(Q_WS_WIN) - void updateColormap(); - QGLContext *olcx; -#elif defined(Q_WS_X11) - QGLOverlayWidget *olw; -#ifndef QT_NO_EGL - void recreateEglSurface(); - WId eglSurfaceWindowId; -#endif -#elif defined(Q_WS_MAC) - QGLContext *olcx; - void updatePaintDevice(); -#endif -#ifdef Q_OS_SYMBIAN - void recreateEglSurface(); - WId eglSurfaceWindowId; -#endif }; class QGLContextGroupResourceBase; @@ -345,54 +307,9 @@ public: void syncGlState(); // Makes sure the GL context's state is what we think it is void swapRegion(const QRegion ®ion); -#if defined(Q_WS_WIN) - void updateFormatVersion(); -#endif - -#if defined(Q_WS_WIN) - HGLRC rc; - HDC dc; - WId win; - int pixelFormatId; - QGLCmap* cmap; - HBITMAP hbitmap; - HDC hbitmap_hdc; - Qt::HANDLE threadId; -#endif -#ifndef QT_NO_EGL - QEglContext *eglContext; - EGLSurface eglSurface; - void destroyEglSurfaceForDevice(); - EGLSurface eglSurfaceForDevice() const; - static QEglProperties *extraWindowSurfaceCreationProps; - static void setExtraWindowSurfaceCreationProps(QEglProperties *props); -#endif - -#if defined(Q_WS_QPA) QGuiGLContext *guiGlContext; void setupSharing(); -#elif defined(Q_WS_X11) || defined(Q_WS_MAC) - void* cx; -#endif -#if defined(Q_WS_X11) || defined(Q_WS_MAC) - void* vi; -#endif -#if defined(Q_WS_X11) - void* pbuf; - quint32 gpm; - int screen; - QHash boundPixmaps; - QGLTexture *bindTextureFromNativePixmap(QPixmap*, const qint64 key, - QGLContext::BindOptions options); - static void destroyGlSurfaceForPixmap(QPlatformPixmap*); - static void unbindPixmapFromTexture(QPlatformPixmap*); -#endif -#if defined(Q_WS_MAC) - bool update; - void *tryFormat(const QGLFormat &format); - void clearDrawable(); -#endif QGLFormat glFormat; QGLFormat reqFormat; GLuint fbo; @@ -417,10 +334,6 @@ public: uint workaround_brokenAlphaTexSubImage : 1; uint workaround_brokenAlphaTexSubImage_init : 1; -#ifndef QT_NO_EGL - uint ownsEglContext : 1; -#endif - QPaintDevice *paintDevice; QColor transpColor; QGLContext *q_ptr; @@ -441,14 +354,8 @@ public: static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; } -#ifdef Q_WS_WIN - static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); } -#endif - -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) static Q_OPENGL_EXPORT QGLExtensionFuncs qt_extensionFuncs; static Q_OPENGL_EXPORT QGLExtensionFuncs& extensionFuncs(const QGLContext *); -#endif static void setCurrentContext(QGLContext *context); }; @@ -514,21 +421,6 @@ Q_SIGNALS: private slots: void freeTexture_slot(QGLContext *context, QPlatformPixmap *boundPixmap, GLuint id) { Q_UNUSED(boundPixmap); -#if defined(Q_WS_X11) - if (boundPixmap) { - QGLContext *oldContext = const_cast(QGLContext::currentContext()); - context->makeCurrent(); - // Although glXReleaseTexImage is a glX call, it must be called while there - // is a current context - the context the pixmap was bound to a texture in. - // Otherwise the release doesn't do anything and you get BadDrawable errors - // when you come to delete the context. - QGLContextPrivate::unbindPixmapFromTexture(boundPixmap); - glDeleteTextures(1, &id); - if (oldContext) - oldContext->makeCurrent(); - return; - } -#endif QGLShareContextScope scope(context); glDeleteTextures(1, &id); } @@ -555,17 +447,12 @@ public: id(tx_id), target(tx_target), options(opt) -#if defined(Q_WS_X11) - , boundPixmap(0) -#endif {} ~QGLTexture() { if (options & QGLContext::MemoryManagedBindOption) { Q_ASSERT(context); -#if !defined(Q_WS_X11) QPlatformPixmap *boundPixmap = 0; -#endif context->d_ptr->texture_destroyer->emitFreeTexture(context, boundPixmap, id); } } @@ -576,10 +463,6 @@ public: QGLContext::BindOptions options; -#if defined(Q_WS_X11) - QPlatformPixmap* boundPixmap; -#endif - bool canBindCompressedTexture (const char *buf, int len, const char *format, bool *hasAlpha); QSize bindCompressedTexture @@ -656,26 +539,6 @@ QGLTexture* QGLTextureCache::getTexture(QGLContext *ctx, qint64 key) extern Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine(); -bool qt_gl_preferGL2Engine(); - -inline GLenum qt_gl_preferredTextureFormat() -{ - return (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian - ? GL_BGRA : GL_RGBA; -} - -inline GLenum qt_gl_preferredTextureTarget() -{ -#if defined(QT_OPENGL_ES_2) - return GL_TEXTURE_2D; -#else - return (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle) - && !qt_gl_preferGL2Engine() - ? GL_TEXTURE_RECTANGLE_NV - : GL_TEXTURE_2D; -#endif -} - /* Base for resources that are shared in a context group. */ diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp deleted file mode 100644 index 3b1643f4c2..0000000000 --- a/src/opengl/qgl_win.cpp +++ /dev/null @@ -1,1601 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -typedef bool (APIENTRY *PFNWGLGETPIXELFORMATATTRIBIVARB)(HDC hdc, - int iPixelFormat, - int iLayerPlane, - uint nAttributes, - const int *piAttributes, - int *piValues); -typedef bool (APIENTRY *PFNWGLCHOOSEPIXELFORMATARB)(HDC hdc, - const int *piAttribList, - const float *pfAttribFList, - uint nMaxFormats, - int *piFormats, - UINT *nNumFormats); -#ifndef WGL_ARB_multisample -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 -#endif - -#ifndef WGL_ARB_pixel_format -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_DRAW_TO_BITMAP_ARB 0x2002 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NEED_PALETTE_ARB 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 -#define WGL_SWAP_METHOD_ARB 0x2007 -#define WGL_NUMBER_OVERLAYS_ARB 0x2008 -#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 -#define WGL_TRANSPARENT_ARB 0x200A -#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 -#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 -#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 -#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A -#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B -#define WGL_SHARE_DEPTH_ARB 0x200C -#define WGL_SHARE_STENCIL_ARB 0x200D -#define WGL_SHARE_ACCUM_ARB 0x200E -#define WGL_SUPPORT_GDI_ARB 0x200F -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_STEREO_ARB 0x2012 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201A -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_ALPHA_SHIFT_ARB 0x201C -#define WGL_ACCUM_BITS_ARB 0x201D -#define WGL_ACCUM_RED_BITS_ARB 0x201E -#define WGL_ACCUM_GREEN_BITS_ARB 0x201F -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_GENERIC_ACCELERATION_ARB 0x2026 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_SWAP_EXCHANGE_ARB 0x2028 -#define WGL_SWAP_COPY_ARB 0x2029 -#define WGL_SWAP_UNDEFINED_ARB 0x202A -#define WGL_TYPE_RGBA_ARB 0x202B -#define WGL_TYPE_COLORINDEX_ARB 0x202C -#endif - -#ifndef WGL_ARB_create_context -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 -#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x0001 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x0002 -// Error codes returned by GetLastError(). -#define ERROR_INVALID_VERSION_ARB 0x2095 -#define ERROR_INVALID_PROFILE_ARB 0x2096 -#endif - -#ifndef GL_VERSION_3_2 -#define GL_CONTEXT_PROFILE_MASK 0x9126 -#define GL_MAJOR_VERSION 0x821B -#define GL_MINOR_VERSION 0x821C -#define GL_NUM_EXTENSIONS 0x821D -#define GL_CONTEXT_FLAGS 0x821E -#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 -#endif - -QT_BEGIN_NAMESPACE - -class QGLCmapPrivate -{ -public: - QGLCmapPrivate() : count(1) { } - void ref() { ++count; } - bool deref() { return !--count; } - uint count; - - enum AllocState{ UnAllocated = 0, Allocated = 0x01, Reserved = 0x02 }; - - int maxSize; - QVector colorArray; - QVector allocArray; - QVector contextArray; - QMap colorMap; -}; - -/***************************************************************************** - QColorMap class - temporarily here, until it is ready for prime time - *****************************************************************************/ - -/**************************************************************************** -** -** Definition of QColorMap class -** -****************************************************************************/ - -class QGLCmapPrivate; - -class /*Q_EXPORT*/ QGLCmap -{ -public: - enum Flags { Reserved = 0x01 }; - - QGLCmap(int maxSize = 256); - QGLCmap(const QGLCmap& map); - ~QGLCmap(); - - QGLCmap& operator=(const QGLCmap& map); - - // isEmpty and/or isNull ? - int size() const; - int maxSize() const; - - void resize(int newSize); - - int find(QRgb color) const; - int findNearest(QRgb color) const; - int allocate(QRgb color, uint flags = 0, quint8 context = 0); - - void setEntry(int idx, QRgb color, uint flags = 0, quint8 context = 0); - - const QRgb* colors() const; - -private: - void detach(); - QGLCmapPrivate* d; -}; - - -QGLCmap::QGLCmap(int maxSize) // add a bool prealloc? -{ - d = new QGLCmapPrivate; - d->maxSize = maxSize; -} - - -QGLCmap::QGLCmap(const QGLCmap& map) -{ - d = map.d; - d->ref(); -} - - -QGLCmap::~QGLCmap() -{ - if (d && d->deref()) - delete d; - d = 0; -} - - -QGLCmap& QGLCmap::operator=(const QGLCmap& map) -{ - map.d->ref(); - if (d->deref()) - delete d; - d = map.d; - return *this; -} - - -int QGLCmap::size() const -{ - return d->colorArray.size(); -} - - -int QGLCmap::maxSize() const -{ - return d->maxSize; -} - - -void QGLCmap::detach() -{ - if (d->count != 1) { - d->deref(); - QGLCmapPrivate* newd = new QGLCmapPrivate; - newd->maxSize = d->maxSize; - newd->colorArray = d->colorArray; - newd->allocArray = d->allocArray; - newd->contextArray = d->contextArray; - newd->colorArray.detach(); - newd->allocArray.detach(); - newd->contextArray.detach(); - newd->colorMap = d->colorMap; - d = newd; - } -} - - -void QGLCmap::resize(int newSize) -{ - if (newSize < 0 || newSize > d->maxSize) { - qWarning("QGLCmap::resize(): size out of range"); - return; - } - int oldSize = size(); - detach(); - //if shrinking; remove the lost elems from colorMap - d->colorArray.resize(newSize); - d->allocArray.resize(newSize); - d->contextArray.resize(newSize); - if (newSize > oldSize) { - memset(d->allocArray.data() + oldSize, 0, newSize - oldSize); - memset(d->contextArray.data() + oldSize, 0, newSize - oldSize); - } -} - - -int QGLCmap::find(QRgb color) const -{ - QMap::ConstIterator it = d->colorMap.find(color); - if (it != d->colorMap.end()) - return *it; - return -1; -} - - -int QGLCmap::findNearest(QRgb color) const -{ - int idx = find(color); - if (idx >= 0) - return idx; - int mapSize = size(); - int mindist = 200000; - int r = qRed(color); - int g = qGreen(color); - int b = qBlue(color); - int rx, gx, bx, dist; - for (int i=0; i < mapSize; i++) { - if (!(d->allocArray[i] & QGLCmapPrivate::Allocated)) - continue; - QRgb ci = d->colorArray[i]; - rx = r - qRed(ci); - gx = g - qGreen(ci); - bx = b - qBlue(ci); - dist = rx*rx + gx*gx + bx*bx; // calculate distance - if (dist < mindist) { // minimal? - mindist = dist; - idx = i; - } - } - return idx; -} - - - - -// Does not always allocate; returns existing c idx if found - -int QGLCmap::allocate(QRgb color, uint flags, quint8 context) -{ - int idx = find(color); - if (idx >= 0) - return idx; - - int mapSize = d->colorArray.size(); - int newIdx = d->allocArray.indexOf(QGLCmapPrivate::UnAllocated); - - if (newIdx < 0) { // Must allocate more room - if (mapSize < d->maxSize) { - newIdx = mapSize; - mapSize++; - resize(mapSize); - } - else { - //# add a bool param that says what to do in case no more room - - // fail (-1) or return nearest? - return -1; - } - } - - d->colorArray[newIdx] = color; - if (flags & QGLCmap::Reserved) { - d->allocArray[newIdx] = QGLCmapPrivate::Reserved; - } - else { - d->allocArray[newIdx] = QGLCmapPrivate::Allocated; - d->colorMap.insert(color, newIdx); - } - d->contextArray[newIdx] = context; - return newIdx; -} - - -void QGLCmap::setEntry(int idx, QRgb color, uint flags, quint8 context) -{ - if (idx < 0 || idx >= d->maxSize) { - qWarning("QGLCmap::set(): Index out of range"); - return; - } - detach(); - int mapSize = size(); - if (idx >= mapSize) { - mapSize = idx + 1; - resize(mapSize); - } - d->colorArray[idx] = color; - if (flags & QGLCmap::Reserved) { - d->allocArray[idx] = QGLCmapPrivate::Reserved; - } - else { - d->allocArray[idx] = QGLCmapPrivate::Allocated; - d->colorMap.insert(color, idx); - } - d->contextArray[idx] = context; -} - - -const QRgb* QGLCmap::colors() const -{ - return d->colorArray.data(); -} - - - -/***************************************************************************** - QGLFormat Win32/WGL-specific code - *****************************************************************************/ - - -void qwglError(const char* method, const char* func) -{ -#ifndef QT_NO_DEBUG - char* lpMsgBuf; - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - 0, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (char*) &lpMsgBuf, 0, 0); - qWarning("%s : %s failed: %s", method, func, lpMsgBuf); - LocalFree(lpMsgBuf); -#else - Q_UNUSED(method); - Q_UNUSED(func); -#endif -} - - - -bool QGLFormat::hasOpenGL() -{ - return true; -} - -static bool opengl32dll = false; - -bool QGLFormat::hasOpenGLOverlays() -{ - // workaround for matrox driver: - // make a cheap call to opengl to force loading of DLL - if (!opengl32dll) { - GLint params; - glGetIntegerv(GL_DEPTH_BITS, ¶ms); - opengl32dll = true; - } - - static bool checkDone = false; - static bool hasOl = false; - - if (!checkDone) { - checkDone = true; - HDC display_dc = GetDC(0); - int pfiMax = DescribePixelFormat(display_dc, 0, 0, NULL); - PIXELFORMATDESCRIPTOR pfd; - for (int pfi = 1; pfi <= pfiMax; pfi++) { - DescribePixelFormat(display_dc, pfi, sizeof(PIXELFORMATDESCRIPTOR), &pfd); - if ((pfd.bReserved & 0x0f) && (pfd.dwFlags & PFD_SUPPORT_OPENGL)) { - // This format has overlays/underlays - LAYERPLANEDESCRIPTOR lpd; - wglDescribeLayerPlane(display_dc, pfi, 1, - sizeof(LAYERPLANEDESCRIPTOR), &lpd); - if (lpd.dwFlags & LPD_SUPPORT_OPENGL) { - hasOl = true; - break; - } - } - } - ReleaseDC(0, display_dc); - } - return hasOl; -} - - -/***************************************************************************** - QGLContext Win32/WGL-specific code - *****************************************************************************/ - -static uchar qgl_rgb_palette_comp(int idx, uint nbits, uint shift) -{ - const uchar map_3_to_8[8] = { - 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377 - }; - const uchar map_2_to_8[4] = { - 0, 0x55, 0xaa, 0xff - }; - const uchar map_1_to_8[2] = { - 0, 255 - }; - - uchar val = (uchar) (idx >> shift); - uchar res = 0; - switch (nbits) { - case 1: - val &= 0x1; - res = map_1_to_8[val]; - break; - case 2: - val &= 0x3; - res = map_2_to_8[val]; - break; - case 3: - val &= 0x7; - res = map_3_to_8[val]; - break; - default: - res = 0; - } - return res; -} - - -static QRgb* qgl_create_rgb_palette(const PIXELFORMATDESCRIPTOR* pfd) -{ - if ((pfd->iPixelType != PFD_TYPE_RGBA) || - !(pfd->dwFlags & PFD_NEED_PALETTE) || - (pfd->cColorBits != 8)) - return 0; - int numEntries = 1 << pfd->cColorBits; - QRgb* pal = new QRgb[numEntries]; - for (int i = 0; i < numEntries; i++) { - int r = qgl_rgb_palette_comp(i, pfd->cRedBits, pfd->cRedShift); - int g = qgl_rgb_palette_comp(i, pfd->cGreenBits, pfd->cGreenShift); - int b = qgl_rgb_palette_comp(i, pfd->cBlueBits, pfd->cBlueShift); - pal[i] = qRgb(r, g, b); - } - - const int syscol_indices[12] = { - 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91 - }; - - const uint syscols[20] = { - 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, - 0x008080, 0xc0c0c0, 0xc0dcc0, 0xa6caf0, 0xfffbf0, 0xa0a0a4, - 0x808080, 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff, - 0x00ffff, 0xffffff - }; // colors #1 - #12 are not present in pal; gets added below - - if ((pfd->cColorBits == 8) && - (pfd->cRedBits == 3) && (pfd->cRedShift == 0) && - (pfd->cGreenBits == 3) && (pfd->cGreenShift == 3) && - (pfd->cBlueBits == 2) && (pfd->cBlueShift == 6)) { - for (int j = 0 ; j < 12 ; j++) - pal[syscol_indices[j]] = QRgb(syscols[j+1]); - } - - return pal; -} - -static QGLFormat pfdToQGLFormat(const PIXELFORMATDESCRIPTOR* pfd) -{ - QGLFormat fmt; - fmt.setDoubleBuffer(pfd->dwFlags & PFD_DOUBLEBUFFER); - fmt.setDepth(pfd->cDepthBits); - if (fmt.depth()) - fmt.setDepthBufferSize(pfd->cDepthBits); - fmt.setRgba(pfd->iPixelType == PFD_TYPE_RGBA); - fmt.setRedBufferSize(pfd->cRedBits); - fmt.setGreenBufferSize(pfd->cGreenBits); - fmt.setBlueBufferSize(pfd->cBlueBits); - fmt.setAlpha(pfd->cAlphaBits); - if (fmt.alpha()) - fmt.setAlphaBufferSize(pfd->cAlphaBits); - fmt.setAccum(pfd->cAccumBits); - if (fmt.accum()) - fmt.setAccumBufferSize(pfd->cAccumRedBits); - fmt.setStencil(pfd->cStencilBits); - if (fmt.stencil()) - fmt.setStencilBufferSize(pfd->cStencilBits); - fmt.setStereo(pfd->dwFlags & PFD_STEREO); - fmt.setDirectRendering((pfd->dwFlags & PFD_GENERIC_ACCELERATED) || - !(pfd->dwFlags & PFD_GENERIC_FORMAT)); - fmt.setOverlay((pfd->bReserved & 0x0f) != 0); - return fmt; -} - -/* - NB! requires a current GL context to work -*/ -QGLFormat pfiToQGLFormat(HDC hdc, int pfi) -{ - QGLFormat fmt; - QVarLengthArray iAttributes(40); - QVarLengthArray iValues(40); - int i = 0; - bool has_sample_buffers = QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers; - - iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; // 0 - iAttributes[i++] = WGL_DEPTH_BITS_ARB; // 1 - iAttributes[i++] = WGL_PIXEL_TYPE_ARB; // 2 - iAttributes[i++] = WGL_RED_BITS_ARB; // 3 - iAttributes[i++] = WGL_GREEN_BITS_ARB; // 4 - iAttributes[i++] = WGL_BLUE_BITS_ARB; // 5 - iAttributes[i++] = WGL_ALPHA_BITS_ARB; // 6 - iAttributes[i++] = WGL_ACCUM_BITS_ARB; // 7 - iAttributes[i++] = WGL_STENCIL_BITS_ARB; // 8 - iAttributes[i++] = WGL_STEREO_ARB; // 9 - iAttributes[i++] = WGL_ACCELERATION_ARB; // 10 - iAttributes[i++] = WGL_NUMBER_OVERLAYS_ARB; // 11 - if (has_sample_buffers) { - iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; // 12 - iAttributes[i++] = WGL_SAMPLES_ARB; // 13 - } - PFNWGLGETPIXELFORMATATTRIBIVARB wglGetPixelFormatAttribivARB = - (PFNWGLGETPIXELFORMATATTRIBIVARB) wglGetProcAddress("wglGetPixelFormatAttribivARB"); - - if (wglGetPixelFormatAttribivARB - && wglGetPixelFormatAttribivARB(hdc, pfi, 0, i, - iAttributes.constData(), - iValues.data())) - { - fmt.setDoubleBuffer(iValues[0]); - fmt.setDepth(iValues[1]); - if (fmt.depth()) - fmt.setDepthBufferSize(iValues[1]); - fmt.setRgba(iValues[2] == WGL_TYPE_RGBA_ARB); - fmt.setRedBufferSize(iValues[3]); - fmt.setGreenBufferSize(iValues[4]); - fmt.setBlueBufferSize(iValues[5]); - fmt.setAlpha(iValues[6]); - if (fmt.alpha()) - fmt.setAlphaBufferSize(iValues[6]); - fmt.setAccum(iValues[7]); - if (fmt.accum()) - fmt.setAccumBufferSize(iValues[7]); - fmt.setStencil(iValues[8]); - if (fmt.stencil()) - fmt.setStencilBufferSize(iValues[8]); - fmt.setStereo(iValues[9]); - if (iValues[10] == WGL_FULL_ACCELERATION_ARB) - fmt.setDirectRendering(true); - else - fmt.setDirectRendering(false); - fmt.setOverlay(iValues[11]); - if (has_sample_buffers) { - fmt.setSampleBuffers(iValues[12]); - if (fmt.sampleBuffers()) - fmt.setSamples(iValues[13]); - } - } -#if 0 - qDebug() << "values for pfi:" << pfi; - qDebug() << "doublebuffer 0:" << fmt.doubleBuffer(); - qDebug() << "depthbuffer 1:" << fmt.depthBufferSize(); - qDebug() << "rgba 2:" << fmt.rgba(); - qDebug() << "red size 3:" << fmt.redBufferSize(); - qDebug() << "green size 4:" << fmt.greenBufferSize(); - qDebug() << "blue size 5:" << fmt.blueBufferSize(); - qDebug() << "alpha size 6:" << fmt.alphaBufferSize(); - qDebug() << "accum size 7:" << fmt.accumBufferSize(); - qDebug() << "stencil size 8:" << fmt.stencilBufferSize(); - qDebug() << "stereo 9:" << fmt.stereo(); - qDebug() << "direct 10:" << fmt.directRendering(); - qDebug() << "has overlays 11:" << fmt.hasOverlay(); - qDebug() << "sample buff 12:" << fmt.sampleBuffers(); - qDebug() << "num samples 13:" << fmt.samples(); -#endif - return fmt; -} - - -/* - QGLTemporaryContext implementation -*/ - -Q_GUI_EXPORT const QString qt_getRegisteredWndClass(); - -class QGLTemporaryContextPrivate -{ -public: - HDC dmy_pdc; - HGLRC dmy_rc; - HDC old_dc; - HGLRC old_context; - WId dmy_id; -}; - -QGLTemporaryContext::QGLTemporaryContext(bool directRendering, QWidget *parent) - : d(new QGLTemporaryContextPrivate) -{ - QString windowClassName = qt_getRegisteredWndClass(); - if (parent && !parent->internalWinId()) - parent = parent->nativeParentWidget(); - - d->dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(), - 0, 0, 0, 0, 1, 1, - parent ? parent->winId() : 0, 0, qWinAppInst(), 0); - - d->dmy_pdc = GetDC(d->dmy_id); - PIXELFORMATDESCRIPTOR dmy_pfd; - memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); - dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); - dmy_pfd.nVersion = 1; - dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; - dmy_pfd.iPixelType = PFD_TYPE_RGBA; - if (!directRendering) - dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT; - - int dmy_pf = ChoosePixelFormat(d->dmy_pdc, &dmy_pfd); - SetPixelFormat(d->dmy_pdc, dmy_pf, &dmy_pfd); - d->dmy_rc = wglCreateContext(d->dmy_pdc); - d->old_dc = wglGetCurrentDC(); - d->old_context = wglGetCurrentContext(); - wglMakeCurrent(d->dmy_pdc, d->dmy_rc); -} - -QGLTemporaryContext::~QGLTemporaryContext() -{ - wglMakeCurrent(d->dmy_pdc, 0); - wglDeleteContext(d->dmy_rc); - ReleaseDC(d->dmy_id, d->dmy_pdc); - DestroyWindow(d->dmy_id); - if (d->old_dc && d->old_context) - wglMakeCurrent(d->old_dc, d->old_context); -} - -static bool qgl_create_context(HDC hdc, QGLContextPrivate *d, QGLContextPrivate *shareContext) -{ - d->rc = 0; - - typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARB)(HDC, HGLRC, const int *); - PFNWGLCREATECONTEXTATTRIBSARB wglCreateContextAttribsARB = - (PFNWGLCREATECONTEXTATTRIBSARB) wglGetProcAddress("wglCreateContextAttribsARB"); - if (wglCreateContextAttribsARB) { - int attributes[11]; - int attribIndex = 0; - const int major = d->reqFormat.majorVersion(); - const int minor = d->reqFormat.minorVersion(); - attributes[attribIndex++] = WGL_CONTEXT_MAJOR_VERSION_ARB; - attributes[attribIndex++] = major; - attributes[attribIndex++] = WGL_CONTEXT_MINOR_VERSION_ARB; - attributes[attribIndex++] = minor; - - if (major >= 3 && !d->reqFormat.testOption(QGL::DeprecatedFunctions)) { - attributes[attribIndex++] = WGL_CONTEXT_FLAGS_ARB; - attributes[attribIndex++] = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; - } - - if ((major == 3 && minor >= 2) || major > 3) { - switch (d->reqFormat.profile()) { - case QGLFormat::NoProfile: - break; - case QGLFormat::CoreProfile: - attributes[attribIndex++] = WGL_CONTEXT_PROFILE_MASK_ARB; - attributes[attribIndex++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; - break; - case QGLFormat::CompatibilityProfile: - attributes[attribIndex++] = WGL_CONTEXT_PROFILE_MASK_ARB; - attributes[attribIndex++] = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - break; - default: - qWarning("QGLContext::chooseContext(): Context profile not supported."); - return false; - } - } - - if (d->reqFormat.plane() != 0) { - attributes[attribIndex++] = WGL_CONTEXT_LAYER_PLANE_ARB; - attributes[attribIndex++] = d->reqFormat.plane(); - } - - attributes[attribIndex++] = 0; // Terminate list. - d->rc = wglCreateContextAttribsARB(hdc, shareContext && shareContext->valid - ? shareContext->rc : 0, attributes); - if (d->rc) { - if (shareContext) - shareContext->sharing = d->sharing = true; - return true; - } - } - - d->rc = wglCreateLayerContext(hdc, d->reqFormat.plane()); - if (d->rc && shareContext && shareContext->valid) - shareContext->sharing = d->sharing = wglShareLists(shareContext->rc, d->rc); - return d->rc != 0; -} - -void QGLContextPrivate::updateFormatVersion() -{ - const GLubyte *s = glGetString(GL_VERSION); - - if (!(s && s[0] >= '0' && s[0] <= '9' && s[1] == '.' && s[2] >= '0' && s[2] <= '9')) { - if (!s) - qWarning("QGLContext::chooseContext(): OpenGL version string is null."); - else - qWarning("QGLContext::chooseContext(): Unexpected OpenGL version string format."); - glFormat.setVersion(0, 0); - glFormat.setProfile(QGLFormat::NoProfile); - glFormat.setOption(QGL::DeprecatedFunctions); - return; - } - - int major = s[0] - '0'; - int minor = s[2] - '0'; - glFormat.setVersion(major, minor); - - if (major < 3) { - glFormat.setProfile(QGLFormat::NoProfile); - glFormat.setOption(QGL::DeprecatedFunctions); - } else { - GLint value = 0; - if (major > 3 || minor >= 2) - glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value); - - switch (value) { - case WGL_CONTEXT_CORE_PROFILE_BIT_ARB: - glFormat.setProfile(QGLFormat::CoreProfile); - break; - case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: - glFormat.setProfile(QGLFormat::CompatibilityProfile); - break; - default: - glFormat.setProfile(QGLFormat::NoProfile); - break; - } - - glGetIntegerv(GL_CONTEXT_FLAGS, &value); - if (value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) - glFormat.setOption(QGL::NoDeprecatedFunctions); - else - glFormat.setOption(QGL::DeprecatedFunctions); - } -} - -bool QGLContext::chooseContext(const QGLContext* shareContext) -{ - QGLContextPrivate *share = shareContext ? const_cast(shareContext)->d_func() : 0; - - Q_D(QGLContext); - // workaround for matrox driver: - // make a cheap call to opengl to force loading of DLL - if (!opengl32dll) { - GLint params; - glGetIntegerv(GL_DEPTH_BITS, ¶ms); - opengl32dll = true; - } - - bool result = true; - HDC myDc; - QWidget *widget = 0; - - if (deviceIsPixmap()) { - if (d->glFormat.plane()) - return false; // Pixmaps can't have overlay - d->win = 0; - HDC display_dc = GetDC(0); - myDc = d->hbitmap_hdc = CreateCompatibleDC(display_dc); - QPixmap *px = static_cast(d->paintDevice); - - BITMAPINFO bmi; - memset(&bmi, 0, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = px->width(); - bmi.bmiHeader.biHeight = px->height(); - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - d->hbitmap = CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, 0, 0, 0); - SelectObject(myDc, d->hbitmap); - ReleaseDC(0, display_dc); - } else { - widget = static_cast(d->paintDevice); - d->win = widget->winId(); - myDc = GetDC(d->win); - } - - // NB! the QGLTemporaryContext object is needed for the - // wglGetProcAddress() calls to succeed and are absolutely - // necessary - don't remove! - QGLTemporaryContext tmp_ctx(d->glFormat.directRendering(), widget); - - if (!myDc) { - qWarning("QGLContext::chooseContext(): Paint device cannot be null"); - result = false; - goto end; - } - - if (d->glFormat.plane()) { - d->pixelFormatId = ((QGLWidget*)d->paintDevice)->context()->d_func()->pixelFormatId; - if (!d->pixelFormatId) { // I.e. the glwidget is invalid - qWarning("QGLContext::chooseContext(): Cannot create overlay context for invalid widget"); - result = false; - goto end; - } - - if (!qgl_create_context(myDc, d, share)) { - qwglError("QGLContext::chooseContext()", "CreateLayerContext"); - result = false; - goto end; - } - - LAYERPLANEDESCRIPTOR lpfd; - wglDescribeLayerPlane(myDc, d->pixelFormatId, d->glFormat.plane(), sizeof(LAYERPLANEDESCRIPTOR), &lpfd); - d->glFormat.setDoubleBuffer(lpfd.dwFlags & LPD_DOUBLEBUFFER); - d->glFormat.setDepth(lpfd.cDepthBits); - d->glFormat.setRgba(lpfd.iPixelType == PFD_TYPE_RGBA); - if (d->glFormat.rgba()) { - if (d->glFormat.redBufferSize() != -1) - d->glFormat.setRedBufferSize(lpfd.cRedBits); - if (d->glFormat.greenBufferSize() != -1) - d->glFormat.setGreenBufferSize(lpfd.cGreenBits); - if (d->glFormat.blueBufferSize() != -1) - d->glFormat.setBlueBufferSize(lpfd.cBlueBits); - } - d->glFormat.setAlpha(lpfd.cAlphaBits); - d->glFormat.setAccum(lpfd.cAccumBits); - d->glFormat.setStencil(lpfd.cStencilBits); - d->glFormat.setStereo(lpfd.dwFlags & LPD_STEREO); - d->glFormat.setDirectRendering(false); - if (d->glFormat.depth()) - d->glFormat.setDepthBufferSize(lpfd.cDepthBits); - if (d->glFormat.alpha()) - d->glFormat.setAlphaBufferSize(lpfd.cAlphaBits); - if (d->glFormat.accum()) - d->glFormat.setAccumBufferSize(lpfd.cAccumRedBits); - if (d->glFormat.stencil()) - d->glFormat.setStencilBufferSize(lpfd.cStencilBits); - - if (d->glFormat.rgba()) { - if (lpfd.dwFlags & LPD_TRANSPARENT) - d->transpColor = QColor(lpfd.crTransparent & 0xff, - (lpfd.crTransparent >> 8) & 0xff, - (lpfd.crTransparent >> 16) & 0xff); - else - d->transpColor = QColor(0, 0, 0); - } - else { - if (lpfd.dwFlags & LPD_TRANSPARENT) - d->transpColor = QColor(qRgb(1, 2, 3));//, lpfd.crTransparent); - else - d->transpColor = QColor(qRgb(1, 2, 3));//, 0); - - d->cmap = new QGLCmap(1 << lpfd.cColorBits); - d->cmap->setEntry(lpfd.crTransparent, qRgb(1, 2, 3));//, QGLCmap::Reserved); - } - } else { - PIXELFORMATDESCRIPTOR pfd; - PIXELFORMATDESCRIPTOR realPfd; - d->pixelFormatId = choosePixelFormat(&pfd, myDc); - if (d->pixelFormatId == 0) { - qwglError("QGLContext::chooseContext()", "ChoosePixelFormat"); - result = false; - goto end; - } - - bool overlayRequested = d->glFormat.hasOverlay(); - DescribePixelFormat(myDc, d->pixelFormatId, sizeof(PIXELFORMATDESCRIPTOR), &realPfd); - - if (!deviceIsPixmap() && wglGetProcAddress("wglGetPixelFormatAttribivARB")) - d->glFormat = pfiToQGLFormat(myDc, d->pixelFormatId); - else - d->glFormat = pfdToQGLFormat(&realPfd); - - d->glFormat.setOverlay(d->glFormat.hasOverlay() && overlayRequested); - - if (deviceIsPixmap() && !(realPfd.dwFlags & PFD_DRAW_TO_BITMAP)) { - qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context."); - result = false; - goto end; - } - - if (deviceIsPixmap() && - (((QPixmap*)d->paintDevice)->depth() != realPfd.cColorBits)) { - qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context of suitable depth."); - result = false; - goto end; - } - - if (!SetPixelFormat(myDc, d->pixelFormatId, &realPfd)) { - qwglError("QGLContext::chooseContext()", "SetPixelFormat"); - result = false; - goto end; - } - - if (!qgl_create_context(myDc, d, share)) { - qwglError("QGLContext::chooseContext()", "wglCreateContext"); - result = false; - goto end; - } - - if(!deviceIsPixmap()) { - QRgb* pal = qgl_create_rgb_palette(&realPfd); - if (pal) { - QGLColormap cmap; - cmap.setEntries(256, pal); - ((QGLWidget*)d->paintDevice)->setColormap(cmap); - delete[] pal; - } - } - } - -end: - // vblanking - wglMakeCurrent(myDc, d->rc); - if (d->rc) - d->updateFormatVersion(); - - typedef BOOL (APIENTRYP PFNWGLSWAPINTERVALEXT) (int interval); - typedef int (APIENTRYP PFNWGLGETSWAPINTERVALEXT) (void); - PFNWGLSWAPINTERVALEXT wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXT) wglGetProcAddress("wglSwapIntervalEXT"); - PFNWGLGETSWAPINTERVALEXT wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXT) wglGetProcAddress("wglGetSwapIntervalEXT"); - if (wglSwapIntervalEXT && wglGetSwapIntervalEXT) { - if (d->reqFormat.swapInterval() != -1) - wglSwapIntervalEXT(d->reqFormat.swapInterval()); - d->glFormat.setSwapInterval(wglGetSwapIntervalEXT()); - } - - if (d->win) - ReleaseDC(d->win, myDc); - return result; -} - - - -static bool qLogEq(bool a, bool b) -{ - return (((!a) && (!b)) || (a && b)); -} - -/* - See qgl.cpp for qdoc comment. - */ -int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc) -{ - Q_D(QGLContext); - // workaround for matrox driver: - // make a cheap call to opengl to force loading of DLL - if (!opengl32dll) { - GLint params; - glGetIntegerv(GL_DEPTH_BITS, ¶ms); - opengl32dll = true; - } - - PFNWGLCHOOSEPIXELFORMATARB wglChoosePixelFormatARB = - (PFNWGLCHOOSEPIXELFORMATARB) wglGetProcAddress("wglChoosePixelFormatARB"); - int chosenPfi = 0; - if (!deviceIsPixmap() && wglChoosePixelFormatARB) { - bool valid; - int pixelFormat = 0; - uint numFormats = 0; - QVarLengthArray iAttributes(40); - int i = 0; - iAttributes[i++] = WGL_ACCELERATION_ARB; - if (d->glFormat.directRendering()) - iAttributes[i++] = WGL_FULL_ACCELERATION_ARB; - else - iAttributes[i++] = WGL_NO_ACCELERATION_ARB; - iAttributes[i++] = WGL_SUPPORT_OPENGL_ARB; - iAttributes[i++] = TRUE; - iAttributes[i++] = WGL_DRAW_TO_WINDOW_ARB; - iAttributes[i++] = TRUE; - iAttributes[i++] = WGL_COLOR_BITS_ARB; - iAttributes[i++] = 24; - iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; - iAttributes[i++] = d->glFormat.doubleBuffer(); - if (d->glFormat.stereo()) { - iAttributes[i++] = WGL_STEREO_ARB; - iAttributes[i++] = TRUE; - } - if (d->glFormat.depth()) { - iAttributes[i++] = WGL_DEPTH_BITS_ARB; - iAttributes[i++] = d->glFormat.depthBufferSize() == -1 ? 24 : d->glFormat.depthBufferSize(); - } - iAttributes[i++] = WGL_PIXEL_TYPE_ARB; - if (d->glFormat.rgba()) { - iAttributes[i++] = WGL_TYPE_RGBA_ARB; - if (d->glFormat.redBufferSize() != -1) { - iAttributes[i++] = WGL_RED_BITS_ARB; - iAttributes[i++] = d->glFormat.redBufferSize(); - } - if (d->glFormat.greenBufferSize() != -1) { - iAttributes[i++] = WGL_GREEN_BITS_ARB; - iAttributes[i++] = d->glFormat.greenBufferSize(); - } - if (d->glFormat.blueBufferSize() != -1) { - iAttributes[i++] = WGL_BLUE_BITS_ARB; - iAttributes[i++] = d->glFormat.blueBufferSize(); - } - } else { - iAttributes[i++] = WGL_TYPE_COLORINDEX_ARB; - } - if (d->glFormat.alpha()) { - iAttributes[i++] = WGL_ALPHA_BITS_ARB; - iAttributes[i++] = d->glFormat.alphaBufferSize() == -1 ? 8 : d->glFormat.alphaBufferSize(); - } - if (d->glFormat.accum()) { - iAttributes[i++] = WGL_ACCUM_BITS_ARB; - iAttributes[i++] = d->glFormat.accumBufferSize() == -1 ? 16 : d->glFormat.accumBufferSize(); - } - if (d->glFormat.stencil()) { - iAttributes[i++] = WGL_STENCIL_BITS_ARB; - iAttributes[i++] = d->glFormat.stencilBufferSize() == -1 ? 8 : d->glFormat.stencilBufferSize(); - } - if (d->glFormat.hasOverlay()) { - iAttributes[i++] = WGL_NUMBER_OVERLAYS_ARB; - iAttributes[i++] = 1; - } - int si = 0; - bool trySampleBuffers = QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers; - if (trySampleBuffers && d->glFormat.sampleBuffers()) { - iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; - iAttributes[i++] = TRUE; - iAttributes[i++] = WGL_SAMPLES_ARB; - si = i; - iAttributes[i++] = d->glFormat.samples() == -1 ? 4 : d->glFormat.samples(); - } - iAttributes[i] = 0; - - do { - valid = wglChoosePixelFormatARB(pdc, iAttributes.constData(), 0, 1, - &pixelFormat, &numFormats); - if (trySampleBuffers && (!valid || numFormats < 1) && d->glFormat.sampleBuffers()) - iAttributes[si] /= 2; // try different no. samples - we aim for the best one - else - break; - } while ((!valid || numFormats < 1) && iAttributes[si] > 1); - chosenPfi = pixelFormat; - } - - if (!chosenPfi) { // fallback if wglChoosePixelFormatARB() failed - int pmDepth = deviceIsPixmap() ? ((QPixmap*)d->paintDevice)->depth() : 0; - PIXELFORMATDESCRIPTOR* p = (PIXELFORMATDESCRIPTOR*)dummyPfd; - memset(p, 0, sizeof(PIXELFORMATDESCRIPTOR)); - p->nSize = sizeof(PIXELFORMATDESCRIPTOR); - p->nVersion = 1; - p->dwFlags = PFD_SUPPORT_OPENGL; - if (deviceIsPixmap()) - p->dwFlags |= PFD_DRAW_TO_BITMAP; - else - p->dwFlags |= PFD_DRAW_TO_WINDOW; - if (!d->glFormat.directRendering()) - p->dwFlags |= PFD_GENERIC_FORMAT; - if (d->glFormat.doubleBuffer() && !deviceIsPixmap()) - p->dwFlags |= PFD_DOUBLEBUFFER; - if (d->glFormat.stereo()) - p->dwFlags |= PFD_STEREO; - if (d->glFormat.depth()) - p->cDepthBits = d->glFormat.depthBufferSize() == -1 ? 32 : d->glFormat.depthBufferSize(); - else - p->dwFlags |= PFD_DEPTH_DONTCARE; - if (d->glFormat.rgba()) { - p->iPixelType = PFD_TYPE_RGBA; - if (d->glFormat.redBufferSize() != -1) - p->cRedBits = d->glFormat.redBufferSize(); - if (d->glFormat.greenBufferSize() != -1) - p->cGreenBits = d->glFormat.greenBufferSize(); - if (d->glFormat.blueBufferSize() != -1) - p->cBlueBits = d->glFormat.blueBufferSize(); - if (deviceIsPixmap()) - p->cColorBits = pmDepth; - else - p->cColorBits = 32; - } else { - p->iPixelType = PFD_TYPE_COLORINDEX; - p->cColorBits = 8; - } - if (d->glFormat.alpha()) - p->cAlphaBits = d->glFormat.alphaBufferSize() == -1 ? 8 : d->glFormat.alphaBufferSize(); - if (d->glFormat.accum()) { - p->cAccumRedBits = p->cAccumGreenBits = p->cAccumBlueBits = p->cAccumAlphaBits = - d->glFormat.accumBufferSize() == -1 ? 16 : d->glFormat.accumBufferSize(); - } - if (d->glFormat.stencil()) - p->cStencilBits = d->glFormat.stencilBufferSize() == -1 ? 8 : d->glFormat.stencilBufferSize(); - p->iLayerType = PFD_MAIN_PLANE; - chosenPfi = ChoosePixelFormat(pdc, p); - - if (!chosenPfi) - qErrnoWarning("QGLContext: ChoosePixelFormat failed"); - - // Since the GDI function ChoosePixelFormat() does not handle - // overlay and direct-rendering requests, we must roll our own here - - bool doSearch = chosenPfi <= 0; - PIXELFORMATDESCRIPTOR pfd; - QGLFormat fmt; - if (!doSearch) { - DescribePixelFormat(pdc, chosenPfi, sizeof(PIXELFORMATDESCRIPTOR), - &pfd); - fmt = pfdToQGLFormat(&pfd); - if (d->glFormat.hasOverlay() && !fmt.hasOverlay()) - doSearch = true; - else if (!qLogEq(d->glFormat.directRendering(), fmt.directRendering())) - doSearch = true; - else if (deviceIsPixmap() && (!(pfd.dwFlags & PFD_DRAW_TO_BITMAP) || - pfd.cColorBits != pmDepth)) - doSearch = true; - else if (!deviceIsPixmap() && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW)) - doSearch = true; - else if (!qLogEq(d->glFormat.rgba(), fmt.rgba())) - doSearch = true; - } - - if (doSearch) { - int pfiMax = DescribePixelFormat(pdc, 0, 0, NULL); - int bestScore = -1; - int bestPfi = -1; - for (int pfi = 1; pfi <= pfiMax; pfi++) { - DescribePixelFormat(pdc, pfi, sizeof(PIXELFORMATDESCRIPTOR), &pfd); - if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL)) - continue; - if (deviceIsPixmap() && (!(pfd.dwFlags & PFD_DRAW_TO_BITMAP) || - pfd.cColorBits != pmDepth)) - continue; - if (!deviceIsPixmap() && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW)) - continue; - - fmt = pfdToQGLFormat(&pfd); - if (d->glFormat.hasOverlay() && !fmt.hasOverlay()) - continue; - - int score = pfd.cColorBits; - if (qLogEq(d->glFormat.depth(), fmt.depth())) - score += pfd.cDepthBits; - if (qLogEq(d->glFormat.alpha(), fmt.alpha())) - score += pfd.cAlphaBits; - if (qLogEq(d->glFormat.accum(), fmt.accum())) - score += pfd.cAccumBits; - if (qLogEq(d->glFormat.stencil(), fmt.stencil())) - score += pfd.cStencilBits; - if (qLogEq(d->glFormat.doubleBuffer(), fmt.doubleBuffer())) - score += 1000; - if (qLogEq(d->glFormat.stereo(), fmt.stereo())) - score += 2000; - if (qLogEq(d->glFormat.directRendering(), fmt.directRendering())) - score += 4000; - if (qLogEq(d->glFormat.rgba(), fmt.rgba())) - score += 8000; - if (score > bestScore) { - bestScore = score; - bestPfi = pfi; - } - } - - if (bestPfi > 0) - chosenPfi = bestPfi; - } - } - return chosenPfi; -} - - - -void QGLContext::reset() -{ - Q_D(QGLContext); - // workaround for matrox driver: - // make a cheap call to opengl to force loading of DLL - if (!opengl32dll) { - GLint params; - glGetIntegerv(GL_DEPTH_BITS, ¶ms); - opengl32dll = true; - } - - if (!d->valid) - return; - d->cleanup(); - doneCurrent(); - if (d->rc) - wglDeleteContext(d->rc); - d->rc = 0; - if (d->win && d->dc) - ReleaseDC(d->win, d->dc); - if (deviceIsPixmap()) { - DeleteDC(d->hbitmap_hdc); - DeleteObject(d->hbitmap); - d->hbitmap_hdc = 0; - d->hbitmap = 0; - } - d->dc = 0; - d->win = 0; - d->threadId = 0; - d->pixelFormatId = 0; - d->sharing = false; - d->valid = false; - d->transpColor = QColor(); - delete d->cmap; - d->cmap = 0; - d->initDone = false; - QGLContextGroup::removeShare(this); -} - -// -// NOTE: In a multi-threaded environment, each thread has a current -// context. If we want to make this code thread-safe, we probably -// have to use TLS (thread local storage) for keeping current contexts. -// - -void QGLContext::makeCurrent() -{ - Q_D(QGLContext); - if (d->rc == wglGetCurrentContext() || !d->valid) // already current - return; - - if (d->win && (!d->dc || d->threadId != QThread::currentThreadId())) { - d->dc = GetDC(d->win); - d->threadId = QThread::currentThreadId(); - if (!d->dc) { - qwglError("QGLContext::makeCurrent()", "GetDC()"); - return; - } - } else if (deviceIsPixmap()) { - d->dc = d->hbitmap_hdc; - } - - HPALETTE hpal = QColormap::hPal(); - if (hpal) { - SelectPalette(d->dc, hpal, FALSE); - RealizePalette(d->dc); - } - if (d->glFormat.plane()) { - wglRealizeLayerPalette(d->dc, d->glFormat.plane(), TRUE); - } - - if (wglMakeCurrent(d->dc, d->rc)) { - QGLContextPrivate::setCurrentContext(this); - } else { - qwglError("QGLContext::makeCurrent()", "wglMakeCurrent"); - } -} - - -void QGLContext::doneCurrent() -{ - Q_D(QGLContext); - wglMakeCurrent(0, 0); - QGLContextPrivate::setCurrentContext(0); - if (deviceIsPixmap() && d->hbitmap) { - QPixmap *pm = static_cast(d->paintDevice); - *pm = QPixmap::fromWinHBITMAP(d->hbitmap); - } - if (d->win && d->dc) { - ReleaseDC(d->win, d->dc); - d->dc = 0; - d->threadId = 0; - } -} - -void QGLContext::swapBuffers() const -{ - Q_D(const QGLContext); - if (d->dc && d->glFormat.doubleBuffer() && !deviceIsPixmap()) { - if (d->glFormat.plane()) - wglSwapLayerBuffers(d->dc, WGL_SWAP_OVERLAY1); - else { - if (d->glFormat.hasOverlay()) - wglSwapLayerBuffers(d->dc, WGL_SWAP_MAIN_PLANE); - else - SwapBuffers(d->dc); - } - } -} - - -QColor QGLContext::overlayTransparentColor() const -{ - return d_func()->transpColor; -} - - -uint QGLContext::colorIndex(const QColor& c) const -{ - Q_D(const QGLContext); - if (!isValid()) - return 0; - if (d->cmap) { - int idx = d->cmap->find(c.rgb()); - if (idx >= 0) - return idx; - if (d->dc && d->glFormat.plane()) { - idx = d->cmap->allocate(c.rgb()); - if (idx >= 0) { - COLORREF r = RGB(qRed(c.rgb()),qGreen(c.rgb()),qBlue(c.rgb())); - wglSetLayerPaletteEntries(d->dc, d->glFormat.plane(), idx, 1, &r); - wglRealizeLayerPalette(d->dc, d->glFormat.plane(), TRUE); - return idx; - } - } - return d->cmap->findNearest(c.rgb()); - } - QColormap cmap = QColormap::instance(); - return cmap.pixel(c) & 0x00ffffff; // Assumes standard palette -} - -void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase) -{ - if (!isValid()) - return; - - HDC display_dc = GetDC(0); - HDC tmp_dc = CreateCompatibleDC(display_dc); - HGDIOBJ old_font = SelectObject(tmp_dc, fnt.handle()); - - ReleaseDC(0, display_dc); - - if (!wglUseFontBitmaps(tmp_dc, 0, 256, listBase)) - qWarning("QGLContext::generateFontDisplayLists: Could not generate display lists for font '%s'", fnt.family().toLatin1().data()); - - SelectObject(tmp_dc, old_font); - DeleteDC(tmp_dc); -} - -void *QGLContext::getProcAddress(const QString &proc) const -{ - return (void *)wglGetProcAddress(proc.toLatin1()); -} - -/***************************************************************************** - QGLWidget Win32/WGL-specific code - *****************************************************************************/ - -void QGLWidgetPrivate::init(QGLContext *ctx, const QGLWidget* shareWidget) -{ - Q_Q(QGLWidget); - olcx = 0; - initContext(ctx, shareWidget); - - if (q->isValid() && q->context()->format().hasOverlay()) { - olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), q); - if (!olcx->create(shareWidget ? shareWidget->overlayContext() : 0)) { - delete olcx; - olcx = 0; - glcx->d_func()->glFormat.setOverlay(false); - } - } else { - olcx = 0; - } -} - -/*\internal - Store color values in the given colormap. -*/ -static void qStoreColors(HPALETTE cmap, const QGLColormap & cols) -{ - QRgb color; - PALETTEENTRY pe; - - for (int i = 0; i < cols.size(); i++) { - color = cols.entryRgb(i); - pe.peRed = qRed(color); - pe.peGreen = qGreen(color); - pe.peBlue = qBlue(color); - pe.peFlags = 0; - - SetPaletteEntries(cmap, i, 1, &pe); - } -} - -void QGLWidgetPrivate::updateColormap() -{ - Q_Q(QGLWidget); - if (!cmap.handle()) - return; - HDC hdc = GetDC(q->winId()); - SelectPalette(hdc, (HPALETTE) cmap.handle(), TRUE); - qStoreColors((HPALETTE) cmap.handle(), cmap); - RealizePalette(hdc); - ReleaseDC(q->winId(), hdc); -} - -void QGLWidget::setMouseTracking(bool enable) -{ - QWidget::setMouseTracking(enable); -} - - -void QGLWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QGLWidget); - if (!isValid()) - return; - makeCurrent(); - if (!d->glcx->initialized()) - glInit(); - resizeGL(width(), height()); - if (d->olcx) { - makeOverlayCurrent(); - resizeOverlayGL(width(), height()); - } -} - - -const QGLContext* QGLWidget::overlayContext() const -{ - return d_func()->olcx; -} - - -void QGLWidget::makeOverlayCurrent() -{ - Q_D(QGLWidget); - if (d->olcx) { - d->olcx->makeCurrent(); - if (!d->olcx->initialized()) { - initializeOverlayGL(); - d->olcx->setInitialized(true); - } - } -} - - -void QGLWidget::updateOverlayGL() -{ - Q_D(QGLWidget); - if (d->olcx) { - makeOverlayCurrent(); - paintOverlayGL(); - if (d->olcx->format().doubleBuffer()) { - if (d->autoSwap) - d->olcx->swapBuffers(); - } - else { - glFlush(); - } - } -} - - -void QGLWidget::setContext(QGLContext *context, - const QGLContext* shareContext, - bool deleteOldContext) -{ - Q_D(QGLWidget); - if (context == 0) { - qWarning("QGLWidget::setContext: Cannot set null context"); - return; - } - if (!context->deviceIsPixmap() && context->device() != this) { - qWarning("QGLWidget::setContext: Context must refer to this widget"); - return; - } - - if (d->glcx) - d->glcx->doneCurrent(); - QGLContext* oldcx = d->glcx; - d->glcx = context; - - bool doShow = false; - if (oldcx && oldcx->d_func()->win == winId() && !d->glcx->deviceIsPixmap()) { - // We already have a context and must therefore create a new - // window since Windows does not permit setting a new OpenGL - // context for a window that already has one set. - doShow = isVisible(); - QWidget *pW = static_cast(parent()); - QPoint pos = geometry().topLeft(); - setParent(pW, windowFlags()); - move(pos); - } - - if (!d->glcx->isValid()) { - bool wasSharing = shareContext || (oldcx && oldcx->isSharing()); - d->glcx->create(shareContext ? shareContext : oldcx); - // the above is a trick to keep disp lists etc when a - // QGLWidget has been reparented, so remove the sharing - // flag if we don't actually have a sharing context. - if (!wasSharing) - d->glcx->d_ptr->sharing = false; - } - - if (deleteOldContext) - delete oldcx; - - if (doShow) - show(); -} - - -bool QGLWidgetPrivate::renderCxPm(QPixmap*) -{ - return false; -} - -void QGLWidgetPrivate::cleanupColormaps() -{ - Q_Q(QGLWidget); - if (cmap.handle()) { - HDC hdc = GetDC(q->winId()); - SelectPalette(hdc, (HPALETTE) GetStockObject(DEFAULT_PALETTE), FALSE); - DeleteObject((HPALETTE) cmap.handle()); - ReleaseDC(q->winId(), hdc); - cmap.setHandle(0); - } - return; -} - -const QGLColormap & QGLWidget::colormap() const -{ - return d_func()->cmap; -} - -void QGLWidget::setColormap(const QGLColormap & c) -{ - Q_D(QGLWidget); - d->cmap = c; - - if (d->cmap.handle()) { // already have an allocated cmap - d->updateColormap(); - } else { - LOGPALETTE *lpal = (LOGPALETTE *) malloc(sizeof(LOGPALETTE) - +c.size()*sizeof(PALETTEENTRY)); - lpal->palVersion = 0x300; - lpal->palNumEntries = c.size(); - d->cmap.setHandle(CreatePalette(lpal)); - free(lpal); - d->updateColormap(); - } -} - -QT_END_NAMESPACE diff --git a/src/opengl/qgl_wince.cpp b/src/opengl/qgl_wince.cpp deleted file mode 100644 index d6d8f24bfa..0000000000 --- a/src/opengl/qgl_wince.cpp +++ /dev/null @@ -1,636 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - - -QT_BEGIN_NAMESPACE - - - -class QGLCmapPrivate -{ -public: - QGLCmapPrivate() : count(1) { } - void ref() { ++count; } - bool deref() { return !--count; } - uint count; - - enum AllocState{ UnAllocated = 0, Allocated = 0x01, Reserved = 0x02 }; - - int maxSize; - QVector colorArray; - QVector allocArray; - QVector contextArray; - QMap colorMap; -}; - -/***************************************************************************** - QColorMap class - temporarily here, until it is ready for prime time - *****************************************************************************/ - -/**************************************************************************** -** -** Definition of QColorMap class -** -****************************************************************************/ - -#ifndef QGLCMAP_H -#define QGLCMAP_H - -#include - -/* - QGLTemporaryContext implementation -*/ - -class QGLTemporaryContextPrivate -{ -public: - QGLWidget *widget; -}; - -QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) - : d(new QGLTemporaryContextPrivate) -{ - d->widget = new QGLWidget; - d->widget->makeCurrent(); -} - -QGLTemporaryContext::~QGLTemporaryContext() -{ - delete d->widget; -} - -/***************************************************************************** - QGLFormat Win32/WGL-specific code - *****************************************************************************/ - -static bool opengl32dll = false; - -bool QGLFormat::hasOpenGLOverlays() -{ - return false; // ### -} - - -bool QGLContext::chooseContext(const QGLContext* shareContext) -{ - Q_D(QGLContext); - - // Validate the device. - if (!device()) - return false; - int devType = device()->devType(); - if (devType != QInternal::Pixmap && devType != QInternal::Image && devType != QInternal::Widget) { - qWarning("QGLContext::chooseContext(): Cannot create QGLContext's for paint device type %d", devType); - return false; - } - - // Get the display and initialize it. - d->eglContext = new QEglContext(); - d->ownsEglContext = true; - d->eglContext->setApi(QEgl::OpenGL); - - // Construct the configuration we need for this surface. - QEglProperties configProps; - qt_eglproperties_set_glformat(configProps, d->glFormat); - configProps.setDeviceType(devType); - configProps.setPaintDeviceFormat(device()); - configProps.setRenderableType(QEgl::OpenGL); - - // Search for a matching configuration, reducing the complexity - // each time until we get something that matches. - if (!d->eglContext->chooseConfig(configProps)) { - delete d->eglContext; - d->eglContext = 0; - return false; - } - - // Inform the higher layers about the actual format properties. - qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config()); - - // Create a new context for the configuration. - if (!d->eglContext->createContext - (shareContext ? shareContext->d_func()->eglContext : 0)) { - delete d->eglContext; - d->eglContext = 0; - return false; - } - d->sharing = d->eglContext->isSharing(); - if (d->sharing && shareContext) - const_cast(shareContext)->d_func()->sharing = true; - -#if defined(EGL_VERSION_1_1) - if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget) - eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval()); -#endif - - // Create the EGL surface to draw into. - d->eglSurface = d->eglContext->createSurface(device()); - if (d->eglSurface == EGL_NO_SURFACE) { - delete d->eglContext; - d->eglContext = 0; - return false; - } - - return true; - -} - - - -static bool qLogEq(bool a, bool b) -{ - return (((!a) && (!b)) || (a && b)); -} - -int QGLContext::choosePixelFormat(void* , HDC ) -{ - - return 0; -} - -class QGLCmapPrivate; - -class /*Q_EXPORT*/ QGLCmap -{ -public: - enum Flags { Reserved = 0x01 }; - - QGLCmap(int maxSize = 256); - QGLCmap(const QGLCmap& map); - ~QGLCmap(); - - QGLCmap& operator=(const QGLCmap& map); - - // isEmpty and/or isNull ? - int size() const; - int maxSize() const; - - void resize(int newSize); - - int find(QRgb color) const; - int findNearest(QRgb color) const; - int allocate(QRgb color, uint flags = 0, quint8 context = 0); - - void setEntry(int idx, QRgb color, uint flags = 0, quint8 context = 0); - - const QRgb* colors() const; - -private: - void detach(); - QGLCmapPrivate* d; -}; - -#endif - - -QGLCmap::QGLCmap(int maxSize) // add a bool prealloc? -{ - d = new QGLCmapPrivate; - d->maxSize = maxSize; -} - -QGLCmap::QGLCmap(const QGLCmap& map) -{ - d = map.d; - d->ref(); -} - -QGLCmap::~QGLCmap() -{ - if (d && d->deref()) - delete d; - d = 0; -} - -QGLCmap& QGLCmap::operator=(const QGLCmap& map) -{ - map.d->ref(); - if (d->deref()) - delete d; - d = map.d; - return *this; -} - -int QGLCmap::size() const -{ - return d->colorArray.size(); -} - -int QGLCmap::maxSize() const -{ - return d->maxSize; -} - -void QGLCmap::detach() -{ - if (d->count != 1) { - d->deref(); - QGLCmapPrivate* newd = new QGLCmapPrivate; - newd->maxSize = d->maxSize; - newd->colorArray = d->colorArray; - newd->allocArray = d->allocArray; - newd->contextArray = d->contextArray; - newd->colorArray.detach(); - newd->allocArray.detach(); - newd->contextArray.detach(); - newd->colorMap = d->colorMap; - d = newd; - } -} - - -void QGLCmap::resize(int newSize) -{ - if (newSize < 0 || newSize > d->maxSize) { - qWarning("QGLCmap::resize(): size out of range"); - return; - } - int oldSize = size(); - detach(); - //if shrinking; remove the lost elems from colorMap - d->colorArray.resize(newSize); - d->allocArray.resize(newSize); - d->contextArray.resize(newSize); - if (newSize > oldSize) { - memset(d->allocArray.data() + oldSize, 0, newSize - oldSize); - memset(d->contextArray.data() + oldSize, 0, newSize - oldSize); - } -} - - -int QGLCmap::find(QRgb color) const -{ - QMap::ConstIterator it = d->colorMap.find(color); - if (it != d->colorMap.end()) - return *it; - return -1; -} - - -int QGLCmap::findNearest(QRgb color) const -{ - int idx = find(color); - if (idx >= 0) - return idx; - int mapSize = size(); - int mindist = 200000; - int r = qRed(color); - int g = qGreen(color); - int b = qBlue(color); - int rx, gx, bx, dist; - for (int i=0; i < mapSize; i++) { - if (!(d->allocArray[i] & QGLCmapPrivate::Allocated)) - continue; - QRgb ci = d->colorArray[i]; - rx = r - qRed(ci); - gx = g - qGreen(ci); - bx = b - qBlue(ci); - dist = rx*rx + gx*gx + bx*bx; // calculate distance - if (dist < mindist) { // minimal? - mindist = dist; - idx = i; - } - } - return idx; -} - - -// Does not always allocate; returns existing c idx if found - -int QGLCmap::allocate(QRgb color, uint flags, quint8 context) -{ - int idx = find(color); - if (idx >= 0) - return idx; - - int mapSize = d->colorArray.size(); - int newIdx = d->allocArray.indexOf(QGLCmapPrivate::UnAllocated); - - if (newIdx < 0) { // Must allocate more room - if (mapSize < d->maxSize) { - newIdx = mapSize; - mapSize++; - resize(mapSize); - } - else { - //# add a bool param that says what to do in case no more room - - // fail (-1) or return nearest? - return -1; - } - } - - d->colorArray[newIdx] = color; - if (flags & QGLCmap::Reserved) { - d->allocArray[newIdx] = QGLCmapPrivate::Reserved; - } - else { - d->allocArray[newIdx] = QGLCmapPrivate::Allocated; - d->colorMap.insert(color, newIdx); - } - d->contextArray[newIdx] = context; - return newIdx; -} - - -void QGLCmap::setEntry(int idx, QRgb color, uint flags, quint8 context) -{ - if (idx < 0 || idx >= d->maxSize) { - qWarning("QGLCmap::set(): Index out of range"); - return; - } - detach(); - int mapSize = size(); - if (idx >= mapSize) { - mapSize = idx + 1; - resize(mapSize); - } - d->colorArray[idx] = color; - if (flags & QGLCmap::Reserved) { - d->allocArray[idx] = QGLCmapPrivate::Reserved; - } - else { - d->allocArray[idx] = QGLCmapPrivate::Allocated; - d->colorMap.insert(color, idx); - } - d->contextArray[idx] = context; -} - - -const QRgb* QGLCmap::colors() const -{ - return d->colorArray.data(); -} - - -/***************************************************************************** - QGLWidget Win32/WGL-specific code - *****************************************************************************/ - -void QGLWidgetPrivate::init(QGLContext *ctx, const QGLWidget* shareWidget) -{ - Q_Q(QGLWidget); - olcx = 0; - initContext(ctx, shareWidget); - - if (q->isValid() && q->context()->format().hasOverlay()) { - olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), q); - if (!olcx->create(shareWidget ? shareWidget->overlayContext() : 0)) { - delete olcx; - olcx = 0; - glcx->d_func()->glFormat.setOverlay(false); - } - } else { - olcx = 0; - } -} - -/*\internal - Store color values in the given colormap. -*/ -static void qStoreColors(HPALETTE cmap, const QGLColormap & cols) -{ - QRgb color; - PALETTEENTRY pe; - - for (int i = 0; i < cols.size(); i++) { - color = cols.entryRgb(i); - pe.peRed = qRed(color); - pe.peGreen = qGreen(color); - pe.peBlue = qBlue(color); - pe.peFlags = 0; - - SetPaletteEntries(cmap, i, 1, &pe); - } -} - -void QGLWidgetPrivate::updateColormap() -{ - Q_Q(QGLWidget); - if (!cmap.handle()) - return; - HDC hdc = GetDC(q->winId()); - SelectPalette(hdc, (HPALETTE) cmap.handle(), TRUE); - qStoreColors((HPALETTE) cmap.handle(), cmap); - RealizePalette(hdc); - ReleaseDC(q->winId(), hdc); -} - -bool QGLWidget::event(QEvent *e) -{ - Q_D(QGLWidget); - if (e->type() == QEvent::ParentChange) { - setContext(new QGLContext(d->glcx->requestedFormat(), this)); - // the overlay needs to be recreated as well - delete d->olcx; - if (isValid() && context()->format().hasOverlay()) { - d->olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), this); - if (!d->olcx->create(isSharing() ? d->glcx : 0)) { - delete d->olcx; - d->olcx = 0; - d->glcx->d_func()->glFormat.setOverlay(false); - } - } else { - d->olcx = 0; - } - } else if (e->type() == QEvent::Show && !format().rgba()) { - d->updateColormap(); - } - - return QWidget::event(e); -} - - -void QGLWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QGLWidget); - if (!isValid()) - return; - makeCurrent(); - if (!d->glcx->initialized()) - glInit(); - resizeGL(width(), height()); - if (d->olcx) { - makeOverlayCurrent(); - resizeOverlayGL(width(), height()); - } -} - - -const QGLContext* QGLWidget::overlayContext() const -{ - return d_func()->olcx; -} - - -void QGLWidget::makeOverlayCurrent() -{ - Q_D(QGLWidget); - if (d->olcx) { - d->olcx->makeCurrent(); - if (!d->olcx->initialized()) { - initializeOverlayGL(); - d->olcx->setInitialized(true); - } - } -} - - -void QGLWidget::updateOverlayGL() -{ - Q_D(QGLWidget); - if (d->olcx) { - makeOverlayCurrent(); - paintOverlayGL(); - if (d->olcx->format().doubleBuffer()) { - if (d->autoSwap) - d->olcx->swapBuffers(); - } - else { - glFlush(); - } - } -} - -void QGLWidget::setContext(QGLContext *context, - const QGLContext* shareContext, - bool deleteOldContext) -{ - Q_D(QGLWidget); - if (context == 0) { - qWarning("QGLWidget::setContext: Cannot set null context"); - return; - } - if (!context->deviceIsPixmap() && context->device() != this) { - qWarning("QGLWidget::setContext: Context must refer to this widget"); - return; - } - - if (d->glcx) - d->glcx->doneCurrent(); - QGLContext* oldcx = d->glcx; - d->glcx = context; - - bool doShow = false; - if (oldcx && oldcx->d_func()->win == winId() && !d->glcx->deviceIsPixmap()) { - // We already have a context and must therefore create a new - // window since Windows does not permit setting a new OpenGL - // context for a window that already has one set. - doShow = isVisible(); - QWidget *pW = static_cast(parent()); - QPoint pos = geometry().topLeft(); - setParent(pW, windowFlags()); - move(pos); - } - - if (!d->glcx->isValid()) { - d->glcx->create(shareContext ? shareContext : oldcx); - // the above is a trick to keep disp lists etc when a - // QGLWidget has been reparented, so remove the sharing - // flag if we don't actually have a sharing context. - if (!shareContext) - d->glcx->d_ptr->sharing = false; - } - - if (deleteOldContext) - delete oldcx; - - if (doShow) - show(); -} - - -void QGLWidgetPrivate::cleanupColormaps() -{ - Q_Q(QGLWidget); - if (cmap.handle()) { - HDC hdc = GetDC(q->winId()); - SelectPalette(hdc, (HPALETTE) GetStockObject(DEFAULT_PALETTE), FALSE); - DeleteObject((HPALETTE) cmap.handle()); - ReleaseDC(q->winId(), hdc); - cmap.setHandle(0); - } - return; -} - -const QGLColormap & QGLWidget::colormap() const -{ - return d_func()->cmap; -} - -void QGLWidget::setColormap(const QGLColormap & c) -{ - Q_D(QGLWidget); - d->cmap = c; - - if (d->cmap.handle()) { // already have an allocated cmap - d->updateColormap(); - } else { - LOGPALETTE *lpal = (LOGPALETTE *) malloc(sizeof(LOGPALETTE) - +c.size()*sizeof(PALETTEENTRY)); - lpal->palVersion = 0x300; - lpal->palNumEntries = c.size(); - d->cmap.setHandle(CreatePalette(lpal)); - free(lpal); - d->updateColormap(); - } -} - -QT_END_NAMESPACE diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp deleted file mode 100644 index c35488da02..0000000000 --- a/src/opengl/qgl_x11.cpp +++ /dev/null @@ -1,1904 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgl.h" -#include "qgl_p.h" - -#include "qmap.h" -#include "qapplication.h" -#include "qcolormap.h" -#include "qdesktopwidget.h" -#include "qpixmap.h" -#include "qhash.h" -#include "qlibrary.h" -#include "qdebug.h" -#include -#include -#include -#include -#include -#ifdef Q_OS_HPUX -// for GLXPBuffer -#include -#endif - -// We always define GLX_EXT_texture_from_pixmap ourselves because -// we can't trust system headers to do it properly -#define GLX_EXT_texture_from_pixmap 1 - -#define INT8 dummy_INT8 -#define INT32 dummy_INT32 -#include -#undef INT8 -#undef INT32 - -#include -#include -#include -#ifdef Q_OS_VXWORS -# ifdef open -# undef open -# endif -# ifdef getpid -# undef getpid -# endif -#endif // Q_OS_VXWORKS -#include - -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) -#include -#endif - -QT_BEGIN_NAMESPACE - -extern Drawable qt_x11Handle(const QPaintDevice *pd); -extern const QX11Info *qt_x11Info(const QPaintDevice *pd); - -#ifndef GLX_ARB_multisample -#define GLX_SAMPLE_BUFFERS_ARB 100000 -#define GLX_SAMPLES_ARB 100001 -#endif - -#ifndef GLX_TEXTURE_2D_BIT_EXT -#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 -#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 -#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 -#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 -#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 -#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 -#define GLX_Y_INVERTED_EXT 0x20D4 -#define GLX_TEXTURE_FORMAT_EXT 0x20D5 -#define GLX_TEXTURE_TARGET_EXT 0x20D6 -#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 -#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 -#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 -#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA -#define GLX_TEXTURE_2D_EXT 0x20DC -#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD -#define GLX_FRONT_LEFT_EXT 0x20DE -#endif - -#ifndef GLX_ARB_create_context -#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 -#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 -#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define GLX_CONTEXT_FLAGS_ARB 0x2094 -#endif - -#ifndef GLX_ARB_create_context_profile -#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 -#endif - -/* - The qt_gl_choose_cmap function is internal and used by QGLWidget::setContext() - and GLX (not Windows). If the application can't find any sharable - colormaps, it must at least create as few colormaps as possible. The - dictionary solution below ensures only one colormap is created per visual. - Colormaps are also deleted when the application terminates. -*/ - -struct QCMapEntry { - QCMapEntry(); - ~QCMapEntry(); - - Colormap cmap; - bool alloc; - XStandardColormap scmap; -}; - -QCMapEntry::QCMapEntry() -{ - cmap = 0; - alloc = false; - scmap.colormap = 0; -} - -QCMapEntry::~QCMapEntry() -{ - if (alloc) - XFreeColormap(X11->display, cmap); -} -typedef QHash CMapEntryHash; -typedef QHash > GLCMapHash; -static bool mesa_gl = false; -static bool first_time = true; - -static void cleanup_cmaps(); - -struct QGLCMapCleanupHandler { - QGLCMapCleanupHandler() { - cmap_hash = new CMapEntryHash; - qglcmap_hash = new GLCMapHash; - } - ~QGLCMapCleanupHandler() { - delete cmap_hash; - delete qglcmap_hash; - } - CMapEntryHash *cmap_hash; - GLCMapHash *qglcmap_hash; -}; -Q_GLOBAL_STATIC(QGLCMapCleanupHandler, cmap_handler) - -static void cleanup_cmaps() -{ - CMapEntryHash *hash = cmap_handler()->cmap_hash; - QHash::ConstIterator it = hash->constBegin(); - while (it != hash->constEnd()) { - delete it.value(); - ++it; - } - - hash->clear(); - cmap_handler()->qglcmap_hash->clear(); -} - -Colormap qt_gl_choose_cmap(Display *dpy, XVisualInfo *vi) -{ - if (first_time) { - const char *v = glXQueryServerString(dpy, vi->screen, GLX_VERSION); - if (v) - mesa_gl = (strstr(v, "Mesa") != 0); - first_time = false; - } - - CMapEntryHash *hash = cmap_handler()->cmap_hash; - CMapEntryHash::ConstIterator it = hash->constFind((long) vi->visualid + (vi->screen * 256)); - if (it != hash->constEnd()) - return it.value()->cmap; // found colormap for visual - - if (vi->visualid == - XVisualIDFromVisual((Visual *) QX11Info::appVisual(vi->screen))) { - // qDebug("Using x11AppColormap"); - return QX11Info::appColormap(vi->screen); - } - - QCMapEntry *x = new QCMapEntry(); - - XStandardColormap *c; - int n, i; - - // qDebug("Choosing cmap for vID %0x", vi->visualid); - - if (mesa_gl) { // we're using MesaGL - Atom hp_cmaps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", true); - if (hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8) { - if (XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n, - hp_cmaps)) { - i = 0; - while (i < n && x->cmap == 0) { - if (c[i].visualid == vi->visual->visualid) { - x->cmap = c[i].colormap; - x->scmap = c[i]; - //qDebug("Using HP_RGB scmap"); - - } - i++; - } - XFree((char *)c); - } - } - } - if (!x->cmap) { - if (XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n, - XA_RGB_DEFAULT_MAP)) { - for (int i = 0; i < n && x->cmap == 0; ++i) { - if (!c[i].red_max || - !c[i].green_max || - !c[i].blue_max || - !c[i].red_mult || - !c[i].green_mult || - !c[i].blue_mult) - continue; // invalid stdcmap - if (c[i].visualid == vi->visualid) { - x->cmap = c[i].colormap; - x->scmap = c[i]; - //qDebug("Using RGB_DEFAULT scmap"); - } - } - XFree((char *)c); - } - } - if (!x->cmap) { // no shared cmap found - x->cmap = XCreateColormap(dpy, RootWindow(dpy,vi->screen), vi->visual, - AllocNone); - x->alloc = true; - // qDebug("Allocating cmap"); - } - - // colormap hash should be cleanup only when the QApplication dtor is called - if (hash->isEmpty()) - qAddPostRoutine(cleanup_cmaps); - - // associate cmap with visualid - hash->insert((long) vi->visualid + (vi->screen * 256), x); - return x->cmap; -} - -struct QTransColor -{ - VisualID vis; - int screen; - long color; -}; - -static QVector trans_colors; -static int trans_colors_init = false; - -static void find_trans_colors() -{ - struct OverlayProp { - long visual; - long type; - long value; - long layer; - }; - - trans_colors_init = true; - - Display* appDisplay = X11->display; - - int scr; - int lastsize = 0; - for (scr = 0; scr < ScreenCount(appDisplay); scr++) { - QWidget* rootWin = QApplication::desktop()->screen(scr); - if (!rootWin) - return; // Should not happen - Atom overlayVisualsAtom = XInternAtom(appDisplay, - "SERVER_OVERLAY_VISUALS", True); - if (overlayVisualsAtom == XNone) - return; // Server has no overlays - - Atom actualType; - int actualFormat; - ulong nItems; - ulong bytesAfter; - unsigned char *retval = 0; - int res = XGetWindowProperty(appDisplay, rootWin->winId(), - overlayVisualsAtom, 0, 10000, False, - overlayVisualsAtom, &actualType, - &actualFormat, &nItems, &bytesAfter, - &retval); - - if (res != Success || actualType != overlayVisualsAtom - || actualFormat != 32 || nItems < 4 || !retval) - return; // Error reading property - - OverlayProp *overlayProps = (OverlayProp *)retval; - - int numProps = nItems / 4; - trans_colors.resize(lastsize + numProps); - int j = lastsize; - for (int i = 0; i < numProps; i++) { - if (overlayProps[i].type == 1) { - trans_colors[j].vis = (VisualID)overlayProps[i].visual; - trans_colors[j].screen = scr; - trans_colors[j].color = (int)overlayProps[i].value; - j++; - } - } - XFree(overlayProps); - lastsize = j; - trans_colors.resize(lastsize); - } -} - -/***************************************************************************** - QGLFormat UNIX/GLX-specific code - *****************************************************************************/ - -void (*qglx_getProcAddress(const char* procName))() -{ - // On systems where the GL driver is pluggable (like Mesa), we have to use - // the glXGetProcAddressARB extension to resolve other function pointers as - // the symbols wont be in the GL library, but rather in a plugin loaded by - // the GL library. - typedef void (*(*qt_glXGetProcAddressARB)(const char *))(); - static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; - static bool triedResolvingGlxGetProcAddress = false; - if (!triedResolvingGlxGetProcAddress) { - triedResolvingGlxGetProcAddress = true; - QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)); - if (extensions.match("GLX_ARB_get_proc_address")) { -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); - dlclose(handle); - } - if (!glXGetProcAddressARB) -#endif - { -#if !defined(QT_NO_LIBRARY) - extern const QString qt_gl_library_name(); - QLibrary lib(qt_gl_library_name()); - glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); -#endif - } - } - } - - void (*procAddress)() = 0; - if (glXGetProcAddressARB) - procAddress = glXGetProcAddressARB(procName); - - // If glXGetProcAddress didn't work, try looking the symbol up in the GL library -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) - if (!procAddress) { - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - procAddress = (void (*)())dlsym(handle, procName); - dlclose(handle); - } - } -#endif -#if !defined(QT_NO_LIBRARY) - if (!procAddress) { - extern const QString qt_gl_library_name(); - QLibrary lib(qt_gl_library_name()); - procAddress = lib.resolve(procName); - } -#endif - - return procAddress; -} - -bool QGLFormat::hasOpenGL() -{ - return glXQueryExtension(X11->display, 0, 0) != 0; -} - - -bool QGLFormat::hasOpenGLOverlays() -{ - if (!trans_colors_init) - find_trans_colors(); - return trans_colors.size() > 0; -} - -static bool buildSpec(int* spec, const QGLFormat& f, QPaintDevice* paintDevice, - int bufDepth, bool onlyFBConfig = false) -{ - int i = 0; - spec[i++] = GLX_LEVEL; - spec[i++] = f.plane(); - const QX11Info *xinfo = qt_x11Info(paintDevice); - bool useFBConfig = onlyFBConfig; - -#if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX) - /* - HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions. - Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented. - */ - QWidget* widget = 0; - if (paintDevice->devType() == QInternal::Widget) - widget = static_cast(paintDevice); - - // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual - if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender) - useFBConfig = true; -#endif - -#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info) - static bool useTranspExt = false; - static bool useTranspExtChecked = false; - if (f.plane() && !useTranspExtChecked && paintDevice) { - QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); - useTranspExt = extensions.match("GLX_EXT_visual_info"); - //# (A bit simplistic; that could theoretically be a substring) - if (useTranspExt) { - QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR)); - useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround - if (useTranspExt) { - // bug workaround - some systems (eg. FireGL) refuses to return an overlay - // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if - // the implementation supports transparent overlays - int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT, - f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT, - XNone }; - XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec); - if (!vinf) { - useTranspExt = false; - } - } - } - - useTranspExtChecked = true; - } - if (f.plane() && useTranspExt && !useFBConfig) { - // Required to avoid non-transparent overlay visual(!) on some systems - spec[i++] = GLX_TRANSPARENT_TYPE_EXT; - spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; - } -#endif - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - // GLX_RENDER_TYPE is only in glx >=1.3 - if (useFBConfig) { - spec[i++] = GLX_RENDER_TYPE; - spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; - } -#endif - - if (f.doubleBuffer()) - spec[i++] = GLX_DOUBLEBUFFER; - if (useFBConfig) - spec[i++] = True; - if (f.depth()) { - spec[i++] = GLX_DEPTH_SIZE; - spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize(); - } - if (f.stereo()) { - spec[i++] = GLX_STEREO; - if (useFBConfig) - spec[i++] = True; - } - if (f.stencil()) { - spec[i++] = GLX_STENCIL_SIZE; - spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize(); - } - if (f.rgba()) { - if (!useFBConfig) - spec[i++] = GLX_RGBA; - spec[i++] = GLX_RED_SIZE; - spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize(); - spec[i++] = GLX_GREEN_SIZE; - spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize(); - spec[i++] = GLX_BLUE_SIZE; - spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize(); - if (f.alpha()) { - spec[i++] = GLX_ALPHA_SIZE; - spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize(); - } - if (f.accum()) { - spec[i++] = GLX_ACCUM_RED_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - spec[i++] = GLX_ACCUM_GREEN_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - spec[i++] = GLX_ACCUM_BLUE_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - if (f.alpha()) { - spec[i++] = GLX_ACCUM_ALPHA_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - } - } - } else { - spec[i++] = GLX_BUFFER_SIZE; - spec[i++] = bufDepth; - } - - if (f.sampleBuffers()) { - spec[i++] = GLX_SAMPLE_BUFFERS_ARB; - spec[i++] = 1; - spec[i++] = GLX_SAMPLES_ARB; - spec[i++] = f.samples() == -1 ? 4 : f.samples(); - } - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - if (useFBConfig) { - spec[i++] = GLX_DRAWABLE_TYPE; - switch(paintDevice->devType()) { - case QInternal::Pixmap: - spec[i++] = GLX_PIXMAP_BIT; - break; - case QInternal::Pbuffer: - spec[i++] = GLX_PBUFFER_BIT; - break; - default: - qWarning("QGLContext: Unknown paint device type %d", paintDevice->devType()); - // Fall-through & assume it's a window - case QInternal::Widget: - spec[i++] = GLX_WINDOW_BIT; - break; - }; - } -#endif - - spec[i] = XNone; - return useFBConfig; -} - -/***************************************************************************** - QGLContext UNIX/GLX-specific code - *****************************************************************************/ - -bool QGLContext::chooseContext(const QGLContext* shareContext) -{ - Q_D(QGLContext); - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - - Display* disp = xinfo->display(); - d->vi = chooseVisual(); - if (!d->vi) - return false; - - if (deviceIsPixmap() && - (((XVisualInfo*)d->vi)->depth != xinfo->depth() || - ((XVisualInfo*)d->vi)->screen != xinfo->screen())) - { - XFree(d->vi); - XVisualInfo appVisInfo; - memset(&appVisInfo, 0, sizeof(XVisualInfo)); - appVisInfo.visualid = XVisualIDFromVisual((Visual *) xinfo->visual()); - appVisInfo.screen = xinfo->screen(); - int nvis; - d->vi = XGetVisualInfo(disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis); - if (!d->vi) - return false; - - int useGL; - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_USE_GL, &useGL); - if (!useGL) - return false; //# Chickening out already... - } - int res; - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_LEVEL, &res); - d->glFormat.setPlane(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DOUBLEBUFFER, &res); - d->glFormat.setDoubleBuffer(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DEPTH_SIZE, &res); - d->glFormat.setDepth(res); - if (d->glFormat.depth()) - d->glFormat.setDepthBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RGBA, &res); - d->glFormat.setRgba(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RED_SIZE, &res); - d->glFormat.setRedBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_GREEN_SIZE, &res); - d->glFormat.setGreenBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BLUE_SIZE, &res); - d->glFormat.setBlueBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ALPHA_SIZE, &res); - d->glFormat.setAlpha(res); - if (d->glFormat.alpha()) - d->glFormat.setAlphaBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ACCUM_RED_SIZE, &res); - d->glFormat.setAccum(res); - if (d->glFormat.accum()) - d->glFormat.setAccumBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STENCIL_SIZE, &res); - d->glFormat.setStencil(res); - if (d->glFormat.stencil()) - d->glFormat.setStencilBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STEREO, &res); - d->glFormat.setStereo(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLE_BUFFERS_ARB, &res); - d->glFormat.setSampleBuffers(res); - if (d->glFormat.sampleBuffers()) { - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLES_ARB, &res); - d->glFormat.setSamples(res); - } - - Bool direct = format().directRendering() ? True : False; - - if (shareContext && - (!shareContext->isValid() || !shareContext->d_func()->cx)) { - qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); - shareContext = 0; - } - - // 1. Sharing between rgba and color-index will give wrong colors. - // 2. Contexts cannot be shared btw. direct/non-direct renderers. - // 3. Pixmaps cannot share contexts that are set up for direct rendering. - // 4. If the contexts are not created on the same screen, they can't be shared - - if (shareContext - && (format().rgba() != shareContext->format().rgba() - || (deviceIsPixmap() && glXIsDirect(disp, (GLXContext)shareContext->d_func()->cx)) - || (shareContext->d_func()->screen != xinfo->screen()))) - { - shareContext = 0; - } - - const int major = d->reqFormat.majorVersion(); - const int minor = d->reqFormat.minorVersion(); - const int profile = d->reqFormat.profile() == QGLFormat::CompatibilityProfile - ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB - : GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - - d->cx = 0; - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - /* - HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions. - Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented. - */ - if ((major == 3 && minor >= 2) || major > 3) { - QGLTemporaryContext *tmpContext = 0; - if (!QGLContext::currentContext()) - tmpContext = new QGLTemporaryContext; - - int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, major, - GLX_CONTEXT_MINOR_VERSION_ARB, minor, - GLX_CONTEXT_PROFILE_MASK_ARB, profile, - 0 }; - - typedef GLXContext ( * Q_PFNGLXCREATECONTEXTATTRIBSARBPROC) - (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); - - - Q_PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = - (Q_PFNGLXCREATECONTEXTATTRIBSARBPROC) qglx_getProcAddress("glXCreateContextAttribsARB"); - - if (glXCreateContextAttribs) { - int spec[45]; - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BUFFER_SIZE, &res); - buildSpec(spec, format(), d->paintDevice, res, true); - - GLXFBConfig *configs; - int configCount = 0; - configs = glXChooseFBConfig(disp, xinfo->screen(), spec, &configCount); - - if (configs && configCount > 0) { - d->cx = glXCreateContextAttribs(disp, configs[0], - shareContext ? (GLXContext)shareContext->d_func()->cx : 0, direct, attributes); - if (!d->cx && shareContext) { - shareContext = 0; - d->cx = glXCreateContextAttribs(disp, configs[0], 0, direct, attributes); - } - d->screen = ((XVisualInfo*)d->vi)->screen; - } - XFree(configs); - } else { - qWarning("QGLContext::chooseContext(): OpenGL %d.%d is not supported", major, minor); - } - - if (tmpContext) - delete tmpContext; - } -#else - Q_UNUSED(major); - Q_UNUSED(minor); - Q_UNUSED(profile); -#endif - - if (!d->cx && shareContext) { - d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, - (GLXContext)shareContext->d_func()->cx, direct); - d->screen = ((XVisualInfo*)d->vi)->screen; - } - if (!d->cx) { - d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, NULL, direct); - d->screen = ((XVisualInfo*)d->vi)->screen; - shareContext = 0; - } - - if (shareContext && d->cx) { - QGLContext *share = const_cast(shareContext); - d->sharing = true; - share->d_func()->sharing = true; - } - - if (!d->cx) - return false; - d->glFormat.setDirectRendering(glXIsDirect(disp, (GLXContext)d->cx)); - if (deviceIsPixmap()) { -#if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) - d->gpm = glXCreateGLXPixmapMESA(disp, (XVisualInfo *)d->vi, - qt_x11Handle(d->paintDevice), - qt_gl_choose_cmap(disp, (XVisualInfo *)d->vi)); -#else - d->gpm = (quint32)glXCreateGLXPixmap(disp, (XVisualInfo *)d->vi, - qt_x11Handle(d->paintDevice)); -#endif - if (!d->gpm) - return false; - } - QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); - if (extensions.match("GLX_SGI_video_sync")) { - if (d->glFormat.swapInterval() == -1) - d->glFormat.setSwapInterval(0); - } else { - d->glFormat.setSwapInterval(-1); - } - return true; -} - -/* - See qgl.cpp for qdoc comment. - */ -void *QGLContext::chooseVisual() -{ - Q_D(QGLContext); - static const int bufDepths[] = { 8, 4, 2, 1 }; // Try 16, 12 also? - //todo: if pixmap, also make sure that vi->depth == pixmap->depth - void* vis = 0; - int i = 0; - bool fail = false; - QGLFormat fmt = format(); - bool tryDouble = !fmt.doubleBuffer(); // Some GL impl's only have double - bool triedDouble = false; - bool triedSample = false; - if (fmt.sampleBuffers()) - fmt.setSampleBuffers(QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers); - while(!fail && !(vis = tryVisual(fmt, bufDepths[i]))) { - if (!fmt.rgba() && bufDepths[i] > 1) { - i++; - continue; - } - if (tryDouble) { - fmt.setDoubleBuffer(true); - tryDouble = false; - triedDouble = true; - continue; - } else if (triedDouble) { - fmt.setDoubleBuffer(false); - triedDouble = false; - } - if (!triedSample && fmt.sampleBuffers()) { - fmt.setSampleBuffers(false); - triedSample = true; - continue; - } - if (fmt.stereo()) { - fmt.setStereo(false); - continue; - } - if (fmt.accum()) { - fmt.setAccum(false); - continue; - } - if (fmt.stencil()) { - fmt.setStencil(false); - continue; - } - if (fmt.alpha()) { - fmt.setAlpha(false); - continue; - } - if (fmt.depth()) { - fmt.setDepth(false); - continue; - } - if (fmt.doubleBuffer()) { - fmt.setDoubleBuffer(false); - continue; - } - fail = true; - } - d->glFormat = fmt; - return vis; -} - -/* - See qgl.cpp for qdoc comment. - */ -void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth) -{ - Q_D(QGLContext); - int spec[45]; - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - bool useFBConfig = buildSpec(spec, f, d->paintDevice, bufDepth, false); - - XVisualInfo* chosenVisualInfo = 0; - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - while (useFBConfig) { - GLXFBConfig *configs; - int configCount = 0; - configs = glXChooseFBConfig(xinfo->display(), xinfo->screen(), spec, &configCount); - - if (!configs) - break; // fallback to trying glXChooseVisual - - for (int i = 0; i < configCount; ++i) { - XVisualInfo* vi; - vi = glXGetVisualFromFBConfig(xinfo->display(), configs[i]); - if (!vi) - continue; - -#if !defined(QT_NO_XRENDER) - QWidget* w = 0; - if (d->paintDevice->devType() == QInternal::Widget) - w = static_cast(d->paintDevice); - - if (w && w->testAttribute(Qt::WA_TranslucentBackground) && f.alpha()) { - // Attempt to find a config who's visual has a proper alpha channel - XRenderPictFormat *pictFormat; - pictFormat = XRenderFindVisualFormat(xinfo->display(), vi->visual); - - if (pictFormat && (pictFormat->type == PictTypeDirect) && pictFormat->direct.alphaMask) { - // The pict format for the visual matching the FBConfig indicates ARGB - if (chosenVisualInfo) - XFree(chosenVisualInfo); - chosenVisualInfo = vi; - break; - } - } else -#endif //QT_NO_XRENDER - if (chosenVisualInfo) { - // If we've got a visual we can use and we're not trying to find one with a - // real alpha channel, we might as well just use the one we've got - break; - } - - if (!chosenVisualInfo) - chosenVisualInfo = vi; // Have something to fall back to - else - XFree(vi); - } - - XFree(configs); - break; - } -#endif // defined(GLX_VERSION_1_3) - - if (!chosenVisualInfo) - chosenVisualInfo = glXChooseVisual(xinfo->display(), xinfo->screen(), spec); - - return chosenVisualInfo; -} - - -void QGLContext::reset() -{ - Q_D(QGLContext); - if (!d->valid) - return; - d->cleanup(); - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - doneCurrent(); - if (d->gpm) - glXDestroyGLXPixmap(xinfo->display(), (GLXPixmap)d->gpm); - d->gpm = 0; - glXDestroyContext(xinfo->display(), (GLXContext)d->cx); - if (d->vi) - XFree(d->vi); - d->vi = 0; - d->cx = 0; - d->crWin = false; - d->sharing = false; - d->valid = false; - d->transpColor = QColor(); - d->initDone = false; - QGLContextGroup::removeShare(this); -} - - -void QGLContext::makeCurrent() -{ - Q_D(QGLContext); - if (!d->valid) { - qWarning("QGLContext::makeCurrent(): Cannot make invalid context current."); - return; - } - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - bool ok = true; - if (d->paintDevice->devType() == QInternal::Pixmap) { - ok = glXMakeCurrent(xinfo->display(), (GLXPixmap)d->gpm, (GLXContext)d->cx); - } else if (d->paintDevice->devType() == QInternal::Pbuffer) { - ok = glXMakeCurrent(xinfo->display(), (GLXPbuffer)d->pbuf, (GLXContext)d->cx); - } else if (d->paintDevice->devType() == QInternal::Widget) { - ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->internalWinId(), (GLXContext)d->cx); - } - if (!ok) - qWarning("QGLContext::makeCurrent(): Failed."); - - if (ok) - QGLContextPrivate::setCurrentContext(this); -} - -void QGLContext::doneCurrent() -{ - Q_D(QGLContext); - glXMakeCurrent(qt_x11Info(d->paintDevice)->display(), 0, 0); - QGLContextPrivate::setCurrentContext(0); -} - - -void QGLContext::swapBuffers() const -{ - Q_D(const QGLContext); - if (!d->valid) - return; - if (!deviceIsPixmap()) { - int interval = d->glFormat.swapInterval(); - if (interval > 0) { - typedef int (*qt_glXGetVideoSyncSGI)(uint *); - typedef int (*qt_glXWaitVideoSyncSGI)(int, int, uint *); - static qt_glXGetVideoSyncSGI glXGetVideoSyncSGI = 0; - static qt_glXWaitVideoSyncSGI glXWaitVideoSyncSGI = 0; - static bool resolved = false; - if (!resolved) { - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); - if (extensions.match("GLX_SGI_video_sync")) { - glXGetVideoSyncSGI = (qt_glXGetVideoSyncSGI)qglx_getProcAddress("glXGetVideoSyncSGI"); - glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI)qglx_getProcAddress("glXWaitVideoSyncSGI"); - } - resolved = true; - } - if (glXGetVideoSyncSGI && glXWaitVideoSyncSGI) { - uint counter; - if (!glXGetVideoSyncSGI(&counter)) - glXWaitVideoSyncSGI(interval + 1, (counter + interval) % (interval + 1), &counter); - } - } - glXSwapBuffers(qt_x11Info(d->paintDevice)->display(), - static_cast(d->paintDevice)->winId()); - } -} - -QColor QGLContext::overlayTransparentColor() const -{ - if (isValid()) - return Qt::transparent; - return QColor(); // Invalid color -} - -static uint qt_transparent_pixel(VisualID id, int screen) -{ - for (int i = 0; i < trans_colors.size(); i++) { - if (trans_colors[i].vis == id && trans_colors[i].screen == screen) - return trans_colors[i].color; - } - return 0; -} - -uint QGLContext::colorIndex(const QColor& c) const -{ - Q_D(const QGLContext); - int screen = ((XVisualInfo *)d->vi)->screen; - QColormap colmap = QColormap::instance(screen); - if (isValid()) { - if (format().plane() && c == Qt::transparent) { - return qt_transparent_pixel(((XVisualInfo *)d->vi)->visualid, - ((XVisualInfo *)d->vi)->screen); - } - if (((XVisualInfo*)d->vi)->visualid == - XVisualIDFromVisual((Visual *) QX11Info::appVisual(screen))) - return colmap.pixel(c); // We're using QColor's cmap - - XVisualInfo *info = (XVisualInfo *) d->vi; - CMapEntryHash *hash = cmap_handler()->cmap_hash; - CMapEntryHash::ConstIterator it = hash->constFind(long(info->visualid) - + (info->screen * 256)); - QCMapEntry *x = 0; - if (it != hash->constEnd()) - x = it.value(); - if (x && !x->alloc) { // It's a standard colormap - int rf = (int)(((float)c.red() * (x->scmap.red_max+1))/256.0); - int gf = (int)(((float)c.green() * (x->scmap.green_max+1))/256.0); - int bf = (int)(((float)c.blue() * (x->scmap.blue_max+1))/256.0); - uint p = x->scmap.base_pixel - + (rf * x->scmap.red_mult) - + (gf * x->scmap.green_mult) - + (bf * x->scmap.blue_mult); - return p; - } else { - QMap &cmap = (*cmap_handler()->qglcmap_hash)[(long)info->visualid]; - - // already in the map? - QRgb target = c.rgb(); - QMap::Iterator it = cmap.begin(); - for (; it != cmap.end(); ++it) { - if ((*it) == target) - return it.key(); - } - - // need to alloc color - unsigned long plane_mask[2]; - unsigned long color_map_entry; - if (!XAllocColorCells (QX11Info::display(), x->cmap, true, plane_mask, 0, - &color_map_entry, 1)) - return colmap.pixel(c); - - XColor col; - col.flags = DoRed | DoGreen | DoBlue; - col.pixel = color_map_entry; - col.red = (ushort)((qRed(c.rgb()) / 255.0) * 65535.0 + 0.5); - col.green = (ushort)((qGreen(c.rgb()) / 255.0) * 65535.0 + 0.5); - col.blue = (ushort)((qBlue(c.rgb()) / 255.0) * 65535.0 + 0.5); - XStoreColor(QX11Info::display(), x->cmap, &col); - - cmap.insert(color_map_entry, target); - return color_map_entry; - } - } - return 0; -} - -#ifndef QT_NO_FONTCONFIG -/*! \internal - This is basically a substitute for glxUseXFont() which can only - handle XLFD fonts. This version relies on freetype to render the - glyphs, but it works with all fonts that fontconfig provides - both - antialiased and aliased bitmap and outline fonts. -*/ -static void qgl_use_font(QFontEngineFT *engine, int first, int count, int listBase) -{ - GLfloat color[4]; - glGetFloatv(GL_CURRENT_COLOR, color); - - // save the pixel unpack state - GLint gl_swapbytes, gl_lsbfirst, gl_rowlength, gl_skiprows, gl_skippixels, gl_alignment; - glGetIntegerv (GL_UNPACK_SWAP_BYTES, &gl_swapbytes); - glGetIntegerv (GL_UNPACK_LSB_FIRST, &gl_lsbfirst); - glGetIntegerv (GL_UNPACK_ROW_LENGTH, &gl_rowlength); - glGetIntegerv (GL_UNPACK_SKIP_ROWS, &gl_skiprows); - glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &gl_skippixels); - glGetIntegerv (GL_UNPACK_ALIGNMENT, &gl_alignment); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - const bool antialiased = engine->drawAntialiased(); - FT_Face face = engine->lockFace(); - - // start generating font glyphs - for (int i = first; i < count; ++i) { - int list = listBase + i; - GLfloat x0, y0, dx, dy; - - FT_Error err; - - err = FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT); - if (err) { - qDebug("failed loading glyph %d from font", i); - Q_ASSERT(!err); - } - err = FT_Render_Glyph(face->glyph, (antialiased ? FT_RENDER_MODE_NORMAL - : FT_RENDER_MODE_MONO)); - if (err) { - qDebug("failed rendering glyph %d from font", i); - Q_ASSERT(!err); - } - - FT_Bitmap bm = face->glyph->bitmap; - x0 = face->glyph->metrics.horiBearingX >> 6; - y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6; - dx = face->glyph->metrics.horiAdvance >> 6; - dy = 0; - int sz = bm.pitch * bm.rows; - uint *aa_glyph = 0; - uchar *ua_glyph = 0; - - if (antialiased) - aa_glyph = new uint[sz]; - else - ua_glyph = new uchar[sz]; - - // convert to GL format - for (int y = 0; y < bm.rows; ++y) { - for (int x = 0; x < bm.pitch; ++x) { - int c1 = y*bm.pitch + x; - int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x; - if (antialiased) { - aa_glyph[c1] = (int(color[0]*255) << 24) - | (int(color[1]*255) << 16) - | (int(color[2]*255) << 8) | bm.buffer[c2]; - } else { - ua_glyph[c1] = bm.buffer[c2]; - } - } - } - - glNewList(list, GL_COMPILE); - if (antialiased) { - // calling glBitmap() is just a trick to move the current - // raster pos, since glGet*() won't work in display lists - glBitmap(0, 0, 0, 0, x0, -y0, 0); - glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph); - glBitmap(0, 0, 0, 0, dx-x0, y0, 0); - } else { - glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph); - } - glEndList(); - antialiased ? delete[] aa_glyph : delete[] ua_glyph; - } - - engine->unlockFace(); - - // restore pixel unpack settings - glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes); - glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst); - glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength); - glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels); - glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); -} -#endif - -#undef d -void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase) -{ - QFont f(fnt); - QFontEngine *engine = f.d->engineForScript(QUnicodeTables::Common); - - if (engine->type() == QFontEngine::Multi) - engine = static_cast(engine)->engine(0); -#ifndef QT_NO_FONTCONFIG - if(engine->type() == QFontEngine::Freetype) { - qgl_use_font(static_cast(engine), 0, 256, listBase); - return; - } -#endif - // glXUseXFont() only works with XLFD font structures and a few GL - // drivers crash if 0 is passed as the font handle - f.setStyleStrategy(QFont::OpenGLCompatible); - if (f.handle() && engine->type() == QFontEngine::XLFD) - glXUseXFont(static_cast(f.handle()), 0, 256, listBase); -} - -void *QGLContext::getProcAddress(const QString &proc) const -{ - typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); - static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; - static bool resolved = false; - - if (resolved && !glXGetProcAddressARB) - return 0; - if (!glXGetProcAddressARB) { - QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)); - if (extensions.match("GLX_ARB_get_proc_address")) { -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); - dlclose(handle); - } - if (!glXGetProcAddressARB) -#endif - { -#if !defined(QT_NO_LIBRARY) - extern const QString qt_gl_library_name(); - QLibrary lib(qt_gl_library_name()); - glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); -#endif - } - } - resolved = true; - } - if (!glXGetProcAddressARB) - return 0; - return glXGetProcAddressARB(reinterpret_cast(proc.toLatin1().data())); -} - -/* - QGLTemporaryContext implementation -*/ - -class QGLTemporaryContextPrivate { -public: - bool initialized; - Window drawable; - GLXContext context; - GLXDrawable oldDrawable; - GLXContext oldContext; -}; - -QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) - : d(new QGLTemporaryContextPrivate) -{ - d->initialized = false; - d->oldDrawable = 0; - d->oldContext = 0; - int screen = 0; - - int attribs[] = {GLX_RGBA, XNone}; - XVisualInfo *vi = glXChooseVisual(X11->display, screen, attribs); - if (!vi) { - qWarning("QGLTempContext: No GL capable X visuals available."); - return; - } - - int useGL; - glXGetConfig(X11->display, vi, GLX_USE_GL, &useGL); - if (!useGL) { - XFree(vi); - return; - } - - d->oldDrawable = glXGetCurrentDrawable(); - d->oldContext = glXGetCurrentContext(); - - XSetWindowAttributes a; - a.colormap = qt_gl_choose_cmap(X11->display, vi); - d->drawable = XCreateWindow(X11->display, RootWindow(X11->display, screen), - 0, 0, 1, 1, 0, - vi->depth, InputOutput, vi->visual, - CWColormap, &a); - d->context = glXCreateContext(X11->display, vi, 0, True); - if (d->context && glXMakeCurrent(X11->display, d->drawable, d->context)) { - d->initialized = true; - } else { - qWarning("QGLTempContext: Unable to create GL context."); - XDestroyWindow(X11->display, d->drawable); - } - XFree(vi); -} - -QGLTemporaryContext::~QGLTemporaryContext() -{ - if (d->initialized) { - glXMakeCurrent(X11->display, 0, 0); - glXDestroyContext(X11->display, d->context); - XDestroyWindow(X11->display, d->drawable); - } - if (d->oldDrawable && d->oldContext) - glXMakeCurrent(X11->display, d->oldDrawable, d->oldContext); -} - -/***************************************************************************** - QGLOverlayWidget (Internal overlay class for X11) - *****************************************************************************/ - -class QGLOverlayWidget : public QGLWidget -{ - Q_OBJECT -public: - QGLOverlayWidget(const QGLFormat& format, QGLWidget* parent, const QGLWidget* shareWidget=0); - -protected: - void initializeGL(); - void paintGL(); - void resizeGL(int w, int h); - bool x11Event(XEvent *e) { return realWidget->x11Event(e); } - -private: - QGLWidget* realWidget; - -private: - Q_DISABLE_COPY(QGLOverlayWidget) -}; - - -QGLOverlayWidget::QGLOverlayWidget(const QGLFormat& format, QGLWidget* parent, - const QGLWidget* shareWidget) - : QGLWidget(format, parent, shareWidget ? shareWidget->d_func()->olw : 0) -{ - setAttribute(Qt::WA_X11OpenGLOverlay); - realWidget = parent; -} - - - -void QGLOverlayWidget::initializeGL() -{ - QColor transparentColor = context()->overlayTransparentColor(); - if (transparentColor.isValid()) - qglClearColor(transparentColor); - else - qWarning("QGLOverlayWidget::initializeGL(): Could not get transparent color"); - realWidget->initializeOverlayGL(); -} - - -void QGLOverlayWidget::resizeGL(int w, int h) -{ - glViewport(0, 0, w, h); - realWidget->resizeOverlayGL(w, h); -} - - -void QGLOverlayWidget::paintGL() -{ - realWidget->paintOverlayGL(); -} - -#undef Bool -QT_BEGIN_INCLUDE_NAMESPACE -#include "qgl_x11.moc" -QT_END_INCLUDE_NAMESPACE - -/***************************************************************************** - QGLWidget UNIX/GLX-specific code - *****************************************************************************/ -void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget) -{ - Q_Q(QGLWidget); - initContext(context, shareWidget); - olw = 0; - - if (q->isValid() && context->format().hasOverlay()) { - QString olwName = q->objectName(); - olwName += QLatin1String("-QGL_internal_overlay_widget"); - olw = new QGLOverlayWidget(QGLFormat::defaultOverlayFormat(), q, shareWidget); - olw->setObjectName(olwName); - if (olw->isValid()) { - olw->setAutoBufferSwap(false); - olw->setFocusProxy(q); - } - else { - delete olw; - olw = 0; - glcx->d_func()->glFormat.setOverlay(false); - } - } -} - -bool QGLWidgetPrivate::renderCxPm(QPixmap* pm) -{ - Q_Q(QGLWidget); - if (((XVisualInfo*)glcx->d_func()->vi)->depth != pm->depth()) - return false; - - GLXPixmap glPm; -#if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) - glPm = glXCreateGLXPixmapMESA(X11->display, - (XVisualInfo*)glcx->vi, - (Pixmap)pm->handle(), - qt_gl_choose_cmap(pm->X11->display, - (XVisualInfo*)glcx->vi)); -#else - glPm = (quint32)glXCreateGLXPixmap(X11->display, - (XVisualInfo*)glcx->d_func()->vi, - (Pixmap)pm->handle()); -#endif - - if (!glXMakeCurrent(X11->display, glPm, (GLXContext)glcx->d_func()->cx)) { - glXDestroyGLXPixmap(X11->display, glPm); - return false; - } - - glDrawBuffer(GL_FRONT); - if (!glcx->initialized()) - q->glInit(); - q->resizeGL(pm->width(), pm->height()); - q->paintGL(); - glFlush(); - q->makeCurrent(); - glXDestroyGLXPixmap(X11->display, glPm); - q->resizeGL(q->width(), q->height()); - return true; -} - -void QGLWidgetPrivate::cleanupColormaps() -{ - if (!cmap.handle()) { - return; - } else { - XFreeColormap(X11->display, (Colormap) cmap.handle()); - cmap.setHandle(0); - } -} - -void QGLWidget::setMouseTracking(bool enable) -{ - Q_D(QGLWidget); - if (d->olw) - d->olw->setMouseTracking(enable); - QWidget::setMouseTracking(enable); -} - - -void QGLWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QGLWidget); - if (!isValid()) - return; - makeCurrent(); - if (!d->glcx->initialized()) - glInit(); - glXWaitX(); - resizeGL(width(), height()); - if (d->olw) - d->olw->setGeometry(rect()); -} - -const QGLContext* QGLWidget::overlayContext() const -{ - Q_D(const QGLWidget); - if (d->olw) - return d->olw->context(); - else - return 0; -} - - -void QGLWidget::makeOverlayCurrent() -{ - Q_D(QGLWidget); - if (d->olw) - d->olw->makeCurrent(); -} - - -void QGLWidget::updateOverlayGL() -{ - Q_D(QGLWidget); - if (d->olw) - d->olw->updateGL(); -} - -/*! - \internal - - Sets a new QGLContext, \a context, for this QGLWidget, using the - shared context, \a shareContext. If \a deleteOldContext is true, - the original context is deleted; otherwise it is overridden. -*/ -void QGLWidget::setContext(QGLContext *context, - const QGLContext* shareContext, - bool deleteOldContext) -{ - Q_D(QGLWidget); - if (context == 0) { - qWarning("QGLWidget::setContext: Cannot set null context"); - return; - } - if (!context->deviceIsPixmap() && context->device() != this) { - qWarning("QGLWidget::setContext: Context must refer to this widget"); - return; - } - - if (d->glcx) - d->glcx->doneCurrent(); - QGLContext* oldcx = d->glcx; - d->glcx = context; - - if (parentWidget()) { - // force creation of delay-created widgets - parentWidget()->winId(); - if (parentWidget()->x11Info().screen() != x11Info().screen()) - d_func()->xinfo = parentWidget()->d_func()->xinfo; - } - - // If the application has set WA_TranslucentBackground and not explicitly set - // the alpha buffer size to zero, modify the format so it have an alpha channel - QGLFormat& fmt = d->glcx->d_func()->glFormat; - if (testAttribute(Qt::WA_TranslucentBackground) && fmt.alphaBufferSize() == -1) - fmt.setAlphaBufferSize(1); - - bool createFailed = false; - if (!d->glcx->isValid()) { - if (!d->glcx->create(shareContext ? shareContext : oldcx)) - createFailed = true; - } - if (createFailed) { - if (deleteOldContext) - delete oldcx; - return; - } - - if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) { - if (deleteOldContext) - delete oldcx; - return; - } - - bool visible = isVisible(); - if (visible) - hide(); - - XVisualInfo *vi = (XVisualInfo*)d->glcx->d_func()->vi; - XSetWindowAttributes a; - - QColormap colmap = QColormap::instance(vi->screen); - a.colormap = qt_gl_choose_cmap(QX11Info::display(), vi); // find best colormap - a.background_pixel = colmap.pixel(palette().color(backgroundRole())); - a.border_pixel = colmap.pixel(Qt::black); - Window p = RootWindow(X11->display, vi->screen); - if (parentWidget()) - p = parentWidget()->winId(); - - Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(), - 0, vi->depth, InputOutput, vi->visual, - CWBackPixel|CWBorderPixel|CWColormap, &a); - Window *cmw; - Window *cmwret; - int count; - if (XGetWMColormapWindows(X11->display, window()->winId(), - &cmwret, &count)) { - cmw = new Window[count+1]; - memcpy((char *)cmw, (char *)cmwret, sizeof(Window)*count); - XFree((char *)cmwret); - int i; - for (i=0; i= count) // append new window - cmw[count++] = w; - } else { - count = 1; - cmw = new Window[count]; - cmw[0] = w; - } - -#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT) - if (oldcx && oldcx->windowCreated()) - glXReleaseBuffersMESA(X11->display, winId()); -#endif - if (deleteOldContext) - delete oldcx; - oldcx = 0; - - if (testAttribute(Qt::WA_WState_Created)) - create(w); - else - d->createWinId(w); - XSetWMColormapWindows(X11->display, window()->winId(), cmw, count); - delete [] cmw; - - // calling QWidget::create() will always result in a new paint - // engine being created - get rid of it and replace it with our - // own - - if (visible) - show(); - XFlush(X11->display); - d->glcx->setWindowCreated(true); -} - -const QGLColormap & QGLWidget::colormap() const -{ - Q_D(const QGLWidget); - return d->cmap; -} - -/*\internal - Store color values in the given colormap. -*/ -static void qStoreColors(QWidget * tlw, Colormap cmap, - const QGLColormap & cols) -{ - Q_UNUSED(tlw); - XColor c; - QRgb color; - - for (int i = 0; i < cols.size(); i++) { - color = cols.entryRgb(i); - c.pixel = i; - c.red = (ushort)((qRed(color) / 255.0) * 65535.0 + 0.5); - c.green = (ushort)((qGreen(color) / 255.0) * 65535.0 + 0.5); - c.blue = (ushort)((qBlue(color) / 255.0) * 65535.0 + 0.5); - c.flags = DoRed | DoGreen | DoBlue; - XStoreColor(X11->display, cmap, &c); - } -} - -/*\internal - Check whether the given visual supports dynamic colormaps or not. -*/ -static bool qCanAllocColors(QWidget * w) -{ - bool validVisual = false; - int numVisuals; - long mask; - XVisualInfo templ; - XVisualInfo * visuals; - VisualID id = XVisualIDFromVisual((Visual *) w->window()->x11Info().visual()); - - mask = VisualScreenMask; - templ.screen = w->x11Info().screen(); - visuals = XGetVisualInfo(X11->display, mask, &templ, &numVisuals); - - for (int i = 0; i < numVisuals; i++) { - if (visuals[i].visualid == id) { - switch (visuals[i].c_class) { - case TrueColor: - case StaticColor: - case StaticGray: - case XGrayScale: - validVisual = false; - break; - case DirectColor: - case PseudoColor: - validVisual = true; - break; - } - break; - } - } - XFree(visuals); - - if (!validVisual) - return false; - return true; -} - - -void QGLWidget::setColormap(const QGLColormap & c) -{ - Q_D(QGLWidget); - QWidget * tlw = window(); // must return a valid widget - - d->cmap = c; - if (!d->cmap.handle()) - return; - - if (!qCanAllocColors(this)) { - qWarning("QGLWidget::setColormap: Cannot create a read/write " - "colormap for this visual"); - return; - } - - // If the child GL widget is not of the same visual class as the - // toplevel widget we will get in trouble.. - Window wid = tlw->winId(); - Visual * vis = (Visual *) tlw->x11Info().visual();; - VisualID cvId = XVisualIDFromVisual((Visual *) x11Info().visual()); - VisualID tvId = XVisualIDFromVisual((Visual *) tlw->x11Info().visual()); - if (cvId != tvId) { - wid = winId(); - vis = (Visual *) x11Info().visual(); - } - - if (!d->cmap.handle()) // allocate a cmap if necessary - d->cmap.setHandle(XCreateColormap(X11->display, wid, vis, AllocAll)); - - qStoreColors(this, (Colormap) d->cmap.handle(), c); - XSetWindowColormap(X11->display, wid, (Colormap) d->cmap.handle()); - - // tell the wm that this window has a special colormap - Window * cmw; - Window * cmwret; - int count; - if (XGetWMColormapWindows(X11->display, tlw->winId(), &cmwret, &count)) - { - cmw = new Window[count+1]; - memcpy((char *) cmw, (char *) cmwret, sizeof(Window) * count); - XFree((char *) cmwret); - int i; - for (i = 0; i < count; i++) { - if (cmw[i] == winId()) { - break; - } - } - if (i >= count) // append new window only if not in the list - cmw[count++] = winId(); - } else { - count = 1; - cmw = new Window[count]; - cmw[0] = winId(); - } - XSetWMColormapWindows(X11->display, tlw->winId(), cmw, count); - delete [] cmw; -} - -// Solaris defines glXBindTexImageEXT as part of the GL library -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) -typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*); -typedef void (*qt_glXReleaseTexImageEXT)(Display*, GLXDrawable, int); -static qt_glXBindTexImageEXT glXBindTexImageEXT = 0; -static qt_glXReleaseTexImageEXT glXReleaseTexImageEXT = 0; - -static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice) -{ - static bool resolvedTextureFromPixmap = false; - - if (!resolvedTextureFromPixmap) { - resolvedTextureFromPixmap = true; - - // Check to see if we have NPOT texture support - if ( !(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) && - !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)) - { - return false; // Can't use TFP without NPOT - } - - const QX11Info *xinfo = qt_x11Info(paintDevice); - Display *display = xinfo ? xinfo->display() : X11->display; - int screen = xinfo ? xinfo->screen() : X11->defaultScreen; - - QGLExtensionMatcher serverExtensions(glXQueryExtensionsString(display, screen)); - QGLExtensionMatcher clientExtensions(glXGetClientString(display, GLX_EXTENSIONS)); - if (serverExtensions.match("GLX_EXT_texture_from_pixmap") - && clientExtensions.match("GLX_EXT_texture_from_pixmap")) - { - glXBindTexImageEXT = (qt_glXBindTexImageEXT) qglx_getProcAddress("glXBindTexImageEXT"); - glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) qglx_getProcAddress("glXReleaseTexImageEXT"); - } - } - - return glXBindTexImageEXT && glXReleaseTexImageEXT; -} -#endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - - -QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key, - QGLContext::BindOptions options) -{ -#if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX) - return 0; -#else - - // Check we have GLX 1.3, as it is needed for glXCreatePixmap & glXDestroyPixmap - int majorVersion = 0; - int minorVersion = 0; - glXQueryVersion(X11->display, &majorVersion, &minorVersion); - if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 3)) - return 0; - - Q_Q(QGLContext); - - QX11PlatformPixmap *handle = static_cast(pixmap->data_ptr().data()); - Q_ASSERT(handle->classId() == QPlatformPixmap::X11Class); - - // We can't use TFP if the pixmap has a separate X11 mask - if (handle->x11_mask) - return 0; - - if (!qt_resolveTextureFromPixmap(paintDevice)) - return 0; - - const QX11Info &x11Info = handle->xinfo; - - // Store the configs (Can be static because configs aren't dependent on current context) - static GLXFBConfig glxRGBPixmapConfig = 0; - static bool RGBConfigInverted = false; - static GLXFBConfig glxRGBAPixmapConfig = 0; - static bool RGBAConfigInverted = false; - - bool hasAlpha = handle->hasAlphaChannel(); - - // Check to see if we need a config - if ( (hasAlpha && !glxRGBAPixmapConfig) || (!hasAlpha && !glxRGBPixmapConfig) ) { - GLXFBConfig *configList = 0; - int configCount = 0; - - int configAttribs[] = { - hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True, - GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, - GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, - // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can: - GLX_Y_INVERTED_EXT, options & QGLContext::CanFlipNativePixmapBindOption ? GLX_DONT_CARE : False, - XNone - }; - configList = glXChooseFBConfig(x11Info.display(), x11Info.screen(), configAttribs, &configCount); - if (!configList) - return 0; - - int yInv; - glXGetFBConfigAttrib(x11Info.display(), configList[0], GLX_Y_INVERTED_EXT, &yInv); - - if (hasAlpha) { - glxRGBAPixmapConfig = configList[0]; - RGBAConfigInverted = yInv; - } - else { - glxRGBPixmapConfig = configList[0]; - RGBConfigInverted = yInv; - } - - XFree(configList); - } - - // Check to see if the surface is still valid - if (handle->gl_surface && - hasAlpha != (handle->flags & QX11PlatformPixmap::GlSurfaceCreatedWithAlpha)) - { - // Surface is invalid! - destroyGlSurfaceForPixmap(handle); - } - - // Check to see if we need a surface - if (!handle->gl_surface) { - GLXPixmap glxPixmap; - int pixmapAttribs[] = { - GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT, - GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, - GLX_MIPMAP_TEXTURE_EXT, False, // Maybe needs to be don't care - XNone - }; - - // Wrap the X Pixmap into a GLXPixmap: - glxPixmap = glXCreatePixmap(x11Info.display(), - hasAlpha ? glxRGBAPixmapConfig : glxRGBPixmapConfig, - handle->handle(), pixmapAttribs); - - if (!glxPixmap) - return 0; - - handle->gl_surface = (void*)glxPixmap; - - // Make sure the cleanup hook gets called so we can delete the glx pixmap - QImagePixmapCleanupHooks::enableCleanupHooks(handle); - } - - GLuint textureId; - glGenTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); - glXBindTexImageEXT(x11Info.display(), (GLXPixmap)handle->gl_surface, GLX_FRONT_LEFT_EXT, 0); - - glBindTexture(GL_TEXTURE_2D, textureId); - GLuint filtering = (options & QGLContext::LinearFilteringBindOption) ? GL_LINEAR : GL_NEAREST; - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); - - if (!((hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted))) - options &= ~QGLContext::InvertedYBindOption; - - QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options); - if (texture->options & QGLContext::InvertedYBindOption) - handle->flags |= QX11PlatformPixmap::InvertedWhenBoundToTexture; - - // We assume the cost of bound pixmaps is zero - QGLTextureCache::instance()->insert(q, key, texture, 0); - - return texture; -#endif //!defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX) -} - - -void QGLContextPrivate::destroyGlSurfaceForPixmap(QPlatformPixmap* pmd) -{ -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - Q_ASSERT(pmd->classId() == QPlatformPixmap::X11Class); - QX11PlatformPixmap *handle = static_cast(pmd); - if (handle->gl_surface) { - glXDestroyPixmap(QX11Info::display(), (GLXPixmap)handle->gl_surface); - handle->gl_surface = 0; - } -#endif -} - -void QGLContextPrivate::unbindPixmapFromTexture(QPlatformPixmap* pmd) -{ -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - Q_ASSERT(pmd->classId() == QPlatformPixmap::X11Class); - Q_ASSERT(QGLContext::currentContext()); - QX11PlatformPixmap *handle = static_cast(pmd); - if (handle->gl_surface) - glXReleaseTexImageEXT(QX11Info::display(), (GLXPixmap)handle->gl_surface, GLX_FRONT_LEFT_EXT); -#endif -} - -QT_END_NAMESPACE diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp deleted file mode 100644 index e8520414d6..0000000000 --- a/src/opengl/qgl_x11egl.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgl.h" -#include -#include -#include -#include -#include "qgl_egl_p.h" -#include "qcolormap.h" -#include -#include - - -QT_BEGIN_NAMESPACE - - -/* - QGLTemporaryContext implementation -*/ - -class QGLTemporaryContextPrivate -{ -public: - bool initialized; - Window window; - EGLContext context; - EGLSurface surface; - EGLDisplay display; -}; - -QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) - : d(new QGLTemporaryContextPrivate) -{ - d->initialized = false; - d->window = 0; - d->context = 0; - d->surface = 0; - int screen = 0; - - d->display = QEgl::display(); - - EGLConfig config; - int numConfigs = 0; - EGLint attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, -#ifdef QT_OPENGL_ES_2 - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, -#endif - EGL_NONE - }; - - eglChooseConfig(d->display, attribs, &config, 1, &numConfigs); - if (!numConfigs) { - qWarning("QGLTemporaryContext: No EGL configurations available."); - return; - } - - XVisualInfo visualInfo; - XVisualInfo *vi; - int numVisuals; - - visualInfo.visualid = QEgl::getCompatibleVisualId(config); - vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals); - if (!vi || numVisuals < 1) { - qWarning("QGLTemporaryContext: Unable to get X11 visual info id."); - return; - } - - XSetWindowAttributes attr; - unsigned long mask; - attr.background_pixel = 0; - attr.border_pixel = 0; - attr.colormap = XCreateColormap(X11->display, DefaultRootWindow(X11->display), vi->visual, AllocNone); - attr.event_mask = StructureNotifyMask | ExposureMask; - mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - - d->window = XCreateWindow(X11->display, RootWindow(X11->display, screen), - 0, 0, 1, 1, 0, - vi->depth, InputOutput, vi->visual, - mask, &attr); - - d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL); - - if (d->surface == EGL_NO_SURFACE) { - qWarning("QGLTemporaryContext: Error creating EGL surface."); - XFree(vi); - XDestroyWindow(X11->display, d->window); - return; - } - - EGLint contextAttribs[] = { -#ifdef QT_OPENGL_ES_2 - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; - d->context = eglCreateContext(d->display, config, 0, contextAttribs); - if (d->context != EGL_NO_CONTEXT - && eglMakeCurrent(d->display, d->surface, d->surface, d->context)) - { - d->initialized = true; - } else { - qWarning("QGLTemporaryContext: Error creating EGL context."); - eglDestroySurface(d->display, d->surface); - XDestroyWindow(X11->display, d->window); - } - XFree(vi); -} - -QGLTemporaryContext::~QGLTemporaryContext() -{ - if (d->initialized) { - eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(d->display, d->context); - eglDestroySurface(d->display, d->surface); - XDestroyWindow(X11->display, d->window); - } -} - -bool QGLFormat::hasOpenGLOverlays() -{ - return false; -} - -// Chooses the EGL config and creates the EGL context -bool QGLContext::chooseContext(const QGLContext* shareContext) -{ - Q_D(QGLContext); - - if (!device()) - return false; - - int devType = device()->devType(); - - QX11PlatformPixmap *x11PlatformPixmap = 0; - if (devType == QInternal::Pixmap) { - QPlatformPixmap *pmd = static_cast(device())->data_ptr().data(); - if (pmd->classId() == QPlatformPixmap::X11Class) - x11PlatformPixmap = static_cast(pmd); - else { - // TODO: Replace the pixmap's data with a new QX11PlatformPixmap - qWarning("WARNING: Creating a QGLContext on a QPixmap is only supported for X11 pixmap backend"); - return false; - } - } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) { - qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType); - return false; - } - - // Only create the eglContext if we don't already have one: - if (d->eglContext == 0) { - d->eglContext = new QEglContext(); - d->ownsEglContext = true; - d->eglContext->setApi(QEgl::OpenGL); - - // If the device is a widget with WA_TranslucentBackground set, make sure the glFormat - // has the alpha channel option set: - if (devType == QInternal::Widget) { - QWidget* widget = static_cast(device()); - if (widget->testAttribute(Qt::WA_TranslucentBackground)) - d->glFormat.setAlpha(true); - } - - // Construct the configuration we need for this surface. - QEglProperties configProps; - configProps.setDeviceType(devType); - configProps.setRenderableType(QEgl::OpenGL); - qt_eglproperties_set_glformat(configProps, d->glFormat); - - // Set buffer preserved for regular QWidgets, QGLWidgets are ok with either preserved or destroyed: - if ((devType == QInternal::Widget) && qobject_cast(static_cast(device())) == 0) - configProps.setValue(EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); - - if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) { - delete d->eglContext; - d->eglContext = 0; - return false; - } - - // Create a new context for the configuration. - QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0; - if (!d->eglContext->createContext(eglSharedContext)) { - delete d->eglContext; - d->eglContext = 0; - return false; - } - d->sharing = d->eglContext->isSharing(); - if (d->sharing && shareContext) - const_cast(shareContext)->d_func()->sharing = true; - } - - // Inform the higher layers about the actual format properties - qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config()); - - // Do don't create the EGLSurface for everything. - // QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface - // QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface - // QPixmap - yes, create the EGLSurface but store it in QX11PlatformPixmap::gl_surface - // QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf - - if (devType == QInternal::Widget) { - if (d->eglSurface != EGL_NO_SURFACE) - eglDestroySurface(d->eglContext->display(), d->eglSurface); - // extraWindowSurfaceCreationProps default to NULL unless were specifically set before - d->eglSurface = QEgl::createSurface(device(), d->eglContext->config(), d->extraWindowSurfaceCreationProps); - XFlush(X11->display); - setWindowCreated(true); - } - - if (x11PlatformPixmap) { - // TODO: Actually check to see if the existing surface can be re-used - if (x11PlatformPixmap->gl_surface) - eglDestroySurface(d->eglContext->display(), (EGLSurface)x11PlatformPixmap->gl_surface); - - x11PlatformPixmap->gl_surface = (void*)QEgl::createSurface(device(), d->eglContext->config()); - } - - return true; -} - -void QGLWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QGLWidget); - if (!isValid()) - return; - makeCurrent(); - if (!d->glcx->initialized()) - glInit(); - resizeGL(width(), height()); - //handle overlay -} - -const QGLContext* QGLWidget::overlayContext() const -{ - return 0; -} - -void QGLWidget::makeOverlayCurrent() -{ - //handle overlay -} - -void QGLWidget::updateOverlayGL() -{ - //handle overlay -} - -void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext) -{ - Q_D(QGLWidget); - if (context == 0) { - qWarning("QGLWidget::setContext: Cannot set null context"); - return; - } - if (!context->deviceIsPixmap() && context->device() != this) { - qWarning("QGLWidget::setContext: Context must refer to this widget"); - return; - } - - if (d->glcx) - d->glcx->doneCurrent(); - QGLContext* oldcx = d->glcx; - d->glcx = context; - - bool createFailed = false; - if (!d->glcx->isValid()) { - // Create the QGLContext here, which in turn chooses the EGL config - // and creates the EGL context: - if (!d->glcx->create(shareContext ? shareContext : oldcx)) - createFailed = true; - } - if (createFailed) { - if (deleteOldContext) - delete oldcx; - return; - } - - - d->eglSurfaceWindowId = winId(); // Remember the window id we created the surface for -} - -void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget* shareWidget) -{ - Q_Q(QGLWidget); - - initContext(context, shareWidget); - - if (q->isValid() && glcx->format().hasOverlay()) { - //no overlay - qWarning("QtOpenGL ES doesn't currently support overlays"); - } -} - -void QGLWidgetPrivate::cleanupColormaps() -{ -} - -const QGLColormap & QGLWidget::colormap() const -{ - return d_func()->cmap; -} - -void QGLWidget::setColormap(const QGLColormap &) -{ -} - -// Re-creates the EGL surface if the window ID has changed or if there isn't a surface -void QGLWidgetPrivate::recreateEglSurface() -{ - Q_Q(QGLWidget); - - Window currentId = q->winId(); - - // If the window ID has changed since the surface was created, we need to delete the - // old surface before re-creating a new one. Note: This should not be the case as the - // surface should be deleted before the old window id. - if (glcx->d_func()->eglSurface != EGL_NO_SURFACE && (currentId != eglSurfaceWindowId)) { - qWarning("EGL surface for deleted window %lx was not destroyed", uint(eglSurfaceWindowId)); - glcx->d_func()->destroyEglSurfaceForDevice(); - } - - if (glcx->d_func()->eglSurface == EGL_NO_SURFACE) { - glcx->d_func()->eglSurface = glcx->d_func()->eglContext->createSurface(q); - eglSurfaceWindowId = currentId; - } -} - - -QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key, - QGLContext::BindOptions options) -{ - Q_Q(QGLContext); - - // The EGL texture_from_pixmap has no facility to invert the y coordinate - if (!(options & QGLContext::CanFlipNativePixmapBindOption)) - return 0; - - - static bool checkedForTFP = false; - static bool haveTFP = false; - static bool checkedForEglImageTFP = false; - static bool haveEglImageTFP = false; - - - if (!checkedForEglImageTFP) { - checkedForEglImageTFP = true; - - // We need to be able to create an EGLImage from a native pixmap, which was split - // into a separate EGL extension, EGL_KHR_image_pixmap. It is possible to have - // eglCreateImageKHR & eglDestroyImageKHR without support for pixmaps, so we must - // check we have the EGLImage from pixmap functionality. - if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) { - - // Being able to create an EGLImage from a native pixmap is also pretty useless - // without the ability to bind that EGLImage as a texture, which is provided by - // the GL_OES_EGL_image extension, which we try to resolve here: - haveEglImageTFP = qt_resolve_eglimage_gl_extensions(q); - - if (haveEglImageTFP) - qDebug("Found EGL_KHR_image_pixmap & GL_OES_EGL_image extensions (preferred method)!"); - } - } - - if (!checkedForTFP) { - // Check for texture_from_pixmap egl extension - checkedForTFP = true; - if (QEgl::hasExtension("EGL_NOKIA_texture_from_pixmap") || - QEgl::hasExtension("EGL_EXT_texture_from_pixmap")) - { - qDebug("Found texture_from_pixmap EGL extension!"); - haveTFP = true; - } - } - - if (!haveTFP && !haveEglImageTFP) - return 0; - - - QX11PlatformPixmap *handle = static_cast(pixmap->data_ptr().data()); - Q_ASSERT(handle->classId() == QPlatformPixmap::X11Class); - bool hasAlpha = handle->hasAlphaChannel(); - bool pixmapHasValidSurface = false; - bool textureIsBound = false; - GLuint textureId; - glGenTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); - - if (haveTFP && handle->gl_surface && - hasAlpha == (handle->flags & QX11PlatformPixmap::GlSurfaceCreatedWithAlpha)) - { - pixmapHasValidSurface = true; - } - - // If we already have a valid EGL surface for the pixmap, we should use it - if (pixmapHasValidSurface) { - EGLBoolean success; - success = eglBindTexImage(QEgl::display(), (EGLSurface)handle->gl_surface, EGL_BACK_BUFFER); - if (success == EGL_FALSE) { - qWarning() << "eglBindTexImage() failed:" << QEgl::errorString(); - eglDestroySurface(QEgl::display(), (EGLSurface)handle->gl_surface); - handle->gl_surface = (void*)EGL_NO_SURFACE; - } else - textureIsBound = true; - } - - // If the pixmap doesn't already have a valid surface, try binding it via EGLImage - // first, as going through EGLImage should be faster and better supported: - if (!textureIsBound && haveEglImageTFP) { - EGLImageKHR eglImage; - - EGLint attribs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_NONE - }; - eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, - (EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs); - - QGLContext* ctx = q; - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage); - - GLint err = glGetError(); - if (err == GL_NO_ERROR) - textureIsBound = true; - - // Once the egl image is bound, the texture becomes a new sibling image and we can safely - // destroy the EGLImage we created for the pixmap: - if (eglImage != EGL_NO_IMAGE_KHR) - QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); - } - - if (!textureIsBound && haveTFP) { - // Check to see if the surface is still valid - if (handle->gl_surface && - hasAlpha != (handle->flags & QX11PlatformPixmap::GlSurfaceCreatedWithAlpha)) - { - // Surface is invalid! - destroyGlSurfaceForPixmap(handle); - } - - if (handle->gl_surface == 0) { - EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, - QEgl::OpenGL, - hasAlpha ? QEgl::Translucent : QEgl::NoOptions); - - handle->gl_surface = (void*)QEgl::createSurface(pixmap, config); - if (handle->gl_surface == (void*)EGL_NO_SURFACE) - return false; - } - - EGLBoolean success; - success = eglBindTexImage(QEgl::display(), (EGLSurface)handle->gl_surface, EGL_BACK_BUFFER); - if (success == EGL_FALSE) { - qWarning() << "eglBindTexImage() failed:" << QEgl::errorString(); - eglDestroySurface(QEgl::display(), (EGLSurface)handle->gl_surface); - handle->gl_surface = (void*)EGL_NO_SURFACE; - haveTFP = false; // If TFP isn't working, disable it's use - } else - textureIsBound = true; - } - - QGLTexture *texture = 0; - - if (textureIsBound) { - texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options); - handle->flags |= QX11PlatformPixmap::InvertedWhenBoundToTexture; - - // We assume the cost of bound pixmaps is zero - QGLTextureCache::instance()->insert(q, key, texture, 0); - - glBindTexture(GL_TEXTURE_2D, textureId); - } else - glDeleteTextures(1, &textureId); - - return texture; -} - - -void QGLContextPrivate::destroyGlSurfaceForPixmap(QPlatformPixmap* pmd) -{ - Q_ASSERT(pmd->classId() == QPlatformPixmap::X11Class); - QX11PlatformPixmap *handle = static_cast(pmd); - if (handle->gl_surface) { - EGLBoolean success; - success = eglDestroySurface(QEgl::display(), (EGLSurface)handle->gl_surface); - if (success == EGL_FALSE) { - qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: " - << QEgl::errorString(); - } - handle->gl_surface = 0; - } -} - -void QGLContextPrivate::unbindPixmapFromTexture(QPlatformPixmap* pmd) -{ - Q_ASSERT(pmd->classId() == QPlatformPixmap::X11Class); - QX11PlatformPixmap *handle = static_cast(pmd); - if (handle->gl_surface) { - EGLBoolean success; - success = eglReleaseTexImage(QEgl::display(), - (EGLSurface)handle->gl_surface, - EGL_BACK_BUFFER); - if (success == EGL_FALSE) { - qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: " - << QEgl::errorString(); - } - } -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp index a1ec3ef8e0..637e48d27d 100644 --- a/src/opengl/qglbuffer.cpp +++ b/src/opengl/qglbuffer.cpp @@ -245,17 +245,7 @@ QGLBuffer::UsagePattern QGLBuffer::usagePattern() const void QGLBuffer::setUsagePattern(QGLBuffer::UsagePattern value) { Q_D(QGLBuffer); -#if defined(QT_OPENGL_ES_1) - // OpenGL/ES 1.1 does not support GL_STREAM_DRAW, so use GL_STATIC_DRAW. - // OpenGL/ES 2.0 does support GL_STREAM_DRAW. - d->usagePattern = value; - if (value == StreamDraw) - d->actualUsagePattern = StaticDraw; - else - d->actualUsagePattern = value; -#else d->usagePattern = d->actualUsagePattern = value; -#endif } #undef ctx diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp index 98d2960e1b..0734f713c6 100644 --- a/src/opengl/qglextensions.cpp +++ b/src/opengl/qglextensions.cpp @@ -222,17 +222,6 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx) #endif } -#ifndef QT_NO_EGL -bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx) -{ - if (glEGLImageTargetTexture2DOES || glEGLImageTargetRenderbufferStorageOES) - return true; - glEGLImageTargetTexture2DOES = (_glEGLImageTargetTexture2DOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetTexture2DOES")); - glEGLImageTargetRenderbufferStorageOES = (_glEGLImageTargetRenderbufferStorageOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetRenderbufferStorageOES")); - return glEGLImageTargetTexture2DOES && glEGLImageTargetRenderbufferStorageOES; -} -#endif - bool qt_resolve_glsl_extensions(QGLContext *ctx) { diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index 98433c366d..2ef8a0169c 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -68,11 +68,6 @@ # define APIENTRYP * #endif -#ifndef QT_NO_EGL -// Needed for EGLImageKHR definition: -#include -#endif - #include #ifndef GL_ARB_vertex_buffer_object @@ -214,15 +209,6 @@ typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum atta // ARB_texture_compression typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); - -#ifndef QT_NO_EGL -// OES_EGL_image -// Note: We define these to take EGLImage whereas spec says they take a new GLeglImageOES -// type, which the EGL image should be cast to. -typedef void (APIENTRY *_glEGLImageTargetTexture2DOES) (GLenum, EGLImageKHR); -typedef void (APIENTRY *_glEGLImageTargetRenderbufferStorageOES) (GLenum, EGLImageKHR); -#endif - QT_BEGIN_NAMESPACE struct QGLExtensionFuncs @@ -340,12 +326,6 @@ struct QGLExtensionFuncs // Texture compression qt_glCompressedTexImage2DARB = 0; #endif - -#ifndef QT_NO_EGL - // OES_EGL_image - qt_glEGLImageTargetTexture2DOES = 0; - qt_glEGLImageTargetRenderbufferStorageOES = 0; -#endif } @@ -466,12 +446,6 @@ struct QGLExtensionFuncs // Texture compression _glCompressedTexImage2DARB qt_glCompressedTexImage2DARB; #endif - -#ifndef QT_NO_EGL - // OES_EGL_image - _glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES; - _glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES; -#endif }; @@ -880,12 +854,6 @@ struct QGLExtensionFuncs #define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB #endif -#ifndef QT_NO_EGL -// OES_EGL_image -#define glEGLImageTargetTexture2DOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetTexture2DOES -#define glEGLImageTargetRenderbufferStorageOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetRenderbufferStorageOES -#endif - extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx); bool Q_OPENGL_EXPORT qt_resolve_buffer_extensions(QGLContext *ctx); @@ -896,10 +864,6 @@ bool qt_resolve_frag_program_extensions(QGLContext *ctx); bool qt_resolve_glsl_extensions(QGLContext *ctx); -#ifndef QT_NO_EGL -Q_OPENGL_EXPORT bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx); -#endif - QT_END_NAMESPACE #endif // QGL_EXTENSIONS_P_H diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 8068410dc1..f35f6e513d 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -45,13 +45,7 @@ #include #include #include -#if !defined(QT_OPENGL_ES_1) #include -#endif - -#ifndef QT_OPENGL_ES_2 -#include -#endif #include #include @@ -306,22 +300,6 @@ GLenum QGLFramebufferObjectFormat::internalTextureFormat() const return d->internal_format; } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLFramebufferObjectFormat::setTextureTarget(QMacCompatGLenum target) -{ - detach(); - d->target = target; -} - -/*! \internal */ -void QGLFramebufferObjectFormat::setInternalTextureFormat(QMacCompatGLenum internalTextureFormat) -{ - detach(); - d->internal_format = internalTextureFormat; -} -#endif - /*! Returns true if all the options of this framebuffer object format are the same as \a other; otherwise returns false. @@ -720,8 +698,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, As of Qt 4.8, it's possible to draw into a QGLFramebufferObject using a QPainter in a separate thread. Note that OpenGL 2.0 or - OpenGL ES 2.0 is required for this to work. Also, under X11, it's - necessary to set the Qt::AA_X11InitThreads application attribute. + OpenGL ES 2.0 is required for this to work. \sa {Framebuffer Object Example} */ @@ -780,16 +757,6 @@ QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target) d->init(this, size, NoAttachment, target, DEFAULT_FORMAT); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -QGLFramebufferObject::QGLFramebufferObject(const QSize &size, QMacCompatGLenum target) - : d_ptr(new QGLFramebufferObjectPrivate) -{ - Q_D(QGLFramebufferObject); - d->init(this, size, NoAttachment, target, DEFAULT_FORMAT); -} -#endif - /*! \overload Constructs an OpenGL framebuffer object and binds a 2D GL texture @@ -832,16 +799,6 @@ QGLFramebufferObject::QGLFramebufferObject(int width, int height, const QGLFrame format.internalTextureFormat(), format.samples(), format.mipmap()); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -QGLFramebufferObject::QGLFramebufferObject(int width, int height, QMacCompatGLenum target) - : d_ptr(new QGLFramebufferObjectPrivate) -{ - Q_D(QGLFramebufferObject); - d->init(this, QSize(width, height), NoAttachment, target, DEFAULT_FORMAT); -} -#endif - /*! \overload Constructs an OpenGL framebuffer object and binds a texture to the @@ -863,17 +820,6 @@ QGLFramebufferObject::QGLFramebufferObject(int width, int height, Attachment att d->init(this, QSize(width, height), attachment, target, internal_format); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -QGLFramebufferObject::QGLFramebufferObject(int width, int height, Attachment attachment, - QMacCompatGLenum target, QMacCompatGLenum internal_format) - : d_ptr(new QGLFramebufferObjectPrivate) -{ - Q_D(QGLFramebufferObject); - d->init(this, QSize(width, height), attachment, target, internal_format); -} -#endif - /*! \overload Constructs an OpenGL framebuffer object and binds a texture to the @@ -895,17 +841,6 @@ QGLFramebufferObject::QGLFramebufferObject(const QSize &size, Attachment attachm d->init(this, size, attachment, target, internal_format); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -QGLFramebufferObject::QGLFramebufferObject(const QSize &size, Attachment attachment, - QMacCompatGLenum target, QMacCompatGLenum internal_format) - : d_ptr(new QGLFramebufferObjectPrivate) -{ - Q_D(QGLFramebufferObject); - d->init(this, size, attachment, target, internal_format); -} -#endif - /*! \fn QGLFramebufferObject::~QGLFramebufferObject() @@ -1092,13 +1027,7 @@ QImage QGLFramebufferObject::toImage() const return image; } -#if !defined(QT_OPENGL_ES_1) Q_GLOBAL_STATIC(QGLEngineThreadStorage, qt_buffer_2_engine) -#endif - -#ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QGLEngineThreadStorage, qt_buffer_engine) -#endif /*! \reimp */ QPaintEngine *QGLFramebufferObject::paintEngine() const @@ -1107,29 +1036,12 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const if (d->engine) return d->engine; -#if !defined(QT_OPENGL_ES_1) -#if !defined (QT_OPENGL_ES_2) - if (qt_gl_preferGL2Engine()) { -#endif - QPaintEngine *engine = qt_buffer_2_engine()->engine(); - if (engine->isActive() && engine->paintDevice() != this) { - d->engine = new QGL2PaintEngineEx; - return d->engine; - } - return engine; -#if !defined (QT_OPENGL_ES_2) - } -#endif -#endif - -#if !defined(QT_OPENGL_ES_2) - QPaintEngine *engine = qt_buffer_engine()->engine(); + QPaintEngine *engine = qt_buffer_2_engine()->engine(); if (engine->isActive() && engine->paintDevice() != this) { - d->engine = new QOpenGLPaintEngine; + d->engine = new QGL2PaintEngineEx; return d->engine; } return engine; -#endif } /*! @@ -1189,14 +1101,6 @@ void QGLFramebufferObject::drawTexture(const QRectF &target, GLuint textureId, G const_cast(QGLContext::currentContext())->drawTexture(target, textureId, textureTarget); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLFramebufferObject::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget) -{ - const_cast(QGLContext::currentContext())->drawTexture(target, textureId, textureTarget); -} -#endif - /*! \since 4.4 @@ -1212,14 +1116,6 @@ void QGLFramebufferObject::drawTexture(const QPointF &point, GLuint textureId, G const_cast(QGLContext::currentContext())->drawTexture(point, textureId, textureTarget); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLFramebufferObject::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget) -{ - const_cast(QGLContext::currentContext())->drawTexture(point, textureId, textureTarget); -} -#endif - /*! \reimp */ int QGLFramebufferObject::metric(PaintDeviceMetric metric) const { diff --git a/src/opengl/qglframebufferobject.h b/src/opengl/qglframebufferobject.h index d5e5c482fb..817aecd9b7 100644 --- a/src/opengl/qglframebufferobject.h +++ b/src/opengl/qglframebufferobject.h @@ -81,16 +81,6 @@ public: QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format); QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format); -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS - QGLFramebufferObject(const QSize &size, QMacCompatGLenum target = GL_TEXTURE_2D); - QGLFramebufferObject(int width, int height, QMacCompatGLenum target = GL_TEXTURE_2D); - - QGLFramebufferObject(const QSize &size, Attachment attachment, - QMacCompatGLenum target = GL_TEXTURE_2D, QMacCompatGLenum internal_format = GL_RGBA8); - QGLFramebufferObject(int width, int height, Attachment attachment, - QMacCompatGLenum target = GL_TEXTURE_2D, QMacCompatGLenum internal_format = GL_RGBA8); -#endif - virtual ~QGLFramebufferObject(); QGLFramebufferObjectFormat format() const; @@ -114,10 +104,6 @@ public: void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D); void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D); -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS - void drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D); - void drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D); -#endif static bool hasOpenGLFramebufferBlit(); static void blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect, @@ -160,11 +146,6 @@ public: void setInternalTextureFormat(GLenum internalTextureFormat); GLenum internalTextureFormat() const; -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS - void setTextureTarget(QMacCompatGLenum target); - void setInternalTextureFormat(QMacCompatGLenum internalTextureFormat); -#endif - bool operator==(const QGLFramebufferObjectFormat& other) const; bool operator!=(const QGLFramebufferObjectFormat& other) const; diff --git a/src/opengl/qglfunctions.h b/src/opengl/qglfunctions.h index 2bb6119b29..e789d4020d 100644 --- a/src/opengl/qglfunctions.h +++ b/src/opengl/qglfunctions.h @@ -419,7 +419,7 @@ struct QGLFunctionsPrivate inline void QGLFunctions::glActiveTexture(GLenum texture) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glActiveTexture(texture); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -449,7 +449,7 @@ inline void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, con inline void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glBindBuffer(target, buffer); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -519,7 +519,7 @@ inline void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLen inline void QGLFunctions::glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glBufferData(target, size, data, usage); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -529,7 +529,7 @@ inline void QGLFunctions::glBufferData(GLenum target, qgl_GLsizeiptr size, const inline void QGLFunctions::glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glBufferSubData(target, offset, size, data); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -568,7 +568,7 @@ inline void QGLFunctions::glCompileShader(GLuint shader) inline void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -578,7 +578,7 @@ inline void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLe inline void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -608,7 +608,7 @@ inline GLuint QGLFunctions::glCreateShader(GLenum type) inline void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glDeleteBuffers(n, buffers); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -717,7 +717,7 @@ inline void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachmen inline void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glGenBuffers(n, buffers); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -947,7 +947,7 @@ inline void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, inline GLboolean QGLFunctions::glIsBuffer(GLuint buffer) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) return ::glIsBuffer(buffer); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); @@ -1027,7 +1027,7 @@ inline void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalfo inline void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert) { -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) ::glSampleCoverage(value, invert); #else Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 45e7cdd875..8116b798ca 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -81,8 +81,7 @@ As of Qt 4.8, it's possible to render into a QGLPixelBuffer using a QPainter in a separate thread. Note that OpenGL 2.0 or OpenGL ES - 2.0 is required for this to work. Also, under X11, it's necessary - to set the Qt::AA_X11InitThreads application attribute. + 2.0 is required for this to work. Pbuffers are provided by the OpenGL \c pbuffer extension; call hasOpenGLPbuffer() to find out if the system provides pbuffers. @@ -92,19 +91,13 @@ #include -#if !defined(QT_OPENGL_ES_1) #include -#endif #include #include #include #include -#ifndef QT_OPENGL_ES_2 -#include -#endif - QT_BEGIN_NAMESPACE #if !defined(QT_OPENGL_ES_2) @@ -149,20 +142,6 @@ void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &form glDevice.setPBuffer(q); qctx->d_func()->paintDevice = q; qctx->d_func()->valid = true; -#if defined(Q_WS_WIN) && !defined(QT_OPENGL_ES) - qctx->d_func()->dc = dc; - qctx->d_func()->rc = ctx; -#elif (defined(Q_WS_X11) && defined(QT_NO_EGL)) - qctx->d_func()->cx = ctx; - qctx->d_func()->pbuf = (void *) pbuf; - qctx->d_func()->vi = 0; -#elif defined(Q_WS_MAC) - qctx->d_func()->cx = ctx; - qctx->d_func()->vi = 0; -#elif !defined(QT_NO_EGL) - qctx->d_func()->eglContext = ctx; - qctx->d_func()->eglSurface = pbuf; -#endif } } @@ -261,6 +240,8 @@ bool QGLPixelBuffer::doneCurrent() } /*! + \fn GLuint QGLPixelBuffer::generateDynamicTexture() const + Generates and binds a 2D GL texture that is the same size as the pbuffer, and returns the texture's ID. This can be used in conjunction with bindToDynamicTexture() and @@ -269,20 +250,6 @@ bool QGLPixelBuffer::doneCurrent() \sa size() */ -#if (defined(Q_WS_X11) || defined(Q_WS_WIN)) && defined(QT_NO_EGL) -GLuint QGLPixelBuffer::generateDynamicTexture() const -{ - Q_D(const QGLPixelBuffer); - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, d->req_size.width(), d->req_size.height(), 0, GL_RGBA, GL_FLOAT, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - return texture; -} -#endif - /*! \fn bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id) Binds the texture specified by \a texture_id to this pbuffer. @@ -353,13 +320,6 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const #endif } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -void QGLPixelBuffer::updateDynamicTexture(QMacCompatGLuint texture_id) const -{ - updateDynamicTexture(GLuint(texture_id)); -} -#endif - /*! Returns the size of the pbuffer. */ @@ -402,27 +362,12 @@ bool QGLPixelBuffer::isValid() const return !d->invalid; } -#if !defined(QT_OPENGL_ES_1) Q_GLOBAL_STATIC(QGLEngineThreadStorage, qt_buffer_2_engine) -#endif - -#ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QGLEngineThreadStorage, qt_buffer_engine) -#endif /*! \reimp */ QPaintEngine *QGLPixelBuffer::paintEngine() const { -#if defined(QT_OPENGL_ES_1) - return qt_buffer_engine()->engine(); -#elif defined(QT_OPENGL_ES_2) return qt_buffer_2_engine()->engine(); -#else - if (qt_gl_preferGL2Engine()) - return qt_buffer_2_engine()->engine(); - else - return qt_buffer_engine()->engine(); -#endif } /*! \reimp */ @@ -493,15 +438,6 @@ GLuint QGLPixelBuffer::bindTexture(const QImage &image, GLenum target) #endif } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -GLuint QGLPixelBuffer::bindTexture(const QImage &image, QMacCompatGLenum target) -{ - Q_D(QGLPixelBuffer); - return d->qctx->bindTexture(image, target, QMacCompatGLint(GL_RGBA8)); -} -#endif - /*! \overload Generates and binds a 2D GL texture based on \a pixmap. @@ -520,15 +456,6 @@ GLuint QGLPixelBuffer::bindTexture(const QPixmap &pixmap, GLenum target) #endif } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -GLuint QGLPixelBuffer::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target) -{ - Q_D(QGLPixelBuffer); - return d->qctx->bindTexture(pixmap, target, QMacCompatGLint(GL_RGBA8)); -} -#endif - /*! \overload Reads the DirectDrawSurface (DDS) compressed file \a fileName and @@ -555,15 +482,6 @@ void QGLPixelBuffer::deleteTexture(GLuint texture_id) d->qctx->deleteTexture(texture_id); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLPixelBuffer::deleteTexture(QMacCompatGLuint texture_id) -{ - Q_D(QGLPixelBuffer); - d->qctx->deleteTexture(texture_id); -} -#endif - /*! \since 4.4 @@ -579,15 +497,6 @@ void QGLPixelBuffer::drawTexture(const QRectF &target, GLuint textureId, GLenum d->qctx->drawTexture(target, textureId, textureTarget); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLPixelBuffer::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget) -{ - Q_D(QGLPixelBuffer); - d->qctx->drawTexture(target, textureId, textureTarget); -} -#endif - /*! \since 4.4 @@ -602,15 +511,6 @@ void QGLPixelBuffer::drawTexture(const QPointF &point, GLuint textureId, GLenum d->qctx->drawTexture(point, textureId, textureTarget); } -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLPixelBuffer::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget) -{ - Q_D(QGLPixelBuffer); - d->qctx->drawTexture(point, textureId, textureTarget); -} -#endif - /*! Returns the format of the pbuffer. The format may be different from the one that was requested. diff --git a/src/opengl/qglpixelbuffer.h b/src/opengl/qglpixelbuffer.h index 1cffb0ec0b..0c7ad38237 100644 --- a/src/opengl/qglpixelbuffer.h +++ b/src/opengl/qglpixelbuffer.h @@ -80,18 +80,6 @@ public: void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D); void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D); -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS - bool bindToDynamicTexture(QMacCompatGLuint texture); - void updateDynamicTexture(QMacCompatGLuint texture_id) const; - GLuint bindTexture(const QImage &image, QMacCompatGLenum target = GL_TEXTURE_2D); - GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum target = GL_TEXTURE_2D); - - void drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D); - void drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D); - - void deleteTexture(QMacCompatGLuint texture_id); -#endif - QSize size() const; Qt::HANDLE handle() const; QImage toImage() const; diff --git a/src/opengl/qglpixelbuffer_egl.cpp b/src/opengl/qglpixelbuffer_egl.cpp deleted file mode 100644 index 64d032799a..0000000000 --- a/src/opengl/qglpixelbuffer_egl.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "qglpixelbuffer.h" -#include "qglpixelbuffer_p.h" -#include "qgl_egl_p.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -#ifdef EGL_BIND_TO_TEXTURE_RGBA -#define QGL_RENDER_TEXTURE 1 -#else -#define QGL_RENDER_TEXTURE 0 -#endif - -bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) -{ - // Create the EGL context. - ctx = new QEglContext(); - ctx->setApi(QEgl::OpenGL); - - // Find the shared context. - QEglContext *shareContext = 0; - if (shareWidget && shareWidget->d_func()->glcx) - shareContext = shareWidget->d_func()->glcx->d_func()->eglContext; - - // Choose an appropriate configuration. We use the best format - // we can find, even if it is greater than the requested format. - // We try for a pbuffer that is capable of texture rendering if possible. - textureFormat = EGL_NONE; - if (shareContext) { - // Use the same configuration as the widget we are sharing with. - ctx->setConfig(shareContext->config()); -#if QGL_RENDER_TEXTURE - if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGBA) == EGL_TRUE) - textureFormat = EGL_TEXTURE_RGBA; - else if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGB) == EGL_TRUE) - textureFormat = EGL_TEXTURE_RGB; -#endif - } else { - QEglProperties configProps; - qt_eglproperties_set_glformat(configProps, f); - configProps.setDeviceType(QInternal::Pbuffer); - configProps.setRenderableType(ctx->api()); - bool ok = false; -#if QGL_RENDER_TEXTURE - textureFormat = EGL_TEXTURE_RGBA; - configProps.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); - ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat); - if (!ok) { - // Try again with RGB texture rendering. - textureFormat = EGL_TEXTURE_RGB; - configProps.removeValue(EGL_BIND_TO_TEXTURE_RGBA); - configProps.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); - ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat); - if (!ok) { - // One last try for a pbuffer with no texture rendering. - configProps.removeValue(EGL_BIND_TO_TEXTURE_RGB); - textureFormat = EGL_NONE; - } - } -#endif - if (!ok) { - if (!ctx->chooseConfig(configProps, QEgl::BestPixelFormat)) { - delete ctx; - ctx = 0; - return false; - } - } - } - - // Retrieve the actual format properties. - qt_glformat_from_eglconfig(format, ctx->config()); - - // Create the attributes needed for the pbuffer. - QEglProperties attribs; - attribs.setValue(EGL_WIDTH, size.width()); - attribs.setValue(EGL_HEIGHT, size.height()); -#if QGL_RENDER_TEXTURE - if (textureFormat != EGL_NONE) { - attribs.setValue(EGL_TEXTURE_FORMAT, textureFormat); - attribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D); - } -#endif - - // Create the pbuffer surface. - pbuf = eglCreatePbufferSurface(ctx->display(), ctx->config(), attribs.properties()); -#if QGL_RENDER_TEXTURE - if (pbuf == EGL_NO_SURFACE && textureFormat != EGL_NONE) { - // Try again with texture rendering disabled. - textureFormat = EGL_NONE; - attribs.removeValue(EGL_TEXTURE_FORMAT); - attribs.removeValue(EGL_TEXTURE_TARGET); - pbuf = eglCreatePbufferSurface(ctx->display(), ctx->config(), attribs.properties()); - } -#endif - if (pbuf == EGL_NO_SURFACE) { - qWarning() << "QGLPixelBufferPrivate::init(): Unable to create EGL pbuffer surface:" << QEgl::errorString(); - return false; - } - - // Create a new context for the configuration. - if (!ctx->createContext(shareContext)) { - delete ctx; - ctx = 0; - return false; - } - - return true; -} - -bool QGLPixelBufferPrivate::cleanup() -{ - // No need to destroy "pbuf" here - it is done in QGLContext::reset(). - return true; -} - -bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id) -{ -#if QGL_RENDER_TEXTURE - Q_D(QGLPixelBuffer); - if (d->invalid || d->textureFormat == EGL_NONE || !d->ctx) - return false; - glBindTexture(GL_TEXTURE_2D, texture_id); - return eglBindTexImage(d->ctx->display(), d->pbuf, EGL_BACK_BUFFER); -#else - Q_UNUSED(texture_id); - return false; -#endif -} - -void QGLPixelBuffer::releaseFromDynamicTexture() -{ -#if QGL_RENDER_TEXTURE - Q_D(QGLPixelBuffer); - if (d->invalid || d->textureFormat == EGL_NONE || !d->ctx) - return; - eglReleaseTexImage(d->ctx->display(), d->pbuf, EGL_BACK_BUFFER); -#endif -} - - -GLuint QGLPixelBuffer::generateDynamicTexture() const -{ -#if QGL_RENDER_TEXTURE - Q_D(const QGLPixelBuffer); - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - if (d->textureFormat == EGL_TEXTURE_RGB) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, d->req_size.width(), d->req_size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - return texture; -#else - return 0; -#endif -} - -bool QGLPixelBuffer::hasOpenGLPbuffers() -{ - // See if we have at least 1 configuration that matches the default format. - EGLDisplay dpy = QEgl::display(); - if (dpy == EGL_NO_DISPLAY) - return false; - QEglProperties configProps; - qt_eglproperties_set_glformat(configProps, QGLFormat::defaultFormat()); - configProps.setDeviceType(QInternal::Pbuffer); - configProps.setRenderableType(QEgl::OpenGL); - do { - EGLConfig cfg = 0; - EGLint matching = 0; - if (eglChooseConfig(dpy, configProps.properties(), - &cfg, 1, &matching) && matching > 0) - return true; - } while (configProps.reduceConfiguration()); - return false; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglpixelbuffer_mac.mm b/src/opengl/qglpixelbuffer_mac.mm deleted file mode 100644 index b364209b95..0000000000 --- a/src/opengl/qglpixelbuffer_mac.mm +++ /dev/null @@ -1,331 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglpixelbuffer.h" -#include "qglpixelbuffer_p.h" - -#ifndef QT_MAC_USE_COCOA -#include -#endif - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -#ifndef GL_TEXTURE_RECTANGLE_EXT -#define GL_TEXTURE_RECTANGLE_EXT 0x84F5 -#endif - -static int nearest_gl_texture_size(int v) -{ - int n = 0, last = 0; - for (int s = 0; s < 32; ++s) { - if (((v>>s) & 1) == 1) { - ++n; - last = s; - } - } - if (n > 1) - return 1 << (last+1); - return 1 << last; -} - -bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) -{ -#ifdef QT_MAC_USE_COCOA - Q_Q(QGLPixelBuffer); - // create a dummy context - QGLContext context(f, q); - context.create(shareWidget ? shareWidget->context() : 0); - - if (context.isSharing()) - share_ctx = shareWidget->context()->d_func()->cx; - - // steal the NSOpenGLContext and update the format - ctx = context.d_func()->cx; - context.d_func()->cx = 0; - // d->cx will be set to ctx later in - // QGLPixelBufferPrivate::common_init, so we need to retain it: - [static_cast(ctx) retain]; - - format = context.format(); - - GLenum target = GL_TEXTURE_2D; - - if ((QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle) - && (size.width() != nearest_gl_texture_size(size.width()) - || size.height() != nearest_gl_texture_size(size.height()))) - { - target = GL_TEXTURE_RECTANGLE_EXT; - } - - pbuf = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target - textureInternalFormat:GL_RGBA - textureMaxMipMapLevel:0 - pixelsWide:size.width() - pixelsHigh:size.height()]; - if (!pbuf) { - qWarning("QGLPixelBuffer: Cannot create a pbuffer"); - return false; - } - - [static_cast(ctx) setPixelBuffer:static_cast(pbuf) - cubeMapFace:0 - mipMapLevel:0 - currentVirtualScreen:0]; - return true; -#else - GLint attribs[40], i=0; - attribs[i++] = AGL_RGBA; - attribs[i++] = AGL_BUFFER_SIZE; - attribs[i++] = 32; - attribs[i++] = AGL_LEVEL; - attribs[i++] = f.plane(); - if (f.redBufferSize() != -1) { - attribs[i++] = AGL_RED_SIZE; - attribs[i++] = f.redBufferSize(); - } - if (f.greenBufferSize() != -1) { - attribs[i++] = AGL_GREEN_SIZE; - attribs[i++] = f.greenBufferSize(); - } - if (f.blueBufferSize() != -1) { - attribs[i++] = AGL_BLUE_SIZE; - attribs[i++] = f.blueBufferSize(); - } - if (f.stereo()) - attribs[i++] = AGL_STEREO; - if (f.alpha()) { - attribs[i++] = AGL_ALPHA_SIZE; - attribs[i++] = f.alphaBufferSize() == -1 ? 8 : f.alphaBufferSize(); - } - if (f.stencil()) { - attribs[i++] = AGL_STENCIL_SIZE; - attribs[i++] = f.stencilBufferSize() == -1 ? 8 : f.stencilBufferSize(); - } - if (f.depth()) { - attribs[i++] = AGL_DEPTH_SIZE; - attribs[i++] = f.depthBufferSize() == -1 ? 32 : f.depthBufferSize(); - } - if (f.accum()) { - attribs[i++] = AGL_ACCUM_RED_SIZE; - attribs[i++] = f.accumBufferSize() == -1 ? 16 : f.accumBufferSize(); - attribs[i++] = AGL_ACCUM_BLUE_SIZE; - attribs[i++] = f.accumBufferSize() == -1 ? 16 : f.accumBufferSize(); - attribs[i++] = AGL_ACCUM_GREEN_SIZE; - attribs[i++] = f.accumBufferSize() == -1 ? 16 : f.accumBufferSize(); - attribs[i++] = AGL_ACCUM_ALPHA_SIZE; - attribs[i++] = f.accumBufferSize() == -1 ? 16 : f.accumBufferSize(); - } - - if (f.sampleBuffers()) { - attribs[i++] = AGL_SAMPLE_BUFFERS_ARB; - attribs[i++] = 1; - attribs[i++] = AGL_SAMPLES_ARB; - attribs[i++] = f.samples() == -1 ? 4 : f.samples(); - } - attribs[i] = AGL_NONE; - - AGLPixelFormat format = aglChoosePixelFormat(0, 0, attribs); - if (!format) { - qWarning("QGLPixelBuffer: Unable to find a pixel format (AGL error %d).", - (int) aglGetError()); - return false; - } - - GLint res; - aglDescribePixelFormat(format, AGL_LEVEL, &res); - this->format.setPlane(res); - aglDescribePixelFormat(format, AGL_DOUBLEBUFFER, &res); - this->format.setDoubleBuffer(res); - aglDescribePixelFormat(format, AGL_DEPTH_SIZE, &res); - this->format.setDepth(res); - if (this->format.depth()) - this->format.setDepthBufferSize(res); - aglDescribePixelFormat(format, AGL_RGBA, &res); - this->format.setRgba(res); - aglDescribePixelFormat(format, AGL_RED_SIZE, &res); - this->format.setRedBufferSize(res); - aglDescribePixelFormat(format, AGL_GREEN_SIZE, &res); - this->format.setGreenBufferSize(res); - aglDescribePixelFormat(format, AGL_BLUE_SIZE, &res); - this->format.setBlueBufferSize(res); - aglDescribePixelFormat(format, AGL_ALPHA_SIZE, &res); - this->format.setAlpha(res); - if (this->format.alpha()) - this->format.setAlphaBufferSize(res); - aglDescribePixelFormat(format, AGL_ACCUM_RED_SIZE, &res); - this->format.setAccum(res); - if (this->format.accum()) - this->format.setAccumBufferSize(res); - aglDescribePixelFormat(format, AGL_STENCIL_SIZE, &res); - this->format.setStencil(res); - if (this->format.stencil()) - this->format.setStencilBufferSize(res); - aglDescribePixelFormat(format, AGL_STEREO, &res); - this->format.setStereo(res); - aglDescribePixelFormat(format, AGL_SAMPLE_BUFFERS_ARB, &res); - this->format.setSampleBuffers(res); - if (this->format.sampleBuffers()) { - aglDescribePixelFormat(format, AGL_SAMPLES_ARB, &res); - this->format.setSamples(res); - } - - AGLContext share = 0; - if (shareWidget) - share = share_ctx = static_cast(shareWidget->d_func()->glcx->d_func()->cx); - ctx = aglCreateContext(format, share); - if (!ctx) { - qWarning("QGLPixelBuffer: Unable to create a context (AGL error %d).", - (int) aglGetError()); - return false; - } - - GLenum target = GL_TEXTURE_2D; - - if ((QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle) - && (size.width() != nearest_gl_texture_size(size.width()) - || size.height() != nearest_gl_texture_size(size.height()))) - { - target = GL_TEXTURE_RECTANGLE_EXT; - } - - if (!aglCreatePBuffer(size.width(), size.height(), target, GL_RGBA, 0, &pbuf)) { - qWarning("QGLPixelBuffer: Unable to create a pbuffer (AGL error %d).", - (int) aglGetError()); - return false; - } - - if (!aglSetPBuffer(ctx, pbuf, 0, 0, 0)) { - qWarning("QGLPixelBuffer: Unable to set pbuffer (AGL error %d).", - (int) aglGetError()); - return false; - } - - aglDestroyPixelFormat(format); - return true; - -#endif -} - -bool QGLPixelBufferPrivate::cleanup() -{ -#ifdef QT_MAC_USE_COCOA - [static_cast(pbuf) release]; - pbuf = 0; - [static_cast(ctx) release]; - ctx = 0; -#else - aglDestroyPBuffer(pbuf); -#endif - return true; -} - -bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id) -{ - Q_D(QGLPixelBuffer); - if (d->invalid || !d->share_ctx) - return false; - -#ifdef QT_MAC_USE_COCOA - NSOpenGLContext *oldContext = [NSOpenGLContext currentContext]; - if (d->share_ctx != oldContext) - [static_cast(d->share_ctx) makeCurrentContext]; - glBindTexture(GL_TEXTURE_2D, texture_id); - [static_cast(d->share_ctx) - setTextureImageToPixelBuffer:static_cast(d->pbuf) - colorBuffer:GL_FRONT]; - if (oldContext && oldContext != d->share_ctx) - [oldContext makeCurrentContext]; - return true; -#else - aglSetCurrentContext(d->share_ctx); - glBindTexture(GL_TEXTURE_2D, texture_id); - aglTexImagePBuffer(d->share_ctx, d->pbuf, GL_FRONT); - return true; -#endif -} - -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -bool QGLPixelBuffer::bindToDynamicTexture(QMacCompatGLuint texture_id) -{ - return bindToDynamicTexture(GLuint(texture_id)); -} -#endif - -void QGLPixelBuffer::releaseFromDynamicTexture() -{ -} - -GLuint QGLPixelBuffer::generateDynamicTexture() const -{ -#ifdef QT_MAC_USE_COCOA - Q_D(const QGLPixelBuffer); - NSOpenGLContext *oldContext = [NSOpenGLContext currentContext]; - if (d->share_ctx != oldContext) - [static_cast(d->share_ctx) makeCurrentContext]; - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - if (oldContext && oldContext != d->share_ctx) - [oldContext makeCurrentContext]; - return texture; -#else - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - return texture; -#endif -} - -bool QGLPixelBuffer::hasOpenGLPbuffers() -{ - return true; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h index 05d8823909..05e161b7ef 100644 --- a/src/opengl/qglpixelbuffer_p.h +++ b/src/opengl/qglpixelbuffer_p.h @@ -59,77 +59,6 @@ QT_BEGIN_INCLUDE_NAMESPACE #include "QtOpenGL/qglpixelbuffer.h" #include #include - -#if defined(Q_WS_X11) && defined(QT_NO_EGL) -#include - -// The below is needed to for compilation on HPUX, due to broken GLX -// headers. Some of the systems define GLX_VERSION_1_3 without -// defining the GLXFBConfig structure, which is wrong. -#if defined (Q_OS_HPUX) && defined(QT_DEFINE_GLXFBCONFIG_STRUCT) -typedef unsigned long GLXPbuffer; - -struct GLXFBConfig { - int visualType; - int transparentType; - /* colors are floats scaled to ints */ - int transparentRed, transparentGreen, transparentBlue, transparentAlpha; - int transparentIndex; - - int visualCaveat; - - int associatedVisualId; - int screen; - - int drawableType; - int renderType; - - int maxPbufferWidth, maxPbufferHeight, maxPbufferPixels; - int optimalPbufferWidth, optimalPbufferHeight; /* for SGIX_pbuffer */ - - int visualSelectGroup; /* visuals grouped by select priority */ - - unsigned int id; - - GLboolean rgbMode; - GLboolean colorIndexMode; - GLboolean doubleBufferMode; - GLboolean stereoMode; - GLboolean haveAccumBuffer; - GLboolean haveDepthBuffer; - GLboolean haveStencilBuffer; - - /* The number of bits present in various buffers */ - GLint accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits; - GLint depthBits; - GLint stencilBits; - GLint indexBits; - GLint redBits, greenBits, blueBits, alphaBits; - GLuint redMask, greenMask, blueMask, alphaMask; - - GLuint multiSampleSize; /* Number of samples per pixel (0 if no ms) */ - - GLuint nMultiSampleBuffers; /* Number of available ms buffers */ - GLint maxAuxBuffers; - - /* frame buffer level */ - GLint level; - - /* color ranges (for SGI_color_range) */ - GLboolean extendedRange; - GLdouble minRed, maxRed; - GLdouble minGreen, maxGreen; - GLdouble minBlue, maxBlue; - GLdouble minAlpha, maxAlpha; -}; - -#endif // Q_OS_HPUX - -#elif defined(Q_OS_WIN) -DECLARE_HANDLE(HPBUFFERARB); -#elif !defined(QT_NO_EGL) -#include -#endif QT_END_INCLUDE_NAMESPACE class QEglContext; @@ -152,11 +81,6 @@ class QGLPixelBufferPrivate { public: QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(0), pbuf(0), ctx(0) { -#ifdef Q_WS_WIN - dc = 0; -#elif defined(Q_WS_MACX) - share_ctx = 0; -#endif } bool init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget); void common_init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget); @@ -172,36 +96,9 @@ public: QPointer req_shareWidget; QSize req_size; -#if defined(Q_WS_X11) && defined(QT_NO_EGL) - GLXPbuffer pbuf; - GLXContext ctx; -#elif defined(Q_WS_WIN) - HDC dc; - bool has_render_texture :1; -#if !defined(QT_OPENGL_ES) - HPBUFFERARB pbuf; - HGLRC ctx; -#endif -#elif defined(Q_WS_MACX) -# ifdef QT_MAC_USE_COCOA - void *pbuf; - void *ctx; - void *share_ctx; -# else - AGLPbuffer pbuf; - AGLContext ctx; - AGLContext share_ctx; -# endif -#endif -#ifndef QT_NO_EGL - EGLSurface pbuf; - QEglContext *ctx; - int textureFormat; -#elif defined(Q_WS_QPA) //stubs void *pbuf; void *ctx; -#endif }; QT_END_NAMESPACE diff --git a/src/opengl/qglpixelbuffer_win.cpp b/src/opengl/qglpixelbuffer_win.cpp deleted file mode 100644 index 80ce99219e..0000000000 --- a/src/opengl/qglpixelbuffer_win.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include - -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -/* WGL_WGLEXT_PROTOTYPES */ -typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); -typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); -typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); -typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); -typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); -typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); -typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); -typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); -typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); -typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int * piAttribList); - -#ifndef WGL_ARB_pbuffer -#define WGL_DRAW_TO_PBUFFER_ARB 0x202D -#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E -#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 -#define WGL_PBUFFER_LARGEST_ARB 0x2033 -#define WGL_PBUFFER_WIDTH_ARB 0x2034 -#define WGL_PBUFFER_HEIGHT_ARB 0x2035 -#define WGL_PBUFFER_LOST_ARB 0x2036 -#endif - -#ifndef WGL_ARB_pixel_format -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_DRAW_TO_BITMAP_ARB 0x2002 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NEED_PALETTE_ARB 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 -#define WGL_SWAP_METHOD_ARB 0x2007 -#define WGL_NUMBER_OVERLAYS_ARB 0x2008 -#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 -#define WGL_TRANSPARENT_ARB 0x200A -#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 -#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 -#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 -#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A -#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B -#define WGL_SHARE_DEPTH_ARB 0x200C -#define WGL_SHARE_STENCIL_ARB 0x200D -#define WGL_SHARE_ACCUM_ARB 0x200E -#define WGL_SUPPORT_GDI_ARB 0x200F -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_STEREO_ARB 0x2012 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201A -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_ALPHA_SHIFT_ARB 0x201C -#define WGL_ACCUM_BITS_ARB 0x201D -#define WGL_ACCUM_RED_BITS_ARB 0x201E -#define WGL_ACCUM_GREEN_BITS_ARB 0x201F -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_GENERIC_ACCELERATION_ARB 0x2026 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_SWAP_EXCHANGE_ARB 0x2028 -#define WGL_SWAP_COPY_ARB 0x2029 -#define WGL_SWAP_UNDEFINED_ARB 0x202A -#define WGL_TYPE_RGBA_ARB 0x202B -#define WGL_TYPE_COLORINDEX_ARB 0x202C -#endif - -#ifndef WGL_ARB_render_texture -#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 -#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 -#define WGL_TEXTURE_FORMAT_ARB 0x2072 -#define WGL_TEXTURE_TARGET_ARB 0x2073 -#define WGL_MIPMAP_TEXTURE_ARB 0x2074 -#define WGL_TEXTURE_RGB_ARB 0x2075 -#define WGL_TEXTURE_RGBA_ARB 0x2076 -#define WGL_NO_TEXTURE_ARB 0x2077 -#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 -#define WGL_TEXTURE_1D_ARB 0x2079 -#define WGL_TEXTURE_2D_ARB 0x207A -#define WGL_MIPMAP_LEVEL_ARB 0x207B -#define WGL_CUBE_MAP_FACE_ARB 0x207C -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 -#define WGL_FRONT_LEFT_ARB 0x2083 -#define WGL_FRONT_RIGHT_ARB 0x2084 -#define WGL_BACK_LEFT_ARB 0x2085 -#define WGL_BACK_RIGHT_ARB 0x2086 -#define WGL_AUX0_ARB 0x2087 -#define WGL_AUX1_ARB 0x2088 -#define WGL_AUX2_ARB 0x2089 -#define WGL_AUX3_ARB 0x208A -#define WGL_AUX4_ARB 0x208B -#define WGL_AUX5_ARB 0x208C -#define WGL_AUX6_ARB 0x208D -#define WGL_AUX7_ARB 0x208E -#define WGL_AUX8_ARB 0x208F -#define WGL_AUX9_ARB 0x2090 -#endif - -#ifndef WGL_FLOAT_COMPONENTS_NV -#define WGL_FLOAT_COMPONENTS_NV 0x20B0 -#endif - -#ifndef WGL_ARB_multisample -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 -#endif - -#ifndef GL_SAMPLES_ARB -#define GL_SAMPLES_ARB 0x80A9 -#endif - -QGLFormat pfiToQGLFormat(HDC hdc, int pfi); - -static void qt_format_to_attrib_list(bool has_render_texture, const QGLFormat &f, int attribs[]) -{ - int i = 0; - attribs[i++] = WGL_SUPPORT_OPENGL_ARB; - attribs[i++] = TRUE; - attribs[i++] = WGL_DRAW_TO_PBUFFER_ARB; - attribs[i++] = TRUE; - - if (has_render_texture) { - attribs[i++] = WGL_BIND_TO_TEXTURE_RGBA_ARB; - attribs[i++] = TRUE; - } - - attribs[i++] = WGL_COLOR_BITS_ARB; - attribs[i++] = 32; - attribs[i++] = WGL_DOUBLE_BUFFER_ARB; - attribs[i++] = FALSE; - - if (f.stereo()) { - attribs[i++] = WGL_STEREO_ARB; - attribs[i++] = TRUE; - } - if (f.depth()) { - attribs[i++] = WGL_DEPTH_BITS_ARB; - attribs[i++] = f.depthBufferSize() == -1 ? 24 : f.depthBufferSize(); - } - if (f.redBufferSize() != -1) { - attribs[i++] = WGL_RED_BITS_ARB; - attribs[i++] = f.redBufferSize(); - } - if (f.greenBufferSize() != -1) { - attribs[i++] = WGL_GREEN_BITS_ARB; - attribs[i++] = f.greenBufferSize(); - } - if (f.blueBufferSize() != -1) { - attribs[i++] = WGL_BLUE_BITS_ARB; - attribs[i++] = f.blueBufferSize(); - } - if (f.alpha()) { - attribs[i++] = WGL_ALPHA_BITS_ARB; - attribs[i++] = f.alphaBufferSize() == -1 ? 8 : f.alphaBufferSize(); - } - if (f.accum()) { - attribs[i++] = WGL_ACCUM_BITS_ARB; - attribs[i++] = f.accumBufferSize() == -1 ? 16 : f.accumBufferSize(); - } - if (f.stencil()) { - attribs[i++] = WGL_STENCIL_BITS_ARB; - attribs[i++] = f.stencilBufferSize() == -1 ? 8 : f.stencilBufferSize(); - } - if ((f.redBufferSize() > 8 || f.greenBufferSize() > 8 - || f.blueBufferSize() > 8 || f.alphaBufferSize() > 8) - && (QGLExtensions::glExtensions() & QGLExtensions::NVFloatBuffer)) - { - attribs[i++] = WGL_FLOAT_COMPONENTS_NV; - attribs[i++] = TRUE; - } - if (f.sampleBuffers()) { - attribs[i++] = WGL_SAMPLE_BUFFERS_ARB; - attribs[i++] = 1; - attribs[i++] = WGL_SAMPLES_ARB; - attribs[i++] = f.samples() == -1 ? 16 : f.samples(); - } - attribs[i] = 0; -} - -bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) -{ - QGLTemporaryContext tempContext; - - PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = - (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB"); - PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = - (PFNWGLGETPBUFFERDCARBPROC) wglGetProcAddress("wglGetPbufferDCARB"); - PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = - (PFNWGLQUERYPBUFFERARBPROC) wglGetProcAddress("wglQueryPbufferARB"); - PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = - (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB"); - - if (!wglCreatePbufferARB) // assumes that if one can be resolved, all of them can - return false; - - dc = wglGetCurrentDC(); - Q_ASSERT(dc); - has_render_texture = false; - - // sample buffers doesn't work in conjunction with the render_texture extension - if (!f.sampleBuffers()) { - PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = - (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); - - if (wglGetExtensionsStringARB) { - QString extensions(QLatin1String(wglGetExtensionsStringARB(dc))); - has_render_texture = extensions.contains(QLatin1String("WGL_ARB_render_texture")); - } - } - - int attribs[40]; - qt_format_to_attrib_list(has_render_texture, f, attribs); - - // Find pbuffer capable pixel format. - unsigned int num_formats = 0; - int pixel_format; - wglChoosePixelFormatARB(dc, attribs, 0, 1, &pixel_format, &num_formats); - - // some GL implementations don't support pbuffers with accum - // buffers, so try that before we give up - if (num_formats == 0 && f.accum()) { - QGLFormat tmp = f; - tmp.setAccum(false); - qt_format_to_attrib_list(has_render_texture, tmp, attribs); - wglChoosePixelFormatARB(dc, attribs, 0, 1, &pixel_format, &num_formats); - } - - if (num_formats == 0) { - qWarning("QGLPixelBuffer: Unable to find a pixel format with pbuffer - giving up."); - return false; - } - format = pfiToQGLFormat(dc, pixel_format); - - // NB! The below ONLY works if the width/height are powers of 2. - // Set some pBuffer attributes so that we can use this pBuffer as - // a 2D RGBA texture target. - int pb_attribs[] = {WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB, - WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, 0}; - - pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), - has_render_texture ? pb_attribs : 0); - if (!pbuf) { - // try again without the render_texture extension - pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), 0); - has_render_texture = false; - if (!pbuf) { - qWarning("QGLPixelBuffer: Unable to create pbuffer [w=%d, h=%d] - giving up.", size.width(), size.height()); - return false; - } - } - - dc = wglGetPbufferDCARB(pbuf); - ctx = wglCreateContext(dc); - if (!dc || !ctx) { - qWarning("QGLPixelBuffer: Unable to create pbuffer context - giving up."); - return false; - } - - // Explicitly disable the render_texture extension if we have a - // multi-sampled pbuffer context. This seems to be a problem only with - // ATI cards if multi-sampling is forced globally in the driver. - wglMakeCurrent(dc, ctx); - GLint samples = 0; - glGetIntegerv(GL_SAMPLES_ARB, &samples); - if (has_render_texture && samples != 0) - has_render_texture = false; - - HGLRC share_ctx = shareWidget ? shareWidget->d_func()->glcx->d_func()->rc : 0; - if (share_ctx && !wglShareLists(share_ctx, ctx)) - qWarning("QGLPixelBuffer: Unable to share display lists - with share widget."); - - int width, height; - wglQueryPbufferARB(pbuf, WGL_PBUFFER_WIDTH_ARB, &width); - wglQueryPbufferARB(pbuf, WGL_PBUFFER_HEIGHT_ARB, &height); - return true; -} - -bool QGLPixelBufferPrivate::cleanup() -{ - PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = - (PFNWGLRELEASEPBUFFERDCARBPROC) wglGetProcAddress("wglReleasePbufferDCARB"); - PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = - (PFNWGLDESTROYPBUFFERARBPROC) wglGetProcAddress("wglDestroyPbufferARB"); - if (!invalid && wglReleasePbufferDCARB && wglDestroyPbufferARB) { - wglReleasePbufferDCARB(pbuf, dc); - wglDestroyPbufferARB(pbuf); - } - return true; -} - -bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id) -{ - Q_D(QGLPixelBuffer); - if (d->invalid || !d->has_render_texture) - return false; - PFNWGLBINDTEXIMAGEARBPROC wglBindTexImageARB = - (PFNWGLBINDTEXIMAGEARBPROC) wglGetProcAddress("wglBindTexImageARB"); - if (wglBindTexImageARB) { - glBindTexture(GL_TEXTURE_2D, texture_id); - return wglBindTexImageARB(d->pbuf, WGL_FRONT_LEFT_ARB); - } - return false; -} - -void QGLPixelBuffer::releaseFromDynamicTexture() -{ - Q_D(QGLPixelBuffer); - if (d->invalid || !d->has_render_texture) - return; - PFNWGLRELEASETEXIMAGEARBPROC wglReleaseTexImageARB = - (PFNWGLRELEASETEXIMAGEARBPROC) wglGetProcAddress("wglReleaseTexImageARB"); - if (wglReleaseTexImageARB) - wglReleaseTexImageARB(d->pbuf, WGL_FRONT_LEFT_ARB); -} - -bool QGLPixelBuffer::hasOpenGLPbuffers() -{ - bool ret = false; - QGLTemporaryContext *tmpContext = 0; - if (!QGLContext::currentContext()) - tmpContext = new QGLTemporaryContext; - PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = - (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); - if (wglGetExtensionsStringARB) { - QString extensions(QLatin1String(wglGetExtensionsStringARB(wglGetCurrentDC()))); - if (extensions.contains(QLatin1String("WGL_ARB_pbuffer")) - && extensions.contains(QLatin1String("WGL_ARB_pixel_format"))) { - ret = true; - } - } - if (tmpContext) - delete tmpContext; - return ret; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglpixelbuffer_x11.cpp b/src/opengl/qglpixelbuffer_x11.cpp deleted file mode 100644 index fcd7b521bb..0000000000 --- a/src/opengl/qglpixelbuffer_x11.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "qglpixelbuffer.h" -#include "qglpixelbuffer_p.h" - -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) -#include -#endif - -QT_BEGIN_NAMESPACE - -#ifndef GLX_VERSION_1_3 -#define GLX_RGBA_BIT 0x00000002 -#define GLX_PBUFFER_BIT 0x00000004 -#define GLX_DRAWABLE_TYPE 0x8010 -#define GLX_RENDER_TYPE 0x8011 -#define GLX_RGBA_TYPE 0x8014 -#define GLX_PBUFFER_HEIGHT 0x8040 -#define GLX_PBUFFER_WIDTH 0x8041 -#endif - -#ifndef GLX_ARB_multisample -#define GLX_SAMPLE_BUFFERS_ARB 100000 -#define GLX_SAMPLES_ARB 100001 -#endif - -typedef GLXFBConfig* (*_glXChooseFBConfig) (Display *dpy, int screen, const int *attrib_list, int *nelements); -typedef int (*_glXGetFBConfigAttrib) (Display *dpy, GLXFBConfig config, int attribute, int *value); -typedef GLXPbuffer (*_glXCreatePbuffer) (Display *dpy, GLXFBConfig config, const int *attrib_list); -typedef void (*_glXDestroyPbuffer) (Display *dpy, GLXPbuffer pbuf); -typedef GLXContext (*_glXCreateNewContext) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); -typedef Bool (*_glXMakeContextCurrent) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); - -static _glXChooseFBConfig qt_glXChooseFBConfig = 0; -static _glXCreateNewContext qt_glXCreateNewContext = 0; -static _glXCreatePbuffer qt_glXCreatePbuffer = 0; -static _glXDestroyPbuffer qt_glXDestroyPbuffer = 0; -static _glXGetFBConfigAttrib qt_glXGetFBConfigAttrib = 0; -static _glXMakeContextCurrent qt_glXMakeContextCurrent = 0; - -#define glXChooseFBConfig qt_glXChooseFBConfig -#define glXCreateNewContext qt_glXCreateNewContext -#define glXCreatePbuffer qt_glXCreatePbuffer -#define glXDestroyPbuffer qt_glXDestroyPbuffer -#define glXGetFBConfigAttrib qt_glXGetFBConfigAttrib -#define glXMakeContextCurrent qt_glXMakeContextCurrent - -extern void (*qglx_getProcAddress(const char* procName))(); // in qgl_x11.cpp - -static bool qt_resolve_pbuffer_extensions() -{ - static int resolved = false; - if (resolved && qt_glXMakeContextCurrent) - return true; - else if (resolved) - return false; - - qt_glXChooseFBConfig = (_glXChooseFBConfig) qglx_getProcAddress("glXChooseFBConfig"); - qt_glXCreateNewContext = (_glXCreateNewContext) qglx_getProcAddress("glXCreateNewContext"); - qt_glXCreatePbuffer = (_glXCreatePbuffer) qglx_getProcAddress("glXCreatePbuffer"); - qt_glXDestroyPbuffer = (_glXDestroyPbuffer) qglx_getProcAddress("glXDestroyPbuffer"); - qt_glXGetFBConfigAttrib = (_glXGetFBConfigAttrib) qglx_getProcAddress("glXGetFBConfigAttrib"); - qt_glXMakeContextCurrent = (_glXMakeContextCurrent) qglx_getProcAddress("glXMakeContextCurrent"); - - resolved = qt_glXMakeContextCurrent ? true : false; - return resolved; -} - -static void qt_format_to_attrib_list(const QGLFormat &f, int attribs[]) -{ - int i = 0; - attribs[i++] = GLX_RENDER_TYPE; - attribs[i++] = GLX_RGBA_BIT; - attribs[i++] = GLX_DRAWABLE_TYPE; - attribs[i++] = GLX_PBUFFER_BIT; - attribs[i++] = GLX_RED_SIZE; - attribs[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize(); - attribs[i++] = GLX_GREEN_SIZE; - attribs[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize(); - attribs[i++] = GLX_BLUE_SIZE; - attribs[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize(); - if (f.doubleBuffer()) { - attribs[i++] = GLX_DOUBLEBUFFER; - attribs[i++] = true; - } - if (f.depth()) { - attribs[i++] = GLX_DEPTH_SIZE; - attribs[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize(); - } - if (f.stereo()) { - attribs[i++] = GLX_STEREO; - attribs[i++] = true; - } - if (f.stencil()) { - attribs[i++] = GLX_STENCIL_SIZE; - attribs[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize(); - } - if (f.alpha()) { - attribs[i++] = GLX_ALPHA_SIZE; - attribs[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize(); - } - if (f.accum()) { - attribs[i++] = GLX_ACCUM_RED_SIZE; - attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - attribs[i++] = GLX_ACCUM_GREEN_SIZE; - attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - attribs[i++] = GLX_ACCUM_BLUE_SIZE; - attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - if (f.alpha()) { - attribs[i++] = GLX_ACCUM_ALPHA_SIZE; - attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - } - } - if (f.sampleBuffers()) { - attribs[i++] = GLX_SAMPLE_BUFFERS_ARB; - attribs[i++] = 1; - attribs[i++] = GLX_SAMPLES_ARB; - attribs[i++] = f.samples() == -1 ? 4 : f.samples(); - } - - attribs[i] = XNone; -} - -bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) -{ - if (!qt_resolve_pbuffer_extensions()) { - qWarning("QGLPixelBuffer: pbuffers are not supported on this system."); - return false; - } - - int attribs[40]; - int num_configs = 0; - - qt_format_to_attrib_list(f, attribs); - - int screen = X11->defaultScreen; - if (shareWidget) - screen = shareWidget->x11Info().screen(); - - GLXFBConfig *configs = glXChooseFBConfig(X11->display, screen, attribs, &num_configs); - if (configs && num_configs) { - int res; - glXGetFBConfigAttrib(X11->display, configs[0], GLX_LEVEL, &res); - format.setPlane(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_DOUBLEBUFFER, &res); - format.setDoubleBuffer(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_DEPTH_SIZE, &res); - format.setDepth(res); - if (format.depth()) - format.setDepthBufferSize(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_RGBA, &res); - format.setRgba(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_RED_SIZE, &res); - format.setRedBufferSize(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_GREEN_SIZE, &res); - format.setGreenBufferSize(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_BLUE_SIZE, &res); - format.setBlueBufferSize(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_ALPHA_SIZE, &res); - format.setAlpha(res); - if (format.alpha()) - format.setAlphaBufferSize(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_ACCUM_RED_SIZE, &res); - format.setAccum(res); - if (format.accum()) - format.setAccumBufferSize(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_STENCIL_SIZE, &res); - format.setStencil(res); - if (format.stencil()) - format.setStencilBufferSize(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_STEREO, &res); - format.setStereo(res); - glXGetFBConfigAttrib(X11->display, configs[0], GLX_SAMPLE_BUFFERS_ARB, &res); - format.setSampleBuffers(res); - if (format.sampleBuffers()) { - glXGetFBConfigAttrib(X11->display, configs[0], GLX_SAMPLES_ARB, &res); - format.setSamples(res); - } - - int pb_attribs[] = {GLX_PBUFFER_WIDTH, size.width(), GLX_PBUFFER_HEIGHT, size.height(), XNone}; - GLXContext shareContext = 0; - if (shareWidget && shareWidget->d_func()->glcx) - shareContext = (GLXContext) shareWidget->d_func()->glcx->d_func()->cx; - - pbuf = glXCreatePbuffer(QX11Info::display(), configs[0], pb_attribs); - ctx = glXCreateNewContext(QX11Info::display(), configs[0], GLX_RGBA_TYPE, shareContext, true); - - XFree(configs); - if (!pbuf || !ctx) { - qWarning("QGLPixelBuffer: Unable to create a pbuffer/context - giving up."); - return false; - } - return true; - } else { - qWarning("QGLPixelBuffer: Unable to find a context/format match - giving up."); - return false; - } -} - -bool QGLPixelBufferPrivate::cleanup() -{ - glXDestroyPbuffer(QX11Info::display(), pbuf); - return true; -} - -bool QGLPixelBuffer::bindToDynamicTexture(GLuint) -{ - return false; -} - -void QGLPixelBuffer::releaseFromDynamicTexture() -{ -} - -bool QGLPixelBuffer::hasOpenGLPbuffers() -{ - bool ret = qt_resolve_pbuffer_extensions(); - - if (!ret) - return false; - - int attribs[40]; - int num_configs = 0; - - qt_format_to_attrib_list(QGLFormat::defaultFormat(), attribs); - - GLXFBConfig *configs = glXChooseFBConfig(X11->display, X11->defaultScreen, attribs, &num_configs); - GLXPbuffer pbuf = 0; - GLXContext ctx = 0; - - if (configs && num_configs) { - int pb_attribs[] = {GLX_PBUFFER_WIDTH, 128, GLX_PBUFFER_HEIGHT, 128, XNone}; - pbuf = glXCreatePbuffer(X11->display, configs[0], pb_attribs); - ctx = glXCreateNewContext(X11->display, configs[0], GLX_RGBA_TYPE, 0, true); - XFree(configs); - glXDestroyContext(X11->display, ctx); - glXDestroyPbuffer(X11->display, pbuf); - } - return pbuf && ctx; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp deleted file mode 100644 index 6c807248ee..0000000000 --- a/src/opengl/qglpixmapfilter.cpp +++ /dev/null @@ -1,619 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qpixmapfilter_p.h" -#include "private/qpaintengineex_opengl2_p.h" -#include "private/qglengineshadermanager_p.h" -#include "qplatformpixmap_qpa.h" -#include "private/qimagepixmapcleanuphooks_p.h" -#include "qglpixmapfilter_p.h" -#include "qpaintengine_opengl_p.h" -#include "qcache.h" - -#include "qglframebufferobject.h" -#include "qglshaderprogram.h" -#include "qgl_p.h" - -#include "private/qapplication_p.h" -#include "private/qdrawhelper_p.h" -#include "private/qmemrotate_p.h" -#include "private/qmath_p.h" -#include "qmath.h" - -QT_BEGIN_NAMESPACE - -// qpixmapfilter.cpp -Q_GUI_EXPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); -Q_GUI_EXPORT QImage qt_halfScaled(const QImage &source); - -void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const -{ - const_cast(QGLContext::currentContext())->d_func()->bindTexture(src, GL_TEXTURE_2D, GL_RGBA, QGLContext::BindOptions(QGLContext::DefaultBindOption | QGLContext::MemoryManagedBindOption)); -} - -void QGLPixmapFilterBase::drawImpl(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF& source) const -{ - processGL(painter, pos, src, source); -} - -class QGLPixmapColorizeFilter: public QGLCustomShaderStage, public QGLPixmapFilter -{ -public: - QGLPixmapColorizeFilter(); - - void setUniforms(QGLShaderProgram *program); - -protected: - bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &pixmap, const QRectF &srcRect) const; -}; - -class QGLPixmapConvolutionFilter: public QGLCustomShaderStage, public QGLPixmapFilter -{ -public: - QGLPixmapConvolutionFilter(); - ~QGLPixmapConvolutionFilter(); - - void setUniforms(QGLShaderProgram *program); - -protected: - bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const; - -private: - QByteArray generateConvolutionShader() const; - - mutable QSize m_srcSize; - mutable int m_prevKernelSize; -}; - -class QGLPixmapBlurFilter : public QGLCustomShaderStage, public QGLPixmapFilter -{ -public: - QGLPixmapBlurFilter(); - -protected: - bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const; -}; - -class QGLPixmapDropShadowFilter : public QGLCustomShaderStage, public QGLPixmapFilter -{ -public: - QGLPixmapDropShadowFilter(); - - void setUniforms(QGLShaderProgram *program); - -protected: - bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const; -}; - -extern const QGLContext *qt_gl_share_context(); - -QPixmapFilter *QGL2PaintEngineEx::pixmapFilter(int type, const QPixmapFilter *prototype) -{ - Q_D(QGL2PaintEngineEx); - switch (type) { - case QPixmapFilter::ColorizeFilter: - if (!d->colorizeFilter) - d->colorizeFilter.reset(new QGLPixmapColorizeFilter); - return d->colorizeFilter.data(); - - case QPixmapFilter::BlurFilter: { - if (!d->blurFilter) - d->blurFilter.reset(new QGLPixmapBlurFilter()); - return d->blurFilter.data(); - } - - case QPixmapFilter::DropShadowFilter: { - if (!d->dropShadowFilter) - d->dropShadowFilter.reset(new QGLPixmapDropShadowFilter()); - return d->dropShadowFilter.data(); - } - - case QPixmapFilter::ConvolutionFilter: - if (!d->convolutionFilter) - d->convolutionFilter.reset(new QGLPixmapConvolutionFilter); - return d->convolutionFilter.data(); - - default: break; - } - return QPaintEngineEx::pixmapFilter(type, prototype); -} - -static const char *qt_gl_colorize_filter = - "uniform lowp vec4 colorizeColor;" - "uniform lowp float colorizeStrength;" - "lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords)" - "{" - " lowp vec4 srcPixel = texture2D(src, srcCoords);" - " lowp float gray = dot(srcPixel.rgb, vec3(0.212671, 0.715160, 0.072169));" - " lowp vec3 colorized = 1.0-((1.0-gray)*(1.0-colorizeColor.rgb));" - " return vec4(mix(srcPixel.rgb, colorized * srcPixel.a, colorizeStrength), srcPixel.a);" - "}"; - -QGLPixmapColorizeFilter::QGLPixmapColorizeFilter() -{ - setSource(qt_gl_colorize_filter); -} - -bool QGLPixmapColorizeFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const -{ - QGLPixmapColorizeFilter *filter = const_cast(this); - - filter->setOnPainter(painter); - painter->drawPixmap(pos, src); - filter->removeFromPainter(painter); - - return true; -} - -void QGLPixmapColorizeFilter::setUniforms(QGLShaderProgram *program) -{ - program->setUniformValue("colorizeColor", color()); - program->setUniformValue("colorizeStrength", float(strength())); -} - -void QGLPixmapConvolutionFilter::setUniforms(QGLShaderProgram *program) -{ - const qreal *kernel = convolutionKernel(); - int kernelWidth = columns(); - int kernelHeight = rows(); - int kernelSize = kernelWidth * kernelHeight; - - QVarLengthArray matrix(kernelSize); - QVarLengthArray offset(kernelSize * 2); - - for(int i = 0; i < kernelSize; ++i) - matrix[i] = kernel[i]; - - for(int y = 0; y < kernelHeight; ++y) { - for(int x = 0; x < kernelWidth; ++x) { - offset[(y * kernelWidth + x) * 2] = x - (kernelWidth / 2); - offset[(y * kernelWidth + x) * 2 + 1] = (kernelHeight / 2) - y; - } - } - - const qreal iw = 1.0 / m_srcSize.width(); - const qreal ih = 1.0 / m_srcSize.height(); - program->setUniformValue("inv_texture_size", iw, ih); - program->setUniformValueArray("matrix", matrix.constData(), kernelSize, 1); - program->setUniformValueArray("offset", offset.constData(), kernelSize, 2); -} - -// generates convolution filter code for arbitrary sized kernel -QByteArray QGLPixmapConvolutionFilter::generateConvolutionShader() const { - QByteArray code; - int kernelWidth = columns(); - int kernelHeight = rows(); - int kernelSize = kernelWidth * kernelHeight; - code.append("uniform highp vec2 inv_texture_size;\n" - "uniform mediump float matrix["); - code.append(QByteArray::number(kernelSize)); - code.append("];\n" - "uniform highp vec2 offset["); - code.append(QByteArray::number(kernelSize)); - code.append("];\n"); - code.append("lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords) {\n"); - - code.append(" int i = 0;\n" - " lowp vec4 sum = vec4(0.0);\n" - " for (i = 0; i < "); - code.append(QByteArray::number(kernelSize)); - code.append("; i++) {\n" - " sum += matrix[i] * texture2D(src,srcCoords+inv_texture_size*offset[i]);\n" - " }\n" - " return sum;\n" - "}"); - return code; -} - -QGLPixmapConvolutionFilter::QGLPixmapConvolutionFilter() - : m_prevKernelSize(-1) -{ -} - -QGLPixmapConvolutionFilter::~QGLPixmapConvolutionFilter() -{ -} - -bool QGLPixmapConvolutionFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const -{ - QGLPixmapConvolutionFilter *filter = const_cast(this); - - m_srcSize = src.size(); - - int kernelSize = rows() * columns(); - if (m_prevKernelSize == -1 || m_prevKernelSize != kernelSize) { - filter->setSource(generateConvolutionShader()); - m_prevKernelSize = kernelSize; - } - - filter->setOnPainter(painter); - painter->drawPixmap(pos, src, srcRect); - filter->removeFromPainter(painter); - - return true; -} - -QGLPixmapBlurFilter::QGLPixmapBlurFilter() -{ -} - -class QGLBlurTextureInfo -{ -public: - QGLBlurTextureInfo(const QImage &image, GLuint tex, qreal r) - : m_texture(tex) - , m_radius(r) - { - m_paddedImage << image; - } - - ~QGLBlurTextureInfo() - { - glDeleteTextures(1, &m_texture); - } - - QImage paddedImage(int scaleLevel = 0) const; - GLuint texture() const { return m_texture; } - qreal radius() const { return m_radius; } - -private: - mutable QList m_paddedImage; - GLuint m_texture; - qreal m_radius; -}; - -QImage QGLBlurTextureInfo::paddedImage(int scaleLevel) const -{ - for (int i = m_paddedImage.size() - 1; i <= scaleLevel; ++i) - m_paddedImage << qt_halfScaled(m_paddedImage.at(i)); - - return m_paddedImage.at(scaleLevel); -} - -class QGLBlurTextureCache : public QObject -{ -public: - static QGLBlurTextureCache *cacheForContext(const QGLContext *context); - - QGLBlurTextureCache(const QGLContext *); - ~QGLBlurTextureCache(); - - QGLBlurTextureInfo *takeBlurTextureInfo(const QPixmap &pixmap); - bool hasBlurTextureInfo(quint64 cacheKey) const; - void insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info); - void clearBlurTextureInfo(quint64 cacheKey); - - void timerEvent(QTimerEvent *event); - -private: - static void pixmapDestroyed(QPlatformPixmap *pixmap); - - QCache cache; - - static QList blurTextureCaches; - - int timerId; -}; - -QList QGLBlurTextureCache::blurTextureCaches; -Q_GLOBAL_STATIC(QGLContextGroupResource, qt_blur_texture_caches) - -QGLBlurTextureCache::QGLBlurTextureCache(const QGLContext *) - : timerId(0) -{ - cache.setMaxCost(4 * 1024 * 1024); - blurTextureCaches.append(this); -} - -QGLBlurTextureCache::~QGLBlurTextureCache() -{ - blurTextureCaches.removeAt(blurTextureCaches.indexOf(this)); -} - -void QGLBlurTextureCache::timerEvent(QTimerEvent *) -{ - killTimer(timerId); - timerId = 0; - - cache.clear(); -} - -QGLBlurTextureCache *QGLBlurTextureCache::cacheForContext(const QGLContext *context) -{ - return qt_blur_texture_caches()->value(context); -} - -QGLBlurTextureInfo *QGLBlurTextureCache::takeBlurTextureInfo(const QPixmap &pixmap) -{ - return cache.take(pixmap.cacheKey()); -} - -void QGLBlurTextureCache::clearBlurTextureInfo(quint64 cacheKey) -{ - cache.remove(cacheKey); -} - -bool QGLBlurTextureCache::hasBlurTextureInfo(quint64 cacheKey) const -{ - return cache.contains(cacheKey); -} - -void QGLBlurTextureCache::insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info) -{ - static bool hookAdded = false; - if (!hookAdded) { - QImagePixmapCleanupHooks::instance()->addPlatformPixmapDestructionHook(pixmapDestroyed); - QImagePixmapCleanupHooks::instance()->addPlatformPixmapModificationHook(pixmapDestroyed); - hookAdded = true; - } - - QImagePixmapCleanupHooks::enableCleanupHooks(pixmap); - cache.insert(pixmap.cacheKey(), info, pixmap.width() * pixmap.height()); - - if (timerId) - killTimer(timerId); - - timerId = startTimer(8000); -} - -void QGLBlurTextureCache::pixmapDestroyed(QPlatformPixmap *pmd) -{ - foreach (QGLBlurTextureCache *cache, blurTextureCaches) { - if (cache->hasBlurTextureInfo(pmd->cacheKey())) - cache->clearBlurTextureInfo(pmd->cacheKey()); - } -} - -static const int qAnimatedBlurLevelIncrement = 16; -static const int qMaxBlurHalfScaleLevel = 1; - -static GLuint generateBlurTexture(const QSize &size, GLenum format = GL_RGBA) -{ - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, - GL_UNSIGNED_BYTE, 0); - return texture; -} - -static inline uint nextMultiple(uint x, uint multiplier) -{ - uint mod = x % multiplier; - if (mod == 0) - return x; - return x + multiplier - mod; -} - -Q_GUI_EXPORT 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 -{ - if (radius() < 1) { - painter->drawPixmap(pos, src); - return true; - } - - qreal actualRadius = radius(); - - QGLContext *ctx = const_cast(QGLContext::currentContext()); - - QGLBlurTextureCache *blurTextureCache = QGLBlurTextureCache::cacheForContext(ctx); - QGLBlurTextureInfo *info = 0; - int padding = nextMultiple(qCeil(actualRadius), qAnimatedBlurLevelIncrement); - QRect targetRect = src.rect().adjusted(-padding, -padding, padding, padding); - - // pad so that we'll be able to half-scale qMaxBlurHalfScaleLevel times - targetRect.setWidth((targetRect.width() + (qMaxBlurHalfScaleLevel-1)) & ~(qMaxBlurHalfScaleLevel-1)); - targetRect.setHeight((targetRect.height() + (qMaxBlurHalfScaleLevel-1)) & ~(qMaxBlurHalfScaleLevel-1)); - - QSize textureSize; - - info = blurTextureCache->takeBlurTextureInfo(src); - if (!info || info->radius() < actualRadius) { - QSize paddedSize = targetRect.size() / 2; - - QImage padded(paddedSize.height(), paddedSize.width(), QImage::Format_ARGB32_Premultiplied); - padded.fill(0); - - if (info) { - int oldPadding = qRound(info->radius()); - - QPainter p(&padded); - p.setCompositionMode(QPainter::CompositionMode_Source); - p.drawImage((padding - oldPadding) / 2, (padding - oldPadding) / 2, info->paddedImage()); - p.end(); - } else { - // TODO: combine byteswapping and memrotating into one by declaring - // custom GL_RGBA pixel type and qt_colorConvert template for it - QImage prepadded = qt_halfScaled(src.toImage()).convertToFormat(QImage::Format_ARGB32_Premultiplied); - - // byte-swap and memrotates in one go - qt_memrotate90_gl(reinterpret_cast(prepadded.bits()), - prepadded.width(), prepadded.height(), prepadded.bytesPerLine(), - reinterpret_cast(padded.scanLine(padding / 2)) + padding / 2, - padded.bytesPerLine()); - } - - delete info; - info = new QGLBlurTextureInfo(padded, generateBlurTexture(paddedSize), padding); - - textureSize = paddedSize; - } else { - textureSize = QSize(info->paddedImage().height(), info->paddedImage().width()); - } - - actualRadius *= qreal(0.5); - int level = 1; - for (; level < qMaxBlurHalfScaleLevel; ++level) { - if (actualRadius <= 16) - break; - actualRadius *= qreal(0.5); - } - - const int s = (1 << level); - - int prepadding = qRound(info->radius()); - padding = qMin(prepadding, qCeil(actualRadius) << level); - targetRect = src.rect().adjusted(-padding, -padding, padding, padding); - - targetRect.setWidth(targetRect.width() & ~(s-1)); - targetRect.setHeight(targetRect.height() & ~(s-1)); - - int paddingDelta = (prepadding - padding) >> level; - - QRect subRect(paddingDelta, paddingDelta, targetRect.width() >> level, targetRect.height() >> level); - QImage sourceImage = info->paddedImage(level-1); - - QImage subImage(subRect.height(), subRect.width(), QImage::Format_ARGB32_Premultiplied); - qt_rectcopy((QRgb *)subImage.bits(), ((QRgb *)sourceImage.scanLine(paddingDelta)) + paddingDelta, - 0, 0, subRect.height(), subRect.width(), subImage.bytesPerLine(), sourceImage.bytesPerLine()); - - GLuint texture = info->texture(); - - qt_blurImage(subImage, actualRadius, blurHints() & QGraphicsBlurEffect::QualityHint, 1); - - // subtract one pixel off the end to prevent the bilinear sampling from sampling uninitialized data - QRect textureSubRect = subImage.rect().adjusted(0, 0, -1, -1); - QRectF targetRectF = QRectF(targetRect).adjusted(0, 0, -targetRect.width() / qreal(textureSize.width()), -targetRect.height() / qreal(textureSize.height())); - - glBindTexture(GL_TEXTURE_2D, texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subImage.width(), subImage.height(), GL_RGBA, - GL_UNSIGNED_BYTE, const_cast(subImage).bits()); - - QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); - painter->setRenderHint(QPainter::SmoothPixmapTransform); - - // texture is flipped on the y-axis - targetRectF = QRectF(targetRectF.x(), targetRectF.bottom(), targetRectF.width(), -targetRectF.height()); - engine->drawTexture(targetRectF.translated(pos), texture, textureSize, textureSubRect); - - blurTextureCache->insertBlurTextureInfo(src, info); - - return true; -} - -static const char *qt_gl_drop_shadow_filter = - "uniform lowp vec4 shadowColor;" - "lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords)" - "{" - " return shadowColor * texture2D(src, srcCoords.yx).a;" - "}"; - - -QGLPixmapDropShadowFilter::QGLPixmapDropShadowFilter() -{ - setSource(qt_gl_drop_shadow_filter); -} - -bool QGLPixmapDropShadowFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const -{ - QGLPixmapDropShadowFilter *filter = const_cast(this); - - qreal r = blurRadius(); - QRectF targetRectUnaligned = QRectF(src.rect()).translated(pos + offset()).adjusted(-r, -r, r, r); - QRect targetRect = targetRectUnaligned.toAlignedRect(); - - // ensure even dimensions (going to divide by two) - targetRect.setWidth((targetRect.width() + 1) & ~1); - targetRect.setHeight((targetRect.height() + 1) & ~1); - - QGLContext *ctx = const_cast(QGLContext::currentContext()); - QGLBlurTextureCache *blurTextureCache = QGLBlurTextureCache::cacheForContext(ctx); - - QGLBlurTextureInfo *info = blurTextureCache->takeBlurTextureInfo(src); - if (!info || info->radius() != r) { - QImage half = qt_halfScaled(src.toImage().alphaChannel()); - - qreal rx = r + targetRect.left() - targetRectUnaligned.left(); - qreal ry = r + targetRect.top() - targetRectUnaligned.top(); - - QImage image = QImage(targetRect.size() / 2, QImage::Format_Indexed8); - image.setColorTable(half.colorTable()); - image.fill(0); - int dx = qRound(rx * qreal(0.5)); - int dy = qRound(ry * qreal(0.5)); - qt_rectcopy(image.bits(), half.bits(), dx, dy, - half.width(), half.height(), - image.bytesPerLine(), half.bytesPerLine()); - - qt_blurImage(image, r * qreal(0.5), false, 1); - - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, image.width(), image.height(), - 0, GL_ALPHA, GL_UNSIGNED_BYTE, image.bits()); - - info = new QGLBlurTextureInfo(image, texture, r); - } - - GLuint texture = info->texture(); - - filter->setOnPainter(painter); - - QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); - painter->setRenderHint(QPainter::SmoothPixmapTransform); - - engine->drawTexture(targetRect, texture, info->paddedImage().size(), info->paddedImage().rect()); - - filter->removeFromPainter(painter); - - // Now draw the actual pixmap over the top. - painter->drawPixmap(pos, src, srcRect); - - blurTextureCache->insertBlurTextureInfo(src, info); - - return true; -} - -void QGLPixmapDropShadowFilter::setUniforms(QGLShaderProgram *program) -{ - QColor col = color(); - qreal alpha = col.alphaF(); - program->setUniformValue("shadowColor", col.redF() * alpha, - col.greenF() * alpha, - col.blueF() * alpha, - alpha); -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglpixmapfilter_p.h b/src/opengl/qglpixmapfilter_p.h deleted file mode 100644 index 1aa234a25b..0000000000 --- a/src/opengl/qglpixmapfilter_p.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGLPIXMAPFILTER_P_H -#define QGLPIXMAPFILTER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QGLPixelBuffer; - -QT_MODULE(OpenGL) - -class QGLPixmapFilterBase -{ -public: - virtual ~QGLPixmapFilterBase() {} -protected: - void bindTexture(const QPixmap &src) const; - void drawImpl(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect = QRectF()) const; - - virtual bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const = 0; -}; - -template -class QGLPixmapFilter : public Filter, public QGLPixmapFilterBase -{ -public: - void draw(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect = QRectF()) const { - const QRectF source = srcRect.isNull() ? QRectF(src.rect()) : srcRect; - if (painter) - drawImpl(painter, pos, src, source); - } -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGLPIXMAPFILTER_P_H diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index e9cae44662..de03553d8f 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -50,8 +50,6 @@ QT_BEGIN_NAMESPACE -#if !defined(QT_OPENGL_ES_1) - /*! \class QGLShaderProgram \brief The QGLShaderProgram class allows OpenGL shader programs to be linked and used. @@ -3269,86 +3267,4 @@ bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context) return true; } - - -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS -/*! \internal */ -void QGLShaderProgram::setAttributeArray - (int location, QMacCompatGLenum type, const void *values, int tupleSize, int stride) -{ - setAttributeArray(location, GLenum(type), values, tupleSize, stride); -} - -/*! \internal */ -void QGLShaderProgram::setAttributeArray - (const char *name, QMacCompatGLenum type, const void *values, int tupleSize, int stride) -{ - setAttributeArray(name, GLenum(type), values, tupleSize, stride); -} - -/*! \internal */ -void QGLShaderProgram::setAttributeBuffer - (int location, QMacCompatGLenum type, int offset, int tupleSize, int stride) -{ - setAttributeBuffer(location, GLenum(type), offset, tupleSize, stride); -} - -/*! \internal */ -void QGLShaderProgram::setAttributeBuffer - (const char *name, QMacCompatGLenum type, int offset, int tupleSize, int stride) -{ - setAttributeBuffer(name, GLenum(type), offset, tupleSize, stride); -} - -/*! \internal */ -void QGLShaderProgram::setUniformValue(int location, QMacCompatGLint value) -{ - setUniformValue(location, GLint(value)); -} - -/*! \internal */ -void QGLShaderProgram::setUniformValue(int location, QMacCompatGLuint value) -{ - setUniformValue(location, GLuint(value)); -} - -/*! \internal */ -void QGLShaderProgram::setUniformValue(const char *name, QMacCompatGLint value) -{ - setUniformValue(name, GLint(value)); -} - -/*! \internal */ -void QGLShaderProgram::setUniformValue(const char *name, QMacCompatGLuint value) -{ - setUniformValue(name, GLuint(value)); -} - -/*! \internal */ -void QGLShaderProgram::setUniformValueArray(int location, const QMacCompatGLint *values, int count) -{ - setUniformValueArray(location, (const GLint *)values, count); -} - -/*! \internal */ -void QGLShaderProgram::setUniformValueArray(int location, const QMacCompatGLuint *values, int count) -{ - setUniformValueArray(location, (const GLuint *)values, count); -} - -/*! \internal */ -void QGLShaderProgram::setUniformValueArray(const char *name, const QMacCompatGLint *values, int count) -{ - setUniformValueArray(name, (const GLint *)values, count); -} - -/*! \internal */ -void QGLShaderProgram::setUniformValueArray(const char *name, const QMacCompatGLuint *values, int count) -{ - setUniformValueArray(name, (const GLuint *)values, count); -} -#endif - -#endif // !defined(QT_OPENGL_ES_1) - QT_END_NAMESPACE diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h index 09b6184bcb..591aab27cd 100644 --- a/src/opengl/qglshaderprogram.h +++ b/src/opengl/qglshaderprogram.h @@ -54,8 +54,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(OpenGL) -#if !defined(QT_OPENGL_ES_1) - class QGLShaderProgram; class QGLShaderPrivate; @@ -204,17 +202,6 @@ public: void setAttributeBuffer (const char *name, GLenum type, int offset, int tupleSize, int stride = 0); -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS - void setAttributeArray - (int location, QMacCompatGLenum type, const void *values, int tupleSize, int stride = 0); - void setAttributeArray - (const char *name, QMacCompatGLenum type, const void *values, int tupleSize, int stride = 0); - void setAttributeBuffer - (int location, QMacCompatGLenum type, int offset, int tupleSize, int stride = 0); - void setAttributeBuffer - (const char *name, QMacCompatGLenum type, int offset, int tupleSize, int stride = 0); -#endif - void enableAttributeArray(int location); void enableAttributeArray(const char *name); void disableAttributeArray(int location); @@ -224,17 +211,6 @@ public: int uniformLocation(const QByteArray& name) const; int uniformLocation(const QString& name) const; -#ifdef Q_MAC_COMPAT_GL_FUNCTIONS - void setUniformValue(int location, QMacCompatGLint value); - void setUniformValue(int location, QMacCompatGLuint value); - void setUniformValue(const char *name, QMacCompatGLint value); - void setUniformValue(const char *name, QMacCompatGLuint value); - void setUniformValueArray(int location, const QMacCompatGLint *values, int count); - void setUniformValueArray(int location, const QMacCompatGLuint *values, int count); - void setUniformValueArray(const char *name, const QMacCompatGLint *values, int count); - void setUniformValueArray(const char *name, const QMacCompatGLuint *values, int count); -#endif - void setUniformValue(int location, GLfloat value); void setUniformValue(int location, GLint value); void setUniformValue(int location, GLuint value); @@ -335,8 +311,6 @@ private: bool init(); }; -#endif - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index 8cca7eae1c..c785fb29ad 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -40,11 +40,9 @@ ****************************************************************************/ #include "qgraphicsshadereffect_p.h" -#if !defined(QT_OPENGL_ES_1) #include "qglshaderprogram.h" #include "gl2paintengineex/qglcustomshaderstage_p.h" #define QGL_HAVE_CUSTOM_SHADERS 1 -#endif #include #include #include diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp deleted file mode 100644 index 3c35c0334c..0000000000 --- a/src/opengl/qpaintengine_opengl.cpp +++ /dev/null @@ -1,5635 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include "qapplication.h" -#include "qbrush.h" -#include "qgl.h" -#include -#include -#include -#include "qmap.h" -#include -#include -#include "qpen.h" -#include "qvarlengtharray.h" -#include -#include -#include -#include -#include - -#include "private/qtessellator_p.h" - -#include "util/fragmentprograms_p.h" - -#ifdef Q_WS_QWS -#include "private/qglwindowsurface_qws_p.h" -#include "qwsmanager_qws.h" -#include "private/qwsmanager_p.h" -#endif - -#define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast(device->context()); - -#include -#include "qpaintengine_opengl_p.h" - -QT_BEGIN_NAMESPACE - -Q_GUI_EXPORT 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 - -#define QREAL_MAX 9e100 -#define QREAL_MIN -9e100 - -extern int qt_next_power_of_two(int v); - -#define DISABLE_DEBUG_ONCE - -//#define DEBUG_DISPLAY_MASK_TEXTURE - -#ifdef DISABLE_DEBUG_ONCE -#define DEBUG_OVERRIDE(state) ; -#define DEBUG_ONCE_STR(str) ; -#define DEBUG_ONCE if (0) -#else -static int DEBUG_OVERRIDE_FLAG = 0; -static bool DEBUG_TEMP_FLAG; -#define DEBUG_OVERRIDE(state) { state ? ++DEBUG_OVERRIDE_FLAG : --DEBUG_OVERRIDE_FLAG; } -#define DEBUG_ONCE if ((DEBUG_TEMP_FLAG = DEBUG_OVERRIDE_FLAG) && 0) ; else for (static int DEBUG_ONCE_FLAG = false; !DEBUG_ONCE_FLAG || DEBUG_TEMP_FLAG; DEBUG_ONCE_FLAG = true, DEBUG_TEMP_FLAG = false) -#define DEBUG_ONCE_STR(str) DEBUG_ONCE qDebug() << (str); -#endif - -#ifdef Q_WS_X11 -static bool qt_nvidiaFboNeedsFinish = false; -#endif - -static inline void qt_glColor4ubv(unsigned char *col) -{ - glColor4f(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, col[3]/255.0f); -} - -struct QT_PointF { - qreal x; - qreal y; -}; - -struct QGLTrapezoid -{ - QGLTrapezoid() - {} - - QGLTrapezoid(qreal top_, qreal bottom_, qreal topLeftX_, qreal topRightX_, qreal bottomLeftX_, qreal bottomRightX_) - : top(top_), - bottom(bottom_), - topLeftX(topLeftX_), - topRightX(topRightX_), - bottomLeftX(bottomLeftX_), - bottomRightX(bottomRightX_) - {} - - const QGLTrapezoid translated(const QPointF &delta) const; - - qreal top; - qreal bottom; - qreal topLeftX; - qreal topRightX; - qreal bottomLeftX; - qreal bottomRightX; -}; - -const QGLTrapezoid QGLTrapezoid::translated(const QPointF &delta) const -{ - QGLTrapezoid trap(*this); - trap.top += delta.y(); - trap.bottom += delta.y(); - trap.topLeftX += delta.x(); - trap.topRightX += delta.x(); - trap.bottomLeftX += delta.x(); - trap.bottomRightX += delta.x(); - return trap; -} - - -class QOpenGLImmediateModeTessellator; -class QGLMaskGenerator; -class QGLOffscreen; - -class QGLMaskTextureCache -{ -public: - void setOffscreenSize(const QSize &offscreenSize); - void setDrawableSize(const QSize &drawableSize); - - struct CacheLocation { - QRect rect; - int channel; - - QRect screen_rect; - }; - - struct CacheInfo { - inline CacheInfo(const QPainterPath &p, const QTransform &m, qreal w = -1) : - path(p), matrix(m), stroke_width(w), age(0) {} - - QPainterPath path; - QTransform matrix; - qreal stroke_width; - - CacheLocation loc; - - int age; - }; - - struct QuadTreeNode { - quint64 key; - - int largest_available_block; - int largest_used_block; - }; - - CacheLocation getMask(QGLMaskGenerator &maskGenerator, QOpenGLPaintEnginePrivate *engine); - - typedef QMultiHash QGLTextureCacheHash; - - enum {block_size = 64}; - - // throw out keys that are too old - void maintainCache(); - void clearCache(); - -private: - quint64 hash(const QPainterPath &p, const QTransform &m, qreal w); - - void createMask(quint64 key, CacheInfo &info, QGLMaskGenerator &maskGenerator); - - QSize offscreenSize; - QSize drawableSize; - - QGLTextureCacheHash cache; - - QVector occupied_quadtree[4]; - - void quadtreeUpdate(int channel, int node, int current_block_size); - void quadtreeAllocate(quint64 key, const QSize &size, QRect *rect, int *channel); - - bool quadtreeFindAvailableLocation(const QSize &size, QRect *rect, int *channel); - void quadtreeFindExistingLocation(const QSize &size, QRect *rect, int *channel); - - void quadtreeInsert(int channel, quint64 key, const QRect &rect, int node = 0); - void quadtreeClear(int channel, const QRect &rect, int node = 0); - - int quadtreeBlocksize(int node); - QPoint quadtreeLocation(int node); - - QOpenGLPaintEnginePrivate *engine; -}; - -Q_GLOBAL_STATIC(QGLMaskTextureCache, qt_mask_texture_cache) - -class QGLOffscreen : public QObject -{ - Q_OBJECT -public: - QGLOffscreen() - : QObject(), - offscreen(0), - ctx(0), - mask_dim(0), - activated(false), - bound(false) - { - connect(QGLSignalProxy::instance(), - SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(cleanupGLContextRefs(const QGLContext*))); - } - - inline void setDevice(QPaintDevice *pdev); - - void begin(); - void end(); - - inline void bind(); - inline void release(); - - inline bool isBound() const; - - inline QSize drawableSize() const; - inline QSize offscreenSize() const; - - inline GLuint offscreenTexture() const; - - QGLContext *context() const; - - static bool isSupported(); - - inline void initialize(); - - inline bool isValid() const; - -public Q_SLOTS: - void cleanupGLContextRefs(const QGLContext *context) { - if (context == ctx) { - delete offscreen; - ctx = 0; - offscreen = 0; - mask_dim = 0; - } - } - -private: - QGLPaintDevice* device; - - QGLFramebufferObject *offscreen; - QGLContext *ctx; - - // dimensions of mask texture (square) - int mask_dim; - QSize last_failed_size; - - bool drawable_fbo; - - bool activated; - bool initialized; - - bool bound; -}; - -inline void QGLOffscreen::setDevice(QPaintDevice *pdev) -{ - if (pdev->devType() == QInternal::OpenGL) - device = static_cast(pdev); - else - device = QGLPaintDevice::getDevice(pdev); - - if (!device) - return; - - drawable_fbo = (pdev->devType() == QInternal::FramebufferObject); -} - -void QGLOffscreen::begin() -{ -#ifndef QT_OPENGL_ES - initialized = false; - - if (activated) - initialize(); -#endif -} - -void QGLOffscreen::initialize() -{ -#ifndef QT_OPENGL_ES - if (initialized) - return; - - activated = true; - initialized = true; - - int dim = qMax(2048, static_cast(qt_next_power_of_two(qMax(device->size().width(), device->size().height())))); - - bool shared_context = QGLContext::areSharing(device->context(), ctx); - bool would_fail = last_failed_size.isValid() && - (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) { - DEBUG_ONCE qDebug() << "QGLOffscreen::initialize(): creating offscreen of size" << dim; - delete offscreen; - offscreen = new QGLFramebufferObject(dim, dim, GLenum(GL_TEXTURE_2D)); - mask_dim = dim; - - if (!offscreen->isValid()) { - qWarning("QGLOffscreen: Invalid offscreen fbo (size %dx%d)", mask_dim, mask_dim); - delete offscreen; - offscreen = 0; - mask_dim = 0; - last_failed_size = device->size(); - } - } - - qt_mask_texture_cache()->setOffscreenSize(offscreenSize()); - qt_mask_texture_cache()->setDrawableSize(device->size()); - ctx = device->context(); -#endif -} - -inline bool QGLOffscreen::isValid() const -{ - return offscreen; -} - -void QGLOffscreen::end() -{ - if (bound) - release(); -#ifdef DEBUG_DISPLAY_MASK_TEXTURE - glReadBuffer(GL_BACK); - glDrawBuffer(GL_BACK); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glColor4f(1, 1, 1, 1); - glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_ONE, GL_ZERO); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, offscreen->texture()); - - glBegin(GL_QUADS); - glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 0.0); - glTexCoord2f(1.0, 1.0); glVertex2f(drawable.size().width(), 0.0); - glTexCoord2f(1.0, 0.0); glVertex2f(drawable.size().width(), drawable.size().height()); - glTexCoord2f(0.0, 0.0); glVertex2f(0.0, drawable.size().height()); - glEnd(); - - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); -#endif -} - -inline void QGLOffscreen::bind() -{ -#ifndef QT_OPENGL_ES - Q_ASSERT(initialized); - - if (!offscreen || bound) - return; - - DEBUG_ONCE qDebug() << "QGLOffscreen: binding offscreen"; - offscreen->bind(); - - bound = true; - - glViewport(0, 0, offscreenSize().width(), offscreenSize().height()); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, offscreenSize().width(), offscreenSize().height(), 0, -999999, 999999); - glMatrixMode(GL_MODELVIEW); -#endif -} - -inline void QGLOffscreen::release() -{ -#ifndef QT_OPENGL_ES - if (!offscreen || !bound) - return; - -#ifdef Q_WS_X11 - // workaround for bug in nvidia driver versions 9x.xx - if (qt_nvidiaFboNeedsFinish) - glFinish(); -#endif - - DEBUG_ONCE_STR("QGLOffscreen: releasing offscreen"); - - if (drawable_fbo) - device->ensureActiveTarget(); //### - else - offscreen->release(); - - QSize sz(device->size()); - glViewport(0, 0, sz.width(), sz.height()); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); -#ifndef QT_OPENGL_ES - glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999); -#else - glOrthof(0, sz.width(), sz.height(), 0, -999999, 999999); -#endif - glMatrixMode(GL_MODELVIEW); - - bound = false; -#endif -} - -inline bool QGLOffscreen::isBound() const -{ - return bound; -} - -inline QSize QGLOffscreen::drawableSize() const -{ - return device->size(); -} - -inline QSize QGLOffscreen::offscreenSize() const -{ - return QSize(mask_dim, mask_dim); -} - -inline GLuint QGLOffscreen::offscreenTexture() const -{ - return offscreen ? offscreen->texture() : 0; -} - -inline QGLContext *QGLOffscreen::context() const -{ - return ctx; -} - -bool QGLOffscreen::isSupported() -{ - return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); // for fbo -} - -struct QDrawQueueItem -{ - QDrawQueueItem(qreal _opacity, - QBrush _brush, - const QPointF &_brush_origion, - QPainter::CompositionMode _composition_mode, - const QTransform &_matrix, - QGLMaskTextureCache::CacheLocation _location) - : opacity(_opacity), - brush(_brush), - brush_origin(_brush_origion), - composition_mode(_composition_mode), - matrix(_matrix), - location(_location) {} - qreal opacity; - QBrush brush; - QPointF brush_origin; - QPainter::CompositionMode composition_mode; - - QTransform matrix; - QGLMaskTextureCache::CacheLocation location; -}; - -////////// GL program cache: start - -struct GLProgram { - int brush; // brush index or mask index - int mode; // composition mode index - bool mask; - GLuint program; -}; - -typedef QMultiHash QGLProgramHash; - -class QGLProgramCache : public QObject -{ - Q_OBJECT -public: - QGLProgramCache() { - // we have to know when a context is deleted so we can free - // any program handles it holds - connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(cleanupPrograms(const QGLContext*))); - - } - ~QGLProgramCache() { - // at this point the cache should contain 0 elements - // Q_ASSERT(program.size() == 0); - } - - GLuint getProgram(const QGLContext *ctx, int brush, int mode, bool mask_mode) - { - // 1. see if we have an entry for the ctx context - QList progs = programs.values(ctx); - for (int i=0; i contexts = programs.uniqueKeys(); - for (int i=0; i progs = programs.values(cx); - for (int k=0; k(src); - - while (glGetError() != GL_NO_ERROR) {} // reset error state - glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - int(strlen(src)), gl_src); - if (glGetError() != GL_NO_ERROR) { -// qDebug() << "QGLProgramCache: Unable to compile fragment program."; - glDeleteProgramsARB(1, &prg.program); - return 0; - } - -// qDebug() << "QGLProgramCache: Creating GL program:" << prg.program << hex << ctx; - programs.insert(ctx, prg); - return prg.program; - } - -public Q_SLOTS: - void cleanupPrograms(const QGLContext *context) - { - QGLProgramHash::iterator it = programs.begin(); - while (it != programs.end()) { - if (it.key() == context) { - if (!context->isSharing()) { - // the ctx variable below is needed for the glDeleteProgramARB call - // since it is resolved from our extension system - // NB! assumes context is the current GL context - const QGLContext *ctx = context; - // qDebug() << "QGLProgramHash: Deleting GL program:" << it.value().program << hex << it.key(); - glDeleteProgramsARB(1, &it.value().program); - } - it = programs.erase(it); - } else { - ++it; - } - } - } - -private: - QGLProgramHash programs; -}; - -Q_GLOBAL_STATIC(QGLProgramCache, qt_gl_program_cache) - -////////// GL program cache: end - -class QOpenGLPaintEnginePrivate; -class QGLPrivateCleanup : public QObject -{ - Q_OBJECT -public: - QGLPrivateCleanup(QOpenGLPaintEnginePrivate *priv) - : p(priv) - { - connect(QGLSignalProxy::instance(), - SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(cleanupGLContextRefs(const QGLContext*))); - } - -public Q_SLOTS: - void cleanupGLContextRefs(const QGLContext *context); - -private: - QOpenGLPaintEnginePrivate *p; -}; - -class QOpenGLPaintEnginePrivate : public QPaintEngineExPrivate -{ - Q_DECLARE_PUBLIC(QOpenGLPaintEngine) -public: - QOpenGLPaintEnginePrivate() - : opacity(1) - , composition_mode(QPainter::CompositionMode_SourceOver) - , has_fast_pen(false) - , use_stencil_method(false) - , dirty_drawable_texture(false) - , has_stencil_face_ext(false) - , use_fragment_programs(false) - , high_quality_antialiasing(false) - , use_smooth_pixmap_transform(false) - , use_emulation(false) - , txop(QTransform::TxNone) - , inverseScale(1) - , moveToCount(0) - , last_created_state(0) - , shader_ctx(0) - , grad_palette(0) - , tess_points(0) - , drawable_texture(0) - , ref_cleaner(this) - {} - - inline void setGLPen(const QColor &c) { - uint alpha = qRound(c.alpha() * opacity); - pen_color[0] = qt_div_255(c.red() * alpha); - pen_color[1] = qt_div_255(c.green() * alpha); - pen_color[2] = qt_div_255(c.blue() * alpha); - pen_color[3] = alpha; - } - - inline void setGLBrush(const QColor &c) { - uint alpha = qRound(c.alpha() * opacity); - brush_color[0] = qt_div_255(c.red() * alpha); - brush_color[1] = qt_div_255(c.green() * alpha); - brush_color[2] = qt_div_255(c.blue() * alpha); - brush_color[3] = alpha; - } - - inline void setGradientOps(const QBrush &brush, const QRectF &bounds); - void createGradientPaletteTexture(const QGradient& g); - - void updateGradient(const QBrush &brush, const QRectF &bounds); - - inline void lineToStencil(qreal x, qreal y); - inline void curveToStencil(const QPointF &cp1, const QPointF &cp2, const QPointF &ep); - void pathToVertexArrays(const QPainterPath &path); - void fillVertexArray(Qt::FillRule fillRule); - void drawVertexArrays(); - void fillPath(const QPainterPath &path); - void fillPolygon_dev(const QPointF *polygonPoints, int pointCount, - Qt::FillRule fill); - - void drawFastRect(const QRectF &rect); - void strokePath(const QPainterPath &path, bool use_cache); - void strokePathFastPen(const QPainterPath &path, bool needsResolving); - void strokeLines(const QPainterPath &path); - - void updateDepthClip(); - void systemStateChanged(); - - void cleanupGLContextRefs(const QGLContext *context) { - if (context == shader_ctx) - shader_ctx = 0; - } - - inline void updateFastPen() { - qreal pen_width = cpen.widthF(); - has_fast_pen = - ((pen_width == 0 || (pen_width <= 1 && matrix.type() <= QTransform::TxTranslate)) - || cpen.isCosmetic()) - && cpen.style() == Qt::SolidLine - && cpen.isSolid(); - - } - - void disableClipping(); - void enableClipping(); - void ensureDrawableTexture(); - - QPen cpen; - QBrush cbrush; - Qt::BrushStyle brush_style; - QPointF brush_origin; - Qt::BrushStyle pen_brush_style; - qreal opacity; - QPainter::CompositionMode composition_mode; - - Qt::BrushStyle current_style; - - uint has_pen : 1; - uint has_brush : 1; - uint has_fast_pen : 1; - uint use_stencil_method : 1; - uint dirty_drawable_texture : 1; - uint has_stencil_face_ext : 1; - uint use_fragment_programs : 1; - uint high_quality_antialiasing : 1; - uint has_antialiasing : 1; - uint has_fast_composition_mode : 1; - uint use_smooth_pixmap_transform : 1; - uint use_system_clip : 1; - uint use_emulation : 1; - - QRegion dirty_stencil; - - void updateUseEmulation(); - - QTransform matrix; - GLubyte pen_color[4]; - GLubyte brush_color[4]; - QTransform::TransformationType txop; - QGLPaintDevice* device; - QGLOffscreen offscreen; - - qreal inverseScale; - - int moveToCount; - QPointF path_start; - - bool isFastRect(const QRectF &r); - - void drawImageAsPath(const QRectF &r, const QImage &img, const QRectF &sr); - void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, const QPointF &offset); - - void drawOffscreenPath(const QPainterPath &path); - - void composite(const QRectF &rect, const QPoint &maskOffset = QPoint()); - void composite(GLuint primitive, const GLfloat *vertexArray, int vertexCount, const QPoint &maskOffset = QPoint()); - - bool createFragmentPrograms(); - void deleteFragmentPrograms(); - void updateFragmentProgramData(int locations[]); - - void cacheItemErased(int channel, const QRect &rect); - - void addItem(const QGLMaskTextureCache::CacheLocation &location); - void drawItem(const QDrawQueueItem &item); - void flushDrawQueue(); - - void copyDrawable(const QRectF &rect); - - void updateGLMatrix() const; - - mutable QPainterState *last_created_state; - - QGLContext *shader_ctx; - GLuint grad_palette; - - GLuint painter_fragment_programs[num_fragment_brushes][num_fragment_composition_modes]; - GLuint mask_fragment_programs[num_fragment_masks]; - - float inv_matrix_data[3][4]; - float fmp_data[4]; - float fmp2_m_radius2_data[4]; - float angle_data[4]; - float linear_data[4]; - - float porterduff_ab_data[4]; - float porterduff_xyz_data[4]; - - float mask_offset_data[4]; - float mask_channel_data[4]; - - FragmentBrushType fragment_brush; - FragmentCompositionModeType fragment_composition_mode; - - void setPorterDuffData(float a, float b, float x, float y, float z); - void setInvMatrixData(const QTransform &inv_matrix); - - qreal max_x; - qreal max_y; - qreal min_x; - qreal min_y; - - QDataBuffer tess_points; - QVector tess_points_stops; - - GLdouble projection_matrix[4][4]; - -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) - GLfloat mv_matrix[4][4]; -#else - GLdouble mv_matrix[4][4]; -#endif - - QList drawQueue; - - GLuint drawable_texture; - QSize drawable_texture_size; - - int max_texture_size; - - QGLPrivateCleanup ref_cleaner; - friend class QGLMaskTextureCache; -}; - -class QOpenGLCoordinateOffset -{ -public: - QOpenGLCoordinateOffset(QOpenGLPaintEnginePrivate *d); - ~QOpenGLCoordinateOffset(); - - static void enableOffset(QOpenGLPaintEnginePrivate *d); - static void disableOffset(QOpenGLPaintEnginePrivate *d); - -private: - QOpenGLPaintEnginePrivate *d; -}; - -QOpenGLCoordinateOffset::QOpenGLCoordinateOffset(QOpenGLPaintEnginePrivate *d_) - : d(d_) -{ - enableOffset(d); -} - -void QOpenGLCoordinateOffset::enableOffset(QOpenGLPaintEnginePrivate *d) -{ - if (!d->has_antialiasing) { - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - d->mv_matrix[3][0] += 0.5; - d->mv_matrix[3][1] += 0.5; - d->updateGLMatrix(); - } -} - -QOpenGLCoordinateOffset::~QOpenGLCoordinateOffset() -{ - disableOffset(d); -} - -void QOpenGLCoordinateOffset::disableOffset(QOpenGLPaintEnginePrivate *d) -{ - if (!d->has_antialiasing) { - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - d->mv_matrix[3][0] -= 0.5; - d->mv_matrix[3][1] -= 0.5; - } -} - -void QGLPrivateCleanup::cleanupGLContextRefs(const QGLContext *context) -{ - p->cleanupGLContextRefs(context); -} - - -static inline void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform) -{ - if (smoothPixmapTransform) { - glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { - glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - glTexParameterf(target, GL_TEXTURE_WRAP_S, wrapMode); - glTexParameterf(target, GL_TEXTURE_WRAP_T, wrapMode); -} - -static inline QPainterPath strokeForPath(const QPainterPath &path, const QPen &cpen) { - QPainterPathStroker stroker; - if (cpen.style() == Qt::CustomDashLine) - stroker.setDashPattern(cpen.dashPattern()); - else - stroker.setDashPattern(cpen.style()); - - stroker.setCapStyle(cpen.capStyle()); - stroker.setJoinStyle(cpen.joinStyle()); - stroker.setMiterLimit(cpen.miterLimit()); - stroker.setDashOffset(cpen.dashOffset()); - - qreal width = cpen.widthF(); - if (width == 0) - stroker.setWidth(1); - else - stroker.setWidth(width); - - QPainterPath stroke = stroker.createStroke(path); - stroke.setFillRule(Qt::WindingFill); - return stroke; -} - -class QGLStrokeCache -{ - struct CacheInfo - { - inline CacheInfo(QPainterPath p, QPainterPath sp, QPen stroke_pen) : - path(p), stroked_path(sp), pen(stroke_pen) {} - QPainterPath path; - QPainterPath stroked_path; - QPen pen; - }; - - typedef QMultiHash QGLStrokeTableHash; - -public: - inline QPainterPath getStrokedPath(const QPainterPath &path, const QPen &pen) { - quint64 hash_val = 0; - - for (int i = 0; i < path.elementCount() && i <= 2; i++) { - hash_val += quint64(path.elementAt(i).x); - hash_val += quint64(path.elementAt(i).y); - } - - QGLStrokeTableHash::const_iterator it = cache.constFind(hash_val); - - if (it == cache.constEnd()) - return addCacheElement(hash_val, path, pen); - else { - do { - const CacheInfo &cache_info = it.value(); - if (cache_info.path == path && cache_info.pen == pen) - return cache_info.stroked_path; - ++it; - } while (it != cache.constEnd() && it.key() == hash_val); - // an exact match for this path was not found, create new cache element - return addCacheElement(hash_val, path, pen); - } - } - -protected: - inline int maxCacheSize() const { return 500; } - QPainterPath addCacheElement(quint64 hash_val, QPainterPath path, const QPen &pen) { - if (cache.size() == maxCacheSize()) { - int elem_to_remove = qrand() % maxCacheSize(); - cache.remove(cache.keys()[elem_to_remove]); // may remove more than 1, but OK - } - QPainterPath stroke = strokeForPath(path, pen); - CacheInfo cache_entry(path, stroke, pen); - return cache.insert(hash_val, cache_entry).value().stroked_path; - } - - QGLStrokeTableHash cache; -}; - -Q_GLOBAL_STATIC(QGLStrokeCache, qt_opengl_stroke_cache) - -class QGLGradientCache : public QObject -{ - Q_OBJECT - struct CacheInfo - { - inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) : - stops(s), opacity(op), interpolationMode(mode) {} - - GLuint texId; - QGradientStops stops; - qreal opacity; - QGradient::InterpolationMode interpolationMode; - }; - - typedef QMultiHash QGLGradientColorTableHash; - -public: - QGLGradientCache() : QObject(), buffer_ctx(0) - { - connect(QGLSignalProxy::instance(), - SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(cleanupGLContextRefs(const QGLContext*))); - } - - inline GLuint getBuffer(const QGradient &gradient, qreal opacity, QGLContext *ctx) { - if (buffer_ctx && !QGLContext::areSharing(buffer_ctx, ctx)) - cleanCache(); - - buffer_ctx = ctx; - - quint64 hash_val = 0; - - QGradientStops stops = gradient.stops(); - for (int i = 0; i < stops.size() && i <= 2; i++) - hash_val += stops[i].second.rgba(); - - QGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val); - - if (it == cache.constEnd()) - return addCacheElement(hash_val, gradient, opacity); - else { - do { - const CacheInfo &cache_info = it.value(); - if (cache_info.stops == stops && cache_info.opacity == opacity && cache_info.interpolationMode == gradient.interpolationMode()) { - return cache_info.texId; - } - ++it; - } while (it != cache.constEnd() && it.key() == hash_val); - // an exact match for these stops and opacity was not found, create new cache - return addCacheElement(hash_val, gradient, opacity); - } - } - - inline int paletteSize() const { return 1024; } - -protected: - inline int maxCacheSize() const { return 60; } - inline void generateGradientColorTable(const QGradient& g, - uint *colorTable, - int size, qreal opacity) const; - GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity) { - if (cache.size() == maxCacheSize()) { - int elem_to_remove = qrand() % maxCacheSize(); - quint64 key = cache.keys()[elem_to_remove]; - - // need to call glDeleteTextures on each removed cache entry: - QGLGradientColorTableHash::const_iterator it = cache.constFind(key); - do { - glDeleteTextures(1, &it.value().texId); - } while (++it != cache.constEnd() && it.key() == key); - cache.remove(key); // may remove more than 1, but OK - } - CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); - uint buffer[1024]; - generateGradientColorTable(gradient, buffer, paletteSize(), opacity); - glGenTextures(1, &cache_entry.texId); -#ifndef QT_OPENGL_ES - glBindTexture(GL_TEXTURE_1D, cache_entry.texId); - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, paletteSize(), - 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer); -#else - // create 2D one-line texture instead. This requires an impl of manual GL_TEXGEN for all primitives -#endif - return cache.insert(hash_val, cache_entry).value().texId; - } - - void cleanCache() { - QGLShareContextScope scope(buffer_ctx); - QGLGradientColorTableHash::const_iterator it = cache.constBegin(); - for (; it != cache.constEnd(); ++it) { - const CacheInfo &cache_info = it.value(); - glDeleteTextures(1, &cache_info.texId); - } - cache.clear(); - } - - QGLGradientColorTableHash cache; - - QGLContext *buffer_ctx; - -public Q_SLOTS: - void cleanupGLContextRefs(const QGLContext *context) { - if (context == buffer_ctx) { - cleanCache(); - buffer_ctx = 0; - } - } -}; - -static inline uint endianColor(uint c) -{ -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - return c; -#else - return ( (c << 24) & 0xff000000) - | ((c >> 24) & 0x000000ff) - | ((c << 8) & 0x00ff0000) - | ((c >> 8) & 0x0000ff00); -#endif // Q_BYTE_ORDER -} - -void QGLGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const -{ - int pos = 0; - QGradientStops s = gradient.stops(); - QVector colors(s.size()); - - for (int i = 0; i < s.size(); ++i) - colors[i] = s[i].second.rgba(); - - bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); - - uint alpha = qRound(opacity * 256); - uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha); - qreal incr = 1.0 / qreal(size); - qreal fpos = 1.5 * incr; - colorTable[pos++] = endianColor(PREMUL(current_color)); - - while (fpos <= s.first().first) { - colorTable[pos] = colorTable[pos - 1]; - pos++; - fpos += incr; - } - - if (colorInterpolation) - current_color = PREMUL(current_color); - - for (int i = 0; i < s.size() - 1; ++i) { - qreal delta = 1/(s[i+1].first - s[i].first); - uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha); - if (colorInterpolation) - next_color = PREMUL(next_color); - - while (fpos < s[i+1].first && pos < size) { - int dist = int(256 * ((fpos - s[i].first) * delta)); - int idist = 256 - dist; - if (colorInterpolation) - colorTable[pos] = endianColor(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); - else - colorTable[pos] = endianColor(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); - ++pos; - fpos += incr; - } - current_color = next_color; - } - - Q_ASSERT(s.size() > 0); - - uint last_color = endianColor(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); - for (;pos < size; ++pos) - colorTable[pos] = last_color; - - // Make sure the last color stop is represented at the end of the table - colorTable[size-1] = last_color; -} - -#ifndef Q_WS_QWS -Q_GLOBAL_STATIC(QGLGradientCache, qt_opengl_gradient_cache) -#endif - -void QOpenGLPaintEnginePrivate::createGradientPaletteTexture(const QGradient& g) -{ -#ifdef QT_OPENGL_ES //### - Q_UNUSED(g); -#else - 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) - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); - else if (g.spread() == QGradient::ReflectSpread) - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT_IBM); - else - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - -#endif -} - - -inline void QOpenGLPaintEnginePrivate::setGradientOps(const QBrush &brush, const QRectF &bounds) -{ - current_style = brush.style(); - - if (current_style < Qt::LinearGradientPattern || current_style > Qt::ConicalGradientPattern) { - setGLBrush(brush.color()); - qt_glColor4ubv(brush_color); - } - - updateGradient(brush, bounds); - -#ifndef QT_OPENGL_ES //### GLES does not have GL_TEXTURE_GEN_ so we are falling back for gradients - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_1D); - - if (current_style == Qt::LinearGradientPattern) { - if (high_quality_antialiasing || !has_fast_composition_mode) { - fragment_brush = FRAGMENT_PROGRAM_BRUSH_LINEAR; - } else { - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_1D); - } - } else { - if (use_fragment_programs) { - if (current_style == Qt::RadialGradientPattern) - fragment_brush = FRAGMENT_PROGRAM_BRUSH_RADIAL; - else if (current_style == Qt::ConicalGradientPattern) - fragment_brush = FRAGMENT_PROGRAM_BRUSH_CONICAL; - else if (current_style == Qt::SolidPattern) - fragment_brush = FRAGMENT_PROGRAM_BRUSH_SOLID; - else if (current_style == Qt::TexturePattern && !brush.texture().isQBitmap()) - fragment_brush = FRAGMENT_PROGRAM_BRUSH_TEXTURE; - else - fragment_brush = FRAGMENT_PROGRAM_BRUSH_PATTERN; - } - } -#endif -} - -QOpenGLPaintEngine::QOpenGLPaintEngine() - : QPaintEngineEx(*(new QOpenGLPaintEnginePrivate)) -{ -} - -QOpenGLPaintEngine::~QOpenGLPaintEngine() -{ -} - -bool QOpenGLPaintEngine::begin(QPaintDevice *pdev) -{ - Q_D(QOpenGLPaintEngine); - - if (pdev->devType() == QInternal::OpenGL) - d->device = static_cast(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->device->beginPaint(); - d->matrix = QTransform(); - d->has_antialiasing = false; - d->high_quality_antialiasing = false; - - QSize sz(d->device->size()); - d->dirty_stencil = QRect(0, 0, sz.width(), sz.height()); - - d->use_emulation = false; - - for (int i = 0; i < 4; ++i) - for (int j = 0; j < 4; ++j) - d->mv_matrix[i][j] = (i == j ? qreal(1) : qreal(0)); - - bool has_frag_program = (QGLExtensions::glExtensions() & QGLExtensions::FragmentProgram) - && (pdev->devType() != QInternal::Pixmap); - - QGLContext *ctx = const_cast(d->device->context()); - if (!ctx) { - qWarning() << "QOpenGLPaintEngine: paint device doesn't have a valid GL context."; - return false; - } - - 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->device->format().stencil() - && (QGLExtensions::glExtensions() & QGLExtensions::StencilWrap); - if (d->device->format().directRendering() - && (d->use_stencil_method && QGLExtensions::glExtensions() & QGLExtensions::StencilTwoSide)) - d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx); - -#ifdef Q_WS_X11 - static bool nvidia_workaround_needs_init = true; - if (nvidia_workaround_needs_init) { - // nvidia 9x.xx unix drivers contain a bug which requires us to - // call glFinish before releasing an fbo to avoid painting - // artifacts - const QByteArray versionString(reinterpret_cast(glGetString(GL_VERSION))); - const int pos = versionString.indexOf("NVIDIA"); - if (pos >= 0) { - const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat(); - qt_nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0; - } - nvidia_workaround_needs_init = false; - } -#endif - -#ifndef QT_OPENGL_ES - if (!ctx->d_ptr->internal_context) { - glGetDoublev(GL_PROJECTION_MATRIX, &d->projection_matrix[0][0]); - glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); - glPushAttrib(GL_ALL_ATTRIB_BITS); - - glDisableClientState(GL_EDGE_FLAG_ARRAY); - glDisableClientState(GL_INDEX_ARRAY); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDisable(GL_TEXTURE_1D); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glPixelTransferi(GL_MAP_COLOR, false); - glPixelTransferi(GL_MAP_STENCIL, false); - glDisable(GL_TEXTURE_GEN_S); - - glPixelStorei(GL_PACK_SWAP_BYTES, false); - glPixelStorei(GL_PACK_LSB_FIRST, false); - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glPixelStorei(GL_PACK_SKIP_ROWS, 0); - glPixelStorei(GL_PACK_SKIP_PIXELS, 0); - glPixelStorei(GL_PACK_ALIGNMENT, 4); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, false); - glPixelStorei(GL_UNPACK_LSB_FIRST, false); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - - if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) { - glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0); - glPixelStorei(GL_PACK_SKIP_IMAGES, 0); - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); - glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0); - } - } -#endif - - if (!ctx->d_ptr->internal_context) { - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glLoadIdentity(); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - - if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers) - glDisable(GL_MULTISAMPLE); - glDisable(GL_TEXTURE_2D); - if (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle) - glDisable(GL_TEXTURE_RECTANGLE_NV); - glDisable(GL_STENCIL_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_LIGHTING); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - - d->offscreen.begin(); - - 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(); -#ifdef QT_OPENGL_ES - glOrthof(0, sz.width(), sz.height(), 0, -999999, 999999); -#else - glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999); -#endif - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glEnable(GL_BLEND); - d->composition_mode = QPainter::CompositionMode_SourceOver; - -#ifdef QT_OPENGL_ES - d->max_texture_size = ctx->d_func()->maxTextureSize(); -#else - bool shared_ctx = QGLContext::areSharing(d->device->context(), d->shader_ctx); - - if (shared_ctx) { - d->max_texture_size = d->shader_ctx->d_func()->maxTextureSize(); - } else { - d->max_texture_size = ctx->d_func()->maxTextureSize(); - - if (d->shader_ctx) { - d->shader_ctx->makeCurrent(); - glBindTexture(GL_TEXTURE_1D, 0); - glDeleteTextures(1, &d->grad_palette); - - if (has_frag_program && d->use_fragment_programs) - glDeleteTextures(1, &d->drawable_texture); - ctx->makeCurrent(); - } - d->shader_ctx = d->device->context(); - glGenTextures(1, &d->grad_palette); - - qt_mask_texture_cache()->clearCache(); - d->use_fragment_programs = has_frag_program; - } - - if (d->use_fragment_programs && (!shared_ctx || sz.width() > d->drawable_texture_size.width() - || sz.height() > d->drawable_texture_size.height())) - { - // delete old texture if size has increased, otherwise it was deleted earlier - if (shared_ctx) - glDeleteTextures(1, &d->drawable_texture); - - d->dirty_drawable_texture = true; - d->drawable_texture_size = QSize(qt_next_power_of_two(sz.width()), - qt_next_power_of_two(sz.height())); - } -#endif - - updateClipRegion(QRegion(), Qt::NoClip); - penChanged(); - brushChanged(); - opacityChanged(); - compositionModeChanged(); - renderHintsChanged(); - transformChanged(); - return true; -} - -bool QOpenGLPaintEngine::end() -{ - Q_D(QOpenGLPaintEngine); - d->flushDrawQueue(); - d->offscreen.end(); - QGLContext *ctx = const_cast(d->device->context()); - if (!ctx->d_ptr->internal_context) { - glMatrixMode(GL_TEXTURE); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - } -#ifndef QT_OPENGL_ES - if (ctx->d_ptr->internal_context) { - glDisable(GL_SCISSOR_TEST); - } else { - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(&d->projection_matrix[0][0]); - glPopAttrib(); - glPopClientAttrib(); - } -#endif - d->device->endPaint(); - qt_mask_texture_cache()->maintainCache(); - -#if defined(Q_WS_X11) - // clear out the references we hold for textures bound with the - // texture_from_pixmap extension - ctx->d_func()->boundPixmaps.clear(); -#endif - return true; -} - -void QOpenGLPaintEngine::updateState(const QPaintEngineState &state) -{ - Q_D(QOpenGLPaintEngine); - QPaintEngine::DirtyFlags flags = state.state(); - - bool update_fast_pen = false; - - if (flags & DirtyOpacity) { - update_fast_pen = true; - d->opacity = state.opacity(); - if (d->opacity > 1.0f) - d->opacity = 1.0f; - if (d->opacity < 0.f) - d->opacity = 0.f; - // force update - flags |= DirtyPen; - flags |= DirtyBrush; - } - - if (flags & DirtyTransform) { - update_fast_pen = true; - updateMatrix(state.transform()); - // brush setup depends on transform state - if (state.brush().style() != Qt::NoBrush) - flags |= DirtyBrush; - } - - if (flags & DirtyPen) { - update_fast_pen = true; - updatePen(state.pen()); - } - - if (flags & (DirtyBrush | DirtyBrushOrigin)) { - updateBrush(state.brush(), state.brushOrigin()); - } - - if (flags & DirtyFont) { - updateFont(state.font()); - } - - if (state.state() & DirtyClipEnabled) { - if (state.isClipEnabled()) - updateClipRegion(painter()->clipRegion(), Qt::ReplaceClip); - else - updateClipRegion(QRegion(), Qt::NoClip); - } - - if (flags & DirtyClipPath) { - updateClipRegion(QRegion(state.clipPath().toFillPolygon().toPolygon(), - state.clipPath().fillRule()), - state.clipOperation()); - } - - if (flags & DirtyClipRegion) { - updateClipRegion(state.clipRegion(), state.clipOperation()); - } - - if (flags & DirtyHints) { - updateRenderHints(state.renderHints()); - } - - if (flags & DirtyCompositionMode) { - updateCompositionMode(state.compositionMode()); - } - - if (update_fast_pen) { - Q_D(QOpenGLPaintEngine); - qreal pen_width = d->cpen.widthF(); - d->has_fast_pen = - ((pen_width == 0 || (pen_width <= 1 && d->txop <= QTransform::TxTranslate)) - || d->cpen.isCosmetic()) - && d->cpen.style() == Qt::SolidLine - && d->cpen.isSolid(); - } -} - - -void QOpenGLPaintEnginePrivate::setInvMatrixData(const QTransform &inv_matrix) -{ - inv_matrix_data[0][0] = inv_matrix.m11(); - inv_matrix_data[1][0] = inv_matrix.m21(); - inv_matrix_data[2][0] = inv_matrix.m31(); - - inv_matrix_data[0][1] = inv_matrix.m12(); - inv_matrix_data[1][1] = inv_matrix.m22(); - inv_matrix_data[2][1] = inv_matrix.m32(); - - inv_matrix_data[0][2] = inv_matrix.m13(); - inv_matrix_data[1][2] = inv_matrix.m23(); - inv_matrix_data[2][2] = inv_matrix.m33(); -} - - -void QOpenGLPaintEnginePrivate::updateGradient(const QBrush &brush, const QRectF &) -{ -#ifdef QT_OPENGL_ES - Q_UNUSED(brush); -#else - bool has_mirrored_repeat = QGLExtensions::glExtensions() & QGLExtensions::MirroredRepeat; - Qt::BrushStyle style = brush.style(); - - QTransform m = brush.transform(); - - if (has_mirrored_repeat && style == Qt::LinearGradientPattern) { - const QLinearGradient *g = static_cast(brush.gradient()); - QTransform m = brush.transform(); - QPointF realStart = g->start(); - QPointF realFinal = g->finalStop(); - QPointF start = m.map(realStart); - QPointF stop; - - if (qFuzzyCompare(m.m11(), m.m22()) && m.m12() == 0.0 && m.m21() == 0.0) { - // It is a simple uniform scale and/or translation - stop = m.map(realFinal); - } else { - // It is not enough to just transform the endpoints. - // We have to make sure the _pattern_ is transformed correctly. - - qreal odx = realFinal.x() - realStart.x(); - qreal ody = realFinal.y() - realStart.y(); - - // nx, ny and dx, dy are normal and gradient direction after transform: - qreal nx = m.m11()*ody - m.m21()*odx; - qreal ny = m.m12()*ody - m.m22()*odx; - - qreal dx = m.m11()*odx + m.m21()*ody; - qreal dy = m.m12()*odx + m.m22()*ody; - - qreal lx = 1 / (dx - dy*nx/ny); - qreal ly = 1 / (dy - dx*ny/nx); - qreal l = 1 / qSqrt(lx*lx+ly*ly); - - stop = start + QPointF(-ny, nx) * l/qSqrt(nx*nx+ny*ny); - } - - float tr[4], f; - tr[0] = stop.x() - start.x(); - tr[1] = stop.y() - start.y(); - f = 1.0 / (tr[0]*tr[0] + tr[1]*tr[1]); - tr[0] *= f; - tr[1] *= f; - tr[2] = 0; - tr[3] = -(start.x()*tr[0] + start.y()*tr[1]); - brush_color[0] = brush_color[1] = brush_color[2] = brush_color[3] = 255; - qt_glColor4ubv(brush_color); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, tr); - } - - if (use_fragment_programs) { - if (style == Qt::RadialGradientPattern) { - const QRadialGradient *g = static_cast(brush.gradient()); - QPointF realCenter = g->center(); - QPointF realFocal = g->focalPoint(); - qreal realRadius = g->radius(); - QTransform translate(1, 0, 0, 1, -realFocal.x(), -realFocal.y()); - QTransform gl_to_qt(1, 0, 0, -1, 0, pdev->height()); - QTransform m = QTransform(matrix).translate(brush_origin.x(), brush_origin.y()); - QTransform inv_matrix = gl_to_qt * (brush.transform() * m).inverted() * translate; - - setInvMatrixData(inv_matrix); - - fmp_data[0] = realCenter.x() - realFocal.x(); - fmp_data[1] = realCenter.y() - realFocal.y(); - - fmp2_m_radius2_data[0] = -fmp_data[0] * fmp_data[0] - fmp_data[1] * fmp_data[1] + realRadius * realRadius; - } else if (style == Qt::ConicalGradientPattern) { - const QConicalGradient *g = static_cast(brush.gradient()); - QPointF realCenter = g->center(); - QTransform translate(1, 0, 0, 1, -realCenter.x(), -realCenter.y()); - QTransform gl_to_qt(1, 0, 0, -1, 0, pdev->height()); - QTransform m = QTransform(matrix).translate(brush_origin.x(), brush_origin.y()); - QTransform inv_matrix = gl_to_qt * (brush.transform() * m).inverted() * translate; - - setInvMatrixData(inv_matrix); - - angle_data[0] = -(g->angle() * 2 * Q_PI) / 360.0; - } else if (style == Qt::LinearGradientPattern) { - const QLinearGradient *g = static_cast(brush.gradient()); - - QPointF realStart = g->start(); - QPointF realFinal = g->finalStop(); - QTransform translate(1, 0, 0, 1, -realStart.x(), -realStart.y()); - QTransform gl_to_qt(1, 0, 0, -1, 0, pdev->height()); - QTransform m = QTransform(matrix).translate(brush_origin.x(), brush_origin.y()); - QTransform inv_matrix = gl_to_qt * (brush.transform() * m).inverted() * translate; - - setInvMatrixData(inv_matrix); - - QPointF l = realFinal - realStart; - - linear_data[0] = l.x(); - linear_data[1] = l.y(); - - linear_data[2] = 1.0f / (l.x() * l.x() + l.y() * l.y()); - } else if (style != Qt::SolidPattern) { - QTransform gl_to_qt(1, 0, 0, -1, 0, pdev->height()); - QTransform m = QTransform(matrix).translate(brush_origin.x(), brush_origin.y()); - QTransform inv_matrix = gl_to_qt * (brush.transform() * m).inverted(); - - setInvMatrixData(inv_matrix); - } - } - - if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) { - createGradientPaletteTexture(*brush.gradient()); - } -#endif -} - - -class QOpenGLTessellator : public QTessellator -{ -public: - QOpenGLTessellator() {} - ~QOpenGLTessellator() { } - QGLTrapezoid toGLTrapezoid(const Trapezoid &trap); -}; - -QGLTrapezoid QOpenGLTessellator::toGLTrapezoid(const Trapezoid &trap) -{ - QGLTrapezoid t; - - t.top = Q27Dot5ToDouble(trap.top); - t.bottom = Q27Dot5ToDouble(trap.bottom); - - Q27Dot5 y = trap.topLeft->y - trap.bottomLeft->y; - - qreal topLeftY = Q27Dot5ToDouble(trap.topLeft->y); - - qreal tx = Q27Dot5ToDouble(trap.topLeft->x); - qreal m = (-tx + Q27Dot5ToDouble(trap.bottomLeft->x)) / Q27Dot5ToDouble(y); - t.topLeftX = tx + m * (topLeftY - t.top); - t.bottomLeftX = tx + m * (topLeftY - t.bottom); - - y = trap.topRight->y - trap.bottomRight->y; - - qreal topRightY = Q27Dot5ToDouble(trap.topRight->y); - - tx = Q27Dot5ToDouble(trap.topRight->x); - m = (-tx + Q27Dot5ToDouble(trap.bottomRight->x)) / Q27Dot5ToDouble(y); - - t.topRightX = tx + m * (topRightY - Q27Dot5ToDouble(trap.top)); - t.bottomRightX = tx + m * (topRightY - Q27Dot5ToDouble(trap.bottom)); - - return t; -} - -class QOpenGLImmediateModeTessellator : public QOpenGLTessellator -{ -public: - void addTrap(const Trapezoid &trap); - void tessellate(const QPointF *points, int nPoints, bool winding) { - trapezoids.reserve(trapezoids.size() + nPoints); - setWinding(winding); - QTessellator::tessellate(points, nPoints); - } - - QVector trapezoids; -}; - -void QOpenGLImmediateModeTessellator::addTrap(const Trapezoid &trap) -{ - trapezoids.append(toGLTrapezoid(trap)); -} - -#ifndef QT_OPENGL_ES -static void drawTrapezoid(const QGLTrapezoid &trap, const qreal offscreenHeight, QGLContext *ctx) -{ - qreal minX = qMin(trap.topLeftX, trap.bottomLeftX); - qreal maxX = qMax(trap.topRightX, trap.bottomRightX); - - if (qFuzzyCompare(trap.top, trap.bottom) || qFuzzyCompare(minX, maxX) || - (qFuzzyCompare(trap.topLeftX, trap.topRightX) && qFuzzyCompare(trap.bottomLeftX, trap.bottomRightX))) - return; - - const qreal xpadding = 1.0; - const qreal ypadding = 1.0; - - qreal topDist = offscreenHeight - trap.top; - qreal bottomDist = offscreenHeight - trap.bottom; - - qreal reciprocal = bottomDist / (bottomDist - topDist); - - qreal leftB = trap.bottomLeftX + (trap.topLeftX - trap.bottomLeftX) * reciprocal; - qreal rightB = trap.bottomRightX + (trap.topRightX - trap.bottomRightX) * reciprocal; - - const bool topZero = qFuzzyIsNull(topDist); - - reciprocal = topZero ? 1.0 / bottomDist : 1.0 / topDist; - - qreal leftA = topZero ? (trap.bottomLeftX - leftB) * reciprocal : (trap.topLeftX - leftB) * reciprocal; - qreal rightA = topZero ? (trap.bottomRightX - rightB) * reciprocal : (trap.topRightX - rightB) * reciprocal; - - qreal invLeftA = qFuzzyIsNull(leftA) ? 0.0 : 1.0 / leftA; - qreal invRightA = qFuzzyIsNull(rightA) ? 0.0 : 1.0 / rightA; - - // fragment program needs the negative of invRightA as it mirrors the line - glTexCoord4f(topDist, bottomDist, invLeftA, -invRightA); - glMultiTexCoord4f(GL_TEXTURE1, leftA, leftB, rightA, rightB); - - qreal topY = trap.top - ypadding; - qreal bottomY = trap.bottom + ypadding; - - qreal bounds_bottomLeftX = leftA * (offscreenHeight - bottomY) + leftB; - qreal bounds_bottomRightX = rightA * (offscreenHeight - bottomY) + rightB; - qreal bounds_topLeftX = leftA * (offscreenHeight - topY) + leftB; - qreal bounds_topRightX = rightA * (offscreenHeight - topY) + rightB; - - QPointF leftNormal(1, -leftA); - leftNormal /= qSqrt(leftNormal.x() * leftNormal.x() + leftNormal.y() * leftNormal.y()); - QPointF rightNormal(1, -rightA); - rightNormal /= qSqrt(rightNormal.x() * rightNormal.x() + rightNormal.y() * rightNormal.y()); - - qreal left_padding = xpadding / qAbs(leftNormal.x()); - qreal right_padding = xpadding / qAbs(rightNormal.x()); - - glVertex2d(bounds_topLeftX - left_padding, topY); - glVertex2d(bounds_topRightX + right_padding, topY); - glVertex2d(bounds_bottomRightX + right_padding, bottomY); - glVertex2d(bounds_bottomLeftX - left_padding, bottomY); - - glTexCoord4f(0.0f, 0.0f, 0.0f, 1.0f); -} -#endif // !Q_WS_QWS - -class QOpenGLTrapezoidToArrayTessellator : public QOpenGLTessellator -{ -public: - QOpenGLTrapezoidToArrayTessellator() : vertices(0), allocated(0), size(0) {} - ~QOpenGLTrapezoidToArrayTessellator() { free(vertices); } - GLfloat *vertices; - int allocated; - int size; - QRectF bounds; - void addTrap(const Trapezoid &trap); - void tessellate(const QPointF *points, int nPoints, bool winding) { - size = 0; - setWinding(winding); - bounds = QTessellator::tessellate(points, nPoints); - } -}; - -void QOpenGLTrapezoidToArrayTessellator::addTrap(const Trapezoid &trap) -{ - // On OpenGL ES we convert the trap to 2 triangles -#ifndef QT_OPENGL_ES - if (size > allocated - 8) { -#else - if (size > allocated - 12) { -#endif - allocated = qMax(2*allocated, 512); - vertices = (GLfloat *)realloc(vertices, allocated * sizeof(GLfloat)); - } - - QGLTrapezoid t = toGLTrapezoid(trap); - -#ifndef QT_OPENGL_ES - vertices[size++] = t.topLeftX; - vertices[size++] = t.top; - vertices[size++] = t.topRightX; - vertices[size++] = t.top; - vertices[size++] = t.bottomRightX; - vertices[size++] = t.bottom; - vertices[size++] = t.bottomLeftX; - vertices[size++] = t.bottom; -#else - // First triangle - vertices[size++] = t.topLeftX; - vertices[size++] = t.top; - vertices[size++] = t.topRightX; - vertices[size++] = t.top; - vertices[size++] = t.bottomRightX; - vertices[size++] = t.bottom; - - // Second triangle - vertices[size++] = t.bottomLeftX; - vertices[size++] = t.bottom; - vertices[size++] = t.topLeftX; - vertices[size++] = t.top; - vertices[size++] = t.bottomRightX; - vertices[size++] = t.bottom; -#endif -} - - -void QOpenGLPaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount, - Qt::FillRule fill) -{ - QOpenGLTrapezoidToArrayTessellator tessellator; - tessellator.tessellate(polygonPoints, pointCount, fill == Qt::WindingFill); - - DEBUG_ONCE qDebug() << "QOpenGLPaintEnginePrivate: Drawing polygon with" << pointCount << "points using fillPolygon_dev"; - - setGradientOps(cbrush, tessellator.bounds); - - bool fast_style = current_style == Qt::LinearGradientPattern - || current_style == Qt::SolidPattern; - -#ifndef QT_OPENGL_ES - GLenum geometry_mode = GL_QUADS; -#else - GLenum geometry_mode = GL_TRIANGLES; -#endif - - if (use_fragment_programs && !(fast_style && has_fast_composition_mode)) { - composite(geometry_mode, tessellator.vertices, tessellator.size / 2); - } else { - glVertexPointer(2, GL_FLOAT, 0, tessellator.vertices); - glEnableClientState(GL_VERTEX_ARRAY); - glDrawArrays(geometry_mode, 0, tessellator.size/2); - glDisableClientState(GL_VERTEX_ARRAY); - } -} - - -inline void QOpenGLPaintEnginePrivate::lineToStencil(qreal x, qreal y) -{ - tess_points.add(QPointF(x, y)); - - if (x > max_x) - max_x = x; - else if (x < min_x) - min_x = x; - if (y > max_y) - max_y = y; - else if (y < min_y) - min_y = y; -} - -inline void QOpenGLPaintEnginePrivate::curveToStencil(const QPointF &cp1, const QPointF &cp2, const QPointF &ep) -{ - qreal inverseScaleHalf = inverseScale / 2; - - QBezier beziers[32]; - beziers[0] = QBezier::fromPoints(tess_points.last(), cp1, cp2, ep); - QBezier *b = beziers; - while (b >= beziers) { - // check if we can pop the top bezier curve from the stack - qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1); - qreal d; - if (l > inverseScale) { - d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - (b->y4 - b->y1)*(b->x1 - b->x2) ) - + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - (b->y4 - b->y1)*(b->x1 - b->x3) ); - d /= l; - } else { - d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) + - qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); - } - if (d < inverseScaleHalf || b == beziers + 31) { - // good enough, we pop it off and add the endpoint - lineToStencil(b->x4, b->y4); - --b; - } else { - // split, second half of the polygon goes lower into the stack - b->split(b+1, b); - ++b; - } - } -} - - -void QOpenGLPaintEnginePrivate::pathToVertexArrays(const QPainterPath &path) -{ - const QPainterPath::Element &first = path.elementAt(0); - min_x = max_x = first.x; - min_y = max_y = first.y; - - tess_points.reset(); - tess_points_stops.clear(); - lineToStencil(first.x, first.y); - - for (int i=1; isystemClip().intersected(dirty_stencil).boundingRect(); - - glStencilMask(~0); - - if (!rect.isEmpty()) { - disableClipping(); - - glEnable(GL_SCISSOR_TEST); - - const int left = rect.left(); - const int width = rect.width(); - const int bottom = device->size().height() - (rect.bottom() + 1); - const int height = rect.height(); - - glScissor(left, bottom, width, height); - - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - dirty_stencil -= rect; - - glDisable(GL_SCISSOR_TEST); - - enableClipping(); - } - - // Enable stencil. - glEnable(GL_STENCIL_TEST); - - // Disable color writes. - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - - GLuint stencilMask = 0; - - if (fillRule == Qt::OddEvenFill) { - stencilMask = 1; - - // Enable stencil writes. - glStencilMask(stencilMask); - - // Set stencil xor mode. - glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); - - // Disable stencil func. - glStencilFunc(GL_ALWAYS, 0, ~0); - - drawVertexArrays(); - } else if (fillRule == Qt::WindingFill) { - stencilMask = ~0; - - if (has_stencil_face_ext) { - QGL_FUNC_CONTEXT; - glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); - - glActiveStencilFaceEXT(GL_BACK); - glStencilOp(GL_KEEP, GL_KEEP, GL_DECR_WRAP_EXT); - glStencilFunc(GL_ALWAYS, 0, ~0); - - glActiveStencilFaceEXT(GL_FRONT); - glStencilOp(GL_KEEP, GL_KEEP, GL_INCR_WRAP_EXT); - glStencilFunc(GL_ALWAYS, 0, ~0); - - drawVertexArrays(); - - glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); - } else { - glStencilFunc(GL_ALWAYS, 0, ~0); - glEnable(GL_CULL_FACE); - - glCullFace(GL_BACK); - glStencilOp(GL_KEEP, GL_KEEP, GL_INCR_WRAP_EXT); - drawVertexArrays(); - - glCullFace(GL_FRONT); - glStencilOp(GL_KEEP, GL_KEEP, GL_DECR_WRAP_EXT); - drawVertexArrays(); - - glDisable(GL_CULL_FACE); - } - } - - // Enable color writes. - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilMask(stencilMask); - - setGradientOps(cbrush, QRectF(QPointF(min_x, min_y), QSizeF(max_x - min_x, max_y - min_y))); - - bool fast_fill = has_fast_composition_mode && (current_style == Qt::LinearGradientPattern || current_style == Qt::SolidPattern); - - if (use_fragment_programs && !fast_fill) { - DEBUG_ONCE qDebug() << "QOpenGLPaintEnginePrivate: Drawing polygon using stencil method (fragment programs)"; - QRectF rect(QPointF(min_x, min_y), QSizeF(max_x - min_x, max_y - min_y)); - - // Enable stencil func. - glStencilFunc(GL_NOTEQUAL, 0, stencilMask); - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - composite(rect); - } else { - DEBUG_ONCE qDebug() << "QOpenGLPaintEnginePrivate: Drawing polygon using stencil method (no fragment programs)"; - - // Enable stencil func. - glStencilFunc(GL_NOTEQUAL, 0, stencilMask); - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); -#ifndef QT_OPENGL_ES - glBegin(GL_QUADS); - glVertex2f(min_x, min_y); - glVertex2f(max_x, min_y); - glVertex2f(max_x, max_y); - glVertex2f(min_x, max_y); - glEnd(); -#endif - } - - // Disable stencil writes. - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glStencilMask(0); - glDisable(GL_STENCIL_TEST); -} - -void QOpenGLPaintEnginePrivate::fillPath(const QPainterPath &path) -{ - if (path.isEmpty()) - return; - - if (use_stencil_method && !high_quality_antialiasing) { - pathToVertexArrays(path); - fillVertexArray(path.fillRule()); - return; - } - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - if (high_quality_antialiasing) - drawOffscreenPath(path); - else { - QPolygonF poly = path.toFillPolygon(matrix); - fillPolygon_dev(poly.data(), poly.count(), - path.fillRule()); - } - - updateGLMatrix(); -} - -extern bool qt_isExtendedRadialGradient(const QBrush &brush); - -static inline bool needsEmulation(Qt::BrushStyle style) -{ - return !(style == Qt::SolidPattern - || (style == Qt::LinearGradientPattern - && (QGLExtensions::glExtensions() & QGLExtensions::MirroredRepeat))); -} - -void QOpenGLPaintEnginePrivate::updateUseEmulation() -{ - use_emulation = (!use_fragment_programs - && ((has_pen && needsEmulation(pen_brush_style)) - || (has_brush && needsEmulation(brush_style)))) - || (has_pen && qt_isExtendedRadialGradient(cpen.brush())) - || (has_brush && qt_isExtendedRadialGradient(cbrush)); -} - -void QOpenGLPaintEngine::updatePen(const QPen &pen) -{ - Q_D(QOpenGLPaintEngine); - Qt::PenStyle pen_style = pen.style(); - d->pen_brush_style = pen.brush().style(); - d->cpen = pen; - d->has_pen = (pen_style != Qt::NoPen) && (d->pen_brush_style != Qt::NoBrush); - d->updateUseEmulation(); - - if (pen.isCosmetic()) { - GLfloat width = pen.widthF() == 0.0f ? 1.0f : pen.widthF(); - glLineWidth(width); - glPointSize(width); - } - - if (d->pen_brush_style >= Qt::LinearGradientPattern - && d->pen_brush_style <= Qt::ConicalGradientPattern) - { - d->setGLPen(Qt::white); - } else { - d->setGLPen(pen.color()); - } - - d->updateFastPen(); -} - -void QOpenGLPaintEngine::updateBrush(const QBrush &brush, const QPointF &origin) -{ - Q_D(QOpenGLPaintEngine); - d->cbrush = brush; - d->brush_style = brush.style(); - d->brush_origin = origin; - d->has_brush = (d->brush_style != Qt::NoBrush); - d->updateUseEmulation(); -} - -void QOpenGLPaintEngine::updateFont(const QFont &) -{ -} - -void QOpenGLPaintEngine::updateMatrix(const QTransform &mtx) -{ - Q_D(QOpenGLPaintEngine); - - d->matrix = mtx; - - d->mv_matrix[0][0] = mtx.m11(); - d->mv_matrix[0][1] = mtx.m12(); - d->mv_matrix[0][2] = 0; - d->mv_matrix[0][3] = mtx.m13(); - - d->mv_matrix[1][0] = mtx.m21(); - d->mv_matrix[1][1] = mtx.m22(); - d->mv_matrix[1][2] = 0; - d->mv_matrix[1][3] = mtx.m23(); - - d->mv_matrix[2][0] = 0; - d->mv_matrix[2][1] = 0; - d->mv_matrix[2][2] = 1; - d->mv_matrix[2][3] = 0; - - d->mv_matrix[3][0] = mtx.dx(); - d->mv_matrix[3][1] = mtx.dy(); - d->mv_matrix[3][2] = 0; - d->mv_matrix[3][3] = mtx.m33(); - - d->txop = mtx.type(); - - // 1/10000 == 0.0001, so we have good enough res to cover curves - // that span the entire widget... - d->inverseScale = qMax(1 / qMax( qMax(qAbs(mtx.m11()), qAbs(mtx.m22())), - qMax(qAbs(mtx.m12()), qAbs(mtx.m21())) ), - qreal(0.0001)); - - d->updateGLMatrix(); - d->updateFastPen(); -} - -void QOpenGLPaintEnginePrivate::updateGLMatrix() const -{ - glMatrixMode(GL_MODELVIEW); -#ifndef QT_OPENGL_ES - glLoadMatrixd(&mv_matrix[0][0]); -#else - glLoadMatrixf(&mv_matrix[0][0]); -#endif -} - -void QOpenGLPaintEnginePrivate::disableClipping() -{ - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); -} - -void QOpenGLPaintEnginePrivate::enableClipping() -{ - Q_Q(QOpenGLPaintEngine); - if (!q->state()->hasClipping) - return; - - if (q->state()->fastClip.isEmpty()) - glEnable(GL_DEPTH_TEST); - else - updateDepthClip(); // this will enable the scissor test -} - -void QOpenGLPaintEnginePrivate::updateDepthClip() -{ - Q_Q(QOpenGLPaintEngine); - - ++q->state()->depthClipId; - - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - - if (!q->state()->hasClipping) - return; - - QRect fastClip; - if (q->state()->clipEnabled) { - fastClip = q->state()->fastClip; - } else if (use_system_clip && q->systemClip().rects().count() == 1) { - fastClip = q->systemClip().rects().at(0); - } - - if (!fastClip.isEmpty()) { - glEnable(GL_SCISSOR_TEST); - - const int left = fastClip.left(); - const int width = fastClip.width(); - const int bottom = device->size().height() - (fastClip.bottom() + 1); - const int height = fastClip.height(); - - glScissor(left, bottom, width, height); - return; - } - -#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) - glClearDepthf(0.0f); -#else - glClearDepth(0.0f); -#endif - - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - glClear(GL_DEPTH_BUFFER_BIT); - - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glDepthFunc(GL_ALWAYS); - - const QVector rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects(); - - // rectangle count * 2 (triangles) * vertex count * component count (Z omitted) - QDataBuffer clipVertex(rects.size()*2*3*2); - for (int i = 0; i < rects.size(); ++i) { - GLfloat x = GLfloat(rects.at(i).left()); - GLfloat w = GLfloat(rects.at(i).width()); - GLfloat h = GLfloat(rects.at(i).height()); - GLfloat y = GLfloat(rects.at(i).top()); - - // First triangle - clipVertex.add(x); - clipVertex.add(y); - - clipVertex.add(x); - clipVertex.add(y + h); - - clipVertex.add(x + w); - clipVertex.add(y); - - // Second triangle - clipVertex.add(x); - clipVertex.add(y + h); - - clipVertex.add(x + w); - clipVertex.add(y + h); - - clipVertex.add (x + w); - clipVertex.add(y); - } - - if (rects.size()) { - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, clipVertex.data()); - - glDrawArrays(GL_TRIANGLES, 0, rects.size()*2*3); - glDisableClientState(GL_VERTEX_ARRAY); - updateGLMatrix(); - } - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_FALSE); - glDepthFunc(GL_LEQUAL); -} - -void QOpenGLPaintEnginePrivate::systemStateChanged() -{ - Q_Q(QOpenGLPaintEngine); - if (q->painter()->hasClipping()) - q->updateClipRegion(q->painter()->clipRegion(), Qt::ReplaceClip); - else - q->updateClipRegion(QRegion(), Qt::NoClip); -} - -void QOpenGLPaintEngine::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op) -{ - Q_D(QOpenGLPaintEngine); - - // clipping is only supported when a stencil or depth buffer is - // available - if (!d->device->format().depth()) - return; - - d->use_system_clip = false; - QRegion sysClip = systemClip(); - if (!sysClip.isEmpty()) { - if (d->pdev->devType() != QInternal::Widget) { - d->use_system_clip = true; - } else { -#ifndef Q_WS_QWS - // Only use the system clip if we're currently rendering a widget with a GL painter. - if (d->currentClipDevice) { - QWidgetPrivate *widgetPrivate = qt_widget_private(static_cast(d->currentClipDevice)->window()); - d->use_system_clip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; - } -#endif - } - } - - d->flushDrawQueue(); - - if (op == Qt::NoClip && !d->use_system_clip) { - state()->hasClipping = false; - state()->clipRegion = QRegion(); - d->updateDepthClip(); - return; - } - - bool isScreenClip = false; - if (!d->use_system_clip) { - QVector untransformedRects = clipRegion.rects(); - - if (untransformedRects.size() == 1) { - QPainterPath path; - path.addRect(untransformedRects[0]); - path = d->matrix.map(path); - - if (path.contains(QRectF(QPointF(), d->device->size()))) - isScreenClip = true; - } - } - - QRegion region = isScreenClip ? QRegion() : clipRegion * d->matrix; - switch (op) { - case Qt::NoClip: - if (!d->use_system_clip) - break; - state()->clipRegion = sysClip; - break; - case Qt::IntersectClip: - if (isScreenClip) - return; - if (state()->hasClipping) { - state()->clipRegion &= region; - break; - } - // fall through - case Qt::ReplaceClip: - if (d->use_system_clip) - state()->clipRegion = region & sysClip; - else - state()->clipRegion = region; - break; - default: - break; - } - - if (isScreenClip) { - state()->hasClipping = false; - state()->clipRegion = QRegion(); - } else { - state()->hasClipping = op != Qt::NoClip || d->use_system_clip; - } - - if (state()->hasClipping && state()->clipRegion.rects().size() == 1) - state()->fastClip = state()->clipRegion.rects().at(0); - else - state()->fastClip = QRect(); - - d->updateDepthClip(); -} - -void QOpenGLPaintEngine::updateRenderHints(QPainter::RenderHints hints) -{ - Q_D(QOpenGLPaintEngine); - - d->flushDrawQueue(); - d->use_smooth_pixmap_transform = bool(hints & QPainter::SmoothPixmapTransform); - if ((hints & QPainter::Antialiasing) || (hints & QPainter::HighQualityAntialiasing)) { - if (d->use_fragment_programs && QGLOffscreen::isSupported() - && (hints & QPainter::HighQualityAntialiasing)) { - d->high_quality_antialiasing = true; - } else { - d->high_quality_antialiasing = false; - if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers) - glEnable(GL_MULTISAMPLE); - } - } else { - d->high_quality_antialiasing = false; - if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers) - glDisable(GL_MULTISAMPLE); - } - - if (d->high_quality_antialiasing) { - d->offscreen.initialize(); - - if (!d->offscreen.isValid()) { - DEBUG_ONCE_STR("Unable to initialize offscreen, disabling high quality antialiasing"); - d->high_quality_antialiasing = false; - if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers) - glEnable(GL_MULTISAMPLE); - } - } - - d->has_antialiasing = d->high_quality_antialiasing - || ((hints & QPainter::Antialiasing) - && (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)); -} - - -void QOpenGLPaintEnginePrivate::setPorterDuffData(float a, float b, float x, float y, float z) -{ - porterduff_ab_data[0] = a; - porterduff_ab_data[1] = b; - - porterduff_xyz_data[0] = x; - porterduff_xyz_data[1] = y; - porterduff_xyz_data[2] = z; -} - - -void QOpenGLPaintEngine::updateCompositionMode(QPainter::CompositionMode composition_mode) -{ - Q_D(QOpenGLPaintEngine); - - if (!d->use_fragment_programs && composition_mode > QPainter::CompositionMode_Plus) - composition_mode = QPainter::CompositionMode_SourceOver; - - d->composition_mode = composition_mode; - - d->has_fast_composition_mode = (!d->high_quality_antialiasing && composition_mode <= QPainter::CompositionMode_Plus) - || composition_mode == QPainter::CompositionMode_SourceOver - || composition_mode == QPainter::CompositionMode_Destination - || composition_mode == QPainter::CompositionMode_DestinationOver - || composition_mode == QPainter::CompositionMode_DestinationOut - || composition_mode == QPainter::CompositionMode_SourceAtop - || composition_mode == QPainter::CompositionMode_Xor - || composition_mode == QPainter::CompositionMode_Plus; - - if (d->has_fast_composition_mode) - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODE_BLEND_MODE_MASK : COMPOSITION_MODE_BLEND_MODE_NOMASK; - else if (composition_mode <= QPainter::CompositionMode_Plus) - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_SIMPLE_PORTER_DUFF : COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK; - else - switch (composition_mode) { - case QPainter::CompositionMode_Multiply: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_MULTIPLY : COMPOSITION_MODES_MULTIPLY_NOMASK; - break; - case QPainter::CompositionMode_Screen: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_SCREEN : COMPOSITION_MODES_SCREEN_NOMASK; - break; - case QPainter::CompositionMode_Overlay: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_OVERLAY : COMPOSITION_MODES_OVERLAY_NOMASK; - break; - case QPainter::CompositionMode_Darken: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_DARKEN : COMPOSITION_MODES_DARKEN_NOMASK; - break; - case QPainter::CompositionMode_Lighten: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_LIGHTEN : COMPOSITION_MODES_LIGHTEN_NOMASK; - break; - case QPainter::CompositionMode_ColorDodge: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_COLORDODGE : COMPOSITION_MODES_COLORDODGE_NOMASK; - break; - case QPainter::CompositionMode_ColorBurn: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_COLORBURN : COMPOSITION_MODES_COLORBURN_NOMASK; - break; - case QPainter::CompositionMode_HardLight: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_HARDLIGHT : COMPOSITION_MODES_HARDLIGHT_NOMASK; - break; - case QPainter::CompositionMode_SoftLight: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_SOFTLIGHT : COMPOSITION_MODES_SOFTLIGHT_NOMASK; - break; - case QPainter::CompositionMode_Difference: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_DIFFERENCE : COMPOSITION_MODES_DIFFERENCE_NOMASK; - break; - case QPainter::CompositionMode_Exclusion: - d->fragment_composition_mode = d->high_quality_antialiasing ? COMPOSITION_MODES_EXCLUSION : COMPOSITION_MODES_EXCLUSION_NOMASK; - break; - default: - Q_ASSERT(false); - } - - switch(composition_mode) { - case QPainter::CompositionMode_DestinationOver: - glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE); - d->setPorterDuffData(0, 1, 1, 1, 1); - break; - case QPainter::CompositionMode_Clear: - glBlendFunc(GL_ZERO, GL_ZERO); - d->setPorterDuffData(0, 0, 0, 0, 0); - break; - case QPainter::CompositionMode_Source: - glBlendFunc(GL_ONE, GL_ZERO); - d->setPorterDuffData(1, 0, 1, 1, 0); - break; - case QPainter::CompositionMode_Destination: - glBlendFunc(GL_ZERO, GL_ONE); - d->setPorterDuffData(0, 1, 1, 0, 1); - break; - case QPainter::CompositionMode_SourceIn: - glBlendFunc(GL_DST_ALPHA, GL_ZERO); - d->setPorterDuffData(1, 0, 1, 0, 0); - break; - case QPainter::CompositionMode_DestinationIn: - glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - d->setPorterDuffData(0, 1, 1, 0, 0); - break; - case QPainter::CompositionMode_SourceOut: - glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO); - d->setPorterDuffData(0, 0, 0, 1, 0); - break; - case QPainter::CompositionMode_DestinationOut: - glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); - d->setPorterDuffData(0, 0, 0, 0, 1); - break; - case QPainter::CompositionMode_SourceAtop: - glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - d->setPorterDuffData(1, 0, 1, 0, 1); - break; - case QPainter::CompositionMode_DestinationAtop: - glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA); - d->setPorterDuffData(0, 1, 1, 1, 0); - break; - case QPainter::CompositionMode_Xor: - glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - d->setPorterDuffData(0, 0, 0, 1, 1); - break; - case QPainter::CompositionMode_SourceOver: - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - d->setPorterDuffData(1, 0, 1, 1, 1); - break; - case QPainter::CompositionMode_Plus: - glBlendFunc(GL_ONE, GL_ONE); - d->setPorterDuffData(1, 1, 1, 1, 1); - break; - default: - break; - } -} - -class QGLMaskGenerator -{ -public: - QGLMaskGenerator(const QPainterPath &path, const QTransform &matrix, qreal stroke_width = -1) - : p(path), - m(matrix), - w(stroke_width) - { - } - - virtual QRect screenRect() = 0; - virtual void drawMask(const QRect &rect) = 0; - - QPainterPath path() const { return p; } - QTransform matrix() const { return m; } - qreal strokeWidth() const { return w; } - - virtual ~QGLMaskGenerator() {} - -private: - QPainterPath p; - QTransform m; - qreal w; -}; - -void QGLMaskTextureCache::setOffscreenSize(const QSize &sz) -{ - Q_ASSERT(sz.width() == sz.height()); - - if (offscreenSize != sz) { - offscreenSize = sz; - clearCache(); - } -} - -void QGLMaskTextureCache::clearCache() -{ - cache.clear(); - - int quad_tree_size = 1; - - for (int i = block_size; i < offscreenSize.width(); i *= 2) - quad_tree_size += quad_tree_size * 4; - - for (int i = 0; i < 4; ++i) { - occupied_quadtree[i].resize(quad_tree_size); - - occupied_quadtree[i][0].key = 0; - occupied_quadtree[i][0].largest_available_block = offscreenSize.width(); - occupied_quadtree[i][0].largest_used_block = 0; - - DEBUG_ONCE qDebug() << "QGLMaskTextureCache:: created quad tree of size" << quad_tree_size; - } -} - -void QGLMaskTextureCache::setDrawableSize(const QSize &sz) -{ - drawableSize = sz; -} - -void QGLMaskTextureCache::maintainCache() -{ - QGLTextureCacheHash::iterator it = cache.begin(); - QGLTextureCacheHash::iterator end = cache.end(); - - while (it != end) { - CacheInfo &cache_info = it.value(); - ++cache_info.age; - - if (cache_info.age > 1) { - quadtreeInsert(cache_info.loc.channel, 0, cache_info.loc.rect); - it = cache.erase(it); - } else { - ++it; - } - } -} - -//#define DISABLE_MASK_CACHE - -QGLMaskTextureCache::CacheLocation QGLMaskTextureCache::getMask(QGLMaskGenerator &maskGenerator, QOpenGLPaintEnginePrivate *e) -{ -#ifndef DISABLE_MASK_CACHE - engine = e; - - quint64 key = hash(maskGenerator.path(), maskGenerator.matrix(), maskGenerator.strokeWidth()); - - if (key == 0) - key = 1; - - CacheInfo info(maskGenerator.path(), maskGenerator.matrix(), maskGenerator.strokeWidth()); - - QGLTextureCacheHash::iterator it = cache.find(key); - - while (it != cache.end() && it.key() == key) { - CacheInfo &cache_info = it.value(); - if (info.stroke_width == cache_info.stroke_width && info.matrix == cache_info.matrix && info.path == cache_info.path) { - DEBUG_ONCE_STR("QGLMaskTextureCache::getMask(): Using cached mask"); - - cache_info.age = 0; - return cache_info.loc; - } - ++it; - } - - // mask was not found, create new mask - - DEBUG_ONCE_STR("QGLMaskTextureCache::getMask(): Creating new mask..."); - - createMask(key, info, maskGenerator); - - cache.insert(key, info); - - return info.loc; -#else - CacheInfo info(maskGenerator.path(), maskGenerator.matrix()); - createMask(0, info, maskGenerator); - return info.loc; -#endif -} - -#ifndef FloatToQuint64 -#define FloatToQuint64(i) (quint64)((i) * 32) -#endif - -quint64 QGLMaskTextureCache::hash(const QPainterPath &p, const QTransform &m, qreal w) -{ - Q_ASSERT(sizeof(quint64) == 8); - - quint64 h = 0; - - for (int i = 0; i < p.elementCount(); ++i) { - h += FloatToQuint64(p.elementAt(i).x) << 32; - h += FloatToQuint64(p.elementAt(i).y); - h += p.elementAt(i).type; - } - - h += FloatToQuint64(m.m11()); -#ifndef Q_OS_WINCE // ### - //Compiler crashes for arm on WinCE - h += FloatToQuint64(m.m12()) << 4; - h += FloatToQuint64(m.m13()) << 8; - h += FloatToQuint64(m.m21()) << 12; - h += FloatToQuint64(m.m22()) << 16; - h += FloatToQuint64(m.m23()) << 20; - h += FloatToQuint64(m.m31()) << 24; - h += FloatToQuint64(m.m32()) << 28; -#endif - h += FloatToQuint64(m.m33()) << 32; - - h += FloatToQuint64(w); - - return h; -} - -void QGLMaskTextureCache::createMask(quint64 key, CacheInfo &info, QGLMaskGenerator &maskGenerator) -{ - info.loc.screen_rect = maskGenerator.screenRect(); - - if (info.loc.screen_rect.isEmpty()) { - info.loc.channel = 0; - info.loc.rect = QRect(); - return; - } - - quadtreeAllocate(key, info.loc.screen_rect.size(), &info.loc.rect, &info.loc.channel); - - int ch = info.loc.channel; - glColorMask(ch == 0, ch == 1, ch == 2, ch == 3); - - maskGenerator.drawMask(info.loc.rect); - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); -} - -int QGLMaskTextureCache::quadtreeBlocksize(int node) -{ - DEBUG_ONCE qDebug() << "Offscreen size:" << offscreenSize.width(); - - int blocksize = offscreenSize.width(); - - while (node) { - node = (node - 1) / 4; - blocksize /= 2; - } - - return blocksize; -} - -QPoint QGLMaskTextureCache::quadtreeLocation(int node) -{ - QPoint location; - int blocksize = quadtreeBlocksize(node); - - while (node) { - --node; - - if (node & 1) - location.setX(location.x() + blocksize); - - if (node & 2) - location.setY(location.y() + blocksize); - - node /= 4; - blocksize *= 2; - } - - return location; -} - -void QGLMaskTextureCache::quadtreeUpdate(int channel, int node, int current_block_size) -{ - while (node) { - node = (node - 1) / 4; - - int first_child = node * 4 + 1; - - int largest_available = 0; - int largest_used = 0; - - bool all_empty = true; - - for (int i = 0; i < 4; ++i) { - largest_available = qMax(largest_available, occupied_quadtree[channel][first_child + i].largest_available_block); - largest_used = qMax(largest_used, occupied_quadtree[channel][first_child + i].largest_used_block); - - if (occupied_quadtree[channel][first_child + i].largest_available_block < current_block_size) - all_empty = false; - } - - current_block_size *= 2; - - if (all_empty) { - occupied_quadtree[channel][node].largest_available_block = current_block_size; - occupied_quadtree[channel][node].largest_used_block = 0; - } else { - occupied_quadtree[channel][node].largest_available_block = largest_available; - occupied_quadtree[channel][node].largest_used_block = largest_used; - } - } -} - -void QGLMaskTextureCache::quadtreeInsert(int channel, quint64 key, const QRect &rect, int node) -{ - int current_block_size = quadtreeBlocksize(node); - QPoint location = quadtreeLocation(node); - QRect relative = rect.translated(-location); - - if (relative.left() >= current_block_size || relative.top() >= current_block_size - || relative.right() < 0 || relative.bottom() < 0) - return; - - if (current_block_size == block_size // no more refining possible - || (relative.top() < block_size && relative.bottom() >= (current_block_size - block_size) - && relative.left() < block_size && relative.right() >= (current_block_size - block_size))) - { - if (key != 0) { - occupied_quadtree[channel][node].largest_available_block = 0; - occupied_quadtree[channel][node].largest_used_block = rect.width() * rect.height(); - } else { - occupied_quadtree[channel][node].largest_available_block = current_block_size; - occupied_quadtree[channel][node].largest_used_block = 0; - } - - occupied_quadtree[channel][node].key = key; - - quadtreeUpdate(channel, node, current_block_size); - } else { - if (key && occupied_quadtree[channel][node].largest_available_block == current_block_size) { - // refining the quad tree, initialize child nodes - int half_block_size = current_block_size / 2; - - int temp = node * 4 + 1; - for (int sibling = 0; sibling < 4; ++sibling) { - occupied_quadtree[channel][temp + sibling].largest_available_block = half_block_size; - occupied_quadtree[channel][temp + sibling].largest_used_block = 0; - occupied_quadtree[channel][temp + sibling].key = 0; - } - } - - node = node * 4 + 1; - - for (int sibling = 0; sibling < 4; ++sibling) - quadtreeInsert(channel, key, rect, node + sibling); - } -} - -void QGLMaskTextureCache::quadtreeClear(int channel, const QRect &rect, int node) -{ - const quint64 &key = occupied_quadtree[channel][node].key; - - int current_block_size = quadtreeBlocksize(node); - QPoint location = quadtreeLocation(node); - - QRect relative = rect.translated(-location); - - if (relative.left() >= current_block_size || relative.top() >= current_block_size - || relative.right() < 0 || relative.bottom() < 0) - return; - - if (key != 0) { - QGLTextureCacheHash::iterator it = cache.find(key); - - Q_ASSERT(it != cache.end()); - - while (it != cache.end() && it.key() == key) { - const CacheInfo &cache_info = it.value(); - - if (cache_info.loc.channel == channel - && cache_info.loc.rect.left() <= location.x() - && cache_info.loc.rect.top() <= location.y() - && cache_info.loc.rect.right() >= location.x() - && cache_info.loc.rect.bottom() >= location.y()) - { - quadtreeInsert(channel, 0, cache_info.loc.rect); - engine->cacheItemErased(channel, cache_info.loc.rect); - cache.erase(it); - goto found; - } else { - ++it; - } - } - - // if we don't find the key there's an error in the quadtree - Q_ASSERT(false); -found: - Q_ASSERT(occupied_quadtree[channel][node].key == 0); - } else if (occupied_quadtree[channel][node].largest_available_block < current_block_size) { - Q_ASSERT(current_block_size >= block_size); - - node = node * 4 + 1; - - for (int sibling = 0; sibling < 4; ++sibling) - quadtreeClear(channel, rect, node + sibling); - } -} - -bool QGLMaskTextureCache::quadtreeFindAvailableLocation(const QSize &size, QRect *rect, int *channel) -{ - int needed_block_size = qMax(1, qMax(size.width(), size.height())); - - for (int i = 0; i < 4; ++i) { - int current_block_size = offscreenSize.width(); - - if (occupied_quadtree[i][0].largest_available_block >= needed_block_size) { - int node = 0; - - while (current_block_size != occupied_quadtree[i][node].largest_available_block) { - Q_ASSERT(current_block_size > block_size); - Q_ASSERT(current_block_size > occupied_quadtree[i][node].largest_available_block); - - node = node * 4 + 1; - current_block_size /= 2; - - int sibling = 0; - - while (occupied_quadtree[i][node + sibling].largest_available_block < needed_block_size) - ++sibling; - - Q_ASSERT(sibling < 4); - node += sibling; - } - - *channel = i; - *rect = QRect(quadtreeLocation(node), size); - - return true; - } - } - - return false; -} - -void QGLMaskTextureCache::quadtreeFindExistingLocation(const QSize &size, QRect *rect, int *channel) -{ - // try to pick small masks to throw out, as large masks are more expensive to recompute - *channel = qrand() % 4; - for (int i = 0; i < 4; ++i) - if (occupied_quadtree[i][0].largest_used_block < occupied_quadtree[*channel][0].largest_used_block) - *channel = i; - - int needed_block_size = qt_next_power_of_two(qMax(1, qMax(size.width(), size.height()))); - - int node = 0; - int current_block_size = offscreenSize.width(); - - while (current_block_size > block_size - && current_block_size >= needed_block_size * 2 - && occupied_quadtree[*channel][node].key == 0) - { - node = node * 4 + 1; - - int sibling = 0; - - for (int i = 1; i < 4; ++i) { - if (occupied_quadtree[*channel][node + i].largest_used_block - <= occupied_quadtree[*channel][node + sibling].largest_used_block) - { - sibling = i; - } - } - - node += sibling; - current_block_size /= 2; - } - - *rect = QRect(quadtreeLocation(node), size); -} - -void QGLMaskTextureCache::quadtreeAllocate(quint64 key, const QSize &size, QRect *rect, int *channel) -{ -#ifndef DISABLE_MASK_CACHE - if (!quadtreeFindAvailableLocation(size, rect, channel)) { - quadtreeFindExistingLocation(size, rect, channel); - quadtreeClear(*channel, *rect); - } - - quadtreeInsert(*channel, key, *rect); -#else - *channel = 0; - *rect = QRect(QPoint(), size); -#endif -} - -class QGLTrapezoidMaskGenerator : public QGLMaskGenerator -{ -public: - QGLTrapezoidMaskGenerator(const QPainterPath &path, const QTransform &matrix, QGLOffscreen &offscreen, GLuint maskFragmentProgram, qreal strokeWidth = -1.0); - - QRect screenRect(); - void drawMask(const QRect &rect); - -private: - QRect screen_rect; - bool has_screen_rect; - - QGLOffscreen *offscreen; - - GLuint maskFragmentProgram; - - virtual QVector generateTrapezoids() = 0; - virtual QRect computeScreenRect() = 0; -}; - -class QGLPathMaskGenerator : public QGLTrapezoidMaskGenerator -{ -public: - QGLPathMaskGenerator(const QPainterPath &path, const QTransform &matrix, QGLOffscreen &offscreen, GLuint maskFragmentProgram); - -private: - QVector generateTrapezoids(); - QRect computeScreenRect(); - - QPolygonF poly; -}; - -class QGLLineMaskGenerator : public QGLTrapezoidMaskGenerator -{ -public: - QGLLineMaskGenerator(const QPainterPath &path, const QTransform &matrix, qreal width, QGLOffscreen &offscreen, GLuint maskFragmentProgram); - -private: - QVector generateTrapezoids(); - QRect computeScreenRect(); - - QPainterPath transformedPath; -}; - -class QGLRectMaskGenerator : public QGLTrapezoidMaskGenerator -{ -public: - QGLRectMaskGenerator(const QPainterPath &path, const QTransform &matrix, QGLOffscreen &offscreen, GLuint maskFragmentProgram); - -private: - QVector generateTrapezoids(); - QRect computeScreenRect(); - - QPainterPath transformedPath; -}; - -class QGLEllipseMaskGenerator : public QGLMaskGenerator -{ -public: - QGLEllipseMaskGenerator(const QRectF &rect, const QTransform &matrix, QGLOffscreen &offscreen, GLuint maskFragmentProgram, int *maskVariableLocations); - - QRect screenRect(); - void drawMask(const QRect &rect); - -private: - QRect screen_rect; - - QRectF ellipseRect; - - QGLOffscreen *offscreen; - - GLuint maskFragmentProgram; - - int *maskVariableLocations; - - float vertexArray[4 * 2]; -}; - -QGLTrapezoidMaskGenerator::QGLTrapezoidMaskGenerator(const QPainterPath &path, const QTransform &matrix, QGLOffscreen &offs, GLuint program, qreal stroke_width) - : QGLMaskGenerator(path, matrix, stroke_width) - , has_screen_rect(false) - , offscreen(&offs) - , maskFragmentProgram(program) -{ -} - -extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); -extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *array); - -void QGLTrapezoidMaskGenerator::drawMask(const QRect &rect) -{ -#ifdef QT_OPENGL_ES - Q_UNUSED(rect); -#else - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - QGLContext *ctx = offscreen->context(); - offscreen->bind(); - - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_1D); - - GLfloat vertexArray[4 * 2]; - qt_add_rect_to_array(rect, vertexArray); - - bool needs_scissor = rect != screen_rect; - - if (needs_scissor) { - glEnable(GL_SCISSOR_TEST); - glScissor(rect.left(), offscreen->offscreenSize().height() - rect.bottom() - 1, rect.width(), rect.height()); - } - - QVector trapezoids = generateTrapezoids(); - - // clear mask - glBlendFunc(GL_ZERO, GL_ZERO); // clear - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glEnableClientState(GL_VERTEX_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - - glBlendFunc(GL_ONE, GL_ONE); // add mask - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, maskFragmentProgram); - - QPoint delta = rect.topLeft() - screen_rect.topLeft(); - glBegin(GL_QUADS); - for (int i = 0; i < trapezoids.size(); ++i) - drawTrapezoid(trapezoids[i].translated(delta), offscreen->offscreenSize().height(), ctx); - glEnd(); - - if (needs_scissor) - glDisable(GL_SCISSOR_TEST); - - glDisable(GL_FRAGMENT_PROGRAM_ARB); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); -#endif -} - -QRect QGLTrapezoidMaskGenerator::screenRect() -{ - if (!has_screen_rect) { - screen_rect = computeScreenRect(); - has_screen_rect = true; - } - - screen_rect = screen_rect.intersected(QRect(QPoint(), offscreen->drawableSize())); - - return screen_rect; -} - -QGLPathMaskGenerator::QGLPathMaskGenerator(const QPainterPath &path, const QTransform &matrix, QGLOffscreen &offs, GLuint program) - : QGLTrapezoidMaskGenerator(path, matrix, offs, program) -{ -} - -QRect QGLPathMaskGenerator::computeScreenRect() -{ - poly = path().toFillPolygon(matrix()); - return poly.boundingRect().toAlignedRect(); -} - -QVector QGLPathMaskGenerator::generateTrapezoids() -{ - QOpenGLImmediateModeTessellator tessellator; - tessellator.tessellate(poly.data(), poly.count(), path().fillRule() == Qt::WindingFill); - return tessellator.trapezoids; -} - -QGLRectMaskGenerator::QGLRectMaskGenerator(const QPainterPath &path, const QTransform &matrix, QGLOffscreen &offs, GLuint program) - : QGLTrapezoidMaskGenerator(path, matrix, offs, program) -{ -} - -QGLLineMaskGenerator::QGLLineMaskGenerator(const QPainterPath &path, const QTransform &matrix, qreal width, QGLOffscreen &offs, GLuint program) - : QGLTrapezoidMaskGenerator(path, matrix, offs, program, width) -{ -} - -QRect QGLRectMaskGenerator::computeScreenRect() -{ - transformedPath = matrix().map(path()); - - return transformedPath.controlPointRect().adjusted(-1, -1, 1, 1).toAlignedRect(); -} - -QRect QGLLineMaskGenerator::computeScreenRect() -{ - transformedPath = matrix().map(path()); - - return transformedPath.controlPointRect().adjusted(-1, -1, 1, 1).toAlignedRect(); -} - -QVector QGLLineMaskGenerator::generateTrapezoids() -{ - QOpenGLImmediateModeTessellator tessellator; - QPointF last; - for (int i = 0; i < transformedPath.elementCount(); ++i) { - QPainterPath::Element element = transformedPath.elementAt(i); - - Q_ASSERT(!element.isCurveTo()); - - if (element.isLineTo()) - tessellator.tessellateRect(last, element, strokeWidth()); - - last = element; - } - - return tessellator.trapezoids; -} - -QVector QGLRectMaskGenerator::generateTrapezoids() -{ - Q_ASSERT(transformedPath.elementCount() == 5); - - QOpenGLImmediateModeTessellator tessellator; - if (matrix().type() <= QTransform::TxScale) { - QPointF a = transformedPath.elementAt(0); - QPointF b = transformedPath.elementAt(1); - QPointF c = transformedPath.elementAt(2); - QPointF d = transformedPath.elementAt(3); - - QPointF first = (a + d) * 0.5; - QPointF last = (b + c) * 0.5; - - QPointF delta = a - d; - - // manhattan distance (no rotation) - qreal width = qAbs(delta.x()) + qAbs(delta.y()); - - Q_ASSERT(qFuzzyIsNull(delta.x()) || qFuzzyIsNull(delta.y())); - - tessellator.tessellateRect(first, last, width); - } else { - QPointF points[5]; - - for (int i = 0; i < 5; ++i) - points[i] = transformedPath.elementAt(i); - - tessellator.tessellateConvex(points, 5); - } - return tessellator.trapezoids; -} - -static QPainterPath ellipseRectToPath(const QRectF &rect) -{ - QPainterPath path; - path.addEllipse(rect); - return path; -} - -QGLEllipseMaskGenerator::QGLEllipseMaskGenerator(const QRectF &rect, const QTransform &matrix, QGLOffscreen &offs, GLuint program, int *locations) - : QGLMaskGenerator(ellipseRectToPath(rect), matrix), - ellipseRect(rect), - offscreen(&offs), - maskFragmentProgram(program), - maskVariableLocations(locations) -{ -} - -QRect QGLEllipseMaskGenerator::screenRect() -{ - QPointF center = ellipseRect.center(); - - QPointF points[] = { - QPointF(ellipseRect.left(), center.y()), - QPointF(ellipseRect.right(), center.y()), - QPointF(center.x(), ellipseRect.top()), - QPointF(center.x(), ellipseRect.bottom()) - }; - - qreal min_screen_delta_len = QREAL_MAX; - - for (int i = 0; i < 4; ++i) { - QPointF delta = points[i] - center; - - // normalize - delta /= qSqrt(delta.x() * delta.x() + delta.y() * delta.y()); - - QPointF screen_delta(matrix().m11() * delta.x() + matrix().m21() * delta.y(), - matrix().m12() * delta.x() + matrix().m22() * delta.y()); - - min_screen_delta_len = qMin(min_screen_delta_len, - qreal(qSqrt(screen_delta.x() * screen_delta.x() + screen_delta.y() * screen_delta.y()))); - } - - const qreal padding = 2.0f; - - qreal grow = padding / min_screen_delta_len; - - QRectF boundingRect = ellipseRect.adjusted(-grow, -grow, grow, grow); - - boundingRect = matrix().mapRect(boundingRect); - - QPointF p(0.5, 0.5); - - screen_rect = QRect((boundingRect.topLeft() - p).toPoint(), - (boundingRect.bottomRight() + p).toPoint()); - - return screen_rect; -} - -void QGLEllipseMaskGenerator::drawMask(const QRect &rect) -{ -#ifdef QT_OPENGL_ES - Q_UNUSED(rect); -#else - QGLContext *ctx = offscreen->context(); - offscreen->bind(); - - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_1D); - - // fragment program needs the inverse radii of the ellipse - glTexCoord2f(1.0f / (ellipseRect.width() * 0.5f), - 1.0f / (ellipseRect.height() * 0.5f)); - - QTransform translate(1, 0, 0, 1, -ellipseRect.center().x(), -ellipseRect.center().y()); - QTransform gl_to_qt(1, 0, 0, -1, 0, offscreen->drawableSize().height()); - QTransform inv_matrix = gl_to_qt * matrix().inverted() * translate; - - float m[3][4] = { { float(inv_matrix.m11()), float(inv_matrix.m12()), float(inv_matrix.m13()) }, - { float(inv_matrix.m21()), float(inv_matrix.m22()), float(inv_matrix.m23()) }, - { float(inv_matrix.m31()), float(inv_matrix.m32()), float(inv_matrix.m33()) } }; - - QPoint offs(screen_rect.left() - rect.left(), (offscreen->drawableSize().height() - screen_rect.top()) - - (offscreen->offscreenSize().height() - rect.top())); - - // last component needs to be 1.0f to avoid Nvidia bug on linux - float ellipse_offset[4] = { float(offs.x()), float(offs.y()), 0.0f, 1.0f }; - - GLfloat vertexArray[4 * 2]; - qt_add_rect_to_array(rect, vertexArray); - - glBlendFunc(GL_ONE, GL_ZERO); // set mask - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, maskFragmentProgram); - - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_INV_MATRIX_M0], m[0]); - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_INV_MATRIX_M1], m[1]); - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_INV_MATRIX_M2], m[2]); - - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_ELLIPSE_OFFSET], ellipse_offset); - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_FRAGMENT_PROGRAM_ARB); -#endif -} - -void QOpenGLPaintEnginePrivate::drawOffscreenPath(const QPainterPath &path) -{ -#ifdef Q_WS_QWS - Q_UNUSED(path); -#else - DEBUG_ONCE_STR("QOpenGLPaintEnginePrivate::drawOffscreenPath()"); - - disableClipping(); - - 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)); - - enableClipping(); -#endif -} - -void QOpenGLPaintEnginePrivate::drawFastRect(const QRectF &r) -{ - Q_Q(QOpenGLPaintEngine); - DEBUG_ONCE_STR("QOpenGLPaintEngine::drawRects(): drawing fast rect"); - - GLfloat vertexArray[10]; - qt_add_rect_to_array(r, vertexArray); - - if (has_pen) - QOpenGLCoordinateOffset::enableOffset(this); - - if (has_brush) { - flushDrawQueue(); - - bool temp = high_quality_antialiasing; - high_quality_antialiasing = false; - - q->updateCompositionMode(composition_mode); - - setGradientOps(cbrush, r); - - bool fast_style = current_style == Qt::LinearGradientPattern - || current_style == Qt::SolidPattern; - - if (fast_style && has_fast_composition_mode) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - } else { - composite(r); - } - - high_quality_antialiasing = temp; - - q->updateCompositionMode(composition_mode); - } - - if (has_pen) { - if (has_fast_pen && !high_quality_antialiasing) { - setGradientOps(cpen.brush(), r); - - vertexArray[8] = vertexArray[0]; - vertexArray[9] = vertexArray[1]; - - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glEnableClientState(GL_VERTEX_ARRAY); - glDrawArrays(GL_LINE_STRIP, 0, 5); - glDisableClientState(GL_VERTEX_ARRAY); - } else { - QPainterPath path; - path.setFillRule(Qt::WindingFill); - - qreal left = r.left(); - qreal right = r.right(); - qreal top = r.top(); - qreal bottom = r.bottom(); - - path.moveTo(left, top); - path.lineTo(right, top); - path.lineTo(right, bottom); - path.lineTo(left, bottom); - path.lineTo(left, top); - - strokePath(path, false); - } - - QOpenGLCoordinateOffset::disableOffset(this); - } -} - -bool QOpenGLPaintEnginePrivate::isFastRect(const QRectF &rect) -{ - if (matrix.type() < QTransform::TxRotate) { - QRectF r = matrix.mapRect(rect); - return r.topLeft().toPoint() == r.topLeft() - && r.bottomRight().toPoint() == r.bottomRight(); - } - - return false; -} - -void QOpenGLPaintEngine::drawRects(const QRect *rects, int rectCount) -{ - struct RectF { - qreal x; - qreal y; - qreal w; - qreal h; - }; - Q_ASSERT(sizeof(RectF) == sizeof(QRectF)); - RectF fr[256]; - while (rectCount) { - int i = 0; - while (i < rectCount && i < 256) { - fr[i].x = rects[i].x(); - fr[i].y = rects[i].y(); - fr[i].w = rects[i].width(); - fr[i].h = rects[i].height(); - ++i; - } - drawRects((QRectF *)(void *)fr, i); - rects += i; - rectCount -= i; - } -} - -void QOpenGLPaintEngine::drawRects(const QRectF *rects, int rectCount) -{ - Q_D(QOpenGLPaintEngine); - - if (d->use_emulation) { - QPaintEngineEx::drawRects(rects, rectCount); - return; - } - - for (int i=0; ihigh_quality_antialiasing || d->isFastRect(r)) { - d->drawFastRect(r); - } else { - QPainterPath path; - path.addRect(r); - - if (d->has_brush) { - d->disableClipping(); - GLuint program = qt_gl_program_cache()->getProgram(d->device->context(), - FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, 0, true); - - if (d->matrix.type() >= QTransform::TxProject) { - QGLPathMaskGenerator maskGenerator(path, d->matrix, d->offscreen, program); - d->addItem(qt_mask_texture_cache()->getMask(maskGenerator, d)); - } else { - QGLRectMaskGenerator maskGenerator(path, d->matrix, d->offscreen, program); - d->addItem(qt_mask_texture_cache()->getMask(maskGenerator, d)); - } - - d->enableClipping(); - } - - if (d->has_pen) { - if (d->has_fast_pen) - d->strokeLines(path); - else - d->strokePath(path, false); - } - } - } -} - -static void addQuadAsTriangle(GLfloat *quad, GLfloat *triangle) -{ - triangle[0] = quad[0]; - triangle[1] = quad[1]; - - triangle[2] = quad[2]; - triangle[3] = quad[3]; - - triangle[4] = quad[4]; - triangle[5] = quad[5]; - - triangle[6] = quad[4]; - triangle[7] = quad[5]; - - triangle[8] = quad[6]; - triangle[9] = quad[7]; - - triangle[10] = quad[0]; - triangle[11] = quad[1]; -} - -void QOpenGLPaintEngine::drawPoints(const QPoint *points, int pointCount) -{ - Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF)); - QT_PointF fp[256]; - while (pointCount) { - int i = 0; - while (i < pointCount && i < 256) { - fp[i].x = points[i].x(); - fp[i].y = points[i].y(); - ++i; - } - drawPoints((QPointF *)(void *)fp, i); - points += i; - pointCount -= i; - } -} - -void QOpenGLPaintEngine::drawPoints(const QPointF *points, int pointCount) -{ - Q_D(QOpenGLPaintEngine); - - if (d->use_emulation) { - QPaintEngineEx::drawPoints(points, pointCount); - return; - } - - d->setGradientOps(d->cpen.brush(), QRectF()); - - if (!d->cpen.isCosmetic() || d->high_quality_antialiasing) { - Qt::PenCapStyle capStyle = d->cpen.capStyle(); - if (capStyle == Qt::FlatCap) - d->cpen.setCapStyle(Qt::SquareCap); - QPaintEngine::drawPoints(points, pointCount); - d->cpen.setCapStyle(capStyle); - return; - } - - d->flushDrawQueue(); - - if (d->has_fast_pen) { - QVarLengthArray vertexArray(6 * pointCount); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - int j = 0; - for (int i = 0; i < pointCount; ++i) { - QPointF mapped = d->matrix.map(points[i]); - - GLfloat x = GLfloat(qRound(mapped.x())); - GLfloat y = GLfloat(qRound(mapped.y())); - - vertexArray[j++] = x; - vertexArray[j++] = y - 0.5f; - - vertexArray[j++] = x + 1.5f; - vertexArray[j++] = y + 1.0f; - - vertexArray[j++] = x; - vertexArray[j++] = y + 1.0f; - } - - glEnableClientState(GL_VERTEX_ARRAY); - - glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); - glDrawArrays(GL_TRIANGLES, 0, pointCount*3); - - glDisableClientState(GL_VERTEX_ARRAY); - - glPopMatrix(); - return; - } - - const qreal *vertexArray = reinterpret_cast(&points[0]); - - if (sizeof(qreal) == sizeof(double)) { - Q_ASSERT(sizeof(QPointF) == 16); - glVertexPointer(2, GL_DOUBLE, 0, vertexArray); - } - else { - Q_ASSERT(sizeof(QPointF) == 8); - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - } - - glEnableClientState(GL_VERTEX_ARRAY); - glDrawArrays(GL_POINTS, 0, pointCount); - glDisableClientState(GL_VERTEX_ARRAY); -} - -void QOpenGLPaintEngine::drawLines(const QLine *lines, int lineCount) -{ - struct PointF { - qreal x; - qreal y; - }; - struct LineF { - PointF p1; - PointF p2; - }; - Q_ASSERT(sizeof(PointF) == sizeof(QPointF)); - Q_ASSERT(sizeof(LineF) == sizeof(QLineF)); - LineF fl[256]; - while (lineCount) { - int i = 0; - while (i < lineCount && i < 256) { - fl[i].p1.x = lines[i].x1(); - fl[i].p1.y = lines[i].y1(); - fl[i].p2.x = lines[i].x2(); - fl[i].p2.y = lines[i].y2(); - ++i; - } - drawLines((QLineF *)(void *)fl, i); - lines += i; - lineCount -= i; - } -} - -void QOpenGLPaintEngine::drawLines(const QLineF *lines, int lineCount) -{ - Q_D(QOpenGLPaintEngine); - - if (d->use_emulation) { - QPaintEngineEx::drawLines(lines, lineCount); - return; - } - - if (d->has_pen) { - QOpenGLCoordinateOffset offset(d); - if (d->has_fast_pen && !d->high_quality_antialiasing) { - //### gradient resolving on lines isn't correct - d->setGradientOps(d->cpen.brush(), QRectF()); - - bool useRects = false; - // scale or 90 degree rotation? - if (d->matrix.type() <= QTransform::TxTranslate - || (!d->cpen.isCosmetic() - && (d->matrix.type() <= QTransform::TxScale - || (d->matrix.type() == QTransform::TxRotate - && d->matrix.m11() == 0 && d->matrix.m22() == 0)))) { - useRects = true; - for (int i = 0; i < lineCount; ++i) { - if (lines[i].p1().x() != lines[i].p2().x() - && lines[i].p1().y() != lines[i].p2().y()) { - useRects = false; - break; - } - } - } - - GLfloat endCap = d->cpen.capStyle() == Qt::FlatCap ? 0.0f : 0.5f; - if (useRects) { - QVarLengthArray vertexArray(12 * lineCount); - - GLfloat quad[8]; - for (int i = 0; i < lineCount; ++i) { - GLfloat x1 = lines[i].x1(); - GLfloat x2 = lines[i].x2(); - GLfloat y1 = lines[i].y1(); - GLfloat y2 = lines[i].y2(); - - if (x1 == x2) { - if (y1 > y2) - qSwap(y1, y2); - - quad[0] = x1 - 0.5f; - quad[1] = y1 - endCap; - - quad[2] = x1 + 0.5f; - quad[3] = y1 - endCap; - - quad[4] = x1 + 0.5f; - quad[5] = y2 + endCap; - - quad[6] = x1 - 0.5f; - quad[7] = y2 + endCap; - } else { - if (x1 > x2) - qSwap(x1, x2); - - quad[0] = x1 - endCap; - quad[1] = y1 + 0.5f; - - quad[2] = x1 - endCap; - quad[3] = y1 - 0.5f; - - quad[4] = x2 + endCap; - quad[5] = y1 - 0.5f; - - quad[6] = x2 + endCap; - quad[7] = y1 + 0.5f; - } - - addQuadAsTriangle(quad, &vertexArray[12*i]); - } - - glEnableClientState(GL_VERTEX_ARRAY); - - glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); - glDrawArrays(GL_TRIANGLES, 0, lineCount*6); - - glDisableClientState(GL_VERTEX_ARRAY); - } else { - QVarLengthArray vertexArray(4 * lineCount); - for (int i = 0; i < lineCount; ++i) { - const QPointF a = lines[i].p1(); - vertexArray[4*i] = lines[i].x1(); - vertexArray[4*i+1] = lines[i].y1(); - vertexArray[4*i+2] = lines[i].x2(); - vertexArray[4*i+3] = lines[i].y2(); - } - - glEnableClientState(GL_VERTEX_ARRAY); - - glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); - glDrawArrays(GL_LINES, 0, lineCount*2); - - glVertexPointer(2, GL_FLOAT, 4*sizeof(GLfloat), vertexArray.constData() + 2); - glDrawArrays(GL_POINTS, 0, lineCount); - - glDisableClientState(GL_VERTEX_ARRAY); - } - } else { - QPainterPath path; - path.setFillRule(Qt::WindingFill); - for (int i=0; icpen.capStyle() != Qt::FlatCap) { - QPointF p = l.p1(); - drawPoints(&p, 1); - } - continue; - } - - path.moveTo(l.x1(), l.y1()); - path.lineTo(l.x2(), l.y2()); - } - - if (d->has_fast_pen && d->high_quality_antialiasing) - d->strokeLines(path); - else - d->strokePath(path, false); - } - } -} - -void QOpenGLPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) -{ - Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF)); - QVarLengthArray p(pointCount); - for (int i=0; iuse_emulation) { - QPaintEngineEx::drawPolygon(points, pointCount, mode); - return; - } - - QRectF bounds; - if ((mode == ConvexMode && !d->high_quality_antialiasing && state()->brushNeedsResolving()) || - ((d->has_fast_pen && !d->high_quality_antialiasing) && state()->penNeedsResolving())) { - qreal minx = points[0].x(), miny = points[0].y(), - maxx = points[0].x(), maxy = points[0].y(); - for (int i = 1; i < pointCount; ++i) { - const QPointF &pt = points[i]; - if (minx > pt.x()) - minx = pt.x(); - if (miny > pt.y()) - miny = pt.y(); - if (maxx < pt.x()) - maxx = pt.x(); - if (maxy < pt.y()) - maxy = pt.y(); - } - bounds = QRectF(minx, maxx, maxx-minx, maxy-miny); - } - - QOpenGLCoordinateOffset offset(d); - - if (d->has_brush && mode != PolylineMode) { - if (mode == ConvexMode && !d->high_quality_antialiasing) { - //### resolving on polygon from points isn't correct - d->setGradientOps(d->cbrush, bounds); - - const qreal *vertexArray = reinterpret_cast(&points[0]); - - if (sizeof(qreal) == sizeof(double)) { - Q_ASSERT(sizeof(QPointF) == 16); - glVertexPointer(2, GL_DOUBLE, 0, vertexArray); - } - else { - Q_ASSERT(sizeof(QPointF) == 8); - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - } - - glEnableClientState(GL_VERTEX_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, pointCount); - glDisableClientState(GL_VERTEX_ARRAY); - } else { - QPainterPath path; - path.setFillRule(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); - path.moveTo(points[0]); - for (int i=1; ifillPath(path); - } - } - - if (d->has_pen) { - if (d->has_fast_pen && !d->high_quality_antialiasing) { - d->setGradientOps(d->cpen.brush(), bounds); - QVarLengthArray vertexArray(pointCount*2 + 2); - glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); - int i; - for (i=0; ihas_fast_pen) - d->strokeLines(path); - else - d->strokePath(path, true); - } - } -} - -void QOpenGLPaintEnginePrivate::strokeLines(const QPainterPath &path) -{ - DEBUG_ONCE_STR("QOpenGLPaintEnginePrivate::strokeLines()"); - - qreal penWidth = cpen.widthF(); - - 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); - - disableClipping(); - - QBrush temp = cbrush; - QPointF origin = brush_origin; - - cbrush = cpen.brush(); - brush_origin = QPointF(); - - addItem(qt_mask_texture_cache()->getMask(maskGenerator, this)); - - cbrush = temp; - brush_origin = origin; - - enableClipping(); -} - -Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp - -void QOpenGLPaintEnginePrivate::strokePath(const QPainterPath &path, bool use_cache) -{ - QBrush old_brush = cbrush; - cbrush = cpen.brush(); - - qreal txscale = 1; - if (cpen.isCosmetic() || (qt_scaleForTransform(matrix, &txscale) && txscale != 1)) { - QTransform temp = matrix; - matrix = QTransform(); - glPushMatrix(); - - if (has_antialiasing) { - glLoadIdentity(); - } else { - float offs_matrix[] = - { 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0.5, 0.5, 0, 1 }; - glLoadMatrixf(offs_matrix); - } - - QPen pen = cpen; - if (txscale != 1) - pen.setWidthF(pen.widthF() * txscale); - if (use_cache) - fillPath(qt_opengl_stroke_cache()->getStrokedPath(temp.map(path), pen)); - else - fillPath(strokeForPath(temp.map(path), pen)); - - glPopMatrix(); - matrix = temp; - } else if (use_cache) { - fillPath(qt_opengl_stroke_cache()->getStrokedPath(path, cpen)); - } else { - fillPath(strokeForPath(path, cpen)); - } - - cbrush = old_brush; -} - -void QOpenGLPaintEnginePrivate::strokePathFastPen(const QPainterPath &path, bool needsResolving) -{ -#ifndef QT_OPENGL_ES - QRectF bounds; - if (needsResolving) - bounds = path.controlPointRect(); - setGradientOps(cpen.brush(), bounds); - - QBezier beziers[32]; - for (int i=0; i= beziers) { - // check if we can pop the top bezier curve from the stack - qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1); - qreal d; - if (l > inverseScale) { - d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - - (b->y4 - b->y1)*(b->x1 - b->x2) ) - + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - - (b->y4 - b->y1)*(b->x1 - b->x3) ); - d /= l; - } else { - d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) + - qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); - } - if (d < inverseScaleHalf || b == beziers + 31) { - // good enough, we pop it off and add the endpoint - glVertex2d(b->x4, b->y4); - --b; - } else { - // split, second half of the polygon goes lower into the stack - b->split(b+1, b); - ++b; - } - } - } // case CurveToElement - default: - break; - } // end of switch - } - glEnd(); // GL_LINE_STRIP -#else - // have to use vertex arrays on embedded - QRectF bounds; - if (needsResolving) - bounds = path.controlPointRect(); - setGradientOps(cpen.brush(), bounds); - - glEnableClientState(GL_VERTEX_ARRAY); - tess_points.reset(); - QBezier beziers[32]; - for (int i=0; i= beziers) { - // check if we can pop the top bezier curve from the stack - qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1); - qreal d; - if (l > inverseScale) { - d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - - (b->y4 - b->y1)*(b->x1 - b->x2) ) - + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - - (b->y4 - b->y1)*(b->x1 - b->x3) ); - d /= l; - } else { - d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) + - qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); - } - if (d < inverseScaleHalf || b == beziers + 31) { - // good enough, we pop it off and add the endpoint - tess_points.add(QPointF(b->x4, b->y4)); - --b; - } else { - // split, second half of the polygon goes lower into the stack - b->split(b+1, b); - ++b; - } - } - } // case CurveToElement - default: - break; - } // end of switch - } - glVertexPointer(2, GL_FLOAT, 0, tess_points.data()); - glDrawArrays(GL_LINE_STRIP, 0, tess_points.size()); - glDisableClientState(GL_VERTEX_ARRAY); -#endif -} - -static bool pathClosed(const QPainterPath &path) -{ - QPointF lastMoveTo = path.elementAt(0); - QPointF lastPoint = lastMoveTo; - - for (int i = 1; i < path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - switch (e.type) { - case QPainterPath::MoveToElement: - if (lastMoveTo != lastPoint) - return false; - lastMoveTo = lastPoint = e; - break; - case QPainterPath::LineToElement: - lastPoint = e; - break; - case QPainterPath::CurveToElement: - lastPoint = path.elementAt(i + 2); - i+=2; - break; - default: - break; - } - } - - return lastMoveTo == lastPoint; -} - -void QOpenGLPaintEngine::drawPath(const QPainterPath &path) -{ - Q_D(QOpenGLPaintEngine); - - if (path.isEmpty()) - return; - - if (d->use_emulation) { - QPaintEngineEx::drawPath(path); - return; - } - - QOpenGLCoordinateOffset offset(d); - - if (d->has_brush) { - bool path_closed = pathClosed(path); - - bool has_thick_pen = - path_closed - && d->has_pen - && d->cpen.style() == Qt::SolidLine - && d->cpen.isSolid() - && d->cpen.color().alpha() == 255 - && d->txop < QTransform::TxProject - && d->cpen.widthF() >= 2 / qSqrt(qMin(d->matrix.m11() * d->matrix.m11() - + d->matrix.m21() * d->matrix.m21(), - d->matrix.m12() * d->matrix.m12() - + d->matrix.m22() * d->matrix.m22())); - - if (has_thick_pen) { - DEBUG_ONCE qDebug() << "QOpenGLPaintEngine::drawPath(): Using thick pen optimization, style:" << d->cbrush.style(); - - d->flushDrawQueue(); - - bool temp = d->high_quality_antialiasing; - d->high_quality_antialiasing = false; - - updateCompositionMode(d->composition_mode); - - d->fillPath(path); - - d->high_quality_antialiasing = temp; - updateCompositionMode(d->composition_mode); - } else { - d->fillPath(path); - } - } - - if (d->has_pen) { - if (d->has_fast_pen && !d->high_quality_antialiasing) - d->strokePathFastPen(path, state()->penNeedsResolving()); - else - d->strokePath(path, true); - } -} - -void QOpenGLPaintEnginePrivate::drawImageAsPath(const QRectF &r, const QImage &img, const QRectF &sr) -{ - QBrush old_brush = cbrush; - QPointF old_brush_origin = brush_origin; - - qreal scaleX = r.width() / sr.width(); - qreal scaleY = r.height() / sr.height(); - - QTransform brush_matrix = QTransform::fromTranslate(r.left(), r.top()); - brush_matrix.scale(scaleX, scaleY); - brush_matrix.translate(-sr.left(), -sr.top()); - - cbrush = QBrush(img); - cbrush.setTransform(brush_matrix); - brush_origin = QPointF(); - - QPainterPath p; - p.addRect(r); - fillPath(p); - - cbrush = old_brush; - brush_origin = old_brush_origin; -} - -void QOpenGLPaintEnginePrivate::drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, - const QPointF &offset) -{ - QBrush old_brush = cbrush; - QPointF old_brush_origin = brush_origin; - - QTransform brush_matrix = QTransform::fromTranslate(r.left(), r.top()); - brush_matrix.scale(sx, sy); - brush_matrix.translate(-offset.x(), -offset.y()); - - cbrush = QBrush(img); - cbrush.setTransform(brush_matrix); - brush_origin = QPointF(); - - QPainterPath p; - p.addRect(r); - fillPath(p); - - cbrush = old_brush; - brush_origin = old_brush_origin; -} - -static const QRectF scaleRect(const QRectF &r, qreal sx, qreal sy) -{ - return QRectF(r.x() * sx, r.y() * sy, r.width() * sx, r.height() * sy); -} - -template -static const T qSubImage(const T &image, const QRectF &src, QRectF *srcNew) -{ - const int sx1 = qMax(0, qFloor(src.left())); - const int sy1 = qMax(0, qFloor(src.top())); - const int sx2 = qMin(image.width(), qCeil(src.right())); - const int sy2 = qMin(image.height(), qCeil(src.bottom())); - - const T sub = image.copy(sx1, sy1, sx2 - sx1, sy2 - sy1); - - if (srcNew) - *srcNew = src.translated(-sx1, -sy1); - - return sub; -} - -void QOpenGLPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ - Q_D(QOpenGLPaintEngine); - if (pm.depth() == 1) { - QPixmap tpx(pm.size()); - tpx.fill(Qt::transparent); - QPainter p(&tpx); - p.setPen(d->cpen); - p.drawPixmap(0, 0, pm); - p.end(); - drawPixmap(r, tpx, sr); - return; - } - - const int sz = d->max_texture_size; - if (pm.width() > sz || pm.height() > sz) { - QRectF subsr; - const QPixmap sub = qSubImage(pm, sr, &subsr); - - if (sub.width() <= sz && sub.height() <= sz) { - drawPixmap(r, sub, subsr); - } else { - const QPixmap scaled = sub.scaled(sz, sz, Qt::KeepAspectRatio); - const qreal sx = scaled.width() / qreal(sub.width()); - const qreal sy = scaled.height() / qreal(sub.height()); - - drawPixmap(r, scaled, scaleRect(subsr, sx, sy)); - } - return; - } - - - if (d->composition_mode > QPainter::CompositionMode_Plus || (d->high_quality_antialiasing && !d->isFastRect(r))) - d->drawImageAsPath(r, pm.toImage(), sr); - else { - GLenum target = qt_gl_preferredTextureTarget(); - d->flushDrawQueue(); - QGLTexture *tex = - d->device->context()->d_func()->bindTexture(pm, target, GL_RGBA, - QGLContext::InternalBindOption); - drawTextureRect(pm.width(), pm.height(), r, sr, target, tex); - } -} - -void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &offset) -{ - Q_D(QOpenGLPaintEngine); - if (pm.depth() == 1) { - QPixmap tpx(pm.size()); - tpx.fill(Qt::transparent); - QPainter p(&tpx); - p.setPen(d->cpen); - p.drawPixmap(0, 0, pm); - p.end(); - drawTiledPixmap(r, tpx, offset); - return; - } - - QImage scaled; - const int sz = d->max_texture_size; - if (pm.width() > sz || pm.height() > sz) { - int rw = qCeil(r.width()); - int rh = qCeil(r.height()); - if (rw < pm.width() && rh < pm.height()) { - drawTiledPixmap(r, pm.copy(0, 0, rw, rh), offset); - return; - } - - scaled = pm.toImage().scaled(sz, sz, Qt::KeepAspectRatio); - } - - if (d->composition_mode > QPainter::CompositionMode_Plus || (d->high_quality_antialiasing && !d->isFastRect(r))) { - if (scaled.isNull()) - d->drawTiledImageAsPath(r, pm.toImage(), 1, 1, offset); - else { - const qreal sx = pm.width() / qreal(scaled.width()); - const qreal sy = pm.height() / qreal(scaled.height()); - d->drawTiledImageAsPath(r, scaled, sx, sy, offset); - } - } else { - d->flushDrawQueue(); - - QGLTexture *tex; - if (scaled.isNull()) - tex = d->device->context()->d_func()->bindTexture(pm, GL_TEXTURE_2D, GL_RGBA, - QGLContext::InternalBindOption); - else - tex = d->device->context()->d_func()->bindTexture(scaled, GL_TEXTURE_2D, GL_RGBA, - QGLContext::InternalBindOption); - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, d->use_smooth_pixmap_transform); - -#ifndef QT_OPENGL_ES - glPushAttrib(GL_CURRENT_BIT); - glDisable(GL_TEXTURE_GEN_S); -#endif - glColor4f(d->opacity, d->opacity, d->opacity, d->opacity); - glEnable(GL_TEXTURE_2D); - - GLdouble tc_w = r.width()/pm.width(); - GLdouble tc_h = r.height()/pm.height(); - - // Rotate the texture so that it is aligned correctly and the - // wrapping is done correctly - if (tex->options & QGLContext::InvertedYBindOption) { - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glRotatef(180.0, 0.0, 1.0, 0.0); - glRotatef(180.0, 0.0, 0.0, 1.0); - } - - GLfloat vertexArray[4*2]; - GLfloat texCoordArray[4*2]; - - double offset_x = offset.x() / pm.width(); - double offset_y = offset.y() / pm.height(); - - qt_add_rect_to_array(r, vertexArray); - qt_add_texcoords_to_array(offset_x, offset_y, - tc_w + offset_x, tc_h + offset_y, texCoordArray); - - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - if (tex->options & QGLContext::InvertedYBindOption) - glPopMatrix(); - - glDisable(GL_TEXTURE_2D); -#ifndef QT_OPENGL_ES - glPopAttrib(); -#endif - } -} - -void QOpenGLPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, - Qt::ImageConversionFlags) -{ - Q_D(QOpenGLPaintEngine); - - const int sz = d->max_texture_size; - if (image.width() > sz || image.height() > sz) { - QRectF subsr; - const QImage sub = qSubImage(image, sr, &subsr); - - if (sub.width() <= sz && sub.height() <= sz) { - drawImage(r, sub, subsr, 0); - } else { - const QImage scaled = sub.scaled(sz, sz, Qt::KeepAspectRatio); - const qreal sx = scaled.width() / qreal(sub.width()); - const qreal sy = scaled.height() / qreal(sub.height()); - - drawImage(r, scaled, scaleRect(subsr, sx, sy), 0); - } - return; - } - - if (d->composition_mode > QPainter::CompositionMode_Plus || (d->high_quality_antialiasing && !d->isFastRect(r))) - d->drawImageAsPath(r, image, sr); - else { - GLenum target = qt_gl_preferredTextureTarget(); - d->flushDrawQueue(); - QGLTexture *tex = - d->device->context()->d_func()->bindTexture(image, target, GL_RGBA, - QGLContext::InternalBindOption); - drawTextureRect(image.width(), image.height(), r, sr, target, tex); - } -} - -void QOpenGLPaintEngine::drawTextureRect(int tx_width, int tx_height, const QRectF &r, - const QRectF &sr, GLenum target, QGLTexture *tex) -{ - Q_D(QOpenGLPaintEngine); -#ifndef QT_OPENGL_ES - glPushAttrib(GL_CURRENT_BIT); - glDisable(GL_TEXTURE_GEN_S); -#endif - glColor4f(d->opacity, d->opacity, d->opacity, d->opacity); - glEnable(target); - updateTextureFilter(target, GL_CLAMP_TO_EDGE, d->use_smooth_pixmap_transform); - - qreal x1, x2, y1, y2; - if (target == GL_TEXTURE_2D) { - x1 = sr.x() / tx_width; - x2 = x1 + sr.width() / tx_width; - if (tex->options & QGLContext::InvertedYBindOption) { - y1 = 1 - (sr.bottom() / tx_height); - y2 = 1 - (sr.y() / tx_height); - } else { - y1 = sr.bottom() / tx_height; - y2 = sr.y() / tx_height; - } - } else { - x1 = sr.x(); - x2 = sr.right(); - y1 = sr.bottom(); - y2 = sr.y(); - } - - GLfloat vertexArray[4*2]; - GLfloat texCoordArray[4*2]; - - qt_add_rect_to_array(r, vertexArray); - qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray); - - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - - glDisable(target); -#ifndef QT_OPENGL_ES - glPopAttrib(); -#endif -} - -#ifdef Q_WS_WIN -HDC -#else -Qt::HANDLE -#endif -QOpenGLPaintEngine::handle() const -{ - return 0; -} - -static const int x_margin = 1; -static const int y_margin = 0; - -struct QGLGlyphCoord { - // stores the offset and size of a glyph texture - qreal x; - qreal y; - qreal width; - qreal height; - qreal log_width; - qreal log_height; - QFixed x_offset; - QFixed y_offset; -}; - -struct QGLFontTexture { - int x_offset; // glyph offset within the - int y_offset; - GLuint texture; - int width; - int height; -}; - -typedef QHash QGLGlyphHash; -typedef QHash QGLFontGlyphHash; -typedef QHash QGLFontTexHash; -typedef QHash QGLContextHash; - -static inline void qt_delete_glyph_hash(QGLGlyphHash *hash) -{ - qDeleteAll(*hash); - delete hash; -} - -class QGLGlyphCache : public QObject -{ - Q_OBJECT -public: - QGLGlyphCache() : QObject(0) { current_cache = 0; } - ~QGLGlyphCache(); - QGLGlyphCoord *lookup(QFontEngine *, glyph_t); - void cacheGlyphs(QGLContext *, QFontEngine *, glyph_t *glyphs, int numGlyphs); - void cleanCache(); - void allocTexture(int width, int height, GLuint texture); - -public slots: - void cleanupContext(const QGLContext *); - void fontEngineDestroyed(QObject *); - void widgetDestroyed(QObject *); - -protected: - QGLGlyphHash *current_cache; - QGLFontTexHash qt_font_textures; - QGLContextHash qt_context_cache; -}; - -QGLGlyphCache::~QGLGlyphCache() -{ -// qDebug() << "cleaning out the QGLGlyphCache"; - cleanCache(); -} - -void QGLGlyphCache::fontEngineDestroyed(QObject *o) -{ -// qDebug() << "fontEngineDestroyed()"; - QFontEngine *fe = static_cast(o); // safe, since only the type is used - QList keys = qt_context_cache.keys(); - const QGLContext *ctx = 0; - - for (int i=0; i < keys.size(); ++i) { - QGLFontGlyphHash *font_cache = qt_context_cache.value(keys.at(i)); - if (font_cache->find(fe) != font_cache->end()) { - ctx = keys.at(i); - QGLGlyphHash *cache = font_cache->take(fe); - qt_delete_glyph_hash(cache); - break; - } - } - - quint64 font_key = (reinterpret_cast(ctx) << 32) | reinterpret_cast(fe); - QGLFontTexture *tex = qt_font_textures.take(font_key); - if (tex) { -#ifdef Q_WS_MAC - if ( -# ifndef QT_MAC_USE_COCOA - aglGetCurrentContext() != 0 -# else - qt_current_nsopengl_context() != 0 -# endif - ) -#endif - glDeleteTextures(1, &tex->texture); - delete tex; - } -} - -void QGLGlyphCache::widgetDestroyed(QObject *) -{ -// qDebug() << "widget destroyed"; - cleanCache(); // ### -} - -void QGLGlyphCache::cleanupContext(const QGLContext *ctx) -{ -// qDebug() << "==> cleaning for: " << hex << ctx; - QGLFontGlyphHash *font_cache = qt_context_cache.take(ctx); - - if (font_cache) { - QList keys = font_cache->keys(); - for (int i=0; i < keys.size(); ++i) { - QFontEngine *fe = keys.at(i); - qt_delete_glyph_hash(font_cache->take(fe)); - quint64 font_key = (reinterpret_cast(ctx) << 32) | reinterpret_cast(fe); - QGLFontTexture *font_tex = qt_font_textures.take(font_key); - if (font_tex) { -#ifdef Q_WS_MAC - if ( -# ifndef QT_MAC_USE_COCOA - aglGetCurrentContext() == 0 -# else - qt_current_nsopengl_context() != 0 -# endif - ) -#endif - glDeleteTextures(1, &font_tex->texture); - delete font_tex; - } - } - delete font_cache; - } -// qDebug() << "<=== done cleaning, num tex:" << qt_font_textures.size() << "num ctx:" << qt_context_cache.size(); -} - -void QGLGlyphCache::cleanCache() -{ - QGLFontTexHash::const_iterator it = qt_font_textures.constBegin(); - if (QGLContext::currentContext()) { - while (it != qt_font_textures.constEnd()) { -#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) - if (qt_current_nsopengl_context() == 0) - break; -#endif - glDeleteTextures(1, &it.value()->texture); - ++it; - } - } - qDeleteAll(qt_font_textures); - qt_font_textures.clear(); - - QList keys = qt_context_cache.keys(); - for (int i=0; i < keys.size(); ++i) { - QGLFontGlyphHash *font_cache = qt_context_cache.value(keys.at(i)); - QGLFontGlyphHash::Iterator it = font_cache->begin(); - for (; it != font_cache->end(); ++it) - qt_delete_glyph_hash(it.value()); - font_cache->clear(); - } - qDeleteAll(qt_context_cache); - qt_context_cache.clear(); -} - -void QGLGlyphCache::allocTexture(int width, int height, GLuint texture) -{ - uchar *tex_data = (uchar *) malloc(width*height*2); - memset(tex_data, 0, width*height*2); - glBindTexture(GL_TEXTURE_2D, texture); -#ifndef QT_OPENGL_ES - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8_ALPHA8, - width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tex_data); -#else - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, - width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tex_data); -#endif - free(tex_data); -} - -#if 0 -// useful for debugging the glyph cache -static QImage getCurrentTexture(const QColor &color, QGLFontTexture *font_tex) -{ - ushort *old_tex_data = (ushort *) malloc(font_tex->width*font_tex->height*2); - glGetTexImage(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, old_tex_data); - QImage im(font_tex->width, font_tex->height, QImage::Format_ARGB32); - for (int y=0; yheight; ++y) { - for (int x=0; xwidth; ++x) { - im.setPixel(x, y, ((*(old_tex_data+x+y*font_tex->width)) << 24) | (0x00ffffff & color.rgb())); - } - } - delete old_tex_data; - return im; -} -#endif - -void QGLGlyphCache::cacheGlyphs(QGLContext *context, QFontEngine *fontEngine, - glyph_t *glyphs, int numGlyphs) -{ - QGLContextHash::const_iterator dev_it = qt_context_cache.constFind(context); - QGLFontGlyphHash *font_cache = 0; - const QGLContext *context_key = 0; - - if (dev_it == qt_context_cache.constEnd()) { - // check for shared contexts - QList contexts = qt_context_cache.keys(); - for (int i=0; iisValid()) { - if (context->device() && context->device()->devType() == QInternal::Widget) { - QWidget *widget = static_cast(context->device()); - connect(widget, SIGNAL(destroyed(QObject*)), SLOT(widgetDestroyed(QObject*))); - } - connect(QGLSignalProxy::instance(), - SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(cleanupContext(const QGLContext*))); - } - } else { - font_cache = dev_it.value(); - } - Q_ASSERT(font_cache != 0); - - QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(fontEngine); - QGLGlyphHash *cache = 0; - if (cache_it == font_cache->constEnd()) { - cache = new QGLGlyphHash; - font_cache->insert(fontEngine, cache); - connect(fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*))); - } else { - cache = cache_it.value(); - } - current_cache = cache; - - quint64 font_key = (reinterpret_cast(context_key ? context_key : context) << 32) - | reinterpret_cast(fontEngine); - QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key); - QGLFontTexture *font_tex; - if (it == qt_font_textures.constEnd()) { - GLuint font_texture; - glGenTextures(1, &font_texture); - GLint tex_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2); - GLint tex_width = qt_next_power_of_two(tex_height*30); // ### - GLint max_tex_size; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); - Q_ASSERT(max_tex_size > 0); - if (tex_width > max_tex_size) - tex_width = max_tex_size; - allocTexture(tex_width, tex_height, font_texture); - font_tex = new QGLFontTexture; - font_tex->texture = font_texture; - font_tex->x_offset = x_margin; - font_tex->y_offset = y_margin; - font_tex->width = tex_width; - font_tex->height = tex_height; -// qDebug() << "new font tex - width:" << tex_width << "height:"<< tex_height -// << hex << "tex id:" << font_tex->texture << "key:" << font_key << "num cached:" << qt_font_textures.size(); - qt_font_textures.insert(font_key, font_tex); - } else { - font_tex = it.value(); - glBindTexture(GL_TEXTURE_2D, font_tex->texture); - } - - for (int i=0; i< numGlyphs; ++i) { - QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]); - if (it == cache->constEnd()) { - // render new glyph and put it in the cache - glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]); - int glyph_width = qRound(metrics.width.toReal())+2; - int glyph_height = qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2; - - if (font_tex->x_offset + glyph_width + x_margin > font_tex->width) { - int strip_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2); - font_tex->x_offset = x_margin; - font_tex->y_offset += strip_height; - if (font_tex->y_offset >= font_tex->height) { - // get hold of the old font texture - uchar *old_tex_data = (uchar *) malloc(font_tex->width*font_tex->height*2); - int old_tex_height = font_tex->height; -#ifndef QT_OPENGL_ES - glGetTexImage(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, old_tex_data); -#endif - - // realloc a larger texture - glDeleteTextures(1, &font_tex->texture); - glGenTextures(1, &font_tex->texture); - font_tex->height = qt_next_power_of_two(font_tex->height + strip_height); - allocTexture(font_tex->width, font_tex->height, font_tex->texture); - - // write back the old texture data - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, font_tex->width, old_tex_height, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, old_tex_data); - free(old_tex_data); - - // update the texture coords and the y offset for the existing glyphs in - // the cache, because of the texture size change - QGLGlyphHash::iterator it = cache->begin(); - while (it != cache->end()) { - it.value()->height = (it.value()->height * old_tex_height) / font_tex->height; - it.value()->y = (it.value()->y * old_tex_height) / font_tex->height; - ++it; - } - } - } - - QImage glyph_im(fontEngine->alphaMapForGlyph(glyphs[i])); - glyph_width = glyph_im.width(); - Q_ASSERT(glyph_width >= 0); - // pad the glyph width to an even number - if (glyph_width%2 != 0) - ++glyph_width; - - QGLGlyphCoord *qgl_glyph = new QGLGlyphCoord; - qgl_glyph->x = qreal(font_tex->x_offset) / font_tex->width; - qgl_glyph->y = qreal(font_tex->y_offset) / font_tex->height; - qgl_glyph->width = qreal(glyph_width) / font_tex->width; - qgl_glyph->height = qreal(glyph_height) / font_tex->height; - qgl_glyph->log_width = qreal(glyph_width); - qgl_glyph->log_height = qgl_glyph->height * font_tex->height; -#ifdef Q_WS_MAC - qgl_glyph->x_offset = -metrics.x + 1; - qgl_glyph->y_offset = metrics.y - 2; -#else - qgl_glyph->x_offset = -metrics.x; - qgl_glyph->y_offset = metrics.y; -#endif - - if (!glyph_im.isNull()) { - int idx = 0; - uchar *tex_data = (uchar *) malloc(glyph_width*glyph_im.height()*2); - memset(tex_data, 0, glyph_width*glyph_im.height()*2); - - bool is8BitGray = false; -#ifdef Q_WS_QPA - if (glyph_im.format() == QImage::Format_Indexed8) { - is8BitGray = true; - } -#endif - glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8); - for (int y=0; yx_offset, font_tex->y_offset, - glyph_width, glyph_im.height(), - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tex_data); - free(tex_data); - } - if (font_tex->x_offset + glyph_width + x_margin > font_tex->width) { - font_tex->x_offset = x_margin; - font_tex->y_offset += glyph_height + y_margin; - } else { - font_tex->x_offset += glyph_width + x_margin; - } - - cache->insert(glyphs[i], qgl_glyph); - } - } -} - -QGLGlyphCoord *QGLGlyphCache::lookup(QFontEngine *, glyph_t g) -{ - Q_ASSERT(current_cache != 0); - // ### careful here - QGLGlyphHash::const_iterator it = current_cache->constFind(g); - if (it == current_cache->constEnd()) - return 0; - else - return it.value(); -} - -Q_GLOBAL_STATIC(QGLGlyphCache, qt_glyph_cache) - -// -// assumption: the context that this is called for has to be the -// current context -// -void qgl_cleanup_glyph_cache(QGLContext *ctx) -{ - qt_glyph_cache()->cleanupContext(ctx); -} - -void QOpenGLPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) -{ - Q_D(QOpenGLPaintEngine); - - d->flushDrawQueue(); - - // make sure the glyphs we want to draw are in the cache - qt_glyph_cache()->cacheGlyphs(d->device->context(), textItem->fontEngine(), textItem->glyphs, - textItem->numGlyphs); - - d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops - qt_glColor4ubv(d->pen_color); - glEnable(GL_TEXTURE_2D); - -#ifdef Q_WS_QWS - // XXX: it is necessary to disable alpha writes on GLES/embedded because we don't want - // text rendering to update the alpha in the window surface. - // XXX: This may not be needed as this behavior does seem to be caused by driver bug - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); -#endif - - // do the actual drawing - GLfloat vertexArray[4*2]; - GLfloat texCoordArray[4*2]; - - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bool antialias = !(textItem->fontEngine()->fontDef.styleStrategy & QFont::NoAntialias) - && (d->matrix.type() > QTransform::TxTranslate); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST); - - for (int i=0; i< textItem->numGlyphs; ++i) { - QGLGlyphCoord *g = qt_glyph_cache()->lookup(textItem->fontEngine(), textItem->glyphs[i]); - - // we don't cache glyphs with no width/height - if (!g) - continue; - - qreal x1, x2, y1, y2; - x1 = g->x; - y1 = g->y; - x2 = x1 + g->width; - y2 = y1 + g->height; - - QPointF logical_pos((textItem->glyphPositions[i].x - g->x_offset).toReal(), - (textItem->glyphPositions[i].y + g->y_offset).toReal()); - - qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray); - qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - - glDisable(GL_TEXTURE_2D); - -#ifdef Q_WS_QWS - // XXX: This may not be needed as this behavior does seem to be caused by driver bug - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); -#endif - -} - -void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) -{ - Q_D(QOpenGLPaintEngine); - - const QTextItemInt &ti = static_cast(textItem); - - // fall back to drawing a polygon if the scale factor is large, or - // we use a gradient pen - if ((d->matrix.det() > 1) || (d->pen_brush_style >= Qt::LinearGradientPattern - && d->pen_brush_style <= Qt::ConicalGradientPattern)) { - QPaintEngine::drawTextItem(p, textItem); - return; - } - - // add the glyphs used to the glyph texture cache - QVarLengthArray positions; - QVarLengthArray glyphs; - QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y())); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - - { - QStaticTextItem staticTextItem; - staticTextItem.chars = const_cast(ti.chars); - staticTextItem.setFontEngine(ti.fontEngine); - staticTextItem.glyphs = glyphs.data(); - staticTextItem.numChars = ti.num_chars; - staticTextItem.numGlyphs = glyphs.size(); - staticTextItem.glyphPositions = positions.data(); - drawStaticTextItem(&staticTextItem); - } - -} - - -void QOpenGLPaintEngine::drawEllipse(const QRectF &rect) -{ -#ifndef Q_WS_QWS - Q_D(QOpenGLPaintEngine); - - if (d->use_emulation) { - QPaintEngineEx::drawEllipse(rect); - return; - } - - if (d->high_quality_antialiasing) { - if (d->has_brush) { - d->disableClipping(); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - GLuint program = qt_gl_program_cache()->getProgram(d->device->context(), - FRAGMENT_PROGRAM_MASK_ELLIPSE_AA, 0, true); - QGLEllipseMaskGenerator maskGenerator(rect, - d->matrix, - d->offscreen, - program, - mask_variable_locations[FRAGMENT_PROGRAM_MASK_ELLIPSE_AA]); - - d->addItem(qt_mask_texture_cache()->getMask(maskGenerator, d)); - - d->enableClipping(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - } - - if (d->has_pen) { - QPainterPath path; - path.addEllipse(rect); - - d->strokePath(path, false); - } - } else { - DEBUG_ONCE_STR("QOpenGLPaintEngine::drawEllipse(): falling back to drawPath()"); - - QPainterPath path; - path.addEllipse(rect); - drawPath(path); - } -#else - QPaintEngineEx::drawEllipse(rect); -#endif -} - - -void QOpenGLPaintEnginePrivate::updateFragmentProgramData(int locations[]) -{ -#ifdef Q_WS_QWS - Q_UNUSED(locations); -#else - QGL_FUNC_CONTEXT; - - QSize sz = offscreen.offscreenSize(); - - float inv_mask_size_data[4] = { 1.0f / sz.width(), 1.0f / sz.height(), 0.0f, 0.0f }; - - sz = drawable_texture_size; - - float inv_dst_size_data[4] = { 1.0f / sz.width(), 1.0f / sz.height(), 0.0f, 0.0f }; - - // default inv size 0.125f == 1.0f / 8.0f for pattern brushes - float inv_brush_texture_size_data[4] = { 0.125f, 0.125f }; - - // texture patterns have their own size - if (current_style == Qt::TexturePattern) { - QSize sz = cbrush.texture().size(); - - inv_brush_texture_size_data[0] = 1.0f / sz.width(); - inv_brush_texture_size_data[1] = 1.0f / sz.height(); - } - - for (unsigned int i = 0; i < num_fragment_variables; ++i) { - int location = locations[i]; - - if (location < 0) - continue; - - switch (i) { - case VAR_ANGLE: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, angle_data); - break; - case VAR_LINEAR: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, linear_data); - break; - case VAR_FMP: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, fmp_data); - break; - case VAR_FMP2_M_RADIUS2: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, fmp2_m_radius2_data); - break; - case VAR_INV_MASK_SIZE: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, inv_mask_size_data); - break; - case VAR_INV_DST_SIZE: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, inv_dst_size_data); - break; - case VAR_INV_MATRIX_M0: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, inv_matrix_data[0]); - break; - case VAR_INV_MATRIX_M1: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, inv_matrix_data[1]); - break; - case VAR_INV_MATRIX_M2: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, inv_matrix_data[2]); - break; - case VAR_PORTERDUFF_AB: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, porterduff_ab_data); - break; - case VAR_PORTERDUFF_XYZ: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, porterduff_xyz_data); - break; - case VAR_INV_BRUSH_TEXTURE_SIZE: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, inv_brush_texture_size_data); - break; - case VAR_MASK_OFFSET: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, mask_offset_data); - break; - case VAR_MASK_CHANNEL: - glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, location, mask_channel_data); - break; - case VAR_DST_TEXTURE: - case VAR_MASK_TEXTURE: - case VAR_PALETTE: - case VAR_BRUSH_TEXTURE: - // texture variables, not handled here - break; - default: - qDebug() << "QOpenGLPaintEnginePrivate: Unhandled fragment variable:" << i; - } - } -#endif -} - - -void QOpenGLPaintEnginePrivate::copyDrawable(const QRectF &rect) -{ -#ifdef Q_WS_QWS - Q_UNUSED(rect); -#else - ensureDrawableTexture(); - - DEBUG_ONCE qDebug() << "Refreshing drawable_texture for rectangle" << rect; - QRectF screen_rect = rect.adjusted(-1, -1, 1, 1); - - int left = qMax(0, static_cast(screen_rect.left())); - int width = qMin(device->size().width() - left, static_cast(screen_rect.width()) + 1); - - int bottom = qMax(0, static_cast(device->size().height() - screen_rect.bottom())); - int height = qMin(device->size().height() - bottom, static_cast(screen_rect.height()) + 1); - - glBindTexture(GL_TEXTURE_2D, drawable_texture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, left, bottom, width, height); -#endif -} - - -void QOpenGLPaintEnginePrivate::composite(const QRectF &rect, const QPoint &maskOffset) -{ -#ifdef Q_WS_QWS - Q_UNUSED(rect); - Q_UNUSED(maskOffset); -#else - GLfloat vertexArray[8]; - qt_add_rect_to_array(rect, vertexArray); - - composite(GL_TRIANGLE_FAN, vertexArray, 4, maskOffset); -#endif -} - - -void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const GLfloat *vertexArray, int vertexCount, const QPoint &maskOffset) -{ -#ifdef QT_OPENGL_ES - Q_UNUSED(primitive); - Q_UNUSED(vertexArray); - Q_UNUSED(vertexCount); - Q_UNUSED(maskOffset); -#else - Q_Q(QOpenGLPaintEngine); - QGL_FUNC_CONTEXT; - - if (current_style == Qt::NoBrush) - return; - - DEBUG_ONCE qDebug() << "QOpenGLPaintEnginePrivate: Using compositing program: fragment_brush =" - << fragment_brush << ", fragment_composition_mode =" << fragment_composition_mode; - - if (has_fast_composition_mode) - q->updateCompositionMode(composition_mode); - else { - qreal minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9; - - for (int i = 0; i < vertexCount; ++i) { - qreal x = vertexArray[2 * i]; - qreal y = vertexArray[2 * i + 1]; - - qreal tx, ty; - matrix.map(x, y, &tx, &ty); - - minX = qMin(minX, tx); - minY = qMin(minY, ty); - maxX = qMax(maxX, tx); - maxY = qMax(maxY, ty); - } - - QRectF r(minX, minY, maxX - minX, maxY - minY); - copyDrawable(r); - - glBlendFunc(GL_ONE, GL_ZERO); - } - - int *locations = painter_variable_locations[fragment_brush][fragment_composition_mode]; - - int texture_locations[] = { locations[VAR_DST_TEXTURE], - locations[VAR_MASK_TEXTURE], - locations[VAR_PALETTE] }; - - int brush_texture_location = locations[VAR_BRUSH_TEXTURE]; - - GLuint texture_targets[] = { GL_TEXTURE_2D, - GL_TEXTURE_2D, - GL_TEXTURE_1D }; - - GLuint textures[] = { drawable_texture, - offscreen.offscreenTexture(), - grad_palette }; - - const int num_textures = sizeof(textures) / sizeof(*textures); - - Q_ASSERT(num_textures == sizeof(texture_locations) / sizeof(*texture_locations)); - Q_ASSERT(num_textures == sizeof(texture_targets) / sizeof(*texture_targets)); - - for (int i = 0; i < num_textures; ++i) - if (texture_locations[i] >= 0) { - glActiveTexture(GL_TEXTURE0 + texture_locations[i]); - glBindTexture(texture_targets[i], textures[i]); - } - - if (brush_texture_location >= 0) { - glActiveTexture(GL_TEXTURE0 + brush_texture_location); - - if (current_style == Qt::TexturePattern) - device->context()->d_func()->bindTexture(cbrush.textureImage(), GL_TEXTURE_2D, GL_RGBA, - QGLContext::InternalBindOption); - else - device->context()->d_func()->bindTexture(qt_imageForBrush(current_style, false), - GL_TEXTURE_2D, GL_RGBA, - QGLContext::InternalBindOption); - - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform); - } - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glEnable(GL_FRAGMENT_PROGRAM_ARB); - GLuint program = qt_gl_program_cache()->getProgram(device->context(), - fragment_brush, - fragment_composition_mode, false); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program); - - mask_offset_data[0] = maskOffset.x(); - mask_offset_data[1] = -maskOffset.y(); - - updateFragmentProgramData(locations); - - glDrawArrays(primitive, 0, vertexCount); - - glDisable(GL_FRAGMENT_PROGRAM_ARB); - glDisableClientState(GL_VERTEX_ARRAY); - - for (int i = 0; i < num_textures; ++i) - if (texture_locations[i] >= 0) { - glActiveTexture(GL_TEXTURE0 + texture_locations[i]); - glBindTexture(texture_targets[i], 0); - } - - if (brush_texture_location >= 0) { - glActiveTexture(GL_TEXTURE0 + brush_texture_location); - glBindTexture(GL_TEXTURE_2D, 0); - } - - glActiveTexture(GL_TEXTURE0); - - if (!has_fast_composition_mode) - q->updateCompositionMode(composition_mode); -#endif -} - -void QOpenGLPaintEnginePrivate::cacheItemErased(int channel, const QRect &rect) -{ - bool isInDrawQueue = false; - - foreach (const QDrawQueueItem &item, drawQueue) { - if (item.location.channel == channel && item.location.rect == rect) { - isInDrawQueue = true; - break; - } - } - - if (isInDrawQueue) - flushDrawQueue(); -} - -void QOpenGLPaintEnginePrivate::addItem(const QGLMaskTextureCache::CacheLocation &location) -{ - drawQueue << QDrawQueueItem(opacity, cbrush, brush_origin, composition_mode, matrix, location); -} - -void QOpenGLPaintEnginePrivate::drawItem(const QDrawQueueItem &item) -{ - Q_Q(QOpenGLPaintEngine); - - opacity = item.opacity; - brush_origin = item.brush_origin; - q->updateCompositionMode(item.composition_mode); - matrix = item.matrix; - cbrush = item.brush; - brush_style = item.brush.style(); - - mask_channel_data[0] = item.location.channel == 0; - mask_channel_data[1] = item.location.channel == 1; - mask_channel_data[2] = item.location.channel == 2; - mask_channel_data[3] = item.location.channel == 3; - - 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() - device->size().height())); -} - -void QOpenGLPaintEnginePrivate::flushDrawQueue() -{ -#ifndef QT_OPENGL_ES - Q_Q(QOpenGLPaintEngine); - - offscreen.release(); - - if (!drawQueue.isEmpty()) { - DEBUG_ONCE qDebug() << "QOpenGLPaintEngine::flushDrawQueue():" << drawQueue.size() << "items"; - - glPushMatrix(); - glLoadIdentity(); - qreal old_opacity = opacity; - QPointF old_brush_origin = brush_origin; - QPainter::CompositionMode old_composition_mode = composition_mode; - QTransform old_matrix = matrix; - QBrush old_brush = cbrush; - - bool hqaa_old = high_quality_antialiasing; - - high_quality_antialiasing = true; - - foreach (const QDrawQueueItem &item, drawQueue) - drawItem(item); - - opacity = old_opacity; - brush_origin = old_brush_origin; - q->updateCompositionMode(old_composition_mode); - matrix = old_matrix; - cbrush = old_brush; - brush_style = old_brush.style(); - - high_quality_antialiasing = hqaa_old; - - setGLBrush(old_brush.color()); - qt_glColor4ubv(brush_color); - - drawQueue.clear(); - - glPopMatrix(); - } -#endif -} - -void QOpenGLPaintEngine::clipEnabledChanged() -{ - Q_D(QOpenGLPaintEngine); - - d->updateDepthClip(); -} - -void QOpenGLPaintEngine::penChanged() -{ - updatePen(state()->pen); -} - -void QOpenGLPaintEngine::brushChanged() -{ - updateBrush(state()->brush, state()->brushOrigin); -} - -void QOpenGLPaintEngine::brushOriginChanged() -{ - updateBrush(state()->brush, state()->brushOrigin); -} - -void QOpenGLPaintEngine::opacityChanged() -{ - Q_D(QOpenGLPaintEngine); - QPainterState *s = state(); - d->opacity = s->opacity; - updateBrush(s->brush, s->brushOrigin); - updatePen(s->pen); -} - -void QOpenGLPaintEngine::compositionModeChanged() -{ - updateCompositionMode(state()->composition_mode); -} - -void QOpenGLPaintEngine::renderHintsChanged() -{ - updateRenderHints(state()->renderHints); -} - -void QOpenGLPaintEngine::transformChanged() -{ - updateMatrix(state()->matrix); -} - -extern QPainterPath qt_painterPathFromVectorPath(const QVectorPath &path); - -void QOpenGLPaintEngine::fill(const QVectorPath &path, const QBrush &brush) -{ - Q_D(QOpenGLPaintEngine); - - if (brush.style() == Qt::NoBrush) - return; - - if ((!d->use_fragment_programs && needsEmulation(brush.style())) || qt_isExtendedRadialGradient(brush)) { - QPainter *p = painter(); - QBrush oldBrush = p->brush(); - p->setBrush(brush); - qt_draw_helper(p->d_ptr.data(), qt_painterPathFromVectorPath(path), QPainterPrivate::FillDraw); - p->setBrush(oldBrush); - return; - } - - QBrush old_brush = state()->brush; - updateBrush(brush, state()->brushOrigin); - - const qreal *points = path.points(); - const QPainterPath::ElementType *types = path.elements(); - if (!types && path.shape() == QVectorPath::RectangleHint) { - QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]); - QPen old_pen = state()->pen; - updatePen(Qt::NoPen); - drawRects(&r, 1); - updatePen(old_pen); - } else { - d->fillPath(qt_painterPathFromVectorPath(path)); - } - - updateBrush(old_brush, state()->brushOrigin); -} - -template static inline bool isRect(const T *pts, int elementCount) { - return (elementCount == 5 // 5-point polygon, check for closed rect - && pts[0] == pts[8] && pts[1] == pts[9] // last point == first point - && pts[0] == pts[6] && pts[2] == pts[4] // x values equal - && pts[1] == pts[3] && pts[5] == pts[7] // y values equal... - ) || - (elementCount == 4 // 4-point polygon, check for unclosed rect - && pts[0] == pts[6] && pts[2] == pts[4] // x values equal - && pts[1] == pts[3] && pts[5] == pts[7] // y values equal... - ); -} - -void QOpenGLPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) -{ - const qreal *points = path.points(); - const QPainterPath::ElementType *types = path.elements(); - if (!types && path.shape() == QVectorPath::RectangleHint) { - QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]); - updateClipRegion(QRegion(r.toRect()), op); - return; - } - - QPainterPath p; - if (types) { - int id = 0; - for (int i=0; i(s); - QOpenGLPaintEngineState *old_state = state(); - - QPaintEngineEx::setState(s); - - // are we in a save() ? - if (s == d->last_created_state) { - d->last_created_state = 0; - return; - } - - if (isActive()) { - if (old_state->depthClipId != new_state->depthClipId) - d->updateDepthClip(); - penChanged(); - brushChanged(); - opacityChanged(); - compositionModeChanged(); - renderHintsChanged(); - transformChanged(); - } -} - -QPainterState *QOpenGLPaintEngine::createState(QPainterState *orig) const -{ - const Q_D(QOpenGLPaintEngine); - - QOpenGLPaintEngineState *s; - if (!orig) - s = new QOpenGLPaintEngineState(); - else - s = new QOpenGLPaintEngineState(*static_cast(orig)); - - d->last_created_state = s; - return s; -} - -// -// QOpenGLPaintEngineState -// - -QOpenGLPaintEngineState::QOpenGLPaintEngineState(QOpenGLPaintEngineState &other) - : QPainterState(other) -{ - clipRegion = other.clipRegion; - hasClipping = other.hasClipping; - fastClip = other.fastClip; - depthClipId = other.depthClipId; -} - -QOpenGLPaintEngineState::QOpenGLPaintEngineState() -{ - hasClipping = false; - depthClipId = 0; -} - -QOpenGLPaintEngineState::~QOpenGLPaintEngineState() -{ -} - -void QOpenGLPaintEnginePrivate::ensureDrawableTexture() -{ - if (!dirty_drawable_texture) - return; - - dirty_drawable_texture = false; - -#ifndef QT_OPENGL_ES - glGenTextures(1, &drawable_texture); - glBindTexture(GL_TEXTURE_2D, drawable_texture); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, - drawable_texture_size.width(), - drawable_texture_size.height(), 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -#endif -} - -QT_END_NAMESPACE - -#include "qpaintengine_opengl.moc" diff --git a/src/opengl/qpaintengine_opengl_p.h b/src/opengl/qpaintengine_opengl_p.h deleted file mode 100644 index 8d0ea83a47..0000000000 --- a/src/opengl/qpaintengine_opengl_p.h +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPAINTENGINE_OPENGL_P_H -#define QPAINTENGINE_OPENGL_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 QLibrary class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QOpenGLPaintEnginePrivate; -class QGLTexture; - -class QOpenGLPaintEngineState : public QPainterState -{ -public: - QOpenGLPaintEngineState(QOpenGLPaintEngineState &other); - QOpenGLPaintEngineState(); - ~QOpenGLPaintEngineState(); - - QRegion clipRegion; - bool hasClipping; - QRect fastClip; - uint depthClipId; -}; - -class QOpenGLPaintEngine : public QPaintEngineEx -{ - Q_DECLARE_PRIVATE(QOpenGLPaintEngine) -public: - QOpenGLPaintEngine(); - ~QOpenGLPaintEngine(); - - bool begin(QPaintDevice *pdev); - bool end(); - - // new stuff - void clipEnabledChanged(); - void penChanged(); - void brushChanged(); - void brushOriginChanged(); - void opacityChanged(); - void compositionModeChanged(); - void renderHintsChanged(); - void transformChanged(); - - void fill(const QVectorPath &path, const QBrush &brush); - void clip(const QVectorPath &path, Qt::ClipOperation op); - - void setState(QPainterState *s); - QPainterState *createState(QPainterState *orig) const; - inline QOpenGLPaintEngineState *state() { - return static_cast(QPaintEngineEx::state()); - } - inline const QOpenGLPaintEngineState *state() const { - return static_cast(QPaintEngineEx::state()); - } - - - // old stuff - void updateState(const QPaintEngineState &state); - - void updatePen(const QPen &pen); - void updateBrush(const QBrush &brush, const QPointF &pt); - void updateFont(const QFont &font); - void updateMatrix(const QTransform &matrix); - void updateClipRegion(const QRegion ®ion, Qt::ClipOperation op); - void updateRenderHints(QPainter::RenderHints hints); - void updateCompositionMode(QPainter::CompositionMode composition_mode); - - void drawRects(const QRectF *r, int rectCount); - void drawLines(const QLineF *lines, int lineCount); - void drawPoints(const QPointF *p, int pointCount); - void drawRects(const QRect *r, int rectCount); - void drawLines(const QLine *lines, int lineCount); - void drawPoints(const QPoint *p, int pointCount); - - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - - void drawPath(const QPainterPath &path); - void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); - void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - void drawImage(const QRectF &r, const QImage &image, const QRectF &sr, - Qt::ImageConversionFlags conversionFlags); - void drawTextItem(const QPointF &p, const QTextItem &ti); - void drawStaticTextItem(QStaticTextItem *staticTextItem); - - void drawEllipse(const QRectF &rect); - -#ifdef Q_WS_WIN - HDC handle() const; -#else - Qt::HANDLE handle() const; -#endif - inline Type type() const { return QPaintEngine::OpenGL; } - bool supportsTransformations(qreal, const QTransform &) const { return true; } - -private: - void drawPolyInternal(const QPolygonF &pa, bool close = true); - void drawTextureRect(int tx_width, int tx_height, const QRectF &r, const QRectF &sr, - GLenum target, QGLTexture *tex); - Q_DISABLE_COPY(QOpenGLPaintEngine) -}; - - -QT_END_NAMESPACE - -#endif // QPAINTENGINE_OPENGL_P_H -- cgit v1.2.3