diff options
Diffstat (limited to 'src/opengl')
101 files changed, 611 insertions, 34021 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 4c50089f6d..aebdce6e01 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -44,6 +44,8 @@ #include "qpaintengineex_opengl2_p.h" #include "qglshadercache_p.h" +#include <QtGui/private/qopenglcontext_p.h> + #if defined(QT_DEBUG) #include <QMetaEnum> #endif @@ -52,18 +54,50 @@ QT_BEGIN_NAMESPACE +class QGLEngineSharedShadersResource : public QOpenGLSharedResource +{ +public: + QGLEngineSharedShadersResource(QOpenGLContext *ctx) + : QOpenGLSharedResource(ctx->shareGroup()) + , m_shaders(new QGLEngineSharedShaders(QGLContext::fromOpenGLContext(ctx))) + { + } + + ~QGLEngineSharedShadersResource() + { + delete m_shaders; + } + + void invalidateResource() + { + delete m_shaders; + m_shaders = 0; + } + + void freeResource(QOpenGLContext *) + { + } + + QGLEngineSharedShaders *shaders() const { return m_shaders; } + +private: + QGLEngineSharedShaders *m_shaders; +}; + class QGLShaderStorage { public: QGLEngineSharedShaders *shadersForThread(const QGLContext *context) { - QGLContextGroupResource<QGLEngineSharedShaders> *&shaders = m_storage.localData(); + QOpenGLMultiGroupSharedResource *&shaders = m_storage.localData(); if (!shaders) - shaders = new QGLContextGroupResource<QGLEngineSharedShaders>(); - return shaders->value(context); + shaders = new QOpenGLMultiGroupSharedResource; + QGLEngineSharedShadersResource *resource = + shaders->value<QGLEngineSharedShadersResource>(context->contextHandle()); + return resource ? resource->shaders() : 0; } private: - QThreadStorage<QGLContextGroupResource<QGLEngineSharedShaders> *> m_storage; + QThreadStorage<QOpenGLMultiGroupSharedResource *> m_storage; }; Q_GLOBAL_STATIC(QGLShaderStorage, qt_shader_storage); @@ -81,8 +115,7 @@ const char* QGLEngineSharedShaders::qShaderSnippets[] = { }; QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) - : ctxGuard(context) - , blitShaderProg(0) + : blitShaderProg(0) , simpleShaderProg(0) { @@ -327,14 +360,14 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS vertexSource.append(qShaderSnippets[prog.mainVertexShader]); vertexSource.append(qShaderSnippets[prog.positionVertexShader]); - QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram(ctxGuard.context(), 0)); + QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram); CachedShader shaderCache(fragSource, vertexSource); - bool inCache = shaderCache.load(shaderProgram.data(), ctxGuard.context()); + bool inCache = shaderCache.load(shaderProgram.data(), QGLContext::currentContext()); if (!inCache) { - QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment, ctxGuard.context(), 0)); + QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment)); QByteArray description; #if defined(QT_DEBUG) // Name the shader for easier debugging @@ -357,7 +390,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS break; } - QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex, ctxGuard.context(), 0)); + QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex)); #if defined(QT_DEBUG) // Name the shader for easier debugging description.clear(); @@ -396,7 +429,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS newProg->program->link(); if (newProg->program->isLinked()) { if (!inCache) - shaderCache.store(newProg->program, ctxGuard.context()); + shaderCache.store(newProg->program, QGLContext::currentContext()); } else { QLatin1String none("none"); QLatin1String br("\n"); diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 921df369f4..58c761df43 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -365,7 +365,6 @@ public: void cleanupCustomStage(QGLCustomShaderStage* stage); private: - QGLSharedResourceGuard ctxGuard; QGLShaderProgram *blitShaderProg; QGLShaderProgram *simpleShaderProg; QList<QGLEngineShaderProg*> cachedPrograms; diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index 9e6b801c40..6ca09ba140 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -51,21 +51,42 @@ class QGL2GradientCacheWrapper public: QGL2GradientCache *cacheForContext(const QGLContext *context) { QMutexLocker lock(&m_mutex); - return m_resource.value(context); + return m_resource.value<QGL2GradientCache>(context->contextHandle()); } private: - QGLContextGroupResource<QGL2GradientCache> m_resource; + QOpenGLMultiGroupSharedResource m_resource; QMutex m_mutex; }; Q_GLOBAL_STATIC(QGL2GradientCacheWrapper, qt_gradient_caches) +QGL2GradientCache::QGL2GradientCache(QOpenGLContext *ctx) + : QOpenGLSharedResource(ctx->shareGroup()) +{ +} + +QGL2GradientCache::~QGL2GradientCache() +{ + cache.clear(); +} + QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context) { return qt_gradient_caches()->cacheForContext(context); } +void QGL2GradientCache::invalidateResource() +{ + QMutexLocker lock(&m_mutex); + cache.clear(); +} + +void QGL2GradientCache::freeResource(QOpenGLContext *) +{ + cleanCache(); +} + void QGL2GradientCache::cleanCache() { QMutexLocker lock(&m_mutex); diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h index 1c2d0a029a..600085a75f 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache_p.h +++ b/src/opengl/gl2paintengineex/qglgradientcache_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE -class QGL2GradientCache +class QGL2GradientCache : public QOpenGLSharedResource { struct CacheInfo { @@ -76,12 +76,15 @@ class QGL2GradientCache public: static QGL2GradientCache *cacheForContext(const QGLContext *context); - QGL2GradientCache(const QGLContext *) {} - ~QGL2GradientCache() { cleanCache(); } + QGL2GradientCache(QOpenGLContext *); + ~QGL2GradientCache(); GLuint getBuffer(const QGradient &gradient, qreal opacity); inline int paletteSize() const { return 1024; } + void invalidateResource(); + void freeResource(QOpenGLContext *ctx); + private: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& gradient, diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index d2c63ddc10..e6a12cd40c 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -76,10 +76,9 @@ #include <QPaintEngine> #include <private/qpainter_p.h> #include <private/qfontengine_p.h> -#include <private/qpixmapdata_gl_p.h> #include <private/qdatabuffer_p.h> #include <private/qstatictext_p.h> -#include <private/qtriangulator_p.h> +#include <QtGui/private/qtriangulator_p.h> #include "qglengineshadermanager_p.h" #include "qgl2pexvertexarray_p.h" @@ -668,6 +667,7 @@ struct QGL2PEVectorPathCache int indexCount; GLenum primitiveType; qreal iscale; + QVertexIndexVector::Type indexType; }; void QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data) @@ -825,13 +825,14 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) cache->indexCount = polys.indices.size(); cache->primitiveType = GL_TRIANGLES; cache->iscale = inverseScale; + cache->indexType = polys.indices.type(); #ifdef QT_OPENGL_CACHE_AS_VBOS glGenBuffers(1, &cache->vbo); glGenBuffers(1, &cache->ibo); glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo); - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) + if (polys.indices.type() == QVertexIndexVector::UnsignedInt) glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint32) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW); else glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint16) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW); @@ -842,7 +843,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW); #else cache->vertices = (float *) qMalloc(sizeof(float) * polys.vertices.size()); - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { + if (polys.indices.type() == QVertexIndexVector::UnsignedInt) { cache->indices = (quint32 *) qMalloc(sizeof(quint32) * polys.indices.size()); memcpy(cache->indices, polys.indices.data(), sizeof(quint32) * polys.indices.size()); } else { @@ -859,7 +860,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo); setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0); - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) + if (cache->indexType == QVertexIndexVector::UnsignedInt) glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, 0); else glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, 0); @@ -867,7 +868,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glBindBuffer(GL_ARRAY_BUFFER, 0); #else setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, cache->vertices); - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) + if (cache->indexType == QVertexIndexVector::UnsignedInt) glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, (qint32 *)cache->indices); else glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, (qint16 *)cache->indices); @@ -896,7 +897,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) prepareForDraw(currentBrush.isOpaque()); setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertices.constData()); - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) + if (polys.indices.type() == QVertexIndexVector::UnsignedInt) glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_INT, polys.indices.data()); else glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_SHORT, polys.indices.data()); @@ -1581,10 +1582,9 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp QGLTextureGlyphCache *cache = (QGLTextureGlyphCache *) staticTextItem->fontEngine()->glyphCache(cacheKey, glyphType, QTransform()); - if (!cache || cache->cacheType() != glyphType || cache->context() == 0) { - cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); + if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) { + cache = new QGLTextureGlyphCache(glyphType, QTransform()); staticTextItem->fontEngine()->setGlyphCache(cacheKey, cache); - cache->insert(ctx, cache); recreateVertexArrays = true; } @@ -2048,21 +2048,13 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) bool QGL2PaintEngineEx::end() { Q_D(QGL2PaintEngineEx); - QGLContext *ctx = d->ctx; + 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; + ctx->d_ptr->active_engine = 0; d->resetGLState(); @@ -2335,8 +2327,8 @@ void QGL2PaintEngineExPrivate::systemStateChanged() if (systemClip.isEmpty()) { useSystemClip = false; } else { - if (q->paintDevice()->devType() == QInternal::Widget && currentClipWidget) { - QWidgetPrivate *widgetPrivate = qt_widget_private(currentClipWidget->window()); + if (q->paintDevice()->devType() == QInternal::Widget && currentClipDevice) { + QWidgetPrivate *widgetPrivate = qt_widget_private(static_cast<QWidget *>(currentClipDevice)->window()); useSystemClip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; } else { useSystemClip = true; 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 <private/qglengineshadermanager_p.h> #include <private/qgl2pexvertexarray_p.h> #include <private/qglpaintdevice_p.h> -#include <private/qglpixmapfilter_p.h> #include <private/qfontengine_p.h> #include <private/qdatabuffer_p.h> #include <private/qtriangulatingstroker_p.h> @@ -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<QPixmapFilter> convolutionFilter; - QScopedPointer<QPixmapFilter> colorizeFilter; - QScopedPointer<QPixmapFilter> blurFilter; - QScopedPointer<QPixmapFilter> dropShadowFilter; - QSet<QVectorPath::CacheEntry *> pathCaches; QVector<GLuint> unusedVBOSToClean; QVector<GLuint> unusedIBOSToClean; diff --git a/src/opengl/gl2paintengineex/qrbtree_p.h b/src/opengl/gl2paintengineex/qrbtree_p.h deleted file mode 100644 index 09ef81cdbb..0000000000 --- a/src/opengl/gl2paintengineex/qrbtree_p.h +++ /dev/null @@ -1,573 +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 QRBTREE_P_H -#define QRBTREE_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 <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -template <class T> -struct QRBTree -{ - struct Node - { - inline Node() : parent(0), left(0), right(0), red(true) { } - inline ~Node() {if (left) delete left; if (right) delete right;} - T data; - Node *parent; - Node *left; - Node *right; - bool red; - }; - - inline QRBTree() : root(0), freeList(0) { } - inline ~QRBTree(); - - inline void clear(); - - void attachBefore(Node *parent, Node *child); - void attachAfter(Node *parent, Node *child); - - inline Node *front(Node *node) const; - inline Node *back(Node *node) const; - Node *next(Node *node) const; - Node *previous(Node *node) const; - - inline void deleteNode(Node *&node); - inline Node *newNode(); - - // Return 1 if 'left' comes after 'right', 0 if equal, and -1 otherwise. - // 'left' and 'right' cannot be null. - int order(Node *left, Node *right); - inline bool validate() const; - -private: - void rotateLeft(Node *node); - void rotateRight(Node *node); - void update(Node *node); - - inline void attachLeft(Node *parent, Node *child); - inline void attachRight(Node *parent, Node *child); - - int blackDepth(Node *top) const; - bool checkRedBlackProperty(Node *top) const; - - void swapNodes(Node *n1, Node *n2); - void detach(Node *node); - - // 'node' must be black. rebalance will reduce the depth of black nodes by one in the sibling tree. - void rebalance(Node *node); - -public: - Node *root; -private: - Node *freeList; -}; - -template <class T> -inline QRBTree<T>::~QRBTree() -{ - clear(); - while (freeList) { - // Avoid recursively calling the destructor, as this list may become large. - Node *next = freeList->right; - freeList->right = 0; - delete freeList; - freeList = next; - } -} - -template <class T> -inline void QRBTree<T>::clear() -{ - if (root) - delete root; - root = 0; -} - -template <class T> -void QRBTree<T>::rotateLeft(Node *node) -{ - // | | // - // N B // - // / \ / \ // - // A B ---> N D // - // / \ / \ // - // C D A C // - - Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root); - ref = node->right; - node->right->parent = node->parent; - - // : // - // N // - // / :| // - // A B // - // / \ // - // C D // - - node->right = ref->left; - if (ref->left) - ref->left->parent = node; - - // : | // - // N B // - // / \ : \ // - // A C D // - - ref->left = node; - node->parent = ref; - - // | // - // B // - // / \ // - // N D // - // / \ // - // A C // -} - -template <class T> -void QRBTree<T>::rotateRight(Node *node) -{ - // | | // - // N A // - // / \ / \ // - // A B ---> C N // - // / \ / \ // - // C D D B // - - Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root); - ref = node->left; - node->left->parent = node->parent; - - node->left = ref->right; - if (ref->right) - ref->right->parent = node; - - ref->right = node; - node->parent = ref; -} - -template <class T> -void QRBTree<T>::update(Node *node) // call this after inserting a node -{ - for (;;) { - Node *parent = node->parent; - - // if the node is the root, color it black - if (!parent) { - node->red = false; - return; - } - - // if the parent is black, the node can be left red - if (!parent->red) - return; - - // at this point, the parent is red and cannot be the root - Node *grandpa = parent->parent; - Q_ASSERT(grandpa); - - Node *uncle = (parent == grandpa->left ? grandpa->right : grandpa->left); - if (uncle && uncle->red) { - // grandpa's black, parent and uncle are red. - // let parent and uncle be black, grandpa red and recursively update grandpa. - Q_ASSERT(!grandpa->red); - parent->red = false; - uncle->red = false; - grandpa->red = true; - node = grandpa; - continue; - } - - // at this point, uncle is black - if (node == parent->right && parent == grandpa->left) - rotateLeft(node = parent); - else if (node == parent->left && parent == grandpa->right) - rotateRight(node = parent); - parent = node->parent; - - if (parent == grandpa->left) { - rotateRight(grandpa); - parent->red = false; - grandpa->red = true; - } else { - rotateLeft(grandpa); - parent->red = false; - grandpa->red = true; - } - return; - } -} - -template <class T> -inline void QRBTree<T>::attachLeft(Node *parent, Node *child) -{ - Q_ASSERT(!parent->left); - parent->left = child; - child->parent = parent; - update(child); -} - -template <class T> -inline void QRBTree<T>::attachRight(Node *parent, Node *child) -{ - Q_ASSERT(!parent->right); - parent->right = child; - child->parent = parent; - update(child); -} - -template <class T> -void QRBTree<T>::attachBefore(Node *parent, Node *child) -{ - if (!root) - update(root = child); - else if (!parent) - attachRight(back(root), child); - else if (parent->left) - attachRight(back(parent->left), child); - else - attachLeft(parent, child); -} - -template <class T> -void QRBTree<T>::attachAfter(Node *parent, Node *child) -{ - if (!root) - update(root = child); - else if (!parent) - attachLeft(front(root), child); - else if (parent->right) - attachLeft(front(parent->right), child); - else - attachRight(parent, child); -} - -template <class T> -void QRBTree<T>::swapNodes(Node *n1, Node *n2) -{ - // Since iterators must not be invalidated, it is not sufficient to only swap the data. - if (n1->parent == n2) { - n1->parent = n2->parent; - n2->parent = n1; - } else if (n2->parent == n1) { - n2->parent = n1->parent; - n1->parent = n2; - } else { - qSwap(n1->parent, n2->parent); - } - - qSwap(n1->left, n2->left); - qSwap(n1->right, n2->right); - qSwap(n1->red, n2->red); - - if (n1->parent) { - if (n1->parent->left == n2) - n1->parent->left = n1; - else - n1->parent->right = n1; - } else { - root = n1; - } - - if (n2->parent) { - if (n2->parent->left == n1) - n2->parent->left = n2; - else - n2->parent->right = n2; - } else { - root = n2; - } - - if (n1->left) - n1->left->parent = n1; - if (n1->right) - n1->right->parent = n1; - - if (n2->left) - n2->left->parent = n2; - if (n2->right) - n2->right->parent = n2; -} - -template <class T> -void QRBTree<T>::detach(Node *node) // call this before removing a node. -{ - if (node->right) - swapNodes(node, front(node->right)); - - Node *child = (node->left ? node->left : node->right); - - if (!node->red) { - if (child && child->red) - child->red = false; - else - rebalance(node); - } - - Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root); - ref = child; - if (child) - child->parent = node->parent; - node->left = node->right = node->parent = 0; -} - -// 'node' must be black. rebalance will reduce the depth of black nodes by one in the sibling tree. -template <class T> -void QRBTree<T>::rebalance(Node *node) -{ - Q_ASSERT(!node->red); - for (;;) { - if (!node->parent) - return; - - // at this point, node is not a parent, it is black, thus it must have a sibling. - Node *sibling = (node == node->parent->left ? node->parent->right : node->parent->left); - Q_ASSERT(sibling); - - if (sibling->red) { - sibling->red = false; - node->parent->red = true; - if (node == node->parent->left) - rotateLeft(node->parent); - else - rotateRight(node->parent); - sibling = (node == node->parent->left ? node->parent->right : node->parent->left); - Q_ASSERT(sibling); - } - - // at this point, the sibling is black. - Q_ASSERT(!sibling->red); - - if ((!sibling->left || !sibling->left->red) && (!sibling->right || !sibling->right->red)) { - bool parentWasRed = node->parent->red; - sibling->red = true; - node->parent->red = false; - if (parentWasRed) - return; - node = node->parent; - continue; - } - - // at this point, at least one of the sibling's children is red. - - if (node == node->parent->left) { - if (!sibling->right || !sibling->right->red) { - Q_ASSERT(sibling->left); - sibling->red = true; - sibling->left->red = false; - rotateRight(sibling); - - sibling = sibling->parent; - Q_ASSERT(sibling); - } - sibling->red = node->parent->red; - node->parent->red = false; - - Q_ASSERT(sibling->right->red); - sibling->right->red = false; - rotateLeft(node->parent); - } else { - if (!sibling->left || !sibling->left->red) { - Q_ASSERT(sibling->right); - sibling->red = true; - sibling->right->red = false; - rotateLeft(sibling); - - sibling = sibling->parent; - Q_ASSERT(sibling); - } - sibling->red = node->parent->red; - node->parent->red = false; - - Q_ASSERT(sibling->left->red); - sibling->left->red = false; - rotateRight(node->parent); - } - return; - } -} - -template <class T> -inline typename QRBTree<T>::Node *QRBTree<T>::front(Node *node) const -{ - while (node->left) - node = node->left; - return node; -} - -template <class T> -inline typename QRBTree<T>::Node *QRBTree<T>::back(Node *node) const -{ - while (node->right) - node = node->right; - return node; -} - -template <class T> -typename QRBTree<T>::Node *QRBTree<T>::next(Node *node) const -{ - if (node->right) - return front(node->right); - while (node->parent && node == node->parent->right) - node = node->parent; - return node->parent; -} - -template <class T> -typename QRBTree<T>::Node *QRBTree<T>::previous(Node *node) const -{ - if (node->left) - return back(node->left); - while (node->parent && node == node->parent->left) - node = node->parent; - return node->parent; -} - -template <class T> -int QRBTree<T>::blackDepth(Node *top) const -{ - if (!top) - return 0; - int leftDepth = blackDepth(top->left); - int rightDepth = blackDepth(top->right); - if (leftDepth != rightDepth) - return -1; - if (!top->red) - ++leftDepth; - return leftDepth; -} - -template <class T> -bool QRBTree<T>::checkRedBlackProperty(Node *top) const -{ - if (!top) - return true; - if (top->left && !checkRedBlackProperty(top->left)) - return false; - if (top->right && !checkRedBlackProperty(top->right)) - return false; - return !(top->red && ((top->left && top->left->red) || (top->right && top->right->red))); -} - -template <class T> -inline bool QRBTree<T>::validate() const -{ - return checkRedBlackProperty(root) && blackDepth(root) != -1; -} - -template <class T> -inline void QRBTree<T>::deleteNode(Node *&node) -{ - Q_ASSERT(node); - detach(node); - node->right = freeList; - freeList = node; - node = 0; -} - -template <class T> -inline typename QRBTree<T>::Node *QRBTree<T>::newNode() -{ - if (freeList) { - Node *node = freeList; - freeList = freeList->right; - node->parent = node->left = node->right = 0; - node->red = true; - return node; - } - return new Node; -} - -// Return 1 if 'left' comes after 'right', 0 if equal, and -1 otherwise. -// 'left' and 'right' cannot be null. -template <class T> -int QRBTree<T>::order(Node *left, Node *right) -{ - Q_ASSERT(left && right); - if (left == right) - return 0; - - QVector<Node *> leftAncestors; - QVector<Node *> rightAncestors; - while (left) { - leftAncestors.push_back(left); - left = left->parent; - } - while (right) { - rightAncestors.push_back(right); - right = right->parent; - } - Q_ASSERT(leftAncestors.back() == root && rightAncestors.back() == root); - - while (!leftAncestors.empty() && !rightAncestors.empty() && leftAncestors.back() == rightAncestors.back()) { - leftAncestors.pop_back(); - rightAncestors.pop_back(); - } - - if (!leftAncestors.empty()) - return (leftAncestors.back() == leftAncestors.back()->parent->left ? -1 : 1); - - if (!rightAncestors.empty()) - return (rightAncestors.back() == rightAncestors.back()->parent->right ? -1 : 1); - - // The code should never reach this point. - Q_ASSERT(!leftAncestors.empty() || !rightAncestors.empty()); - return 0; -} - -QT_END_NAMESPACE - -#endif diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index dbed354dfb..af6cb53a3a 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 @@ -55,19 +51,16 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled; QBasicAtomicInt qgltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); -QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) - : QImageTextureGlyphCache(type, matrix), QGLContextGroupResourceBase() - , ctx(0) +QGLTextureGlyphCache::QGLTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) + : QImageTextureGlyphCache(type, matrix) , pex(0) , m_blitProgram(0) , m_filterMode(Nearest) , m_serialNumber(qgltextureglyphcache_serial_number.fetchAndAddRelaxed(1)) { #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG - qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, ctx); + qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, QOpenGLContext::currentContext()); #endif - setContext(context); - m_vertexCoordinateArray[0] = -1.0f; m_vertexCoordinateArray[1] = -1.0f; m_vertexCoordinateArray[2] = 1.0f; @@ -95,14 +88,9 @@ QGLTextureGlyphCache::~QGLTextureGlyphCache() delete m_blitProgram; } -void QGLTextureGlyphCache::setContext(const QGLContext *context) -{ - ctx = context; - m_h = 0; -} - void QGLTextureGlyphCache::createTextureData(int width, int height) { + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); if (ctx == 0) { qWarning("QGLTextureGlyphCache::createTextureData: Called with no context"); return; @@ -120,12 +108,17 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) if (height < 16) height = 16; - QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); - glGenTextures(1, &glyphTexture->m_texture); - glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); + if (m_textureResource && !m_textureResource->m_texture) + delete m_textureResource; + + if (!m_textureResource) + m_textureResource = new QGLGlyphTexture(ctx); + + glGenTextures(1, &m_textureResource->m_texture); + glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); - glyphTexture->m_width = width; - glyphTexture->m_height = height; + m_textureResource->m_width = width; + m_textureResource->m_height = height; if (m_type == QFontEngineGlyphCache::Raster_RGBMask) { QVarLengthArray<uchar> data(width * height * 4); @@ -148,14 +141,14 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) void QGLTextureGlyphCache::resizeTextureData(int width, int height) { + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); if (ctx == 0) { qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context"); return; } - QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); - int oldWidth = glyphTexture->m_width; - int oldHeight = glyphTexture->m_height; + int oldWidth = m_textureResource->m_width; + int oldHeight = m_textureResource->m_height; // Make the lower glyph texture size 16 x 16. if (width < 16) @@ -163,7 +156,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) if (height < 16) height = 16; - GLuint oldTexture = glyphTexture->m_texture; + GLuint oldTexture = m_textureResource->m_texture; createTextureData(width, height); if (ctx->d_ptr->workaround_brokenFBOReadBack) { @@ -177,7 +170,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail - glBindFramebuffer(GL_FRAMEBUFFER_EXT, glyphTexture->m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_textureResource->m_fbo); GLuint tmp_texture; glGenTextures(1, &tmp_texture); @@ -261,7 +254,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); + glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); @@ -280,16 +273,16 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) { + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); if (ctx == 0) { qWarning("QGLTextureGlyphCache::fillTexture: Called with no context"); return; } - QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition); - glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); + glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); const QImage &texture = image(); const uchar *bits = texture.constBits(); bits += c.y * texture.bytesPerLine() + c.x; @@ -326,7 +319,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub } } - glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); + glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); if (mask.format() == QImage::Format_RGB32) { glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); } else { @@ -362,6 +355,7 @@ int QGLTextureGlyphCache::glyphPadding() const int QGLTextureGlyphCache::maxTextureWidth() const { + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); if (ctx == 0) return QImageTextureGlyphCache::maxTextureWidth(); else @@ -370,6 +364,7 @@ int QGLTextureGlyphCache::maxTextureWidth() const int QGLTextureGlyphCache::maxTextureHeight() const { + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); if (ctx == 0) return QImageTextureGlyphCache::maxTextureHeight(); @@ -381,16 +376,15 @@ int QGLTextureGlyphCache::maxTextureHeight() const void QGLTextureGlyphCache::clear() { - if (ctx != 0) { - m_textureResource.cleanup(ctx); - - m_w = 0; - m_h = 0; - m_cx = 0; - m_cy = 0; - m_currentRowHeight = 0; - coords.clear(); - } + m_textureResource->free(); + m_textureResource = 0; + + m_w = 0; + m_h = 0; + m_cx = 0; + m_cy = 0; + m_currentRowHeight = 0; + coords.clear(); } QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 83ca06d040..7b7da9d8e8 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -63,10 +63,11 @@ QT_BEGIN_NAMESPACE class QGL2PaintEngineExPrivate; -struct QGLGlyphTexture +struct QGLGlyphTexture : public QOpenGLSharedResource { QGLGlyphTexture(const QGLContext *ctx) - : m_width(0) + : QOpenGLSharedResource(ctx->contextHandle()->shareGroup()) + , m_width(0) , m_height(0) { if (ctx && !ctx->d_ptr->workaround_brokenFBOReadBack) @@ -77,19 +78,24 @@ struct QGLGlyphTexture #endif } - ~QGLGlyphTexture() { - const QGLContext *ctx = QGLContext::currentContext(); + void freeResource(QOpenGLContext *context) + { + const QGLContext *ctx = QGLContext::fromOpenGLContext(context); #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG qDebug("~QGLGlyphTexture() %p for context %p.", this, ctx); #endif - // At this point, the context group is made current, so it's safe to - // release resources without a makeCurrent() call - if (ctx) { - if (!ctx->d_ptr->workaround_brokenFBOReadBack) - glDeleteFramebuffers(1, &m_fbo); - if (m_width || m_height) - glDeleteTextures(1, &m_texture); - } + if (!ctx->d_ptr->workaround_brokenFBOReadBack) + glDeleteFramebuffers(1, &m_fbo); + if (m_width || m_height) + glDeleteTextures(1, &m_texture); + } + + void invalidateResource() + { + m_texture = 0; + m_fbo = 0; + m_width = 0; + m_height = 0; } GLuint m_texture; @@ -98,10 +104,10 @@ struct QGLGlyphTexture int m_height; }; -class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache, public QGLContextGroupResourceBase +class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache { public: - QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); + QGLTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix); ~QGLTextureGlyphCache(); virtual void createTextureData(int width, int height); @@ -113,25 +119,24 @@ public: inline GLuint texture() const { QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); - QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + QGLGlyphTexture *glyphTexture = that->m_textureResource; return glyphTexture ? glyphTexture->m_texture : 0; } inline int width() const { QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); - QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + QGLGlyphTexture *glyphTexture = that->m_textureResource; return glyphTexture ? glyphTexture->m_width : 0; } inline int height() const { QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); - QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + QGLGlyphTexture *glyphTexture = that->m_textureResource; return glyphTexture ? glyphTexture->m_height : 0; } inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } - void setContext(const QGLContext *context); - inline const QGLContext *context() const { return ctx; } + inline const QOpenGLContextGroup *contextGroup() const { return m_textureResource ? m_textureResource->group() : 0; } inline int serialNumber() const { return m_serialNumber; } @@ -144,12 +149,9 @@ public: void clear(); - void freeResource(void *) { ctx = 0; } - private: - QGLContextGroupResource<QGLGlyphTexture> m_textureResource; + QGLGlyphTexture *m_textureResource; - const QGLContext *ctx; QGL2PaintEngineExPrivate *pex; QGLShaderProgram *m_blitProgram; FilterMode m_filterMode; diff --git a/src/opengl/gl2paintengineex/qtriangulator.cpp b/src/opengl/gl2paintengineex/qtriangulator.cpp deleted file mode 100644 index d4b7131794..0000000000 --- a/src/opengl/gl2paintengineex/qtriangulator.cpp +++ /dev/null @@ -1,2612 +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 "qtriangulator_p.h" - -#include <QtGui/qdialog.h> -#include <QtGui/qevent.h> -#include <QtGui/qpainter.h> -#include <QtGui/qpainterpath.h> -#include <QtGui/private/qbezier_p.h> -#include <QtGui/private/qdatabuffer_p.h> -#include <QtCore/qbitarray.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qqueue.h> -#include <QtCore/qglobal.h> -#include <QtCore/qpoint.h> -#include <QtCore/qalgorithms.h> - -#include <private/qgl_p.h> -#include <private/qrbtree_p.h> - -#include <math.h> - -QT_BEGIN_NAMESPACE - -//#define Q_TRIANGULATOR_DEBUG - -#define Q_FIXED_POINT_SCALE 32 - -// Quick sort. -template <class T, class LessThan> -#ifdef Q_CC_RVCT // RVCT 2.2 doesn't see recursive _static_ template function -void sort(T *array, int count, LessThan lessThan) -#else -static void sort(T *array, int count, LessThan lessThan) -#endif -{ - // If the number of elements fall below some threshold, use insertion sort. - const int INSERTION_SORT_LIMIT = 7; // About 7 is fastest on my computer... - if (count <= INSERTION_SORT_LIMIT) { - for (int i = 1; i < count; ++i) { - T temp = array[i]; - int j = i; - while (j > 0 && lessThan(temp, array[j - 1])) { - array[j] = array[j - 1]; - --j; - } - array[j] = temp; - } - return; - } - - int high = count - 1; - int low = 0; - int mid = high / 2; - if (lessThan(array[mid], array[low])) - qSwap(array[mid], array[low]); - if (lessThan(array[high], array[mid])) - qSwap(array[high], array[mid]); - if (lessThan(array[mid], array[low])) - qSwap(array[mid], array[low]); - - --high; - ++low; - qSwap(array[mid], array[high]); - int pivot = high; - --high; - - while (low <= high) { - while (!lessThan(array[pivot], array[low])) { - ++low; - if (low > high) - goto sort_loop_end; - } - while (!lessThan(array[high], array[pivot])) { - --high; - if (low > high) - goto sort_loop_end; - } - qSwap(array[low], array[high]); - ++low; - --high; - } -sort_loop_end: - if (low != pivot) - qSwap(array[pivot], array[low]); - sort(array, low, lessThan); - sort(array + low + 1, count - low - 1, lessThan); -} - -// Quick sort. -template <class T> -#ifdef Q_CC_RVCT -void sort(T *array, int count) // RVCT 2.2 doesn't see recursive _static_ template function -#else -static void sort(T *array, int count) -#endif -{ - // If the number of elements fall below some threshold, use insertion sort. - const int INSERTION_SORT_LIMIT = 25; // About 25 is fastest on my computer... - if (count <= INSERTION_SORT_LIMIT) { - for (int i = 1; i < count; ++i) { - T temp = array[i]; - int j = i; - while (j > 0 && (temp < array[j - 1])) { - array[j] = array[j - 1]; - --j; - } - array[j] = temp; - } - return; - } - - int high = count - 1; - int low = 0; - int mid = high / 2; - if ((array[mid] < array[low])) - qSwap(array[mid], array[low]); - if ((array[high] < array[mid])) - qSwap(array[high], array[mid]); - if ((array[mid] < array[low])) - qSwap(array[mid], array[low]); - - --high; - ++low; - qSwap(array[mid], array[high]); - int pivot = high; - --high; - - while (low <= high) { - while (!(array[pivot] < array[low])) { - ++low; - if (low > high) - goto sort_loop_end; - } - while (!(array[high] < array[pivot])) { - --high; - if (low > high) - goto sort_loop_end; - } - qSwap(array[low], array[high]); - ++low; - --high; - } -sort_loop_end: - if (low != pivot) - qSwap(array[pivot], array[low]); - sort(array, low); - sort(array + low + 1, count - low - 1); -} - -template<typename T> -struct QVertexSet -{ - inline QVertexSet() { } - inline QVertexSet(const QVertexSet<T> &other) : vertices(other.vertices), indices(other.indices) { } - QVertexSet<T> &operator = (const QVertexSet<T> &other) {vertices = other.vertices; indices = other.indices; return *this;} - - // The vertices of a triangle are given by: (x[i[n]], y[i[n]]), (x[j[n]], y[j[n]]), (x[k[n]], y[k[n]]), n = 0, 1, ... - QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...] - QVector<T> indices; // [i[0], j[0], k[0], i[1], j[1], k[1], i[2], ...] -}; - -//============================================================================// -// QFraction // -//============================================================================// - -// Fraction must be in the range [0, 1) -struct QFraction -{ - // Comparison operators must not be called on invalid fractions. - inline bool operator < (const QFraction &other) const; - inline bool operator == (const QFraction &other) const; - inline bool operator != (const QFraction &other) const {return !(*this == other);} - inline bool operator > (const QFraction &other) const {return other < *this;} - inline bool operator >= (const QFraction &other) const {return !(*this < other);} - inline bool operator <= (const QFraction &other) const {return !(*this > other);} - - inline bool isValid() const {return denominator != 0;} - - // numerator and denominator must not have common denominators. - quint64 numerator, denominator; -}; - -static inline quint64 gcd(quint64 x, quint64 y) -{ - while (y != 0) { - quint64 z = y; - y = x % y; - x = z; - } - return x; -} - -static inline int compare(quint64 a, quint64 b) -{ - return (a > b) - (a < b); -} - -// Compare a/b with c/d. -// Return negative if less, 0 if equal, positive if greater. -// a < b, c < d -static int qCompareFractions(quint64 a, quint64 b, quint64 c, quint64 d) -{ - const quint64 LIMIT = Q_UINT64_C(0x100000000); - for (;;) { - // If the products 'ad' and 'bc' fit into 64 bits, they can be directly compared. - if (b < LIMIT && d < LIMIT) - return compare(a * d, b * c); - - if (a == 0 || c == 0) - return compare(a, c); - - // a/b < c/d <=> d/c < b/a - quint64 b_div_a = b / a; - quint64 d_div_c = d / c; - if (b_div_a != d_div_c) - return compare(d_div_c, b_div_a); - - // floor(d/c) == floor(b/a) - // frac(d/c) < frac(b/a) ? - // frac(x/y) = (x%y)/y - d -= d_div_c * c; //d %= c; - b -= b_div_a * a; //b %= a; - qSwap(a, d); - qSwap(b, c); - } -} - -// Fraction must be in the range [0, 1) -// Assume input is valid. -static QFraction qFraction(quint64 n, quint64 d) { - QFraction result; - if (n == 0) { - result.numerator = 0; - result.denominator = 1; - } else { - quint64 g = gcd(n, d); - result.numerator = n / g; - result.denominator = d / g; - } - return result; -} - -inline bool QFraction::operator < (const QFraction &other) const -{ - return qCompareFractions(numerator, denominator, other.numerator, other.denominator) < 0; -} - -inline bool QFraction::operator == (const QFraction &other) const -{ - return numerator == other.numerator && denominator == other.denominator; -} - -//============================================================================// -// QPodPoint // -//============================================================================// - -struct QPodPoint -{ - inline bool operator < (const QPodPoint &other) const - { - if (y != other.y) - return y < other.y; - return x < other.x; - } - - inline bool operator > (const QPodPoint &other) const {return other < *this;} - inline bool operator <= (const QPodPoint &other) const {return !(*this > other);} - inline bool operator >= (const QPodPoint &other) const {return !(*this < other);} - inline bool operator == (const QPodPoint &other) const {return x == other.x && y == other.y;} - inline bool operator != (const QPodPoint &other) const {return x != other.x || y != other.y;} - - inline QPodPoint &operator += (const QPodPoint &other) {x += other.x; y += other.y; return *this;} - inline QPodPoint &operator -= (const QPodPoint &other) {x -= other.x; y -= other.y; return *this;} - inline QPodPoint operator + (const QPodPoint &other) const {QPodPoint result = {x + other.x, y + other.y}; return result;} - inline QPodPoint operator - (const QPodPoint &other) const {QPodPoint result = {x - other.x, y - other.y}; return result;} - - int x; - int y; -}; - -static inline qint64 qCross(const QPodPoint &u, const QPodPoint &v) -{ - return qint64(u.x) * qint64(v.y) - qint64(u.y) * qint64(v.x); -} - -static inline qint64 qDot(const QPodPoint &u, const QPodPoint &v) -{ - return qint64(u.x) * qint64(v.x) + qint64(u.y) * qint64(v.y); -} - -// Return positive value if 'p' is to the right of the line 'v1'->'v2', negative if left of the -// line and zero if exactly on the line. -// The returned value is the z-component of the qCross product between 'v2-v1' and 'p-v1', -// which is twice the signed area of the triangle 'p'->'v1'->'v2' (positive for CW order). -static inline qint64 qPointDistanceFromLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2) -{ - return qCross(v2 - v1, p - v1); -} - -static inline bool qPointIsLeftOfLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2) -{ - return QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p, v1, v2) < 0; -} - -// Return: -// -1 if u < v -// 0 if u == v -// 1 if u > v -static int comparePoints(const QPodPoint &u, const QPodPoint &v) -{ - if (u.y < v.y) - return -1; - if (u.y > v.y) - return 1; - if (u.x < v.x) - return -1; - if (u.x > v.x) - return 1; - return 0; -} - -//============================================================================// -// QIntersectionPoint // -//============================================================================// - -struct QIntersectionPoint -{ - inline bool isValid() const {return xOffset.isValid() && yOffset.isValid();} - QPodPoint round() const; - inline bool isAccurate() const {return xOffset.numerator == 0 && yOffset.numerator == 0;} - bool operator < (const QIntersectionPoint &other) const; - bool operator == (const QIntersectionPoint &other) const; - inline bool operator != (const QIntersectionPoint &other) const {return !(*this == other);} - inline bool operator > (const QIntersectionPoint &other) const {return other < *this;} - inline bool operator >= (const QIntersectionPoint &other) const {return !(*this < other);} - inline bool operator <= (const QIntersectionPoint &other) const {return !(*this > other);} - bool isOnLine(const QPodPoint &u, const QPodPoint &v) const; - - QPodPoint upperLeft; - QFraction xOffset; - QFraction yOffset; -}; - -static inline QIntersectionPoint qIntersectionPoint(const QPodPoint &point) -{ - // upperLeft = point, xOffset = 0/1, yOffset = 0/1. - QIntersectionPoint p = {{point.x, point.y}, {0, 1}, {0, 1}}; - return p; -} - -static inline QIntersectionPoint qIntersectionPoint(int x, int y) -{ - // upperLeft = (x, y), xOffset = 0/1, yOffset = 0/1. - QIntersectionPoint p = {{x, y}, {0, 1}, {0, 1}}; - return p; -} - -static QIntersectionPoint qIntersectionPoint(const QPodPoint &u1, const QPodPoint &u2, const QPodPoint &v1, const QPodPoint &v2) -{ - QIntersectionPoint result = {{0, 0}, {0, 0}, {0, 0}}; - - QPodPoint u = u2 - u1; - QPodPoint v = v2 - v1; - qint64 d1 = qCross(u, v1 - u1); - qint64 d2 = qCross(u, v2 - u1); - qint64 det = d2 - d1; - qint64 d3 = qCross(v, u1 - v1); - qint64 d4 = d3 - det; //qCross(v, u2 - v1); - - // Check that the math is correct. - Q_ASSERT(d4 == qCross(v, u2 - v1)); - - // The intersection point can be expressed as: - // v1 - v * d1/det - // v2 - v * d2/det - // u1 + u * d3/det - // u2 + u * d4/det - - // I'm only interested in lines that are crossing, so ignore parallel lines even if they overlap. - if (det == 0) - return result; - - if (det < 0) { - det = -det; - d1 = -d1; - d2 = -d2; - d3 = -d3; - d4 = -d4; - } - - // I'm only interested in lines intersecting at their interior, not at their end points. - // The lines intersect at their interior if and only if 'd1 < 0', 'd2 > 0', 'd3 < 0' and 'd4 > 0'. - if (d1 >= 0 || d2 <= 0 || d3 <= 0 || d4 >= 0) - return result; - - // Calculate the intersection point as follows: - // v1 - v * d1/det | v1 <= v2 (component-wise) - // v2 - v * d2/det | v2 < v1 (component-wise) - - // Assuming 21 bits per vector component. - // TODO: Make code path for 31 bits per vector component. - if (v.x >= 0) { - result.upperLeft.x = v1.x + (-v.x * d1) / det; - result.xOffset = qFraction(quint64(-v.x * d1) % quint64(det), quint64(det)); - } else { - result.upperLeft.x = v2.x + (-v.x * d2) / det; - result.xOffset = qFraction(quint64(-v.x * d2) % quint64(det), quint64(det)); - } - - if (v.y >= 0) { - result.upperLeft.y = v1.y + (-v.y * d1) / det; - result.yOffset = qFraction(quint64(-v.y * d1) % quint64(det), quint64(det)); - } else { - result.upperLeft.y = v2.y + (-v.y * d2) / det; - result.yOffset = qFraction(quint64(-v.y * d2) % quint64(det), quint64(det)); - } - - Q_ASSERT(result.xOffset.isValid()); - Q_ASSERT(result.yOffset.isValid()); - return result; -} - -QPodPoint QIntersectionPoint::round() const -{ - QPodPoint result = upperLeft; - if (2 * xOffset.numerator >= xOffset.denominator) - ++result.x; - if (2 * yOffset.numerator >= yOffset.denominator) - ++result.y; - return result; -} - -bool QIntersectionPoint::operator < (const QIntersectionPoint &other) const -{ - if (upperLeft.y != other.upperLeft.y) - return upperLeft.y < other.upperLeft.y; - if (yOffset != other.yOffset) - return yOffset < other.yOffset; - if (upperLeft.x != other.upperLeft.x) - return upperLeft.x < other.upperLeft.x; - return xOffset < other.xOffset; -} - -bool QIntersectionPoint::operator == (const QIntersectionPoint &other) const -{ - return upperLeft == other.upperLeft && xOffset == other.xOffset && yOffset == other.yOffset; -} - -// Returns true if this point is on the infinite line passing through 'u' and 'v'. -bool QIntersectionPoint::isOnLine(const QPodPoint &u, const QPodPoint &v) const -{ - // TODO: Make code path for coordinates with more than 21 bits. - const QPodPoint p = upperLeft - u; - const QPodPoint q = v - u; - bool isHorizontal = p.y == 0 && yOffset.numerator == 0; - bool isVertical = p.x == 0 && xOffset.numerator == 0; - if (isHorizontal && isVertical) - return true; - if (isHorizontal) - return q.y == 0; - if (q.y == 0) - return false; - if (isVertical) - return q.x == 0; - if (q.x == 0) - return false; - - // At this point, 'p+offset' and 'q' cannot lie on the x or y axis. - - if (((q.x < 0) == (q.y < 0)) != ((p.x < 0) == (p.y < 0))) - return false; // 'p + offset' and 'q' pass through different quadrants. - - // Move all coordinates into the first quadrant. - quint64 nx, ny; - if (p.x < 0) - nx = quint64(-p.x) * xOffset.denominator - xOffset.numerator; - else - nx = quint64(p.x) * xOffset.denominator + xOffset.numerator; - if (p.y < 0) - ny = quint64(-p.y) * yOffset.denominator - yOffset.numerator; - else - ny = quint64(p.y) * yOffset.denominator + yOffset.numerator; - - return qFraction(quint64(qAbs(q.x)) * xOffset.denominator, quint64(qAbs(q.y)) * yOffset.denominator) == qFraction(nx, ny); -} - -//============================================================================// -// QMaxHeap // -//============================================================================// - -template <class T> -class QMaxHeap -{ -public: - QMaxHeap() : m_data(0) {} - inline int size() const {return m_data.size();} - inline bool empty() const {return m_data.isEmpty();} - inline bool isEmpty() const {return m_data.isEmpty();} - void push(const T &x); - T pop(); - inline const T &top() const {return m_data.first();} -private: - static inline int parent(int i) {return (i - 1) / 2;} - static inline int left(int i) {return 2 * i + 1;} - static inline int right(int i) {return 2 * i + 2;} - - QDataBuffer<T> m_data; -}; - -template <class T> -void QMaxHeap<T>::push(const T &x) -{ - int current = m_data.size(); - int parent = QMaxHeap::parent(current); - m_data.add(x); - while (current != 0 && m_data.at(parent) < x) { - m_data.at(current) = m_data.at(parent); - current = parent; - parent = QMaxHeap::parent(current); - } - m_data.at(current) = x; -} - -template <class T> -T QMaxHeap<T>::pop() -{ - T result = m_data.first(); - T back = m_data.last(); - m_data.pop_back(); - if (!m_data.isEmpty()) { - int current = 0; - for (;;) { - int left = QMaxHeap::left(current); - int right = QMaxHeap::right(current); - if (left >= m_data.size()) - break; - int greater = left; - if (right < m_data.size() && m_data.at(left) < m_data.at(right)) - greater = right; - if (m_data.at(greater) < back) - break; - m_data.at(current) = m_data.at(greater); - current = greater; - } - m_data.at(current) = back; - } - return result; -} - -//============================================================================// -// QInt64Hash // -//============================================================================// - -// Copied from qhash.cpp -static const uchar prime_deltas[] = { - 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, - 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 -}; - -// Copied from qhash.cpp -static inline int primeForNumBits(int numBits) -{ - return (1 << numBits) + prime_deltas[numBits]; -} - -static inline int primeForCount(int count) -{ - int low = 0; - int high = 32; - for (int i = 0; i < 5; ++i) { - int mid = (high + low) / 2; - if (count >= 1 << mid) - low = mid; - else - high = mid; - } - return primeForNumBits(high); -} - -// Hash set of quint64s. Elements cannot be removed without clearing the -// entire set. A value of -1 is used to mark unused entries. -class QInt64Set -{ -public: - inline QInt64Set(int capacity = 64); - inline ~QInt64Set() {if (m_array) delete[] m_array;} - inline bool isValid() const {return m_array;} - void insert(quint64 key); - bool contains(quint64 key) const; - inline void clear(); -private: - bool rehash(int capacity); - - static const quint64 UNUSED; - - quint64 *m_array; - int m_capacity; - int m_count; -}; - -const quint64 QInt64Set::UNUSED = quint64(-1); - -inline QInt64Set::QInt64Set(int capacity) -{ - m_capacity = primeForCount(capacity); - m_array = new quint64[m_capacity]; - if (m_array) - clear(); - else - m_capacity = 0; -} - -bool QInt64Set::rehash(int capacity) -{ - quint64 *oldArray = m_array; - int oldCapacity = m_capacity; - - m_capacity = capacity; - m_array = new quint64[m_capacity]; - if (m_array) { - clear(); - if (oldArray) { - for (int i = 0; i < oldCapacity; ++i) { - if (oldArray[i] != UNUSED) - insert(oldArray[i]); - } - delete[] oldArray; - } - return true; - } else { - m_capacity = oldCapacity; - m_array = oldArray; - return false; - } -} - -void QInt64Set::insert(quint64 key) -{ - if (m_count > 3 * m_capacity / 4) - rehash(primeForCount(2 * m_capacity)); - Q_ASSERT_X(m_array, "QInt64Hash<T>::insert", "Hash set not allocated."); - int index = int(key % m_capacity); - for (int i = 0; i < m_capacity; ++i) { - index += i; - if (index >= m_capacity) - index -= m_capacity; - if (m_array[index] == key) - return; - if (m_array[index] == UNUSED) { - ++m_count; - m_array[index] = key; - return; - } - } - Q_ASSERT_X(0, "QInt64Hash<T>::insert", "Hash set full."); -} - -bool QInt64Set::contains(quint64 key) const -{ - Q_ASSERT_X(m_array, "QInt64Hash<T>::contains", "Hash set not allocated."); - int index = int(key % m_capacity); - for (int i = 0; i < m_capacity; ++i) { - index += i; - if (index >= m_capacity) - index -= m_capacity; - if (m_array[index] == key) - return true; - if (m_array[index] == UNUSED) - return false; - } - return false; -} - -inline void QInt64Set::clear() -{ - Q_ASSERT_X(m_array, "QInt64Hash<T>::clear", "Hash set not allocated."); - for (int i = 0; i < m_capacity; ++i) - m_array[i] = UNUSED; - m_count = 0; -} - -//============================================================================// -// QRingBuffer // -//============================================================================// - -// T must be POD. -template <class T> -class QRingBuffer -{ -public: - inline QRingBuffer() : m_array(0), m_head(0), m_size(0), m_capacity(0) { } - inline ~QRingBuffer() {if (m_array) delete[] m_array;} - bool reallocate(int capacity); - inline const T &head() const {Q_ASSERT(m_size > 0); return m_array[m_head];} - inline const T &dequeue(); - inline void enqueue(const T &x); - inline bool isEmpty() const {return m_size == 0;} -private: - T *m_array; - int m_head; - int m_size; - int m_capacity; -}; - -template <class T> -bool QRingBuffer<T>::reallocate(int capacity) -{ - T *oldArray = m_array; - m_array = new T[capacity]; - if (m_array) { - if (oldArray) { - if (m_head + m_size > m_capacity) { - memcpy(m_array, oldArray + m_head, (m_capacity - m_head) * sizeof(T)); - memcpy(m_array + (m_capacity - m_head), oldArray, (m_head + m_size - m_capacity) * sizeof(T)); - } else { - memcpy(m_array, oldArray + m_head, m_size * sizeof(T)); - } - delete[] oldArray; - } - m_capacity = capacity; - m_head = 0; - return true; - } else { - m_array = oldArray; - return false; - } -} - -template <class T> -inline const T &QRingBuffer<T>::dequeue() -{ - Q_ASSERT(m_size > 0); - Q_ASSERT(m_array); - Q_ASSERT(m_capacity >= m_size); - int index = m_head; - if (++m_head >= m_capacity) - m_head -= m_capacity; - --m_size; - return m_array[index]; -} - -template <class T> -inline void QRingBuffer<T>::enqueue(const T &x) -{ - if (m_size == m_capacity) - reallocate(qMax(2 * m_capacity, 64)); - int index = m_head + m_size; - if (index >= m_capacity) - index -= m_capacity; - m_array[index] = x; - ++m_size; -} - -//============================================================================// -// QTriangulator // -//============================================================================// -template<typename T> -class QTriangulator -{ -public: - typedef QVarLengthArray<int, 6> ShortArray; - - //================================// - // QTriangulator::ComplexToSimple // - //================================// - friend class ComplexToSimple; - class ComplexToSimple - { - public: - inline ComplexToSimple(QTriangulator<T> *parent) : m_parent(parent), - m_edges(0), m_events(0), m_splits(0) { } - void decompose(); - private: - struct Edge - { - inline int &upper() {return pointingUp ? to : from;} - inline int &lower() {return pointingUp ? from : to;} - inline int upper() const {return pointingUp ? to : from;} - inline int lower() const {return pointingUp ? from : to;} - - QRBTree<int>::Node *node; - int from, to; // vertex - int next, previous; // edge - int winding; - bool mayIntersect; - bool pointingUp, originallyPointingUp; - }; - - friend class CompareEdges; - class CompareEdges - { - public: - inline CompareEdges(ComplexToSimple *parent) : m_parent(parent) { } - bool operator () (int i, int j) const; - private: - ComplexToSimple *m_parent; - }; - - struct Intersection - { - bool operator < (const Intersection &other) const {return other.intersectionPoint < intersectionPoint;} - - QIntersectionPoint intersectionPoint; - int vertex; - int leftEdge; - int rightEdge; - }; - - struct Split - { - int vertex; - int edge; - bool accurate; - }; - - struct Event - { - enum Type {Upper, Lower}; - inline bool operator < (const Event &other) const; - - QPodPoint point; - Type type; - int edge; - }; - -#ifdef Q_TRIANGULATOR_DEBUG - friend class DebugDialog; - friend class QTriangulator; - class DebugDialog : public QDialog - { - public: - DebugDialog(ComplexToSimple *parent, int currentVertex); - protected: - void paintEvent(QPaintEvent *); - void wheelEvent(QWheelEvent *); - void mouseMoveEvent(QMouseEvent *); - void mousePressEvent(QMouseEvent *); - private: - ComplexToSimple *m_parent; - QRectF m_window; - QPoint m_lastMousePos; - int m_vertex; - }; -#endif - - void initEdges(); - bool calculateIntersection(int left, int right); - bool edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const; - QRBTree<int>::Node *searchEdgeLeftOf(int edgeIndex) const; - QRBTree<int>::Node *searchEdgeLeftOf(int edgeIndex, QRBTree<int>::Node *after) const; - QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> bounds(const QPodPoint &point) const; - QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> outerBounds(const QPodPoint &point) const; - void splitEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost, int vertex, const QIntersectionPoint &intersectionPoint); - void reorderEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost); - void sortEdgeList(const QPodPoint eventPoint); - void fillPriorityQueue(); - void calculateIntersections(); - int splitEdge(int splitIndex); - bool splitEdgesAtIntersections(); - void insertEdgeIntoVectorIfWanted(ShortArray &orderedEdges, int i); - void removeUnwantedEdgesAndConnect(); - void removeUnusedPoints(); - - QTriangulator *m_parent; - QDataBuffer<Edge> m_edges; - QRBTree<int> m_edgeList; - QDataBuffer<Event> m_events; - QDataBuffer<Split> m_splits; - QMaxHeap<Intersection> m_topIntersection; - QInt64Set m_processedEdgePairs; - int m_initialPointCount; - }; -#ifdef Q_TRIANGULATOR_DEBUG - friend class ComplexToSimple::DebugDialog; -#endif - - //=================================// - // QTriangulator::SimpleToMonotone // - //=================================// - friend class SimpleToMonotone; - class SimpleToMonotone - { - public: - inline SimpleToMonotone(QTriangulator<T> *parent) : m_parent(parent), m_edges(0), m_upperVertex(0) { } - void decompose(); - private: - enum VertexType {MergeVertex, EndVertex, RegularVertex, StartVertex, SplitVertex}; - - struct Edge - { - QRBTree<int>::Node *node; - int helper, twin, next, previous; - T from, to; - VertexType type; - bool pointingUp; - int upper() const {return (pointingUp ? to : from);} - int lower() const {return (pointingUp ? from : to);} - }; - - friend class CompareVertices; - class CompareVertices - { - public: - CompareVertices(SimpleToMonotone *parent) : m_parent(parent) { } - bool operator () (int i, int j) const; - private: - SimpleToMonotone *m_parent; - }; - - void setupDataStructures(); - void removeZeroLengthEdges(); - void fillPriorityQueue(); - bool edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const; - // Returns the rightmost edge not to the right of the given edge. - QRBTree<int>::Node *searchEdgeLeftOfEdge(int edgeIndex) const; - // Returns the rightmost edge left of the given point. - QRBTree<int>::Node *searchEdgeLeftOfPoint(int pointIndex) const; - void classifyVertex(int i); - void classifyVertices(); - bool pointIsInSector(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2, const QPodPoint &v3); - bool pointIsInSector(int vertex, int sector); - int findSector(int edge, int vertex); - void createDiagonal(int lower, int upper); - void monotoneDecomposition(); - - QTriangulator *m_parent; - QRBTree<int> m_edgeList; - QDataBuffer<Edge> m_edges; - QDataBuffer<int> m_upperVertex; - bool m_clockwiseOrder; - }; - - //====================================// - // QTriangulator::MonotoneToTriangles // - //====================================// - friend class MonotoneToTriangles; - class MonotoneToTriangles - { - public: - inline MonotoneToTriangles(QTriangulator<T> *parent) : m_parent(parent) { } - void decompose(); - private: - inline T indices(int index) const {return m_parent->m_indices.at(index + m_first);} - inline int next(int index) const {return (index + 1) % m_length;} - inline int previous(int index) const {return (index + m_length - 1) % m_length;} - inline bool less(int i, int j) const {return m_parent->m_vertices.at((qint32)indices(i)) < m_parent->m_vertices.at(indices(j));} - inline bool leftOfEdge(int i, int j, int k) const - { - return qPointIsLeftOfLine(m_parent->m_vertices.at((qint32)indices(i)), - m_parent->m_vertices.at((qint32)indices(j)), m_parent->m_vertices.at((qint32)indices(k))); - } - - QTriangulator<T> *m_parent; - int m_first; - int m_length; - }; - - inline QTriangulator() : m_vertices(0) { } - - // Call this only once. - void initialize(const qreal *polygon, int count, uint hint, const QTransform &matrix); - // Call this only once. - void initialize(const QVectorPath &path, const QTransform &matrix, qreal lod); - // Call this only once. - void initialize(const QPainterPath &path, const QTransform &matrix, qreal lod); - // Call either triangulate() or polyline() only once. - QVertexSet<T> triangulate(); - QVertexSet<T> polyline(); -private: - QDataBuffer<QPodPoint> m_vertices; - QVector<T> m_indices; - uint m_hint; -}; - -//============================================================================// -// QTriangulator // -//============================================================================// - -template <typename T> -QVertexSet<T> QTriangulator<T>::triangulate() -{ - for (int i = 0; i < m_vertices.size(); ++i) { - Q_ASSERT(qAbs(m_vertices.at(i).x) < (1 << 21)); - Q_ASSERT(qAbs(m_vertices.at(i).y) < (1 << 21)); - } - - if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill))) - m_hint |= QVectorPath::OddEvenFill; - - if (m_hint & QVectorPath::NonConvexShapeMask) { - ComplexToSimple c2s(this); - c2s.decompose(); - SimpleToMonotone s2m(this); - s2m.decompose(); - } - MonotoneToTriangles m2t(this); - m2t.decompose(); - - QVertexSet<T> result; - result.indices = m_indices; - result.vertices.resize(2 * m_vertices.size()); - for (int i = 0; i < m_vertices.size(); ++i) { - result.vertices[2 * i + 0] = qreal(m_vertices.at(i).x) / Q_FIXED_POINT_SCALE; - result.vertices[2 * i + 1] = qreal(m_vertices.at(i).y) / Q_FIXED_POINT_SCALE; - } - return result; -} - -template <typename T> -QVertexSet<T> QTriangulator<T>::polyline() -{ - for (int i = 0; i < m_vertices.size(); ++i) { - Q_ASSERT(qAbs(m_vertices.at(i).x) < (1 << 21)); - Q_ASSERT(qAbs(m_vertices.at(i).y) < (1 << 21)); - } - - if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill))) - m_hint |= QVectorPath::OddEvenFill; - - if (m_hint & QVectorPath::NonConvexShapeMask) { - ComplexToSimple c2s(this); - c2s.decompose(); - } - - QVertexSet<T> result; - result.indices = m_indices; - result.vertices.resize(2 * m_vertices.size()); - for (int i = 0; i < m_vertices.size(); ++i) { - result.vertices[2 * i + 0] = qreal(m_vertices.at(i).x) / Q_FIXED_POINT_SCALE; - result.vertices[2 * i + 1] = qreal(m_vertices.at(i).y) / Q_FIXED_POINT_SCALE; - } - return result; -} - -template <typename T> -void QTriangulator<T>::initialize(const qreal *polygon, int count, uint hint, const QTransform &matrix) -{ - m_hint = hint; - m_vertices.resize(count); - m_indices.resize(count + 1); - for (int i = 0; i < count; ++i) { - qreal x, y; - matrix.map(polygon[2 * i + 0], polygon[2 * i + 1], &x, &y); - m_vertices.at(i).x = qRound(x * Q_FIXED_POINT_SCALE); - m_vertices.at(i).y = qRound(y * Q_FIXED_POINT_SCALE); - m_indices[i] = i; - } - m_indices[count] = T(-1); //Q_TRIANGULATE_END_OF_POLYGON -} - -template <typename T> -void QTriangulator<T>::initialize(const QVectorPath &path, const QTransform &matrix, qreal lod) -{ - m_hint = path.hints(); - // Curved paths will be converted to complex polygons. - m_hint &= ~QVectorPath::CurvedShapeMask; - - const qreal *p = path.points(); - const QPainterPath::ElementType *e = path.elements(); - if (e) { - for (int i = 0; i < path.elementCount(); ++i, ++e, p += 2) { - switch (*e) { - case QPainterPath::MoveToElement: - if (!m_indices.isEmpty()) - m_indices.push_back(T(-1)); // Q_TRIANGULATE_END_OF_POLYGON - // Fall through. - case QPainterPath::LineToElement: - m_indices.push_back(T(m_vertices.size())); - m_vertices.resize(m_vertices.size() + 1); - qreal x, y; - matrix.map(p[0], p[1], &x, &y); - m_vertices.last().x = qRound(x * Q_FIXED_POINT_SCALE); - m_vertices.last().y = qRound(y * Q_FIXED_POINT_SCALE); - break; - case QPainterPath::CurveToElement: - { - qreal pts[8]; - for (int i = 0; i < 4; ++i) - matrix.map(p[2 * i - 2], p[2 * i - 1], &pts[2 * i + 0], &pts[2 * i + 1]); - for (int i = 0; i < 8; ++i) - pts[i] *= lod; - QBezier bezier = QBezier::fromPoints(QPointF(pts[0], pts[1]), QPointF(pts[2], pts[3]), QPointF(pts[4], pts[5]), QPointF(pts[6], pts[7])); - QPolygonF poly = bezier.toPolygon(); - // Skip first point, it already exists in 'm_vertices'. - for (int j = 1; j < poly.size(); ++j) { - m_indices.push_back(T(m_vertices.size())); - m_vertices.resize(m_vertices.size() + 1); - m_vertices.last().x = qRound(poly.at(j).x() * Q_FIXED_POINT_SCALE / lod); - m_vertices.last().y = qRound(poly.at(j).y() * Q_FIXED_POINT_SCALE / lod); - } - } - i += 2; - e += 2; - p += 4; - break; - default: - Q_ASSERT_X(0, "QTriangulator::triangulate", "Unexpected element type."); - break; - } - } - } else { - for (int i = 0; i < path.elementCount(); ++i, p += 2) { - m_indices.push_back(T(m_vertices.size())); - m_vertices.resize(m_vertices.size() + 1); - qreal x, y; - matrix.map(p[0], p[1], &x, &y); - m_vertices.last().x = qRound(x * Q_FIXED_POINT_SCALE); - m_vertices.last().y = qRound(y * Q_FIXED_POINT_SCALE); - } - } - m_indices.push_back(T(-1)); // Q_TRIANGULATE_END_OF_POLYGON -} - -template <typename T> -void QTriangulator<T>::initialize(const QPainterPath &path, const QTransform &matrix, qreal lod) -{ - initialize(qtVectorPathForPath(path), matrix, lod); -} - -//============================================================================// -// QTriangulator::ComplexToSimple // -//============================================================================// -template <typename T> -void QTriangulator<T>::ComplexToSimple::decompose() -{ - m_initialPointCount = m_parent->m_vertices.size(); - initEdges(); - do { - calculateIntersections(); - } while (splitEdgesAtIntersections()); - - removeUnwantedEdgesAndConnect(); - removeUnusedPoints(); - - m_parent->m_indices.clear(); - QBitArray processed(m_edges.size(), false); - for (int first = 0; first < m_edges.size(); ++first) { - // If already processed, or if unused path, skip. - if (processed.at(first) || m_edges.at(first).next == -1) - continue; - - int i = first; - do { - Q_ASSERT(!processed.at(i)); - Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i); - m_parent->m_indices.push_back(m_edges.at(i).from); - processed.setBit(i); - i = m_edges.at(i).next; // CCW order - } while (i != first); - m_parent->m_indices.push_back(T(-1)); // Q_TRIANGULATE_END_OF_POLYGON - } -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::initEdges() -{ - // Initialize edge structure. - // 'next' and 'previous' are not being initialized at this point. - int first = 0; - for (int i = 0; i < m_parent->m_indices.size(); ++i) { - if (m_parent->m_indices.at(i) == T(-1)) { // Q_TRIANGULATE_END_OF_POLYGON - if (m_edges.size() != first) - m_edges.last().to = m_edges.at(first).from; - first = m_edges.size(); - } else { - Q_ASSERT(i + 1 < m_parent->m_indices.size()); - // {node, from, to, next, previous, winding, mayIntersect, pointingUp, originallyPointingUp} - Edge edge = {0, m_parent->m_indices.at(i), m_parent->m_indices.at(i + 1), -1, -1, 0, true, false, false}; - m_edges.add(edge); - } - } - if (first != m_edges.size()) - m_edges.last().to = m_edges.at(first).from; - for (int i = 0; i < m_edges.size(); ++i) { - m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp = - m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from); - } -} - -// Return true if new intersection was found -template <typename T> -bool QTriangulator<T>::ComplexToSimple::calculateIntersection(int left, int right) -{ - const Edge &e1 = m_edges.at(left); - const Edge &e2 = m_edges.at(right); - - const QPodPoint &u1 = m_parent->m_vertices.at((qint32)e1.from); - const QPodPoint &u2 = m_parent->m_vertices.at((qint32)e1.to); - const QPodPoint &v1 = m_parent->m_vertices.at((qint32)e2.from); - const QPodPoint &v2 = m_parent->m_vertices.at((qint32)e2.to); - if (qMax(u1.x, u2.x) <= qMin(v1.x, v2.x)) - return false; - - quint64 key = (left > right ? (quint64(right) << 32) | quint64(left) : (quint64(left) << 32) | quint64(right)); - if (m_processedEdgePairs.contains(key)) - return false; - m_processedEdgePairs.insert(key); - - Intersection intersection; - intersection.leftEdge = left; - intersection.rightEdge = right; - intersection.intersectionPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(u1, u2, v1, v2); - - if (!intersection.intersectionPoint.isValid()) - return false; - - Q_ASSERT(intersection.intersectionPoint.isOnLine(u1, u2)); - Q_ASSERT(intersection.intersectionPoint.isOnLine(v1, v2)); - - intersection.vertex = m_parent->m_vertices.size(); - m_topIntersection.push(intersection); - m_parent->m_vertices.add(intersection.intersectionPoint.round()); - return true; -} - -template <typename T> -bool QTriangulator<T>::ComplexToSimple::edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const -{ - const Edge &leftEdge = m_edges.at(leftEdgeIndex); - const Edge &rightEdge = m_edges.at(rightEdgeIndex); - const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper()); - const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower()); - const QPodPoint &upper = m_parent->m_vertices.at(leftEdge.upper()); - if (upper.x < qMin(l.x, u.x)) - return true; - if (upper.x > qMax(l.x, u.x)) - return false; - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(upper, l, u); - // d < 0: left, d > 0: right, d == 0: on top - if (d == 0) - d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u); - return d < 0; -} - -template <typename T> -QRBTree<int>::Node *QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edgeIndex) const -{ - QRBTree<int>::Node *current = m_edgeList.root; - QRBTree<int>::Node *result = 0; - while (current) { - if (edgeIsLeftOfEdge(edgeIndex, current->data)) { - current = current->left; - } else { - result = current; - current = current->right; - } - } - return result; -} - -template <typename T> -QRBTree<int>::Node *QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edgeIndex, QRBTree<int>::Node *after) const -{ - if (!m_edgeList.root) - return after; - QRBTree<int>::Node *result = after; - QRBTree<int>::Node *current = (after ? m_edgeList.next(after) : m_edgeList.front(m_edgeList.root)); - while (current) { - if (edgeIsLeftOfEdge(edgeIndex, current->data)) - return result; - result = current; - current = m_edgeList.next(current); - } - return result; -} - -template <typename T> -QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> QTriangulator<T>::ComplexToSimple::bounds(const QPodPoint &point) const -{ - QRBTree<int>::Node *current = m_edgeList.root; - QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> result(0, 0); - while (current) { - const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); - const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2); - if (d == 0) { - result.first = result.second = current; - break; - } - current = (d < 0 ? current->left : current->right); - } - if (current == 0) - return result; - - current = result.first->left; - while (current) { - const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); - const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2); - Q_ASSERT(d >= 0); - if (d == 0) { - result.first = current; - current = current->left; - } else { - current = current->right; - } - } - - current = result.second->right; - while (current) { - const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); - const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2); - Q_ASSERT(d <= 0); - if (d == 0) { - result.second = current; - current = current->right; - } else { - current = current->left; - } - } - - return result; -} - -template <typename T> -QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> QTriangulator<T>::ComplexToSimple::outerBounds(const QPodPoint &point) const -{ - QRBTree<int>::Node *current = m_edgeList.root; - QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> result(0, 0); - - while (current) { - const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); - const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2); - if (d == 0) - break; - if (d < 0) { - result.second = current; - current = current->left; - } else { - result.first = current; - current = current->right; - } - } - - if (!current) - return result; - - QRBTree<int>::Node *mid = current; - - current = mid->left; - while (current) { - const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); - const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2); - Q_ASSERT(d >= 0); - if (d == 0) { - current = current->left; - } else { - result.first = current; - current = current->right; - } - } - - current = mid->right; - while (current) { - const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); - const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2); - Q_ASSERT(d <= 0); - if (d == 0) { - current = current->right; - } else { - result.second = current; - current = current->left; - } - } - - return result; -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::splitEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost, int vertex, const QIntersectionPoint &intersectionPoint) -{ - Q_ASSERT(leftmost && rightmost); - - // Split. - for (;;) { - const QPodPoint &u = m_parent->m_vertices.at(m_edges.at(leftmost->data).from); - const QPodPoint &v = m_parent->m_vertices.at(m_edges.at(leftmost->data).to); - Q_ASSERT(intersectionPoint.isOnLine(u, v)); - const Split split = {vertex, leftmost->data, intersectionPoint.isAccurate()}; - if (intersectionPoint.xOffset.numerator != 0 || intersectionPoint.yOffset.numerator != 0 || (intersectionPoint.upperLeft != u && intersectionPoint.upperLeft != v)) - m_splits.add(split); - if (leftmost == rightmost) - break; - leftmost = m_edgeList.next(leftmost); - } -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::reorderEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost) -{ - Q_ASSERT(leftmost && rightmost); - - QRBTree<int>::Node *storeLeftmost = leftmost; - QRBTree<int>::Node *storeRightmost = rightmost; - - // Reorder. - while (leftmost != rightmost) { - Edge &left = m_edges.at(leftmost->data); - Edge &right = m_edges.at(rightmost->data); - qSwap(left.node, right.node); - qSwap(leftmost->data, rightmost->data); - leftmost = m_edgeList.next(leftmost); - if (leftmost == rightmost) - break; - rightmost = m_edgeList.previous(rightmost); - } - - rightmost = m_edgeList.next(storeRightmost); - leftmost = m_edgeList.previous(storeLeftmost); - if (leftmost) - calculateIntersection(leftmost->data, storeLeftmost->data); - if (rightmost) - calculateIntersection(storeRightmost->data, rightmost->data); -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::sortEdgeList(const QPodPoint eventPoint) -{ - QIntersectionPoint eventPoint2 = QT_PREPEND_NAMESPACE(qIntersectionPoint)(eventPoint); - while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint < eventPoint2) { - Intersection intersection = m_topIntersection.pop(); - - QIntersectionPoint currentIntersectionPoint = intersection.intersectionPoint; - int currentVertex = intersection.vertex; - - QRBTree<int>::Node *leftmost = m_edges.at(intersection.leftEdge).node; - QRBTree<int>::Node *rightmost = m_edges.at(intersection.rightEdge).node; - - for (;;) { - QRBTree<int>::Node *previous = m_edgeList.previous(leftmost); - if (!previous) - break; - const Edge &edge = m_edges.at(previous->data); - const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from); - const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to); - if (!currentIntersectionPoint.isOnLine(u, v)) { - Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0); - break; - } - leftmost = previous; - } - - for (;;) { - QRBTree<int>::Node *next = m_edgeList.next(rightmost); - if (!next) - break; - const Edge &edge = m_edges.at(next->data); - const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from); - const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to); - if (!currentIntersectionPoint.isOnLine(u, v)) { - Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0); - break; - } - rightmost = next; - } - - Q_ASSERT(leftmost && rightmost); - splitEdgeListRange(leftmost, rightmost, currentVertex, currentIntersectionPoint); - reorderEdgeListRange(leftmost, rightmost); - - while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= currentIntersectionPoint) - m_topIntersection.pop(); - -#ifdef Q_TRIANGULATOR_DEBUG - DebugDialog dialog(this, intersection.vertex); - dialog.exec(); -#endif - - } -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::fillPriorityQueue() -{ - m_events.reset(); - m_events.reserve(m_edges.size() * 2); - for (int i = 0; i < m_edges.size(); ++i) { - Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1); - Q_ASSERT(m_edges.at(i).node == 0); - Q_ASSERT(m_edges.at(i).pointingUp == m_edges.at(i).originallyPointingUp); - Q_ASSERT(m_edges.at(i).pointingUp == (m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from))); - // Ignore zero-length edges. - if (m_parent->m_vertices.at(m_edges.at(i).to) != m_parent->m_vertices.at(m_edges.at(i).from)) { - QPodPoint upper = m_parent->m_vertices.at(m_edges.at(i).upper()); - QPodPoint lower = m_parent->m_vertices.at(m_edges.at(i).lower()); - Event upperEvent = {{upper.x, upper.y}, Event::Upper, i}; - Event lowerEvent = {{lower.x, lower.y}, Event::Lower, i}; - m_events.add(upperEvent); - m_events.add(lowerEvent); - } - } - //qSort(m_events.data(), m_events.data() + m_events.size()); - sort(m_events.data(), m_events.size()); -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::calculateIntersections() -{ - fillPriorityQueue(); - - Q_ASSERT(m_topIntersection.empty()); - Q_ASSERT(m_edgeList.root == 0); - - // Find all intersection points. - while (!m_events.isEmpty()) { - Event event = m_events.last(); - sortEdgeList(event.point); - - // Find all edges in the edge list that contain the current vertex and mark them to be split later. - QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> range = bounds(event.point); - QRBTree<int>::Node *leftNode = range.first ? m_edgeList.previous(range.first) : 0; - int vertex = (event.type == Event::Upper ? m_edges.at(event.edge).upper() : m_edges.at(event.edge).lower()); - QIntersectionPoint eventPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(event.point); - - if (range.first != 0) { - splitEdgeListRange(range.first, range.second, vertex, eventPoint); - reorderEdgeListRange(range.first, range.second); - } - - // Handle the edges with start or end point in the current vertex. - while (!m_events.isEmpty() && m_events.last().point == event.point) { - event = m_events.last(); - m_events.pop_back(); - int i = event.edge; - - if (m_edges.at(i).node) { - // Remove edge from edge list. - Q_ASSERT(event.type == Event::Lower); - QRBTree<int>::Node *left = m_edgeList.previous(m_edges.at(i).node); - QRBTree<int>::Node *right = m_edgeList.next(m_edges.at(i).node); - m_edgeList.deleteNode(m_edges.at(i).node); - if (!left || !right) - continue; - calculateIntersection(left->data, right->data); - } else { - // Insert edge into edge list. - Q_ASSERT(event.type == Event::Upper); - QRBTree<int>::Node *left = searchEdgeLeftOf(i, leftNode); - m_edgeList.attachAfter(left, m_edges.at(i).node = m_edgeList.newNode()); - m_edges.at(i).node->data = i; - QRBTree<int>::Node *right = m_edgeList.next(m_edges.at(i).node); - if (left) - calculateIntersection(left->data, i); - if (right) - calculateIntersection(i, right->data); - } - } - while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= eventPoint) - m_topIntersection.pop(); -#ifdef Q_TRIANGULATOR_DEBUG - DebugDialog dialog(this, vertex); - dialog.exec(); -#endif - } - m_processedEdgePairs.clear(); -} - -// Split an edge into two pieces at the given point. -// The upper piece is pushed to the end of the 'm_edges' vector. -// The lower piece replaces the old edge. -// Return the edge whose 'from' is 'pointIndex'. -template <typename T> -int QTriangulator<T>::ComplexToSimple::splitEdge(int splitIndex) -{ - const Split &split = m_splits.at(splitIndex); - Edge &lowerEdge = m_edges.at(split.edge); - Q_ASSERT(lowerEdge.node == 0); - Q_ASSERT(lowerEdge.previous == -1 && lowerEdge.next == -1); - - if (lowerEdge.from == split.vertex) - return split.edge; - if (lowerEdge.to == split.vertex) - return lowerEdge.next; - - // Check that angle >= 90 degrees. - //Q_ASSERT(qDot(m_points.at(m_edges.at(edgeIndex).from) - m_points.at(pointIndex), - // m_points.at(m_edges.at(edgeIndex).to) - m_points.at(pointIndex)) <= 0); - - Edge upperEdge = lowerEdge; - upperEdge.mayIntersect |= !split.accurate; // The edge may have been split before at an inaccurate split point. - lowerEdge.mayIntersect = !split.accurate; - if (lowerEdge.pointingUp) { - lowerEdge.to = upperEdge.from = split.vertex; - m_edges.add(upperEdge); - return m_edges.size() - 1; - } else { - lowerEdge.from = upperEdge.to = split.vertex; - m_edges.add(upperEdge); - return split.edge; - } -} - -template <typename T> -bool QTriangulator<T>::ComplexToSimple::splitEdgesAtIntersections() -{ - for (int i = 0; i < m_edges.size(); ++i) - m_edges.at(i).mayIntersect = false; - bool checkForNewIntersections = false; - for (int i = 0; i < m_splits.size(); ++i) { - splitEdge(i); - checkForNewIntersections |= !m_splits.at(i).accurate; - } - for (int i = 0; i < m_edges.size(); ++i) { - m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp = - m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from); - } - m_splits.reset(); - return checkForNewIntersections; -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::insertEdgeIntoVectorIfWanted(ShortArray &orderedEdges, int i) -{ - // Edges with zero length should not reach this part. - Q_ASSERT(m_parent->m_vertices.at(m_edges.at(i).from) != m_parent->m_vertices.at(m_edges.at(i).to)); - - // Skip edges with unwanted winding number. - int windingNumber = m_edges.at(i).winding; - if (m_edges.at(i).originallyPointingUp) - ++windingNumber; - - // Make sure exactly one fill rule is specified. - Q_ASSERT(((m_parent->m_hint & QVectorPath::WindingFill) != 0) != ((m_parent->m_hint & QVectorPath::OddEvenFill) != 0)); - - if ((m_parent->m_hint & QVectorPath::WindingFill) && windingNumber != 0 && windingNumber != 1) - return; - - // Skip cancelling edges. - if (!orderedEdges.isEmpty()) { - int j = orderedEdges[orderedEdges.size() - 1]; - // If the last edge is already connected in one end, it should not be cancelled. - if (m_edges.at(j).next == -1 && m_edges.at(j).previous == -1 - && (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(j).to)) - && (m_parent->m_vertices.at(m_edges.at(i).to) == m_parent->m_vertices.at(m_edges.at(j).from))) { - orderedEdges.removeLast(); - return; - } - } - orderedEdges.append(i); -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::removeUnwantedEdgesAndConnect() -{ - Q_ASSERT(m_edgeList.root == 0); - // Initialize priority queue. - fillPriorityQueue(); - - ShortArray orderedEdges; - - while (!m_events.isEmpty()) { - Event event = m_events.last(); - int edgeIndex = event.edge; - - // Check that all the edges in the list crosses the current scanline - //if (m_edgeList.root) { - // for (QRBTree<int>::Node *node = m_edgeList.front(m_edgeList.root); node; node = m_edgeList.next(node)) { - // Q_ASSERT(event.point <= m_points.at(m_edges.at(node->data).lower())); - // } - //} - - orderedEdges.clear(); - QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> b = outerBounds(event.point); - if (m_edgeList.root) { - QRBTree<int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root)); - // Process edges that are going to be removed from the edge list at the current event point. - while (current != b.second) { - Q_ASSERT(current); - Q_ASSERT(m_edges.at(current->data).node == current); - Q_ASSERT(QT_PREPEND_NAMESPACE(qIntersectionPoint)(event.point).isOnLine(m_parent->m_vertices.at(m_edges.at(current->data).from), m_parent->m_vertices.at(m_edges.at(current->data).to))); - Q_ASSERT(m_parent->m_vertices.at(m_edges.at(current->data).from) == event.point || m_parent->m_vertices.at(m_edges.at(current->data).to) == event.point); - insertEdgeIntoVectorIfWanted(orderedEdges, current->data); - current = m_edgeList.next(current); - } - } - - // Remove edges above the event point, insert edges below the event point. - do { - event = m_events.last(); - m_events.pop_back(); - edgeIndex = event.edge; - - // Edges with zero length should not reach this part. - Q_ASSERT(m_parent->m_vertices.at(m_edges.at(edgeIndex).from) != m_parent->m_vertices.at(m_edges.at(edgeIndex).to)); - - if (m_edges.at(edgeIndex).node) { - Q_ASSERT(event.type == Event::Lower); - Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).lower())); - m_edgeList.deleteNode(m_edges.at(edgeIndex).node); - } else { - Q_ASSERT(event.type == Event::Upper); - Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).upper())); - QRBTree<int>::Node *left = searchEdgeLeftOf(edgeIndex, b.first); - m_edgeList.attachAfter(left, m_edges.at(edgeIndex).node = m_edgeList.newNode()); - m_edges.at(edgeIndex).node->data = edgeIndex; - } - } while (!m_events.isEmpty() && m_events.last().point == event.point); - - if (m_edgeList.root) { - QRBTree<int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root)); - - // Calculate winding number and turn counter-clockwise. - int currentWindingNumber = (b.first ? m_edges.at(b.first->data).winding : 0); - while (current != b.second) { - Q_ASSERT(current); - //Q_ASSERT(b.second == 0 || m_edgeList.order(current, b.second) < 0); - int i = current->data; - Q_ASSERT(m_edges.at(i).node == current); - - // Winding number. - int ccwWindingNumber = m_edges.at(i).winding = currentWindingNumber; - if (m_edges.at(i).originallyPointingUp) { - --m_edges.at(i).winding; - } else { - ++m_edges.at(i).winding; - ++ccwWindingNumber; - } - currentWindingNumber = m_edges.at(i).winding; - - // Turn counter-clockwise. - if ((ccwWindingNumber & 1) == 0) { - Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1); - qSwap(m_edges.at(i).from, m_edges.at(i).to); - m_edges.at(i).pointingUp = !m_edges.at(i).pointingUp; - } - - current = m_edgeList.next(current); - } - - // Process edges that were inserted into the edge list at the current event point. - current = (b.second ? m_edgeList.previous(b.second) : m_edgeList.back(m_edgeList.root)); - while (current != b.first) { - Q_ASSERT(current); - Q_ASSERT(m_edges.at(current->data).node == current); - insertEdgeIntoVectorIfWanted(orderedEdges, current->data); - current = m_edgeList.previous(current); - } - } - if (orderedEdges.isEmpty()) - continue; - - Q_ASSERT((orderedEdges.size() & 1) == 0); - - // Connect edges. - // First make sure the first edge point towards the current point. - int i; - if (m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).from) == event.point) { - i = 1; - int copy = orderedEdges[0]; // Make copy in case the append() will cause a reallocation. - orderedEdges.append(copy); - } else { - Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).to) == event.point); - i = 0; - } - - // Remove references to duplicate points. First find the point with lowest index. - int pointIndex = INT_MAX; - for (int j = i; j < orderedEdges.size(); j += 2) { - Q_ASSERT(j + 1 < orderedEdges.size()); - Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j]).to) == event.point); - Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j + 1]).from) == event.point); - if (m_edges.at(orderedEdges[j]).to < pointIndex) - pointIndex = m_edges.at(orderedEdges[j]).to; - if (m_edges.at(orderedEdges[j + 1]).from < pointIndex) - pointIndex = m_edges.at(orderedEdges[j + 1]).from; - } - - for (; i < orderedEdges.size(); i += 2) { - // Remove references to duplicate points by making all edges reference one common point. - m_edges.at(orderedEdges[i]).to = m_edges.at(orderedEdges[i + 1]).from = pointIndex; - - Q_ASSERT(m_edges.at(orderedEdges[i]).pointingUp || m_edges.at(orderedEdges[i]).previous != -1); - Q_ASSERT(!m_edges.at(orderedEdges[i + 1]).pointingUp || m_edges.at(orderedEdges[i + 1]).next != -1); - - m_edges.at(orderedEdges[i]).next = orderedEdges[i + 1]; - m_edges.at(orderedEdges[i + 1]).previous = orderedEdges[i]; - } - } // end while -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::removeUnusedPoints() { - QBitArray used(m_parent->m_vertices.size(), false); - for (int i = 0; i < m_edges.size(); ++i) { - Q_ASSERT((m_edges.at(i).previous == -1) == (m_edges.at(i).next == -1)); - if (m_edges.at(i).next != -1) - used.setBit(m_edges.at(i).from); - } - QDataBuffer<quint32> newMapping(m_parent->m_vertices.size()); - newMapping.resize(m_parent->m_vertices.size()); - int count = 0; - for (int i = 0; i < m_parent->m_vertices.size(); ++i) { - if (used.at(i)) { - m_parent->m_vertices.at(count) = m_parent->m_vertices.at(i); - newMapping.at(i) = count; - ++count; - } - } - m_parent->m_vertices.resize(count); - for (int i = 0; i < m_edges.size(); ++i) { - m_edges.at(i).from = newMapping.at(m_edges.at(i).from); - m_edges.at(i).to = newMapping.at(m_edges.at(i).to); - } -} - -template <typename T> -bool QTriangulator<T>::ComplexToSimple::CompareEdges::operator () (int i, int j) const -{ - int cmp = comparePoints(m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).from), - m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).from)); - if (cmp == 0) { - cmp = comparePoints(m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).to), - m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).to)); - } - return cmp > 0; -} - -template <typename T> -inline bool QTriangulator<T>::ComplexToSimple::Event::operator < (const Event &other) const -{ - if (point == other.point) - return type < other.type; // 'Lower' has higher priority than 'Upper'. - return other.point < point; -} - -//============================================================================// -// QTriangulator::ComplexToSimple::DebugDialog // -//============================================================================// - -#ifdef Q_TRIANGULATOR_DEBUG -template <typename T> -QTriangulator<T>::ComplexToSimple::DebugDialog::DebugDialog(ComplexToSimple *parent, int currentVertex) - : m_parent(parent), m_vertex(currentVertex) -{ - QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices; - if (vertices.isEmpty()) - return; - - int minX, maxX, minY, maxY; - minX = maxX = vertices.at(0).x; - minY = maxY = vertices.at(0).y; - for (int i = 1; i < vertices.size(); ++i) { - minX = qMin(minX, vertices.at(i).x); - maxX = qMax(maxX, vertices.at(i).x); - minY = qMin(minY, vertices.at(i).y); - maxY = qMax(maxY, vertices.at(i).y); - } - int w = maxX - minX; - int h = maxY - minY; - qreal border = qMin(w, h) / 10.0; - m_window = QRectF(minX - border, minY - border, (maxX - minX + 2 * border), (maxY - minY + 2 * border)); -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::DebugDialog::paintEvent(QPaintEvent *) -{ - QPainter p(this); - p.setRenderHint(QPainter::Antialiasing, true); - p.fillRect(rect(), Qt::black); - QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices; - if (vertices.isEmpty()) - return; - - qreal halfPointSize = qMin(m_window.width(), m_window.height()) / 300.0; - p.setWindow(m_window.toRect()); - - p.setPen(Qt::white); - - QDataBuffer<Edge> &edges = m_parent->m_edges; - for (int i = 0; i < edges.size(); ++i) { - QPodPoint u = vertices.at(edges.at(i).from); - QPodPoint v = vertices.at(edges.at(i).to); - p.drawLine(u.x, u.y, v.x, v.y); - } - - for (int i = 0; i < vertices.size(); ++i) { - QPodPoint q = vertices.at(i); - p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::red); - } - - Qt::GlobalColor colors[6] = {Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta, Qt::yellow}; - p.setOpacity(0.5); - int count = 0; - if (m_parent->m_edgeList.root) { - QRBTree<int>::Node *current = m_parent->m_edgeList.front(m_parent->m_edgeList.root); - while (current) { - p.setPen(colors[count++ % 6]); - QPodPoint u = vertices.at(edges.at(current->data).from); - QPodPoint v = vertices.at(edges.at(current->data).to); - p.drawLine(u.x, u.y, v.x, v.y); - current = m_parent->m_edgeList.next(current); - } - } - - p.setOpacity(1.0); - QPodPoint q = vertices.at(m_vertex); - p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::green); - - p.setPen(Qt::gray); - QDataBuffer<Split> &splits = m_parent->m_splits; - for (int i = 0; i < splits.size(); ++i) { - QPodPoint q = vertices.at(splits.at(i).vertex); - QPodPoint u = vertices.at(edges.at(splits.at(i).edge).from) - q; - QPodPoint v = vertices.at(edges.at(splits.at(i).edge).to) - q; - qreal uLen = sqrt(qreal(qDot(u, u))); - qreal vLen = sqrt(qreal(qDot(v, v))); - if (uLen) { - u.x *= 2 * halfPointSize / uLen; - u.y *= 2 * halfPointSize / uLen; - } - if (vLen) { - v.x *= 2 * halfPointSize / vLen; - v.y *= 2 * halfPointSize / vLen; - } - u += q; - v += q; - p.drawLine(u.x, u.y, v.x, v.y); - } -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::DebugDialog::wheelEvent(QWheelEvent *event) -{ - qreal scale = exp(-0.001 * event->delta()); - QPointF center = m_window.center(); - QPointF delta = scale * (m_window.bottomRight() - center); - m_window = QRectF(center - delta, center + delta); - event->accept(); - update(); -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::DebugDialog::mouseMoveEvent(QMouseEvent *event) -{ - if (event->buttons() & Qt::LeftButton) { - QPointF delta = event->pos() - m_lastMousePos; - delta.setX(delta.x() * m_window.width() / width()); - delta.setY(delta.y() * m_window.height() / height()); - m_window.translate(-delta.x(), -delta.y()); - m_lastMousePos = event->pos(); - event->accept(); - update(); - } -} - -template <typename T> -void QTriangulator<T>::ComplexToSimple::DebugDialog::mousePressEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) - m_lastMousePos = event->pos(); - event->accept(); -} - - -#endif - -//============================================================================// -// QTriangulator::SimpleToMonotone // -//============================================================================// -template <typename T> -void QTriangulator<T>::SimpleToMonotone::decompose() -{ - setupDataStructures(); - removeZeroLengthEdges(); - monotoneDecomposition(); - - m_parent->m_indices.clear(); - QBitArray processed(m_edges.size(), false); - for (int first = 0; first < m_edges.size(); ++first) { - if (processed.at(first)) - continue; - int i = first; - do { - Q_ASSERT(!processed.at(i)); - Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i); - m_parent->m_indices.push_back(m_edges.at(i).from); - processed.setBit(i); - i = m_edges.at(i).next; - } while (i != first); - if (m_parent->m_indices.size() > 0 && m_parent->m_indices.back() != T(-1)) // Q_TRIANGULATE_END_OF_POLYGON - m_parent->m_indices.push_back(T(-1)); // Q_TRIANGULATE_END_OF_POLYGON - } -} - -template <typename T> -void QTriangulator<T>::SimpleToMonotone::setupDataStructures() -{ - int i = 0; - Edge e; - e.node = 0; - e.twin = -1; - - while (i + 3 <= m_parent->m_indices.size()) { - int start = m_edges.size(); - - do { - e.from = m_parent->m_indices.at(i); - e.type = RegularVertex; - e.next = m_edges.size() + 1; - e.previous = m_edges.size() - 1; - m_edges.add(e); - ++i; - Q_ASSERT(i < m_parent->m_indices.size()); - } while (m_parent->m_indices.at(i) != T(-1)); // Q_TRIANGULATE_END_OF_POLYGON - - m_edges.last().next = start; - m_edges.at(start).previous = m_edges.size() - 1; - ++i; // Skip Q_TRIANGULATE_END_OF_POLYGON. - } - - for (i = 0; i < m_edges.size(); ++i) { - m_edges.at(i).to = m_edges.at(m_edges.at(i).next).from; - m_edges.at(i).pointingUp = m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from); - m_edges.at(i).helper = -1; // Not initialized here. - } -} - -template <typename T> -void QTriangulator<T>::SimpleToMonotone::removeZeroLengthEdges() -{ - for (int i = 0; i < m_edges.size(); ++i) { - if (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(i).to)) { - m_edges.at(m_edges.at(i).previous).next = m_edges.at(i).next; - m_edges.at(m_edges.at(i).next).previous = m_edges.at(i).previous; - m_edges.at(m_edges.at(i).next).from = m_edges.at(i).from; - m_edges.at(i).next = -1; // Mark as removed. - } - } - - QDataBuffer<int> newMapping(m_edges.size()); - newMapping.resize(m_edges.size()); - int count = 0; - for (int i = 0; i < m_edges.size(); ++i) { - if (m_edges.at(i).next != -1) { - m_edges.at(count) = m_edges.at(i); - newMapping.at(i) = count; - ++count; - } - } - m_edges.resize(count); - for (int i = 0; i < m_edges.size(); ++i) { - m_edges.at(i).next = newMapping.at(m_edges.at(i).next); - m_edges.at(i).previous = newMapping.at(m_edges.at(i).previous); - } -} - -template <typename T> -void QTriangulator<T>::SimpleToMonotone::fillPriorityQueue() -{ - m_upperVertex.reset(); - m_upperVertex.reserve(m_edges.size()); - for (int i = 0; i < m_edges.size(); ++i) - m_upperVertex.add(i); - CompareVertices cmp(this); - //qSort(m_upperVertex.data(), m_upperVertex.data() + m_upperVertex.size(), cmp); - sort(m_upperVertex.data(), m_upperVertex.size(), cmp); - //for (int i = 1; i < m_upperVertex.size(); ++i) { - // Q_ASSERT(!cmp(m_upperVertex.at(i), m_upperVertex.at(i - 1))); - //} -} - -template <typename T> -bool QTriangulator<T>::SimpleToMonotone::edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const -{ - const Edge &leftEdge = m_edges.at(leftEdgeIndex); - const Edge &rightEdge = m_edges.at(rightEdgeIndex); - const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper()); - const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower()); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.upper()), l, u); - // d < 0: left, d > 0: right, d == 0: on top - if (d == 0) - d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u); - return d < 0; -} - -// Returns the rightmost edge not to the right of the given edge. -template <typename T> -QRBTree<int>::Node *QTriangulator<T>::SimpleToMonotone::searchEdgeLeftOfEdge(int edgeIndex) const -{ - QRBTree<int>::Node *current = m_edgeList.root; - QRBTree<int>::Node *result = 0; - while (current) { - if (edgeIsLeftOfEdge(edgeIndex, current->data)) { - current = current->left; - } else { - result = current; - current = current->right; - } - } - return result; -} - -// Returns the rightmost edge left of the given point. -template <typename T> -QRBTree<int>::Node *QTriangulator<T>::SimpleToMonotone::searchEdgeLeftOfPoint(int pointIndex) const -{ - QRBTree<int>::Node *current = m_edgeList.root; - QRBTree<int>::Node *result = 0; - while (current) { - const QPodPoint &p1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); - const QPodPoint &p2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(pointIndex), p1, p2); - if (d <= 0) { - current = current->left; - } else { - result = current; - current = current->right; - } - } - return result; -} - -template <typename T> -void QTriangulator<T>::SimpleToMonotone::classifyVertex(int i) -{ - Edge &e2 = m_edges.at(i); - const Edge &e1 = m_edges.at(e2.previous); - - bool startOrSplit = (e1.pointingUp && !e2.pointingUp); - bool endOrMerge = (!e1.pointingUp && e2.pointingUp); - - const QPodPoint &p1 = m_parent->m_vertices.at(e1.from); - const QPodPoint &p2 = m_parent->m_vertices.at(e2.from); - const QPodPoint &p3 = m_parent->m_vertices.at(e2.to); - qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p1, p2, p3); - Q_ASSERT(d != 0 || (!startOrSplit && !endOrMerge)); - - e2.type = RegularVertex; - - if (m_clockwiseOrder) { - if (startOrSplit) - e2.type = (d < 0 ? SplitVertex : StartVertex); - else if (endOrMerge) - e2.type = (d < 0 ? MergeVertex : EndVertex); - } else { - if (startOrSplit) - e2.type = (d > 0 ? SplitVertex : StartVertex); - else if (endOrMerge) - e2.type = (d > 0 ? MergeVertex : EndVertex); - } -} - -template <typename T> -void QTriangulator<T>::SimpleToMonotone::classifyVertices() -{ - for (int i = 0; i < m_edges.size(); ++i) - classifyVertex(i); -} - -template <typename T> -bool QTriangulator<T>::SimpleToMonotone::pointIsInSector(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2, const QPodPoint &v3) -{ - bool leftOfPreviousEdge = !qPointIsLeftOfLine(p, v2, v1); - bool leftOfNextEdge = !qPointIsLeftOfLine(p, v3, v2); - - if (qPointIsLeftOfLine(v1, v2, v3)) - return leftOfPreviousEdge && leftOfNextEdge; - else - return leftOfPreviousEdge || leftOfNextEdge; -} - -template <typename T> -bool QTriangulator<T>::SimpleToMonotone::pointIsInSector(int vertex, int sector) -{ - const QPodPoint ¢er = m_parent->m_vertices.at(m_edges.at(sector).from); - // Handle degenerate edges. - while (m_parent->m_vertices.at(m_edges.at(vertex).from) == center) - vertex = m_edges.at(vertex).next; - int next = m_edges.at(sector).next; - while (m_parent->m_vertices.at(m_edges.at(next).from) == center) - next = m_edges.at(next).next; - int previous = m_edges.at(sector).previous; - while (m_parent->m_vertices.at(m_edges.at(previous).from) == center) - previous = m_edges.at(previous).previous; - - const QPodPoint &p = m_parent->m_vertices.at(m_edges.at(vertex).from); - const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(previous).from); - const QPodPoint &v3 = m_parent->m_vertices.at(m_edges.at(next).from); - if (m_clockwiseOrder) - return pointIsInSector(p, v3, center, v1); - else - return pointIsInSector(p, v1, center, v3); -} - -template <typename T> -int QTriangulator<T>::SimpleToMonotone::findSector(int edge, int vertex) -{ - while (!pointIsInSector(vertex, edge)) { - edge = m_edges.at(m_edges.at(edge).previous).twin; - Q_ASSERT(edge != -1); - } - return edge; -} - -template <typename T> -void QTriangulator<T>::SimpleToMonotone::createDiagonal(int lower, int upper) -{ - lower = findSector(lower, upper); - upper = findSector(upper, lower); - - int prevLower = m_edges.at(lower).previous; - int prevUpper = m_edges.at(upper).previous; - - Edge e; - - e.twin = m_edges.size() + 1; - e.next = upper; - e.previous = prevLower; - e.from = m_edges.at(lower).from; - e.to = m_edges.at(upper).from; - m_edges.at(upper).previous = m_edges.at(prevLower).next = int(m_edges.size()); - m_edges.add(e); - - e.twin = m_edges.size() - 1; - e.next = lower; - e.previous = prevUpper; - e.from = m_edges.at(upper).from; - e.to = m_edges.at(lower).from; - m_edges.at(lower).previous = m_edges.at(prevUpper).next = int(m_edges.size()); - m_edges.add(e); -} - -template <typename T> -void QTriangulator<T>::SimpleToMonotone::monotoneDecomposition() -{ - if (m_edges.isEmpty()) - return; - - Q_ASSERT(!m_edgeList.root); - QDataBuffer<QPair<int, int> > diagonals(m_upperVertex.size()); - - int i = 0; - for (int index = 1; index < m_edges.size(); ++index) { - if (m_parent->m_vertices.at(m_edges.at(index).from) < m_parent->m_vertices.at(m_edges.at(i).from)) - i = index; - } - Q_ASSERT(i < m_edges.size()); - int j = m_edges.at(i).previous; - Q_ASSERT(j < m_edges.size()); - m_clockwiseOrder = qPointIsLeftOfLine(m_parent->m_vertices.at((quint32)m_edges.at(i).from), - m_parent->m_vertices.at((quint32)m_edges.at(j).from), m_parent->m_vertices.at((quint32)m_edges.at(i).to)); - - classifyVertices(); - fillPriorityQueue(); - - // debug: set helpers explicitly (shouldn't be necessary) - //for (int i = 0; i < m_edges.size(); ++i) - // m_edges.at(i).helper = m_edges.at(i).upper(); - - while (!m_upperVertex.isEmpty()) { - i = m_upperVertex.last(); - Q_ASSERT(i < m_edges.size()); - m_upperVertex.pop_back(); - j = m_edges.at(i).previous; - Q_ASSERT(j < m_edges.size()); - - QRBTree<int>::Node *leftEdgeNode = 0; - - switch (m_edges.at(i).type) { - case RegularVertex: - // If polygon interior is to the right of the vertex... - if (m_edges.at(i).pointingUp == m_clockwiseOrder) { - if (m_edges.at(i).node) { - Q_ASSERT(!m_edges.at(j).node); - if (m_edges.at(m_edges.at(i).helper).type == MergeVertex) - diagonals.add(QPair<int, int>(i, m_edges.at(i).helper)); - m_edges.at(j).node = m_edges.at(i).node; - m_edges.at(i).node = 0; - m_edges.at(j).node->data = j; - m_edges.at(j).helper = i; - } else if (m_edges.at(j).node) { - Q_ASSERT(!m_edges.at(i).node); - if (m_edges.at(m_edges.at(j).helper).type == MergeVertex) - diagonals.add(QPair<int, int>(i, m_edges.at(j).helper)); - m_edges.at(i).node = m_edges.at(j).node; - m_edges.at(j).node = 0; - m_edges.at(i).node->data = i; - m_edges.at(i).helper = i; - } else { - qWarning("Inconsistent polygon. (#1)"); - } - } else { - leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from); - if (leftEdgeNode) { - if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex) - diagonals.add(QPair<int, int>(i, m_edges.at(leftEdgeNode->data).helper)); - m_edges.at(leftEdgeNode->data).helper = i; - } else { - qWarning("Inconsistent polygon. (#2)"); - } - } - break; - case SplitVertex: - leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from); - if (leftEdgeNode) { - diagonals.add(QPair<int, int>(i, m_edges.at(leftEdgeNode->data).helper)); - m_edges.at(leftEdgeNode->data).helper = i; - } else { - qWarning("Inconsistent polygon. (#3)"); - } - // Fall through. - case StartVertex: - if (m_clockwiseOrder) { - leftEdgeNode = searchEdgeLeftOfEdge(j); - QRBTree<int>::Node *node = m_edgeList.newNode(); - node->data = j; - m_edges.at(j).node = node; - m_edges.at(j).helper = i; - m_edgeList.attachAfter(leftEdgeNode, node); - Q_ASSERT(m_edgeList.validate()); - } else { - leftEdgeNode = searchEdgeLeftOfEdge(i); - QRBTree<int>::Node *node = m_edgeList.newNode(); - node->data = i; - m_edges.at(i).node = node; - m_edges.at(i).helper = i; - m_edgeList.attachAfter(leftEdgeNode, node); - Q_ASSERT(m_edgeList.validate()); - } - break; - case MergeVertex: - leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from); - if (leftEdgeNode) { - if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex) - diagonals.add(QPair<int, int>(i, m_edges.at(leftEdgeNode->data).helper)); - m_edges.at(leftEdgeNode->data).helper = i; - } else { - qWarning("Inconsistent polygon. (#4)"); - } - // Fall through. - case EndVertex: - if (m_clockwiseOrder) { - if (m_edges.at(m_edges.at(i).helper).type == MergeVertex) - diagonals.add(QPair<int, int>(i, m_edges.at(i).helper)); - if (m_edges.at(i).node) { - m_edgeList.deleteNode(m_edges.at(i).node); - Q_ASSERT(m_edgeList.validate()); - } else { - qWarning("Inconsistent polygon. (#5)"); - } - } else { - if (m_edges.at(m_edges.at(j).helper).type == MergeVertex) - diagonals.add(QPair<int, int>(i, m_edges.at(j).helper)); - if (m_edges.at(j).node) { - m_edgeList.deleteNode(m_edges.at(j).node); - Q_ASSERT(m_edgeList.validate()); - } else { - qWarning("Inconsistent polygon. (#6)"); - } - } - break; - } - } - - for (int i = 0; i < diagonals.size(); ++i) - createDiagonal(diagonals.at(i).first, diagonals.at(i).second); -} - -template <typename T> -bool QTriangulator<T>::SimpleToMonotone::CompareVertices::operator () (int i, int j) const -{ - if (m_parent->m_edges.at(i).from == m_parent->m_edges.at(j).from) - return m_parent->m_edges.at(i).type > m_parent->m_edges.at(j).type; - return m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).from) > - m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).from); -} - -//============================================================================// -// QTriangulator::MonotoneToTriangles // -//============================================================================// -template <typename T> -void QTriangulator<T>::MonotoneToTriangles::decompose() -{ - QVector<T> result; - QDataBuffer<int> stack(m_parent->m_indices.size()); - m_first = 0; - // Require at least three more indices. - while (m_first + 3 <= m_parent->m_indices.size()) { - m_length = 0; - while (m_parent->m_indices.at(m_first + m_length) != T(-1)) { // Q_TRIANGULATE_END_OF_POLYGON - ++m_length; - Q_ASSERT(m_first + m_length < m_parent->m_indices.size()); - } - if (m_length < 3) { - m_first += m_length + 1; - continue; - } - - int minimum = 0; - while (less(next(minimum), minimum)) - minimum = next(minimum); - while (less(previous(minimum), minimum)) - minimum = previous(minimum); - - stack.reset(); - stack.add(minimum); - int left = previous(minimum); - int right = next(minimum); - bool stackIsOnLeftSide; - bool clockwiseOrder = leftOfEdge(minimum, left, right); - - if (less(left, right)) { - stack.add(left); - left = previous(left); - stackIsOnLeftSide = true; - } else { - stack.add(right); - right = next(right); - stackIsOnLeftSide = false; - } - - for (int count = 0; count + 2 < m_length; ++count) - { - Q_ASSERT(stack.size() >= 2); - if (less(left, right)) { - if (stackIsOnLeftSide == false) { - for (int i = 0; i + 1 < stack.size(); ++i) { - result.push_back(indices(stack.at(i + 1))); - result.push_back(indices(left)); - result.push_back(indices(stack.at(i))); - } - stack.first() = stack.last(); - stack.resize(1); - } else { - while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(left, stack.at(stack.size() - 2), stack.last()))) { - result.push_back(indices(stack.at(stack.size() - 2))); - result.push_back(indices(left)); - result.push_back(indices(stack.last())); - stack.pop_back(); - } - } - stack.add(left); - left = previous(left); - stackIsOnLeftSide = true; - } else { - if (stackIsOnLeftSide == true) { - for (int i = 0; i + 1 < stack.size(); ++i) { - result.push_back(indices(stack.at(i))); - result.push_back(indices(right)); - result.push_back(indices(stack.at(i + 1))); - } - stack.first() = stack.last(); - stack.resize(1); - } else { - while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(right, stack.last(), stack.at(stack.size() - 2)))) { - result.push_back(indices(stack.last())); - result.push_back(indices(right)); - result.push_back(indices(stack.at(stack.size() - 2))); - stack.pop_back(); - } - } - stack.add(right); - right = next(right); - stackIsOnLeftSide = false; - } - } - - m_first += m_length + 1; - } - m_parent->m_indices = result; -} - -//============================================================================// -// qTriangulate // -//============================================================================// - -QTriangleSet qTriangulate(const qreal *polygon, - int count, uint hint, const QTransform &matrix) -{ - QTriangleSet triangleSet; - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { - QTriangulator<quint32> triangulator; - triangulator.initialize(polygon, count, hint, matrix); - QVertexSet<quint32> vertexSet = triangulator.triangulate(); - triangleSet.vertices = vertexSet.vertices; - triangleSet.indices.setDataUint(vertexSet.indices); - - } else { - QTriangulator<quint16> triangulator; - triangulator.initialize(polygon, count, hint, matrix); - QVertexSet<quint16> vertexSet = triangulator.triangulate(); - triangleSet.vertices = vertexSet.vertices; - triangleSet.indices.setDataUshort(vertexSet.indices); - } - return triangleSet; -} - -QTriangleSet qTriangulate(const QVectorPath &path, - const QTransform &matrix, qreal lod) -{ - QTriangleSet triangleSet; - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { - QTriangulator<quint32> triangulator; - triangulator.initialize(path, matrix, lod); - QVertexSet<quint32> vertexSet = triangulator.triangulate(); - triangleSet.vertices = vertexSet.vertices; - triangleSet.indices.setDataUint(vertexSet.indices); - } else { - QTriangulator<quint16> triangulator; - triangulator.initialize(path, matrix, lod); - QVertexSet<quint16> vertexSet = triangulator.triangulate(); - triangleSet.vertices = vertexSet.vertices; - triangleSet.indices.setDataUshort(vertexSet.indices); - } - return triangleSet; -} - -QTriangleSet qTriangulate(const QPainterPath &path, - const QTransform &matrix, qreal lod) -{ - QTriangleSet triangleSet; - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { - QTriangulator<quint32> triangulator; - triangulator.initialize(path, matrix, lod); - QVertexSet<quint32> vertexSet = triangulator.triangulate(); - triangleSet.vertices = vertexSet.vertices; - triangleSet.indices.setDataUint(vertexSet.indices); - } else { - QTriangulator<quint16> triangulator; - triangulator.initialize(path, matrix, lod); - QVertexSet<quint16> vertexSet = triangulator.triangulate(); - triangleSet.vertices = vertexSet.vertices; - triangleSet.indices.setDataUshort(vertexSet.indices); - } - return triangleSet; -} - -QPolylineSet qPolyline(const QVectorPath &path, - const QTransform &matrix, qreal lod) -{ - QPolylineSet polyLineSet; - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { - QTriangulator<quint32> triangulator; - triangulator.initialize(path, matrix, lod); - QVertexSet<quint32> vertexSet = triangulator.polyline(); - polyLineSet.vertices = vertexSet.vertices; - polyLineSet.indices.setDataUint(vertexSet.indices); - } else { - QTriangulator<quint16> triangulator; - triangulator.initialize(path, matrix, lod); - QVertexSet<quint16> vertexSet = triangulator.polyline(); - polyLineSet.vertices = vertexSet.vertices; - polyLineSet.indices.setDataUshort(vertexSet.indices); - } - return polyLineSet; -} - -QPolylineSet qPolyline(const QPainterPath &path, - const QTransform &matrix, qreal lod) -{ - QPolylineSet polyLineSet; - if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { - QTriangulator<quint32> triangulator; - triangulator.initialize(path, matrix, lod); - QVertexSet<quint32> vertexSet = triangulator.polyline(); - polyLineSet.vertices = vertexSet.vertices; - polyLineSet.indices.setDataUint(vertexSet.indices); - } else { - QTriangulator<quint16> triangulator; - triangulator.initialize(path, matrix, lod); - QVertexSet<quint16> vertexSet = triangulator.polyline(); - polyLineSet.vertices = vertexSet.vertices; - polyLineSet.indices.setDataUshort(vertexSet.indices); - } - return polyLineSet; -} - -QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qtriangulator_p.h b/src/opengl/gl2paintengineex/qtriangulator_p.h deleted file mode 100644 index 04a219c255..0000000000 --- a/src/opengl/gl2paintengineex/qtriangulator_p.h +++ /dev/null @@ -1,148 +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 QTRIANGULATOR_P_H -#define QTRIANGULATOR_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 <QtCore/qvector.h> -#include <QtGui/private/qvectorpath_p.h> - -QT_BEGIN_NAMESPACE - -class Q_OPENGL_EXPORT QVertexIndexVector -{ -public: - enum Type { - UnsignedInt, - UnsignedShort - }; - - inline Type type() const { return t; } - - inline void setDataUint(const QVector<quint32> &data) - { - t = UnsignedInt; - indices32 = data; - } - - inline void setDataUshort(const QVector<quint16> &data) - { - t = UnsignedShort; - indices16 = data; - } - - inline const void* data() const - { - if (t == UnsignedInt) - return indices32.data(); - return indices16.data(); - } - - inline int size() const - { - if (t == UnsignedInt) - return indices32.size(); - return indices16.size(); - } - - inline QVertexIndexVector &operator = (const QVertexIndexVector &other) - { - if (t == UnsignedInt) - indices32 = other.indices32; - else - indices16 = other.indices16; - - return *this; - } - -private: - - Type t; - QVector<quint32> indices32; - QVector<quint16> indices16; -}; - -struct Q_OPENGL_EXPORT QTriangleSet -{ - inline QTriangleSet() { } - inline QTriangleSet(const QTriangleSet &other) : vertices(other.vertices), indices(other.indices) { } - QTriangleSet &operator = (const QTriangleSet &other) {vertices = other.vertices; indices = other.indices; return *this;} - - // The vertices of a triangle are given by: (x[i[n]], y[i[n]]), (x[j[n]], y[j[n]]), (x[k[n]], y[k[n]]), n = 0, 1, ... - QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...] - QVertexIndexVector indices; // [i[0], j[0], k[0], i[1], j[1], k[1], i[2], ...] -}; - -struct Q_OPENGL_EXPORT QPolylineSet -{ - inline QPolylineSet() { } - inline QPolylineSet(const QPolylineSet &other) : vertices(other.vertices), indices(other.indices) { } - QPolylineSet &operator = (const QPolylineSet &other) {vertices = other.vertices; indices = other.indices; return *this;} - - QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...] - QVertexIndexVector indices; // End of polyline is marked with -1. -}; - -// The vertex coordinates of the returned triangle set will be rounded to a grid with a mesh size -// of 1/32. The polygon is first transformed, then scaled by 32, the coordinates are rounded to -// integers, the polygon is triangulated, and then scaled back by 1/32. -// 'hint' should be a combination of QVectorPath::Hints. -// 'lod' is the level of detail. Default is 1. Curves are split into more lines when 'lod' is higher. -QTriangleSet qTriangulate(const qreal *polygon, int count, uint hint = QVectorPath::PolygonHint | QVectorPath::OddEvenFill, const QTransform &matrix = QTransform()); -QTriangleSet qTriangulate(const QVectorPath &path, const QTransform &matrix = QTransform(), qreal lod = 1); -QTriangleSet Q_OPENGL_EXPORT qTriangulate(const QPainterPath &path, const QTransform &matrix = QTransform(), qreal lod = 1); -QPolylineSet qPolyline(const QVectorPath &path, const QTransform &matrix = QTransform(), qreal lod = 1); -QPolylineSet Q_OPENGL_EXPORT qPolyline(const QPainterPath &path, const QTransform &matrix = QTransform(), qreal lod = 1); - -QT_END_NAMESPACE - -#endif diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index e2dc011532..658cdd5eb4 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -2,7 +2,7 @@ load(qt_module) TARGET = QtOpenGL QPRO_PWD = $$PWD -QT = core-private gui-private +QT = core-private gui-private widgets-private CONFIG += module MODULE_PRI = ../modules/qt_opengl.pri @@ -19,7 +19,7 @@ load(qt_module_config) HEADERS += $$QT_SOURCE_TREE/src/opengl/qtopenglversion.h -!win32:!embedded:!mac:!symbian:!qpa:CONFIG += x11 +!win32:!embedded:!mac:!qpa:CONFIG += x11 contains(QT_CONFIG, opengl):CONFIG += opengl contains(QT_CONFIG, opengles1):CONFIG += opengles1 contains(QT_CONFIG, opengles2):CONFIG += opengles2 @@ -47,144 +47,32 @@ 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 \ - qgraphicssystem_gl_p.h \ - qwindowsurface_gl_p.h \ - qpixmapdata_gl_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 \ - qgraphicssystem_gl.cpp \ - qwindowsurface_gl.cpp \ - qpixmapdata_gl.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 \ - qpixmapdata_x11gl_egl.cpp \ - qwindowsurface_x11gl.cpp - - HEADERS += qgl_egl_p.h \ - qpixmapdata_x11gl_p.h \ - qwindowsurface_x11gl_p.h - - } else { - SOURCES += qgl_x11.cpp \ - qglpixelbuffer_x11.cpp - } - - contains(QT_CONFIG, fontconfig) { - contains(QT_CONFIG, system-freetype) { - embedded:CONFIG += opentype - # 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 - SOURCES += qgl_win.cpp \ - qglpixelbuffer_win.cpp -} -wince*: { - SOURCES += qgl_wince.cpp \ - qglpixelbuffer_egl.cpp \ - qgl_egl.cpp - - HEADERS += qgl_egl_p.h -} - -embedded { - SOURCES += qgl_qws.cpp \ - qglpixelbuffer_egl.cpp \ - qglscreen_qws.cpp \ - qglwindowsurface_qws.cpp \ - qgl_egl.cpp - - HEADERS += qglscreen_qws.h \ - qglwindowsurface_qws_p.h \ - qgl_egl_p.h - - contains(QT_CONFIG, fontconfig) { - include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) - } else { - DEFINES *= QT_NO_FREETYPE - } -} - -symbian { - DEFINES += QGL_USE_TEXTURE_POOL QGL_NO_PRESERVED_SWAP - SOURCES -= qpixmapdata_gl.cpp - SOURCES += qgl_symbian.cpp \ - qpixmapdata_poolgl.cpp \ - qglpixelbuffer_egl.cpp \ - qgl_egl.cpp \ - qgltexturepool.cpp - - HEADERS += qgl_egl_p.h \ - qgltexturepool_p.h - - contains(QT_CONFIG, freetype) { - DEFINES += QT_NO_FONTCONFIG - INCLUDEPATH += \ - ../3rdparty/freetype/src \ - ../3rdparty/freetype/include - } - - symbian:TARGET.UID3 = 0x2002131A -} +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/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/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 f1fb2b4e7f..ad53b20098 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -45,21 +45,6 @@ #include <qdebug.h> #include <qglfunctions.h> -#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 <GL/glx.h> -#endif -#undef INT32 -#undef INT8 -#include "qx11info_x11.h" -#elif defined(Q_WS_MAC) -# include <private/qt_mac_p.h> -#endif - #include <qdatetime.h> #include <stdlib.h> // malloc @@ -68,29 +53,15 @@ #include "qimage.h" #include "qgl_p.h" -#if !defined(QT_OPENGL_ES_1) #include "gl2paintengineex/qpaintengineex_opengl2_p.h" -#include <private/qwindowsurface_gl_p.h> -#endif - -#ifndef QT_OPENGL_ES_2 -#include <private/qpaintengine_opengl_p.h> -#endif -#ifdef Q_WS_QWS -#include <private/qglwindowsurface_qws_p.h> -#endif - -#ifdef Q_WS_QPA -#include <QtGui/QPlatformGLContext> -#endif +#include <QtGui/QPlatformOpenGLContext> #include <qglpixelbuffer.h> #include <qglframebufferobject.h> #include <private/qimage_p.h> -#include <private/qpixmapdata_p.h> -#include <private/qpixmapdata_gl_p.h> +#include <qplatformpixmap_qpa.h> #include <private/qglpixelbuffer_p.h> #include <private/qimagepixmapcleanuphooks_p.h> #include "qcolormap.h" @@ -98,24 +69,11 @@ #include "qlibrary.h" #include <qmutex.h> -#if defined(QT_OPENGL_ES) && !defined(QT_NO_EGL) -#include <EGL/egl.h> -#endif -#ifdef QGL_USE_TEXTURE_POOL -#include <private/qgltexturepool_p.h> -#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() { @@ -125,10 +83,6 @@ struct QGLThreadContext { QGLContext *context; }; -#ifndef Q_WS_QPA -static QThreadStorage<QGLThreadContext *> qgl_context_storage; -#endif - Q_GLOBAL_STATIC(QGLFormat, qgl_default_format) class QGLDefaultOverlayFormat: public QGLFormat @@ -155,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 @@ -266,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 *****************************************************************************/ @@ -1613,42 +1476,16 @@ Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups) *****************************************************************************/ QGLContextGroup::QGLContextGroup(const QGLContext *context) - : m_context(context), m_guards(0), m_refs(1) + : m_context(context), m_refs(1) { qt_context_groups()->append(this); } QGLContextGroup::~QGLContextGroup() { - // Clear any remaining QGLSharedResourceGuard objects on the group. - QGLSharedResourceGuard *guard = m_guards; - while (guard != 0) { - guard->m_group = 0; - guard->m_id = 0; - guard = guard->m_next; - } qt_context_groups()->remove(this); } -void QGLContextGroup::addGuard(QGLSharedResourceGuard *guard) -{ - if (m_guards) - m_guards->m_prev = guard; - guard->m_next = m_guards; - guard->m_prev = 0; - m_guards = guard; -} - -void QGLContextGroup::removeGuard(QGLSharedResourceGuard *guard) -{ - if (guard->m_next) - guard->m_next->m_prev = guard->m_prev; - if (guard->m_prev) - guard->m_prev->m_next = guard->m_next; - else - m_guards = guard->m_next; -} - const QGLContext *qt_gl_transfer_context(const QGLContext *ctx) { if (!ctx) @@ -1664,11 +1501,15 @@ const QGLContext *qt_gl_transfer_context(const QGLContext *ctx) QGLContextPrivate::QGLContextPrivate(QGLContext *context) : internal_context(false) , q_ptr(context) + , texture_destroyer(0) , functions(0) { group = new QGLContextGroup(context); - texture_destroyer = new QGLTextureDestroyer; - texture_destroyer->moveToThread(qApp->thread()); + + if (qApp) { + texture_destroyer = new QGLTextureDestroyer; + texture_destroyer->moveToThread(qApp->thread()); + } } QGLContextPrivate::~QGLContextPrivate() @@ -1689,35 +1530,9 @@ 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) - platformContext = 0; -#endif -#if !defined(QT_NO_EGL) - ownsEglContext = false; - eglContext = 0; - eglSurface = EGL_NO_SURFACE; -#endif + + guiGlContext = 0; + ownContext = false; fbo = 0; crWin = false; initDone = false; @@ -1795,7 +1610,7 @@ static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, boo img = img.mirrored(); } -Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) +QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) { QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); @@ -1811,7 +1626,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 @@ -1845,15 +1660,15 @@ Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache) QGLTextureCache::QGLTextureCache() : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though { - QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTexturesForPixampData); - QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction); + QImagePixmapCleanupHooks::instance()->addPlatformPixmapModificationHook(cleanupTexturesForPixampData); + QImagePixmapCleanupHooks::instance()->addPlatformPixmapDestructionHook(cleanupBeforePixmapDestruction); QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey); } QGLTextureCache::~QGLTextureCache() { - QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData); - QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction); + QImagePixmapCleanupHooks::instance()->removePlatformPixmapModificationHook(cleanupTexturesForPixampData); + QImagePixmapCleanupHooks::instance()->removePlatformPixmapDestructionHook(cleanupBeforePixmapDestruction); QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey); } @@ -1912,22 +1727,15 @@ void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey) } -void QGLTextureCache::cleanupTexturesForPixampData(QPixmapData* pmd) +void QGLTextureCache::cleanupTexturesForPixampData(QPlatformPixmap* pmd) { cleanupTexturesForCacheKey(pmd->cacheKey()); } -void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd) +void QGLTextureCache::cleanupBeforePixmapDestruction(QPlatformPixmap* pmd) { // Remove any bound textures first: cleanupTexturesForPixampData(pmd); - -#if defined(Q_WS_X11) - if (pmd->classId() == QPixmapData::X11Class) { - Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken - QGLContextPrivate::destroyGlSurfaceForPixmap(pmd); - } -#endif } QGLTextureCache *QGLTextureCache::instance() @@ -2105,8 +1913,6 @@ QGLContext::~QGLContext() // clean up resources specific to this context d_ptr->cleanup(); - // clean up resources belonging to this context's group - d_ptr->group->cleanupResources(this); QGLSignalProxy::instance()->emitAboutToDestroyContext(this); reset(); @@ -2114,10 +1920,6 @@ QGLContext::~QGLContext() void QGLContextPrivate::cleanup() { - QHash<QGLContextResourceBase *, void *>::ConstIterator it; - for (it = m_resources.begin(); it != m_resources.end(); ++it) - it.key()->freeResource(it.value()); - m_resources.clear(); } #define ctx q_ptr @@ -2152,13 +1954,11 @@ void QGLContextPrivate::syncGlState() } #undef ctx -#ifdef QT_NO_EGL void QGLContextPrivate::swapRegion(const QRegion &) { Q_Q(QGLContext); q->swapBuffers(); } -#endif /*! \overload @@ -2303,12 +2103,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) @@ -2547,18 +2345,8 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G #endif const QImage &constRef = img; // to avoid detach in bits()... -#ifdef QGL_USE_TEXTURE_POOL - QGLTexturePool::instance()->createPermanentTexture(tx_id, - target, - 0, internalFormat, - img.width(), img.height(), - externalFormat, - pixel_type, - constRef.bits()); -#else glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat, pixel_type, constRef.bits()); -#endif #if defined(QT_OPENGL_ES_2) if (genMipmap) glGenerateMipmap(target); @@ -2601,19 +2389,8 @@ QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum targe QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options) { Q_Q(QGLContext); - QPixmapData *pd = pixmap.pixmapData(); -#if !defined(QT_OPENGL_ES_1) - if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) { - const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd); - - if (data->isValidContext(q)) { - data->bind(); - return data->texture(); - } - } -#else + QPlatformPixmap *pd = pixmap.handle(); Q_UNUSED(pd); -#endif const qint64 key = pixmap.cacheKey(); QGLTexture *texture = textureCacheLookup(key, target); @@ -2628,39 +2405,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() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::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<const char*>(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<QPixmap*>(&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 @@ -2779,31 +2523,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. @@ -2835,30 +2554,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 @@ -2873,14 +2568,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(); @@ -3020,14 +2707,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 @@ -3091,15 +2770,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. @@ -3329,11 +2999,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->platformContext) -#else - if (!d->paintDevice) -#endif + if (!d->paintDevice && !d->guiGlContext) return false; reset(); @@ -3342,10 +3008,6 @@ bool QGLContext::create(const QGLContext* shareContext) QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(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; } @@ -3419,37 +3081,15 @@ void QGLContext::setInitialized(bool on) const QGLContext* QGLContext::currentContext() { -#ifdef Q_WS_QPA - if (const QPlatformGLContext *threadContext = QPlatformGLContext::currentContext()) { - return QGLContext::fromPlatformGLContext(const_cast<QPlatformGLContext *>(threadContext)); + if (const QOpenGLContext *threadContext = QOpenGLContext::currentContext()) { + return QGLContext::fromOpenGLContext(const_cast<QOpenGLContext *>(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 } /*! @@ -3761,11 +3401,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. @@ -3906,30 +3541,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 } /*! @@ -4275,125 +3889,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) @@ -4467,28 +3962,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(); - - QPixmapData *data = new QX11PixmapData(QPixmapData::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<Visual *>(xinfo.visual()); - const_cast<QX11Info &>(pm.x11Info()).setX11Data(xd); - } - -#else QPixmap pm(sz); -#endif d->glcx->doneCurrent(); @@ -4500,9 +3974,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(); @@ -4520,13 +3991,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(); @@ -4546,21 +4010,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<QColor> 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; } @@ -4595,11 +4046,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()) @@ -4918,18 +4364,13 @@ 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; } - // this changes what paintEngine() returns - qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); - engine = paintEngine(); QPainter *p; bool reuse_painter = false; if (engine->isActive()) { @@ -4973,7 +4414,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); @@ -5021,18 +4461,14 @@ 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; } - // this changes what paintEngine() returns - qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); - engine = paintEngine(); QPainter *p; bool reuse_painter = false; bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); @@ -5077,7 +4513,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); @@ -5150,28 +4585,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. @@ -5204,23 +4617,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. @@ -5245,15 +4641,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 @@ -5267,15 +4654,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 @@ -5289,42 +4667,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<QGL2PaintEngineEx>, qt_gl_2_engine) -#endif - -#ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_gl_engine) -#endif -Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine() +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 { @@ -5492,10 +4845,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; @@ -5588,32 +4937,24 @@ 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) +void qt_set_gl_library_name(const QString& name) { qt_gl_lib_name()->operator=(name); } -Q_OPENGL_EXPORT const QString qt_gl_library_name() +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); @@ -5653,108 +4994,6 @@ void QGLContextGroup::removeShare(const QGLContext *context) { group->m_shares.clear(); } -QGLContextGroupResourceBase::QGLContextGroupResourceBase() - : active(0) -{ -#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG - qDebug("Creating context group resource object %p.", this); -#endif -} - -QGLContextGroupResourceBase::~QGLContextGroupResourceBase() -{ -#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG - qDebug("Deleting context group resource %p. Group size: %d.", this, m_groups.size()); -#endif - for (int i = 0; i < m_groups.size(); ++i) { - m_groups.at(i)->m_resources.remove(this); - active.deref(); - } -#ifndef QT_NO_DEBUG - if (active != 0) { - qWarning("QtOpenGL: Resources are still available at program shutdown.\n" - " This is possibly caused by a leaked QGLWidget, \n" - " QGLFramebufferObject or QGLPixelBuffer."); - } -#endif -} - -void QGLContextGroupResourceBase::insert(const QGLContext *context, void *value) -{ -#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG - qDebug("Inserting context group resource %p for context %p, managed by %p.", value, context, this); -#endif - QGLContextGroup *group = QGLContextPrivate::contextGroup(context); - Q_ASSERT(!group->m_resources.contains(this)); - group->m_resources.insert(this, value); - m_groups.append(group); - active.ref(); -} - -void *QGLContextGroupResourceBase::value(const QGLContext *context) -{ - QGLContextGroup *group = QGLContextPrivate::contextGroup(context); - return group->m_resources.value(this, 0); -} - -void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx) -{ - void *resource = value(ctx); - - if (resource != 0) { - QGLShareContextScope scope(ctx); - freeResource(resource); - - QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx); - group->m_resources.remove(this); - m_groups.removeOne(group); - active.deref(); - } -} - -void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx, void *value) -{ -#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG - qDebug("Cleaning up context group resource %p, for context %p in thread %p.", this, ctx, QThread::currentThread()); -#endif - QGLShareContextScope scope(ctx); - freeResource(value); - active.deref(); - - QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx); - m_groups.removeOne(group); -} - -void QGLContextGroup::cleanupResources(const QGLContext *context) -{ - // If there are still shares, then no cleanup to be done yet. - if (m_shares.size() > 1) - return; - - // Iterate over all resources and free each in turn. - QHash<QGLContextGroupResourceBase *, void *>::ConstIterator it; - for (it = m_resources.begin(); it != m_resources.end(); ++it) - it.key()->cleanup(context, it.value()); -} - -QGLSharedResourceGuard::~QGLSharedResourceGuard() -{ - if (m_group) - m_group->removeGuard(this); -} - -void QGLSharedResourceGuard::setContext(const QGLContext *context) -{ - if (m_group) - m_group->removeGuard(this); - if (context) { - m_group = QGLContextPrivate::contextGroup(context); - m_group->addGuard(this); - } else { - m_group = 0; - } -} - QSize QGLTexture::bindCompressedTexture (const QString& fileName, const char *format) { diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index f7685ed8b4..665dcac412 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -42,34 +42,22 @@ #ifndef QGL_H #define QGL_H -#include <QtGui/qwidget.h> +#include <QtWidgets/qwidget.h> #include <QtGui/qpaintengine.h> #include <QtOpenGL/qglcolormap.h> #include <QtCore/qmap.h> #include <QtCore/qscopedpointer.h> -#ifdef Q_WS_QPA -#include <QtGui/QPlatformWindowFormat> -#endif +#include <QtGui/QSurfaceFormat> QT_BEGIN_HEADER -#if defined(Q_WS_WIN) +#if defined(Q_OS_WIN) # include <QtCore/qt_windows.h> #endif -#if defined(QT_OPENGL_ES_1) -# if defined(Q_OS_MAC) -# include <OpenGLES/ES1/gl.h> -# else -# include <GLES/gl.h> -# endif -# ifndef GL_DOUBLE -# define GL_DOUBLE GL_FLOAT -# endif -# ifndef GLdouble -typedef GLfloat GLdouble; -# endif +#if defined(Q_OS_MAC) +# include <OpenGL/gl.h> #elif defined(QT_OPENGL_ES_2) # if defined(Q_OS_MAC) # include <OpenGLES/ES2/gl.h> @@ -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 <typename T> -struct QMacGLCompatTypes -{ - typedef long CompatGLint; - typedef unsigned long CompatGLuint; - typedef unsigned long CompatGLenum; -}; - -template <> -struct QMacGLCompatTypes<long> -{ - typedef int CompatGLint; - typedef unsigned int CompatGLuint; - typedef unsigned int CompatGLenum; -}; - -typedef QMacGLCompatTypes<GLint>::CompatGLint QMacCompatGLint; -typedef QMacGLCompatTypes<GLint>::CompatGLuint QMacCompatGLuint; -typedef QMacGLCompatTypes<GLint>::CompatGLenum QMacCompatGLenum; - -#endif - #ifdef QT3_SUPPORT #define QGL_VERSION 460 #define QGL_VERSION_STR "4.6" @@ -132,17 +95,12 @@ class QGLCmap; #endif class QPixmap; -#if defined(Q_WS_X11) && !defined(QT_OPENGL_ES) -class QGLOverlayWidget; -#endif class QGLWidgetPrivate; class QGLContextPrivate; // Namespace class: namespace QGL { - Q_OPENGL_EXPORT void setPreferredPaintEngine(QPaintEngine::Type engineType); - enum FormatOption { DoubleBuffer = 0x0001, DepthBuffer = 0x0002, @@ -284,10 +242,8 @@ public: static OpenGLVersionFlags openGLVersionFlags(); -#if defined(Q_WS_QPA) - static QGLFormat fromPlatformWindowFormat(const QPlatformWindowFormat &format); - static QPlatformWindowFormat toPlatformWindowFormat(const QGLFormat &format); -#endif + static QGLFormat fromSurfaceFormat(const QSurfaceFormat &format); + static QSurfaceFormat toSurfaceFormat(const QGLFormat &format); private: QGLFormatPrivate *d; @@ -373,22 +329,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(); @@ -398,23 +338,12 @@ public: static const QGLContext* currentContext(); -#ifdef Q_WS_QPA - static QGLContext *fromPlatformGLContext(QPlatformGLContext *platformContext); -#endif + static QGLContext *fromOpenGLContext(QOpenGLContext *platformContext); + QOpenGLContext *contextHandle() const; + 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) - 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 +359,7 @@ protected: static QGLContext* currentCtx; private: -#ifdef Q_WS_QPA - QGLContext(QPlatformGLContext *platformContext); -#endif + QGLContext(QOpenGLContext *windowContext); QScopedPointer<QGLContextPrivate> d_ptr; @@ -441,18 +368,12 @@ 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 QGLWindowSurface; - friend class QGLPixmapData; - friend class QGLPixmapFilterBase; friend class QGLTextureGlyphCache; friend struct QGLGlyphTexture; friend class QGLContextGroup; - friend class QGLSharedResourceGuard; friend class QGLPixmapBlurFilter; friend class QGLExtensions; friend class QGLTexture; @@ -469,7 +390,6 @@ private: friend class QGLFBOGLPaintDevice; friend class QGLPaintDevice; friend class QGLWidgetGLPaintDevice; - friend class QX11GLPixmapData; friend class QX11GLSharedContexts; friend class QGLContextResourceBase; friend class QSGDistanceFieldGlyphCache; @@ -556,22 +476,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(); @@ -613,7 +517,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 4de5122a86..0000000000 --- a/src/opengl/qgl_egl.cpp +++ /dev/null @@ -1,351 +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 <QtCore/qdebug.h> -#include <QtOpenGL/qgl.h> -#include <QtOpenGL/qglpixelbuffer.h> -#include "qgl_p.h" -#include "qgl_egl_p.h" -#include "qglpixelbuffer_p.h" - -#ifdef Q_WS_X11 -#include <QtGui/private/qpixmap_x11_p.h> -#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<const char *>(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 - // (as opposed to a QGLWindowSurface use case). - if (paintDevice && paintDevice->devType() == QInternal::Widget) { - QWidget *w = static_cast<QWidget *>(paintDevice); - if (QGLWidget *wgl = qobject_cast<QGLWidget *>(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 QPixmapData had to create the QGLContext, we don't have a paintDevice - if (!paintDevice) - return eglSurface; - -#ifdef Q_WS_X11 - if (paintDevice->devType() == QInternal::Pixmap) { - QPixmapData *pmd = static_cast<QPixmap*>(paintDevice)->data_ptr().data(); - if (pmd->classId() == QPixmapData::X11Class) { - QX11PixmapData* x11PixmapData = static_cast<QX11PixmapData*>(pmd); - return (EGLSurface)x11PixmapData->gl_surface; - } - } -#endif - - if (paintDevice->devType() == QInternal::Pbuffer) { - QGLPixelBuffer* pbuf = static_cast<QGLPixelBuffer*>(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<const char *>(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 <QtGui/private/qegl_p.h> -#include <QtGui/private/qeglcontext_p.h> -#include <QtGui/private/qeglproperties_p.h> - -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 <AGL/agl.h> -# include <AGL/aglRenderers.h> -# include <OpenGL/gl.h> -# ifdef QT_NO_DEBUG -# define qDebug qt_noop(),1?(void)0:qDebug -# endif -#else -# include <AGL/agl.h> -# include <AGL/aglRenderers.h> -# include <OpenGL/gl.h> -#endif -#else -#include <private/qcocoaview_mac_p.h> -#endif - - -#include <OpenGL/gl.h> -#include <CoreServices/CoreServices.h> -#include <private/qfont_p.h> -#include <private/qfontengine_p.h> -#include <private/qgl_p.h> -#include <private/qpaintengine_opengl_p.h> -#include <private/qt_mac_p.h> -#include <qpixmap.h> -#include <qtimer.h> -#include <qapplication.h> -#include <qstack.h> -#include <qdesktopwidget.h> -#include <qdebug.h> - -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<NSOpenGLPixelFormat *>(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<NSOpenGLContext *>(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<QGLContext *>(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<QPixmap *>(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<QPixmap *>(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<QPixmap *>(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<NSOpenGLContext *>(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<NSOpenGLContext *>(d->cx) release]; -#endif - d->cx = 0; -#ifndef QT_MAC_USE_COCOA - if (d->vi) - aglDestroyPixelFormat((AGLPixelFormat)d->vi); -#else - [static_cast<NSOpenGLPixelFormat *>(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<NSOpenGLContext *>(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<QRect> 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<QPixmap *>(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<char *>(qt_mac_pixmap_get_base(pm)), - qt_mac_pixmap_get_bytes_per_line(pm)); - - PixMapHandle pixmapHandle = GetGWorldPixMap(gworld); - aglSetOffScreen(reinterpret_cast<AGLContext>(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<NSOpenGLContext *>(d->cx) view] != view && ![view isHidden]) - [static_cast<NSOpenGLContext *>(d->cx) setView:view]; - } else if (d->paintDevice->devType() == QInternal::Pixmap) { - const QPixmap *pm = static_cast<const QPixmap *>(d->paintDevice); - [static_cast<NSOpenGLContext *>(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<NSOpenGLContext *>(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<NSOpenGLContext *>(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<CFURLRef> 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<CFBundleRef>(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<QWidget*>(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 4c22f0f3d7..668728be20 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -60,24 +60,18 @@ #include "QtCore/qthreadstorage.h" #include "QtCore/qhash.h" #include "QtCore/qatomic.h" -#include "private/qwidget_p.h" +#include "QtWidgets/private/qwidget_p.h" +#include "QtGui/private/qopenglcontext_p.h" #include "qcache.h" #include "qglpaintdevice_p.h" -#ifndef QT_NO_EGL -#include <QtGui/private/qegl_p.h> -#endif - -#if defined(Q_WS_QPA) -#include <QtGui/QPlatformGLContext> -#endif +#include <QtGui/QOpenGLContext> QT_BEGIN_NAMESPACE class QGLContext; class QGLOverlayWidget; class QPixmap; -class QPixmapFilter; #ifdef Q_WS_MAC # ifdef qDebug # define old_qDebug qDebug @@ -96,14 +90,6 @@ QT_END_INCLUDE_NAMESPACE class QMacWindowChangeEvent; #endif -#ifdef Q_WS_QWS -class QWSGLWindowSurface; -#endif - -#ifndef QT_NO_EGL -class QEglContext; -#endif - QT_BEGIN_INCLUDE_NAMESPACE #include <QtOpenGL/private/qglextensions_p.h> QT_END_INCLUDE_NAMESPACE @@ -165,15 +151,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; } @@ -199,31 +176,8 @@ 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(); -#elif defined(Q_WS_QWS) - QWSGLWindowSurface *wsurf; -#endif -#ifdef Q_OS_SYMBIAN - void recreateEglSurface(); - WId eglSurfaceWindowId; -#endif }; -class QGLContextGroupResourceBase; -class QGLSharedResourceGuard; - // QGLContextPrivate has the responsibility of creating context groups. // QGLContextPrivate maintains the reference counter and destroys // context groups when needed. @@ -237,9 +191,6 @@ public: bool isSharing() const { return m_shares.size() >= 2; } QList<const QGLContext *> shares() const { return m_shares; } - void addGuard(QGLSharedResourceGuard *guard); - void removeGuard(QGLSharedResourceGuard *guard); - static void addShare(const QGLContext *context, const QGLContext *share); static void removeShare(const QGLContext *context); @@ -249,12 +200,8 @@ private: QGLExtensionFuncs m_extensionFuncs; const QGLContext *m_context; // context group's representative QList<const QGLContext *> m_shares; - QHash<QGLContextGroupResourceBase *, void *> m_resources; - QGLSharedResourceGuard *m_guards; // double-linked list of active guards. QAtomicInt m_refs; - void cleanupResources(const QGLContext *ctx); - friend class QGLContext; friend class QGLContextPrivate; friend class QGLContextGroupResourceBase; @@ -262,7 +209,7 @@ private: // Get the context that resources for "ctx" will transfer to once // "ctx" is destroyed. Returns null if nothing is sharing with ctx. -Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *); +const QGLContext *qt_gl_transfer_context(const QGLContext *); // GL extension definitions class QGLExtensions { @@ -351,54 +298,11 @@ 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 + QOpenGLContext *guiGlContext; + bool ownContext; -#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) - QPlatformGLContext *platformContext; 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<QPixmapData*, QPixmap> boundPixmaps; - QGLTexture *bindTextureFromNativePixmap(QPixmap*, const qint64 key, - QGLContext::BindOptions options); - static void destroyGlSurfaceForPixmap(QPixmapData*); - static void unbindPixmapFromTexture(QPixmapData*); -#endif -#if defined(Q_WS_MAC) - bool update; - void *tryFormat(const QGLFormat &format); - void clearDrawable(); -#endif QGLFormat glFormat; QGLFormat reqFormat; GLuint fbo; @@ -423,10 +327,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; @@ -439,7 +339,6 @@ public: GLuint current_fbo; GLuint default_fbo; QPaintEngine *active_engine; - QHash<QGLContextResourceBase *, void *> m_resources; QGLTextureDestroyer *texture_destroyer; QGLFunctions *functions; @@ -448,14 +347,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); }; @@ -508,34 +401,19 @@ class Q_OPENGL_EXPORT QGLTextureDestroyer : public QObject public: QGLTextureDestroyer() : QObject() { qRegisterMetaType<GLuint>("GLuint"); - connect(this, SIGNAL(freeTexture(QGLContext *, QPixmapData *, GLuint)), - this, SLOT(freeTexture_slot(QGLContext *, QPixmapData *, GLuint))); + connect(this, SIGNAL(freeTexture(QGLContext *, QPlatformPixmap *, GLuint)), + this, SLOT(freeTexture_slot(QGLContext *, QPlatformPixmap *, GLuint))); } - void emitFreeTexture(QGLContext *context, QPixmapData *boundPixmap, GLuint id) { + void emitFreeTexture(QGLContext *context, QPlatformPixmap *boundPixmap, GLuint id) { emit freeTexture(context, boundPixmap, id); } Q_SIGNALS: - void freeTexture(QGLContext *context, QPixmapData *boundPixmap, GLuint id); + void freeTexture(QGLContext *context, QPlatformPixmap *boundPixmap, GLuint id); private slots: - void freeTexture_slot(QGLContext *context, QPixmapData *boundPixmap, GLuint id) { + void freeTexture_slot(QGLContext *context, QPlatformPixmap *boundPixmap, GLuint id) { Q_UNUSED(boundPixmap); -#if defined(Q_WS_X11) - if (boundPixmap) { - QGLContext *oldContext = const_cast<QGLContext *>(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); } @@ -562,17 +440,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) - QPixmapData *boundPixmap = 0; -#endif + QPlatformPixmap *boundPixmap = 0; context->d_ptr->texture_destroyer->emitFreeTexture(context, boundPixmap, id); } } @@ -583,10 +456,6 @@ public: QGLContext::BindOptions options; -#if defined(Q_WS_X11) - QPixmapData* boundPixmap; -#endif - bool canBindCompressedTexture (const char *buf, int len, const char *format, bool *hasAlpha); QSize bindCompressedTexture @@ -629,8 +498,8 @@ public: void removeContextTextures(QGLContext *ctx); static QGLTextureCache *instance(); static void cleanupTexturesForCacheKey(qint64 cacheKey); - static void cleanupTexturesForPixampData(QPixmapData* pixmap); - static void cleanupBeforePixmapDestruction(QPixmapData* pixmap); + static void cleanupTexturesForPixampData(QPlatformPixmap* pixmap); + static void cleanupBeforePixmapDestruction(QPlatformPixmap* pixmap); private: QCache<QGLTextureCacheKey, QGLTexture> m_cache; @@ -661,199 +530,71 @@ QGLTexture* QGLTextureCache::getTexture(QGLContext *ctx, qint64 key) return m_cache.object(cacheKey); } -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 -} +extern QPaintEngine* qt_qgl_paint_engine(); -/* - Base for resources that are shared in a context group. -*/ -class Q_OPENGL_EXPORT QGLContextGroupResourceBase -{ -public: - QGLContextGroupResourceBase(); - virtual ~QGLContextGroupResourceBase(); - void insert(const QGLContext *context, void *value); - void *value(const QGLContext *context); - void cleanup(const QGLContext *context); - void cleanup(const QGLContext *context, void *value); - virtual void freeResource(void *value) = 0; - -protected: - QList<QGLContextGroup *> m_groups; - -private: - QAtomicInt active; -}; - -/* - The QGLContextGroupResource template is used to manage a resource - for a group of sharing GL contexts. When the last context in the - group is destroyed, or when the QGLContextGroupResource object - itself is destroyed (implies potential context switches), the - resource will be freed. - - The class used as the template class type needs to have a - constructor with the following signature: - T(const QGLContext *); -*/ -template <class T> -class QGLContextGroupResource : public QGLContextGroupResourceBase +// Put a guard around a GL object identifier and its context. +// When the context goes away, a shared context will be used +// in its place. If there are no more shared contexts, then +// the identifier is returned as zero - it is assumed that the +// context destruction cleaned up the identifier in this case. +class QGLSharedResourceGuardBase : public QOpenGLSharedResource { public: - ~QGLContextGroupResource() { - for (int i = 0; i < m_groups.size(); ++i) { - const QGLContext *context = m_groups.at(i)->context(); - T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context)); - if (resource) { - QGLShareContextScope scope(context); - delete resource; - } - } + QGLSharedResourceGuardBase(QGLContext *context, GLuint id) + : QOpenGLSharedResource(context->contextHandle()->shareGroup()) + , m_id(id) + { } - T *value(const QGLContext *context) { - T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context)); - if (!resource) { - resource = new T(context); - insert(context, resource); - } - return resource; + GLuint id() const + { + return m_id; } protected: - void freeResource(void *resource) { - delete reinterpret_cast<T *>(resource); - } -}; - -/* - Base for resources that are context specific. -*/ -class Q_OPENGL_EXPORT QGLContextResourceBase -{ -public: - virtual ~QGLContextResourceBase() { - for (int i = 0; i < m_contexts.size(); ++i) - m_contexts.at(i)->d_ptr->m_resources.remove(this); - } - - void insert(const QGLContext *context, void *value) { - context->d_ptr->m_resources.insert(this, value); - } - - void *value(const QGLContext *context) { - return context->d_ptr->m_resources.value(this, 0); + void invalidateResource() + { + m_id = 0; } - virtual void freeResource(void *value) = 0; -protected: - QList<const QGLContext *> m_contexts; -}; - -/* - The QGLContextResource template is used to manage a resource for a - single GL context. Just before the context is destroyed (while it's - still the current context), or when the QGLContextResource object - itself is destroyed (implies potential context switches), the - resource will be freed. The class used as the template class type - needs to have a constructor with the following signature: T(const - QGLContext *); -*/ -template <class T> -class QGLContextResource : public QGLContextResourceBase -{ -public: - ~QGLContextResource() { - for (int i = 0; i < m_contexts.size(); ++i) { - const QGLContext *context = m_contexts.at(i); - T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context)); - if (resource) { - QGLShareContextScope scope(context); - delete resource; - } + void freeResource(QOpenGLContext *context) + { + if (m_id) { + freeResource(QGLContext::fromOpenGLContext(context), m_id); } } - T *value(const QGLContext *context) { - T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context)); - if (!resource) { - resource = new T(context); - insert(context, resource); - } - return resource; - } + virtual void freeResource(QGLContext *ctx, GLuint id) = 0; -protected: - void freeResource(void *resource) { - delete reinterpret_cast<T *>(resource); - } +private: + GLuint m_id; }; -// Put a guard around a GL object identifier and its context. -// When the context goes away, a shared context will be used -// in its place. If there are no more shared contexts, then -// the identifier is returned as zero - it is assumed that the -// context destruction cleaned up the identifier in this case. -class Q_OPENGL_EXPORT QGLSharedResourceGuard +template <typename Func> +class QGLSharedResourceGuard : public QGLSharedResourceGuardBase { public: - QGLSharedResourceGuard(const QGLContext *context) - : m_group(0), m_id(0), m_next(0), m_prev(0) - { - setContext(context); - } - QGLSharedResourceGuard(const QGLContext *context, GLuint id) - : m_group(0), m_id(id), m_next(0), m_prev(0) + QGLSharedResourceGuard(QGLContext *context, GLuint id, Func func) + : QGLSharedResourceGuardBase(context, id) + , m_func(func) { - setContext(context); } - ~QGLSharedResourceGuard(); - const QGLContext *context() const - { - return m_group ? m_group->context() : 0; - } - - void setContext(const QGLContext *context); - - GLuint id() const - { - return m_id; - } - - void setId(GLuint id) +protected: + void freeResource(QGLContext *ctx, GLuint id) { - m_id = id; + m_func(ctx, id); } private: - QGLContextGroup *m_group; - GLuint m_id; - QGLSharedResourceGuard *m_next; - QGLSharedResourceGuard *m_prev; - - friend class QGLContextGroup; + Func m_func; }; +template <typename Func> +QGLSharedResourceGuardBase *createSharedResourceGuard(QGLContext *context, GLuint id, Func cleanupFunc) +{ + return new QGLSharedResourceGuard<Func>(context, id, cleanupFunc); +} class QGLExtensionMatcher { diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp index 9ba8b75362..afa2772a6f 100644 --- a/src/opengl/qgl_qpa.cpp +++ b/src/opengl/qgl_qpa.cpp @@ -40,12 +40,14 @@ ****************************************************************************/ #include <QApplication> -#include <QtGui/private/qapplication_p.h> +#include <private/qapplication_p.h> #include <QPixmap> #include <QDebug> -#include <QtGui/private/qapplication_p.h> +#include <private/qapplication_p.h> +#include <QtGui/QPlatformOpenGLContext> #include <QtGui/QPlatformWindow> +#include <QtGui/QSurfaceFormat> #include "qgl.h" #include "qgl_p.h" @@ -53,81 +55,66 @@ QT_BEGIN_NAMESPACE /*! - Returns an OpenGL format for the platform window format specified by \a format. + Returns an OpenGL format for the window format specified by \a format. */ -QGLFormat QGLFormat::fromPlatformWindowFormat(const QPlatformWindowFormat &format) +QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format) { QGLFormat retFormat; - retFormat.setAccum(format.accum()); - if (format.accumBufferSize() >= 0) - retFormat.setAccumBufferSize(format.accumBufferSize()); - retFormat.setAlpha(format.alpha()); if (format.alphaBufferSize() >= 0) retFormat.setAlphaBufferSize(format.alphaBufferSize()); if (format.blueBufferSize() >= 0) retFormat.setBlueBufferSize(format.blueBufferSize()); - retFormat.setDepth(format.depth()); - if (format.depthBufferSize() >= 0) - retFormat.setDepthBufferSize(format.depthBufferSize()); - retFormat.setDirectRendering(format.directRendering()); - retFormat.setDoubleBuffer(format.doubleBuffer()); if (format.greenBufferSize() >= 0) retFormat.setGreenBufferSize(format.greenBufferSize()); if (format.redBufferSize() >= 0) retFormat.setRedBufferSize(format.redBufferSize()); - retFormat.setRgba(format.rgba()); - retFormat.setSampleBuffers(format.sampleBuffers()); - retFormat.setSamples(format.sampleBuffers()); - retFormat.setStencil(format.stencil()); - if (format.stencilBufferSize() >= 0) + if (format.depthBufferSize() >= 0) + retFormat.setDepthBufferSize(format.depthBufferSize()); + if (format.samples() > 1) { + retFormat.setSampleBuffers(format.samples()); + retFormat.setSamples(true); + } + if (format.stencilBufferSize() > 0) { + retFormat.setStencil(true); retFormat.setStencilBufferSize(format.stencilBufferSize()); + } + retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer); retFormat.setStereo(format.stereo()); - retFormat.setSwapInterval(format.swapInterval()); return retFormat; } /*! - Returns a platform window format for the OpenGL format specified by \a format. + Returns a window format for the OpenGL format specified by \a format. */ -QPlatformWindowFormat QGLFormat::toPlatformWindowFormat(const QGLFormat &format) +QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format) { - QPlatformWindowFormat retFormat; - retFormat.setAccum(format.accum()); - if (format.accumBufferSize() >= 0) - retFormat.setAccumBufferSize(format.accumBufferSize()); - retFormat.setAlpha(format.alpha()); - if (format.alphaBufferSize() >= 0) - retFormat.setAlphaBufferSize(format.alphaBufferSize()); + QSurfaceFormat retFormat; + if (format.alpha()) + retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize()); if (format.blueBufferSize() >= 0) retFormat.setBlueBufferSize(format.blueBufferSize()); - retFormat.setDepth(format.depth()); - if (format.depthBufferSize() >= 0) - retFormat.setDepthBufferSize(format.depthBufferSize()); - retFormat.setDirectRendering(format.directRendering()); - retFormat.setDoubleBuffer(format.doubleBuffer()); if (format.greenBufferSize() >= 0) retFormat.setGreenBufferSize(format.greenBufferSize()); if (format.redBufferSize() >= 0) retFormat.setRedBufferSize(format.redBufferSize()); - retFormat.setRgba(format.rgba()); - retFormat.setSampleBuffers(format.sampleBuffers()); - if (format.samples() >= 0) - retFormat.setSamples(format.samples()); - retFormat.setStencil(format.stencil()); - if (format.stencilBufferSize() >= 0) - retFormat.setStencilBufferSize(format.stencilBufferSize()); + if (format.depth()) + retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize()); + retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::DefaultSwapBehavior); + if (format.sampleBuffers()) + retFormat.setSamples(format.samples() == -1 ? 4 : format.samples()); + if (format.stencil()) + retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize()); retFormat.setStereo(format.stereo()); - retFormat.setSwapInterval(format.swapInterval()); return retFormat; } void QGLContextPrivate::setupSharing() { Q_Q(QGLContext); - QPlatformGLContext *sharedPlatformGLContext = platformContext->platformWindowFormat().sharedGLContext(); - if (sharedPlatformGLContext) { - QGLContext *actualSharedContext = QGLContext::fromPlatformGLContext(sharedPlatformGLContext); + QOpenGLContext *sharedContext = guiGlContext->shareContext(); + if (sharedContext) { + QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext); sharing = true; - QGLContextGroup::addShare(q,actualSharedContext); + QGLContextGroup::addShare(q, actualSharedContext); } } @@ -150,26 +137,30 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) d->valid = false; }else { QWidget *widget = static_cast<QWidget *>(d->paintDevice); - if (!widget->platformWindow()){ - QGLFormat glformat = format(); - QPlatformWindowFormat winFormat = QGLFormat::toPlatformWindowFormat(glformat); - if (shareContext) { - winFormat.setSharedContext(shareContext->d_func()->platformContext); - } - if (widget->testAttribute(Qt::WA_TranslucentBackground)) - winFormat.setAlpha(true); - winFormat.setWindowApi(QPlatformWindowFormat::OpenGL); - winFormat.setWindowSurface(false); - widget->setPlatformWindowFormat(winFormat); + QGLFormat glformat = format(); + QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat); + if (widget->testAttribute(Qt::WA_TranslucentBackground)) + winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8)); + + if (!widget->windowHandle()->handle()) { + widget->windowHandle()->setSurfaceType(QWindow::OpenGLSurface); + widget->windowHandle()->setFormat(winFormat); widget->winId();//make window } - d->platformContext = widget->platformWindow()->glContext(); - Q_ASSERT(d->platformContext); - d->glFormat = QGLFormat::fromPlatformWindowFormat(d->platformContext->platformWindowFormat()); - d->valid =(bool) d->platformContext; - if (d->valid) { - d->platformContext->setQGLContextHandle(this,qDeleteQGLContext); - } + + if (d->ownContext) + delete d->guiGlContext; + d->ownContext = true; + QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0; + d->guiGlContext = new QOpenGLContext; + d->guiGlContext->setFormat(winFormat); + d->guiGlContext->setShareContext(shareGlContext); + d->valid = d->guiGlContext->create(); + + if (d->valid) + d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext); + + d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format()); d->setupSharing(); } @@ -190,42 +181,60 @@ void QGLContext::reset() d->transpColor = QColor(); d->initDone = false; QGLContextGroup::removeShare(this); - if (d->platformContext) { - d->platformContext->setQGLContextHandle(0,0); + if (d->guiGlContext) { + if (d->ownContext) + delete d->guiGlContext; + else + d->guiGlContext->setQGLContextHandle(0,0); + d->guiGlContext = 0; } + d->ownContext = false; } void QGLContext::makeCurrent() { Q_D(QGLContext); - d->platformContext->makeCurrent(); + if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) + return; + + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + if (!widget->windowHandle()) + return; - if (!d->workaroundsCached) { - d->workaroundsCached = true; - const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); - if (renderer && strstr(renderer, "Mali")) { - d->workaround_brokenFBOReadBack = true; + if (d->guiGlContext->makeCurrent(widget->windowHandle())) { + if (!d->workaroundsCached) { + d->workaroundsCached = true; + const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); + if (renderer && strstr(renderer, "Mali")) { + d->workaround_brokenFBOReadBack = true; + } } } - } void QGLContext::doneCurrent() { Q_D(QGLContext); - d->platformContext->doneCurrent(); + d->guiGlContext->doneCurrent(); } void QGLContext::swapBuffers() const { Q_D(const QGLContext); - d->platformContext->swapBuffers(); + if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) + return; + + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + if (!widget->windowHandle()) + return; + + d->guiGlContext->swapBuffers(widget->windowHandle()); } void *QGLContext::getProcAddress(const QString &procName) const { Q_D(const QGLContext); - return d->platformContext->getProcAddress(procName); + return (void *)d->guiGlContext->getProcAddress(procName.toAscii()); } void QGLWidget::setContext(QGLContext *context, @@ -283,33 +292,34 @@ void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase) class QGLTemporaryContextPrivate { public: - QWidget *widget; - QPlatformGLContext *context; + QWindow *window; + QOpenGLContext *context; + + QGLContext *oldContext; }; QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) : d(new QGLTemporaryContextPrivate) { - d->context = const_cast<QPlatformGLContext *>(QPlatformGLContext::currentContext()); - if (d->context) - d->context->doneCurrent(); - d->widget = new QWidget; - d->widget->setGeometry(0,0,3,3); - QPlatformWindowFormat format = d->widget->platformWindowFormat(); - format.setWindowApi(QPlatformWindowFormat::OpenGL); - format.setWindowSurface(false); - d->widget->setPlatformWindowFormat(format); - d->widget->winId(); + d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); - d->widget->platformWindow()->glContext()->makeCurrent(); + d->window = new QWindow; + d->window->setSurfaceType(QWindow::OpenGLSurface); + d->window->setGeometry(QRect(0, 0, 3, 3)); + d->window->create(); + + d->context = new QOpenGLContext; + d->context->create(); + d->context->makeCurrent(d->window); } QGLTemporaryContext::~QGLTemporaryContext() { - d->widget->platformWindow()->glContext()->doneCurrent(); - if (d->context) - d->context->makeCurrent(); - delete d->widget; + if (d->oldContext) + d->oldContext->makeCurrent(); + + delete d->context; + delete d->window; } @@ -375,29 +385,35 @@ void QGLWidget::setColormap(const QGLColormap & c) Q_UNUSED(c); } -QGLContext::QGLContext(QPlatformGLContext *platformContext) +QGLContext::QGLContext(QOpenGLContext *context) : d_ptr(new QGLContextPrivate(this)) { Q_D(QGLContext); - d->init(0,QGLFormat::fromPlatformWindowFormat(platformContext->platformWindowFormat())); - d->platformContext = platformContext; - d->platformContext->setQGLContextHandle(this,qDeleteQGLContext); - d->valid = true; + d->init(0, QGLFormat::fromSurfaceFormat(context->format())); + d->guiGlContext = context; + d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext); + d->ownContext = false; + d->valid = context->isValid(); d->setupSharing(); } +QOpenGLContext *QGLContext::contextHandle() const +{ + Q_D(const QGLContext); + return d->guiGlContext; +} + /*! - Returns a OpenGL context for the platform-specific OpenGL context given by - \a platformContext. + Returns a OpenGL context for the window context specified by \a windowContext */ -QGLContext *QGLContext::fromPlatformGLContext(QPlatformGLContext *platformContext) +QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context) { - if (!platformContext) + if (!context) return 0; - if (platformContext->qGLContextHandle()) { - return reinterpret_cast<QGLContext *>(platformContext->qGLContextHandle()); + if (context->qGLContextHandle()) { + return reinterpret_cast<QGLContext *>(context->qGLContextHandle()); } - QGLContext *glContext = new QGLContext(platformContext); + QGLContext *glContext = new QGLContext(context); //Dont call create on context. This can cause the platformFormat to be set on the widget, which //will cause the platformWindow to be recreated. return glContext; diff --git a/src/opengl/qgl_qws.cpp b/src/opengl/qgl_qws.cpp deleted file mode 100644 index c0844786e2..0000000000 --- a/src/opengl/qgl_qws.cpp +++ /dev/null @@ -1,318 +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_egl_p.h" -#include "qglpixelbuffer.h" - -#include <qglscreen_qws.h> -#include <qscreenproxy_qws.h> -#include <private/qglwindowsurface_qws_p.h> - -#include <private/qbackingstore_p.h> -#include <private/qfont_p.h> -#include <private/qfontengine_p.h> -#include <private/qgl_p.h> -#include <private/qpaintengine_opengl_p.h> -#include <qpixmap.h> -#include <qtimer.h> -#include <qapplication.h> -#include <qstack.h> -#include <qdesktopwidget.h> -#include <qdebug.h> -#include <qvarlengtharray.h> - -QT_BEGIN_NAMESPACE - -static QGLScreen *glScreenForDevice(QPaintDevice *device) -{ - QScreen *screen = qt_screen; - if (screen->classId() == QScreen::MultiClass) { - int screenNumber; - if (device && device->devType() == QInternal::Widget) - screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device)); - else - screenNumber = 0; - screen = screen->subScreens()[screenNumber]; - } - while (screen->classId() == QScreen::ProxyClass || - screen->classId() == QScreen::TransformedClass) { - screen = static_cast<QProxyScreen *>(screen)->screen(); - } - if (screen->classId() == QScreen::GLClass) - return static_cast<QGLScreen *>(screen); - else - return 0; -} - -/* - 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; -} - -/***************************************************************************** - QOpenGL debug facilities - *****************************************************************************/ -//#define DEBUG_OPENGL_REGION_UPDATE - -bool QGLFormat::hasOpenGLOverlays() -{ - QGLScreen *glScreen = glScreenForDevice(0); - if (glScreen) - return (glScreen->options() & QGLScreen::Overlays); - else - return false; -} - -static EGLSurface qt_egl_create_surface - (QEglContext *context, QPaintDevice *device, - const QEglProperties *properties = 0) -{ - // Get the screen surface functions, which are used to create native ids. - QGLScreen *glScreen = glScreenForDevice(device); - if (!glScreen) - return EGL_NO_SURFACE; - QGLScreenSurfaceFunctions *funcs = glScreen->surfaceFunctions(); - if (!funcs) - return EGL_NO_SURFACE; - - // Create the native drawable for the paint device. - int devType = device->devType(); - EGLNativePixmapType pixmapDrawable = 0; - EGLNativeWindowType windowDrawable = 0; - bool ok; - if (devType == QInternal::Pixmap) { - ok = funcs->createNativePixmap(static_cast<QPixmap *>(device), &pixmapDrawable); - } else if (devType == QInternal::Image) { - ok = funcs->createNativeImage(static_cast<QImage *>(device), &pixmapDrawable); - } else { - ok = funcs->createNativeWindow(static_cast<QWidget *>(device), &windowDrawable); - } - if (!ok) { - qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); - return EGL_NO_SURFACE; - } - - // Create the EGL surface to draw into, based on the native drawable. - const int *props; - if (properties) - props = properties->properties(); - else - props = 0; - EGLSurface surf; - if (devType == QInternal::Widget) { - surf = eglCreateWindowSurface - (context->display(), context->config(), windowDrawable, props); - } else { - surf = eglCreatePixmapSurface - (context->display(), context->config(), pixmapDrawable, props); - } - if (surf == EGL_NO_SURFACE) - qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); - return surf; -} - -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<QGLContext *>(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. We cannot use - // QEglContext::createSurface() because it does not have - // access to the QGLScreen. - d->eglSurface = qt_egl_create_surface(d->eglContext, device()); - if (d->eglSurface == EGL_NO_SURFACE) { - delete d->eglContext; - d->eglContext = 0; - return false; - } - - return true; -} - - -bool QGLWidget::event(QEvent *e) -{ - return QWidget::event(e); -} - - -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(d->glcx) - d->glcx->doneCurrent(); - QGLContext* oldcx = d->glcx; - d->glcx = context; - if(!d->glcx->isValid()) - d->glcx->create(shareContext ? shareContext : oldcx); - if(deleteOldContext) - delete oldcx; -} - -void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget* shareWidget) -{ - Q_Q(QGLWidget); - - QGLScreen *glScreen = glScreenForDevice(q); - if (glScreen) { - wsurf = static_cast<QWSGLWindowSurface*>(glScreen->createSurface(q)); - q->setWindowSurface(wsurf); - } - - 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 &) -{ -} - -QT_END_NAMESPACE diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp deleted file mode 100644 index bc65bcd44a..0000000000 --- a/src/opengl/qgl_symbian.cpp +++ /dev/null @@ -1,472 +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 <fbs.h> -#include <private/qt_s60_p.h> -#include <private/qpixmap_s60_p.h> -#include <private/qimagepixmapcleanuphooks_p.h> -#include <private/qgl_p.h> -#include <private/qpaintengine_opengl_p.h> -#include <private/qwidget_p.h> // to access QWExtra -#include <private/qnativeimagehandleprovider_p.h> -#include "qgl_egl_p.h" -#include "qpixmapdata_gl_p.h" -#include "qgltexturepool_p.h" -#include "qcolormap.h" -#include <QDebug> - -QT_BEGIN_NAMESPACE - -// Turn off "direct to window" rendering if EGL cannot support it. -#if !defined(EGL_RENDER_BUFFER) || !defined(EGL_SINGLE_BUFFER) -#if defined(QGL_DIRECT_TO_WINDOW) -#undef QGL_DIRECT_TO_WINDOW -#endif -#endif - -// Determine if preserved window contents should be used. -#if !defined(EGL_SWAP_BEHAVIOR) || !defined(EGL_BUFFER_PRESERVED) -#if !defined(QGL_NO_PRESERVED_SWAP) -#define QGL_NO_PRESERVED_SWAP 1 -#endif -#endif - -extern int qt_gl_pixmap_serial; - -/* - QGLTemporaryContext implementation -*/ - - -class QGLTemporaryContextPrivate -{ -public: - bool initialized; - RWindow *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; - - d->display = 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; - } - - d->window = new RWindow(CCoeEnv::Static()->WsSession()); - d->window->Construct(CCoeEnv::Static()->RootWin(),(uint)this); - - d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL); - - if (d->surface == EGL_NO_SURFACE) { - qWarning("QGLTemporaryContext: Error creating EGL surface."); - delete d->window; - d->window = 0; - 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."); - d->window = 0; - return; - } -} - -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); - delete d->window; - } -} - -bool QGLFormat::hasOpenGLOverlays() -{ - return false; -} - -// Chooses the EGL config and creates the EGL context -bool QGLContext::chooseContext(const QGLContext* shareContext) // almost same as in qgl_x11egl.cpp -{ - Q_D(QGLContext); - - if (!device()) - return false; - - int devType = device()->devType(); - - if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) { - qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType); - return false; - } - - // Get the display and initialize it. - 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<QWidget*>(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.setPaintDeviceFormat(device()); - configProps.setRenderableType(QEgl::OpenGL); - configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_SWAP_BEHAVIOR_PRESERVED_BIT); - - qt_eglproperties_set_glformat(configProps, d->glFormat); - - 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<QGLContext *>(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 - // 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); - - d->eglSurface = QEgl::createSurface(device(), d->eglContext->config()); - - eglGetError(); // Clear error state first. - -#ifdef QGL_NO_PRESERVED_SWAP - eglSurfaceAttrib(QEgl::display(), d->eglSurface, - EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); - - if (eglGetError() != EGL_SUCCESS) - qWarning("QGLContext: could not enable destroyed swap behaviour"); -#else - eglSurfaceAttrib(QEgl::display(), d->eglSurface, - EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); - - if (eglGetError() != EGL_SUCCESS) - qWarning("QGLContext: could not enable preserved swap behaviour"); -#endif - - setWindowCreated(true); - } - - return true; -} - -void QGLWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QGLWidget); - if (!isValid()) - return; - - if (QGLContext::currentContext()) - doneCurrent(); - - // Symbian needs to recreate the surface on resize. - d->recreateEglSurface(); - - 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 &) -{ -} - -void QGLWidgetPrivate::recreateEglSurface() -{ - Q_Q(QGLWidget); - - WId currentId = q->winId(); - - if (glcx->d_func()->eglSurface != EGL_NO_SURFACE) { - eglDestroySurface(glcx->d_func()->eglContext->display(), - glcx->d_func()->eglSurface); - } - - glcx->d_func()->eglSurface = QEgl::createSurface(glcx->device(), - glcx->d_func()->eglContext->config()); - -#if !defined(QGL_NO_PRESERVED_SWAP) - eglGetError(); // Clear error state first. - eglSurfaceAttrib(QEgl::display(), glcx->d_func()->eglSurface, - EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); - if (eglGetError() != EGL_SUCCESS) { - qWarning("QGLContext: could not enable preserved swap"); - } -#endif - - eglSurfaceWindowId = currentId; -} - -static inline bool knownGoodFormat(QImage::Format format) -{ - switch (format) { - case QImage::Format_RGB16: // EColor64K - case QImage::Format_RGB32: // EColor16MU - case QImage::Format_ARGB32_Premultiplied: // EColor16MAP - return true; - default: - return false; - } -} - -void QGLPixmapData::fromNativeType(void* pixmap, NativeType type) -{ - if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap); - QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight); - if (size.width() == w && size.height() == h) - setSerialNumber(++qt_gl_pixmap_serial); - resize(size.width(), size.height()); - m_source = QVolatileImage(bitmap); - if (pixelType() == BitmapType) { - m_source.ensureFormat(QImage::Format_MonoLSB); - } else if (!knownGoodFormat(m_source.format())) { - m_source.beginDataAccess(); - QImage::Format format = idealFormat(m_source.imageRef(), Qt::AutoColor); - m_source.endDataAccess(true); - m_source.ensureFormat(format); - } - m_hasAlpha = m_source.hasAlphaChannel(); - m_hasFillColor = false; - m_dirty = true; - - } else if (type == QPixmapData::VolatileImage && pixmap) { - // Support QS60Style in more efficient skin graphics retrieval. - QVolatileImage *img = static_cast<QVolatileImage *>(pixmap); - if (img->width() == w && img->height() == h) - setSerialNumber(++qt_gl_pixmap_serial); - resize(img->width(), img->height()); - m_source = *img; - m_hasAlpha = m_source.hasAlphaChannel(); - m_hasFillColor = false; - m_dirty = true; - } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) { - destroyTexture(); - nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap); - // Cannot defer the retrieval, we need at least the size right away. - createFromNativeImageHandleProvider(); - } -} - -void* QGLPixmapData::toNativeType(NativeType type) -{ - if (type == QPixmapData::FbsBitmap) { - if (m_source.isNull()) - m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied); - return m_source.duplicateNativeImage(); - } - - return 0; -} - -bool QGLPixmapData::initFromNativeImageHandle(void *handle, const QString &type) -{ - if (type == QLatin1String("RSgImage")) { - fromNativeType(handle, QPixmapData::SgImage); - return true; - } else if (type == QLatin1String("CFbsBitmap")) { - fromNativeType(handle, QPixmapData::FbsBitmap); - return true; - } - return false; -} - -void QGLPixmapData::createFromNativeImageHandleProvider() -{ - void *handle = 0; - QString type; - nativeImageHandleProvider->get(&handle, &type); - if (handle) { - if (initFromNativeImageHandle(handle, type)) { - nativeImageHandle = handle; - nativeImageType = type; - } else { - qWarning("QGLPixmapData: Unknown native image type '%s'", qPrintable(type)); - } - } else { - qWarning("QGLPixmapData: Native handle is null"); - } -} - -void QGLPixmapData::releaseNativeImageHandle() -{ - if (nativeImageHandleProvider && nativeImageHandle) { - nativeImageHandleProvider->release(nativeImageHandle, nativeImageType); - nativeImageHandle = 0; - nativeImageType = QString(); - } -} - -QT_END_NAMESPACE 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 <qgl.h> -#include <qlist.h> -#include <qmap.h> -#include <qpixmap.h> -#include <qevent.h> -#include <private/qgl_p.h> -#include <qcolormap.h> -#include <qvarlengtharray.h> -#include <qdebug.h> -#include <qcolor.h> - -#include <qt_windows.h> - -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<uint> colorArray; - QVector<quint8> allocArray; - QVector<quint8> contextArray; - QMap<uint,int> 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<uint,int>::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<int> iAttributes(40); - QVarLengthArray<int> 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<QGLContext *>(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<QPixmap *>(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<QWidget *>(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<int> 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<QPixmap *>(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<QWidget *>(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 <qgl.h> -#include <qlist.h> -#include <qmap.h> -#include <qpixmap.h> -#include <qevent.h> -#include <private/qgl_p.h> -#include <qcolormap.h> -#include <qvarlengtharray.h> -#include <qdebug.h> -#include <qapplication.h> -#include <qdesktopwidget> - -#include <windows.h> - -#include <private/qeglproperties_p.h> -#include <private/qeglcontext_p.h> -#include <private/qgl_egl_p.h> - - -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<uint> colorArray; - QVector<quint8> allocArray; - QVector<quint8> contextArray; - QMap<uint,int> colorMap; -}; - -/***************************************************************************** - QColorMap class - temporarily here, until it is ready for prime time - *****************************************************************************/ - -/**************************************************************************** -** -** Definition of QColorMap class -** -****************************************************************************/ - -#ifndef QGLCMAP_H -#define QGLCMAP_H - -#include <qcolor.h> - -/* - 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<QGLContext *>(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<uint,int>::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<QWidget *>(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 22a222eb1b..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 <private/qfontengine_ft_p.h> -#include <private/qt_x11_p.h> -#include <private/qpixmap_x11_p.h> -#include <private/qimagepixmapcleanuphooks_p.h> -#include <private/qunicodetables_p.h> -#ifdef Q_OS_HPUX -// for GLXPBuffer -#include <private/qglpixelbuffer_p.h> -#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 <GL/glx.h> -#undef INT8 -#undef INT32 - -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xos.h> -#ifdef Q_OS_VXWORS -# ifdef open -# undef open -# endif -# ifdef getpid -# undef getpid -# endif -#endif // Q_OS_VXWORKS -#include <X11/Xatom.h> - -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) -#include <dlfcn.h> -#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<int, QCMapEntry *> CMapEntryHash; -typedef QHash<int, QMap<int, QRgb> > 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<int, QCMapEntry *>::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<QTransColor> 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<QWidget*>(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<QGLContext *>(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<QWidget*>(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<QWidget *>(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<int, QRgb> &cmap = (*cmap_handler()->qglcmap_hash)[(long)info->visualid]; - - // already in the map? - QRgb target = c.rgb(); - QMap<int, QRgb>::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<QFontEngineMulti *>(engine)->engine(0); -#ifndef QT_NO_FONTCONFIG - if(engine->type() == QFontEngine::Freetype) { - qgl_use_font(static_cast<QFontEngineFT *>(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<Font>(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<const GLubyte *>(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; i++) { - if (cmw[i] == winId()) { // replace old window - cmw[i] = w; - break; - } - } - if (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); - - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); - Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); - - // We can't use TFP if the pixmap has a separate X11 mask - if (pixmapData->x11_mask) - return 0; - - if (!qt_resolveTextureFromPixmap(paintDevice)) - return 0; - - const QX11Info &x11Info = pixmapData->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 = pixmapData->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 (pixmapData->gl_surface && - hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) - { - // Surface is invalid! - destroyGlSurfaceForPixmap(pixmapData); - } - - // Check to see if we need a surface - if (!pixmapData->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, - pixmapData->handle(), pixmapAttribs); - - if (!glxPixmap) - return 0; - - pixmapData->gl_surface = (void*)glxPixmap; - - // Make sure the cleanup hook gets called so we can delete the glx pixmap - QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); - } - - GLuint textureId; - glGenTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); - glXBindTexImageEXT(x11Info.display(), (GLXPixmap)pixmapData->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) - pixmapData->flags |= QX11PixmapData::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(QPixmapData* pmd) -{ -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); - if (pixmapData->gl_surface) { - glXDestroyPixmap(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface); - pixmapData->gl_surface = 0; - } -#endif -} - -void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd) -{ -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - Q_ASSERT(QGLContext::currentContext()); - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); - if (pixmapData->gl_surface) - glXReleaseTexImageEXT(QX11Info::display(), (GLXPixmap)pixmapData->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 4dd7fc2f5d..0000000000 --- a/src/opengl/qgl_x11egl.cpp +++ /dev/null @@ -1,562 +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 <private/qt_x11_p.h> -#include <private/qpixmap_x11_p.h> -#include <private/qgl_p.h> -#include <private/qpaintengine_opengl_p.h> -#include "qgl_egl_p.h" -#include "qcolormap.h" -#include <QDebug> -#include <QPixmap> - - -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(); - - QX11PixmapData *x11PixmapData = 0; - if (devType == QInternal::Pixmap) { - QPixmapData *pmd = static_cast<QPixmap*>(device())->data_ptr().data(); - if (pmd->classId() == QPixmapData::X11Class) - x11PixmapData = static_cast<QX11PixmapData*>(pmd); - else { - // TODO: Replace the pixmap's data with a new QX11PixmapData - 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<QWidget*>(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<QGLWidget*>(static_cast<QWidget*>(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<QGLContext *>(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 QX11PixmapData::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 (x11PixmapData) { - // TODO: Actually check to see if the existing surface can be re-used - if (x11PixmapData->gl_surface) - eglDestroySurface(d->eglContext->display(), (EGLSurface)x11PixmapData->gl_surface); - - x11PixmapData->gl_surface = (void*)QEgl::createSurface(device(), d->eglContext->config()); - } - - return true; -} - -void *QGLContext::chooseVisual() -{ - qFatal("QGLContext::chooseVisual - this method must not be called as Qt is built with EGL support"); - return 0; -} - -void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth) -{ - Q_UNUSED(f); - Q_UNUSED(bufDepth); - qFatal("QGLContext::tryVisual - this method must not be called as Qt is built with EGL support"); - return 0; -} - -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; - - - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); - Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); - bool hasAlpha = pixmapData->hasAlphaChannel(); - bool pixmapHasValidSurface = false; - bool textureIsBound = false; - GLuint textureId; - glGenTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); - - if (haveTFP && pixmapData->gl_surface && - hasAlpha == (pixmapData->flags & QX11PixmapData::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)pixmapData->gl_surface, EGL_BACK_BUFFER); - if (success == EGL_FALSE) { - qWarning() << "eglBindTexImage() failed:" << QEgl::errorString(); - eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); - pixmapData->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 (pixmapData->gl_surface && - hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) - { - // Surface is invalid! - destroyGlSurfaceForPixmap(pixmapData); - } - - if (pixmapData->gl_surface == 0) { - EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, - QEgl::OpenGL, - hasAlpha ? QEgl::Translucent : QEgl::NoOptions); - - pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config); - if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) - return false; - } - - EGLBoolean success; - success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER); - if (success == EGL_FALSE) { - qWarning() << "eglBindTexImage() failed:" << QEgl::errorString(); - eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); - pixmapData->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); - pixmapData->flags |= QX11PixmapData::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(QPixmapData* pmd) -{ - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); - if (pixmapData->gl_surface) { - EGLBoolean success; - success = eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); - if (success == EGL_FALSE) { - qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: " - << QEgl::errorString(); - } - pixmapData->gl_surface = 0; - } -} - -void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd) -{ - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); - if (pixmapData->gl_surface) { - EGLBoolean success; - success = eglReleaseTexImage(QEgl::display(), - (EGLSurface)pixmapData->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..c1128a0ebd 100644 --- a/src/opengl/qglbuffer.cpp +++ b/src/opengl/qglbuffer.cpp @@ -141,7 +141,7 @@ public: QAtomicInt ref; QGLBuffer::Type type; - QGLSharedResourceGuard guard; + QGLSharedResourceGuardBase *guard; QGLBuffer::UsagePattern usagePattern; QGLBuffer::UsagePattern actualUsagePattern; }; @@ -184,7 +184,7 @@ QGLBuffer::QGLBuffer(const QGLBuffer &other) d_ptr->ref.ref(); } -#define ctx d->guard.context() +#define ctx QGLContext::currentContext(); /*! Destroys this buffer object, including the storage being @@ -245,21 +245,19 @@ 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 +namespace { + void freeBufferFunc(QGLContext *ctx, GLuint id) + { + Q_UNUSED(ctx); + glDeleteBuffers(1, &id); + } +} + /*! Creates the buffer object in the GL server. Returns true if the object was created; false otherwise. @@ -276,24 +274,26 @@ void QGLBuffer::setUsagePattern(QGLBuffer::UsagePattern value) bool QGLBuffer::create() { Q_D(QGLBuffer); - if (d->guard.id()) + if (d->guard && d->guard->id()) return true; - const QGLContext *ctx = QGLContext::currentContext(); + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); if (ctx) { - if (!qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx))) + if (!qt_resolve_buffer_extensions(ctx)) return false; GLuint bufferId = 0; glGenBuffers(1, &bufferId); if (bufferId) { - d->guard.setContext(ctx); - d->guard.setId(bufferId); + if (d->guard) + d->guard->free(); + + d->guard = createSharedResourceGuard(ctx, bufferId, freeBufferFunc); return true; } } return false; } -#define ctx d->guard.context() +#define ctx QGLContext::currentContext() /*! Returns true if this buffer has been created; false otherwise. @@ -303,7 +303,7 @@ bool QGLBuffer::create() bool QGLBuffer::isCreated() const { Q_D(const QGLBuffer); - return d->guard.id() != 0; + return d->guard && d->guard->id(); } /*! @@ -314,14 +314,10 @@ bool QGLBuffer::isCreated() const void QGLBuffer::destroy() { Q_D(QGLBuffer); - GLuint bufferId = d->guard.id(); - if (bufferId) { - // Switch to the original creating context to destroy it. - QGLShareContextScope scope(d->guard.context()); - glDeleteBuffers(1, &bufferId); + if (d->guard) { + d->guard->free(); + d->guard = 0; } - d->guard.setId(0); - d->guard.setContext(0); } /*! @@ -338,7 +334,7 @@ bool QGLBuffer::read(int offset, void *data, int count) { #if !defined(QT_OPENGL_ES) Q_D(QGLBuffer); - if (!glGetBufferSubData || !d->guard.id()) + if (!glGetBufferSubData || !d->guard->id()) return false; while (glGetError() != GL_NO_ERROR) ; // Clear error state. glGetBufferSubData(d->type, offset, count, data); @@ -368,7 +364,7 @@ void QGLBuffer::write(int offset, const void *data, int count) qWarning("QGLBuffer::allocate(): buffer not created"); #endif Q_D(QGLBuffer); - if (d->guard.id()) + if (d->guard && d->guard->id()) glBufferSubData(d->type, offset, count, data); } @@ -388,7 +384,7 @@ void QGLBuffer::allocate(const void *data, int count) qWarning("QGLBuffer::allocate(): buffer not created"); #endif Q_D(QGLBuffer); - if (d->guard.id()) + if (d->guard && d->guard->id()) glBufferData(d->type, count, data, d->actualUsagePattern); } @@ -423,10 +419,9 @@ bool QGLBuffer::bind() qWarning("QGLBuffer::bind(): buffer not created"); #endif Q_D(const QGLBuffer); - GLuint bufferId = d->guard.id(); + GLuint bufferId = d->guard ? d->guard->id() : 0; if (bufferId) { - if (!QGLContext::areSharing(QGLContext::currentContext(), - d->guard.context())) { + if (d->guard->group() != QOpenGLContextGroup::currentContextGroup()) { #ifndef QT_NO_DEBUG qWarning("QGLBuffer::bind: buffer is not valid in the current context"); #endif @@ -455,7 +450,7 @@ void QGLBuffer::release() qWarning("QGLBuffer::release(): buffer not created"); #endif Q_D(const QGLBuffer); - if (d->guard.id()) + if (d->guard && d->guard->id()) glBindBuffer(d->type, 0); } @@ -481,7 +476,7 @@ void QGLBuffer::release(QGLBuffer::Type type) glBindBuffer(GLenum(type), 0); } -#define ctx d->guard.context() +#define ctx QGLContext::currentContext() /*! Returns the GL identifier associated with this buffer; zero if @@ -492,7 +487,7 @@ void QGLBuffer::release(QGLBuffer::Type type) GLuint QGLBuffer::bufferId() const { Q_D(const QGLBuffer); - return d->guard.id(); + return d->guard ? d->guard->id() : 0; } #ifndef GL_BUFFER_SIZE @@ -511,7 +506,7 @@ GLuint QGLBuffer::bufferId() const int QGLBuffer::size() const { Q_D(const QGLBuffer); - if (!d->guard.id()) + if (!d->guard || !d->guard->id()) return -1; GLint value = -1; glGetBufferParameteriv(d->type, GL_BUFFER_SIZE, &value); @@ -539,7 +534,7 @@ void *QGLBuffer::map(QGLBuffer::Access access) if (!isCreated()) qWarning("QGLBuffer::map(): buffer not created"); #endif - if (!d->guard.id()) + if (!d->guard || !d->guard->id()) return 0; if (!glMapBufferARB) return 0; @@ -566,7 +561,7 @@ bool QGLBuffer::unmap() if (!isCreated()) qWarning("QGLBuffer::unmap(): buffer not created"); #endif - if (!d->guard.id()) + if (!d->guard || !d->guard->id()) return false; if (!glUnmapBufferARB) return false; 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..991fbba8c7 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 <QtGui/private/qegl_p.h> -#endif - #include <QtCore/qglobal.h> #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,26 +854,16 @@ 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); +bool qt_resolve_buffer_extensions(QGLContext *ctx); bool qt_resolve_version_1_3_functions(QGLContext *ctx); -bool Q_OPENGL_EXPORT qt_resolve_version_2_0_functions(QGLContext *ctx); +bool qt_resolve_version_2_0_functions(QGLContext *ctx); bool qt_resolve_stencil_face_extension(QGLContext *ctx); 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 682c26255d..5e140ab9da 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -45,24 +45,17 @@ #include <qdebug.h> #include <private/qgl_p.h> #include <private/qfont_p.h> -#if !defined(QT_OPENGL_ES_1) -#include <private/qpaintengineex_opengl2_p.h> -#endif - -#ifndef QT_OPENGL_ES_2 -#include <private/qpaintengine_opengl_p.h> -#endif +#include "gl2paintengineex/qpaintengineex_opengl2_p.h" -#include <qglframebufferobject.h> #include <qlibrary.h> #include <qimage.h> QT_BEGIN_NAMESPACE -extern Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize&, bool, bool); +extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool); -#define QGL_FUNC_CONTEXT const QGLContext *ctx = d_ptr->fbo_guard.context(); -#define QGL_FUNCP_CONTEXT const QGLContext *ctx = fbo_guard.context(); +#define QGL_FUNC_CONTEXT const QGLContext *ctx = QGLContext::currentContext(); +#define QGL_FUNCP_CONTEXT const QGLContext *ctx = QGLContext::currentContext(); #ifndef QT_NO_DEBUG #define QT_RESET_GLERROR() \ @@ -306,22 +299,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. @@ -373,13 +350,7 @@ void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f, QGLContext *QGLFBOGLPaintDevice::context() const { - QGLContext *fboContext = const_cast<QGLContext *>(fbo->d_ptr->fbo_guard.context()); - QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext()); - - if (QGLContextPrivate::contextGroup(fboContext) == QGLContextPrivate::contextGroup(currentContext)) - return currentContext; - else - return fboContext; + return const_cast<QGLContext *>(QGLContext::currentContext()); } bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const @@ -429,13 +400,33 @@ bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const return false; } +namespace +{ + void freeFramebufferFunc(QGLContext *ctx, GLuint id) + { + Q_UNUSED(ctx); + glDeleteFramebuffers(1, &id); + } + + void freeRenderbufferFunc(QGLContext *ctx, GLuint id) + { + Q_UNUSED(ctx); + glDeleteRenderbuffers(1, &id); + } + + void freeTextureFunc(QGLContext *ctx, GLuint id) + { + Q_UNUSED(ctx); + glDeleteTextures(1, &id); + } +} + void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, QGLFramebufferObject::Attachment attachment, GLenum texture_target, GLenum internal_format, GLint samples, bool mipmap) { QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); - fbo_guard.setContext(ctx); bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx))) @@ -449,9 +440,11 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, GLuint fbo = 0; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo); - fbo_guard.setId(fbo); - glDevice.setFBO(q, attachment); + GLuint texture = 0; + GLuint color_buffer = 0; + GLuint depth_buffer = 0; + GLuint stencil_buffer = 0; QT_CHECK_GLERROR(); // init texture @@ -625,7 +618,21 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, } glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); - if (!valid) { + if (valid) { + fbo_guard = createSharedResourceGuard(ctx, fbo, freeFramebufferFunc); + if (color_buffer) + color_buffer_guard = createSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc); + else + texture_guard = createSharedResourceGuard(ctx, texture, freeTextureFunc); + if (depth_buffer) + depth_buffer_guard = createSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc); + if (stencil_buffer) { + if (stencil_buffer == depth_buffer) + stencil_buffer_guard = depth_buffer_guard; + else + stencil_buffer_guard = createSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc); + } + } else { if (color_buffer) glDeleteRenderbuffers(1, &color_buffer); else @@ -635,7 +642,6 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, if (stencil_buffer && depth_buffer != stencil_buffer) glDeleteRenderbuffers(1, &stencil_buffer); glDeleteFramebuffers(1, &fbo); - fbo_guard.setId(0); } QT_CHECK_GLERROR(); @@ -644,6 +650,8 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, format.setAttachment(fbo_attachment); format.setInternalTextureFormat(internal_format); format.setMipmap(mipmap); + + glDevice.setFBO(q, attachment); } /*! @@ -720,8 +728,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 +787,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 +829,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 +850,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 +871,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() @@ -914,23 +879,19 @@ QGLFramebufferObject::QGLFramebufferObject(const QSize &size, Attachment attachm QGLFramebufferObject::~QGLFramebufferObject() { Q_D(QGLFramebufferObject); - QGL_FUNC_CONTEXT; delete d->engine; - if (isValid() && ctx) { - QGLShareContextScope scope(ctx); - if (d->texture) - glDeleteTextures(1, &d->texture); - if (d->color_buffer) - glDeleteRenderbuffers(1, &d->color_buffer); - if (d->depth_buffer) - glDeleteRenderbuffers(1, &d->depth_buffer); - if (d->stencil_buffer && d->stencil_buffer != d->depth_buffer) - glDeleteRenderbuffers(1, &d->stencil_buffer); - GLuint fbo = d->fbo(); - glDeleteFramebuffers(1, &fbo); - } + if (d->texture_guard) + d->texture_guard->free(); + if (d->color_buffer_guard) + d->color_buffer_guard->free(); + if (d->depth_buffer_guard) + d->depth_buffer_guard->free(); + if (d->stencil_buffer_guard && d->stencil_buffer_guard != d->depth_buffer_guard) + d->stencil_buffer_guard->free(); + if (d->fbo_guard) + d->fbo_guard->free(); } /*! @@ -954,7 +915,7 @@ QGLFramebufferObject::~QGLFramebufferObject() bool QGLFramebufferObject::isValid() const { Q_D(const QGLFramebufferObject); - return d->valid && d->fbo_guard.context(); + return d->valid && d->fbo_guard && d->fbo_guard->id(); } /*! @@ -1037,7 +998,7 @@ bool QGLFramebufferObject::release() GLuint QGLFramebufferObject::texture() const { Q_D(const QGLFramebufferObject); - return d->texture; + return d->texture_guard ? d->texture_guard->id() : 0; } /*! @@ -1092,13 +1053,7 @@ QImage QGLFramebufferObject::toImage() const return image; } -#if !defined(QT_OPENGL_ES_1) Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine) -#endif - -#ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_buffer_engine) -#endif /*! \reimp */ QPaintEngine *QGLFramebufferObject::paintEngine() const @@ -1107,29 +1062,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 +1127,6 @@ void QGLFramebufferObject::drawTexture(const QRectF &target, GLuint textureId, G const_cast<QGLContext *>(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 *>(QGLContext::currentContext())->drawTexture(target, textureId, textureTarget); -} -#endif - /*! \since 4.4 @@ -1212,14 +1142,6 @@ void QGLFramebufferObject::drawTexture(const QPointF &point, GLuint textureId, G const_cast<QGLContext *>(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 *>(QGLContext::currentContext())->drawTexture(point, textureId, textureTarget); -} -#endif - /*! \reimp */ int QGLFramebufferObject::metric(PaintDeviceMetric metric) const { @@ -1370,10 +1292,12 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q return; const QGLContext *ctx = QGLContext::currentContext(); - if (!ctx) + if (!ctx || !ctx->contextHandle()) return; - const int height = ctx->device()->height(); + QSurface *surface = ctx->contextHandle()->surface(); + + const int height = static_cast<QWindow *>(surface)->height(); const int sh = source ? source->height() : height; const int th = target ? target->height() : height; 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/qglframebufferobject_p.h b/src/opengl/qglframebufferobject_p.h index f82361279d..61d39c6a07 100644 --- a/src/opengl/qglframebufferobject_p.h +++ b/src/opengl/qglframebufferobject_p.h @@ -130,8 +130,9 @@ private: class QGLFramebufferObjectPrivate { public: - QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_buffer(0), stencil_buffer(0) - , color_buffer(0), valid(false), engine(0) {} + QGLFramebufferObjectPrivate() : fbo_guard(0), texture_guard(0), depth_buffer_guard(0) + , stencil_buffer_guard(0), color_buffer_guard(0) + , valid(false), engine(0) {} ~QGLFramebufferObjectPrivate() {} void init(QGLFramebufferObject *q, const QSize& sz, @@ -139,11 +140,11 @@ public: GLenum internal_format, GLenum texture_target, GLint samples = 0, bool mipmap = false); bool checkFramebufferStatus() const; - QGLSharedResourceGuard fbo_guard; - GLuint texture; - GLuint depth_buffer; - GLuint stencil_buffer; - GLuint color_buffer; + QGLSharedResourceGuardBase *fbo_guard; + QGLSharedResourceGuardBase *texture_guard; + QGLSharedResourceGuardBase *depth_buffer_guard; + QGLSharedResourceGuardBase *stencil_buffer_guard; + QGLSharedResourceGuardBase *color_buffer_guard; GLenum target; QSize size; QGLFramebufferObjectFormat format; @@ -152,7 +153,7 @@ public: mutable QPaintEngine *engine; QGLFBOGLPaintDevice glDevice; - inline GLuint fbo() const { return fbo_guard.id(); } + inline GLuint fbo() const { return fbo_guard ? fbo_guard->id() : 0; } }; diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp index 02e7091c9e..227e6cc176 100644 --- a/src/opengl/qglfunctions.cpp +++ b/src/opengl/qglfunctions.cpp @@ -41,6 +41,7 @@ #include "qglfunctions.h" #include "qgl_p.h" +#include "QtGui/private/qopenglcontext_p.h" QT_BEGIN_NAMESPACE @@ -139,25 +140,28 @@ QT_BEGIN_NAMESPACE */ // Hidden private fields for additional extension data. -struct QGLFunctionsPrivateEx : public QGLFunctionsPrivate +struct QGLFunctionsPrivateEx : public QGLFunctionsPrivate, public QOpenGLSharedResource { - QGLFunctionsPrivateEx(const QGLContext *context = 0) - : QGLFunctionsPrivate(context) + QGLFunctionsPrivateEx(QOpenGLContext *context) + : QGLFunctionsPrivate(QGLContext::fromOpenGLContext(context)) + , QOpenGLSharedResource(context->shareGroup()) , m_features(-1) {} + void invalidateResource() + { + m_features = -1; + } + + void freeResource(QOpenGLContext *) + { + // no gl resources to free + } + int m_features; }; -#if QT_VERSION >= 0x040800 -Q_GLOBAL_STATIC(QGLContextGroupResource<QGLFunctionsPrivateEx>, qt_gl_functions_resource) -#else -static void qt_gl_functions_free(void *data) -{ - delete reinterpret_cast<QGLFunctionsPrivateEx *>(data); -} +Q_GLOBAL_STATIC(QOpenGLMultiGroupSharedResource, qt_gl_functions_resource) -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gl_functions_resource, (qt_gl_functions_free)) -#endif static QGLFunctionsPrivateEx *qt_gl_functions(const QGLContext *context = 0) { if (!context) @@ -165,13 +169,7 @@ static QGLFunctionsPrivateEx *qt_gl_functions(const QGLContext *context = 0) Q_ASSERT(context); QGLFunctionsPrivateEx *funcs = reinterpret_cast<QGLFunctionsPrivateEx *> - (qt_gl_functions_resource()->value(context)); -#if QT_VERSION < 0x040800 - if (!funcs) { - funcs = new QGLFunctionsPrivateEx(); - qt_gl_functions_resource()->insert(context, funcs); - } -#endif + (qt_gl_functions_resource()->value<QGLFunctionsPrivateEx>(context->contextHandle())); return funcs; } 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/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp index b4e12d8b7e..08807bdd49 100644 --- a/src/opengl/qglpaintdevice.cpp +++ b/src/opengl/qglpaintdevice.cpp @@ -43,14 +43,6 @@ #include <private/qgl_p.h> #include <private/qglpixelbuffer_p.h> #include <private/qglframebufferobject_p.h> -#ifdef Q_WS_X11 -#include <private/qpixmapdata_x11gl_p.h> -#endif - -#if !defined(QT_OPENGL_ES_1) -#include <private/qpixmapdata_gl_p.h> -#include <private/qwindowsurface_gl_p.h> -#endif QT_BEGIN_NAMESPACE @@ -220,19 +212,7 @@ QGLPaintDevice* QGLPaintDevice::getDevice(QPaintDevice* pd) glpd = &(static_cast<QGLFramebufferObject*>(pd)->d_func()->glDevice); break; case QInternal::Pixmap: { -#if !defined(QT_OPENGL_ES_1) - QPixmapData* pmd = static_cast<QPixmap*>(pd)->pixmapData(); - if (pmd->classId() == QPixmapData::OpenGLClass) - glpd = static_cast<QGLPixmapData*>(pmd)->glDevice(); -#ifdef Q_WS_X11 - else if (pmd->classId() == QPixmapData::X11Class) - glpd = static_cast<QX11GLPixmapData*>(pmd); -#endif - else - qWarning("Pixmap type not supported for GL rendering"); -#else - qWarning("Pixmap render targets not supported on OpenGL ES 1.x"); -#endif + qWarning("Pixmap type not supported for GL rendering"); break; } default: diff --git a/src/opengl/qglpaintdevice_p.h b/src/opengl/qglpaintdevice_p.h index c5390645e2..32ae85dc90 100644 --- a/src/opengl/qglpaintdevice_p.h +++ b/src/opengl/qglpaintdevice_p.h @@ -55,7 +55,7 @@ #include <qpaintdevice.h> -#include <qgl.h> +#include <QtOpenGL/qgl.h> QT_BEGIN_NAMESPACE diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 45e7cdd875..ddabbef0b2 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,28 +91,16 @@ #include <QtCore/qglobal.h> -#if !defined(QT_OPENGL_ES_1) -#include <private/qpaintengineex_opengl2_p.h> -#endif +#include "gl2paintengineex/qpaintengineex_opengl2_p.h" #include <qglpixelbuffer.h> #include <private/qglpixelbuffer_p.h> #include <private/qfont_p.h> #include <qimage.h> -#ifndef QT_OPENGL_ES_2 -#include <private/qpaintengine_opengl_p.h> -#endif - QT_BEGIN_NAMESPACE -#if !defined(QT_OPENGL_ES_2) -extern void qgl_cleanup_glyph_cache(QGLContext *); -#else -void qgl_cleanup_glyph_cache(QGLContext *) {} -#endif - -extern Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize&, bool, bool); +extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool); QGLContext* QGLPBufferGLPaintDevice::context() const @@ -149,20 +136,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 } } @@ -221,7 +194,6 @@ QGLPixelBuffer::~QGLPixelBuffer() QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext()); if (current != d->qctx) makeCurrent(); - qgl_cleanup_glyph_cache(d->qctx); d->cleanup(); delete d->qctx; if (current && current != d->qctx) @@ -261,6 +233,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 +243,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 +313,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 +355,12 @@ bool QGLPixelBuffer::isValid() const return !d->invalid; } -#if !defined(QT_OPENGL_ES_1) Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine) -#endif - -#ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, 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 +431,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 +449,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 +475,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 +490,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 +504,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 dcd1a6ca71..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; @@ -109,7 +97,6 @@ private: Q_DISABLE_COPY(QGLPixelBuffer) QScopedPointer<QGLPixelBufferPrivate> d_ptr; friend class QGLDrawable; - friend class QGLWindowSurface; friend class QGLPaintDevice; friend class QGLPBufferGLPaintDevice; friend class QGLContextPrivate; 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 <qdebug.h> -#include "qglpixelbuffer.h" -#include "qglpixelbuffer_p.h" -#include "qgl_egl_p.h" - -#include <qimage.h> -#include <private/qgl_p.h> - -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 <AGL/agl.h> -#endif - -#include <qimage.h> -#include <private/qgl_p.h> -#include <qdebug.h> - -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<NSOpenGLContext *>(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<NSOpenGLContext *>(ctx) setPixelBuffer:static_cast<NSOpenGLPixelBuffer *>(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<AGLContext>(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<NSOpenGLPixelBuffer *>(pbuf) release]; - pbuf = 0; - [static_cast<NSOpenGLContext *>(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<NSOpenGLContext *>(d->share_ctx) makeCurrentContext]; - glBindTexture(GL_TEXTURE_2D, texture_id); - [static_cast<NSOpenGLContext *>(d->share_ctx) - setTextureImageToPixelBuffer:static_cast<NSOpenGLPixelBuffer *>(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<NSOpenGLContext *>(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 eb761047e7..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 <private/qgl_p.h> #include <private/qglpaintdevice_p.h> - -#if defined(Q_WS_X11) && defined(QT_NO_EGL) -#include <GL/glx.h> - -// 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_WS_WIN) -DECLARE_HANDLE(HPBUFFERARB); -#elif !defined(QT_NO_EGL) -#include <QtGui/private/qegl_p.h> -#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<QGLWidget> 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 <qglpixelbuffer.h> -#include <qgl.h> -#include <private/qgl_p.h> - -#include <private/qglpixelbuffer_p.h> - -#include <qimage.h> -#include <qdebug.h> - -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 <qlibrary.h> -#include <qdebug.h> -#include <private/qgl_p.h> -#include <private/qt_x11_p.h> -#include <private/qpaintengine_opengl_p.h> - -#include <qx11info_x11.h> -#include <GL/glx.h> -#include <qimage.h> - -#include "qglpixelbuffer.h" -#include "qglpixelbuffer_p.h" - -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) -#include <dlfcn.h> -#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 7546d84064..0000000000 --- a/src/opengl/qglpixmapfilter.cpp +++ /dev/null @@ -1,621 +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/qpixmapdata_gl_p.h" -#include "private/qpaintengineex_opengl2_p.h" -#include "private/qglengineshadermanager_p.h" -#include "private/qpixmapdata_p.h" -#include "private/qimagepixmapcleanuphooks_p.h" -#include "qglpixmapfilter_p.h" -#include "qgraphicssystem_gl_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 *>(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<QPixmapColorizeFilter> -{ -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<QPixmapConvolutionFilter> -{ -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<QPixmapBlurFilter> -{ -public: - QGLPixmapBlurFilter(); - -protected: - bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const; -}; - -class QGLPixmapDropShadowFilter : public QGLCustomShaderStage, public QGLPixmapFilter<QPixmapDropShadowFilter> -{ -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<QGLPixmapColorizeFilter *>(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<GLfloat> matrix(kernelSize); - QVarLengthArray<GLfloat> 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<QGLPixmapConvolutionFilter *>(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<QImage> 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(QPixmapData *pixmap); - - QCache<quint64, QGLBlurTextureInfo > cache; - - static QList<QGLBlurTextureCache *> blurTextureCaches; - - int timerId; -}; - -QList<QGLBlurTextureCache *> QGLBlurTextureCache::blurTextureCaches; -Q_GLOBAL_STATIC(QGLContextGroupResource<QGLBlurTextureCache>, 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()->addPixmapDataDestructionHook(pixmapDestroyed); - QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(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(QPixmapData *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 *>(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<const quint32*>(prepadded.bits()), - prepadded.width(), prepadded.height(), prepadded.bytesPerLine(), - reinterpret_cast<quint32*>(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<const QImage &>(subImage).bits()); - - QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(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<QGLPixmapDropShadowFilter *>(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 *>(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<QGL2PaintEngineEx *>(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 <private/qpixmapfilter_p.h> - -#include <QtOpenGL/qgl.h> - -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 <typename Filter> -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/qglscreen_qws.cpp b/src/opengl/qglscreen_qws.cpp deleted file mode 100644 index 517813e628..0000000000 --- a/src/opengl/qglscreen_qws.cpp +++ /dev/null @@ -1,242 +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 <QGLScreen> -#include <QGLContext> -#include <QGLWidget> -#include "private/qglwindowsurface_qws_p.h" - -QT_BEGIN_NAMESPACE - -class QGLScreenPrivate -{ -public: - QGLScreen::Options options; - QGLScreenSurfaceFunctions *functions; -}; - -/*! - \internal - \preliminary - \class QGLScreen - - \brief This class encapsulates an OpenGL screen driver. -*/ - -QGLScreen::QGLScreen(int displayId) - : QScreen(displayId, GLClass), d_ptr(new QGLScreenPrivate) -{ - d_ptr->options = NoOptions; - d_ptr->functions = new QGLScreenSurfaceFunctions(); -} - -QGLScreen::~QGLScreen() -{ - delete d_ptr->functions; - delete d_ptr; -} - -/*! - \since 4.3 - \obsolete - - Initializes the \a context and sets up the QGLWindowSurface of the - QWidget of \a context based on the parameters of \a context and - based on its own requirements. The format() of \a context needs - to be updated with the actual parameters of the OpenGLES drawable - that was set up. - - \a shareContext is used in the same way as for QGLContext. It is - the context with which \a context shares display lists and texture - ids etc. The window surface must be set up so that this sharing - works. - - Returns true in case of success and false if it is not possible to - create the necessary OpenGLES drawable/context. - - Since 4.4.2, this function will be not be called if options() - indicates that a native window or pixmap drawable can be created - via the functions in the surfaceFunctions() object. - - This function is obsolete in Qt 4.5 and higher. Use surfaceFunctions() - instead. - - \sa options(), surfaceFunctions() -*/ -bool -QGLScreen::chooseContext(QGLContext *context, const QGLContext *shareContext) -{ - Q_UNUSED(context); - Q_UNUSED(shareContext); - return false; -} - -/*! - \enum QGLScreen::Option - This enum defines options that can be set on QGLScreen instances. - - \value NoOptions There are no special options on the screen. This is the default. - \value NativeWindows Native windows can be created with QGLScreenSurfaceFunctions::createNativeWindow(). - \value NativePixmaps Native pixmaps can be created with QGLScreenSurfaceFunctions::createNativePixmap(). - \value NativeImages Native images can be created with QGLScreenSurfaceFunctions::createNativeImage(). - \value Overlays The screen supports GL overlays. -*/ - -/*! - \since 4.4.2 - - Returns the options associated with this QGLScreen. - - \sa setOptions() -*/ -QGLScreen::Options QGLScreen::options() const -{ - return d_ptr->options; -} - -/*! - \since 4.4.2 - - Sets the options associated with this QGLScreen to \a value. - - \sa options() -*/ -void QGLScreen::setOptions(QGLScreen::Options value) -{ - d_ptr->options = value; -} - -/*! - \since 4.4.2 - - Returns the surface functions object for this QGLScreen. - - \sa setSurfaceFunctions() -*/ -QGLScreenSurfaceFunctions *QGLScreen::surfaceFunctions() const -{ - return d_ptr->functions; -} - -/*! - \since 4.4.2 - - Sets the surface functions object for this QGLScreen to \a functions. - The QGLScreen will take over ownership of \a functions and delete - it when the QGLScreen is deleted. - - \sa setSurfaceFunctions() -*/ -void QGLScreen::setSurfaceFunctions(QGLScreenSurfaceFunctions *functions) -{ - if (functions && functions != d_ptr->functions) { - delete d_ptr->functions; - d_ptr->functions = functions; - } -} - -/*! - \internal - \preliminary - \class QGLScreenSurfaceFunctions - \brief The QGLScreenSurfaceFunctions class encapsulates the functions for creating native windows and pixmaps for OpenGL ES. -*/ - -/*! - \since 4.4.2 - - Creates a native OpenGLES drawable for the surface of \a widget and - returns it in \a native. Returns true if the OpenGLES drawable could - be created, or false if windows are not supported. - - This function will be called if the NativeWindows option is set on - the screen. - - \sa createNativePixmap(), createNativeImage(), QGLScreen::options() -*/ -bool QGLScreenSurfaceFunctions::createNativeWindow(QWidget *widget, EGLNativeWindowType *native) -{ - Q_UNUSED(widget); - Q_UNUSED(native); - return false; -} - -/*! - \since 4.4.2 - - Creates a native OpenGLES drawable for directly rendering into - \a pixmap and returns it in \a native. Returns true if the OpenGLES - drawable could be created, or false if direct rendering into pixmaps - is not supported. - - This function will be called if the NativePixmaps option is set on - the screen. - - \sa createNativeWindow(), createNativeImage(), QGLScreen::options() -*/ -bool QGLScreenSurfaceFunctions::createNativePixmap(QPixmap *pixmap, EGLNativePixmapType *native) -{ - Q_UNUSED(pixmap); - Q_UNUSED(native); - return false; -} - -/*! - \since 4.4.2 - - Creates a native OpenGLES drawable for directly rendering into - \a image and returns it in \a native. Returns true if the OpenGLES - drawable could be created, or false if direct rendering into images - is not supported. - - This function will be called if the NativeImages option is set on - the screen. - - \sa createNativeWindow(), createNativePixmap(), QGLScreen::options() -*/ -bool QGLScreenSurfaceFunctions::createNativeImage(QImage *image, EGLNativePixmapType *native) -{ - Q_UNUSED(image); - Q_UNUSED(native); - return false; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglscreen_qws.h b/src/opengl/qglscreen_qws.h deleted file mode 100644 index a033b6badb..0000000000 --- a/src/opengl/qglscreen_qws.h +++ /dev/null @@ -1,127 +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 QSCREENEGL_P_H -#define QSCREENEGL_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 QScreenEGL class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include <QtGui/QScreen> -#include <QtOpenGL/qgl.h> -#if defined(QT_OPENGL_ES_2) -#include <EGL/egl.h> -#else -#include <GLES/egl.h> -#endif -#if !defined(EGL_VERSION_1_3) && !defined(QEGL_NATIVE_TYPES_DEFINED) -#undef EGLNativeWindowType -#undef EGLNativePixmapType -#undef EGLNativeDisplayType -typedef NativeWindowType EGLNativeWindowType; -typedef NativePixmapType EGLNativePixmapType; -typedef NativeDisplayType EGLNativeDisplayType; -#define QEGL_NATIVE_TYPES_DEFINED 1 -#endif - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(OpenGL) - -class QGLScreenPrivate; - -class Q_OPENGL_EXPORT QGLScreenSurfaceFunctions -{ -public: - virtual bool createNativeWindow(QWidget *widget, EGLNativeWindowType *native); - virtual bool createNativePixmap(QPixmap *pixmap, EGLNativePixmapType *native); - virtual bool createNativeImage(QImage *image, EGLNativePixmapType *native); -}; - -class Q_OPENGL_EXPORT QGLScreen : public QScreen -{ - Q_DECLARE_PRIVATE(QGLScreen) -public: - QGLScreen(int displayId); - virtual ~QGLScreen(); - - enum Option - { - NoOptions = 0, - NativeWindows = 1, - NativePixmaps = 2, - NativeImages = 4, - Overlays = 8 - }; - Q_DECLARE_FLAGS(Options, Option) - - QGLScreen::Options options() const; - - virtual bool chooseContext(QGLContext *context, const QGLContext *shareContext); - virtual bool hasOpenGL() = 0; - - QGLScreenSurfaceFunctions *surfaceFunctions() const; - -protected: - void setOptions(QGLScreen::Options value); - void setSurfaceFunctions(QGLScreenSurfaceFunctions *functions); - -private: - QGLScreenPrivate *d_ptr; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QGLScreen::Options) - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QSCREENEGL_P_H diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index e9cae44662..0163d60f0c 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. @@ -191,15 +189,15 @@ class QGLShaderPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGLShader) public: - QGLShaderPrivate(const QGLContext *context, QGLShader::ShaderType type) - : shaderGuard(context) + QGLShaderPrivate(const QGLContext *, QGLShader::ShaderType type) + : shaderGuard(0) , shaderType(type) , compiled(false) { } ~QGLShaderPrivate(); - QGLSharedResourceGuard shaderGuard; + QGLSharedResourceGuardBase *shaderGuard; QGLShader::ShaderType shaderType; bool compiled; QString log; @@ -209,22 +207,28 @@ public: void deleteShader(); }; -#define ctx shaderGuard.context() +namespace { + void freeShaderFunc(QGLContext *ctx, GLuint id) + { + Q_UNUSED(ctx); + glDeleteShader(id); + } +} + +#define ctx QGLContext::currentContext() QGLShaderPrivate::~QGLShaderPrivate() { - if (shaderGuard.id()) { - QGLShareContextScope scope(shaderGuard.context()); - glDeleteShader(shaderGuard.id()); - } + if (shaderGuard) + shaderGuard->free(); } bool QGLShaderPrivate::create() { - const QGLContext *context = shaderGuard.context(); + QGLContext *context = const_cast<QGLContext *>(QGLContext::currentContext()); if (!context) return false; - if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) { + if (qt_resolve_glsl_extensions(context)) { GLuint shader; if (shaderType == QGLShader::Vertex) shader = glCreateShader(GL_VERTEX_SHADER); @@ -236,7 +240,7 @@ bool QGLShaderPrivate::create() qWarning() << "QGLShader: could not create shader"; return false; } - shaderGuard.setId(shader); + shaderGuard = createSharedResourceGuard(context, shader, freeShaderFunc); return true; } else { return false; @@ -245,7 +249,7 @@ bool QGLShaderPrivate::create() bool QGLShaderPrivate::compile(QGLShader *q) { - GLuint shader = shaderGuard.id(); + GLuint shader = shaderGuard ? shaderGuard->id() : 0; if (!shader) return false; glCompileShader(shader); @@ -288,15 +292,12 @@ bool QGLShaderPrivate::compile(QGLShader *q) void QGLShaderPrivate::deleteShader() { - if (shaderGuard.id()) { - glDeleteShader(shaderGuard.id()); - shaderGuard.setId(0); + if (shaderGuard) { + shaderGuard->free(); + shaderGuard = 0; } } -#undef ctx -#define ctx d->shaderGuard.context() - /*! Constructs a new QGLShader object of the specified \a type and attaches it to \a parent. If shader programs are not supported, @@ -389,7 +390,7 @@ static const char redefineHighp[] = bool QGLShader::compileSourceCode(const char *source) { Q_D(QGLShader); - if (d->shaderGuard.id()) { + if (d->shaderGuard && d->shaderGuard->id()) { QVarLengthArray<const char *, 4> src; QVarLengthArray<GLint, 4> srclen; int headerLen = 0; @@ -422,7 +423,7 @@ bool QGLShader::compileSourceCode(const char *source) #endif src.append(source + headerLen); srclen.append(GLint(qstrlen(source + headerLen))); - glShaderSource(d->shaderGuard.id(), src.size(), src.data(), srclen.data()); + glShaderSource(d->shaderGuard->id(), src.size(), src.data(), srclen.data()); return d->compile(this); } else { return false; @@ -482,7 +483,7 @@ bool QGLShader::compileSourceFile(const QString& fileName) QByteArray QGLShader::sourceCode() const { Q_D(const QGLShader); - GLuint shader = d->shaderGuard.id(); + GLuint shader = d->shaderGuard ? d->shaderGuard->id() : 0; if (!shader) return QByteArray(); GLint size = 0; @@ -527,22 +528,17 @@ QString QGLShader::log() const GLuint QGLShader::shaderId() const { Q_D(const QGLShader); - return d->shaderGuard.id(); + return d->shaderGuard ? d->shaderGuard->id() : 0; } - - - - #undef ctx -#define ctx programGuard.context() class QGLShaderProgramPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGLShaderProgram) public: - QGLShaderProgramPrivate(const QGLContext *context) - : programGuard(context) + QGLShaderProgramPrivate(const QGLContext *) + : programGuard(0) , linked(false) , inited(false) , removingShaders(false) @@ -553,7 +549,7 @@ public: } ~QGLShaderProgramPrivate(); - QGLSharedResourceGuard programGuard; + QGLSharedResourceGuardBase *programGuard; bool linked; bool inited; bool removingShaders; @@ -569,12 +565,19 @@ public: bool hasShader(QGLShader::ShaderType type) const; }; +namespace { + void freeProgramFunc(QGLContext *ctx, GLuint id) + { + Q_UNUSED(ctx); + glDeleteProgram(id); + } +} + + QGLShaderProgramPrivate::~QGLShaderProgramPrivate() { - if (programGuard.id()) { - QGLShareContextScope scope(programGuard.context()); - glDeleteProgram(programGuard.id()); - } + if (programGuard) + programGuard->free(); } bool QGLShaderProgramPrivate::hasShader(QGLShader::ShaderType type) const @@ -586,8 +589,7 @@ bool QGLShaderProgramPrivate::hasShader(QGLShader::ShaderType type) const return false; } -#undef ctx -#define ctx d->programGuard.context() +#define ctx QGLContext::currentContext() /*! Constructs a new shader program and attaches it to \a parent. @@ -625,24 +627,21 @@ QGLShaderProgram::~QGLShaderProgram() bool QGLShaderProgram::init() { Q_D(QGLShaderProgram); - if (d->programGuard.id() || d->inited) + if ((d->programGuard && d->programGuard->id()) || d->inited) return true; d->inited = true; - const QGLContext *context = d->programGuard.context(); - if (!context) { - context = QGLContext::currentContext(); - d->programGuard.setContext(context); - } - + QGLContext *context = const_cast<QGLContext *>(QGLContext::currentContext()); if (!context) return false; - if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) { + if (qt_resolve_glsl_extensions(context)) { GLuint program = glCreateProgram(); if (!program) { qWarning() << "QGLShaderProgram: could not create shader program"; return false; } - d->programGuard.setId(program); + if (d->programGuard) + delete d->programGuard; + d->programGuard = createSharedResourceGuard(context, program, freeProgramFunc); return true; } else { qWarning() << "QGLShaderProgram: shader programs are not supported"; @@ -669,15 +668,14 @@ bool QGLShaderProgram::addShader(QGLShader *shader) return false; if (d->shaders.contains(shader)) return true; // Already added to this shader program. - if (d->programGuard.id() && shader) { - if (!QGLContext::areSharing(shader->d_func()->shaderGuard.context(), - d->programGuard.context())) { + if (d->programGuard && d->programGuard->id() && shader) { + if (!shader->d_func()->shaderGuard || !shader->d_func()->shaderGuard->id()) + return false; + if (d->programGuard->group() != shader->d_func()->shaderGuard->group()) { qWarning("QGLShaderProgram::addShader: Program and shader are not associated with same context."); return false; } - if (!shader->d_func()->shaderGuard.id()) - return false; - glAttachShader(d->programGuard.id(), shader->d_func()->shaderGuard.id()); + glAttachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id()); d->linked = false; // Program needs to be relinked. d->shaders.append(shader); connect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed())); @@ -786,14 +784,17 @@ bool QGLShaderProgram::addShaderFromSourceFile /*! Removes \a shader from this shader program. The object is not deleted. + The shader program must be valid in the current QGLContext. + \sa addShader(), link(), removeAllShaders() */ void QGLShaderProgram::removeShader(QGLShader *shader) { Q_D(QGLShaderProgram); - if (d->programGuard.id() && shader && shader->d_func()->shaderGuard.id()) { - QGLShareContextScope scope(d->programGuard.context()); - glDetachShader(d->programGuard.id(), shader->d_func()->shaderGuard.id()); + if (d->programGuard && d->programGuard->id() + && shader && shader->d_func()->shaderGuard) + { + glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id()); } d->linked = false; // Program needs to be relinked. if (shader) { @@ -828,8 +829,11 @@ void QGLShaderProgram::removeAllShaders() Q_D(QGLShaderProgram); d->removingShaders = true; foreach (QGLShader *shader, d->shaders) { - if (d->programGuard.id() && shader && shader->d_func()->shaderGuard.id()) - glDetachShader(d->programGuard.id(), shader->d_func()->shaderGuard.id()); + if (d->programGuard && d->programGuard->id() + && shader && shader->d_func()->shaderGuard) + { + glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id()); + } } foreach (QGLShader *shader, d->anonShaders) { // Delete shader objects that were created anonymously. @@ -858,7 +862,7 @@ void QGLShaderProgram::removeAllShaders() bool QGLShaderProgram::link() { Q_D(QGLShaderProgram); - GLuint program = d->programGuard.id(); + GLuint program = d->programGuard ? d->programGuard->id() : 0; if (!program) return false; @@ -948,13 +952,13 @@ QString QGLShaderProgram::log() const bool QGLShaderProgram::bind() { Q_D(QGLShaderProgram); - GLuint program = d->programGuard.id(); + GLuint program = d->programGuard ? d->programGuard->id() : 0; if (!program) return false; if (!d->linked && !link()) return false; #ifndef QT_NO_DEBUG - if (!QGLContext::areSharing(d->programGuard.context(), QGLContext::currentContext())) { + if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) { qWarning("QGLShaderProgram::bind: program is not valid in the current context."); return false; } @@ -976,7 +980,7 @@ void QGLShaderProgram::release() { #ifndef QT_NO_DEBUG Q_D(QGLShaderProgram); - if (!QGLContext::areSharing(d->programGuard.context(), QGLContext::currentContext())) + if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) qWarning("QGLShaderProgram::release: program is not valid in the current context."); #endif #if defined(QT_OPENGL_ES_2) @@ -987,9 +991,6 @@ void QGLShaderProgram::release() #endif } -#undef ctx -#define ctx d->programGuard.context() - /*! Returns the OpenGL identifier associated with this shader program. @@ -998,7 +999,7 @@ void QGLShaderProgram::release() GLuint QGLShaderProgram::programId() const { Q_D(const QGLShaderProgram); - GLuint id = d->programGuard.id(); + GLuint id = d->programGuard ? d->programGuard->id() : 0; if (id) return id; @@ -1007,7 +1008,7 @@ GLuint QGLShaderProgram::programId() const // themselves, particularly those using program binaries. if (!const_cast<QGLShaderProgram *>(this)->init()) return 0; - return d->programGuard.id(); + return d->programGuard ? d->programGuard->id() : 0; } /*! @@ -1024,9 +1025,9 @@ GLuint QGLShaderProgram::programId() const void QGLShaderProgram::bindAttributeLocation(const char *name, int location) { Q_D(QGLShaderProgram); - if (!init()) + if (!init() || !d->programGuard || !d->programGuard->id()) return; - glBindAttribLocation(d->programGuard.id(), location, name); + glBindAttribLocation(d->programGuard->id(), location, name); d->linked = false; // Program needs to be relinked. } @@ -1076,8 +1077,8 @@ void QGLShaderProgram::bindAttributeLocation(const QString& name, int location) int QGLShaderProgram::attributeLocation(const char *name) const { Q_D(const QGLShaderProgram); - if (d->linked) { - return glGetAttribLocation(d->programGuard.id(), name); + if (d->linked && d->programGuard && d->programGuard->id()) { + return glGetAttribLocation(d->programGuard->id(), name); } else { qWarning() << "QGLShaderProgram::attributeLocation(" << name << "): shader program is not linked"; @@ -1754,8 +1755,8 @@ int QGLShaderProgram::uniformLocation(const char *name) const { Q_D(const QGLShaderProgram); Q_UNUSED(d); - if (d->linked) { - return glGetUniformLocation(d->programGuard.id(), name); + if (d->linked && d->programGuard && d->programGuard->id()) { + return glGetUniformLocation(d->programGuard->id(), name); } else { qWarning() << "QGLShaderProgram::uniformLocation(" << name << "): shader program is not linked"; @@ -3269,86 +3270,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/qgltexturepool.cpp b/src/opengl/qgltexturepool.cpp deleted file mode 100644 index d809328725..0000000000 --- a/src/opengl/qgltexturepool.cpp +++ /dev/null @@ -1,244 +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 QtOpenVG 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 "qgltexturepool_p.h" -#include "qpixmapdata_gl_p.h" - -QT_BEGIN_NAMESPACE - -Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget(); - -static QGLTexturePool *qt_gl_texture_pool = 0; - -class QGLTexturePoolPrivate -{ -public: - QGLTexturePoolPrivate() : lruFirst(0), lruLast(0) {} - - QGLPixmapData *lruFirst; - QGLPixmapData *lruLast; -}; - -QGLTexturePool::QGLTexturePool() - : d_ptr(new QGLTexturePoolPrivate()) -{ -} - -QGLTexturePool::~QGLTexturePool() -{ -} - -QGLTexturePool *QGLTexturePool::instance() -{ - if (!qt_gl_texture_pool) - qt_gl_texture_pool = new QGLTexturePool(); - return qt_gl_texture_pool; -} - -GLuint QGLTexturePool::createTextureForPixmap(GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - QGLPixmapData *data) -{ - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(target, texture); - do { - glTexImage2D(target, level, internalformat, width, height, 0, format, type, 0); - GLenum error = glGetError(); - if (error == GL_NO_ERROR) { - if (data) - moveToHeadOfLRU(data); - return texture; - } else if (error != GL_OUT_OF_MEMORY) { - qWarning("QGLTexturePool: cannot create temporary texture because of invalid params"); - return 0; - } - } while (reclaimSpace(internalformat, width, height, format, type, data)); - qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d pixmap", - width, height); - return 0; -} - -bool QGLTexturePool::createPermanentTexture(GLuint texture, - GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const GLvoid *data) -{ - glBindTexture(target, texture); - do { - glTexImage2D(target, level, internalformat, width, height, 0, format, type, data); - - GLenum error = glGetError(); - if (error == GL_NO_ERROR) { - return true; - } else if (error != GL_OUT_OF_MEMORY) { - qWarning("QGLTexturePool: cannot create permanent texture because of invalid params"); - return false; - } - } while (reclaimSpace(internalformat, width, height, format, type, 0)); - qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d pixmap", - width, height); - return 0; -} - -void QGLTexturePool::releaseTexture(QGLPixmapData *data, GLuint texture) -{ - // Very simple strategy at the moment: just destroy the texture. - if (data) - removeFromLRU(data); - - QGLWidget *shareWidget = qt_gl_share_widget(); - if (shareWidget) { - QGLShareContextScope ctx(shareWidget->context()); - glDeleteTextures(1, &texture); - } -} - -void QGLTexturePool::useTexture(QGLPixmapData *data) -{ - moveToHeadOfLRU(data); -} - -void QGLTexturePool::detachTexture(QGLPixmapData *data) -{ - removeFromLRU(data); -} - -bool QGLTexturePool::reclaimSpace(GLint internalformat, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - QGLPixmapData *data) -{ - Q_UNUSED(internalformat); // For future use in picking the best texture to eject. - Q_UNUSED(width); - Q_UNUSED(height); - Q_UNUSED(format); - Q_UNUSED(type); - - bool succeeded = false; - bool wasInLRU = false; - if (data) { - wasInLRU = data->inLRU; - moveToHeadOfLRU(data); - } - - QGLPixmapData *lrudata = pixmapLRU(); - if (lrudata && lrudata != data) { - lrudata->reclaimTexture(); - succeeded = true; - } - - if (data && !wasInLRU) - removeFromLRU(data); - - return succeeded; -} - -void QGLTexturePool::hibernate() -{ - Q_D(QGLTexturePool); - QGLPixmapData *pd = d->lruLast; - while (pd) { - QGLPixmapData *prevLRU = pd->prevLRU; - pd->inTexturePool = false; - pd->inLRU = false; - pd->nextLRU = 0; - pd->prevLRU = 0; - pd->hibernate(); - pd = prevLRU; - } - d->lruFirst = 0; - d->lruLast = 0; -} - -void QGLTexturePool::moveToHeadOfLRU(QGLPixmapData *data) -{ - Q_D(QGLTexturePool); - if (data->inLRU) { - if (!data->prevLRU) - return; // Already at the head of the list. - removeFromLRU(data); - } - data->inLRU = true; - data->nextLRU = d->lruFirst; - data->prevLRU = 0; - if (d->lruFirst) - d->lruFirst->prevLRU = data; - else - d->lruLast = data; - d->lruFirst = data; -} - -void QGLTexturePool::removeFromLRU(QGLPixmapData *data) -{ - Q_D(QGLTexturePool); - if (!data->inLRU) - return; - if (data->nextLRU) - data->nextLRU->prevLRU = data->prevLRU; - else - d->lruLast = data->prevLRU; - if (data->prevLRU) - data->prevLRU->nextLRU = data->nextLRU; - else - d->lruFirst = data->nextLRU; - data->inLRU = false; -} - -QGLPixmapData *QGLTexturePool::pixmapLRU() -{ - Q_D(QGLTexturePool); - return d->lruLast; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qgltexturepool_p.h b/src/opengl/qgltexturepool_p.h deleted file mode 100644 index 27b730cbb9..0000000000 --- a/src/opengl/qgltexturepool_p.h +++ /dev/null @@ -1,147 +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 QtOpenVG 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 QGLTEXTUREPOOL_P_H -#define QGLTEXTUREPOOL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qgl.h" -#include <QtCore/qscopedpointer.h> - -QT_BEGIN_NAMESPACE - -class QGLPixmapData; -class QGLTexturePoolPrivate; - -class QGLTexturePool -{ -public: - QGLTexturePool(); - virtual ~QGLTexturePool(); - - static QGLTexturePool *instance(); - - // Create a new texture with the specified parameters and associate - // it with "data". The QGLPixmapData will be notified when the - // texture needs to be reclaimed by the pool. - // - // This function will call reclaimSpace() when texture creation fails. - GLuint createTextureForPixmap(GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - QGLPixmapData *data); - - // Create a permanent texture with the specified parameters. - // If there is insufficient space for the texture, - // then this function will call reclaimSpace() and try again. - // - // The caller is responsible for calling glDeleteTextures() - // when it no longer needs the texture, as the texture is not - // recorded in the texture pool. - bool createPermanentTexture(GLuint texture, - GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const GLvoid *data); - - // Release a texture that is no longer required. - void releaseTexture(QGLPixmapData *data, GLuint texture); - - // Notify the pool that a QGLPixmapData object is using - // an texture again. This allows the pool to move the texture - // within a least-recently-used list of QGLPixmapData objects. - void useTexture(QGLPixmapData *data); - - // Notify the pool that the texture associated with a - // QGLPixmapData is being detached from the pool. The caller - // will become responsible for calling glDeleteTextures(). - void detachTexture(QGLPixmapData *data); - - // Reclaim space for an image allocation with the specified parameters. - // Returns true if space was reclaimed, or false if there is no - // further space that can be reclaimed. The "data" parameter - // indicates the pixmap that is trying to obtain space which should - // not itself be reclaimed. - bool reclaimSpace(GLint internalformat, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - QGLPixmapData *data); - - // Hibernate the image pool because the context is about to be - // destroyed. All textures left in the pool should be released. - void hibernate(); - -protected: - // Helper functions for managing the LRU list of QGLPixmapData objects. - void moveToHeadOfLRU(QGLPixmapData *data); - void removeFromLRU(QGLPixmapData *data); - QGLPixmapData *pixmapLRU(); - -private: - QScopedPointer<QGLTexturePoolPrivate> d_ptr; - - Q_DECLARE_PRIVATE(QGLTexturePool) - Q_DISABLE_COPY(QGLTexturePool) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/opengl/qglwindowsurface_qws.cpp b/src/opengl/qglwindowsurface_qws.cpp deleted file mode 100644 index b3ad45185e..0000000000 --- a/src/opengl/qglwindowsurface_qws.cpp +++ /dev/null @@ -1,133 +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 <QtGui/QPaintDevice> -#include <QtGui/QWidget> -#include <QtOpenGL/QGLWidget> -#include "private/qglwindowsurface_qws_p.h" -#include "private/qpaintengine_opengl_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QWSGLWindowSurface - \since 4.3 - \ingroup qws - \preliminary - - \brief The QWSGLWindowSurface class provides the drawing area for top-level - windows with Qt for Embedded Linux on EGL/OpenGL ES. It also provides the - drawing area for \l{QGLWidget}s whether they are top-level windows or - children of another QWidget. - - Note that this class is only available in Qt for Embedded Linux and only - available if Qt is configured with OpenGL support. -*/ - -class QWSGLWindowSurfacePrivate -{ -public: - QWSGLWindowSurfacePrivate() : - qglContext(0), ownsContext(false) {} - - QGLContext *qglContext; - bool ownsContext; -}; - -/*! - Constructs an empty QWSGLWindowSurface for the given top-level \a window. - The window surface is later initialized from chooseContext() and resources for it - is typically allocated in setGeometry(). -*/ -QWSGLWindowSurface::QWSGLWindowSurface(QWidget *window) - : QWSWindowSurface(window), - d_ptr(new QWSGLWindowSurfacePrivate) -{ -} - -/*! - Constructs an empty QWSGLWindowSurface. -*/ -QWSGLWindowSurface::QWSGLWindowSurface() - : d_ptr(new QWSGLWindowSurfacePrivate) -{ -} - -/*! - Destroys the QWSGLWindowSurface object and frees any - allocated resources. - */ -QWSGLWindowSurface::~QWSGLWindowSurface() -{ - Q_D(QWSGLWindowSurface); - if (d->ownsContext) - delete d->qglContext; - delete d; -} - -/*! - Returns the QGLContext of the window surface. -*/ -QGLContext *QWSGLWindowSurface::context() const -{ - Q_D(const QWSGLWindowSurface); - if (!d->qglContext) { - QWSGLWindowSurface *that = const_cast<QWSGLWindowSurface*>(this); - that->setContext(new QGLContext(QGLFormat::defaultFormat())); - that->d_func()->ownsContext = true; - } - return d->qglContext; -} - -/*! - Sets the QGLContext for this window surface to \a context. -*/ -void QWSGLWindowSurface::setContext(QGLContext *context) -{ - Q_D(QWSGLWindowSurface); - if (d->ownsContext) { - delete d->qglContext; - d->ownsContext = false; - } - d->qglContext = context; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qglwindowsurface_qws_p.h b/src/opengl/qglwindowsurface_qws_p.h deleted file mode 100644 index 07362b1b88..0000000000 --- a/src/opengl/qglwindowsurface_qws_p.h +++ /dev/null @@ -1,90 +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 QGLWINDOWSURFACE_QWS_P_H -#define QGLWINDOWSURFACE_QWS_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 QWSGLWindowSurface class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QPaintDevice> -#include "private/qwindowsurface_qws_p.h" - -QT_BEGIN_NAMESPACE - -class QPaintDevice; -class QPoint; -class QRegion; -class QSize; -class QWidget; -class QGLContext; - -class QWSGLWindowSurfacePrivate; - -class Q_OPENGL_EXPORT QWSGLWindowSurface : public QWSWindowSurface -{ - Q_DECLARE_PRIVATE(QWSGLWindowSurface) - -public: - QWSGLWindowSurface(QWidget *widget); - QWSGLWindowSurface(); - ~QWSGLWindowSurface(); - - QGLContext *context() const; - void setContext(QGLContext *context); - -private: - QWSGLWindowSurfacePrivate *d_ptr; -}; - - -QT_END_NAMESPACE - -#endif // QGLWINDOWSURFACE_QWS_P_H diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index c7a058e9ef..c785fb29ad 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -40,14 +40,12 @@ ****************************************************************************/ #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 <QtGui/qpainter.h> -#include <QtGui/qgraphicsitem.h> -#include <QtGui/private/qgraphicseffect_p.h> +#include <QtWidgets/qgraphicsitem.h> +#include <private/qgraphicseffect_p.h> QT_BEGIN_NAMESPACE diff --git a/src/opengl/qgraphicsshadereffect_p.h b/src/opengl/qgraphicsshadereffect_p.h index 12d716524b..7ae5f53d7e 100644 --- a/src/opengl/qgraphicsshadereffect_p.h +++ b/src/opengl/qgraphicsshadereffect_p.h @@ -53,7 +53,7 @@ // We mean it. // -#include <QtGui/qgraphicseffect.h> +#include <QtWidgets/qgraphicseffect.h> QT_BEGIN_HEADER diff --git a/src/opengl/qgraphicssystem_gl.cpp b/src/opengl/qgraphicssystem_gl.cpp deleted file mode 100644 index 01a2864ecc..0000000000 --- a/src/opengl/qgraphicssystem_gl.cpp +++ /dev/null @@ -1,114 +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 "qgraphicssystem_gl_p.h" -#include <QGraphicsView> - -#include "private/qpixmap_raster_p.h" -#include "private/qpixmapdata_gl_p.h" -#include "private/qwindowsurface_gl_p.h" -#include "private/qgl_p.h" -#include <private/qwindowsurface_raster_p.h> - -#if defined(Q_WS_X11) && !defined(QT_NO_EGL) -#include "private/qpixmapdata_x11gl_p.h" -#include "private/qwindowsurface_x11gl_p.h" -#endif - -#if defined(Q_OS_SYMBIAN) -#include <QtGui/private/qapplication_p.h> -#endif - -#ifdef QGL_USE_TEXTURE_POOL -#include "private/qgltexturepool_p.h" -#endif - -QT_BEGIN_NAMESPACE - -extern QGLWidget *qt_gl_getShareWidget(); - -QPixmapData *QGLGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const -{ - return new QGLPixmapData(type); -} - -QWindowSurface *QGLGraphicsSystem::createWindowSurface(QWidget *widget) const -{ -#ifdef Q_WS_WIN - // On Windows the QGLWindowSurface class can't handle - // drop shadows and native effects, e.g. fading a menu in/out using - // top level window opacity. - if (widget->windowType() == Qt::Popup) - return new QRasterWindowSurface(widget); -#endif - -#if defined(Q_WS_X11) && !defined(QT_NO_EGL) - if (m_useX11GL && QX11GLPixmapData::hasX11GLPixmaps()) { - // If the widget is a QGraphicsView which will be re-drawing the entire - // scene each frame anyway, we should use QGLWindowSurface as this may - // provide proper buffer flipping, which should be faster than QX11GL's - // blitting approach: - QGraphicsView* qgv = qobject_cast<QGraphicsView*>(widget); - if (qgv && qgv->viewportUpdateMode() == QGraphicsView::FullViewportUpdate) - return new QGLWindowSurface(widget); - else - return new QX11GLWindowSurface(widget); - } -#endif - -#if defined(Q_OS_SYMBIAN) - if (!QApplicationPrivate::instance()->useTranslucentEGLSurfaces) { - QWidgetPrivate *d = qt_widget_private(widget); - if (!d->isOpaque && widget->testAttribute(Qt::WA_TranslucentBackground)) - return d->createDefaultWindowSurface_sys(); - } -#endif - - return new QGLWindowSurface(widget); -} -#ifdef QGL_USE_TEXTURE_POOL -void QGLGraphicsSystem::releaseCachedResources() -{ - QGLTexturePool::instance()->hibernate(); -} -#endif -QT_END_NAMESPACE - diff --git a/src/opengl/qgraphicssystem_gl_p.h b/src/opengl/qgraphicssystem_gl_p.h deleted file mode 100644 index 6e8e9a8966..0000000000 --- a/src/opengl/qgraphicssystem_gl_p.h +++ /dev/null @@ -1,80 +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 QGRAPHICSSYSTEM_RASTER_P_H -#define QGRAPHICSSYSTEM_RASTER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qgraphicssystem_p.h" - -#include <QMap> - -QT_BEGIN_NAMESPACE - -class Q_OPENGL_EXPORT QGLGraphicsSystem : public QGraphicsSystem -{ -public: - QGLGraphicsSystem(bool useX11GL); - - QPixmapData *createPixmapData(QPixmapData::PixelType type) const; - QWindowSurface *createWindowSurface(QWidget *widget) const; - -#ifdef QGL_USE_TEXTURE_POOL - void releaseCachedResources(); -#endif -private: - bool m_useX11GL; -}; - -QT_END_NAMESPACE - -#endif - diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp deleted file mode 100644 index 56a6af1cfe..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 <qdebug.h> -#include <private/qfontengine_p.h> -#include <qmath.h> -#include <private/qmath_p.h> -#include <private/qdrawhelper_p.h> -#include <private/qpaintengine_p.h> -#include "qapplication.h" -#include "qbrush.h" -#include "qgl.h" -#include <private/qgl_p.h> -#include <private/qglpaintdevice_p.h> -#include <private/qpainter_p.h> -#include "qmap.h" -#include <private/qpaintengine_opengl_p.h> -#include <private/qdatabuffer_p.h> -#include "qpen.h" -#include "qvarlengtharray.h" -#include <private/qpainter_p.h> -#include <private/qglpixelbuffer_p.h> -#include <private/qbezier_p.h> -#include <qglframebufferobject.h> -#include <private/qstatictext_p.h> - -#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<QGLContext *>(device->context()); - -#include <stdlib.h> -#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<quint64, CacheInfo> 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<QuadTreeNode> 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<QGLPaintDevice*>(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<int>(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<const QGLContext *, GLProgram> 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<GLProgram> progs = programs.values(ctx); - for (int i=0; i<progs.size(); ++i) { - const GLProgram &prg = progs.at(i); - if (mask_mode) { - if (prg.mask && prg.brush == brush) - return prg.program; - } else { - if (!prg.mask && prg.brush == brush && prg.mode == mode) - return prg.program; - } - } - - // 2. try to find a match in a shared context, and update the - // hash with the entry found - QList<const QGLContext *> contexts = programs.uniqueKeys(); - for (int i=0; i<contexts.size(); ++i) { - const QGLContext *cx = contexts.at(i); - if (cx != ctx && QGLContext::areSharing(cx, ctx)) { - QList<GLProgram> progs = programs.values(cx); - for (int k=0; k<progs.size(); ++k) { - const GLProgram &prg = progs.at(k); - if (mask_mode) { - if (prg.mask && prg.brush == brush) { - programs.insert(ctx, prg); - return prg.program; - } - } else { - if (!prg.mask && prg.brush == brush && prg.mode == mode) { - programs.insert(ctx, prg); - return prg.program; - } - } - } - } - } - - // 3. compile a new program and place it into the cache - // NB! assumes ctx is the current GL context - GLProgram prg; - prg.brush = brush; - prg.mode = mode; - prg.mask = mask_mode; - glGenProgramsARB(1, &prg.program); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prg.program); - const char *src = mask_mode - ? mask_fragment_program_sources[brush] - : painter_fragment_program_sources[brush][mode]; - // necessary for .NET 2002, apparently - const GLbyte *gl_src = reinterpret_cast<const GLbyte *>(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<QPointF> tess_points; - QVector<int> 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<QDrawQueueItem> 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<quint64, CacheInfo> 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<quint64, CacheInfo> 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<uint> 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<QGLPaintDevice*>(pdev); - else - d->device = QGLPaintDevice::getDevice(pdev); - - if (!d->device) - return false; - - d->offscreen.setDevice(pdev); - d->has_fast_pen = false; - d->inverseScale = 1; - d->opacity = 1; - d->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<QGLContext *>(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<const char*>(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<QGLContext *>(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<const QLinearGradient *>(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<const QRadialGradient *>(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<const QConicalGradient *>(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<const QLinearGradient *>(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<QGLTrapezoid> 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; i<path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - switch (e.type) { - case QPainterPath::MoveToElement: - tess_points_stops.append(tess_points.size()); - lineToStencil(e.x, e.y); - break; - case QPainterPath::LineToElement: - lineToStencil(e.x, e.y); - break; - case QPainterPath::CurveToElement: - curveToStencil(e, path.elementAt(i+1), path.elementAt(i+2)); - i+=2; - break; - default: - break; - } - } - lineToStencil(first.x, first.y); - tess_points_stops.append(tess_points.size()); -} - - -void QOpenGLPaintEnginePrivate::drawVertexArrays() -{ - if (tess_points_stops.count() == 0) - return; - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_DOUBLE, 0, tess_points.data()); - int previous_stop = 0; - foreach(int stop, tess_points_stops) { - glDrawArrays(GL_TRIANGLE_FAN, previous_stop, stop-previous_stop); - previous_stop = stop; - } - glDisableClientState(GL_VERTEX_ARRAY); -} - -void QOpenGLPaintEnginePrivate::fillVertexArray(Qt::FillRule fillRule) -{ - Q_Q(QOpenGLPaintEngine); - - QRect rect = dirty_stencil.boundingRect(); - - if (use_system_clip) - rect = q->systemClip().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<QRect> rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects(); - - // rectangle count * 2 (triangles) * vertex count * component count (Z omitted) - QDataBuffer<GLfloat> 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->currentClipWidget) { - QWidgetPrivate *widgetPrivate = qt_widget_private(d->currentClipWidget->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<QRect> 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<QGLTrapezoid> generateTrapezoids() = 0; - virtual QRect computeScreenRect() = 0; -}; - -class QGLPathMaskGenerator : public QGLTrapezoidMaskGenerator -{ -public: - QGLPathMaskGenerator(const QPainterPath &path, const QTransform &matrix, QGLOffscreen &offscreen, GLuint maskFragmentProgram); - -private: - QVector<QGLTrapezoid> 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<QGLTrapezoid> generateTrapezoids(); - QRect computeScreenRect(); - - QPainterPath transformedPath; -}; - -class QGLRectMaskGenerator : public QGLTrapezoidMaskGenerator -{ -public: - QGLRectMaskGenerator(const QPainterPath &path, const QTransform &matrix, QGLOffscreen &offscreen, GLuint maskFragmentProgram); - -private: - QVector<QGLTrapezoid> 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<QGLTrapezoid> 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<QGLTrapezoid> 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<QGLTrapezoid> 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<QGLTrapezoid> 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; i<rectCount; ++i) { - const QRectF &r = rects[i]; - - // optimization for rects which can be drawn aliased - if (!d->high_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<GLfloat> 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<const qreal*>(&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<GLfloat> 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<GLfloat> 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; i<lineCount; ++i) { - const QLineF &l = lines[i]; - - if (l.p1() == l.p2()) { - if (d->cpen.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<QT_PointF> p(pointCount); - for (int i=0; i<pointCount; ++i) { - p[i].x = points[i].x(); - p[i].y = points[i].y(); - } - drawPolygon((QPointF *)p.data(), pointCount, mode); -} - -void QOpenGLPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -{ - Q_D(QOpenGLPaintEngine); - if(pointCount < 2) - return; - - if (d->use_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<const qreal*>(&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; i<pointCount; ++i) - path.lineTo(points[i]); - d->fillPath(path); - } - } - - if (d->has_pen) { - if (d->has_fast_pen && !d->high_quality_antialiasing) { - d->setGradientOps(d->cpen.brush(), bounds); - QVarLengthArray<GLfloat> vertexArray(pointCount*2 + 2); - glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); - int i; - for (i=0; i<pointCount; ++i) { - vertexArray[i*2] = points[i].x(); - vertexArray[i*2+1] = points[i].y(); - } - - glEnableClientState(GL_VERTEX_ARRAY); - if (mode != PolylineMode) { - vertexArray[i*2] = vertexArray[0]; - vertexArray[i*2+1] = vertexArray[1]; - glDrawArrays(GL_LINE_STRIP, 0, pointCount+1); - } else { - glDrawArrays(GL_LINE_STRIP, 0, pointCount); - glDrawArrays(GL_POINTS, pointCount-1, 1); - } - glDisableClientState(GL_VERTEX_ARRAY); - } else { - QPainterPath path(points[0]); - for (int i = 1; i < pointCount; ++i) - path.lineTo(points[i]); - if (mode != PolylineMode) - path.lineTo(points[0]); - - if (d->has_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<path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - switch (e.type) { - case QPainterPath::MoveToElement: - if (i != 0) - glEnd(); // GL_LINE_STRIP - glBegin(GL_LINE_STRIP); - glVertex2d(e.x, e.y); - - break; - case QPainterPath::LineToElement: - glVertex2d(e.x, e.y); - break; - - case QPainterPath::CurveToElement: - { - QPointF sp = path.elementAt(i-1); - QPointF cp2 = path.elementAt(i+1); - QPointF ep = path.elementAt(i+2); - i+=2; - - qreal inverseScaleHalf = inverseScale / 2; - beziers[0] = QBezier::fromPoints(sp, e, 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 - 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<path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - switch (e.type) { - case QPainterPath::MoveToElement: - if (i != 0) { - glVertexPointer(2, GL_FLOAT, 0, tess_points.data()); - glDrawArrays(GL_LINE_STRIP, 0, tess_points.size()); - tess_points.reset(); - } - tess_points.add(QPointF(e.x, e.y)); - - break; - case QPainterPath::LineToElement: - tess_points.add(QPointF(e.x, e.y)); - break; - - case QPainterPath::CurveToElement: - { - QPointF sp = path.elementAt(i-1); - QPointF cp2 = path.elementAt(i+1); - QPointF ep = path.elementAt(i+2); - i+=2; - - qreal inverseScaleHalf = inverseScale / 2; - beziers[0] = QBezier::fromPoints(sp, e, 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 - 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 <typename T> -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<glyph_t, QGLGlyphCoord*> QGLGlyphHash; -typedef QHash<QFontEngine*, QGLGlyphHash*> QGLFontGlyphHash; -typedef QHash<quint64, QGLFontTexture*> QGLFontTexHash; -typedef QHash<const QGLContext*, QGLFontGlyphHash*> 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<QFontEngine *>(o); // safe, since only the type is used - QList<const QGLContext *> 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<quint64>(ctx) << 32) | reinterpret_cast<quint64>(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<QFontEngine *> 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<quint64>(ctx) << 32) | reinterpret_cast<quint64>(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<const QGLContext *> 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; y<font_tex->height; ++y) { - for (int x=0; x<font_tex->width; ++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<const QGLContext *> contexts = qt_context_cache.keys(); - for (int i=0; i<contexts.size(); ++i) { - const QGLContext *ctx = contexts.at(i); - if (ctx != context && QGLContext::areSharing(context, ctx)) { - context_key = ctx; - dev_it = qt_context_cache.constFind(context_key); - break; - } - } - } - - if (dev_it == qt_context_cache.constEnd()) { - // no shared contexts either - create a new entry - font_cache = new QGLFontGlyphHash; -// qDebug() << "new context" << context << font_cache; - qt_context_cache.insert(context, font_cache); - if (context->isValid()) { - if (context->device() && context->device()->devType() == QInternal::Widget) { - QWidget *widget = static_cast<QWidget *>(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<quint64>(context_key ? context_key : context) << 32) - | reinterpret_cast<quint64>(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; y<glyph_im.height(); ++y) { - uchar *s = (uchar *) glyph_im.scanLine(y); - for (int x=0; x<glyph_im.width(); ++x) { - uchar alpha = is8BitGray ? *s : qAlpha(glyph_im.color(*s)); - tex_data[idx] = alpha; - tex_data[idx+1] = alpha; - ++s; - idx += 2; - } - if (glyph_im.width()%2 != 0) - idx += 2; - } - glTexSubImage2D(GL_TEXTURE_2D, 0, font_tex->x_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<const QTextItemInt &>(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<QFixedPoint> positions; - QVarLengthArray<glyph_t> 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<QChar *>(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<int>(screen_rect.left())); - int width = qMin(device->size().width() - left, static_cast<int>(screen_rect.width()) + 1); - - int bottom = qMax(0, static_cast<int>(device->size().height() - screen_rect.bottom())); - int height = qMin(device->size().height() - bottom, static_cast<int>(screen_rect.height()) + 1); - - glBindTexture(GL_TEXTURE_2D, drawable_texture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, left, bottom, width, height); -#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 <typename T> 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<path.elementCount(); ++i) { - switch(types[i]) { - case QPainterPath::MoveToElement: - p.moveTo(QPointF(points[id], points[id+1])); - id+=2; - break; - case QPainterPath::LineToElement: - p.lineTo(QPointF(points[id], points[id+1])); - id+=2; - break; - case QPainterPath::CurveToElement: { - QPointF p1(points[id], points[id+1]); - QPointF p2(points[id+2], points[id+3]); - QPointF p3(points[id+4], points[id+5]); - p.cubicTo(p1, p2, p3); - id+=6; - break; - } - case QPainterPath::CurveToDataElement: - ; - break; - } - } - } else if (!path.isEmpty()) { - p.moveTo(QPointF(points[0], points[1])); - int id = 2; - for (int i=1; i<path.elementCount(); ++i) { - p.lineTo(QPointF(points[id], points[id+1])); - id+=2; - } - } - if (path.hints() & QVectorPath::WindingFill) - p.setFillRule(Qt::WindingFill); - - updateClipRegion(QRegion(p.toFillPolygon().toPolygon(), p.fillRule()), op); - return; -} - -void QOpenGLPaintEngine::setState(QPainterState *s) -{ - Q_D(QOpenGLPaintEngine); - QOpenGLPaintEngineState *new_state = static_cast<QOpenGLPaintEngineState *>(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<QOpenGLPaintEngineState *>(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 <private/qpaintengineex_p.h> - -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<QOpenGLPaintEngineState *>(QPaintEngineEx::state()); - } - inline const QOpenGLPaintEngineState *state() const { - return static_cast<const QOpenGLPaintEngineState *>(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 diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp deleted file mode 100644 index e909ff30b9..0000000000 --- a/src/opengl/qpixmapdata_gl.cpp +++ /dev/null @@ -1,829 +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 "qpixmap.h" -#include "qglframebufferobject.h" - -#include <private/qpaintengine_raster_p.h> - -#include "qpixmapdata_gl_p.h" - -#include <private/qgl_p.h> -#include <private/qdrawhelper_p.h> -#include <private/qimage_p.h> -#include <private/qfont_p.h> - -#include <private/qpaintengineex_opengl2_p.h> - -#include <qdesktopwidget.h> -#include <qfile.h> -#include <qimagereader.h> -#include <qbuffer.h> - -QT_BEGIN_NAMESPACE - -Q_OPENGL_EXPORT extern const QGLContext* qt_gl_share_context(); - -/*! - \class QGLFramebufferObjectPool - \since 4.6 - - \brief The QGLFramebufferObject class provides a pool of framebuffer - objects for offscreen rendering purposes. - - When requesting an FBO of a given size and format, an FBO of the same - format and a size at least as big as the requested size will be returned. - - \internal -*/ - -static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo) -{ - return qAbs(size.width() * size.height() - fbo->width() * fbo->height()); -} - -extern int qt_next_power_of_two(int v); - -static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz) -{ -#ifdef QT_OPENGL_ES_2 - QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height())); - if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height()) - return rounded; -#endif - return sz; -} - - -QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize) -{ - QGLFramebufferObject *chosen = 0; - QGLFramebufferObject *candidate = 0; - for (int i = 0; !chosen && i < m_fbos.size(); ++i) { - QGLFramebufferObject *fbo = m_fbos.at(i); - - if (strictSize) { - if (fbo->size() == requestSize && fbo->format() == requestFormat) { - chosen = fbo; - break; - } else { - continue; - } - } - - if (fbo->format() == requestFormat) { - // choose the fbo with a matching format and the closest size - if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo)) - candidate = fbo; - } - - if (candidate) { - m_fbos.removeOne(candidate); - - const QSize fboSize = candidate->size(); - QSize sz = fboSize; - - if (sz.width() < requestSize.width()) - sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5))); - if (sz.height() < requestSize.height()) - sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5))); - - // wasting too much space? - if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4) - sz = requestSize; - - if (sz != fboSize) { - delete candidate; - candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat); - } - - chosen = candidate; - } - } - - if (!chosen) { - if (strictSize) - chosen = new QGLFramebufferObject(requestSize, requestFormat); - else - chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat); - } - - if (!chosen->isValid()) { - delete chosen; - chosen = 0; - } - - return chosen; -} - -void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo) -{ - if (fbo) - m_fbos << fbo; -} - - -QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const -{ - return data->paintEngine(); -} - -void QGLPixmapGLPaintDevice::beginPaint() -{ - if (!data->isValid()) - return; - - // QGLPaintDevice::beginPaint will store the current binding and replace - // it with m_thisFBO: - m_thisFBO = data->m_renderFbo->handle(); - QGLPaintDevice::beginPaint(); - - Q_ASSERT(data->paintEngine()->type() == QPaintEngine::OpenGL2); - - // QPixmap::fill() is deferred until now, where we actually need to do the fill: - if (data->needsFill()) { - const QColor &c = data->fillColor(); - float alpha = c.alphaF(); - glDisable(GL_SCISSOR_TEST); - glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha); - glClear(GL_COLOR_BUFFER_BIT); - } - else if (!data->isUninitialized()) { - // If the pixmap (GL Texture) has valid content (it has been - // uploaded from an image or rendered into before), we need to - // copy it from the texture to the render FBO. - - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - -#if !defined(QT_OPENGL_ES_2) - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, data->width(), data->height(), 0, -999999, 999999); -#endif - - glViewport(0, 0, data->width(), data->height()); - - // Pass false to bind so it doesn't copy the FBO into the texture! - context()->drawTexture(QRect(0, 0, data->width(), data->height()), data->bind(false)); - } -} - -void QGLPixmapGLPaintDevice::endPaint() -{ - if (!data->isValid()) - return; - - data->copyBackFromRenderFbo(false); - - // Base's endPaint will restore the previous FBO binding - QGLPaintDevice::endPaint(); - - qgl_fbo_pool()->release(data->m_renderFbo); - data->m_renderFbo = 0; -} - -QGLContext* QGLPixmapGLPaintDevice::context() const -{ - data->ensureCreated(); - return data->m_ctx; -} - -QSize QGLPixmapGLPaintDevice::size() const -{ - return data->size(); -} - -bool QGLPixmapGLPaintDevice::alphaRequested() const -{ - return data->m_hasAlpha; -} - -void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d) -{ - data = d; -} - -static int qt_gl_pixmap_serial = 0; - -QGLPixmapData::QGLPixmapData(PixelType type) - : QPixmapData(type, OpenGLClass) - , m_renderFbo(0) - , m_engine(0) - , m_ctx(0) - , m_dirty(false) - , m_hasFillColor(false) - , m_hasAlpha(false) -{ - setSerialNumber(++qt_gl_pixmap_serial); - m_glDevice.setPixmapData(this); -} - -QGLPixmapData::~QGLPixmapData() -{ - const QGLContext *shareContext = qt_gl_share_context(); - if (!shareContext) - return; - - delete m_engine; - - if (m_texture.id) { - QGLShareContextScope ctx(shareContext); - glDeleteTextures(1, &m_texture.id); - } -} - -QPixmapData *QGLPixmapData::createCompatiblePixmapData() const -{ - return new QGLPixmapData(pixelType()); -} - -bool QGLPixmapData::isValid() const -{ - return w > 0 && h > 0; -} - -bool QGLPixmapData::isValidContext(const QGLContext *ctx) const -{ - if (ctx == m_ctx) - return true; - - const QGLContext *share_ctx = qt_gl_share_context(); - return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); -} - -void QGLPixmapData::resize(int width, int height) -{ - if (width == w && height == h) - return; - - if (width <= 0 || height <= 0) { - width = 0; - height = 0; - } - - w = width; - h = height; - is_null = (w <= 0 || h <= 0); - d = pixelType() == QPixmapData::PixmapType ? 32 : 1; - - if (m_texture.id) { - QGLShareContextScope ctx(qt_gl_share_context()); - glDeleteTextures(1, &m_texture.id); - m_texture.id = 0; - } - - m_source = QImage(); - m_dirty = isValid(); - setSerialNumber(++qt_gl_pixmap_serial); -} - -void QGLPixmapData::ensureCreated() const -{ - if (!m_dirty) - return; - - m_dirty = false; - - QGLShareContextScope ctx(qt_gl_share_context()); - m_ctx = ctx; - - const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB; -#ifdef QT_OPENGL_ES_2 - const GLenum external_format = internal_format; -#else - const GLenum external_format = qt_gl_preferredTextureFormat(); -#endif - const GLenum target = GL_TEXTURE_2D; - - if (!m_texture.id) { - glGenTextures(1, &m_texture.id); - glBindTexture(target, m_texture.id); - glTexImage2D(target, 0, internal_format, w, h, 0, external_format, GL_UNSIGNED_BYTE, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - - if (!m_source.isNull()) { - if (external_format == GL_RGB) { - const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true); - - glBindTexture(target, m_texture.id); - glTexSubImage2D(target, 0, 0, 0, w, h, external_format, - GL_UNSIGNED_BYTE, tx.bits()); - } else { - const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format); - - glBindTexture(target, m_texture.id); - glTexSubImage2D(target, 0, 0, 0, w, h, external_format, - GL_UNSIGNED_BYTE, tx.bits()); - } - - if (useFramebufferObjects()) - m_source = QImage(); - } - - m_texture.options &= ~QGLContext::MemoryManagedBindOption; -} - -void QGLPixmapData::fromImage(const QImage &image, - Qt::ImageConversionFlags flags) -{ - QImage img = image; - createPixmapForImage(img, flags, false); -} - -void QGLPixmapData::fromImageReader(QImageReader *imageReader, - Qt::ImageConversionFlags flags) -{ - QImage image = imageReader->read(); - if (image.isNull()) - return; - - createPixmapForImage(image, flags, true); -} - -bool QGLPixmapData::fromFile(const QString &filename, const char *format, - Qt::ImageConversionFlags flags) -{ - if (pixelType() == QPixmapData::BitmapType) - return QPixmapData::fromFile(filename, format, flags); - QFile file(filename); - if (file.open(QIODevice::ReadOnly)) { - QByteArray data = file.peek(64); - bool alpha; - if (m_texture.canBindCompressedTexture - (data.constData(), data.size(), format, &alpha)) { - resize(0, 0); - data = file.readAll(); - file.close(); - QGLShareContextScope ctx(qt_gl_share_context()); - QSize size = m_texture.bindCompressedTexture - (data.constData(), data.size(), format); - if (!size.isEmpty()) { - w = size.width(); - h = size.height(); - is_null = false; - d = 32; - m_hasAlpha = alpha; - m_source = QImage(); - m_dirty = isValid(); - return true; - } - return false; - } - } - - QImage image = QImageReader(filename, format).read(); - if (image.isNull()) - return false; - - createPixmapForImage(image, flags, true); - - return !isNull(); -} - -bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, - Qt::ImageConversionFlags flags) -{ - bool alpha; - const char *buf = reinterpret_cast<const char *>(buffer); - if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) { - resize(0, 0); - QGLShareContextScope ctx(qt_gl_share_context()); - QSize size = m_texture.bindCompressedTexture(buf, int(len), format); - if (!size.isEmpty()) { - w = size.width(); - h = size.height(); - is_null = false; - d = 32; - m_hasAlpha = alpha; - m_source = QImage(); - m_dirty = isValid(); - return true; - } - } - - QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len); - QBuffer b(&a); - b.open(QIODevice::ReadOnly); - QImage image = QImageReader(&b, format).read(); - if (image.isNull()) - return false; - - createPixmapForImage(image, flags, true); - - return !isNull(); -} - -/*! - out-of-place conversion (inPlace == false) will always detach() - */ -void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) -{ - if (image.size() == QSize(w, h)) - setSerialNumber(++qt_gl_pixmap_serial); - - resize(image.width(), image.height()); - - if (pixelType() == BitmapType) { - m_source = image.convertToFormat(QImage::Format_MonoLSB); - - } else { - QImage::Format format = QImage::Format_RGB32; - if (qApp->desktop()->depth() == 16) - format = QImage::Format_RGB16; - - if (image.hasAlphaChannel() - && ((flags & Qt::NoOpaqueDetection) - || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) - format = QImage::Format_ARGB32_Premultiplied;; - - if (inPlace && image.data_ptr()->convertInPlace(format, flags)) { - m_source = image; - } else { - m_source = image.convertToFormat(format); - - // convertToFormat won't detach the image if format stays the same. - if (image.format() == format) - m_source.detach(); - } - } - - m_dirty = true; - m_hasFillColor = false; - - m_hasAlpha = m_source.hasAlphaChannel(); - w = image.width(); - h = image.height(); - is_null = (w <= 0 || h <= 0); - d = m_source.depth(); - - if (m_texture.id) { - QGLShareContextScope ctx(qt_gl_share_context()); - glDeleteTextures(1, &m_texture.id); - m_texture.id = 0; - } -} - -bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) -{ - Q_UNUSED(dx); - Q_UNUSED(dy); - Q_UNUSED(rect); - return false; -} - -void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect) -{ - if (data->classId() != QPixmapData::OpenGLClass || !static_cast<const QGLPixmapData *>(data)->useFramebufferObjects()) { - QPixmapData::copy(data, rect); - return; - } - - const QGLPixmapData *other = static_cast<const QGLPixmapData *>(data); - if (other->m_renderFbo) { - QGLShareContextScope ctx(qt_gl_share_context()); - - resize(rect.width(), rect.height()); - m_hasAlpha = other->m_hasAlpha; - ensureCreated(); - - if (!ctx->d_ptr->fbo) - glGenFramebuffers(1, &ctx->d_ptr->fbo); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, m_texture.id, 0); - - if (!other->m_renderFbo->isBound()) - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, other->m_renderFbo->handle()); - - glDisable(GL_SCISSOR_TEST); - if (ctx->d_ptr->active_engine && ctx->d_ptr->active_engine->type() == QPaintEngine::OpenGL2) - static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine)->invalidateState(); - - glBlitFramebufferEXT(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(), - 0, 0, w, h, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); - } else { - QPixmapData::copy(data, rect); - } -} - -void QGLPixmapData::fill(const QColor &color) -{ - if (!isValid()) - return; - - bool hasAlpha = color.alpha() != 255; - if (hasAlpha && !m_hasAlpha) { - if (m_texture.id) { - glDeleteTextures(1, &m_texture.id); - m_texture.id = 0; - m_dirty = true; - } - m_hasAlpha = color.alpha() != 255; - } - - if (useFramebufferObjects()) { - m_source = QImage(); - m_hasFillColor = true; - m_fillColor = color; - } else { - - if (m_source.isNull()) { - m_fillColor = color; - m_hasFillColor = true; - - } else if (m_source.depth() == 32) { - m_source.fill(PREMUL(color.rgba())); - - } else if (m_source.depth() == 1) { - if (color == Qt::color1) - m_source.fill(1); - else - m_source.fill(0); - } - } -} - -bool QGLPixmapData::hasAlphaChannel() const -{ - return m_hasAlpha; -} - -QImage QGLPixmapData::fillImage(const QColor &color) const -{ - QImage img; - if (pixelType() == BitmapType) { - img = QImage(w, h, QImage::Format_MonoLSB); - - img.setColorCount(2); - img.setColor(0, QColor(Qt::color0).rgba()); - img.setColor(1, QColor(Qt::color1).rgba()); - - if (color == Qt::color1) - img.fill(1); - else - img.fill(0); - } else { - img = QImage(w, h, - m_hasAlpha - ? QImage::Format_ARGB32_Premultiplied - : QImage::Format_RGB32); - img.fill(PREMUL(color.rgba())); - } - return img; -} - -extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha); - -QImage QGLPixmapData::toImage() const -{ - if (!isValid()) - return QImage(); - - if (m_renderFbo) { - copyBackFromRenderFbo(true); - } else if (!m_source.isNull()) { - QImageData *data = const_cast<QImage &>(m_source).data_ptr(); - if (data->paintEngine && data->paintEngine->isActive() - && data->paintEngine->paintDevice() == &m_source) - { - return m_source.copy(); - } - return m_source; - } else if (m_dirty || m_hasFillColor) { - return fillImage(m_fillColor); - } else { - ensureCreated(); - } - - QGLShareContextScope ctx(qt_gl_share_context()); - glBindTexture(GL_TEXTURE_2D, m_texture.id); - return qt_gl_read_texture(QSize(w, h), true, true); -} - -struct TextureBuffer -{ - QGLFramebufferObject *fbo; - QGL2PaintEngineEx *engine; -}; - -Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool) -QGLFramebufferObjectPool* qgl_fbo_pool() -{ - return _qgl_fbo_pool(); -} - -void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const -{ - if (!isValid()) - return; - - m_hasFillColor = false; - - const QGLContext *share_ctx = qt_gl_share_context(); - QGLShareContextScope ctx(share_ctx); - - ensureCreated(); - - if (!ctx->d_ptr->fbo) - glGenFramebuffers(1, &ctx->d_ptr->fbo); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, m_texture.id, 0); - - const int x0 = 0; - const int x1 = w; - const int y0 = 0; - const int y1 = h; - - if (!m_renderFbo->isBound()) - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle()); - - glDisable(GL_SCISSOR_TEST); - - glBlitFramebufferEXT(x0, y0, x1, y1, - x0, y0, x1, y1, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - if (keepCurrentFboBound) { - glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); - } else { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_renderFbo->handle()); - ctx->d_ptr->current_fbo = m_renderFbo->handle(); - } -} - -bool QGLPixmapData::useFramebufferObjects() const -{ - return QGLFramebufferObject::hasOpenGLFramebufferObjects() - && QGLFramebufferObject::hasOpenGLFramebufferBlit() - && qt_gl_preferGL2Engine() - && (w * h > 32*32); // avoid overhead of FBOs for small pixmaps -} - -QPaintEngine* QGLPixmapData::paintEngine() const -{ - if (!isValid()) - return 0; - - if (m_renderFbo) - return m_engine; - - if (useFramebufferObjects()) { - extern QGLWidget* qt_gl_share_widget(); - - if (!QGLContext::currentContext()) - const_cast<QGLContext *>(qt_gl_share_context())->makeCurrent(); - QGLShareContextScope ctx(qt_gl_share_context()); - - QGLFramebufferObjectFormat format; - format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - format.setSamples(4); - format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB)); - - m_renderFbo = qgl_fbo_pool()->acquire(size(), format); - - if (m_renderFbo) { - if (!m_engine) - m_engine = new QGL2PaintEngineEx; - return m_engine; - } - - qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine"; - } - - m_dirty = true; - if (m_source.size() != size()) - m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied); - if (m_hasFillColor) { - m_source.fill(PREMUL(m_fillColor.rgba())); - m_hasFillColor = false; - } - return m_source.paintEngine(); -} - -extern QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format); - -// If copyBack is true, bind will copy the contents of the render -// FBO to the texture (which is not bound to the texture, as it's -// a multisample FBO). -GLuint QGLPixmapData::bind(bool copyBack) const -{ - if (m_renderFbo && copyBack) { - copyBackFromRenderFbo(true); - } else { - ensureCreated(); - } - - GLuint id = m_texture.id; - glBindTexture(GL_TEXTURE_2D, id); - - if (m_hasFillColor) { - if (!useFramebufferObjects()) { - m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied); - m_source.fill(PREMUL(m_fillColor.rgba())); - } - - m_hasFillColor = false; - - GLenum format = qt_gl_preferredTextureFormat(); - QImage tx(w, h, QImage::Format_ARGB32_Premultiplied); - tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format)); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits()); - } - - return id; -} - -QGLTexture* QGLPixmapData::texture() const -{ - return &m_texture; -} - -int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const -{ - if (w == 0) - return 0; - - switch (metric) { - case QPaintDevice::PdmWidth: - return w; - case QPaintDevice::PdmHeight: - return h; - case QPaintDevice::PdmNumColors: - return 0; - case QPaintDevice::PdmDepth: - return d; - case QPaintDevice::PdmWidthMM: - return qRound(w * 25.4 / qt_defaultDpiX()); - case QPaintDevice::PdmHeightMM: - return qRound(h * 25.4 / qt_defaultDpiY()); - case QPaintDevice::PdmDpiX: - case QPaintDevice::PdmPhysicalDpiX: - return qt_defaultDpiX(); - case QPaintDevice::PdmDpiY: - case QPaintDevice::PdmPhysicalDpiY: - return qt_defaultDpiY(); - default: - qWarning("QGLPixmapData::metric(): Invalid metric"); - return 0; - } -} - -QGLPaintDevice *QGLPixmapData::glDevice() const -{ - return &m_glDevice; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h deleted file mode 100644 index 909f264d05..0000000000 --- a/src/opengl/qpixmapdata_gl_p.h +++ /dev/null @@ -1,247 +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 QPIXMAPDATA_GL_P_H -#define QPIXMAPDATA_GL_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 "qgl_p.h" -#include "qgl.h" - -#include "private/qpixmapdata_p.h" -#include "private/qglpaintdevice_p.h" - -#ifdef Q_OS_SYMBIAN -#include "private/qvolatileimage_p.h" -#endif - -QT_BEGIN_NAMESPACE - -class QPaintEngine; -class QGLFramebufferObject; -class QGLFramebufferObjectFormat; -class QGLPixmapData; - -#ifdef QGL_USE_TEXTURE_POOL -void qt_gl_register_pixmap(QGLPixmapData *pd); -void qt_gl_unregister_pixmap(QGLPixmapData *pd); -void qt_gl_hibernate_pixmaps(); -#endif - -#ifdef Q_OS_SYMBIAN -class QNativeImageHandleProvider; -#endif - -class QGLFramebufferObjectPool -{ -public: - QGLFramebufferObject *acquire(const QSize &size, const QGLFramebufferObjectFormat &format, bool strictSize = false); - void release(QGLFramebufferObject *fbo); - -private: - QList<QGLFramebufferObject *> m_fbos; -}; - -QGLFramebufferObjectPool* qgl_fbo_pool(); - - -class QGLPixmapGLPaintDevice : public QGLPaintDevice -{ -public: - QPaintEngine* paintEngine() const; - - void beginPaint(); - void endPaint(); - QGLContext* context() const; - QSize size() const; - bool alphaRequested() const; - - void setPixmapData(QGLPixmapData*); -private: - QGLPixmapData *data; -}; - - -class Q_OPENGL_EXPORT QGLPixmapData : public QPixmapData -{ -public: - QGLPixmapData(PixelType type); - ~QGLPixmapData(); - - QPixmapData *createCompatiblePixmapData() const; - - // Re-implemented from QPixmapData: - void resize(int width, int height); - void fromImage(const QImage &image, Qt::ImageConversionFlags flags); - void fromImageReader(QImageReader *imageReader, - Qt::ImageConversionFlags flags); - bool fromFile(const QString &filename, const char *format, - Qt::ImageConversionFlags flags); - bool fromData(const uchar *buffer, uint len, const char *format, - Qt::ImageConversionFlags flags); - void copy(const QPixmapData *data, const QRect &rect); - bool scroll(int dx, int dy, const QRect &rect); - void fill(const QColor &color); - bool hasAlphaChannel() const; - QImage toImage() const; - QPaintEngine *paintEngine() const; - int metric(QPaintDevice::PaintDeviceMetric metric) const; - - // For accessing as a target: - QGLPaintDevice *glDevice() const; - - // For accessing as a source: - bool isValidContext(const QGLContext *ctx) const; - GLuint bind(bool copyBack = true) const; - QGLTexture *texture() const; - -#ifdef QGL_USE_TEXTURE_POOL - void destroyTexture(); - // Detach this image from the image pool. - void detachTextureFromPool(); - // Release the GL resources associated with this pixmap and copy - // the pixmap's contents out of the GPU back into main memory. - // The GL resource will be automatically recreated the next time - // ensureCreated() is called. Does nothing if the pixmap cannot be - // hibernated for some reason (e.g. texture is shared with another - // process via a SgImage). - void hibernate(); - // Called when the QGLTexturePool wants to reclaim this pixmap's - // texture objects to reuse storage. - void reclaimTexture(); - void forceToImage(); -#endif - -#ifdef Q_OS_SYMBIAN - QImage::Format idealFormat(QImage &image, Qt::ImageConversionFlags flags); - void* toNativeType(NativeType type); - void fromNativeType(void* pixmap, NativeType type); - bool initFromNativeImageHandle(void *handle, const QString &type); - void createFromNativeImageHandleProvider(); - void releaseNativeImageHandle(); -#endif - -private: - bool isValid() const; - - void ensureCreated() const; - - bool isUninitialized() const { return m_dirty && m_source.isNull(); } - - bool needsFill() const { return m_hasFillColor; } - QColor fillColor() const { return m_fillColor; } - - - - QGLPixmapData(const QGLPixmapData &other); - QGLPixmapData &operator=(const QGLPixmapData &other); - - void copyBackFromRenderFbo(bool keepCurrentFboBound) const; - QSize size() const { return QSize(w, h); } - - bool useFramebufferObjects() const; - - QImage fillImage(const QColor &color) const; - - void createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace); - - mutable QGLFramebufferObject *m_renderFbo; - mutable QPaintEngine *m_engine; - mutable QGLContext *m_ctx; -#ifdef Q_OS_SYMBIAN - mutable QVolatileImage m_source; - mutable QNativeImageHandleProvider *nativeImageHandleProvider; - void *nativeImageHandle; - QString nativeImageType; -#else - mutable QImage m_source; -#endif - mutable QGLTexture m_texture; - - // the texture is not in sync with the source image - mutable bool m_dirty; - - // fill has been called and no painting has been done, so the pixmap is - // represented by a single fill color - mutable QColor m_fillColor; - mutable bool m_hasFillColor; - - mutable bool m_hasAlpha; - - mutable QGLPixmapGLPaintDevice m_glDevice; - -#ifdef QGL_USE_TEXTURE_POOL - QGLPixmapData *nextLRU; - QGLPixmapData *prevLRU; - mutable bool inLRU; - mutable bool failedToAlloc; - mutable bool inTexturePool; - - QGLPixmapData *next; - QGLPixmapData *prev; - - friend class QGLTexturePool; - - friend void qt_gl_register_pixmap(QGLPixmapData *pd); - friend void qt_gl_unregister_pixmap(QGLPixmapData *pd); - friend void qt_gl_hibernate_pixmaps(); -#endif - - friend class QGLPixmapGLPaintDevice; - friend class QMeeGoPixmapData; - friend class QMeeGoLivePixmapData; -}; - -QT_END_NAMESPACE - -#endif // QPIXMAPDATA_GL_P_H - - diff --git a/src/opengl/qpixmapdata_poolgl.cpp b/src/opengl/qpixmapdata_poolgl.cpp deleted file mode 100644 index 5dd7b09c64..0000000000 --- a/src/opengl/qpixmapdata_poolgl.cpp +++ /dev/null @@ -1,934 +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 "qpixmap.h" -#include "qglframebufferobject.h" - -#include <private/qpaintengine_raster_p.h> - -#include "qpixmapdata_gl_p.h" - -#include <private/qgl_p.h> -#include <private/qdrawhelper_p.h> -#include <private/qimage_p.h> -#include <private/qnativeimagehandleprovider_p.h> -#include <private/qfont_p.h> - -#include <private/qpaintengineex_opengl2_p.h> - -#include <qdesktopwidget.h> -#include <qfile.h> -#include <qimagereader.h> -#include <qbuffer.h> - -#include "qgltexturepool_p.h" - -QT_BEGIN_NAMESPACE - -Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget(); - -static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo) -{ - return qAbs(size.width() * size.height() - fbo->width() * fbo->height()); -} - -extern int qt_next_power_of_two(int v); - -static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz) -{ -#ifdef QT_OPENGL_ES_2 - QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height())); - if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height()) - return rounded; -#endif - return sz; -} - - -QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize) -{ - QGLFramebufferObject *chosen = 0; - QGLFramebufferObject *candidate = 0; - for (int i = 0; !chosen && i < m_fbos.size(); ++i) { - QGLFramebufferObject *fbo = m_fbos.at(i); - - if (strictSize) { - if (fbo->size() == requestSize && fbo->format() == requestFormat) { - chosen = fbo; - break; - } else { - continue; - } - } - - if (fbo->format() == requestFormat) { - // choose the fbo with a matching format and the closest size - if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo)) - candidate = fbo; - } - - if (candidate) { - m_fbos.removeOne(candidate); - - const QSize fboSize = candidate->size(); - QSize sz = fboSize; - - if (sz.width() < requestSize.width()) - sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5))); - if (sz.height() < requestSize.height()) - sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5))); - - // wasting too much space? - if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4) - sz = requestSize; - - if (sz != fboSize) { - delete candidate; - candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat); - } - - chosen = candidate; - } - } - - if (!chosen) { - if (strictSize) - chosen = new QGLFramebufferObject(requestSize, requestFormat); - else - chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat); - } - - if (!chosen->isValid()) { - delete chosen; - chosen = 0; - } - - return chosen; -} - -void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo) -{ - if (fbo) - m_fbos << fbo; -} - - -QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const -{ - return data->paintEngine(); -} - -void QGLPixmapGLPaintDevice::beginPaint() -{ - if (!data->isValid()) - return; - - // QGLPaintDevice::beginPaint will store the current binding and replace - // it with m_thisFBO: - m_thisFBO = data->m_renderFbo->handle(); - QGLPaintDevice::beginPaint(); - - Q_ASSERT(data->paintEngine()->type() == QPaintEngine::OpenGL2); - - // QPixmap::fill() is deferred until now, where we actually need to do the fill: - if (data->needsFill()) { - const QColor &c = data->fillColor(); - float alpha = c.alphaF(); - glDisable(GL_SCISSOR_TEST); - glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha); - glClear(GL_COLOR_BUFFER_BIT); - } - else if (!data->isUninitialized()) { - // If the pixmap (GL Texture) has valid content (it has been - // uploaded from an image or rendered into before), we need to - // copy it from the texture to the render FBO. - - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - -#if !defined(QT_OPENGL_ES_2) - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, data->width(), data->height(), 0, -999999, 999999); -#endif - - glViewport(0, 0, data->width(), data->height()); - - // Pass false to bind so it doesn't copy the FBO into the texture! - context()->drawTexture(QRect(0, 0, data->width(), data->height()), data->bind(false)); - } -} - -void QGLPixmapGLPaintDevice::endPaint() -{ - if (!data->isValid()) - return; - - data->copyBackFromRenderFbo(false); - - // Base's endPaint will restore the previous FBO binding - QGLPaintDevice::endPaint(); - - qgl_fbo_pool()->release(data->m_renderFbo); - data->m_renderFbo = 0; -} - -QGLContext* QGLPixmapGLPaintDevice::context() const -{ - data->ensureCreated(); - return data->m_ctx; -} - -QSize QGLPixmapGLPaintDevice::size() const -{ - return data->size(); -} - -bool QGLPixmapGLPaintDevice::alphaRequested() const -{ - return data->m_hasAlpha; -} - -void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d) -{ - data = d; -} - -int qt_gl_pixmap_serial = 0; - -QGLPixmapData::QGLPixmapData(PixelType type) - : QPixmapData(type, OpenGLClass) - , m_renderFbo(0) - , m_engine(0) - , m_ctx(0) - , nativeImageHandleProvider(0) - , nativeImageHandle(0) - , m_dirty(false) - , m_hasFillColor(false) - , m_hasAlpha(false) - , inLRU(false) - , failedToAlloc(false) - , inTexturePool(false) -{ - setSerialNumber(++qt_gl_pixmap_serial); - m_glDevice.setPixmapData(this); - - qt_gl_register_pixmap(this); -} - -QGLPixmapData::~QGLPixmapData() -{ - delete m_engine; - - destroyTexture(); - qt_gl_unregister_pixmap(this); -} - -void QGLPixmapData::destroyTexture() -{ - if (inTexturePool) { - QGLTexturePool *pool = QGLTexturePool::instance(); - if (m_texture.id) - pool->releaseTexture(this, m_texture.id); - } else { - if (m_texture.id) { - QGLWidget *shareWidget = qt_gl_share_widget(); - if (shareWidget) { - QGLShareContextScope ctx(shareWidget->context()); - glDeleteTextures(1, &m_texture.id); - } - } - } - m_texture.id = 0; - inTexturePool = false; - - releaseNativeImageHandle(); -} - -QPixmapData *QGLPixmapData::createCompatiblePixmapData() const -{ - return new QGLPixmapData(pixelType()); -} - -bool QGLPixmapData::isValid() const -{ - return w > 0 && h > 0; -} - -bool QGLPixmapData::isValidContext(const QGLContext *ctx) const -{ - if (ctx == m_ctx) - return true; - - const QGLContext *share_ctx = qt_gl_share_widget()->context(); - return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); -} - -void QGLPixmapData::resize(int width, int height) -{ - if (width == w && height == h) - return; - - if (width <= 0 || height <= 0) { - width = 0; - height = 0; - } - - w = width; - h = height; - is_null = (w <= 0 || h <= 0); - d = pixelType() == QPixmapData::PixmapType ? 32 : 1; - - destroyTexture(); - - m_source = QVolatileImage(); - m_dirty = isValid(); - setSerialNumber(++qt_gl_pixmap_serial); -} - -void QGLPixmapData::ensureCreated() const -{ - if (!m_dirty) - return; - - m_dirty = false; - - if (nativeImageHandleProvider && !nativeImageHandle) - const_cast<QGLPixmapData *>(this)->createFromNativeImageHandleProvider(); - - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - m_ctx = ctx; - - const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB; -#ifdef QT_OPENGL_ES_2 - const GLenum external_format = internal_format; -#else - const GLenum external_format = qt_gl_preferredTextureFormat(); -#endif - const GLenum target = GL_TEXTURE_2D; - - GLenum type = GL_UNSIGNED_BYTE; - // Avoid conversion when pixmap is created from CFbsBitmap of EColor64K. - if (!m_source.isNull() && m_source.format() == QImage::Format_RGB16) - type = GL_UNSIGNED_SHORT_5_6_5; - - m_texture.options &= ~QGLContext::MemoryManagedBindOption; - - if (!m_texture.id) { - m_texture.id = QGLTexturePool::instance()->createTextureForPixmap( - target, - 0, internal_format, - w, h, - external_format, - type, - const_cast<QGLPixmapData*>(this)); - if (!m_texture.id) { - failedToAlloc = true; - return; - } - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - inTexturePool = true; - } else if (inTexturePool) { - glBindTexture(target, m_texture.id); - QGLTexturePool::instance()->useTexture(const_cast<QGLPixmapData*>(this)); - } - - if (!m_source.isNull() && m_texture.id) { - if (external_format == GL_RGB) { - m_source.beginDataAccess(); - QImage tx; - if (type == GL_UNSIGNED_BYTE) - tx = m_source.imageRef().convertToFormat(QImage::Format_RGB888).mirrored(false, true); - else if (type == GL_UNSIGNED_SHORT_5_6_5) - tx = m_source.imageRef().mirrored(false, true); - m_source.endDataAccess(true); - - glBindTexture(target, m_texture.id); - if (!tx.isNull()) - glTexSubImage2D(target, 0, 0, 0, w, h, external_format, - type, tx.constBits()); - else - qWarning("QGLPixmapData: Failed to create GL_RGB image of size %dx%d", w, h); - } else { - // do byte swizzling ARGB -> RGBA - m_source.beginDataAccess(); - const QImage tx = ctx->d_func()->convertToGLFormat(m_source.imageRef(), true, external_format); - m_source.endDataAccess(true); - glBindTexture(target, m_texture.id); - if (!tx.isNull()) - glTexSubImage2D(target, 0, 0, 0, w, h, external_format, - type, tx.constBits()); - else - qWarning("QGLPixmapData: Failed to create GL_RGBA image of size %dx%d", w, h); - } - - if (useFramebufferObjects()) - m_source = QVolatileImage(); - } -} - - -void QGLPixmapData::fromImage(const QImage &image, - Qt::ImageConversionFlags flags) -{ - QImage img = image; - createPixmapForImage(img, flags, false); -} - -void QGLPixmapData::fromImageReader(QImageReader *imageReader, - Qt::ImageConversionFlags flags) -{ - QImage image = imageReader->read(); - if (image.isNull()) - return; - - createPixmapForImage(image, flags, true); -} - -bool QGLPixmapData::fromFile(const QString &filename, const char *format, - Qt::ImageConversionFlags flags) -{ - if (pixelType() == QPixmapData::BitmapType) - return QPixmapData::fromFile(filename, format, flags); - QFile file(filename); - if (file.open(QIODevice::ReadOnly)) { - QByteArray data = file.peek(64); - bool alpha; - if (m_texture.canBindCompressedTexture - (data.constData(), data.size(), format, &alpha)) { - resize(0, 0); - data = file.readAll(); - file.close(); - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QSize size = m_texture.bindCompressedTexture - (data.constData(), data.size(), format); - if (!size.isEmpty()) { - w = size.width(); - h = size.height(); - is_null = false; - d = 32; - m_hasAlpha = alpha; - m_source = QVolatileImage(); - m_dirty = isValid(); - return true; - } - return false; - } - } - - QImage image = QImageReader(filename, format).read(); - if (image.isNull()) - return false; - - createPixmapForImage(image, flags, true); - - return !isNull(); -} - -bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, - Qt::ImageConversionFlags flags) -{ - bool alpha; - const char *buf = reinterpret_cast<const char *>(buffer); - if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) { - resize(0, 0); - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QSize size = m_texture.bindCompressedTexture(buf, int(len), format); - if (!size.isEmpty()) { - w = size.width(); - h = size.height(); - is_null = false; - d = 32; - m_hasAlpha = alpha; - m_source = QVolatileImage(); - m_dirty = isValid(); - return true; - } - } - - QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len); - QBuffer b(&a); - b.open(QIODevice::ReadOnly); - QImage image = QImageReader(&b, format).read(); - if (image.isNull()) - return false; - - createPixmapForImage(image, flags, true); - - return !isNull(); -} - -QImage::Format QGLPixmapData::idealFormat(QImage &image, Qt::ImageConversionFlags flags) -{ - QImage::Format format = QImage::Format_RGB32; - if (qApp->desktop()->depth() == 16) - format = QImage::Format_RGB16; - - if (image.hasAlphaChannel() - && ((flags & Qt::NoOpaqueDetection) - || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) - format = QImage::Format_ARGB32_Premultiplied; - - return format; -} - -void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) -{ - if (image.size() == QSize(w, h)) - setSerialNumber(++qt_gl_pixmap_serial); - - resize(image.width(), image.height()); - - if (pixelType() == BitmapType) { - QImage convertedImage = image.convertToFormat(QImage::Format_MonoLSB); - if (image.format() == QImage::Format_MonoLSB) - convertedImage.detach(); - - m_source = QVolatileImage(convertedImage); - - } else { - QImage::Format format = idealFormat(image, flags); - - if (inPlace && image.data_ptr()->convertInPlace(format, flags)) { - m_source = QVolatileImage(image); - } else { - QImage convertedImage = image.convertToFormat(format); - - // convertToFormat won't detach the image if format stays the same. - if (image.format() == format) - convertedImage.detach(); - - m_source = QVolatileImage(convertedImage); - } - } - - m_dirty = true; - m_hasFillColor = false; - - m_hasAlpha = m_source.hasAlphaChannel(); - w = image.width(); - h = image.height(); - is_null = (w <= 0 || h <= 0); - d = m_source.depth(); - - destroyTexture(); -} - -bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) -{ - Q_UNUSED(dx); - Q_UNUSED(dy); - Q_UNUSED(rect); - return false; -} - -void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect) -{ - if (data->classId() != QPixmapData::OpenGLClass || !static_cast<const QGLPixmapData *>(data)->useFramebufferObjects()) { - QPixmapData::copy(data, rect); - return; - } - - const QGLPixmapData *other = static_cast<const QGLPixmapData *>(data); - if (other->m_renderFbo) { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - - resize(rect.width(), rect.height()); - m_hasAlpha = other->m_hasAlpha; - ensureCreated(); - - if (!ctx->d_ptr->fbo) - glGenFramebuffers(1, &ctx->d_ptr->fbo); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, m_texture.id, 0); - - if (!other->m_renderFbo->isBound()) - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, other->m_renderFbo->handle()); - - glDisable(GL_SCISSOR_TEST); - if (ctx->d_ptr->active_engine && ctx->d_ptr->active_engine->type() == QPaintEngine::OpenGL2) - static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine)->invalidateState(); - - glBlitFramebufferEXT(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(), - 0, 0, w, h, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); - } else { - QPixmapData::copy(data, rect); - } -} - -void QGLPixmapData::fill(const QColor &color) -{ - if (!isValid()) - return; - - bool hasAlpha = color.alpha() != 255; - if (hasAlpha && !m_hasAlpha) { - if (m_texture.id) { - destroyTexture(); - m_dirty = true; - } - m_hasAlpha = color.alpha() != 255; - } - - if (useFramebufferObjects()) { - m_source = QVolatileImage(); - m_hasFillColor = true; - m_fillColor = color; - } else { - forceToImage(); - - if (m_source.depth() == 32) { - m_source.fill(PREMUL(color.rgba())); - - } else if (m_source.depth() == 1) { - if (color == Qt::color1) - m_source.fill(1); - else - m_source.fill(0); - } - } -} - -bool QGLPixmapData::hasAlphaChannel() const -{ - return m_hasAlpha; -} - -QImage QGLPixmapData::fillImage(const QColor &color) const -{ - QImage img; - if (pixelType() == BitmapType) { - img = QImage(w, h, QImage::Format_MonoLSB); - - img.setColorCount(2); - img.setColor(0, QColor(Qt::color0).rgba()); - img.setColor(1, QColor(Qt::color1).rgba()); - - if (color == Qt::color1) - img.fill(1); - else - img.fill(0); - } else { - img = QImage(w, h, - m_hasAlpha - ? QImage::Format_ARGB32_Premultiplied - : QImage::Format_RGB32); - img.fill(PREMUL(color.rgba())); - } - return img; -} - -extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha); - -QImage QGLPixmapData::toImage() const -{ - if (!isValid()) - return QImage(); - - if (m_renderFbo) { - copyBackFromRenderFbo(true); - } else if (!m_source.isNull()) { - // QVolatileImage::toImage() will make a copy always so no check - // for active painting is needed. - QImage img = m_source.toImage(); - if (img.format() == QImage::Format_MonoLSB) { - img.setColorCount(2); - img.setColor(0, QColor(Qt::color0).rgba()); - img.setColor(1, QColor(Qt::color1).rgba()); - } - return img; - } else if (m_dirty || m_hasFillColor) { - return fillImage(m_fillColor); - } else { - ensureCreated(); - } - - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glBindTexture(GL_TEXTURE_2D, m_texture.id); - return qt_gl_read_texture(QSize(w, h), true, true); -} - -struct TextureBuffer -{ - QGLFramebufferObject *fbo; - QGL2PaintEngineEx *engine; -}; - -Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool) -QGLFramebufferObjectPool* qgl_fbo_pool() -{ - return _qgl_fbo_pool(); -} - -void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const -{ - if (!isValid()) - return; - - m_hasFillColor = false; - - const QGLContext *share_ctx = qt_gl_share_widget()->context(); - QGLShareContextScope ctx(share_ctx); - - ensureCreated(); - - if (!ctx->d_ptr->fbo) - glGenFramebuffers(1, &ctx->d_ptr->fbo); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, m_texture.id, 0); - - const int x0 = 0; - const int x1 = w; - const int y0 = 0; - const int y1 = h; - - if (!m_renderFbo->isBound()) - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle()); - - glDisable(GL_SCISSOR_TEST); - - glBlitFramebufferEXT(x0, y0, x1, y1, - x0, y0, x1, y1, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - if (keepCurrentFboBound) { - glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); - } else { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_renderFbo->handle()); - ctx->d_ptr->current_fbo = m_renderFbo->handle(); - } -} - -bool QGLPixmapData::useFramebufferObjects() const -{ -#ifdef Q_OS_SYMBIAN - // We don't want to use FBOs on Symbian - return false; -#else - return QGLFramebufferObject::hasOpenGLFramebufferObjects() - && QGLFramebufferObject::hasOpenGLFramebufferBlit() - && qt_gl_preferGL2Engine() - && (w * h > 32*32); // avoid overhead of FBOs for small pixmaps -#endif -} - -QPaintEngine* QGLPixmapData::paintEngine() const -{ - if (!isValid()) - return 0; - - if (m_renderFbo) - return m_engine; - - if (useFramebufferObjects()) { - extern QGLWidget* qt_gl_share_widget(); - - if (!QGLContext::currentContext()) - qt_gl_share_widget()->makeCurrent(); - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - - QGLFramebufferObjectFormat format; - format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - format.setSamples(4); - format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB)); - - m_renderFbo = qgl_fbo_pool()->acquire(size(), format); - - if (m_renderFbo) { - if (!m_engine) - m_engine = new QGL2PaintEngineEx; - return m_engine; - } - - qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine"; - } - - // If the application wants to paint into the QPixmap, we first - // force it to QImage format and then paint into that. - // This is simpler than juggling multiple GL contexts. - const_cast<QGLPixmapData *>(this)->forceToImage(); - - if (m_hasFillColor) { - m_source.fill(PREMUL(m_fillColor.rgba())); - m_hasFillColor = false; - } - return m_source.paintEngine(); -} - -extern QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format); - -// If copyBack is true, bind will copy the contents of the render -// FBO to the texture (which is not bound to the texture, as it's -// a multisample FBO). -GLuint QGLPixmapData::bind(bool copyBack) const -{ - if (m_renderFbo && copyBack) { - copyBackFromRenderFbo(true); - } else { - ensureCreated(); - } - - GLuint id = m_texture.id; - glBindTexture(GL_TEXTURE_2D, id); - - if (m_hasFillColor) { - if (!useFramebufferObjects()) { - m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied); - m_source.fill(PREMUL(m_fillColor.rgba())); - } - - m_hasFillColor = false; - - GLenum format = qt_gl_preferredTextureFormat(); - QImage tx(w, h, QImage::Format_ARGB32_Premultiplied); - tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format)); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.constBits()); - } - - return id; -} - -QGLTexture* QGLPixmapData::texture() const -{ - return &m_texture; -} - -void QGLPixmapData::detachTextureFromPool() -{ - if (inTexturePool) { - QGLTexturePool::instance()->detachTexture(this); - inTexturePool = false; - } -} - -void QGLPixmapData::hibernate() -{ - // If the image was imported (e.g, from an SgImage under Symbian), then - // skip the hibernation, there is no sense in copying it back to main - // memory because the data is most likely shared between several processes. - bool skipHibernate = (m_texture.id && m_source.isNull()); -#if defined(Q_OS_SYMBIAN) - // However we have to proceed normally if the image was retrieved via - // a handle provider. - skipHibernate &= !nativeImageHandleProvider; -#endif - if (skipHibernate) - return; - - forceToImage(); - destroyTexture(); -} - -void QGLPixmapData::reclaimTexture() -{ - if (!inTexturePool) - return; - forceToImage(); - destroyTexture(); -} - -int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const -{ - if (w == 0) - return 0; - - switch (metric) { - case QPaintDevice::PdmWidth: - return w; - case QPaintDevice::PdmHeight: - return h; - case QPaintDevice::PdmNumColors: - return 0; - case QPaintDevice::PdmDepth: - return d; - case QPaintDevice::PdmWidthMM: - return qRound(w * 25.4 / qt_defaultDpiX()); - case QPaintDevice::PdmHeightMM: - return qRound(h * 25.4 / qt_defaultDpiY()); - case QPaintDevice::PdmDpiX: - case QPaintDevice::PdmPhysicalDpiX: - return qt_defaultDpiX(); - case QPaintDevice::PdmDpiY: - case QPaintDevice::PdmPhysicalDpiY: - return qt_defaultDpiY(); - default: - qWarning("QGLPixmapData::metric(): Invalid metric"); - return 0; - } -} - -// Force the pixmap data to be backed by some valid data. -void QGLPixmapData::forceToImage() -{ - if (!isValid()) - return; - - if (m_source.isNull()) { - QImage::Format format = QImage::Format_ARGB32_Premultiplied; - if (pixelType() == BitmapType) - format = QImage::Format_MonoLSB; - m_source = QVolatileImage(w, h, format); - } - - m_dirty = true; -} - -QGLPaintDevice *QGLPixmapData::glDevice() const -{ - return &m_glDevice; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp deleted file mode 100644 index 8a8eb38b7c..0000000000 --- a/src/opengl/qpixmapdata_x11gl_egl.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 <QDebug> - -#include <QtGui/private/qt_x11_p.h> -#include <QtGui/private/qegl_p.h> -#include <QtGui/private/qeglproperties_p.h> -#include <QtGui/private/qeglcontext_p.h> - -#if !defined(QT_OPENGL_ES_1) -#include <QtOpenGL/private/qpaintengineex_opengl2_p.h> -#endif - -#ifndef QT_OPENGL_ES_2 -#include <QtOpenGL/private/qpaintengine_opengl_p.h> -#endif - -#include <QtOpenGL/private/qgl_p.h> -#include <QtOpenGL/private/qgl_egl_p.h> - -#include "qpixmapdata_x11gl_p.h" - -QT_BEGIN_NAMESPACE - - -class QX11GLSharedContexts -{ -public: - QX11GLSharedContexts() - : rgbContext(0) - , argbContext(0) - , sharedQGLContext(0) - , sharePixmap(0) - { - EGLint rgbConfigId; - EGLint argbConfigId; - - do { - EGLConfig rgbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, QEgl::Renderable); - EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, - QEgl::Renderable | QEgl::Translucent); - - eglGetConfigAttrib(QEgl::display(), rgbConfig, EGL_CONFIG_ID, &rgbConfigId); - eglGetConfigAttrib(QEgl::display(), argbConfig, EGL_CONFIG_ID, &argbConfigId); - - rgbContext = new QEglContext; - rgbContext->setConfig(rgbConfig); - rgbContext->createContext(); - - if (!rgbContext->isValid()) - break; - - // If the RGB & ARGB configs are the same, use the same egl context for both: - if (rgbConfig == argbConfig) - argbContext = rgbContext; - - // Otherwise, create a separate context to be used for ARGB pixmaps: - if (!argbContext) { - argbContext = new QEglContext; - argbContext->setConfig(argbConfig); - bool success = argbContext->createContext(rgbContext); - if (!success) { - qWarning("QX11GLPixmapData - RGB & ARGB contexts aren't shared"); - success = argbContext->createContext(); - if (!success) - argbContext = rgbContext; // Might work, worth a shot at least. - } - } - - if (!argbContext->isValid()) - break; - - // Create the pixmap which will be used to create the egl surface for the share QGLContext - QX11PixmapData *rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); - rgbPixmapData->resize(8, 8); - rgbPixmapData->fill(Qt::red); - sharePixmap = new QPixmap(rgbPixmapData); - EGLSurface sharePixmapSurface = QEgl::createSurface(sharePixmap, rgbConfig); - rgbPixmapData->gl_surface = (void*)sharePixmapSurface; - - // Create the actual QGLContext which will be used for sharing - sharedQGLContext = new QGLContext(QX11GLPixmapData::glFormat()); - sharedQGLContext->d_func()->eglContext = rgbContext; - sharedQGLContext->d_func()->eglSurface = sharePixmapSurface; - sharedQGLContext->d_func()->valid = true; - qt_glformat_from_eglconfig(sharedQGLContext->d_func()->glFormat, rgbConfig); - - - valid = rgbContext->makeCurrent(sharePixmapSurface); - - // If the ARGB & RGB configs are different, check ARGB works too: - if (argbConfig != rgbConfig) { - QX11PixmapData *argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); - argbPixmapData->resize(8, 8); - argbPixmapData->fill(Qt::transparent); // Force ARGB - QPixmap argbPixmap(argbPixmapData); // destroys pixmap data when goes out of scope - EGLSurface argbPixmapSurface = QEgl::createSurface(&argbPixmap, argbConfig); - valid = argbContext->makeCurrent(argbPixmapSurface); - argbContext->doneCurrent(); - eglDestroySurface(QEgl::display(), argbPixmapSurface); - argbPixmapData->gl_surface = 0; - } - - if (!valid) { - qWarning() << "Unable to make pixmap surface current:" << QEgl::errorString(); - break; - } - - // The pixmap surface destruction hooks are installed by QGLTextureCache, so we - // must make sure this is instanciated: - QGLTextureCache::instance(); - } while(0); - - if (!valid) - cleanup(); - else - qDebug("Using QX11GLPixmapData with EGL config %d for ARGB and config %d for RGB", argbConfigId, rgbConfigId); - - } - - ~QX11GLSharedContexts() { - cleanup(); - } - - void cleanup() { - if (sharedQGLContext) { - delete sharedQGLContext; - sharedQGLContext = 0; - } - if (argbContext && argbContext != rgbContext) - delete argbContext; - argbContext = 0; - - if (rgbContext) { - delete rgbContext; - rgbContext = 0; - } - - // Deleting the QPixmap will fire the pixmap destruction cleanup hooks which in turn - // will destroy the egl surface: - if (sharePixmap) { - delete sharePixmap; - sharePixmap = 0; - } - } - - bool isValid() { return valid;} - - // On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need - // different contexts: - QEglContext *rgbContext; - QEglContext *argbContext; - - // The share context wraps the rgbContext and is used as the master of the context share - // group. As all other contexts will have the same egl context (or a shared one if rgb != argb) - // all QGLContexts will actually be sharing and can be in the same context group. - QGLContext *sharedQGLContext; -private: - QPixmap *sharePixmap; - bool valid; -}; - -static void qt_cleanup_x11gl_share_contexts(); - -Q_GLOBAL_STATIC_WITH_INITIALIZER(QX11GLSharedContexts, qt_x11gl_share_contexts, - { - qAddPostRoutine(qt_cleanup_x11gl_share_contexts); - }) - -static void qt_cleanup_x11gl_share_contexts() -{ - qt_x11gl_share_contexts()->cleanup(); -} - - -QX11GLSharedContexts* QX11GLPixmapData::sharedContexts() -{ - return qt_x11gl_share_contexts(); -} - -bool QX11GLPixmapData::hasX11GLPixmaps() -{ - static bool checkedForX11GLPixmaps = false; - static bool haveX11GLPixmaps = false; - - if (checkedForX11GLPixmaps) - return haveX11GLPixmaps; - - haveX11GLPixmaps = qt_x11gl_share_contexts()->isValid(); - checkedForX11GLPixmaps = true; - - return haveX11GLPixmaps; -} - -QX11GLPixmapData::QX11GLPixmapData() - : QX11PixmapData(QPixmapData::PixmapType), - ctx(0) -{ -} - -QX11GLPixmapData::~QX11GLPixmapData() -{ - if (ctx) - delete ctx; -} - - -void QX11GLPixmapData::fill(const QColor &color) -{ - if (ctx) { - ctx->makeCurrent(); - glFinish(); - eglWaitClient(); - } - - QX11PixmapData::fill(color); - XSync(X11->display, False); - - if (ctx) { - ctx->makeCurrent(); - eglWaitNative(EGL_CORE_NATIVE_ENGINE); - } -} - -void QX11GLPixmapData::copy(const QPixmapData *data, const QRect &rect) -{ - if (ctx) { - ctx->makeCurrent(); - glFinish(); - eglWaitClient(); - } - - QX11PixmapData::copy(data, rect); - XSync(X11->display, False); - - if (ctx) { - ctx->makeCurrent(); - eglWaitNative(EGL_CORE_NATIVE_ENGINE); - } -} - -bool QX11GLPixmapData::scroll(int dx, int dy, const QRect &rect) -{ - if (ctx) { - ctx->makeCurrent(); - glFinish(); - eglWaitClient(); - } - - bool success = QX11PixmapData::scroll(dx, dy, rect); - XSync(X11->display, False); - - if (ctx) { - ctx->makeCurrent(); - eglWaitNative(EGL_CORE_NATIVE_ENGINE); - } - - return success; -} - -#if !defined(QT_OPENGL_ES_1) -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_pixmap_2_engine) -#endif - -#ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_pixmap_engine) -#endif - - -QPaintEngine* QX11GLPixmapData::paintEngine() const -{ - // We need to create the context before beginPaint - do it here: - if (!ctx) { - ctx = new QGLContext(glFormat()); - Q_ASSERT(ctx->d_func()->eglContext == 0); - ctx->d_func()->eglContext = hasAlphaChannel() ? sharedContexts()->argbContext : sharedContexts()->rgbContext; - - // While we use a separate QGLContext for each pixmap, the underlying QEglContext is - // the same. So we must use a "fake" QGLContext and fool the texture cache into thinking - // each pixmap's QGLContext is sharing with this central one. The only place this is - // going to fail is where we the underlying EGL RGB and ARGB contexts aren't sharing. - ctx->d_func()->sharing = true; - QGLContextGroup::addShare(ctx, sharedContexts()->sharedQGLContext); - - // Update the glFormat for the QGLContext: - qt_glformat_from_eglconfig(ctx->d_func()->glFormat, ctx->d_func()->eglContext->config()); - } - - QPaintEngine* engine; - -#if defined(QT_OPENGL_ES_1) - engine = qt_gl_pixmap_engine(); -#elif defined(QT_OPENGL_ES_2) - engine = qt_gl_pixmap_2_engine(); -#else - if (qt_gl_preferGL2Engine()) - engine = qt_gl_pixmap_2_engine(); - else - engine = qt_gl_pixmap_engine(); -#endif - - - - // Support multiple painters on multiple pixmaps simultaniously - if (engine->isActive()) { - qWarning("Pixmap paint engine already active"); - -#if defined(QT_OPENGL_ES_1) - engine = new QOpenGLPaintEngine; -#elif defined(QT_OPENGL_ES_2) - engine = new QGL2PaintEngineEx; -#else - if (qt_gl_preferGL2Engine()) - engine = new QGL2PaintEngineEx; - else - engine = new QOpenGLPaintEngine; -#endif - - engine->setAutoDestruct(true); - return engine; - } - - return engine; -} - -void QX11GLPixmapData::beginPaint() -{ -// qDebug("QX11GLPixmapData::beginPaint()"); - // TODO: Check to see if the surface is renderable - if ((EGLSurface)gl_surface == EGL_NO_SURFACE) { - QPixmap tmpPixmap(this); - EGLConfig cfg = ctx->d_func()->eglContext->config(); - Q_ASSERT(cfg != QEGL_NO_CONFIG); - -// qDebug("QX11GLPixmapData - using EGL Config ID %d", ctx->d_func()->eglContext->configAttrib(EGL_CONFIG_ID)); - EGLSurface surface = QEgl::createSurface(&tmpPixmap, cfg); - if (surface == EGL_NO_SURFACE) { - qWarning() << "Error creating EGL surface for pixmap:" << QEgl::errorString(); - return; - } - gl_surface = (void*)surface; - ctx->d_func()->eglSurface = surface; - ctx->d_func()->valid = true; - } - QGLPaintDevice::beginPaint(); -} - -QGLContext* QX11GLPixmapData::context() const -{ - return ctx; -} - -QSize QX11GLPixmapData::size() const -{ - return QSize(w, h); -} - - -QGLFormat QX11GLPixmapData::glFormat() -{ - return QGLFormat::defaultFormat(); //### -} - -QT_END_NAMESPACE diff --git a/src/opengl/qpixmapdata_x11gl_p.h b/src/opengl/qpixmapdata_x11gl_p.h deleted file mode 100644 index 0a6c4e8f2f..0000000000 --- a/src/opengl/qpixmapdata_x11gl_p.h +++ /dev/null @@ -1,98 +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 QPIXMAPDATA_X11GL_P_H -#define QPIXMAPDATA_X11GL_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 <private/qpixmapdata_p.h> -#include <private/qpixmap_x11_p.h> -#include <private/qglpaintdevice_p.h> - -#include <qgl.h> - -#ifndef QT_NO_EGL -#include <QtGui/private/qeglcontext_p.h> -#endif - -QT_BEGIN_NAMESPACE - -class QX11GLSharedContexts; - -class QX11GLPixmapData : public QX11PixmapData, public QGLPaintDevice -{ -public: - QX11GLPixmapData(); - virtual ~QX11GLPixmapData(); - - // Re-implemented from QX11PixmapData: - void fill(const QColor &color); - void copy(const QPixmapData *data, const QRect &rect); - bool scroll(int dx, int dy, const QRect &rect); - - // Re-implemented from QGLPaintDevice - QPaintEngine* paintEngine() const; // Also re-implements QX11PixmapData::paintEngine - void beginPaint(); - QGLContext* context() const; - QSize size() const; - - static bool hasX11GLPixmaps(); - static QGLFormat glFormat(); - static QX11GLSharedContexts* sharedContexts(); - -private: - mutable QGLContext* ctx; -}; - - -QT_END_NAMESPACE - -#endif // QPIXMAPDATA_X11GL_P_H diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp deleted file mode 100644 index 4f00908b9d..0000000000 --- a/src/opengl/qwindowsurface_gl.cpp +++ /dev/null @@ -1,1174 +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 <QtGui/QApplication> -#include <QtGui/QColormap> -#include <QtGui/QDesktopWidget> -#include <QtGui/QPaintDevice> -#include <QtGui/QWidget> - -#include <qglframebufferobject.h> -#include <qglpixelbuffer.h> -#include <qcolormap.h> -#include <qdesktopwidget.h> -#include <private/qwidget_p.h> -#include "qdebug.h" - -#ifdef Q_WS_X11 -#include <private/qt_x11_p.h> -#include <qx11info_x11.h> - -#ifndef QT_OPENGL_ES -#include <GL/glx.h> -#include <X11/Xlib.h> -#endif -#endif //Q_WS_X11 - -#include <private/qglextensions_p.h> -#include <private/qwindowsurface_gl_p.h> - -#include <private/qgl_p.h> - -#include <private/qglpixelbuffer_p.h> -#include <private/qgraphicssystem_gl_p.h> - -#include <private/qpaintengineex_opengl2_p.h> -#include <private/qpixmapdata_gl_p.h> - -#ifndef QT_OPENGL_ES_2 -#include <private/qpaintengine_opengl_p.h> -#endif - -#ifndef GLX_ARB_multisample -#define GLX_SAMPLE_BUFFERS_ARB 100000 -#define GLX_SAMPLES_ARB 100001 -#endif - -#ifndef QT_NO_EGL -#include <private/qeglcontext_p.h> -#endif - -QT_BEGIN_NAMESPACE - -// -// QGLGraphicsSystem -// -#ifdef Q_WS_WIN -extern Q_GUI_EXPORT bool qt_win_owndc_required; -#endif -QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) - : QGraphicsSystem(), m_useX11GL(useX11GL) -{ -#if defined(Q_WS_X11) && !defined(QT_OPENGL_ES) - // only override the system defaults if the user hasn't already - // picked a visual - if (X11->visual == 0 && X11->visual_id == -1 && X11->visual_class == -1) { - // find a double buffered, RGBA visual that supports OpenGL - // and set that as the default visual for windows in Qt - int i = 0; - int spec[16]; - spec[i++] = GLX_RGBA; - spec[i++] = GLX_DOUBLEBUFFER; - - if (!qgetenv("QT_GL_SWAPBUFFER_PRESERVE").isNull()) { - spec[i++] = GLX_DEPTH_SIZE; - spec[i++] = 8; - spec[i++] = GLX_STENCIL_SIZE; - spec[i++] = 8; - spec[i++] = GLX_SAMPLE_BUFFERS_ARB; - spec[i++] = 1; - spec[i++] = GLX_SAMPLES_ARB; - spec[i++] = 4; - } - - spec[i++] = XNone; - - XVisualInfo *vi = glXChooseVisual(X11->display, X11->defaultScreen, spec); - if (vi) { - X11->visual_id = vi->visualid; - X11->visual_class = vi->c_class; - - QGLFormat format; - int res; - glXGetConfig(X11->display, vi, GLX_LEVEL, &res); - format.setPlane(res); - glXGetConfig(X11->display, vi, GLX_DOUBLEBUFFER, &res); - format.setDoubleBuffer(res); - glXGetConfig(X11->display, vi, GLX_DEPTH_SIZE, &res); - format.setDepth(res); - if (format.depth()) - format.setDepthBufferSize(res); - glXGetConfig(X11->display, vi, GLX_RGBA, &res); - format.setRgba(res); - glXGetConfig(X11->display, vi, GLX_RED_SIZE, &res); - format.setRedBufferSize(res); - glXGetConfig(X11->display, vi, GLX_GREEN_SIZE, &res); - format.setGreenBufferSize(res); - glXGetConfig(X11->display, vi, GLX_BLUE_SIZE, &res); - format.setBlueBufferSize(res); - glXGetConfig(X11->display, vi, GLX_ALPHA_SIZE, &res); - format.setAlpha(res); - if (format.alpha()) - format.setAlphaBufferSize(res); - glXGetConfig(X11->display, vi, GLX_ACCUM_RED_SIZE, &res); - format.setAccum(res); - if (format.accum()) - format.setAccumBufferSize(res); - glXGetConfig(X11->display, vi, GLX_STENCIL_SIZE, &res); - format.setStencil(res); - if (format.stencil()) - format.setStencilBufferSize(res); - glXGetConfig(X11->display, vi, GLX_STEREO, &res); - format.setStereo(res); - glXGetConfig(X11->display, vi, GLX_SAMPLE_BUFFERS_ARB, &res); - format.setSampleBuffers(res); - if (format.sampleBuffers()) { - glXGetConfig(X11->display, vi, GLX_SAMPLES_ARB, &res); - format.setSamples(res); - } - - QGLWindowSurface::surfaceFormat = format; - XFree(vi); - - printf("using visual class %x, id %x\n", X11->visual_class, X11->visual_id); - } - } -#elif defined(Q_WS_WIN) - QGLWindowSurface::surfaceFormat.setDoubleBuffer(true); - - qt_win_owndc_required = true; -#endif -} - -static void qt_cleanup_gl_share_widget(); - -// -// QGLWindowSurface -// -class QGLGlobalShareWidget -{ -public: - QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) { - // ### FIXME - readd the post routine if the qApp is recreated - qAddPostRoutine(qt_cleanup_gl_share_widget); - created = true; - } - - QGLWidget *shareWidget() { - if (!initializing && !widget && !cleanedUp) { - initializing = true; - widget = new QGLWidget(QGLFormat(QGL::SingleBuffer | QGL::NoDepthBuffer | QGL::NoStencilBuffer)); - widget->resize(1, 1); - - // We don't need this internal widget to appear in QApplication::topLevelWidgets() - if (QWidgetPrivate::allWidgets) - QWidgetPrivate::allWidgets->remove(widget); - initializing = false; - } - return widget; - } - - // destroys the share widget and prevents recreation - void cleanup() { - QGLWidget *w = widget; - cleanedUp = true; - widget = 0; - delete w; - } - - // destroys the share widget, but allows it to be recreated later on - void destroy() { - if (cleanedUp) - return; - - QGLWidget *w = widget; - - // prevent potential recursions - cleanedUp = true; - widget = 0; - delete w; - cleanedUp = false; - } - - static bool cleanedUp; - static bool created; - - QGLPixmapData *firstPixmap; - int widgetRefCount; - -private: - QGLWidget *widget; - bool initializing; -}; - -bool QGLGlobalShareWidget::cleanedUp = false; -bool QGLGlobalShareWidget::created = false; - -Q_GLOBAL_STATIC(QGLGlobalShareWidget, _qt_gl_share_widget) - -static void qt_cleanup_gl_share_widget() -{ - if (QGLGlobalShareWidget::created) - _qt_gl_share_widget()->cleanup(); -} - -QGLWidget* qt_gl_share_widget() -{ - if (QGLGlobalShareWidget::cleanedUp) - return 0; - return _qt_gl_share_widget()->shareWidget(); -} - -void qt_destroy_gl_share_widget() -{ - if (QGLGlobalShareWidget::created) - _qt_gl_share_widget()->destroy(); -} - -const QGLContext *qt_gl_share_context() -{ - QGLWidget *widget = qt_gl_share_widget(); - if (widget) - return widget->context(); - return 0; -} - -#ifdef QGL_USE_TEXTURE_POOL -void qt_gl_register_pixmap(QGLPixmapData *pd) -{ - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - pd->next = shared->firstPixmap; - pd->prev = 0; - if (shared->firstPixmap) - shared->firstPixmap->prev = pd; - shared->firstPixmap = pd; -} - -void qt_gl_unregister_pixmap(QGLPixmapData *pd) -{ - if (pd->next) - pd->next->prev = pd->prev; - if (pd->prev) { - pd->prev->next = pd->next; - } else { - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - if (shared) - shared->firstPixmap = pd->next; - } -} - -void qt_gl_hibernate_pixmaps() -{ - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - - // Scan all QGLPixmapData objects in the system and hibernate them. - QGLPixmapData *pd = shared->firstPixmap; - while (pd != 0) { - pd->hibernate(); - pd = pd->next; - } -} -#endif - -struct QGLWindowSurfacePrivate -{ - QGLFramebufferObject *fbo; - QGLPixelBuffer *pb; - GLuint tex_id; - GLuint pb_tex_id; - - int tried_fbo : 1; - int tried_pb : 1; - int destructive_swap_buffers : 1; - int geometry_updated : 1; - int did_paint : 1; - - QGLContext *ctx; - - QList<QGLContext **> contexts; - - QRegion paintedRegion; - QSize size; - - QSize textureSize; - - QList<QImage> buffers; - QGLWindowSurfaceGLPaintDevice glDevice; - QGLWindowSurface* q_ptr; - - bool swap_region_support; -}; - -QGLFormat QGLWindowSurface::surfaceFormat; -QGLWindowSurface::SwapMode QGLWindowSurface::swapBehavior = QGLWindowSurface::AutomaticSwap; - -void QGLWindowSurfaceGLPaintDevice::endPaint() -{ - glFlush(); - QGLPaintDevice::endPaint(); -} - -QSize QGLWindowSurfaceGLPaintDevice::size() const -{ - return d->size; -} - -QGLContext* QGLWindowSurfaceGLPaintDevice::context() const -{ - return d->ctx; -} - - -int QGLWindowSurfaceGLPaintDevice::metric(PaintDeviceMetric m) const -{ - return qt_paint_device_metric(d->q_ptr->window(), m); -} - -QPaintEngine *QGLWindowSurfaceGLPaintDevice::paintEngine() const -{ - return qt_qgl_paint_engine(); -} - -QGLWindowSurface::QGLWindowSurface(QWidget *window) - : QWindowSurface(window), d_ptr(new QGLWindowSurfacePrivate) -{ -// Q_ASSERT(window->isTopLevel()); - d_ptr->pb = 0; - d_ptr->fbo = 0; - d_ptr->ctx = 0; - d_ptr->tex_id = 0; -#if defined (QT_OPENGL_ES_2) - d_ptr->tried_fbo = true; - d_ptr->tried_pb = true; -#else - d_ptr->tried_fbo = false; - d_ptr->tried_pb = false; -#endif - d_ptr->destructive_swap_buffers = qgetenv("QT_GL_SWAPBUFFER_PRESERVE").isNull(); - d_ptr->glDevice.d = d_ptr; - d_ptr->q_ptr = this; - d_ptr->geometry_updated = false; - d_ptr->did_paint = false; - d_ptr->swap_region_support = false; -} - -QGLWindowSurface::~QGLWindowSurface() -{ - if (d_ptr->ctx) - glDeleteTextures(1, &d_ptr->tex_id); -#ifndef Q_WS_QPA // Dont delete the contexts. Destroying the window does that for us - foreach(QGLContext **ctx, d_ptr->contexts) { - delete *ctx; - *ctx = 0; - } -#endif - delete d_ptr->pb; - delete d_ptr->fbo; - delete d_ptr; - - if (QGLGlobalShareWidget::cleanedUp) - return; - - --(_qt_gl_share_widget()->widgetRefCount); - -#ifdef QGL_USE_TEXTURE_POOL - if (_qt_gl_share_widget()->widgetRefCount <= 0) { - // All of the widget window surfaces have been destroyed - // but we still have GL pixmaps active. Ask them to hibernate - // to free up GPU resources until a widget is shown again. - // This may eventually cause the EGLContext to be destroyed - // because nothing in the system needs a context, which will - // free up even more GPU resources. - qt_gl_hibernate_pixmaps(); - - // Destroy the context if necessary. - if (!qt_gl_share_widget()->context()->isSharing()) - qt_destroy_gl_share_widget(); - } -#endif // QGL_USE_TEXTURE_POOL -} - -void QGLWindowSurface::deleted(QObject *object) -{ - QWidget *widget = qobject_cast<QWidget *>(object); - if (widget) { - if (widget == window()) { - // Make sure that the fbo is destroyed before destroying its context. - delete d_ptr->fbo; - d_ptr->fbo = 0; - } - -#ifndef Q_WS_QPA //no need to specifically delete the QGLContext as it will be deleted by QWidget - QWidgetPrivate *widgetPrivate = widget->d_func(); - if (widgetPrivate->extraData()) { - union { QGLContext **ctxPtrPtr; void **voidPtrPtr; }; - voidPtrPtr = &widgetPrivate->extraData()->glContext; - int index = d_ptr->contexts.indexOf(ctxPtrPtr); - if (index != -1) { - delete *ctxPtrPtr; - *ctxPtrPtr = 0; - d_ptr->contexts.removeAt(index); - } - } -#endif - } -} - -void QGLWindowSurface::hijackWindow(QWidget *widget) -{ - QWidgetPrivate *widgetPrivate = widget->d_func(); - widgetPrivate->createExtra(); - if (widgetPrivate->extraData()->glContext) - return; - - QGLContext *ctx = NULL; - - // For translucent top-level widgets we need alpha in the format. - if (widget->testAttribute(Qt::WA_TranslucentBackground)) { - QGLFormat modFormat(surfaceFormat); - modFormat.setSampleBuffers(false); - modFormat.setSamples(0); - modFormat.setAlpha(true); - ctx = new QGLContext(modFormat, widget); - } else - ctx = new QGLContext(surfaceFormat, widget); - - ctx->create(qt_gl_share_context()); - - if (widget != qt_gl_share_widget()) - ++(_qt_gl_share_widget()->widgetRefCount); - -#ifndef QT_NO_EGL - static bool checkedForNOKSwapRegion = false; - static bool haveNOKSwapRegion = false; - - if (!checkedForNOKSwapRegion) { - haveNOKSwapRegion = QEgl::hasExtension("EGL_NOK_swap_region2"); - checkedForNOKSwapRegion = true; - - if (haveNOKSwapRegion) - qDebug() << "Found EGL_NOK_swap_region2 extension. Using partial updates."; - } - - d_ptr->destructive_swap_buffers = true; - if (ctx->d_func()->eglContext->configAttrib(EGL_SURFACE_TYPE)&EGL_SWAP_BEHAVIOR_PRESERVED_BIT) { - EGLint swapBehavior; - if (eglQuerySurface(ctx->d_func()->eglContext->display(), ctx->d_func()->eglSurface - , EGL_SWAP_BEHAVIOR, &swapBehavior)) { - d_ptr->destructive_swap_buffers = (swapBehavior != EGL_BUFFER_PRESERVED); - } - } - - d_ptr->swap_region_support = haveNOKSwapRegion; -#endif - - widgetPrivate->extraData()->glContext = ctx; - - union { QGLContext **ctxPtrPtr; void **voidPtrPtr; }; - - connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(deleted(QObject*))); - - voidPtrPtr = &widgetPrivate->extraData()->glContext; - d_ptr->contexts << ctxPtrPtr; -#ifndef Q_OS_SYMBIAN - qDebug() << "hijackWindow() context created for" << widget << d_ptr->contexts.size(); -#endif -} - -QGLContext *QGLWindowSurface::context() const -{ - return d_ptr->ctx; -} - -QPaintDevice *QGLWindowSurface::paintDevice() -{ - updateGeometry(); - - if (d_ptr->pb) - return d_ptr->pb; - - if (d_ptr->ctx) - return &d_ptr->glDevice; - - QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext); - ctx->makeCurrent(); - - Q_ASSERT(d_ptr->fbo); - return d_ptr->fbo; -} - -static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &src = QRectF()); - -void QGLWindowSurface::beginPaint(const QRegion &) -{ - d_ptr->did_paint = true; - updateGeometry(); - - int clearFlags = 0; - - QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext); - - if (!ctx) - return; - - if (ctx->d_func()->workaround_needsFullClearOnEveryFrame) - clearFlags = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; - else if (ctx->format().alpha()) - clearFlags = GL_COLOR_BUFFER_BIT; - - if (clearFlags) { - if (d_ptr->fbo) - d_ptr->fbo->bind(); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(clearFlags); - - if (d_ptr->fbo) - d_ptr->fbo->release(); - } -} - -void QGLWindowSurface::endPaint(const QRegion &rgn) -{ - if (context()) - d_ptr->paintedRegion |= rgn; - - d_ptr->buffers.clear(); -} - -static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport, const QSize &texSize, const QRect &targetRect, const QRect &sourceRect) -{ - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - - glViewport(0, 0, viewport.width(), viewport.height()); - - QGLShaderProgram *blitProgram = - QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram(); - blitProgram->bind(); - blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); - - // The shader manager's blit program does not multiply the - // vertices by the pmv matrix, so we need to do the effect - // of the orthographic projection here ourselves. - QRectF r; - qreal w = viewport.width(); - qreal h = viewport.height(); - r.setLeft((targetRect.left() / w) * 2.0f - 1.0f); - if (targetRect.right() == (viewport.width() - 1)) - r.setRight(1.0f); - else - r.setRight((targetRect.right() / w) * 2.0f - 1.0f); - r.setBottom((targetRect.top() / h) * 2.0f - 1.0f); - if (targetRect.bottom() == (viewport.height() - 1)) - r.setTop(1.0f); - else - r.setTop((targetRect.bottom() / w) * 2.0f - 1.0f); - - drawTexture(r, texture, texSize, sourceRect); -} - - -void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) -{ - //### Find out why d_ptr->geometry_updated isn't always false. - // flush() should not be called when d_ptr->geometry_updated is true. It assumes that either - // d_ptr->fbo or d_ptr->pb is allocated and has the correct size. - if (d_ptr->geometry_updated) - return; - - // did_paint is set to true in ::beginPaint. ::beginPaint means that we - // at least cleared the background (= painted something). In EGL API it's a - // mistake to call swapBuffers if nothing was painted unless - // EGL_BUFFER_PRESERVED is set. This check protects the flush func from - // being executed if it's for nothing. - if (!d_ptr->destructive_swap_buffers && !d_ptr->did_paint) - return; - -#ifdef Q_OS_SYMBIAN - if (window() != widget) { - // For performance reasons we don't support - // flushing native child widgets on Symbian. - // It breaks overlapping native child widget - // rendering in some cases but we prefer performance. - return; - } -#endif - - - QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget(); - Q_ASSERT(parent); - -#if !defined(Q_WS_QPA) - if (!geometry().isValid()) - return; -#else - if (!size().isValid()) - return; -#endif - - // Needed to support native child-widgets... - hijackWindow(parent); - - QRect br = rgn.boundingRect().translated(offset); - br = br.intersected(window()->rect()); - QPoint wOffset = qt_qwidget_data(parent)->wrect.topLeft(); - QRect rect = br.translated(-offset - wOffset); - - const GLenum target = GL_TEXTURE_2D; - Q_UNUSED(target); - - if (QGLWindowSurface::swapBehavior == QGLWindowSurface::KillSwap) - return; - - if (context()) { - context()->makeCurrent(); - - if (context()->format().doubleBuffer()) { -#if !defined(QT_OPENGL_ES_2) - if (d_ptr->destructive_swap_buffers) { - glBindTexture(target, d_ptr->tex_id); - - QVector<QRect> rects = d_ptr->paintedRegion.rects(); - for (int i = 0; i < rects.size(); ++i) { - QRect br = rects.at(i); - if (br.isEmpty()) - continue; - - const uint bottom = window()->height() - (br.y() + br.height()); - glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height()); - } - - glBindTexture(target, 0); - - QRegion dirtyRegion = QRegion(window()->rect()) - d_ptr->paintedRegion; - - if (!dirtyRegion.isEmpty()) { - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); -#ifndef QT_OPENGL_ES - glOrtho(0, window()->width(), window()->height(), 0, -999999, 999999); -#else - glOrthof(0, window()->width(), window()->height(), 0, -999999, 999999); -#endif - glViewport(0, 0, window()->width(), window()->height()); - - QVector<QRect> rects = dirtyRegion.rects(); - glColor4f(1, 1, 1, 1); - for (int i = 0; i < rects.size(); ++i) { - QRect rect = rects.at(i); - if (rect.isEmpty()) - continue; - - drawTexture(rect, d_ptr->tex_id, window()->size(), rect); - } - } - } -#endif - bool doingPartialUpdate = false; - if (d_ptr->swap_region_support) { - if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AutomaticSwap) - doingPartialUpdate = br.width() * br.height() < parent->geometry().width() * parent->geometry().height() * 0.2; - else if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AlwaysPartialSwap) - doingPartialUpdate = true; - } - - QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext); - if (widget != window()) { - if (initializeOffscreenTexture(window()->size())) - qWarning() << "QGLWindowSurface: Flushing to native child widget, may lead to significant performance loss"; - glBindTexture(target, d_ptr->tex_id); - - const uint bottom = window()->height() - (br.y() + br.height()); - glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height()); - - glBindTexture(target, 0); - - ctx->makeCurrent(); - if (doingPartialUpdate) - blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), rect, br); - else - blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), parent->rect(), parent->rect().translated(offset + wOffset)); - } - - if (doingPartialUpdate) - ctx->d_func()->swapRegion(br); - else - ctx->swapBuffers(); - - d_ptr->paintedRegion = QRegion(); - } else { - glFlush(); - } - return; - } - - QGLContext *previous_ctx = const_cast<QGLContext *>(QGLContext::currentContext()); - QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext); - - // QPainter::end() should have unbound the fbo, otherwise something is very wrong... - Q_ASSERT(!d_ptr->fbo || !d_ptr->fbo->isBound()); - - if (ctx != previous_ctx) { - ctx->makeCurrent(); - } - - QSize size = widget->rect().size(); - if (d_ptr->destructive_swap_buffers && ctx->format().doubleBuffer()) { - rect = parent->rect(); - br = rect.translated(wOffset + offset); - size = parent->size(); - } - - glDisable(GL_SCISSOR_TEST); - - if (d_ptr->fbo && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)) { - const int h = d_ptr->fbo->height(); - - const int sx0 = br.left(); - const int sx1 = br.left() + br.width(); - const int sy0 = h - (br.top() + br.height()); - const int sy1 = h - br.top(); - - const int tx0 = rect.left(); - const int tx1 = rect.left() + rect.width(); - const int ty0 = parent->height() - (rect.top() + rect.height()); - const int ty1 = parent->height() - rect.top(); - - if (window() == parent || d_ptr->fbo->format().samples() <= 1) { - if (ctx->d_ptr->current_fbo != 0) - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); - - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); - - glBlitFramebufferEXT(sx0, sy0, sx1, sy1, - tx0, ty0, tx1, ty1, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0); - } else { - // can't do sub-region blits with multisample FBOs - QGLFramebufferObject *temp = qgl_fbo_pool()->acquire(d_ptr->fbo->size(), QGLFramebufferObjectFormat()); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, temp->handle()); - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); - - glBlitFramebufferEXT(0, 0, d_ptr->fbo->width(), d_ptr->fbo->height(), - 0, 0, d_ptr->fbo->width(), d_ptr->fbo->height(), - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, temp->handle()); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); - - glBlitFramebufferEXT(sx0, sy0, sx1, sy1, - tx0, ty0, tx1, ty1, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0); - - qgl_fbo_pool()->release(temp); - } - - ctx->d_ptr->current_fbo = 0; - } -#if !defined(QT_OPENGL_ES_2) - else { - GLuint texture; - if (d_ptr->fbo) { - texture = d_ptr->fbo->texture(); - } else { - d_ptr->pb->makeCurrent(); - glBindTexture(target, d_ptr->pb_tex_id); - const uint bottom = window()->height() - (br.y() + br.height()); - glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height()); - texture = d_ptr->pb_tex_id; - glBindTexture(target, 0); - } - - glDisable(GL_DEPTH_TEST); - - if (d_ptr->fbo) { - d_ptr->fbo->release(); - } else { - ctx->makeCurrent(); - } - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); -#ifndef QT_OPENGL_ES - glOrtho(0, size.width(), size.height(), 0, -999999, 999999); -#else - glOrthof(0, size.width(), size.height(), 0, -999999, 999999); -#endif - glViewport(0, 0, size.width(), size.height()); - - glColor4f(1, 1, 1, 1); - drawTexture(rect, texture, window()->size(), br); - - if (d_ptr->fbo) - d_ptr->fbo->bind(); - } -#else - // OpenGL/ES 2.0 version of the fbo blit. - else if (d_ptr->fbo) { - Q_UNUSED(target); - - if (d_ptr->fbo->isBound()) - d_ptr->fbo->release(); - - blitTexture(ctx, d_ptr->fbo->texture(), size, window()->size(), rect, br); - } -#endif - - if (ctx->format().doubleBuffer()) - ctx->swapBuffers(); - else - glFlush(); - - d_ptr->did_paint = false; -} - - -#if !defined(Q_WS_QPA) -void QGLWindowSurface::setGeometry(const QRect &rect) -{ - QWindowSurface::setGeometry(rect); - d_ptr->geometry_updated = true; -} -#else -void QGLWindowSurface::resize(const QSize &size) -{ - QWindowSurface::resize(size); - d_ptr->geometry_updated = true; -} -#endif - -void QGLWindowSurface::updateGeometry() { - if (!d_ptr->geometry_updated) - return; - d_ptr->geometry_updated = false; - - bool hijack(true); - QWidgetPrivate *wd = window()->d_func(); - if (wd->extraData() && wd->extraData()->glContext) { -#ifdef Q_OS_SYMBIAN // Symbian needs to recreate the context when native window size changes - if (d_ptr->size != geometry().size()) { - if (window() != qt_gl_share_widget()) - --(_qt_gl_share_widget()->widgetRefCount); - - delete wd->extraData()->glContext; - wd->extraData()->glContext = 0; - d_ptr->ctx = 0; - } - else -#endif - { - hijack = false; // we already have gl context for widget - } - } - - if (hijack) - hijackWindow(window()); - - QGLContext *ctx = reinterpret_cast<QGLContext *>(wd->extraData()->glContext); - -#ifdef Q_WS_MAC - ctx->updatePaintDevice(); -#endif - - QSize surfSize = geometry().size(); - - if (surfSize.width() <= 0 || surfSize.height() <= 0) - return; - - if (d_ptr->size == surfSize) - return; - - d_ptr->size = surfSize; - - if (d_ptr->ctx) { -#ifndef QT_OPENGL_ES_2 - if (d_ptr->destructive_swap_buffers) - initializeOffscreenTexture(surfSize); -#endif - return; - } - - const GLenum target = GL_TEXTURE_2D; - if (d_ptr->destructive_swap_buffers - && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject) - && (d_ptr->fbo || !d_ptr->tried_fbo) - && qt_gl_preferGL2Engine()) - { - d_ptr->tried_fbo = true; - ctx->d_ptr->internal_context = true; - ctx->makeCurrent(); - delete d_ptr->fbo; - - QGLFramebufferObjectFormat format; - format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - format.setInternalTextureFormat(GLenum(GL_RGBA)); - format.setTextureTarget(target); - - if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit) - format.setSamples(8); - - d_ptr->fbo = new QGLFramebufferObject(surfSize, format); - - if (d_ptr->fbo->isValid()) { - qDebug() << "Created Window Surface FBO" << surfSize - << "with samples" << d_ptr->fbo->format().samples(); - return; - } else { - qDebug() << "QGLWindowSurface: Failed to create valid FBO, falling back"; - delete d_ptr->fbo; - d_ptr->fbo = 0; - } - } - -#if !defined(QT_OPENGL_ES_2) && !defined(Q_WS_QPA) //QPA doesn't support pixelbuffers - if (d_ptr->destructive_swap_buffers && (d_ptr->pb || !d_ptr->tried_pb)) { - d_ptr->tried_pb = true; - - if (d_ptr->pb) { - d_ptr->pb->makeCurrent(); - glDeleteTextures(1, &d_ptr->pb_tex_id); - } - - delete d_ptr->pb; - - d_ptr->pb = new QGLPixelBuffer(surfSize.width(), surfSize.height(), - QGLFormat(QGL::SampleBuffers | QGL::StencilBuffer | QGL::DepthBuffer), - qt_gl_share_widget()); - - if (d_ptr->pb->isValid()) { - qDebug() << "Created Window Surface Pixelbuffer, Sample buffers:" << d_ptr->pb->format().sampleBuffers(); - d_ptr->pb->makeCurrent(); - - glGenTextures(1, &d_ptr->pb_tex_id); - glBindTexture(target, d_ptr->pb_tex_id); - glTexImage2D(target, 0, GL_RGBA, surfSize.width(), surfSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - - glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glBindTexture(target, 0); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, d_ptr->pb->width(), d_ptr->pb->height(), 0, -999999, 999999); - - d_ptr->pb->d_ptr->qctx->d_func()->internal_context = true; - return; - } else { - qDebug() << "QGLWindowSurface: Failed to create valid pixelbuffer, falling back"; - delete d_ptr->pb; - d_ptr->pb = 0; - } - } -#endif // !defined(QT_OPENGL_ES_2) !defined(Q_WS_QPA) - - ctx->makeCurrent(); - -#ifndef QT_OPENGL_ES_2 - if (d_ptr->destructive_swap_buffers) - initializeOffscreenTexture(surfSize); -#endif -#ifndef Q_OS_SYMBIAN - qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this; -#endif - d_ptr->ctx = ctx; - d_ptr->ctx->d_ptr->internal_context = true; -} - -bool QGLWindowSurface::initializeOffscreenTexture(const QSize &size) -{ - if (size == d_ptr->textureSize) - return false; - - glGenTextures(1, &d_ptr->tex_id); - glBindTexture(GL_TEXTURE_2D, d_ptr->tex_id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); - - d_ptr->textureSize = size; - return true; -} - -bool QGLWindowSurface::scroll(const QRegion &area, int dx, int dy) -{ - // this code randomly fails currently for unknown reasons - return false; - - if (!d_ptr->pb) - return false; - - d_ptr->pb->makeCurrent(); - - QRect br = area.boundingRect(); - -#if 0 - // ## workaround driver issue (scrolling by these deltas is unbearably slow for some reason) - // ## maybe we should use glCopyTexSubImage insteadk - if (dx == 1 || dx == -1 || dy == 1 || dy == -1 || dy == 2) - return false; - - glRasterPos2i(br.x() + dx, br.y() + br.height() + dy); - glCopyPixels(br.x(), d_ptr->pb->height() - (br.y() + br.height()), br.width(), br.height(), GL_COLOR); - return true; -#endif - - const GLenum target = GL_TEXTURE_2D; - - glBindTexture(target, d_ptr->tex_id); - glCopyTexImage2D(target, 0, GL_RGBA, br.x(), d_ptr->pb->height() - (br.y() + br.height()), br.width(), br.height(), 0); - glBindTexture(target, 0); - - drawTexture(br.translated(dx, dy), d_ptr->tex_id, window()->size()); - - return true; -} - -static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br) -{ - const GLenum target = GL_TEXTURE_2D; - QRectF src = br.isEmpty() - ? QRectF(QPointF(), texSize) - : QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size()); - - if (target == GL_TEXTURE_2D) { - qreal width = texSize.width(); - qreal height = texSize.height(); - - src.setLeft(src.left() / width); - src.setRight(src.right() / width); - src.setTop(src.top() / height); - src.setBottom(src.bottom() / height); - } - - const GLfloat tx1 = src.left(); - const GLfloat tx2 = src.right(); - const GLfloat ty1 = src.top(); - const GLfloat ty2 = src.bottom(); - - GLfloat texCoordArray[4*2] = { - tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 - }; - - GLfloat vertexArray[4*2]; - extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); // qpaintengine_opengl.cpp - qt_add_rect_to_array(rect, vertexArray); - -#if !defined(QT_OPENGL_ES_2) - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); - - glBindTexture(target, tex_id); - glEnable(target); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glDisable(target); - glBindTexture(target, 0); -#else - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray); - glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray); - - glBindTexture(target, tex_id); - - glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - - glBindTexture(target, 0); -#endif -} - -QImage *QGLWindowSurface::buffer(const QWidget *widget) -{ - QImage image; - - if (d_ptr->pb) - image = d_ptr->pb->toImage(); - else if (d_ptr->fbo) - image = d_ptr->fbo->toImage(); - - if (image.isNull()) - return 0; - - QRect rect = widget->rect(); - rect.translate(widget->mapTo(widget->window(), QPoint())); - - QImage subImage = image.copy(rect); - d_ptr->buffers << subImage; - return &d_ptr->buffers.last(); -} - -QWindowSurface::WindowSurfaceFeatures QGLWindowSurface::features() const -{ - WindowSurfaceFeatures features = 0; - if (!d_ptr->destructive_swap_buffers || d_ptr->swap_region_support) - features |= PartialUpdates; - if (!d_ptr->destructive_swap_buffers) - features |= PreservedContents; - return features; -} - -QT_END_NAMESPACE - diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h deleted file mode 100644 index 91d1f9e245..0000000000 --- a/src/opengl/qwindowsurface_gl_p.h +++ /dev/null @@ -1,129 +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 QWINDOWSURFACE_GL_P_H -#define QWINDOWSURFACE_GL_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 <qglobal.h> -#include <qgl.h> -#include <private/qwindowsurface_p.h> -#include <private/qglpaintdevice_p.h> - -QT_BEGIN_NAMESPACE - -class QPaintDevice; -class QPoint; -class QRegion; -class QWidget; -struct QGLWindowSurfacePrivate; - -Q_OPENGL_EXPORT QGLWidget* qt_gl_share_widget(); -Q_OPENGL_EXPORT void qt_destroy_gl_share_widget(); - -class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice -{ -public: - QPaintEngine* paintEngine() const; - void endPaint(); - QSize size() const; - int metric(PaintDeviceMetric m) const; - QGLContext* context() const; - QGLWindowSurfacePrivate* d; -}; - -class Q_OPENGL_EXPORT QGLWindowSurface : public QObject, public QWindowSurface // , public QPaintDevice -{ - Q_OBJECT -public: - QGLWindowSurface(QWidget *window); - ~QGLWindowSurface(); - - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - -#if !defined(Q_WS_QPA) - void setGeometry(const QRect &rect); -#else - virtual void resize(const QSize &size); -#endif - - void updateGeometry(); - bool scroll(const QRegion &area, int dx, int dy); - - void beginPaint(const QRegion ®ion); - void endPaint(const QRegion ®ion); - - QImage *buffer(const QWidget *widget); - - WindowSurfaceFeatures features() const; - - QGLContext *context() const; - - static QGLFormat surfaceFormat; - - enum SwapMode { AutomaticSwap, AlwaysFullSwap, AlwaysPartialSwap, KillSwap }; - static SwapMode swapBehavior; - -private slots: - void deleted(QObject *object); - -private: - void hijackWindow(QWidget *widget); - bool initializeOffscreenTexture(const QSize &size); - - QGLWindowSurfacePrivate *d_ptr; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSURFACE_GL_P_H - diff --git a/src/opengl/qwindowsurface_x11gl.cpp b/src/opengl/qwindowsurface_x11gl.cpp deleted file mode 100644 index bec0ea7587..0000000000 --- a/src/opengl/qwindowsurface_x11gl.cpp +++ /dev/null @@ -1,213 +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 <QTime> -#include <QDebug> - -#include <private/qt_x11_p.h> -#include <private/qimagepixmapcleanuphooks_p.h> - -#include "qwindowsurface_x11gl_p.h" -#include "qpixmapdata_x11gl_p.h" - -QT_BEGIN_NAMESPACE - -QX11GLWindowSurface::QX11GLWindowSurface(QWidget* window) - : QWindowSurface(window), m_windowGC(0), m_pixmapGC(0), m_window(window) -{ -} - -QX11GLWindowSurface::~QX11GLWindowSurface() -{ - if (m_windowGC) - XFree(m_windowGC); - if (m_pixmapGC) - XFree(m_pixmapGC); -} - -QPaintDevice *QX11GLWindowSurface::paintDevice() -{ - return &m_backBuffer; -} - -extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp - -void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset) -{ - // We don't need to know the widget which initiated the flush. Instead we just use the offset - // to translate the widgetRegion: - Q_UNUSED(widget); - - if (m_backBuffer.isNull()) { - qDebug("QX11GLWindowSurface::flush() - backBuffer is null, not flushing anything"); - return; - } - - Q_ASSERT(window()->size() != m_backBuffer.size()); - - // Wait for all GL rendering to the back buffer pixmap to complete before trying to - // copy it to the window. We do this by making sure the pixmap's context is current - // and then call eglWaitClient. The EGL 1.4 spec says eglWaitClient doesn't have to - // block, just that "All rendering calls...are guaranteed to be executed before native - // rendering calls". This makes it potentially less expensive than glFinish. - QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context(); - if (QGLContext::currentContext() != ctx && ctx && ctx->isValid()) - ctx->makeCurrent(); - eglWaitClient(); - - if (m_windowGC == 0) { - XGCValues attribs; - attribs.graphics_exposures = False; - m_windowGC = XCreateGC(X11->display, m_window->handle(), GCGraphicsExposures, &attribs); - } - - int rectCount; - XRectangle *rects = (XRectangle *)qt_getClipRects(widgetRegion, rectCount); - if (rectCount <= 0) - return; - - XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded); - - QRect dirtyRect = widgetRegion.boundingRect().translated(-offset); - XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC, - dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), - dirtyRect.x(), dirtyRect.y()); - - // Make sure the blit of the update from the back buffer to the window completes - // before allowing rendering to start again to the back buffer. Otherwise the GPU - // might start rendering to the back buffer again while the blit takes place. - eglWaitNative(EGL_CORE_NATIVE_ENGINE); -} - -void QX11GLWindowSurface::setGeometry(const QRect &rect) -{ - if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) { - QX11GLPixmapData *pd = new QX11GLPixmapData; - QSize newSize = rect.size(); - pd->resize(newSize.width(), newSize.height()); - m_backBuffer = QPixmap(pd); - if (window()->testAttribute(Qt::WA_TranslucentBackground)) - m_backBuffer.fill(Qt::transparent); - if (m_pixmapGC) { - XFreeGC(X11->display, m_pixmapGC); - m_pixmapGC = 0; - } - } - - QWindowSurface::setGeometry(rect); -} - -bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy) -{ - if (m_backBuffer.isNull()) - return false; - - Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class); - - // Make sure all GL rendering is complete before starting the scroll operation: - QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context(); - if (QGLContext::currentContext() != ctx && ctx && ctx->isValid()) - ctx->makeCurrent(); - eglWaitClient(); - - if (!m_pixmapGC) - m_pixmapGC = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0); - - foreach (const QRect& rect, area.rects()) { - XCopyArea(X11->display, m_backBuffer.handle(), m_backBuffer.handle(), m_pixmapGC, - rect.x(), rect.y(), rect.width(), rect.height(), - rect.x()+dx, rect.y()+dy); - } - - // Make sure the scroll operation is complete before allowing GL rendering to resume - eglWaitNative(EGL_CORE_NATIVE_ENGINE); - - return true; -} - - -QPixmap QX11GLWindowSurface::grabWidget(const QWidget *widget, const QRect& rect) const -{ - if (!widget || m_backBuffer.isNull()) - return QPixmap(); - - QRect srcRect; - - // make sure the rect is inside the widget & clip to widget's rect - if (!rect.isEmpty()) - srcRect = rect & widget->rect(); - else - srcRect = widget->rect(); - - if (srcRect.isEmpty()) - return QPixmap(); - - // If it's a child widget we have to translate the coordinates - if (widget != window()) - srcRect.translate(widget->mapTo(window(), QPoint(0, 0))); - - QPixmap::x11SetDefaultScreen(widget->x11Info().screen()); - - QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType); - pmd->resize(srcRect.width(), srcRect.height()); - QPixmap px(pmd); - - GC tmpGc = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0); - - // Make sure all GL rendering is complete before copying the window - QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.pixmapData())->context(); - if (QGLContext::currentContext() != ctx && ctx && ctx->isValid()) - ctx->makeCurrent(); - eglWaitClient(); - - // Copy srcRect from the backing store to the new pixmap - XSetGraphicsExposures(X11->display, tmpGc, False); - XCopyArea(X11->display, m_backBuffer.handle(), px.handle(), tmpGc, - srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), 0, 0); - XFreeGC(X11->display, tmpGc); - - // Wait until the copy has finised before allowing more rendering into the back buffer - eglWaitNative(EGL_CORE_NATIVE_ENGINE); - - return px; -} - -QT_END_NAMESPACE diff --git a/src/opengl/qwindowsurface_x11gl_p.h b/src/opengl/qwindowsurface_x11gl_p.h deleted file mode 100644 index 737997b879..0000000000 --- a/src/opengl/qwindowsurface_x11gl_p.h +++ /dev/null @@ -1,83 +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 QWINDOWSURFACE_X11GL_P_H -#define QWINDOWSURFACE_X11GL_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 <private/qwindowsurface_p.h> - -QT_BEGIN_NAMESPACE - -class QX11GLWindowSurface : public QWindowSurface -{ -public: - QX11GLWindowSurface(QWidget* window); - virtual ~QX11GLWindowSurface(); - - // Inherreted from QWindowSurface - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - void setGeometry(const QRect &rect); - bool scroll(const QRegion &area, int dx, int dy); - QPixmap grabWidget(const QWidget *widget, const QRect& rectangle = QRect()) const; - -private: - GC m_windowGC; - GC m_pixmapGC; - QPixmap m_backBuffer; - QWidget *m_window; -}; - - -QT_END_NAMESPACE - -#endif // QWINDOWSURFACE_X11GL_P_H diff --git a/src/opengl/util/README-GLSL b/src/opengl/util/README-GLSL deleted file mode 100644 index ff20eb45b2..0000000000 --- a/src/opengl/util/README-GLSL +++ /dev/null @@ -1,18 +0,0 @@ -Use of GLSL for vertex and fragment programs in Qt ---------------------------------------------------- - -We don't compile the *.glsl files because we don't want the build process of -Qt to require cgc from nVidia to build the fragment programs. - -The script src/opengl/util/glsl_to_include.sh will compile a GLSL program to a file -that can be included in a C(++) program. The file is the output from cgc -quoted as a string. - -This can be done manually by: - -./glsl_to_include.sh radial.glsl -./glsl_to_include.sh conical.glsl - -This will produce the files radial.frag and radial.glsl_quoted. -(and also conical.frag and conical.glsl_quoted) -These files are included by qpaintengine_opengl.cpp diff --git a/src/opengl/util/brush_painter.glsl b/src/opengl/util/brush_painter.glsl deleted file mode 100644 index 6c4acdf924..0000000000 --- a/src/opengl/util/brush_painter.glsl +++ /dev/null @@ -1,7 +0,0 @@ -// fast brush painter for composition modes which can be implemented with blendfuncs -// no mask, used for fast filling of aliased primitives (or multisampled) - -void main() -{ - gl_FragColor = brush(); -} diff --git a/src/opengl/util/brushes.conf b/src/opengl/util/brushes.conf deleted file mode 100644 index 93e2b3b295..0000000000 --- a/src/opengl/util/brushes.conf +++ /dev/null @@ -1,6 +0,0 @@ -FRAGMENT_PROGRAM_BRUSH_SOLID solid_brush.glsl -FRAGMENT_PROGRAM_BRUSH_RADIAL radial_brush.glsl -FRAGMENT_PROGRAM_BRUSH_CONICAL conical_brush.glsl -FRAGMENT_PROGRAM_BRUSH_LINEAR linear_brush.glsl -FRAGMENT_PROGRAM_BRUSH_TEXTURE texture_brush.glsl -FRAGMENT_PROGRAM_BRUSH_PATTERN pattern_brush.glsl diff --git a/src/opengl/util/composition_mode_colorburn.glsl b/src/opengl/util/composition_mode_colorburn.glsl deleted file mode 100644 index c913b9737f..0000000000 --- a/src/opengl/util/composition_mode_colorburn.glsl +++ /dev/null @@ -1,13 +0,0 @@ -// Dca' = Sca.Da + Dca.Sa <= Sa.Da ? -// Sca.(1 - Da) + Dca.(1 - Sa) -// Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - result.rgb = mix(src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), - src.a * (src.rgb * dst.a + dst.rgb * src.a - src.a * dst.a) / max(src.rgb, 0.00001) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), - step(src.a * dst.a, src.rgb * dst.a + dst.rgb * src.a)); - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_mode_colordodge.glsl b/src/opengl/util/composition_mode_colordodge.glsl deleted file mode 100644 index b75e83cf4e..0000000000 --- a/src/opengl/util/composition_mode_colordodge.glsl +++ /dev/null @@ -1,15 +0,0 @@ -// Dca' = Sca.Da + Dca.Sa <= Sa.Da ? -// Dca.Sa/(1 - Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) : -// Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - vec3 temp = src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a); - result.rgb = mix(dst.rgb * src.a / max(1.0 - src.rgb / max(src.a, 0.000001), 0.000001) + temp, - src.a * dst.a + temp, - step(src.a * dst.a, src.rgb * dst.a + dst.rgb * src.a)); - - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_mode_darken.glsl b/src/opengl/util/composition_mode_darken.glsl deleted file mode 100644 index 8bbb82b3ce..0000000000 --- a/src/opengl/util/composition_mode_darken.glsl +++ /dev/null @@ -1,9 +0,0 @@ -// Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - result.rgb = min(src.rgb * dst.a, dst.rgb * src.a) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a); - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_mode_difference.glsl b/src/opengl/util/composition_mode_difference.glsl deleted file mode 100644 index 3c46ec71f2..0000000000 --- a/src/opengl/util/composition_mode_difference.glsl +++ /dev/null @@ -1,9 +0,0 @@ -// Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - result.rgb = src.rgb + dst.rgb - 2.0 * min(src.rgb * dst.a, dst.rgb * src.a); - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_mode_exclusion.glsl b/src/opengl/util/composition_mode_exclusion.glsl deleted file mode 100644 index 59c2da99ea..0000000000 --- a/src/opengl/util/composition_mode_exclusion.glsl +++ /dev/null @@ -1,9 +0,0 @@ -// Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - result.rgb = (src.rgb * dst.a + dst.rgb * src.a - 2.0 * src.rgb * dst.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a); - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_mode_hardlight.glsl b/src/opengl/util/composition_mode_hardlight.glsl deleted file mode 100644 index 4ea355029d..0000000000 --- a/src/opengl/util/composition_mode_hardlight.glsl +++ /dev/null @@ -1,14 +0,0 @@ -// Dca' = 2.Sca < Sa ? -// 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) : -// Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - result.rgb = mix(2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), - src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), - step(src.a, 2.0 * src.rgb)); - result.a = src.a + dst.a - src.a * dst.a; - - return result; -} diff --git a/src/opengl/util/composition_mode_lighten.glsl b/src/opengl/util/composition_mode_lighten.glsl deleted file mode 100644 index 13ef507a4c..0000000000 --- a/src/opengl/util/composition_mode_lighten.glsl +++ /dev/null @@ -1,9 +0,0 @@ -// Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - result.rgb = max(src.rgb * dst.a, dst.rgb * src.a) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a); - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_mode_multiply.glsl b/src/opengl/util/composition_mode_multiply.glsl deleted file mode 100644 index f90b7f00ad..0000000000 --- a/src/opengl/util/composition_mode_multiply.glsl +++ /dev/null @@ -1,9 +0,0 @@ -// Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - result.rgb = src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a); - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_mode_overlay.glsl b/src/opengl/util/composition_mode_overlay.glsl deleted file mode 100644 index f621bdee96..0000000000 --- a/src/opengl/util/composition_mode_overlay.glsl +++ /dev/null @@ -1,13 +0,0 @@ -// Dca' = 2.Dca < Da ? -// 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) -// Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - result.rgb = mix(2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), - src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), - step(dst.a, 2.0 * dst.rgb)); - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_mode_screen.glsl b/src/opengl/util/composition_mode_screen.glsl deleted file mode 100644 index 8f4f010032..0000000000 --- a/src/opengl/util/composition_mode_screen.glsl +++ /dev/null @@ -1,6 +0,0 @@ -// Dca' = Sca + Dca - Sca.Dca -// Da' = Sa + Da - Sa.Da -vec4 composite(vec4 src, vec4 dst) -{ - return src + dst - src * dst; -} diff --git a/src/opengl/util/composition_mode_softlight.glsl b/src/opengl/util/composition_mode_softlight.glsl deleted file mode 100644 index e4c1f89156..0000000000 --- a/src/opengl/util/composition_mode_softlight.glsl +++ /dev/null @@ -1,22 +0,0 @@ -// if 2.Sca <= Sa -// Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) -// otherwise if 2.Sca > Sa and 4.Dca <= Da -// Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) -// otherwise if 2.Sca > Sa and 4.Dca > Da -// Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) -// Da' = Sa + Da - Sa.Da - -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - float da = max(dst.a, 0.00001); - vec3 dst_np = dst.rgb / da; - result.rgb = mix(dst.rgb * (src.a + (2.0 * src.rgb - src.a) * (1.0 - dst_np)), - mix(dst.rgb * src.a + dst.a * (2.0 * src.rgb - src.a) * ((16.0 * dst_np - 12.0) * dst_np + 3.0) * dst_np, - dst.rgb * src.a + dst.a * (2.0 * src.rgb - src.a) * (sqrt(dst_np) - dst_np), - step(dst.a, 4.0 * dst.rgb)), - step(src.a, 2.0 * src.rgb)) - + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a); - result.a = src.a + dst.a - src.a * dst.a; - return result; -} diff --git a/src/opengl/util/composition_modes.conf b/src/opengl/util/composition_modes.conf deleted file mode 100644 index df52830b99..0000000000 --- a/src/opengl/util/composition_modes.conf +++ /dev/null @@ -1,12 +0,0 @@ -COMPOSITION_MODES_SIMPLE_PORTER_DUFF simple_porter_duff.glsl -COMPOSITION_MODES_MULTIPLY composition_mode_multiply.glsl -COMPOSITION_MODES_SCREEN composition_mode_screen.glsl -COMPOSITION_MODES_OVERLAY composition_mode_overlay.glsl -COMPOSITION_MODES_DARKEN composition_mode_darken.glsl -COMPOSITION_MODES_LIGHTEN composition_mode_lighten.glsl -COMPOSITION_MODES_COLORDODGE composition_mode_colordodge.glsl -COMPOSITION_MODES_COLORBURN composition_mode_colorburn.glsl -COMPOSITION_MODES_HARDLIGHT composition_mode_hardlight.glsl -COMPOSITION_MODES_SOFTLIGHT composition_mode_softlight.glsl -COMPOSITION_MODES_DIFFERENCE composition_mode_difference.glsl -COMPOSITION_MODES_EXCLUSION composition_mode_exclusion.glsl diff --git a/src/opengl/util/conical_brush.glsl b/src/opengl/util/conical_brush.glsl deleted file mode 100644 index b3ec1d7efe..0000000000 --- a/src/opengl/util/conical_brush.glsl +++ /dev/null @@ -1,27 +0,0 @@ -// conical gradient shader -#define M_PI 3.14159265358979323846 -uniform sampler1D palette; -uniform float angle; -uniform vec3 inv_matrix_m0; -uniform vec3 inv_matrix_m1; -uniform vec3 inv_matrix_m2; - -vec4 brush() -{ - mat3 mat; - - mat[0] = inv_matrix_m0; - mat[1] = inv_matrix_m1; - mat[2] = inv_matrix_m2; - - vec3 hcoords = mat * vec3(gl_FragCoord.xy, 1); - vec2 A = hcoords.xy / hcoords.z; - -/* float val = fmod((atan2(-A.y, A.x) + angle) / (2.0 * M_PI), 1); */ - if (abs(A.y) == abs(A.x)) - A.y += 0.002; - float t = (atan(-A.y, A.x) + angle) / (2.0 * M_PI); - float val = t - floor(t); - return texture1D(palette, val); -} - diff --git a/src/opengl/util/ellipse_aa.glsl b/src/opengl/util/ellipse_aa.glsl deleted file mode 100644 index 257e3bbd47..0000000000 --- a/src/opengl/util/ellipse_aa.glsl +++ /dev/null @@ -1,58 +0,0 @@ -uniform vec3 inv_matrix_m0; -uniform vec3 inv_matrix_m1; -uniform vec3 inv_matrix_m2; - -uniform vec2 ellipse_offset; - -// ellipse equation - -// s^2/a^2 + t^2/b^2 = 1 -// -// implicit equation: -// g(s,t) = 1 - s^2/r_s^2 - t^2/r_t^2 - -// distance from ellipse: -// grad = [dg/dx dg/dy] -// d(s, t) ~= g(s, t) / |grad| - -// dg/dx = dg/ds * ds/dx + dg/dt * dt/dx -// dg/dy = dg/ds * ds/dy + dg/dt * dt/dy - -float ellipse_aa() -{ - mat3 mat; - - mat[0] = inv_matrix_m0; - mat[1] = inv_matrix_m1; - mat[2] = inv_matrix_m2; - - vec3 hcoords = mat * vec3(gl_FragCoord.xy + ellipse_offset, 1); - float inv_w = 1.0 / hcoords.z; - vec2 st = hcoords.xy * inv_w; - - vec4 xy = vec4(mat[0].xy, mat[1].xy); - vec2 h = vec2(mat[0].z, mat[1].z); - - vec4 dstdxy = (xy.xzyw - h.xyxy * st.xxyy) * inv_w; - - //dstdxy.x = (mat[0].x - mat[0].z * st.x) * inv_w; // ds/dx - //dstdxy.y = (mat[1].x - mat[1].z * st.x) * inv_w; // ds/dy - //dstdxy.z = (mat[0].y - mat[0].z * st.y) * inv_w; // dt/dx - //dstdxy.w = (mat[1].y - mat[1].z * st.y) * inv_w; // dt/dy - - vec2 inv_r = gl_TexCoord[0].xy; - vec2 n = st * inv_r; - float g = 1.0 - dot(n, n); - - vec2 dgdst = -2.0 * n * inv_r; - - vec2 grad = vec2(dot(dgdst, dstdxy.xz), - dot(dgdst, dstdxy.yw)); - - return smoothstep(-0.5, 0.5, g * inversesqrt(dot(grad, grad))); -} - -void main() -{ - gl_FragColor = ellipse_aa().xxxx; -} diff --git a/src/opengl/util/fast_painter.glsl b/src/opengl/util/fast_painter.glsl deleted file mode 100644 index 63f5e5f3be..0000000000 --- a/src/opengl/util/fast_painter.glsl +++ /dev/null @@ -1,19 +0,0 @@ -// fast painter for composition modes which can be implemented with blendfuncs - -uniform sampler2D mask_texture; -uniform vec2 inv_mask_size; -uniform vec2 mask_offset; -uniform vec4 mask_channel; - -float mask() -{ - return dot(mask_channel, texture2D(mask_texture, (gl_FragCoord.xy + mask_offset) * inv_mask_size)); -} - -void main() -{ - // combine clip and coverage channels - float mask_alpha = mask(); - - gl_FragColor = brush() * mask_alpha; -} diff --git a/src/opengl/util/fragmentprograms_p.h b/src/opengl/util/fragmentprograms_p.h deleted file mode 100644 index b1a47e3d5f..0000000000 --- a/src/opengl/util/fragmentprograms_p.h +++ /dev/null @@ -1,7287 +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 FRAGMENTPROGRAMS_P_H -#define FRAGMENTPROGRAMS_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. -// - -enum FragmentVariable { - VAR_BRUSH_TEXTURE, - VAR_LINEAR, - VAR_INV_MATRIX_M1, - VAR_INV_MASK_SIZE, - VAR_INV_MATRIX_M2, - VAR_PORTERDUFF_AB, - VAR_MASK_CHANNEL, - VAR_ELLIPSE_OFFSET, - VAR_PORTERDUFF_XYZ, - VAR_INV_DST_SIZE, - VAR_MASK_TEXTURE, - VAR_DST_TEXTURE, - VAR_PALETTE, - VAR_MASK_OFFSET, - VAR_INV_BRUSH_TEXTURE_SIZE, - VAR_FMP2_M_RADIUS2, - VAR_FMP, - VAR_INV_MATRIX_M0, - VAR_ANGLE -}; - -enum FragmentBrushType { - FRAGMENT_PROGRAM_BRUSH_SOLID, - FRAGMENT_PROGRAM_BRUSH_RADIAL, - FRAGMENT_PROGRAM_BRUSH_CONICAL, - FRAGMENT_PROGRAM_BRUSH_LINEAR, - FRAGMENT_PROGRAM_BRUSH_TEXTURE, - FRAGMENT_PROGRAM_BRUSH_PATTERN -}; - -enum FragmentCompositionModeType { - COMPOSITION_MODES_SIMPLE_PORTER_DUFF, - COMPOSITION_MODES_MULTIPLY, - COMPOSITION_MODES_SCREEN, - COMPOSITION_MODES_OVERLAY, - COMPOSITION_MODES_DARKEN, - COMPOSITION_MODES_LIGHTEN, - COMPOSITION_MODES_COLORDODGE, - COMPOSITION_MODES_COLORBURN, - COMPOSITION_MODES_HARDLIGHT, - COMPOSITION_MODES_SOFTLIGHT, - COMPOSITION_MODES_DIFFERENCE, - COMPOSITION_MODES_EXCLUSION, - COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK, - COMPOSITION_MODES_MULTIPLY_NOMASK, - COMPOSITION_MODES_SCREEN_NOMASK, - COMPOSITION_MODES_OVERLAY_NOMASK, - COMPOSITION_MODES_DARKEN_NOMASK, - COMPOSITION_MODES_LIGHTEN_NOMASK, - COMPOSITION_MODES_COLORDODGE_NOMASK, - COMPOSITION_MODES_COLORBURN_NOMASK, - COMPOSITION_MODES_HARDLIGHT_NOMASK, - COMPOSITION_MODES_SOFTLIGHT_NOMASK, - COMPOSITION_MODES_DIFFERENCE_NOMASK, - COMPOSITION_MODES_EXCLUSION_NOMASK, - COMPOSITION_MODE_BLEND_MODE_MASK, - COMPOSITION_MODE_BLEND_MODE_NOMASK -}; - -enum FragmentMaskType { - FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, - FRAGMENT_PROGRAM_MASK_ELLIPSE_AA -}; - -static const unsigned int num_fragment_variables = 19; - -static const unsigned int num_fragment_brushes = 6; -static const unsigned int num_fragment_composition_modes = 26; -static const unsigned int num_fragment_masks = 2; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA = - "!!ARBfp1.0\n" - "PARAM c[1] = { { 0.5, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "ADD R3.z, fragment.position.x, c[0].x;\n" - "ADD R0.y, fragment.position, -c[0].x;\n" - "MAX R4.x, fragment.texcoord[0].y, R0.y;\n" - "ADD R0.x, fragment.position.y, c[0];\n" - "MIN R3.w, R0.x, fragment.texcoord[0].x;\n" - "ADD R2.z, fragment.position.x, -c[0].x;\n" - "MOV R2.w, R3.z;\n" - "MOV R0.yw, R4.x;\n" - "MOV R0.xz, R3.w;\n" - "MAD R0, fragment.texcoord[1].xxzz, R0, fragment.texcoord[1].yyww;\n" - "MAD R0.zw, fragment.position.x, c[0].y, -R0;\n" - "MOV R2.x, R0;\n" - "MOV R2.y, R0.z;\n" - "MOV R1.w, R0;\n" - "MOV R1.z, R0.y;\n" - "MIN R1.xy, R2, R1.zwzw;\n" - "SGE R0.xy, R1.zwzw, R2;\n" - "ADD R0.zw, -fragment.texcoord[0], -fragment.texcoord[0];\n" - "MAD R3.xy, R0, R0.zwzw, fragment.texcoord[0].zwzw;\n" - "ADD R0, -R1.xxyy, R2.zwzw;\n" - "MAD R0, R0, R3.xxyy, R4.x;\n" - "ADD R3.xy, R0.ywzw, R0.xzzw;\n" - "ADD R4.zw, R3.w, -R0.xyxz;\n" - "ADD R0.zw, -R4.x, R0.xyyw;\n" - "ADD R0.xy, R3.z, -R1;\n" - "MAX R1.zw, R2.xyxy, R1;\n" - "MUL R0.xy, R0, R0.zwzw;\n" - "MAD R3.xy, -R3, c[0].x, R3.w;\n" - "ADD R2.w, R3.z, -R2.z;\n" - "MUL R2.xy, R3, R2.w;\n" - "ADD R2.w, R3, -R4.x;\n" - "ADD R3.xy, -R2.z, R1.zwzw;\n" - "MUL R3.xy, R4.zwzw, R3;\n" - "ADD R4.zw, R1.xyxy, R1;\n" - "MAD R0.zw, R4, c[0].x, -R2.z;\n" - "MAD R0.xy, -R0, c[0].x, R2.w;\n" - "MAD R4.zw, R0, R2.w, -R0.xyxy;\n" - "SGE R0.zw, R3.z, R1;\n" - "MAD R0.xy, R0.zwzw, R4.zwzw, R0;\n" - "MAD R3.xy, R3, c[0].x, -R2;\n" - "MAD R0.zw, R0, R3.xyxy, R2.xyxy;\n" - "ADD R2.xy, R0.zwzw, -R0;\n" - "SGE R0.zw, R2.z, R1.xyxy;\n" - "MAD R0.xy, R0.zwzw, R2, R0;\n" - "SGE R0.zw, R1, R2.z;\n" - "ADD R0.xy, R0, -R2.w;\n" - "SGE R1.xy, R3.z, R1;\n" - "MAD R0.xy, R1, R0, R2.w;\n" - "MAD R0.x, -R0, R0.z, R2.w;\n" - "SGE R0.z, R3.w, R4.x;\n" - "MAD R0.x, -R0.y, R0.w, R0;\n" - "MUL result.color, R0.x, R0.z;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_MASK_ELLIPSE_AA = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..3],\n" - " { -2, 1, -0.5, 2 },\n" - " { 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "ADD R0.xy, fragment.position, c[3];\n" - "MUL R1.xyz, R0.y, c[1];\n" - "MAD R0.xyz, R0.x, c[0], R1;\n" - "ADD R0.xyz, R0, c[2];\n" - "RCP R2.z, R0.z;\n" - "MUL R0.zw, R0.xyxy, R2.z;\n" - "MUL R2.xy, R0.zwzw, fragment.texcoord[0];\n" - "MOV R1.xy, c[0];\n" - "MOV R1.zw, c[1].xyxy;\n" - "MOV R0.x, c[0].z;\n" - "MOV R0.y, c[1].z;\n" - "MAD R0, R0.zzww, -R0.xyxy, R1.xzyw;\n" - "MUL R1.xy, R2, fragment.texcoord[0];\n" - "MUL R0, R2.z, R0;\n" - "MUL R1.xy, R1, c[4].x;\n" - "MUL R1.zw, R1.xyxy, R0.xyxz;\n" - "MUL R0.zw, R1.xyxy, R0.xyyw;\n" - "ADD R0.y, R0.z, R0.w;\n" - "ADD R0.x, R1.z, R1.w;\n" - "MUL R0.xy, R0, R0;\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, R2.xyxy, R2.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "ADD R0.y, -R0.z, c[4];\n" - "RSQ R0.x, R0.x;\n" - "MAD_SAT R0.x, R0, R0.y, -c[4].z;\n" - "MUL R0.y, -R0.x, c[4].w;\n" - "ADD R0.y, R0, c[5].x;\n" - "MUL R0.x, R0, R0;\n" - "MUL result.color, R0.x, R0.y;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SIMPLE_PORTER_DUFF = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xy, fragment.position, c[3];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.xyz, R0, c[0].y;\n" - "MUL R2.xyz, fragment.color.primary.w, R1;\n" - "MUL R1.xyz, fragment.color.primary, c[0].x;\n" - "MAD R2.xyz, R0.w, R1, R2;\n" - "ADD R3.xy, fragment.position, c[4];\n" - "ADD R1.w, -R0, c[6].x;\n" - "MUL R1.xyz, fragment.color.primary, c[1].y;\n" - "MAD R2.xyz, R1.w, R1, R2;\n" - "MUL R1.xyz, R0, c[1].z;\n" - "ADD R2.w, -fragment.color.primary, c[6].x;\n" - "MAD R2.xyz, R2.w, R1, R2;\n" - "MUL R1.z, R0.w, R2.w;\n" - "MUL R1.x, fragment.color.primary.w, R0.w;\n" - "MUL R1.y, fragment.color.primary.w, R1.w;\n" - "DP3 R2.w, R1, c[1];\n" - "MUL R3.xy, R3, c[2];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[5];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_MULTIPLY = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -R0.w, c[4];\n" - "MUL R1.xyz, fragment.color.primary, R1.x;\n" - "MAD R1.xyz, fragment.color.primary, R0, R1;\n" - "ADD R1.w, -fragment.color.primary, c[4].x;\n" - "MAD R2.xyz, R0, R1.w, R1;\n" - "ADD R1.z, fragment.color.primary.w, R0.w;\n" - "MAD R2.w, -fragment.color.primary, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SCREEN = - "!!ARBfp1.0\n" - "PARAM c[4] = { program.local[0..3] };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "ADD R2, fragment.color.primary, R0;\n" - "MUL R1.xy, R1, c[0];\n" - "MAD R2, -fragment.color.primary, R0, R2;\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_OVERLAY = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R1, R0, texture[0], 2D;\n" - "ADD R0.w, -R1, c[4].y;\n" - "MUL R3.xyz, fragment.color.primary, R0.w;\n" - "ADD R2.xyz, fragment.color.primary.w, -fragment.color.primary;\n" - "ADD R0.xyz, R1.w, -R1;\n" - "MUL R0.xyz, R0, R2;\n" - "MUL R0.xyz, R0, c[4].x;\n" - "MAD R0.xyz, fragment.color.primary.w, R1.w, -R0;\n" - "MAD R0.xyz, fragment.color.primary, R0.w, R0;\n" - "MUL R2.xyz, fragment.color.primary, R1;\n" - "MAD R2.xyz, R2, c[4].x, R3;\n" - "ADD R0.w, -fragment.color.primary, c[4].y;\n" - "MAD R3.xyz, R1, R0.w, R0;\n" - "MAD R2.xyz, R1, R0.w, R2;\n" - "MUL R0.xyz, R1, c[4].x;\n" - "SGE R0.xyz, R0, R1.w;\n" - "ADD R3.xyz, R3, -R2;\n" - "MAD R2.xyz, R0, R3, R2;\n" - "ADD R0.z, fragment.color.primary.w, R1.w;\n" - "MAD R2.w, -fragment.color.primary, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[2];\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[3];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DARKEN = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R2.xyz, fragment.color.primary.w, R0;\n" - "MUL R1.xyz, fragment.color.primary, R0.w;\n" - "MIN R1.xyz, R1, R2;\n" - "ADD R1.w, -R0, c[4].x;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "ADD R1.w, -fragment.color.primary, c[4].x;\n" - "MAD R2.xyz, R0, R1.w, R1;\n" - "ADD R1.z, fragment.color.primary.w, R0.w;\n" - "MAD R2.w, -fragment.color.primary, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_LIGHTEN = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R2.xyz, fragment.color.primary.w, R0;\n" - "MUL R1.xyz, fragment.color.primary, R0.w;\n" - "MAX R1.xyz, R1, R2;\n" - "ADD R1.w, -R0, c[4].x;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "ADD R1.w, -fragment.color.primary, c[4].x;\n" - "MAD R2.xyz, R0, R1.w, R1;\n" - "ADD R1.z, fragment.color.primary.w, R0.w;\n" - "MAD R2.w, -fragment.color.primary, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_COLORDODGE = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -fragment.color.primary.w, c[4];\n" - "MAX R1.y, fragment.color.primary.w, c[4];\n" - "MUL R2.xyz, R0, R1.x;\n" - "ADD R1.w, -R0, c[4].x;\n" - "MAD R3.xyz, fragment.color.primary, R1.w, R2;\n" - "RCP R1.y, R1.y;\n" - "MAD R1.xyz, -fragment.color.primary, R1.y, c[4].x;\n" - "MAX R1.xyz, R1, c[4].y;\n" - "MUL R2.xyz, fragment.color.primary.w, R0;\n" - "MUL R1.w, fragment.color.primary, R0;\n" - "RCP R1.x, R1.x;\n" - "RCP R1.y, R1.y;\n" - "RCP R1.z, R1.z;\n" - "MAD R1.xyz, R2, R1, R3;\n" - "MAD R3.xyz, fragment.color.primary.w, R0.w, R3;\n" - "MAD R2.xyz, fragment.color.primary, R0.w, R2;\n" - "ADD R3.xyz, R3, -R1;\n" - "SGE R2.xyz, R2, R1.w;\n" - "MAD R2.xyz, R2, R3, R1;\n" - "ADD R1.z, fragment.color.primary.w, R0.w;\n" - "MAD R2.w, -fragment.color.primary, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_COLORBURN = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.w, -R0, c[4].x;\n" - "MUL R1.xyz, fragment.color.primary.w, R0;\n" - "MAD R2.xyz, fragment.color.primary, R0.w, R1;\n" - "MAD R1.xyz, -fragment.color.primary.w, R0.w, R2;\n" - "MUL R3.xyz, fragment.color.primary.w, R1;\n" - "MAX R1.xyz, fragment.color.primary, c[4].y;\n" - "ADD R2.w, -fragment.color.primary, c[4].x;\n" - "MUL R4.xyz, fragment.color.primary, R1.w;\n" - "RCP R1.x, R1.x;\n" - "RCP R1.y, R1.y;\n" - "RCP R1.z, R1.z;\n" - "MAD R3.xyz, R3, R1, R4;\n" - "MUL R1.xyz, R0, R2.w;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "MAD R3.xyz, R0, R2.w, R3;\n" - "MUL R1.w, fragment.color.primary, R0;\n" - "ADD R3.xyz, R3, -R1;\n" - "SGE R2.xyz, R2, R1.w;\n" - "MAD R2.xyz, R2, R3, R1;\n" - "ADD R1.z, fragment.color.primary.w, R0.w;\n" - "MAD R2.w, -fragment.color.primary, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_HARDLIGHT = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R1, R0, texture[0], 2D;\n" - "ADD R0.w, -R1, c[4].y;\n" - "MUL R3.xyz, fragment.color.primary, R0.w;\n" - "ADD R2.xyz, fragment.color.primary.w, -fragment.color.primary;\n" - "ADD R0.xyz, R1.w, -R1;\n" - "MUL R0.xyz, R0, R2;\n" - "MUL R0.xyz, R0, c[4].x;\n" - "MAD R0.xyz, fragment.color.primary.w, R1.w, -R0;\n" - "MAD R0.xyz, fragment.color.primary, R0.w, R0;\n" - "MUL R2.xyz, fragment.color.primary, R1;\n" - "MAD R2.xyz, R2, c[4].x, R3;\n" - "ADD R0.w, -fragment.color.primary, c[4].y;\n" - "MAD R3.xyz, R1, R0.w, R0;\n" - "MAD R2.xyz, R1, R0.w, R2;\n" - "MUL R0.xyz, fragment.color.primary, c[4].x;\n" - "SGE R0.xyz, R0, fragment.color.primary.w;\n" - "ADD R3.xyz, R3, -R2;\n" - "MAD R2.xyz, R0, R3, R2;\n" - "ADD R0.z, fragment.color.primary.w, R1.w;\n" - "MAD R2.w, -fragment.color.primary, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[2];\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[3];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SOFTLIGHT = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..3],\n" - " { 1, 2, 9.9999997e-006, 4 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MAX R1.x, R0.w, c[4].z;\n" - "RCP R1.x, R1.x;\n" - "MUL R2.xyz, R0, R1.x;\n" - "MAD R1.xyz, R2, c[5].x, -c[5].y;\n" - "MAD R3.xyz, R2, R1, c[5].z;\n" - "MAD R1.xyz, fragment.color.primary, c[4].y, -fragment.color.primary.w;\n" - "MUL R4.xyz, R0.w, R1;\n" - "MUL R5.xyz, R4, R3;\n" - "RSQ R1.w, R2.x;\n" - "RSQ R2.w, R2.z;\n" - "RCP R3.x, R1.w;\n" - "RSQ R1.w, R2.y;\n" - "MUL R5.xyz, R2, R5;\n" - "RCP R3.z, R2.w;\n" - "RCP R3.y, R1.w;\n" - "ADD R3.xyz, -R2, R3;\n" - "MUL R3.xyz, R4, R3;\n" - "ADD R2.xyz, -R2, c[4].x;\n" - "MAD R1.xyz, R1, R2, fragment.color.primary.w;\n" - "MUL R2.xyz, fragment.color.primary, c[4].y;\n" - "MAD R4.xyz, fragment.color.primary.w, R0, R5;\n" - "MAD R3.xyz, fragment.color.primary.w, R0, R3;\n" - "ADD R5.xyz, R3, -R4;\n" - "MUL R3.xyz, R0, c[4].w;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MAD R3.xyz, R3, R5, R4;\n" - "MAD R3.xyz, -R0, R1, R3;\n" - "MUL R1.xyz, R0, R1;\n" - "SGE R2.xyz, R2, fragment.color.primary.w;\n" - "MAD R2.xyz, R2, R3, R1;\n" - "ADD R1.x, -R0.w, c[4];\n" - "MAD R2.xyz, fragment.color.primary, R1.x, R2;\n" - "ADD R1.x, -fragment.color.primary.w, c[4];\n" - "MAD R2.xyz, R0, R1.x, R2;\n" - "ADD R1.z, fragment.color.primary.w, R0.w;\n" - "MAD R2.w, -fragment.color.primary, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DIFFERENCE = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.xyz, fragment.color.primary, R0;\n" - "MUL R3.xyz, fragment.color.primary.w, R0;\n" - "MUL R2.xyz, fragment.color.primary, R0.w;\n" - "MIN R2.xyz, R2, R3;\n" - "MAD R2.xyz, -R2, c[4].x, R1;\n" - "ADD R1.z, fragment.color.primary.w, R0.w;\n" - "MAD R2.w, -fragment.color.primary, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_EXCLUSION = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[1];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.xyz, fragment.color.primary.w, R0;\n" - "MAD R2.xyz, fragment.color.primary, R0.w, R1;\n" - "MUL R1.xyz, fragment.color.primary, R0;\n" - "MAD R1.xyz, -R1, c[4].x, R2;\n" - "ADD R1.w, -R0, c[4].y;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "ADD R1.w, -fragment.color.primary, c[4].y;\n" - "MAD R2.xyz, R0, R1.w, R1;\n" - "ADD R1.z, fragment.color.primary.w, R0.w;\n" - "MAD R2.w, -fragment.color.primary, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[2];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[3];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[4] = { program.local[0..2],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[2];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.xyz, R0, c[0].y;\n" - "MUL R2.xyz, fragment.color.primary.w, R1;\n" - "MUL R1.xyz, fragment.color.primary, c[0].x;\n" - "MAD R2.xyz, R0.w, R1, R2;\n" - "MUL R0.xyz, R0, c[1].z;\n" - "ADD R1.w, -R0, c[3].x;\n" - "MUL R1.xyz, fragment.color.primary, c[1].y;\n" - "MAD R1.xyz, R1.w, R1, R2;\n" - "ADD R2.x, -fragment.color.primary.w, c[3];\n" - "MAD result.color.xyz, R2.x, R0, R1;\n" - "MUL R0.x, fragment.color.primary.w, R0.w;\n" - "MUL R0.z, R0.w, R2.x;\n" - "MUL R0.y, fragment.color.primary.w, R1.w;\n" - "DP3 result.color.w, R0, c[1];\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_MULTIPLY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -R0.w, c[1];\n" - "MUL R1.xyz, fragment.color.primary, R1.x;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "MAD R1.xyz, fragment.color.primary, R0, R1;\n" - "ADD R2.x, -fragment.color.primary.w, c[1];\n" - "MAD result.color.xyz, R0, R2.x, R1;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SCREEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[1] = { program.local[0] };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1, fragment.color.primary, R0;\n" - "MAD result.color, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_OVERLAY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.w, -R0, c[1].y;\n" - "ADD R2.xyz, fragment.color.primary.w, -fragment.color.primary;\n" - "ADD R1.xyz, R0.w, -R0;\n" - "MUL R1.xyz, R1, R2;\n" - "MUL R1.xyz, R1, c[1].x;\n" - "MAD R1.xyz, fragment.color.primary.w, R0.w, -R1;\n" - "MUL R3.xyz, fragment.color.primary, R1.w;\n" - "MUL R2.xyz, fragment.color.primary, R0;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "ADD R1.w, -fragment.color.primary, c[1].y;\n" - "MAD R2.xyz, R2, c[1].x, R3;\n" - "MAD R2.xyz, R0, R1.w, R2;\n" - "MAD R1.xyz, R0, R1.w, R1;\n" - "MUL R0.xyz, R0, c[1].x;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "ADD R1.xyz, R1, -R2;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD result.color.xyz, R0, R1, R2;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DARKEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R2.xyz, fragment.color.primary.w, R0;\n" - "MUL R1.xyz, fragment.color.primary, R0.w;\n" - "MIN R1.xyz, R1, R2;\n" - "ADD R1.w, -R0, c[1].x;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "ADD R2.x, -fragment.color.primary.w, c[1];\n" - "MAD result.color.xyz, R0, R2.x, R1;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_LIGHTEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R2.xyz, fragment.color.primary.w, R0;\n" - "MUL R1.xyz, fragment.color.primary, R0.w;\n" - "MAX R1.xyz, R1, R2;\n" - "ADD R1.w, -R0, c[1].x;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "ADD R2.x, -fragment.color.primary.w, c[1];\n" - "MAD result.color.xyz, R0, R2.x, R1;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_COLORDODGE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MAX R1.y, fragment.color.primary.w, c[1];\n" - "RCP R2.x, R1.y;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -fragment.color.primary.w, c[1];\n" - "MUL R1.xyz, R0, R1.x;\n" - "ADD R1.w, -R0, c[1].x;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "MAD R2.xyz, -fragment.color.primary, R2.x, c[1].x;\n" - "MAX R2.xyz, R2, c[1].y;\n" - "MUL R0.xyz, fragment.color.primary.w, R0;\n" - "MUL R1.w, fragment.color.primary, R0;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R0, R2, R1;\n" - "MAD R1.xyz, fragment.color.primary.w, R0.w, R1;\n" - "MAD R0.xyz, fragment.color.primary, R0.w, R0;\n" - "SGE R0.xyz, R0, R1.w;\n" - "ADD R1.xyz, R1, -R2;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "MAD result.color.xyz, R0, R1, R2;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_COLORBURN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.xyz, fragment.color.primary.w, R0;\n" - "MAD R2.xyz, fragment.color.primary, R0.w, R1;\n" - "MAD R1.xyz, -fragment.color.primary.w, R0.w, R2;\n" - "MUL R3.xyz, fragment.color.primary.w, R1;\n" - "MAX R1.xyz, fragment.color.primary, c[1].y;\n" - "ADD R1.w, -R0, c[1].x;\n" - "MUL R4.xyz, fragment.color.primary, R1.w;\n" - "ADD R2.w, -fragment.color.primary, c[1].x;\n" - "RCP R1.x, R1.x;\n" - "RCP R1.y, R1.y;\n" - "RCP R1.z, R1.z;\n" - "MAD R1.xyz, R3, R1, R4;\n" - "MUL R3.xyz, R0, R2.w;\n" - "MAD R0.xyz, R0, R2.w, R1;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R3;\n" - "MUL R1.w, fragment.color.primary, R0;\n" - "SGE R2.xyz, R2, R1.w;\n" - "ADD R0.xyz, R0, -R1;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "MAD result.color.xyz, R2, R0, R1;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_HARDLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.w, -R0, c[1].y;\n" - "ADD R2.xyz, fragment.color.primary.w, -fragment.color.primary;\n" - "ADD R1.xyz, R0.w, -R0;\n" - "MUL R1.xyz, R1, R2;\n" - "MUL R1.xyz, R1, c[1].x;\n" - "MAD R1.xyz, fragment.color.primary.w, R0.w, -R1;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "MUL R3.xyz, fragment.color.primary, R1.w;\n" - "MUL R2.xyz, fragment.color.primary, R0;\n" - "ADD R1.w, -fragment.color.primary, c[1].y;\n" - "MAD R2.xyz, R2, c[1].x, R3;\n" - "MAD R2.xyz, R0, R1.w, R2;\n" - "MAD R0.xyz, R0, R1.w, R1;\n" - "ADD R1.xyz, R0, -R2;\n" - "MUL R0.xyz, fragment.color.primary, c[1].x;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "SGE R0.xyz, R0, fragment.color.primary.w;\n" - "MAD result.color.xyz, R0, R1, R2;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SOFTLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[3] = { program.local[0],\n" - " { 1, 2, 9.9999997e-006, 4 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MAX R1.x, R0.w, c[1].z;\n" - "RCP R1.x, R1.x;\n" - "MUL R2.xyz, R0, R1.x;\n" - "MAD R1.xyz, R2, c[2].x, -c[2].y;\n" - "MAD R3.xyz, R2, R1, c[2].z;\n" - "MAD R1.xyz, fragment.color.primary, c[1].y, -fragment.color.primary.w;\n" - "MUL R4.xyz, R0.w, R1;\n" - "MUL R5.xyz, R4, R3;\n" - "RSQ R1.w, R2.x;\n" - "RCP R3.x, R1.w;\n" - "RSQ R2.w, R2.z;\n" - "RSQ R1.w, R2.y;\n" - "MUL R5.xyz, R2, R5;\n" - "RCP R3.z, R2.w;\n" - "RCP R3.y, R1.w;\n" - "ADD R3.xyz, -R2, R3;\n" - "MUL R3.xyz, R4, R3;\n" - "ADD R2.xyz, -R2, c[1].x;\n" - "MAD R1.xyz, R1, R2, fragment.color.primary.w;\n" - "MUL R2.xyz, fragment.color.primary, c[1].y;\n" - "MAD R4.xyz, fragment.color.primary.w, R0, R5;\n" - "MAD R3.xyz, fragment.color.primary.w, R0, R3;\n" - "ADD R5.xyz, R3, -R4;\n" - "MUL R3.xyz, R0, c[1].w;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MAD R3.xyz, R3, R5, R4;\n" - "MAD R3.xyz, -R0, R1, R3;\n" - "MUL R1.xyz, R0, R1;\n" - "SGE R2.xyz, R2, fragment.color.primary.w;\n" - "MAD R2.xyz, R2, R3, R1;\n" - "ADD R1.x, -R0.w, c[1];\n" - "MAD R2.xyz, fragment.color.primary, R1.x, R2;\n" - "ADD R1.x, fragment.color.primary.w, R0.w;\n" - "ADD R1.y, -fragment.color.primary.w, c[1].x;\n" - "MAD result.color.xyz, R0, R1.y, R2;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DIFFERENCE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R2.xyz, fragment.color.primary.w, R0;\n" - "MUL R1.xyz, fragment.color.primary, R0.w;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "MIN R1.xyz, R1, R2;\n" - "ADD R0.xyz, fragment.color.primary, R0;\n" - "MAD result.color.xyz, -R1, c[1].x, R0;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_EXCLUSION_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[2] = { program.local[0],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xy, fragment.position, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.xyz, fragment.color.primary.w, R0;\n" - "MAD R2.xyz, fragment.color.primary, R0.w, R1;\n" - "MUL R1.xyz, fragment.color.primary, R0;\n" - "MAD R1.xyz, -R1, c[1].x, R2;\n" - "ADD R1.w, -R0, c[1].y;\n" - "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n" - "ADD R1.w, fragment.color.primary, R0;\n" - "ADD R2.x, -fragment.color.primary.w, c[1].y;\n" - "MAD result.color.xyz, R0, R2.x, R1;\n" - "MAD result.color.w, -fragment.color.primary, R0, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODE_BLEND_MODE_MASK = - "!!ARBfp1.0\n" - "PARAM c[3] = { program.local[0..2] };\n" - "TEMP R0;\n" - "ADD R0.xy, fragment.position, c[1];\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[0], 2D;\n" - "DP4 R0.x, R0, c[2];\n" - "MUL result.color, fragment.color.primary, R0.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODE_BLEND_MODE_NOMASK = - "!!ARBfp1.0\n" - "MOV result.color, fragment.color.primary;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF = - "!!ARBfp1.0\n" - "PARAM c[12] = { program.local[0..10],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[11].x;\n" - "MUL R0.z, R0, c[11].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.x, R0.x;\n" - "RCP R0.z, R0.x;\n" - "ADD R1.x, -R0.y, R0.z;\n" - "MOV R0.x, c[11];\n" - "MUL R0.z, R0.x, c[1].x;\n" - "RCP R1.y, R0.z;\n" - "MUL R0.xy, fragment.position, c[8];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.x, R1, R1.y;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R2.xyz, R0, c[5].y;\n" - "MUL R3.xyz, R1.w, R2;\n" - "MUL R2.xyz, R1, c[5].x;\n" - "MAD R2.xyz, R0.w, R2, R3;\n" - "ADD R3.xy, fragment.position, c[9];\n" - "ADD R2.w, -R0, c[11].z;\n" - "MUL R1.xyz, R1, c[6].y;\n" - "MAD R2.xyz, R2.w, R1, R2;\n" - "MUL R1.xyz, R0, c[6].z;\n" - "ADD R3.z, -R1.w, c[11];\n" - "MAD R2.xyz, R3.z, R1, R2;\n" - "MUL R1.y, R1.w, R2.w;\n" - "MUL R1.x, R1.w, R0.w;\n" - "MUL R1.z, R0.w, R3;\n" - "DP3 R2.w, R1, c[6];\n" - "MUL R3.xy, R3, c[7];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[10];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_MULTIPLY = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.x, R0.x;\n" - "RCP R0.z, R0.x;\n" - "ADD R1.x, -R0.y, R0.z;\n" - "MOV R0.x, c[9];\n" - "MUL R0.z, R0.x, c[1].x;\n" - "RCP R1.y, R0.z;\n" - "MUL R0.xy, fragment.position, c[6];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.x, R1, R1.y;\n" - "TEX R1, R1, texture[2], 1D;\n" - "ADD R2.x, -R0.w, c[9].z;\n" - "MUL R2.xyz, R1, R2.x;\n" - "MAD R1.xyz, R1, R0, R2;\n" - "ADD R2.x, -R1.w, c[9].z;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[7];\n" - "MUL R1.xy, R1, c[5];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[8];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SCREEN = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.z, R0.y, R0.y, -R0;\n" - "ADD R3.xy, fragment.position, c[7];\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RSQ R0.z, R0.z;\n" - "RCP R0.x, R0.z;\n" - "RCP R0.z, R0.w;\n" - "ADD R0.x, -R0.y, R0;\n" - "MUL R0.z, R0.x, R0;\n" - "TEX R1, R0.z, texture[2], 1D;\n" - "MUL R0.xy, fragment.position, c[6];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R2, R1, R0;\n" - "MAD R2, -R1, R0, R2;\n" - "MUL R3.xy, R3, c[5];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[8];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_OVERLAY = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.z, R0.y, R0.y, -R0;\n" - "MUL R1.xy, fragment.position, c[6];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RSQ R0.z, R0.z;\n" - "RCP R0.x, R0.z;\n" - "ADD R2.w, -R1, c[9].z;\n" - "RCP R0.z, R0.w;\n" - "ADD R0.x, -R0.y, R0;\n" - "MUL R0.x, R0, R0.z;\n" - "TEX R0, R0, texture[2], 1D;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[9].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MUL R3.xyz, R0, R1;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, -R0.w, c[9].z;\n" - "MAD R3.xyz, R3, c[9].x, R4;\n" - "MAD R3.xyz, R1, R2.x, R3;\n" - "MAD R0.xyz, R1, R2.x, R0;\n" - "MUL R2.xyz, R1, c[9].x;\n" - "ADD R0.xyz, R0, -R3;\n" - "SGE R2.xyz, R2, R1.w;\n" - "MAD R2.xyz, R2, R0, R3;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[7];\n" - "MUL R0.xy, R0, c[5];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[8];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DARKEN = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.x, R0, c[1];\n" - "RCP R0.z, R0.z;\n" - "ADD R0.z, -R0.y, R0;\n" - "RCP R0.w, R0.x;\n" - "MUL R1.x, R0.z, R0.w;\n" - "MUL R0.xy, fragment.position, c[6];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[9].z;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[9].z;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[7];\n" - "MUL R1.xy, R1, c[5];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[8];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_LIGHTEN = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.x, R0, c[1];\n" - "RCP R0.z, R0.z;\n" - "ADD R0.z, -R0.y, R0;\n" - "RCP R0.w, R0.x;\n" - "MUL R1.x, R0.z, R0.w;\n" - "MUL R0.xy, fragment.position, c[6];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[9].z;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[9].z;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[7];\n" - "MUL R1.xy, R1, c[5];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[8];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORDODGE = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4, 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.z, R0.y, R0.y, -R0;\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RSQ R0.z, R0.z;\n" - "RCP R0.x, R0.z;\n" - "RCP R0.z, R0.w;\n" - "ADD R0.x, -R0.y, R0;\n" - "MUL R0.x, R0, R0.z;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MAX R1.x, R0.w, c[9].w;\n" - "RCP R1.x, R1.x;\n" - "MAD R1.xyz, -R0, R1.x, c[9].z;\n" - "MAX R2.xyz, R1, c[9].w;\n" - "MUL R1.xy, fragment.position, c[6];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R0, c[9].z;\n" - "MUL R3.xyz, R1, R2.w;\n" - "ADD R2.w, -R1, c[9].z;\n" - "MAD R4.xyz, R0, R2.w, R3;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MUL R2.w, R0, R1;\n" - "MAD R0.xyz, R0, R1.w, R3;\n" - "SGE R0.xyz, R0, R2.w;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R3, R2, R4;\n" - "MAD R4.xyz, R0.w, R1.w, R4;\n" - "ADD R4.xyz, R4, -R2;\n" - "MAD R2.xyz, R0, R4, R2;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[7];\n" - "MUL R0.xy, R0, c[5];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[8];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORBURN = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4, 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RCP R0.z, R0.z;\n" - "ADD R0.x, -R0.y, R0.z;\n" - "RCP R0.y, R0.w;\n" - "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, R0.y;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "MAD R2.xyz, -R0.w, R1.w, R3;\n" - "MUL R4.xyz, R0.w, R2;\n" - "MAX R2.xyz, R0, c[9].w;\n" - "ADD R2.w, -R1, c[9].z;\n" - "MUL R5.xyz, R0, R2.w;\n" - "ADD R3.w, -R0, c[9].z;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R1, R3.w;\n" - "MAD R0.xyz, R0, R2.w, R4;\n" - "MUL R2.w, R0, R1;\n" - "MAD R2.xyz, R1, R3.w, R2;\n" - "ADD R2.xyz, R2, -R0;\n" - "SGE R3.xyz, R3, R2.w;\n" - "MAD R2.xyz, R3, R2, R0;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[7];\n" - "MUL R0.xy, R0, c[5];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[8];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_HARDLIGHT = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.z, R0.y, R0.y, -R0;\n" - "MUL R1.xy, fragment.position, c[6];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RSQ R0.z, R0.z;\n" - "RCP R0.x, R0.z;\n" - "ADD R2.w, -R1, c[9].z;\n" - "RCP R0.z, R0.w;\n" - "ADD R0.x, -R0.y, R0;\n" - "MUL R0.x, R0, R0.z;\n" - "TEX R0, R0, texture[2], 1D;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[9].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R3.xyz, R0, R1;\n" - "ADD R2.w, -R0, c[9].z;\n" - "MAD R3.xyz, R3, c[9].x, R4;\n" - "MUL R0.xyz, R0, c[9].x;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD R3.xyz, R1, R2.w, R3;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "ADD R2.xyz, R2, -R3;\n" - "MAD R2.xyz, R0, R2, R3;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[7];\n" - "MUL R0.xy, R0, c[5];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[8];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SOFTLIGHT = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..8],\n" - " { 2, 4, 1, 9.9999997e-006 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.z, c[9];\n" - "MUL R0.x, R0, c[9];\n" - "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MAD R0.y, R0.x, R0.x, -R0;\n" - "RSQ R0.y, R0.y;\n" - "RCP R0.y, R0.y;\n" - "ADD R0.y, -R0.x, R0;\n" - "MOV R0.x, c[9];\n" - "MUL R0.x, R0, c[1];\n" - "MAX R0.z, R1.w, c[9].w;\n" - "RCP R0.z, R0.z;\n" - "MUL R3.xyz, R1, R0.z;\n" - "MAD R4.xyz, R3, c[10].x, -c[10].y;\n" - "RCP R0.x, R0.x;\n" - "MUL R0.x, R0.y, R0;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MAD R2.xyz, R0, c[9].x, -R0.w;\n" - "MAD R4.xyz, R3, R4, c[10].z;\n" - "MUL R5.xyz, R1.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[9].z;\n" - "MAD R2.xyz, R2, R3, R0.w;\n" - "MUL R3.xyz, R0, c[9].x;\n" - "MAD R5.xyz, R0.w, R1, R6;\n" - "MAD R4.xyz, R0.w, R1, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R1, c[9].y;\n" - "SGE R4.xyz, R4, R1.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R1, R2, R4;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MUL R2.xyz, R1, R2;\n" - "ADD R2.w, -R1, c[9].z;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R0.x, -R0.w, c[9].z;\n" - "MAD R2.xyz, R1, R0.x, R2;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[7];\n" - "MUL R0.xy, R0, c[5];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[8];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DIFFERENCE = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.x, R0, c[1];\n" - "RCP R0.z, R0.z;\n" - "ADD R0.z, -R0.y, R0;\n" - "RCP R0.w, R0.x;\n" - "MUL R1.x, R0.z, R0.w;\n" - "MUL R0.xy, fragment.position, c[6];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "ADD R2.xyz, R1, R0;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R1.xyz, R1, R0.w;\n" - "MIN R1.xyz, R1, R3;\n" - "MAD R2.xyz, -R1, c[9].x, R2;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[7];\n" - "MUL R1.xy, R1, c[5];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[8];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_EXCLUSION = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..8],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[9].x;\n" - "MUL R0.z, R0, c[9].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[9];\n" - "MUL R0.x, R0, c[1];\n" - "RCP R0.z, R0.z;\n" - "ADD R0.z, -R0.y, R0;\n" - "RCP R0.w, R0.x;\n" - "MUL R1.x, R0.z, R0.w;\n" - "MUL R0.xy, fragment.position, c[6];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R2.xyz, R1.w, R0;\n" - "MAD R3.xyz, R1, R0.w, R2;\n" - "MUL R2.xyz, R1, R0;\n" - "MAD R2.xyz, -R2, c[9].x, R3;\n" - "ADD R2.w, -R0, c[9].z;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[9].z;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[7];\n" - "MUL R1.xy, R1, c[5];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[8];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[8].x;\n" - "MUL R0.z, R0, c[8].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.x, R0.x;\n" - "RCP R0.z, R0.x;\n" - "ADD R0.y, -R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R2.xyz, R1, c[5].y;\n" - "MOV R0.x, c[8];\n" - "MUL R0.x, R0, c[1];\n" - "RCP R0.x, R0.x;\n" - "MUL R0.x, R0.y, R0;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R3.xyz, R0.w, R2;\n" - "MUL R2.xyz, R0, c[5].x;\n" - "MAD R2.xyz, R1.w, R2, R3;\n" - "ADD R2.w, -R1, c[8].z;\n" - "MUL R0.xyz, R0, c[6].y;\n" - "MAD R0.xyz, R2.w, R0, R2;\n" - "ADD R2.x, -R0.w, c[8].z;\n" - "MUL R1.xyz, R1, c[6].z;\n" - "MAD result.color.xyz, R2.x, R1, R0;\n" - "MUL R0.x, R0.w, R1.w;\n" - "MUL R0.z, R1.w, R2.x;\n" - "MUL R0.y, R0.w, R2.w;\n" - "DP3 result.color.w, R0, c[6];\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_MULTIPLY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.x, R0.x;\n" - "RCP R0.z, R0.x;\n" - "ADD R0.y, -R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MOV R0.x, c[6];\n" - "MUL R0.x, R0, c[1];\n" - "RCP R0.x, R0.x;\n" - "MUL R0.x, R0.y, R0;\n" - "TEX R0, R0, texture[1], 1D;\n" - "ADD R2.x, -R1.w, c[6].z;\n" - "MUL R2.xyz, R0, R2.x;\n" - "MAD R0.xyz, R0, R1, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[6].z;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SCREEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RCP R0.z, R0.z;\n" - "ADD R0.x, -R0.y, R0.z;\n" - "RCP R0.y, R0.w;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "ADD R2, R0, R1;\n" - "MAD result.color, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_OVERLAY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.z, R0.y, R0.y, -R0;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RSQ R0.z, R0.z;\n" - "RCP R0.x, R0.z;\n" - "ADD R2.w, -R1, c[6].z;\n" - "RCP R0.z, R0.w;\n" - "ADD R0.x, -R0.y, R0;\n" - "MUL R0.x, R0, R0.z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[6].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R3.xyz, R0, R2.w;\n" - "MUL R0.xyz, R0, R1;\n" - "ADD R2.w, -R0, c[6].z;\n" - "MAD R0.xyz, R0, c[6].x, R3;\n" - "MAD R0.xyz, R1, R2.w, R0;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MUL R1.xyz, R1, c[6].x;\n" - "ADD R2.w, R0, R1;\n" - "ADD R2.xyz, R2, -R0;\n" - "SGE R1.xyz, R1, R1.w;\n" - "MAD result.color.xyz, R1, R2, R0;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DARKEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RCP R0.z, R0.z;\n" - "ADD R0.x, -R0.y, R0.z;\n" - "RCP R0.y, R0.w;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[6].z;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[6].z;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_LIGHTEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RCP R0.z, R0.z;\n" - "ADD R0.x, -R0.y, R0.z;\n" - "RCP R0.y, R0.w;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[6].z;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[6].z;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORDODGE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4, 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.z, R0.y, R0.y, -R0;\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RSQ R0.z, R0.z;\n" - "RCP R0.x, R0.z;\n" - "RCP R0.z, R0.w;\n" - "ADD R0.x, -R0.y, R0;\n" - "MUL R0.x, R0, R0.z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MAX R1.x, R0.w, c[6].w;\n" - "RCP R1.x, R1.x;\n" - "MAD R1.xyz, -R0, R1.x, c[6].z;\n" - "MAX R2.xyz, R1, c[6].w;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R0, c[6].z;\n" - "MUL R3.xyz, R1, R2.w;\n" - "ADD R2.w, -R1, c[6].z;\n" - "MAD R3.xyz, R0, R2.w, R3;\n" - "MUL R1.xyz, R0.w, R1;\n" - "MAD R0.xyz, R0, R1.w, R1;\n" - "MUL R2.w, R0, R1;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R1, R2, R3;\n" - "MAD R3.xyz, R0.w, R1.w, R3;\n" - "ADD R1.x, R0.w, R1.w;\n" - "ADD R3.xyz, R3, -R2;\n" - "SGE R0.xyz, R0, R2.w;\n" - "MAD result.color.xyz, R0, R3, R2;\n" - "MAD result.color.w, -R0, R1, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORBURN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4, 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RCP R0.z, R0.z;\n" - "ADD R0.x, -R0.y, R0.z;\n" - "RCP R0.y, R0.w;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "ADD R2.w, -R1, c[6].z;\n" - "MAD R2.xyz, -R0.w, R1.w, R3;\n" - "MUL R4.xyz, R0.w, R2;\n" - "MAX R2.xyz, R0, c[6].w;\n" - "MUL R5.xyz, R0, R2.w;\n" - "ADD R3.w, -R0, c[6].z;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R1, R3.w;\n" - "MAD R1.xyz, R1, R3.w, R2;\n" - "MAD R0.xyz, R0, R2.w, R4;\n" - "MUL R2.x, R0.w, R1.w;\n" - "ADD R2.w, R0, R1;\n" - "ADD R1.xyz, R1, -R0;\n" - "SGE R2.xyz, R3, R2.x;\n" - "MAD result.color.xyz, R2, R1, R0;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_HARDLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.z, R0.y, R0.y, -R0;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RSQ R0.z, R0.z;\n" - "RCP R0.x, R0.z;\n" - "ADD R2.w, -R1, c[6].z;\n" - "RCP R0.z, R0.w;\n" - "ADD R0.x, -R0.y, R0;\n" - "MUL R0.x, R0, R0.z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[6].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MUL R3.xyz, R0, R1;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R2.w, -R0, c[6].z;\n" - "MUL R0.xyz, R0, c[6].x;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MAD R3.xyz, R3, c[6].x, R4;\n" - "MAD R1.xyz, R1, R2.w, R3;\n" - "ADD R2.w, R0, R1;\n" - "ADD R2.xyz, R2, -R1;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD result.color.xyz, R0, R2, R1;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SOFTLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..5],\n" - " { 2, 4, 1, 9.9999997e-006 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.z, c[6];\n" - "MUL R0.x, R0, c[6];\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MAD R0.y, R0.x, R0.x, -R0;\n" - "RSQ R0.y, R0.y;\n" - "RCP R0.y, R0.y;\n" - "ADD R0.y, -R0.x, R0;\n" - "MOV R0.x, c[6];\n" - "MUL R0.x, R0, c[1];\n" - "MAX R0.z, R1.w, c[6].w;\n" - "RCP R0.z, R0.z;\n" - "MUL R3.xyz, R1, R0.z;\n" - "MAD R4.xyz, R3, c[7].x, -c[7].y;\n" - "RCP R0.x, R0.x;\n" - "MUL R0.x, R0.y, R0;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MAD R2.xyz, R0, c[6].x, -R0.w;\n" - "MAD R4.xyz, R3, R4, c[7].z;\n" - "MUL R5.xyz, R1.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[6].z;\n" - "MAD R2.xyz, R2, R3, R0.w;\n" - "MUL R3.xyz, R0, c[6].x;\n" - "MAD R5.xyz, R0.w, R1, R6;\n" - "MAD R4.xyz, R0.w, R1, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R1, c[6].y;\n" - "SGE R4.xyz, R4, R1.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R1, R2, R4;\n" - "MUL R2.xyz, R1, R2;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "ADD R2.w, -R1, c[6].z;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R0.x, R0.w, R1.w;\n" - "ADD R0.y, -R0.w, c[6].z;\n" - "MAD result.color.xyz, R1, R0.y, R2;\n" - "MAD result.color.w, -R0, R1, R0.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DIFFERENCE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RCP R0.z, R0.z;\n" - "ADD R0.x, -R0.y, R0.z;\n" - "RCP R0.y, R0.w;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "ADD R0.xyz, R0, R1;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R1.x, R0.w, R1.w;\n" - "MAD result.color.xyz, -R2, c[6].x, R0;\n" - "MAD result.color.w, -R0, R1, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_EXCLUSION_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..5],\n" - " { 2, 4, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.x, c[6].x;\n" - "MUL R0.z, R0, c[6].y;\n" - "MAD R0.x, R0.y, R0.y, -R0.z;\n" - "RSQ R0.z, R0.x;\n" - "MOV R0.x, c[6];\n" - "MUL R0.w, R0.x, c[1].x;\n" - "RCP R0.z, R0.z;\n" - "ADD R0.x, -R0.y, R0.z;\n" - "RCP R0.y, R0.w;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "MUL R2.xyz, R0, R1;\n" - "MAD R2.xyz, -R2, c[6].x, R3;\n" - "ADD R2.w, -R1, c[6].z;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[6].z;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODE_BLEND_MODE_MASK = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2, 4 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "ADD R0.z, R0, R0.w;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.z, c[8];\n" - "MUL R0.x, R0, c[8];\n" - "MAD R0.y, R0.x, R0.x, -R0;\n" - "RSQ R0.y, R0.y;\n" - "RCP R0.y, R0.y;\n" - "ADD R1.x, -R0, R0.y;\n" - "MOV R0.x, c[8];\n" - "MUL R0.x, R0, c[1];\n" - "RCP R1.y, R0.x;\n" - "ADD R0.zw, fragment.position.xyxy, c[6].xyxy;\n" - "MUL R0.zw, R0, c[5].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R1.x, R1, R1.y;\n" - "DP4 R1.y, R0, c[7];\n" - "TEX R0, R1, texture[1], 1D;\n" - "MUL result.color, R0, R1.y;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODE_BLEND_MODE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2, 4 } };\n" - "TEMP R0;\n" - "MUL R0.xyz, fragment.position.y, c[3];\n" - "MAD R0.xyz, fragment.position.x, c[2], R0;\n" - "ADD R0.xyz, R0, c[4];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.xyxy;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.z, R0, R0.w;\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, -R0, c[1].x;\n" - "MUL R0.y, R0.z, c[5];\n" - "MUL R0.x, R0, c[5];\n" - "MAD R0.z, R0.x, R0.x, -R0.y;\n" - "MOV R0.y, c[5].x;\n" - "RSQ R0.z, R0.z;\n" - "MUL R0.w, R0.y, c[1].x;\n" - "RCP R0.y, R0.z;\n" - "RCP R0.z, R0.w;\n" - "ADD R0.x, -R0, R0.y;\n" - "MUL R0.x, R0, R0.z;\n" - "TEX result.color, R0, texture[0], 1D;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF = - "!!ARBfp1.0\n" - "PARAM c[13] = { program.local[0..9],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[10].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[11].x, c[11].y;\n" - "MAD R1.z, R1, R1.y, -c[11];\n" - "MAD R1.z, R1, R1.y, c[11].w;\n" - "MAD R1.z, R1, R1.y, -c[12].x;\n" - "MAD R1.y, R1.z, R1, c[12];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[10].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[10].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R1.x, R0, c[10];\n" - "FLR R1.y, R1.x;\n" - "MUL R0.xy, fragment.position, c[7];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, R1, -R1.y;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R2.xyz, R0, c[4].y;\n" - "MUL R3.xyz, R1.w, R2;\n" - "MUL R2.xyz, R1, c[4].x;\n" - "MAD R2.xyz, R0.w, R2, R3;\n" - "ADD R3.xy, fragment.position, c[8];\n" - "ADD R2.w, -R0, c[12].z;\n" - "MUL R1.xyz, R1, c[5].y;\n" - "MAD R2.xyz, R2.w, R1, R2;\n" - "MUL R1.xyz, R0, c[5].z;\n" - "ADD R3.z, -R1.w, c[12];\n" - "MAD R2.xyz, R3.z, R1, R2;\n" - "MUL R1.y, R1.w, R2.w;\n" - "MUL R1.x, R1.w, R0.w;\n" - "MUL R1.z, R0.w, R3;\n" - "DP3 R2.w, R1, c[5];\n" - "MUL R3.xy, R3, c[6];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[9];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_MULTIPLY = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[9].x, c[9].y;\n" - "MAD R1.z, R1, R1.y, -c[9];\n" - "MAD R1.z, R1, R1.y, c[9].w;\n" - "MAD R1.z, R1, R1.y, -c[10].x;\n" - "MAD R1.y, R1.z, R1, c[10];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[8].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[8].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R1.x, R0, c[8];\n" - "FLR R1.y, R1.x;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, R1, -R1.y;\n" - "TEX R1, R1, texture[2], 1D;\n" - "ADD R2.x, -R0.w, c[10].z;\n" - "MUL R2.xyz, R1, R2.x;\n" - "MAD R1.xyz, R1, R0, R2;\n" - "ADD R2.x, -R1.w, c[10].z;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SCREEN = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ADD R3.xy, fragment.position, c[6];\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[9].x, c[9].y;\n" - "MAD R1.z, R1, R1.y, -c[9];\n" - "MAD R1.z, R1, R1.y, c[9].w;\n" - "MAD R1.z, R1, R1.y, -c[10].x;\n" - "MAD R1.y, R1.z, R1, c[10];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[8].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[8].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[8];\n" - "FLR R0.y, R0.x;\n" - "ADD R0.z, R0.x, -R0.y;\n" - "TEX R1, R0.z, texture[2], 1D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R2, R1, R0;\n" - "MAD R2, -R1, R0, R2;\n" - "MUL R3.xy, R3, c[4];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_OVERLAY = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8];\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[8].y, c[8];\n" - "MAD R1.z, R1, R1.y, -c[8].w;\n" - "MAD R1.z, R1, R1.y, c[9].x;\n" - "MAD R1.z, R1, R1.y, -c[9].y;\n" - "MAD R1.y, R1.z, R1, c[9].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[9].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[10].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[10].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[10];\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[10].z;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MUL R3.xyz, R0, R1;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, -R0.w, c[10].w;\n" - "MAD R3.xyz, R3, c[10].z, R4;\n" - "MAD R3.xyz, R1, R2.x, R3;\n" - "MAD R0.xyz, R1, R2.x, R0;\n" - "MUL R2.xyz, R1, c[10].z;\n" - "ADD R0.xyz, R0, -R3;\n" - "SGE R2.xyz, R2, R1.w;\n" - "MAD R2.xyz, R2, R0, R3;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DARKEN = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[9].x, c[9].y;\n" - "MAD R1.z, R1, R1.y, -c[9];\n" - "MAD R1.z, R1, R1.y, c[9].w;\n" - "MAD R1.z, R1, R1.y, -c[10].x;\n" - "MAD R1.y, R1.z, R1, c[10];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[8].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[8].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.z, R0.x, c[8].x;\n" - "FLR R0.w, R0.z;\n" - "ADD R1.x, R0.z, -R0.w;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[10].z;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[10].z;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_LIGHTEN = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[9].x, c[9].y;\n" - "MAD R1.z, R1, R1.y, -c[9];\n" - "MAD R1.z, R1, R1.y, c[9].w;\n" - "MAD R1.z, R1, R1.y, -c[10].x;\n" - "MAD R1.y, R1.z, R1, c[10];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[8].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[8].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.z, R0.x, c[8].x;\n" - "FLR R0.w, R0.z;\n" - "ADD R1.x, R0.z, -R0.w;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[10].z;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[10].z;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORDODGE = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8];\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[8].y, c[8];\n" - "MAD R1.z, R1, R1.y, -c[8].w;\n" - "MAD R1.z, R1, R1.y, c[9].x;\n" - "MAD R1.z, R1, R1.y, -c[9].y;\n" - "MAD R1.y, R1.z, R1, c[9].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[9].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[10].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[10].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MAX R1.x, R0.w, c[10].w;\n" - "RCP R1.x, R1.x;\n" - "MAD R1.xyz, -R0, R1.x, c[10].z;\n" - "MAX R2.xyz, R1, c[10].w;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R0, c[10].z;\n" - "MUL R3.xyz, R1, R2.w;\n" - "ADD R2.w, -R1, c[10].z;\n" - "MAD R4.xyz, R0, R2.w, R3;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MUL R2.w, R0, R1;\n" - "MAD R0.xyz, R0, R1.w, R3;\n" - "SGE R0.xyz, R0, R2.w;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R3, R2, R4;\n" - "MAD R4.xyz, R0.w, R1.w, R4;\n" - "ADD R4.xyz, R4, -R2;\n" - "MAD R2.xyz, R0, R4, R2;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORBURN = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.w, R0.x;\n" - "ABS R0.z, R0.y;\n" - "ADD R0.z, R0, -R0.w;\n" - "ADD R1.x, R0.y, c[8];\n" - "ABS R0.z, R0;\n" - "CMP R0.y, -R0.z, R0, R1.x;\n" - "ABS R0.z, -R0.y;\n" - "MAX R1.x, R0.w, R0.z;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.w, R0.z;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[8].y, c[8];\n" - "MAD R1.z, R1, R1.y, -c[8].w;\n" - "MAD R1.z, R1, R1.y, c[9].x;\n" - "MAD R1.z, R1, R1.y, -c[9].y;\n" - "MAD R1.y, R1.z, R1, c[9].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[9].w;\n" - "ADD R0.z, -R0.w, R0;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[10].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[10].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "MAD R2.xyz, -R0.w, R1.w, R3;\n" - "MUL R4.xyz, R0.w, R2;\n" - "MAX R2.xyz, R0, c[10].w;\n" - "ADD R2.w, -R1, c[10].z;\n" - "ADD R3.w, -R0, c[10].z;\n" - "MUL R5.xyz, R0, R2.w;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R1, R3.w;\n" - "MAD R0.xyz, R0, R2.w, R4;\n" - "MUL R2.w, R0, R1;\n" - "MAD R2.xyz, R1, R3.w, R2;\n" - "ADD R2.xyz, R2, -R0;\n" - "SGE R3.xyz, R3, R2.w;\n" - "MAD R2.xyz, R3, R2, R0;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_HARDLIGHT = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8];\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[8].y, c[8];\n" - "MAD R1.z, R1, R1.y, -c[8].w;\n" - "MAD R1.z, R1, R1.y, c[9].x;\n" - "MAD R1.z, R1, R1.y, -c[9].y;\n" - "MAD R1.y, R1.z, R1, c[9].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[9].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[10].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[10].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[10];\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[10].z;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R3.xyz, R0, R1;\n" - "ADD R2.w, -R0, c[10];\n" - "MAD R3.xyz, R3, c[10].z, R4;\n" - "MUL R0.xyz, R0, c[10].z;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD R3.xyz, R1, R2.w, R3;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "ADD R2.xyz, R2, -R3;\n" - "MAD R2.xyz, R0, R2, R3;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SOFTLIGHT = - "!!ARBfp1.0\n" - "PARAM c[13] = { program.local[0..7],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 1, 2 },\n" - " { 9.9999997e-006, 4, 16, 12 },\n" - " { 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.w, R0.x;\n" - "ABS R0.z, R0.y;\n" - "ADD R0.z, R0, -R0.w;\n" - "ADD R1.x, R0.y, c[8];\n" - "ABS R0.z, R0;\n" - "CMP R0.y, -R0.z, R0, R1.x;\n" - "ABS R0.z, -R0.y;\n" - "MAX R1.x, R0.w, R0.z;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.w, R0.z;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[8].y, c[8];\n" - "MAD R1.z, R1, R1.y, -c[8].w;\n" - "MAD R1.z, R1, R1.y, c[9].x;\n" - "MAD R1.z, R1, R1.y, -c[9].y;\n" - "MAD R1.y, R1.z, R1, c[9].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[9].w;\n" - "ADD R0.z, -R0.w, R0;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[10].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MAX R0.z, R1.w, c[11].x;\n" - "RCP R2.x, R0.z;\n" - "MUL R3.xyz, R1, R2.x;\n" - "MAD R4.xyz, R3, c[11].z, -c[11].w;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[10].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MAD R2.xyz, R0, c[10].w, -R0.w;\n" - "MAD R4.xyz, R3, R4, c[12].x;\n" - "MUL R5.xyz, R1.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[10].z;\n" - "MAD R2.xyz, R2, R3, R0.w;\n" - "MUL R3.xyz, R0, c[10].w;\n" - "MAD R5.xyz, R0.w, R1, R6;\n" - "MAD R4.xyz, R0.w, R1, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R1, c[11].y;\n" - "SGE R4.xyz, R4, R1.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R1, R2, R4;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MUL R2.xyz, R1, R2;\n" - "ADD R2.w, -R1, c[10].z;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R0.x, -R0.w, c[10].z;\n" - "MAD R2.xyz, R1, R0.x, R2;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DIFFERENCE = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[9].x, c[9].y;\n" - "MAD R1.z, R1, R1.y, -c[9];\n" - "MAD R1.z, R1, R1.y, c[9].w;\n" - "MAD R1.z, R1, R1.y, -c[10].x;\n" - "MAD R1.y, R1.z, R1, c[10];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[8].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[8].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.z, R0.x, c[8].x;\n" - "FLR R0.w, R0.z;\n" - "ADD R1.x, R0.z, -R0.w;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "ADD R2.xyz, R1, R0;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R1.xyz, R1, R0.w;\n" - "MIN R1.xyz, R1, R3;\n" - "MAD R2.xyz, -R1, c[10].z, R2;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_EXCLUSION = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..7],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[8].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[9].x, c[9].y;\n" - "MAD R1.z, R1, R1.y, -c[9];\n" - "MAD R1.z, R1, R1.y, c[9].w;\n" - "MAD R1.z, R1, R1.y, -c[10].x;\n" - "MAD R1.y, R1.z, R1, c[10];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[8].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[8].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.z, R0.x, c[8].x;\n" - "FLR R0.w, R0.z;\n" - "ADD R1.x, R0.z, -R0.w;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R2.xyz, R1.w, R0;\n" - "MAD R3.xyz, R1, R0.w, R2;\n" - "MUL R2.xyz, R1, R0;\n" - "MAD R2.xyz, -R2, c[10].z, R3;\n" - "ADD R2.w, -R0, c[10];\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[10].w;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..6],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[7].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[8].x, c[8].y;\n" - "MAD R1.z, R1, R1.y, -c[8];\n" - "MAD R1.z, R1, R1.y, c[8].w;\n" - "MAD R1.z, R1, R1.y, -c[9].x;\n" - "MAD R1.y, R1.z, R1, c[9];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[7].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[7].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R2.xyz, R1, c[4].y;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[7];\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R3.xyz, R0.w, R2;\n" - "MUL R2.xyz, R0, c[4].x;\n" - "MAD R2.xyz, R1.w, R2, R3;\n" - "ADD R2.w, -R1, c[9].z;\n" - "MUL R0.xyz, R0, c[5].y;\n" - "MAD R0.xyz, R2.w, R0, R2;\n" - "ADD R2.x, -R0.w, c[9].z;\n" - "MUL R1.xyz, R1, c[5].z;\n" - "MAD result.color.xyz, R2.x, R1, R0;\n" - "MUL R0.x, R0.w, R1.w;\n" - "MUL R0.z, R1.w, R2.x;\n" - "MUL R0.y, R0.w, R2.w;\n" - "DP3 result.color.w, R0, c[5];\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_MULTIPLY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[6].x, c[6].y;\n" - "MAD R1.z, R1, R1.y, -c[6];\n" - "MAD R1.z, R1, R1.y, c[6].w;\n" - "MAD R1.z, R1, R1.y, -c[7].x;\n" - "MAD R1.y, R1.z, R1, c[7];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[5].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[5].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[5];\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "ADD R2.x, -R1.w, c[7].z;\n" - "MUL R2.xyz, R0, R2.x;\n" - "MAD R0.xyz, R0, R1, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[7].z;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SCREEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[6].x, c[6].y;\n" - "MAD R1.z, R1, R1.y, -c[6];\n" - "MAD R1.z, R1, R1.y, c[6].w;\n" - "MAD R1.z, R1, R1.y, -c[7].x;\n" - "MAD R1.y, R1.z, R1, c[7];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[5].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[5].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[5];\n" - "FLR R0.y, R0.x;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "ADD R2, R0, R1;\n" - "MAD result.color, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_OVERLAY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5];\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[5].y, c[5];\n" - "MAD R1.z, R1, R1.y, -c[5].w;\n" - "MAD R1.z, R1, R1.y, c[6].x;\n" - "MAD R1.z, R1, R1.y, -c[6].y;\n" - "MAD R1.y, R1.z, R1, c[6].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[6].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[7].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[7].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[7];\n" - "MUL R2.xyz, R2, c[7].z;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R3.xyz, R0, R2.w;\n" - "MUL R0.xyz, R0, R1;\n" - "ADD R2.w, -R0, c[7];\n" - "MAD R0.xyz, R0, c[7].z, R3;\n" - "MAD R0.xyz, R1, R2.w, R0;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MUL R1.xyz, R1, c[7].z;\n" - "ADD R2.w, R0, R1;\n" - "ADD R2.xyz, R2, -R0;\n" - "SGE R1.xyz, R1, R1.w;\n" - "MAD result.color.xyz, R1, R2, R0;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DARKEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[6].x, c[6].y;\n" - "MAD R1.z, R1, R1.y, -c[6];\n" - "MAD R1.z, R1, R1.y, c[6].w;\n" - "MAD R1.z, R1, R1.y, -c[7].x;\n" - "MAD R1.y, R1.z, R1, c[7];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[5].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[5].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[5];\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[7].z;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[7].z;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_LIGHTEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[6].x, c[6].y;\n" - "MAD R1.z, R1, R1.y, -c[6];\n" - "MAD R1.z, R1, R1.y, c[6].w;\n" - "MAD R1.z, R1, R1.y, -c[7].x;\n" - "MAD R1.y, R1.z, R1, c[7];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[5].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[5].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[5];\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[7].z;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[7].z;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORDODGE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5];\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[5].y, c[5];\n" - "MAD R1.z, R1, R1.y, -c[5].w;\n" - "MAD R1.z, R1, R1.y, c[6].x;\n" - "MAD R1.z, R1, R1.y, -c[6].y;\n" - "MAD R1.y, R1.z, R1, c[6].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[6].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[7].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[7].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MAX R1.x, R0.w, c[7].w;\n" - "RCP R1.x, R1.x;\n" - "MAD R1.xyz, -R0, R1.x, c[7].z;\n" - "MAX R2.xyz, R1, c[7].w;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R0, c[7].z;\n" - "MUL R3.xyz, R1, R2.w;\n" - "ADD R2.w, -R1, c[7].z;\n" - "MAD R3.xyz, R0, R2.w, R3;\n" - "MUL R1.xyz, R0.w, R1;\n" - "MAD R0.xyz, R0, R1.w, R1;\n" - "MUL R2.w, R0, R1;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R1, R2, R3;\n" - "MAD R3.xyz, R0.w, R1.w, R3;\n" - "ADD R1.x, R0.w, R1.w;\n" - "ADD R3.xyz, R3, -R2;\n" - "SGE R0.xyz, R0, R2.w;\n" - "MAD result.color.xyz, R0, R3, R2;\n" - "MAD result.color.w, -R0, R1, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORBURN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.w, R0.x;\n" - "ABS R0.z, R0.y;\n" - "ADD R0.z, R0, -R0.w;\n" - "ADD R1.x, R0.y, c[5];\n" - "ABS R0.z, R0;\n" - "CMP R0.y, -R0.z, R0, R1.x;\n" - "ABS R0.z, -R0.y;\n" - "MAX R1.x, R0.w, R0.z;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.w, R0.z;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[5].y, c[5];\n" - "MAD R1.z, R1, R1.y, -c[5].w;\n" - "MAD R1.z, R1, R1.y, c[6].x;\n" - "MAD R1.z, R1, R1.y, -c[6].y;\n" - "MAD R1.y, R1.z, R1, c[6].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[6].w;\n" - "ADD R0.z, -R0.w, R0;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[7].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[7].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "ADD R2.w, -R1, c[7].z;\n" - "MAD R2.xyz, -R0.w, R1.w, R3;\n" - "MUL R4.xyz, R0.w, R2;\n" - "MAX R2.xyz, R0, c[7].w;\n" - "MUL R5.xyz, R0, R2.w;\n" - "ADD R3.w, -R0, c[7].z;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R1, R3.w;\n" - "MAD R1.xyz, R1, R3.w, R2;\n" - "MAD R0.xyz, R0, R2.w, R4;\n" - "MUL R2.x, R0.w, R1.w;\n" - "ADD R2.w, R0, R1;\n" - "ADD R1.xyz, R1, -R0;\n" - "SGE R2.xyz, R3, R2.x;\n" - "MAD result.color.xyz, R2, R1, R0;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_HARDLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5];\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[5].y, c[5];\n" - "MAD R1.z, R1, R1.y, -c[5].w;\n" - "MAD R1.z, R1, R1.y, c[6].x;\n" - "MAD R1.z, R1, R1.y, -c[6].y;\n" - "MAD R1.y, R1.z, R1, c[6].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[6].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[7].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[7].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[7];\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[7].z;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MUL R3.xyz, R0, R1;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R2.w, -R0, c[7];\n" - "MUL R0.xyz, R0, c[7].z;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MAD R3.xyz, R3, c[7].z, R4;\n" - "MAD R1.xyz, R1, R2.w, R3;\n" - "ADD R2.w, R0, R1;\n" - "ADD R2.xyz, R2, -R1;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD result.color.xyz, R0, R2, R1;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SOFTLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..4],\n" - " { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n" - " { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n" - " { 3.141593, 0.15915494, 1, 2 },\n" - " { 9.9999997e-006, 4, 16, 12 },\n" - " { 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.w, R0.x;\n" - "ABS R0.z, R0.y;\n" - "ADD R0.z, R0, -R0.w;\n" - "ADD R1.x, R0.y, c[5];\n" - "ABS R0.z, R0;\n" - "CMP R0.y, -R0.z, R0, R1.x;\n" - "ABS R0.z, -R0.y;\n" - "MAX R1.x, R0.w, R0.z;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.w, R0.z;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[5].y, c[5];\n" - "MAD R1.z, R1, R1.y, -c[5].w;\n" - "MAD R1.z, R1, R1.y, c[6].x;\n" - "MAD R1.z, R1, R1.y, -c[6].y;\n" - "MAD R1.y, R1.z, R1, c[6].z;\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[6].w;\n" - "ADD R0.z, -R0.w, R0;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[7].x;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MAX R0.z, R1.w, c[8].x;\n" - "RCP R2.x, R0.z;\n" - "MUL R3.xyz, R1, R2.x;\n" - "MAD R4.xyz, R3, c[8].z, -c[8].w;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[7].y;\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MAD R2.xyz, R0, c[7].w, -R0.w;\n" - "MAD R4.xyz, R3, R4, c[9].x;\n" - "MUL R5.xyz, R1.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[7].z;\n" - "MAD R2.xyz, R2, R3, R0.w;\n" - "MUL R3.xyz, R0, c[7].w;\n" - "MAD R5.xyz, R0.w, R1, R6;\n" - "MAD R4.xyz, R0.w, R1, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R1, c[8].y;\n" - "SGE R4.xyz, R4, R1.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R1, R2, R4;\n" - "MUL R2.xyz, R1, R2;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "ADD R2.w, -R1, c[7].z;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R0.x, R0.w, R1.w;\n" - "ADD R0.y, -R0.w, c[7].z;\n" - "MAD result.color.xyz, R1, R0.y, R2;\n" - "MAD result.color.w, -R0, R1, R0.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DIFFERENCE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[6].x, c[6].y;\n" - "MAD R1.z, R1, R1.y, -c[6];\n" - "MAD R1.z, R1, R1.y, c[6].w;\n" - "MAD R1.z, R1, R1.y, -c[7].x;\n" - "MAD R1.y, R1.z, R1, c[7];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[5].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[5].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[5];\n" - "FLR R0.y, R0.x;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "ADD R0.xyz, R0, R1;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R1.x, R0.w, R1.w;\n" - "MAD result.color.xyz, -R2, c[7].z, R0;\n" - "MAD result.color.w, -R0, R1, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_EXCLUSION_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..4],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559, 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[5].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[6].x, c[6].y;\n" - "MAD R1.z, R1, R1.y, -c[6];\n" - "MAD R1.z, R1, R1.y, c[6].w;\n" - "MAD R1.z, R1, R1.y, -c[7].x;\n" - "MAD R1.y, R1.z, R1, c[7];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[5].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[5].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[5];\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "MUL R2.xyz, R0, R1;\n" - "MAD R2.xyz, -R2, c[7].z, R3;\n" - "ADD R2.w, -R1, c[7];\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[7].w;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODE_BLEND_MODE_MASK = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..6],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[7].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[8].x, c[8].y;\n" - "MAD R1.z, R1, R1.y, -c[8];\n" - "MAD R1.z, R1, R1.y, c[8].w;\n" - "MAD R1.z, R1, R1.y, -c[9].x;\n" - "MAD R1.y, R1.z, R1, c[9];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R1.y, -R1.x, c[7].w;\n" - "ADD R0.z, -R0, R0.w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[7].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R1.x, R0, c[7];\n" - "FLR R1.y, R1.x;\n" - "ADD R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "MUL R0.xy, R0.zwzw, c[4];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, R1, -R1.y;\n" - "DP4 R1.y, R0, c[6];\n" - "TEX R0, R1, texture[1], 1D;\n" - "MUL result.color, R0, R1.y;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODE_BLEND_MODE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..3],\n" - " { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n" - " { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n" - " { 0.33299461, 0.99999559 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "ABS R0.z, R0.x;\n" - "ABS R0.w, R0.y;\n" - "ADD R0.w, R0, -R0.z;\n" - "ADD R1.x, R0.y, c[4].y;\n" - "ABS R0.w, R0;\n" - "CMP R0.y, -R0.w, R0, R1.x;\n" - "ABS R0.w, -R0.y;\n" - "MAX R1.x, R0.z, R0.w;\n" - "RCP R1.y, R1.x;\n" - "MIN R1.x, R0.z, R0.w;\n" - "MUL R1.x, R1, R1.y;\n" - "MUL R1.y, R1.x, R1.x;\n" - "MAD R1.z, R1.y, c[5].x, c[5].y;\n" - "MAD R1.z, R1, R1.y, -c[5];\n" - "MAD R1.z, R1, R1.y, c[5].w;\n" - "MAD R1.z, R1, R1.y, -c[6].x;\n" - "MAD R1.y, R1.z, R1, c[6];\n" - "MUL R1.x, R1.y, R1;\n" - "ADD R0.z, -R0, R0.w;\n" - "ADD R1.y, -R1.x, c[4].w;\n" - "CMP R0.z, -R0, R1.y, R1.x;\n" - "ADD R0.w, -R0.z, c[4].z;\n" - "CMP R0.x, R0, R0.w, R0.z;\n" - "CMP R0.x, -R0.y, -R0, R0;\n" - "ADD R0.x, R0, c[0];\n" - "MUL R0.x, R0, c[4];\n" - "FLR R0.y, R0.x;\n" - "ADD R0.x, R0, -R0.y;\n" - "TEX result.color, R0, texture[0], 1D;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SIMPLE_PORTER_DUFF = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..9],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, c[0].xyxy;\n" - "ADD R1.x, R0.z, R0.w;\n" - "MUL R0.xy, fragment.position, c[7];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.x, R1, c[0].z;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R2.xyz, R0, c[4].y;\n" - "MUL R3.xyz, R1.w, R2;\n" - "MUL R2.xyz, R1, c[4].x;\n" - "MAD R2.xyz, R0.w, R2, R3;\n" - "ADD R3.xy, fragment.position, c[8];\n" - "ADD R2.w, -R0, c[10].x;\n" - "MUL R1.xyz, R1, c[5].y;\n" - "MAD R2.xyz, R2.w, R1, R2;\n" - "MUL R1.xyz, R0, c[5].z;\n" - "ADD R3.z, -R1.w, c[10].x;\n" - "MAD R2.xyz, R3.z, R1, R2;\n" - "MUL R1.y, R1.w, R2.w;\n" - "MUL R1.x, R1.w, R0.w;\n" - "MUL R1.z, R0.w, R3;\n" - "DP3 R2.w, R1, c[5];\n" - "MUL R3.xy, R3, c[6];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[9];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_MULTIPLY = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, c[0].xyxy;\n" - "ADD R1.x, R0.z, R0.w;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.x, R1, c[0].z;\n" - "TEX R1, R1, texture[2], 1D;\n" - "ADD R2.x, -R0.w, c[8];\n" - "MUL R2.xyz, R1, R2.x;\n" - "MAD R1.xyz, R1, R0, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SCREEN = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..7] };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.z, R0.x, c[0];\n" - "ADD R3.xy, fragment.position, c[6];\n" - "TEX R1, R0.z, texture[2], 1D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R2, R1, R0;\n" - "MAD R2, -R1, R0, R2;\n" - "MUL R3.xy, R3, c[4];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_OVERLAY = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[8].y;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[8].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MUL R3.xyz, R0, R1;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, -R0.w, c[8].y;\n" - "MAD R3.xyz, R3, c[8].x, R4;\n" - "MAD R3.xyz, R1, R2.x, R3;\n" - "MAD R0.xyz, R1, R2.x, R0;\n" - "MUL R2.xyz, R1, c[8].x;\n" - "ADD R0.xyz, R0, -R3;\n" - "SGE R2.xyz, R2, R1.w;\n" - "MAD R2.xyz, R2, R0, R3;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_DARKEN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.z, R0.x, R0.y;\n" - "MUL R1.x, R0.z, c[0].z;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_LIGHTEN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.z, R0.x, R0.y;\n" - "MUL R1.x, R0.z, c[0].z;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORDODGE = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MAX R1.x, R0.w, c[8].y;\n" - "RCP R1.x, R1.x;\n" - "MAD R2.xyz, -R0, R1.x, c[8].x;\n" - "MAX R2.xyz, R2, c[8].y;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MUL R3.xyz, R1, R2.w;\n" - "ADD R2.w, -R1, c[8].x;\n" - "MAD R4.xyz, R0, R2.w, R3;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MUL R2.w, R0, R1;\n" - "MAD R0.xyz, R0, R1.w, R3;\n" - "SGE R0.xyz, R0, R2.w;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R3, R2, R4;\n" - "MAD R4.xyz, R0.w, R1.w, R4;\n" - "ADD R4.xyz, R4, -R2;\n" - "MAD R2.xyz, R0, R4, R2;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORBURN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "MAD R2.xyz, -R0.w, R1.w, R3;\n" - "MUL R4.xyz, R0.w, R2;\n" - "MAX R2.xyz, R0, c[8].y;\n" - "ADD R2.w, -R1, c[8].x;\n" - "MUL R5.xyz, R0, R2.w;\n" - "ADD R3.w, -R0, c[8].x;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R1, R3.w;\n" - "MAD R0.xyz, R0, R2.w, R4;\n" - "MUL R2.w, R0, R1;\n" - "MAD R2.xyz, R1, R3.w, R2;\n" - "ADD R2.xyz, R2, -R0;\n" - "SGE R3.xyz, R3, R2.w;\n" - "MAD R2.xyz, R3, R2, R0;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_HARDLIGHT = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[8].y;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[8].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R3.xyz, R0, R1;\n" - "ADD R2.w, -R0, c[8].y;\n" - "MAD R3.xyz, R3, c[8].x, R4;\n" - "MUL R0.xyz, R0, c[8].x;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD R3.xyz, R1, R2.w, R3;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "ADD R2.xyz, R2, -R3;\n" - "MAD R2.xyz, R0, R2, R3;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SOFTLIGHT = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..7],\n" - " { 1, 2, 9.9999997e-006, 4 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MAX R0.z, R1.w, c[8];\n" - "RCP R0.z, R0.z;\n" - "MUL R3.xyz, R1, R0.z;\n" - "MAD R2.xyz, R3, c[9].x, -c[9].y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[2], 1D;\n" - "MAD R4.xyz, R3, R2, c[9].z;\n" - "MAD R2.xyz, R0, c[8].y, -R0.w;\n" - "MUL R5.xyz, R1.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[8].x;\n" - "MAD R2.xyz, R2, R3, R0.w;\n" - "MUL R3.xyz, R0, c[8].y;\n" - "MAD R5.xyz, R0.w, R1, R6;\n" - "MAD R4.xyz, R0.w, R1, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R1, c[8].w;\n" - "SGE R4.xyz, R4, R1.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R1, R2, R4;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MUL R2.xyz, R1, R2;\n" - "ADD R2.w, -R1, c[8].x;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R0.x, -R0.w, c[8];\n" - "MAD R2.xyz, R1, R0.x, R2;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_DIFFERENCE = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.z, R0.x, R0.y;\n" - "MUL R1.x, R0.z, c[0].z;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "ADD R2.xyz, R1, R0;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R1.xyz, R1, R0.w;\n" - "MIN R1.xyz, R1, R3;\n" - "MAD R2.xyz, -R1, c[8].x, R2;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_EXCLUSION = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.z, R0.x, R0.y;\n" - "MUL R1.x, R0.z, c[0].z;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 1D;\n" - "MUL R2.xyz, R1.w, R0;\n" - "MAD R3.xyz, R1, R0.w, R2;\n" - "MUL R2.xyz, R1, R0;\n" - "MAD R2.xyz, -R2, c[8].x, R3;\n" - "ADD R2.w, -R0, c[8].y;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8].y;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..6],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R2.xyz, R1, c[4].y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R3.xyz, R0.w, R2;\n" - "MUL R2.xyz, R0, c[4].x;\n" - "MAD R2.xyz, R1.w, R2, R3;\n" - "ADD R2.w, -R1, c[7].x;\n" - "MUL R0.xyz, R0, c[5].y;\n" - "MAD R0.xyz, R2.w, R0, R2;\n" - "ADD R2.x, -R0.w, c[7];\n" - "MUL R1.xyz, R1, c[5].z;\n" - "MAD result.color.xyz, R2.x, R1, R0;\n" - "MUL R0.x, R0.w, R1.w;\n" - "MUL R0.z, R1.w, R2.x;\n" - "MUL R0.y, R0.w, R2.w;\n" - "DP3 result.color.w, R0, c[5];\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_MULTIPLY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "ADD R2.x, -R1.w, c[5];\n" - "MUL R2.xyz, R0, R2.x;\n" - "MAD R0.xyz, R0, R1, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[5].x;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SCREEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..4] };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "ADD R2, R0, R1;\n" - "MAD result.color, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_OVERLAY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[5].y;\n" - "MUL R2.xyz, R2, c[5].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R3.xyz, R0, R2.w;\n" - "MUL R0.xyz, R0, R1;\n" - "ADD R2.w, -R0, c[5].y;\n" - "MAD R0.xyz, R0, c[5].x, R3;\n" - "MAD R0.xyz, R1, R2.w, R0;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MUL R1.xyz, R1, c[5].x;\n" - "ADD R2.w, R0, R1;\n" - "ADD R2.xyz, R2, -R0;\n" - "SGE R1.xyz, R1, R1.w;\n" - "MAD result.color.xyz, R1, R2, R0;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_DARKEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[5].x;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_LIGHTEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[5].x;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORDODGE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MAX R1.x, R0.w, c[5].y;\n" - "RCP R1.x, R1.x;\n" - "MAD R3.xyz, -R0, R1.x, c[5].x;\n" - "MAX R3.xyz, R3, c[5].y;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.x, -R0.w, c[5];\n" - "MUL R2.xyz, R1, R2.x;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R1.xyz, R0.w, R1;\n" - "MAD R0.xyz, R0, R1.w, R1;\n" - "MUL R2.w, R0, R1;\n" - "RCP R3.x, R3.x;\n" - "RCP R3.y, R3.y;\n" - "RCP R3.z, R3.z;\n" - "MAD R3.xyz, R1, R3, R2;\n" - "MAD R2.xyz, R0.w, R1.w, R2;\n" - "ADD R1.x, R0.w, R1.w;\n" - "ADD R2.xyz, R2, -R3;\n" - "SGE R0.xyz, R0, R2.w;\n" - "MAD result.color.xyz, R0, R2, R3;\n" - "MAD result.color.w, -R0, R1, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORBURN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R2.xyz, -R0.w, R1.w, R3;\n" - "MUL R4.xyz, R0.w, R2;\n" - "MAX R2.xyz, R0, c[5].y;\n" - "MUL R5.xyz, R0, R2.w;\n" - "ADD R3.w, -R0, c[5].x;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R1, R3.w;\n" - "MAD R1.xyz, R1, R3.w, R2;\n" - "MAD R0.xyz, R0, R2.w, R4;\n" - "MUL R2.x, R0.w, R1.w;\n" - "ADD R2.w, R0, R1;\n" - "ADD R1.xyz, R1, -R0;\n" - "SGE R2.xyz, R3, R2.x;\n" - "MAD result.color.xyz, R2, R1, R0;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_HARDLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[5].y;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[5].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MUL R3.xyz, R0, R1;\n" - "MUL R0.xyz, R0, c[5].x;\n" - "ADD R2.w, -R0, c[5].y;\n" - "MAD R3.xyz, R3, c[5].x, R4;\n" - "MAD R3.xyz, R1, R2.w, R3;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R1.xyz, R1, -R3;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD result.color.xyz, R0, R1, R3;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SOFTLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..4],\n" - " { 1, 2, 9.9999997e-006, 4 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MAX R0.z, R1.w, c[5];\n" - "RCP R0.z, R0.z;\n" - "MUL R3.xyz, R1, R0.z;\n" - "MAD R2.xyz, R3, c[6].x, -c[6].y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MAD R4.xyz, R3, R2, c[6].z;\n" - "MAD R2.xyz, R0, c[5].y, -R0.w;\n" - "MUL R5.xyz, R1.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[5].x;\n" - "MAD R2.xyz, R2, R3, R0.w;\n" - "MUL R3.xyz, R0, c[5].y;\n" - "MAD R5.xyz, R0.w, R1, R6;\n" - "MAD R4.xyz, R0.w, R1, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R1, c[5].w;\n" - "SGE R4.xyz, R4, R1.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R1, R2, R4;\n" - "MUL R2.xyz, R1, R2;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R0.x, R0.w, R1.w;\n" - "ADD R0.y, -R0.w, c[5].x;\n" - "MAD result.color.xyz, R1, R0.y, R2;\n" - "MAD result.color.w, -R0, R1, R0.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_DIFFERENCE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "ADD R0.xyz, R0, R1;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R1.x, R0.w, R1.w;\n" - "MAD result.color.xyz, -R2, c[5].x, R0;\n" - "MAD result.color.w, -R0, R1, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_EXCLUSION_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX R0, R0, texture[1], 1D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "MUL R2.xyz, R0, R1;\n" - "MAD R2.xyz, -R2, c[5].x, R3;\n" - "ADD R2.w, -R1, c[5].y;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[5];\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODE_BLEND_MODE_MASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..6] };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.z;\n" - "MUL R0.zw, R0, c[0].xyxy;\n" - "ADD R1.x, R0.z, R0.w;\n" - "ADD R0.xy, fragment.position, c[5];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[0], 2D;\n" - "DP4 R1.y, R0, c[6];\n" - "MUL R1.x, R1, c[0].z;\n" - "TEX R0, R1, texture[1], 1D;\n" - "MUL result.color, R0, R1.y;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODE_BLEND_MODE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[4] = { program.local[0..3] };\n" - "TEMP R0;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "ADD R0.x, R0, R0.y;\n" - "MUL R0.x, R0, c[0].z;\n" - "TEX result.color, R0, texture[0], 1D;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SIMPLE_PORTER_DUFF = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..9],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R1.xyz, R0, c[3];\n" - "RCP R0.z, R1.z;\n" - "MUL R1.xy, R1, R0.z;\n" - "MUL R0.xy, fragment.position, c[7];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[2], 2D;\n" - "MUL R2.xyz, R0, c[4].y;\n" - "MUL R3.xyz, R1.w, R2;\n" - "MUL R2.xyz, R1, c[4].x;\n" - "MAD R2.xyz, R0.w, R2, R3;\n" - "ADD R3.xy, fragment.position, c[8];\n" - "ADD R2.w, -R0, c[10].x;\n" - "MUL R1.xyz, R1, c[5].y;\n" - "MAD R2.xyz, R2.w, R1, R2;\n" - "MUL R1.xyz, R0, c[5].z;\n" - "ADD R3.z, -R1.w, c[10].x;\n" - "MAD R2.xyz, R3.z, R1, R2;\n" - "MUL R1.y, R1.w, R2.w;\n" - "MUL R1.x, R1.w, R0.w;\n" - "MUL R1.z, R0.w, R3;\n" - "DP3 R2.w, R1, c[5];\n" - "MUL R3.xy, R3, c[6];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[9];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_MULTIPLY = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R1.xyz, R0, c[3];\n" - "RCP R0.z, R1.z;\n" - "MUL R1.xy, R1, R0.z;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1, R1, texture[2], 2D;\n" - "ADD R2.x, -R0.w, c[8];\n" - "MUL R2.xyz, R1, R2.x;\n" - "MAD R1.xyz, R1, R0, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SCREEN = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..7] };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, c[0].xyxy;\n" - "ADD R3.xy, fragment.position, c[6];\n" - "TEX R1, R0.zwzw, texture[2], 2D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R2, R1, R0;\n" - "MAD R2, -R1, R0, R2;\n" - "MUL R3.xy, R3, c[4];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_OVERLAY = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[2], 2D;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[8].y;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[8].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MUL R3.xyz, R0, R1;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, -R0.w, c[8].y;\n" - "MAD R3.xyz, R3, c[8].x, R4;\n" - "MAD R3.xyz, R1, R2.x, R3;\n" - "MAD R0.xyz, R1, R2.x, R0;\n" - "MUL R2.xyz, R1, c[8].x;\n" - "ADD R0.xyz, R0, -R3;\n" - "SGE R2.xyz, R2, R1.w;\n" - "MAD R2.xyz, R2, R0, R3;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_DARKEN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.z;\n" - "MUL R1.xy, R0.zwzw, c[0];\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 2D;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_LIGHTEN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.z;\n" - "MUL R1.xy, R0.zwzw, c[0];\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 2D;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_COLORDODGE = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[2], 2D;\n" - "MAX R1.x, R0.w, c[8].y;\n" - "RCP R1.x, R1.x;\n" - "MAD R2.xyz, -R0, R1.x, c[8].x;\n" - "MAX R2.xyz, R2, c[8].y;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MUL R3.xyz, R1, R2.w;\n" - "ADD R2.w, -R1, c[8].x;\n" - "MAD R4.xyz, R0, R2.w, R3;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MUL R2.w, R0, R1;\n" - "MAD R0.xyz, R0, R1.w, R3;\n" - "SGE R0.xyz, R0, R2.w;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R3, R2, R4;\n" - "MAD R4.xyz, R0.w, R1.w, R4;\n" - "ADD R4.xyz, R4, -R2;\n" - "MAD R2.xyz, R0, R4, R2;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_COLORBURN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[2], 2D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "MAD R2.xyz, -R0.w, R1.w, R3;\n" - "MUL R4.xyz, R0.w, R2;\n" - "MAX R2.xyz, R0, c[8].y;\n" - "ADD R2.w, -R1, c[8].x;\n" - "MUL R5.xyz, R0, R2.w;\n" - "ADD R3.w, -R0, c[8].x;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R1, R3.w;\n" - "MAD R0.xyz, R0, R2.w, R4;\n" - "MUL R2.w, R0, R1;\n" - "MAD R2.xyz, R1, R3.w, R2;\n" - "ADD R2.xyz, R2, -R0;\n" - "SGE R3.xyz, R3, R2.w;\n" - "MAD R2.xyz, R3, R2, R0;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_HARDLIGHT = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[2], 2D;\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[8].y;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[8].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R3.xyz, R0, R1;\n" - "ADD R2.w, -R0, c[8].y;\n" - "MAD R3.xyz, R3, c[8].x, R4;\n" - "MUL R0.xyz, R0, c[8].x;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD R3.xyz, R1, R2.w, R3;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "ADD R2.xyz, R2, -R3;\n" - "MAD R2.xyz, R0, R2, R3;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SOFTLIGHT = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..7],\n" - " { 1, 2, 9.9999997e-006, 4 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MUL R1.xy, fragment.position, c[5];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MAX R0.w, R1, c[8].z;\n" - "RCP R0.w, R0.w;\n" - "MUL R3.xyz, R1, R0.w;\n" - "MAD R2.xyz, R3, c[9].x, -c[9].y;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[2], 2D;\n" - "MAD R4.xyz, R3, R2, c[9].z;\n" - "MAD R2.xyz, R0, c[8].y, -R0.w;\n" - "MUL R5.xyz, R1.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[8].x;\n" - "MAD R2.xyz, R2, R3, R0.w;\n" - "MUL R3.xyz, R0, c[8].y;\n" - "MAD R5.xyz, R0.w, R1, R6;\n" - "MAD R4.xyz, R0.w, R1, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R1, c[8].w;\n" - "SGE R4.xyz, R4, R1.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R1, R2, R4;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MUL R2.xyz, R1, R2;\n" - "ADD R2.w, -R1, c[8].x;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R0.x, -R0.w, c[8];\n" - "MAD R2.xyz, R1, R0.x, R2;\n" - "ADD R0.z, R0.w, R1.w;\n" - "MAD R2.w, -R0, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[6];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R2, -R1;\n" - "DP4 R0.x, R0, c[7];\n" - "MAD result.color, R0.x, R2, R1;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_DIFFERENCE = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.z;\n" - "MUL R1.xy, R0.zwzw, c[0];\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 2D;\n" - "ADD R2.xyz, R1, R0;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R1.xyz, R1, R0.w;\n" - "MIN R1.xyz, R1, R3;\n" - "MAD R2.xyz, -R1, c[8].x, R2;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_EXCLUSION = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.z;\n" - "MUL R1.xy, R0.zwzw, c[0];\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "TEX R1, R1, texture[2], 2D;\n" - "MUL R2.xyz, R1.w, R0;\n" - "MAD R3.xyz, R1, R0.w, R2;\n" - "MUL R2.xyz, R1, R0;\n" - "MAD R2.xyz, -R2, c[8].x, R3;\n" - "ADD R2.w, -R0, c[8].y;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8].y;\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..6],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R1.xy, fragment.position, c[6];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MUL R2.xyz, R1, c[4].y;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MUL R3.xyz, R0.w, R2;\n" - "MUL R2.xyz, R0, c[4].x;\n" - "MAD R2.xyz, R1.w, R2, R3;\n" - "ADD R2.w, -R1, c[7].x;\n" - "MUL R0.xyz, R0, c[5].y;\n" - "MAD R0.xyz, R2.w, R0, R2;\n" - "ADD R2.x, -R0.w, c[7];\n" - "MUL R1.xyz, R1, c[5].z;\n" - "MAD result.color.xyz, R2.x, R1, R0;\n" - "MUL R0.x, R0.w, R1.w;\n" - "MUL R0.z, R1.w, R2.x;\n" - "MUL R0.y, R0.w, R2.w;\n" - "DP3 result.color.w, R0, c[5];\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_MULTIPLY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2.x, -R1.w, c[5];\n" - "MUL R2.xyz, R0, R2.x;\n" - "MAD R0.xyz, R0, R1, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[5].x;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SCREEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..4] };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "ADD R2, R0, R1;\n" - "MAD result.color, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_OVERLAY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[5].y;\n" - "MUL R2.xyz, R2, c[5].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R3.xyz, R0, R2.w;\n" - "MUL R0.xyz, R0, R1;\n" - "ADD R2.w, -R0, c[5].y;\n" - "MAD R0.xyz, R0, c[5].x, R3;\n" - "MAD R0.xyz, R1, R2.w, R0;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MUL R1.xyz, R1, c[5].x;\n" - "ADD R2.w, R0, R1;\n" - "ADD R2.xyz, R2, -R0;\n" - "SGE R1.xyz, R1, R1.w;\n" - "MAD result.color.xyz, R1, R2, R0;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_DARKEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[5].x;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_LIGHTEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[5].x;\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_COLORDODGE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MAX R1.x, R0.w, c[5].y;\n" - "RCP R1.x, R1.x;\n" - "MAD R3.xyz, -R0, R1.x, c[5].x;\n" - "MAX R3.xyz, R3, c[5].y;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.x, -R0.w, c[5];\n" - "MUL R2.xyz, R1, R2.x;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R1.xyz, R0.w, R1;\n" - "MAD R0.xyz, R0, R1.w, R1;\n" - "MUL R2.w, R0, R1;\n" - "RCP R3.x, R3.x;\n" - "RCP R3.y, R3.y;\n" - "RCP R3.z, R3.z;\n" - "MAD R3.xyz, R1, R3, R2;\n" - "MAD R2.xyz, R0.w, R1.w, R2;\n" - "ADD R1.x, R0.w, R1.w;\n" - "ADD R2.xyz, R2, -R3;\n" - "SGE R0.xyz, R0, R2.w;\n" - "MAD result.color.xyz, R0, R2, R3;\n" - "MAD result.color.w, -R0, R1, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_COLORBURN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R2.xyz, -R0.w, R1.w, R3;\n" - "MUL R4.xyz, R0.w, R2;\n" - "MAX R2.xyz, R0, c[5].y;\n" - "MUL R5.xyz, R0, R2.w;\n" - "ADD R3.w, -R0, c[5].x;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R1, R3.w;\n" - "MAD R1.xyz, R1, R3.w, R2;\n" - "MAD R0.xyz, R0, R2.w, R4;\n" - "MUL R2.x, R0.w, R1.w;\n" - "ADD R2.w, R0, R1;\n" - "ADD R1.xyz, R1, -R0;\n" - "SGE R2.xyz, R3, R2.x;\n" - "MAD result.color.xyz, R2, R1, R0;\n" - "MAD result.color.w, -R0, R1, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_HARDLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "ADD R2.w, -R1, c[5].y;\n" - "ADD R3.xyz, R0.w, -R0;\n" - "ADD R2.xyz, R1.w, -R1;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[5].x;\n" - "MAD R2.xyz, R0.w, R1.w, -R2;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R4.xyz, R0, R2.w;\n" - "MUL R3.xyz, R0, R1;\n" - "MUL R0.xyz, R0, c[5].x;\n" - "ADD R2.w, -R0, c[5].y;\n" - "MAD R3.xyz, R3, c[5].x, R4;\n" - "MAD R3.xyz, R1, R2.w, R3;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R1.xyz, R1, -R3;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD result.color.xyz, R0, R1, R3;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SOFTLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..4],\n" - " { 1, 2, 9.9999997e-006, 4 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MUL R1.xy, fragment.position, c[4];\n" - "TEX R1, R1, texture[0], 2D;\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MAX R0.w, R1, c[5].z;\n" - "RCP R0.w, R0.w;\n" - "MUL R3.xyz, R1, R0.w;\n" - "MAD R2.xyz, R3, c[6].x, -c[6].y;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MAD R4.xyz, R3, R2, c[6].z;\n" - "MAD R2.xyz, R0, c[5].y, -R0.w;\n" - "MUL R5.xyz, R1.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[5].x;\n" - "MAD R2.xyz, R2, R3, R0.w;\n" - "MUL R3.xyz, R0, c[5].y;\n" - "MAD R5.xyz, R0.w, R1, R6;\n" - "MAD R4.xyz, R0.w, R1, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R1, c[5].w;\n" - "SGE R4.xyz, R4, R1.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R1, R2, R4;\n" - "MUL R2.xyz, R1, R2;\n" - "SGE R3.xyz, R3, R0.w;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R0.x, R0.w, R1.w;\n" - "ADD R0.y, -R0.w, c[5].x;\n" - "MAD result.color.xyz, R1, R0.y, R2;\n" - "MAD result.color.w, -R0, R1, R0.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_DIFFERENCE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MUL R2.xyz, R0, R1.w;\n" - "MUL R3.xyz, R0.w, R1;\n" - "ADD R0.xyz, R0, R1;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R1.x, R0.w, R1.w;\n" - "MAD result.color.xyz, -R2, c[5].x, R0;\n" - "MAD result.color.w, -R0, R1, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_EXCLUSION_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 2, 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R1, R0.zwzw, texture[0], 2D;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0, R0, texture[1], 2D;\n" - "MUL R2.xyz, R0.w, R1;\n" - "MAD R3.xyz, R0, R1.w, R2;\n" - "MUL R2.xyz, R0, R1;\n" - "MAD R2.xyz, -R2, c[5].x, R3;\n" - "ADD R2.w, -R1, c[5].y;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R0.w, R1.w;\n" - "ADD R2.y, -R0.w, c[5];\n" - "MAD result.color.xyz, R1, R2.y, R0;\n" - "MAD result.color.w, -R0, R1, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODE_BLEND_MODE_MASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..6] };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R1.xyz, R0, c[3];\n" - "RCP R0.z, R1.z;\n" - "MUL R1.xy, R1, R0.z;\n" - "ADD R0.xy, fragment.position, c[5];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[0], 2D;\n" - "DP4 R1.z, R0, c[6];\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R0, R1, texture[1], 2D;\n" - "MUL result.color, R0, R1.z;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODE_BLEND_MODE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[4] = { program.local[0..3] };\n" - "TEMP R0;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX result.color, R0, texture[0], 2D;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SIMPLE_PORTER_DUFF = - "!!ARBfp1.0\n" - "PARAM c[11] = { program.local[0..9],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, c[0].xyxy;\n" - "TEX R1.x, R0.zwzw, texture[2], 2D;\n" - "MUL R0.xy, fragment.position, c[7];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -R1, c[10];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R2.xyz, R0, c[4].y;\n" - "MUL R3.xyz, R1.w, R2;\n" - "MUL R2.xyz, R1, c[4].x;\n" - "MAD R2.xyz, R0.w, R2, R3;\n" - "ADD R3.xy, fragment.position, c[8];\n" - "ADD R2.w, -R0, c[10].x;\n" - "MUL R1.xyz, R1, c[5].y;\n" - "MAD R2.xyz, R2.w, R1, R2;\n" - "MUL R1.xyz, R0, c[5].z;\n" - "ADD R3.z, -R1.w, c[10].x;\n" - "MAD R2.xyz, R3.z, R1, R2;\n" - "MUL R1.y, R1.w, R2.w;\n" - "MUL R1.x, R1.w, R0.w;\n" - "MUL R1.z, R0.w, R3;\n" - "DP3 R2.w, R1, c[5];\n" - "MUL R3.xy, R3, c[6];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[9];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_MULTIPLY = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.zw, R0.xyxy, c[0].xyxy;\n" - "TEX R1.x, R0.zwzw, texture[2], 2D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -R1, c[8];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "ADD R2.x, -R0.w, c[8];\n" - "MUL R2.xyz, R1, R2.x;\n" - "MAD R1.xyz, R1, R0, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SCREEN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[2], 2D;\n" - "ADD R0.z, -R0.x, c[8].x;\n" - "ADD R3.xy, fragment.position, c[6];\n" - "MUL R1, fragment.color.primary, R0.z;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R2, R1, R0;\n" - "MAD R2, -R1, R0, R2;\n" - "MUL R3.xy, R3, c[4];\n" - "TEX R1, R3, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_OVERLAY = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[2], 2D;\n" - "ADD R0.x, -R0, c[8];\n" - "MUL R1, fragment.color.primary, R0.x;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "ADD R2.w, -R0, c[8].x;\n" - "ADD R3.xyz, R1.w, -R1;\n" - "ADD R2.xyz, R0.w, -R0;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[8].y;\n" - "MAD R2.xyz, R1.w, R0.w, -R2;\n" - "MUL R4.xyz, R1, R2.w;\n" - "MUL R3.xyz, R1, R0;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R3.xyz, R3, c[8].y, R4;\n" - "MAD R3.xyz, R0, R2.x, R3;\n" - "MAD R1.xyz, R0, R2.x, R1;\n" - "MUL R2.xyz, R0, c[8].y;\n" - "ADD R1.xyz, R1, -R3;\n" - "SGE R2.xyz, R2, R0.w;\n" - "MAD R2.xyz, R2, R1, R3;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DARKEN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R1.x, R0, texture[2], 2D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -R1, c[8];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_LIGHTEN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R1.x, R0, texture[2], 2D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -R1, c[8];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORDODGE = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[2], 2D;\n" - "ADD R0.x, -R0, c[8];\n" - "MUL R1, fragment.color.primary, R0.x;\n" - "MAX R0.x, R1.w, c[8].y;\n" - "RCP R0.x, R0.x;\n" - "MAD R2.xyz, -R1, R0.x, c[8].x;\n" - "MAX R2.xyz, R2, c[8].y;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R2.w, -R1, c[8].x;\n" - "MUL R3.xyz, R0, R2.w;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R4.xyz, R1, R2.w, R3;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.w, R1, R0;\n" - "MAD R1.xyz, R1, R0.w, R3;\n" - "SGE R1.xyz, R1, R2.w;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R3, R2, R4;\n" - "MAD R4.xyz, R1.w, R0.w, R4;\n" - "ADD R4.xyz, R4, -R2;\n" - "MAD R2.xyz, R1, R4, R2;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORBURN = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[2], 2D;\n" - "ADD R1.x, -R0, c[8];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R2.xyz, R1.w, R0;\n" - "MAD R3.xyz, R1, R0.w, R2;\n" - "MAD R2.xyz, -R1.w, R0.w, R3;\n" - "MUL R4.xyz, R1.w, R2;\n" - "MAX R2.xyz, R1, c[8].y;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MUL R5.xyz, R1, R2.w;\n" - "ADD R3.w, -R1, c[8].x;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R0, R3.w;\n" - "MAD R1.xyz, R1, R2.w, R4;\n" - "MUL R2.w, R1, R0;\n" - "MAD R2.xyz, R0, R3.w, R2;\n" - "ADD R2.xyz, R2, -R1;\n" - "SGE R3.xyz, R3, R2.w;\n" - "MAD R2.xyz, R3, R2, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_HARDLIGHT = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[2], 2D;\n" - "ADD R0.x, -R0, c[8];\n" - "MUL R1, fragment.color.primary, R0.x;\n" - "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "ADD R2.w, -R0, c[8].x;\n" - "ADD R3.xyz, R1.w, -R1;\n" - "ADD R2.xyz, R0.w, -R0;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[8].y;\n" - "MAD R2.xyz, R1.w, R0.w, -R2;\n" - "MUL R4.xyz, R1, R2.w;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MUL R3.xyz, R1, R0;\n" - "ADD R2.w, -R1, c[8].x;\n" - "MAD R3.xyz, R3, c[8].y, R4;\n" - "MUL R1.xyz, R1, c[8].y;\n" - "SGE R1.xyz, R1, R1.w;\n" - "MAD R3.xyz, R0, R2.w, R3;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "ADD R2.xyz, R2, -R3;\n" - "MAD R2.xyz, R1, R2, R3;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SOFTLIGHT = - "!!ARBfp1.0\n" - "PARAM c[10] = { program.local[0..7],\n" - " { 1, 2, 9.9999997e-006, 4 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R1.xyz, R0, c[3];\n" - "RCP R1.z, R1.z;\n" - "MUL R1.xy, R1, R1.z;\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1.x, R1, texture[2], 2D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MAX R1.z, R0.w, c[8];\n" - "RCP R1.z, R1.z;\n" - "MUL R3.xyz, R0, R1.z;\n" - "MAD R2.xyz, R3, c[9].x, -c[9].y;\n" - "ADD R1.x, -R1, c[8];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MAD R4.xyz, R3, R2, c[9].z;\n" - "MAD R2.xyz, R1, c[8].y, -R1.w;\n" - "MUL R5.xyz, R0.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[8].x;\n" - "MAD R2.xyz, R2, R3, R1.w;\n" - "MUL R3.xyz, R1, c[8].y;\n" - "MAD R5.xyz, R1.w, R0, R6;\n" - "MAD R4.xyz, R1.w, R0, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R0, c[8].w;\n" - "SGE R4.xyz, R4, R0.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R0, R2, R4;\n" - "SGE R3.xyz, R3, R1.w;\n" - "MUL R2.xyz, R0, R2;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "ADD R1.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R1.x, R2;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DIFFERENCE = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R1.x, R0, texture[2], 2D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "ADD R1.x, -R1, c[8];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "ADD R2.xyz, R1, R0;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R1.xyz, R1, R0.w;\n" - "MIN R1.xyz, R1, R3;\n" - "MAD R2.xyz, -R1, c[8].y, R2;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_EXCLUSION = - "!!ARBfp1.0\n" - "PARAM c[9] = { program.local[0..7],\n" - " { 1, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R1.x, R0, texture[2], 2D;\n" - "MUL R0.xy, fragment.position, c[5];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R1.x, -R1, c[8];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R2.xyz, R1.w, R0;\n" - "MAD R3.xyz, R1, R0.w, R2;\n" - "MUL R2.xyz, R1, R0;\n" - "MAD R2.xyz, -R2, c[8].y, R3;\n" - "ADD R2.w, -R0, c[8].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, -R1.w, c[8];\n" - "MAD R2.xyz, R0, R2.x, R1;\n" - "ADD R1.z, R1.w, R0.w;\n" - "MAD R2.w, -R1, R0, R1.z;\n" - "ADD R1.xy, fragment.position, c[6];\n" - "MUL R1.xy, R1, c[4];\n" - "TEX R1, R1, texture[1], 2D;\n" - "ADD R2, R2, -R0;\n" - "DP4 R1.x, R1, c[7];\n" - "MAD result.color, R1.x, R2, R0;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..6],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R1.x, R0, texture[1], 2D;\n" - "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R2.xyz, R0, c[4].y;\n" - "ADD R1.x, -R1, c[7];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R3.xyz, R1.w, R2;\n" - "MUL R2.xyz, R1, c[4].x;\n" - "MUL R0.xyz, R0, c[5].z;\n" - "MAD R2.xyz, R0.w, R2, R3;\n" - "ADD R2.w, -R0, c[7].x;\n" - "MUL R1.xyz, R1, c[5].y;\n" - "MAD R1.xyz, R2.w, R1, R2;\n" - "ADD R2.x, -R1.w, c[7];\n" - "MAD result.color.xyz, R2.x, R0, R1;\n" - "MUL R0.x, R1.w, R0.w;\n" - "MUL R0.z, R0.w, R2.x;\n" - "MUL R0.y, R1.w, R2.w;\n" - "DP3 result.color.w, R0, c[5];\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_MULTIPLY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R1.x, R0, texture[1], 2D;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "ADD R1.x, -R1, c[5];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "ADD R2.x, -R0.w, c[5];\n" - "MUL R2.xyz, R1, R2.x;\n" - "MAD R1.xyz, R1, R0, R2;\n" - "ADD R2.x, R1.w, R0.w;\n" - "ADD R2.y, -R1.w, c[5].x;\n" - "MAD result.color.xyz, R0, R2.y, R1;\n" - "MAD result.color.w, -R1, R0, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SCREEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R1.x, -R0, c[5];\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "ADD R2, R1, R0;\n" - "MAD result.color, -R1, R0, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_OVERLAY_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R0.x, -R0, c[5];\n" - "MUL R1, fragment.color.primary, R0.x;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "ADD R3.xyz, R1.w, -R1;\n" - "ADD R2.xyz, R0.w, -R0;\n" - "MUL R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[5].x;\n" - "MUL R2.xyz, R2, c[5].y;\n" - "MAD R2.xyz, R1.w, R0.w, -R2;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MUL R3.xyz, R1, R2.w;\n" - "MUL R1.xyz, R1, R0;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R1.xyz, R1, c[5].y, R3;\n" - "MAD R1.xyz, R0, R2.w, R1;\n" - "MAD R2.xyz, R0, R2.w, R2;\n" - "MUL R0.xyz, R0, c[5].y;\n" - "ADD R2.w, R1, R0;\n" - "ADD R2.xyz, R2, -R1;\n" - "SGE R0.xyz, R0, R0.w;\n" - "MAD result.color.xyz, R0, R2, R1;\n" - "MAD result.color.w, -R1, R0, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DARKEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R1.x, -R0, c[5];\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[5].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, R1.w, R0.w;\n" - "ADD R2.y, -R1.w, c[5].x;\n" - "MAD result.color.xyz, R0, R2.y, R1;\n" - "MAD result.color.w, -R1, R0, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_LIGHTEN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R1.x, -R0, c[5];\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R2.xyz, R1, R0.w;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MAX R2.xyz, R2, R3;\n" - "ADD R2.w, -R0, c[5].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, R1.w, R0.w;\n" - "ADD R2.y, -R1.w, c[5].x;\n" - "MAD result.color.xyz, R0, R2.y, R1;\n" - "MAD result.color.w, -R1, R0, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORDODGE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 1e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R0.x, -R0, c[5];\n" - "MUL R1, fragment.color.primary, R0.x;\n" - "MAX R0.x, R1.w, c[5].y;\n" - "RCP R0.x, R0.x;\n" - "MAD R3.xyz, -R1, R0.x, c[5].x;\n" - "MAX R3.xyz, R3, c[5].y;\n" - "MUL R0.xy, fragment.position, c[4];\n" - "TEX R0, R0, texture[0], 2D;\n" - "ADD R2.x, -R1.w, c[5];\n" - "MUL R2.xyz, R0, R2.x;\n" - "ADD R2.w, -R0, c[5].x;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MUL R0.xyz, R1.w, R0;\n" - "RCP R3.x, R3.x;\n" - "RCP R3.y, R3.y;\n" - "RCP R3.z, R3.z;\n" - "MAD R3.xyz, R0, R3, R2;\n" - "MAD R0.xyz, R1, R0.w, R0;\n" - "MAD R2.xyz, R1.w, R0.w, R2;\n" - "MUL R2.w, R1, R0;\n" - "ADD R1.x, R1.w, R0.w;\n" - "ADD R2.xyz, R2, -R3;\n" - "SGE R0.xyz, R0, R2.w;\n" - "MAD result.color.xyz, R0, R2, R3;\n" - "MAD result.color.w, -R1, R0, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORBURN_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 9.9999997e-006 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R1.x, -R0, c[5];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R2.xyz, R1.w, R0;\n" - "MAD R3.xyz, R1, R0.w, R2;\n" - "ADD R2.w, -R0, c[5].x;\n" - "MAD R2.xyz, -R1.w, R0.w, R3;\n" - "MUL R4.xyz, R1.w, R2;\n" - "MAX R2.xyz, R1, c[5].y;\n" - "MUL R5.xyz, R1, R2.w;\n" - "ADD R3.w, -R1, c[5].x;\n" - "RCP R2.x, R2.x;\n" - "RCP R2.y, R2.y;\n" - "RCP R2.z, R2.z;\n" - "MAD R2.xyz, R4, R2, R5;\n" - "MUL R4.xyz, R0, R3.w;\n" - "MAD R0.xyz, R0, R3.w, R2;\n" - "MAD R1.xyz, R1, R2.w, R4;\n" - "MUL R2.x, R1.w, R0.w;\n" - "ADD R2.w, R1, R0;\n" - "ADD R0.xyz, R0, -R1;\n" - "SGE R2.xyz, R3, R2.x;\n" - "MAD result.color.xyz, R2, R0, R1;\n" - "MAD result.color.w, -R1, R0, R2;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_HARDLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R0.x, -R0, c[5];\n" - "MUL R1, fragment.color.primary, R0.x;\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "ADD R2.w, -R0, c[5].x;\n" - "ADD R3.xyz, R1.w, -R1;\n" - "ADD R2.xyz, R0.w, -R0;\n" - "MUL R2.xyz, R2, R3;\n" - "MUL R2.xyz, R2, c[5].y;\n" - "MAD R2.xyz, R1.w, R0.w, -R2;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "MUL R4.xyz, R1, R2.w;\n" - "MUL R3.xyz, R1, R0;\n" - "MUL R1.xyz, R1, c[5].y;\n" - "ADD R2.w, -R1, c[5].x;\n" - "MAD R3.xyz, R3, c[5].y, R4;\n" - "MAD R3.xyz, R0, R2.w, R3;\n" - "MAD R0.xyz, R0, R2.w, R2;\n" - "ADD R2.x, R1.w, R0.w;\n" - "ADD R0.xyz, R0, -R3;\n" - "SGE R1.xyz, R1, R1.w;\n" - "MAD result.color.xyz, R1, R0, R3;\n" - "MAD result.color.w, -R1, R0, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SOFTLIGHT_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[7] = { program.local[0..4],\n" - " { 1, 2, 9.9999997e-006, 4 },\n" - " { 16, 12, 3 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "TEMP R4;\n" - "TEMP R5;\n" - "TEMP R6;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R1.xyz, R0, c[3];\n" - "RCP R1.z, R1.z;\n" - "MUL R1.xy, R1, R1.z;\n" - "MUL R1.xy, R1, c[0];\n" - "TEX R1.x, R1, texture[1], 2D;\n" - "MUL R0.xy, fragment.position, c[4];\n" - "TEX R0, R0, texture[0], 2D;\n" - "MAX R1.z, R0.w, c[5];\n" - "RCP R1.z, R1.z;\n" - "MUL R3.xyz, R0, R1.z;\n" - "MAD R2.xyz, R3, c[6].x, -c[6].y;\n" - "ADD R1.x, -R1, c[5];\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MAD R4.xyz, R3, R2, c[6].z;\n" - "MAD R2.xyz, R1, c[5].y, -R1.w;\n" - "MUL R5.xyz, R0.w, R2;\n" - "MUL R6.xyz, R5, R4;\n" - "RSQ R2.w, R3.x;\n" - "RCP R4.x, R2.w;\n" - "RSQ R2.w, R3.y;\n" - "RSQ R3.w, R3.z;\n" - "RCP R4.y, R2.w;\n" - "RCP R4.z, R3.w;\n" - "ADD R4.xyz, -R3, R4;\n" - "MUL R6.xyz, R3, R6;\n" - "MUL R4.xyz, R5, R4;\n" - "ADD R3.xyz, -R3, c[5].x;\n" - "MAD R2.xyz, R2, R3, R1.w;\n" - "MUL R3.xyz, R1, c[5].y;\n" - "MAD R5.xyz, R1.w, R0, R6;\n" - "MAD R4.xyz, R1.w, R0, R4;\n" - "ADD R6.xyz, R4, -R5;\n" - "MUL R4.xyz, R0, c[5].w;\n" - "SGE R4.xyz, R4, R0.w;\n" - "MAD R4.xyz, R4, R6, R5;\n" - "MAD R4.xyz, -R0, R2, R4;\n" - "MUL R2.xyz, R0, R2;\n" - "SGE R3.xyz, R3, R1.w;\n" - "MAD R2.xyz, R3, R4, R2;\n" - "ADD R2.w, -R0, c[5].x;\n" - "MAD R2.xyz, R1, R2.w, R2;\n" - "ADD R1.x, R1.w, R0.w;\n" - "ADD R1.y, -R1.w, c[5].x;\n" - "MAD result.color.xyz, R0, R1.y, R2;\n" - "MAD result.color.w, -R1, R0, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DIFFERENCE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R1.x, -R0, c[5];\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R3.xyz, R1.w, R0;\n" - "MUL R2.xyz, R1, R0.w;\n" - "ADD R0.xyz, R1, R0;\n" - "MIN R2.xyz, R2, R3;\n" - "ADD R1.x, R1.w, R0.w;\n" - "MAD result.color.xyz, -R2, c[5].y, R0;\n" - "MAD result.color.w, -R1, R0, R1.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_EXCLUSION_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[6] = { program.local[0..4],\n" - " { 1, 2 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "TEMP R2;\n" - "TEMP R3;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[1], 2D;\n" - "ADD R1.x, -R0, c[5];\n" - "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n" - "TEX R0, R0.zwzw, texture[0], 2D;\n" - "MUL R1, fragment.color.primary, R1.x;\n" - "MUL R2.xyz, R1.w, R0;\n" - "MAD R3.xyz, R1, R0.w, R2;\n" - "MUL R2.xyz, R1, R0;\n" - "MAD R2.xyz, -R2, c[5].y, R3;\n" - "ADD R2.w, -R0, c[5].x;\n" - "MAD R1.xyz, R1, R2.w, R2;\n" - "ADD R2.x, R1.w, R0.w;\n" - "ADD R2.y, -R1.w, c[5].x;\n" - "MAD result.color.xyz, R0, R2.y, R1;\n" - "MAD result.color.w, -R1, R0, R2.x;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODE_BLEND_MODE_MASK = - "!!ARBfp1.0\n" - "PARAM c[8] = { program.local[0..6],\n" - " { 1 } };\n" - "TEMP R0;\n" - "TEMP R1;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.zw, R0.xyxy, R0.z;\n" - "MUL R0.zw, R0, c[0].xyxy;\n" - "TEX R1.x, R0.zwzw, texture[1], 2D;\n" - "ADD R0.xy, fragment.position, c[5];\n" - "MUL R0.xy, R0, c[4];\n" - "TEX R0, R0, texture[0], 2D;\n" - "DP4 R1.y, R0, c[6];\n" - "ADD R1.x, -R1, c[7];\n" - "MUL R0, fragment.color.primary, R1.x;\n" - "MUL result.color, R0, R1.y;\n" - "END\n" - ; - -static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODE_BLEND_MODE_NOMASK = - "!!ARBfp1.0\n" - "PARAM c[5] = { program.local[0..3],\n" - " { 1 } };\n" - "TEMP R0;\n" - "MUL R0.xyz, fragment.position.y, c[2];\n" - "MAD R0.xyz, fragment.position.x, c[1], R0;\n" - "ADD R0.xyz, R0, c[3];\n" - "RCP R0.z, R0.z;\n" - "MUL R0.xy, R0, R0.z;\n" - "MUL R0.xy, R0, c[0];\n" - "TEX R0.x, R0, texture[0], 2D;\n" - "ADD R0.x, -R0, c[4];\n" - "MUL result.color, fragment.color.primary, R0.x;\n" - "END\n" - ; - -static const char *mask_fragment_program_sources[num_fragment_masks] = { - FragmentProgram_FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, - FragmentProgram_FRAGMENT_PROGRAM_MASK_ELLIPSE_AA, -}; - -static const char *painter_fragment_program_sources[num_fragment_brushes][num_fragment_composition_modes] = { - { - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SIMPLE_PORTER_DUFF, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_MULTIPLY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SCREEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_OVERLAY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DARKEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_LIGHTEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_COLORDODGE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_COLORBURN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_HARDLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SOFTLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DIFFERENCE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_EXCLUSION, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_MULTIPLY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SCREEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_OVERLAY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DARKEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_LIGHTEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_COLORDODGE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_COLORBURN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_HARDLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SOFTLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DIFFERENCE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_EXCLUSION_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODE_BLEND_MODE_MASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODE_BLEND_MODE_NOMASK, - }, - { - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_MULTIPLY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SCREEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_OVERLAY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DARKEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_LIGHTEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORDODGE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORBURN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_HARDLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SOFTLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DIFFERENCE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_EXCLUSION, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_MULTIPLY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SCREEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_OVERLAY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DARKEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_LIGHTEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORDODGE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORBURN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_HARDLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SOFTLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DIFFERENCE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_EXCLUSION_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODE_BLEND_MODE_MASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODE_BLEND_MODE_NOMASK, - }, - { - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_MULTIPLY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SCREEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_OVERLAY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DARKEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_LIGHTEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORDODGE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORBURN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_HARDLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SOFTLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DIFFERENCE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_EXCLUSION, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_MULTIPLY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SCREEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_OVERLAY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DARKEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_LIGHTEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORDODGE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORBURN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_HARDLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SOFTLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DIFFERENCE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_EXCLUSION_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODE_BLEND_MODE_MASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODE_BLEND_MODE_NOMASK, - }, - { - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SIMPLE_PORTER_DUFF, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_MULTIPLY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SCREEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_OVERLAY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_DARKEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_LIGHTEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORDODGE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORBURN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_HARDLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SOFTLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_DIFFERENCE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_EXCLUSION, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_MULTIPLY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SCREEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_OVERLAY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_DARKEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_LIGHTEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORDODGE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORBURN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_HARDLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SOFTLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_DIFFERENCE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_EXCLUSION_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODE_BLEND_MODE_MASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODE_BLEND_MODE_NOMASK, - }, - { - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SIMPLE_PORTER_DUFF, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_MULTIPLY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SCREEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_OVERLAY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_DARKEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_LIGHTEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_COLORDODGE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_COLORBURN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_HARDLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SOFTLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_DIFFERENCE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_EXCLUSION, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_MULTIPLY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SCREEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_OVERLAY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_DARKEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_LIGHTEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_COLORDODGE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_COLORBURN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_HARDLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SOFTLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_DIFFERENCE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_EXCLUSION_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODE_BLEND_MODE_MASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODE_BLEND_MODE_NOMASK, - }, - { - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SIMPLE_PORTER_DUFF, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_MULTIPLY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SCREEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_OVERLAY, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DARKEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_LIGHTEN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORDODGE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORBURN, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_HARDLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SOFTLIGHT, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DIFFERENCE, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_EXCLUSION, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_MULTIPLY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SCREEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_OVERLAY_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DARKEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_LIGHTEN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORDODGE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORBURN_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_HARDLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SOFTLIGHT_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DIFFERENCE_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_EXCLUSION_NOMASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODE_BLEND_MODE_MASK, - FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODE_BLEND_MODE_NOMASK, - }, -}; - -static int painter_variable_locations[num_fragment_brushes][num_fragment_composition_modes][num_fragment_variables] = { - { - { -1, -1, -1, 2, -1, 0, 5, -1, 1, 3, 1, 0, -1, 4, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, 0, -1, -1, 1, 2, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, 0, -1, -1, 2, -1, -1, -1, 0, -1, -1, 1, -1, -1, -1, -1, -1, }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - }, - { - { -1, -1, 3, 7, 4, 5, 10, -1, 6, 8, 1, 0, 2, 9, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, 5, -1, -1, 6, 7, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, }, - { -1, -1, 3, 5, 4, -1, 7, -1, -1, -1, 0, -1, 1, 6, -1, 1, 0, 2, -1, }, - { -1, -1, 3, -1, 4, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, 0, 2, -1, }, - }, - { - { -1, -1, 2, 6, 3, 4, 9, -1, 5, 7, 1, 0, 2, 8, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, 4, -1, -1, 5, 6, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, }, - { -1, -1, 2, 4, 3, -1, 6, -1, -1, -1, 0, -1, 1, 5, -1, -1, -1, 1, 0, }, - { -1, -1, 2, -1, 3, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 1, 0, }, - }, - { - { -1, 0, 2, 6, 3, 4, 9, -1, 5, 7, 1, 0, 2, 8, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, 4, -1, -1, 5, 6, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, }, - { -1, 0, 2, 4, 3, -1, 6, -1, -1, -1, 0, -1, 1, 5, -1, -1, -1, 1, -1, }, - { -1, 0, 2, -1, 3, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 1, -1, }, - }, - { - { 2, -1, 2, 6, 3, 4, 9, -1, 5, 7, 1, 0, -1, 8, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, 4, -1, -1, 5, 6, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, 4, 3, -1, 6, -1, -1, -1, 0, -1, -1, 5, 0, -1, -1, 1, -1, }, - { 0, -1, 2, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, }, - }, - { - { 2, -1, 2, 6, 3, 4, 9, -1, 5, 7, 1, 0, -1, 8, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, 4, -1, -1, 5, 6, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, }, - { 1, -1, 2, 4, 3, -1, 6, -1, -1, -1, 0, -1, -1, 5, 0, -1, -1, 1, -1, }, - { 0, -1, 2, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, }, - }, -}; - -static int mask_variable_locations[num_fragment_masks][num_fragment_variables] = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { -1, -1, 1, -1, 2, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, }, -}; - -#endif diff --git a/src/opengl/util/generator.cpp b/src/opengl/util/generator.cpp deleted file mode 100644 index 3d12446842..0000000000 --- a/src/opengl/util/generator.cpp +++ /dev/null @@ -1,500 +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 <QFile> -#include <QList> -#include <QMap> -#include <QPair> -#include <QSet> -#include <QString> -#include <QTextStream> - -#include <QtDebug> -#include <cstdlib> - -QT_BEGIN_NAMESPACE - -QT_USE_NAMESPACE - -#define TAB " " - -typedef QPair<QString, QString> QStringPair; - -QString readSourceFile(const QString &sourceFile, bool fragmentProgram = false) -{ - QFile file(sourceFile); - - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qDebug() << "Missing source file" << sourceFile; - exit(0); - } - - QString source; - - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine(); - - if (fragmentProgram && line[0] == '#' && !line.startsWith("#var")) - continue; - - if (fragmentProgram) - source.append(" \""); - - source.append(line); - - if (fragmentProgram) - source.append("\\n\""); - - source.append('\n'); - } - - if (fragmentProgram) - source.append(" ;\n"); - - return source; -} - -QList<QStringPair> readConf(const QString &confFile) -{ - QFile file(confFile); - - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qDebug() << "Missing file" << confFile; - exit(0); - } - - QList<QStringPair> result; - - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine(); - - if (line.startsWith('#')) - continue; - - QTextStream lineStream(&line); - - QString enumerator; - QString sourceFile; - - lineStream >> enumerator; - - if (lineStream.atEnd()) { - qDebug() << "Error in file" << confFile << '(' << enumerator << ')'; - exit(0); - } - - lineStream >> sourceFile; - - result << QStringPair(enumerator, readSourceFile(sourceFile)); - } - - return result; -} - -QString compileSource(const QString &source) -{ - { - QFile tempSourceFile("__tmp__.glsl"); - if (!tempSourceFile.open(QIODevice::WriteOnly | QIODevice::Text)) { - qDebug() << "Failed opening __tmp__.glsl"; - exit(0); - } - - QTextStream out(&tempSourceFile); - out << source; - } - - if (std::system("cgc -quiet -oglsl -profile arbfp1 __tmp__.glsl >__tmp__.frag") == -1) { - qDebug() << "Failed running cgc"; - exit(0); - } - - return readSourceFile("__tmp__.frag", true); -} - -QString getWord(QString line, int word) -{ - QTextStream in(&line); - - QString result; - - for (int i = 0; i < word; ++i) - in >> result; - - return result; -} - -static int toInt(const QByteArray &str) -{ - int value = 0; - - for (int i = 0; i < str.size(); ++i) { - if (str[i] < '0' || str[i] > '9') - break; - - value *= 10; - value += (str[i] - '0'); - } - - return value; -} -QList<int> getLocations(const QSet<QString> &variables, QString source) -{ - QTextStream in(&source); - - QMap<QString, int> locations; - - foreach (QString variable, variables) - locations[variable] = -1; - - while (!in.atEnd()) { - QString line = in.readLine().trimmed(); - - line = line.right(line.size() - 1); - - if (line.startsWith("#var")) { - QByteArray temp; - QByteArray name; - - QTextStream lineStream(&line); - - lineStream >> temp >> temp >> name; - - int location = -1; - - while (!lineStream.atEnd()) { - lineStream >> temp; - - if (temp.startsWith("c[")) { - location = toInt(temp.right(temp.size() - 2)); - break; - } - - if (temp == "texunit") { - lineStream >> temp; - location = toInt(temp); - break; - } - } - - locations[name] = location; - } - } - - QList<int> result; - - foreach (QString variable, variables) - result << locations[variable]; - - return result; -} - -// remove #var statements -QString trimmed(QString source) -{ - QTextStream in(&source); - - QString result; - - while (!in.atEnd()) { - QString line = in.readLine(); - if (!line.trimmed().startsWith("\"#")) - result += line + '\n'; - } - - return result; -} - -void writeVariablesEnum(QTextStream &out, const char *name, const QSet<QString> &s) -{ - out << "enum " << name << " {"; - QSet<QString>::const_iterator it = s.begin(); - if (it != s.end()) { - out << "\n" TAB "VAR_" << it->toUpper(); - for (++it; it != s.end(); ++it) - out << ",\n" TAB "VAR_" << it->toUpper(); - } - out << "\n};\n\n"; -} - -void writeTypesEnum(QTextStream &out, const char *name, const QList<QStringPair> &s) -{ - out << "enum " << name << " {"; - QList<QStringPair>::const_iterator it = s.begin(); - if (it != s.end()) { - out << "\n" TAB << it->first; - for (++it; it != s.end(); ++it) - out << ",\n" TAB << it->first; - } - out << "\n};\n\n"; -} - -void writeIncludeFile(const QSet<QString> &variables, - const QList<QStringPair> &brushes, - const QList<QStringPair> &compositionModes, - const QList<QStringPair> &masks, - const QMap<QString, QMap<QString, QString> > &compiled) -{ - QFile includeFile("fragmentprograms_p.h"); - if (!includeFile.open(QIODevice::WriteOnly | QIODevice::Text)) { - qDebug() << "Failed opening fragmentprograms_p.h"; - exit(0); - } - - QTextStream out(&includeFile); - - QLatin1String tab(TAB); - - out << "/****************************************************************************\n" - "**\n" - "** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).\n" - "** All rights reserved.\n" - "** Contact: Nokia Corporation (qt-info@nokia.com)\n" - "**\n" - "** This file is part of the QtOpenGL module of the Qt Toolkit.\n" - "**\n" - "** $QT_BEGIN_LICENSE:LGPL$\n" - "** GNU Lesser General Public License Usage\n" - "** This file may be used under the terms of the GNU Lesser General Public\n" - "** License version 2.1 as published by the Free Software Foundation and\n" - "** appearing in the file LICENSE.LGPL included in the packaging of this\n" - "** file. Please review the following information to ensure the GNU Lesser\n" - "** General Public License version 2.1 requirements will be met:\n" - "** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n" - "**\n" - "** In addition, as a special exception, Nokia gives you certain additional\n" - "** rights. These rights are described in the Nokia Qt LGPL Exception\n" - "** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n" - "**\n" - "** GNU General Public License Usage\n" - "** Alternatively, this file may be used under the terms of the GNU General\n" - "** Public License version 3.0 as published by the Free Software Foundation\n" - "** and appearing in the file LICENSE.GPL included in the packaging of this\n" - "** file. Please review the following information to ensure the GNU General\n" - "** Public License version 3.0 requirements will be met:\n" - "** http://www.gnu.org/copyleft/gpl.html.\n" - "**\n" - "** Other Usage\n" - "** Alternatively, this file may be used in accordance with the terms and\n" - "** conditions contained in a signed written agreement between you and Nokia.\n" - "**\n" - "**\n" - "**\n" - "**\n" - "**\n" - "** $QT_END_LICENSE$\n" - "**\n" - "****************************************************************************/\n" - "\n" - "#ifndef FRAGMENTPROGRAMS_P_H\n" - "#define FRAGMENTPROGRAMS_P_H\n" - "\n" - "//\n" - "// W A R N I N G\n" - "// -------------\n" - "//\n" - "// This file is not part of the Qt API. It exists purely as an\n" - "// implementation detail. This header file may change from version to\n" - "// version without notice, or even be removed.\n" - "//\n" - "// We mean it.\n" - "//\n" - "\n"; - - writeVariablesEnum(out, "FragmentVariable", variables); - writeTypesEnum(out, "FragmentBrushType", brushes); - writeTypesEnum(out, "FragmentCompositionModeType", compositionModes); - writeTypesEnum(out, "FragmentMaskType", masks); - - out << "static const unsigned int num_fragment_variables = " << variables.size() << ";\n\n"; - out << "static const unsigned int num_fragment_brushes = " << brushes.size() << ";\n"; - out << "static const unsigned int num_fragment_composition_modes = " << compositionModes.size() << ";\n"; - out << "static const unsigned int num_fragment_masks = " << masks.size() << ";\n\n"; - - foreach (QStringPair mask, masks) { - const QString compiledSource = compiled[mask.first]["MASK__"]; - - out << "static const char *FragmentProgram_" << mask.first << " =\n" - << trimmed(compiledSource) - << '\n'; - } - - foreach (QStringPair brush, brushes) { - foreach (QStringPair mode, compositionModes) { - const QString compiledSource = compiled[brush.first][mode.first]; - - out << "static const char *FragmentProgram_" << brush.first << '_' << mode.first << " =\n" - << trimmed(compiledSource) - << '\n'; - } - } - - out << "static const char *mask_fragment_program_sources[num_fragment_masks] = {\n"; - foreach (QStringPair mask, masks) - out << tab << "FragmentProgram_" << mask.first << ",\n"; - out << "};\n\n"; - - out << "static const char *painter_fragment_program_sources[num_fragment_brushes][num_fragment_composition_modes] = {\n"; - foreach (QStringPair brush, brushes) { - out << tab << "{\n"; - - foreach (QStringPair mode, compositionModes) - out << tab << tab << "FragmentProgram_" << brush.first << '_' << mode.first << ",\n"; - - out << tab << "},\n"; - } - out << "};\n\n"; - - out << "static int painter_variable_locations[num_fragment_brushes][num_fragment_composition_modes][num_fragment_variables] = {\n"; - foreach (QStringPair brush, brushes) { - out << tab << "{\n"; - - foreach (QStringPair mode, compositionModes) { - out << tab << tab << "{ "; - - QList<int> locations = getLocations(variables, compiled[brush.first][mode.first]); - - foreach (int location, locations) - out << location << ", "; - - out << "},\n"; - } - - out << tab << "},\n"; - } - out << "};\n\n"; - - out << "static int mask_variable_locations[num_fragment_masks][num_fragment_variables] = {\n"; - foreach (QStringPair mask, masks) { - out << tab << "{ "; - - QList<int> locations = getLocations(variables, compiled[mask.first]["MASK__"]); - - foreach (int location, locations) - out << location << ", "; - - out << "},\n"; - } - out << "};\n\n"; - out << "#endif\n"; -} - -QList<QString> getVariables(QString program) -{ - QList<QString> result; - - QTextStream in(&program); - while (!in.atEnd()) { - QString line = in.readLine(); - - if (line.startsWith("uniform")) { - QString word = getWord(line, 3); - result << word.left(word.size() - 1); - } else if (line.startsWith("#include")) { - QString file = getWord(line, 2); - result << getVariables(readSourceFile(file.mid(1, file.size() - 2))); - } - } - - return result; -} - -int main() -{ - QList<QStringPair> brushes = readConf(QLatin1String("brushes.conf")); - QList<QStringPair> compositionModes = readConf(QLatin1String("composition_modes.conf")); - QList<QStringPair> masks = readConf(QLatin1String("masks.conf")); - - QString painterSource = readSourceFile("painter.glsl"); - QString painterNoMaskSource = readSourceFile("painter_nomask.glsl"); - QString fastPainterSource = readSourceFile("fast_painter.glsl"); - QString brushPainterSource = readSourceFile("brush_painter.glsl"); - - QSet<QString> variables; - - QList<QStringPair> programs[3] = { brushes, compositionModes, masks }; - - for (int i = 0; i < 3; ++i) - foreach (QStringPair value, programs[i]) - variables += QSet<QString>::fromList(getVariables(value.second)); - - variables += QSet<QString>::fromList(getVariables(painterSource)); - variables += QSet<QString>::fromList(getVariables(fastPainterSource)); - - QMap<QString, QMap<QString, QString> > compiled; - - foreach (QStringPair brush, brushes) { - foreach (QStringPair mode, compositionModes) { - QString combinedSource = brush.second + mode.second + painterSource; - compiled[brush.first][mode.first] = compileSource(combinedSource); - - combinedSource = brush.second + mode.second + painterNoMaskSource; - compiled[brush.first][mode.first + "_NOMASK"] = compileSource(combinedSource); - } - - QString fastSource = brush.second + fastPainterSource; - QString brushSource = brush.second + brushPainterSource; - - compiled[brush.first]["COMPOSITION_MODE_BLEND_MODE_MASK"] = compileSource(fastSource); - compiled[brush.first]["COMPOSITION_MODE_BLEND_MODE_NOMASK"] = compileSource(brushSource); - } - - QList<QStringPair> temp; - - foreach (QStringPair mode, compositionModes) - temp << QStringPair(mode.first + "_NOMASK", mode.second); - - compositionModes += temp; - - compositionModes << QStringPair("COMPOSITION_MODE_BLEND_MODE_MASK", "") - << QStringPair("COMPOSITION_MODE_BLEND_MODE_NOMASK", ""); - - foreach (QStringPair mask, masks) - compiled[mask.first]["MASK__"] = compileSource(mask.second); - - writeIncludeFile(variables, brushes, compositionModes, masks, compiled); - - return 0; -} - -QT_END_NAMESPACE diff --git a/src/opengl/util/generator.pro b/src/opengl/util/generator.pro deleted file mode 100644 index ac71934ecf..0000000000 --- a/src/opengl/util/generator.pro +++ /dev/null @@ -1,13 +0,0 @@ -###################################################################### -# Automatically generated by qmake (2.01a) Thu Oct 19 11:03:24 2006 -###################################################################### - -TEMPLATE = app -TARGET = generator -DEPENDPATH += . -INCLUDEPATH += . - -# Input -SOURCES += generator.cpp - -CONFIG += console diff --git a/src/opengl/util/glsl_to_include.sh b/src/opengl/util/glsl_to_include.sh deleted file mode 100755 index c97239bfdd..0000000000 --- a/src/opengl/util/glsl_to_include.sh +++ /dev/null @@ -1,73 +0,0 @@ -#! /bin/sh -############################################################################# -## -## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -## All rights reserved. -## Contact: Nokia Corporation (qt-info@nokia.com) -## -## This file is the build configuration utility 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$ -## -############################################################################# - -# Compile a .glsl file to a file that can be included in a C++ program -USAGE="Usage: $0 <file.glsl>" -CGC=cgc -CGC_PROFILE=arbfp1 - -if test $# -ne 1 -then - echo $USAGE - exit 1 -fi - -GLSL_FILE=$1 -FRAG_FILE=`basename $1 .glsl`.frag -#GLSL_INC_FILE=`basename $1 .glsl`.glsl_quoted - -echo "// Generated by src/opengl/util/$0 from $1" > $FRAG_FILE -$CGC -quiet -oglsl -profile $CGC_PROFILE $GLSL_FILE | while read line -do - if test `echo $line | cut -c1` != "#" - then - echo -e \"$line\" >> $FRAG_FILE - fi -done -echo "; // Generated by src/opengl/util/$0 from $1" >> $FRAG_FILE - -#echo "// Generated by src/opengl/util/$0 from $1" > $GLSL_INC_FILE -#cat $GLSL_FILE | while read line -#do -# printf \"%s\\\\n\"\\n "$line" >> $GLSL_INC_FILE -#done -#echo "; // Generated by src/opengl/util/$0 from $1" >> $GLSL_INC_FILE diff --git a/src/opengl/util/linear_brush.glsl b/src/opengl/util/linear_brush.glsl deleted file mode 100644 index 90a4440a99..0000000000 --- a/src/opengl/util/linear_brush.glsl +++ /dev/null @@ -1,22 +0,0 @@ -uniform sampler1D palette; -uniform vec3 linear; -uniform vec3 inv_matrix_m0; -uniform vec3 inv_matrix_m1; -uniform vec3 inv_matrix_m2; - -vec4 brush() -{ - mat3 mat; - - mat[0] = inv_matrix_m0; - mat[1] = inv_matrix_m1; - mat[2] = inv_matrix_m2; - - vec3 hcoords = mat * vec3(gl_FragCoord.xy, 1); - vec2 A = hcoords.xy / hcoords.z; - - float val = dot(linear.xy, A) * linear.z; - - return texture1D(palette, val); -} - diff --git a/src/opengl/util/masks.conf b/src/opengl/util/masks.conf deleted file mode 100644 index d853d0b6e9..0000000000 --- a/src/opengl/util/masks.conf +++ /dev/null @@ -1,2 +0,0 @@ -FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA trap_exact_aa.glsl -FRAGMENT_PROGRAM_MASK_ELLIPSE_AA ellipse_aa.glsl diff --git a/src/opengl/util/meego/main.cpp b/src/opengl/util/meego/main.cpp deleted file mode 100644 index 21ac5fd629..0000000000 --- a/src/opengl/util/meego/main.cpp +++ /dev/null @@ -1,89 +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 <QtCore/qdebug.h> - -#define QT_DEBUG_SHADER_CACHE -#define QT_MEEGO_EXPERIMENTAL_SHADERCACHE -#define QT_OPENGL_ES_2 -#define QT_BOOTSTRAPPED - -typedef int GLsizei; -typedef unsigned int GLenum; - -#include "../../gl2paintengineex/qglshadercache_meego_p.h" - -#include <stdlib.h> -#include <stdio.h> - -int main() -{ - ShaderCacheSharedMemory shm; - - if (!shm.isAttached()) { - fprintf(stderr, "Unable to attach to shared memory\n"); - return EXIT_FAILURE; - } - - ShaderCacheLocker locker(&shm); - if (!locker.isLocked()) { - fprintf(stderr, "Unable to lock shared memory\n"); - return EXIT_FAILURE; - } - - void *data = shm.data(); - Q_ASSERT(data); - - CachedShaders *cache = reinterpret_cast<CachedShaders *>(data); - - for (int i = 0; i < cache->shaderCount; ++i) { - printf("Shader %d: %d bytes\n", i, cache->headers[i].size); - } - - printf("\nSummary:\n\n" - " Amount of cached shaders: %d\n" - " Bytes used: %d\n" - " Bytes available: %d\n", - cache->shaderCount, cache->dataSize, cache->availableSize()); - - return EXIT_SUCCESS; -} - diff --git a/src/opengl/util/meego/shader-cache-introspector.pro b/src/opengl/util/meego/shader-cache-introspector.pro deleted file mode 100644 index 520e9a5108..0000000000 --- a/src/opengl/util/meego/shader-cache-introspector.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app - -SOURCES += main.cpp - -TARGET = shader-cache-introspector - -QT = core diff --git a/src/opengl/util/painter.glsl b/src/opengl/util/painter.glsl deleted file mode 100644 index b990234778..0000000000 --- a/src/opengl/util/painter.glsl +++ /dev/null @@ -1,21 +0,0 @@ -uniform sampler2D dst_texture; -uniform sampler2D mask_texture; -uniform vec2 inv_mask_size; -uniform vec2 inv_dst_size; -uniform vec2 mask_offset; -uniform vec4 mask_channel; - -float mask() -{ - return dot(mask_channel, texture2D(mask_texture, (gl_FragCoord.xy + mask_offset) * inv_mask_size)); -} - -void main() -{ - vec4 dst = texture2D(dst_texture, gl_FragCoord.xy * inv_dst_size); - - // combine clip and coverage channels - float mask_alpha = mask(); - - gl_FragColor = mix(dst, composite(brush(), dst), mask_alpha); -} diff --git a/src/opengl/util/painter_nomask.glsl b/src/opengl/util/painter_nomask.glsl deleted file mode 100644 index af5ad6505f..0000000000 --- a/src/opengl/util/painter_nomask.glsl +++ /dev/null @@ -1,9 +0,0 @@ -uniform sampler2D dst_texture; -uniform vec2 inv_dst_size; - -void main() -{ - vec4 dst = texture2D(dst_texture, gl_FragCoord.xy * inv_dst_size); - - gl_FragColor = composite(brush(), dst); -} diff --git a/src/opengl/util/pattern_brush.glsl b/src/opengl/util/pattern_brush.glsl deleted file mode 100644 index 31702b887c..0000000000 --- a/src/opengl/util/pattern_brush.glsl +++ /dev/null @@ -1,23 +0,0 @@ -uniform sampler2D brush_texture; -uniform vec2 inv_brush_texture_size; -uniform vec3 inv_matrix_m0; -uniform vec3 inv_matrix_m1; -uniform vec3 inv_matrix_m2; - -vec4 brush() -{ - mat3 mat; - - mat[0] = inv_matrix_m0; - mat[1] = inv_matrix_m1; - mat[2] = inv_matrix_m2; - - vec3 hcoords = mat * vec3(gl_FragCoord.xy, 1); - vec2 coords = hcoords.xy / hcoords.z; - - coords *= inv_brush_texture_size; - - float alpha = 1.0 - texture2D(brush_texture, coords).r; - - return gl_Color * alpha; -} diff --git a/src/opengl/util/radial_brush.glsl b/src/opengl/util/radial_brush.glsl deleted file mode 100644 index 84bec62e65..0000000000 --- a/src/opengl/util/radial_brush.glsl +++ /dev/null @@ -1,28 +0,0 @@ -uniform sampler1D palette; -uniform vec2 fmp; -uniform float fmp2_m_radius2; -uniform vec3 inv_matrix_m0; -uniform vec3 inv_matrix_m1; -uniform vec3 inv_matrix_m2; - -vec4 brush() -{ - mat3 mat; - - mat[0] = inv_matrix_m0; - mat[1] = inv_matrix_m1; - mat[2] = inv_matrix_m2; - - vec3 hcoords = mat * vec3(gl_FragCoord.xy, 1); - vec2 A = hcoords.xy / hcoords.z; - vec2 B = fmp; - - float a = fmp2_m_radius2; - float b = 2.0*dot(A, B); - float c = -dot(A, A); - - float val = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a); - - return texture1D(palette, val); -} - diff --git a/src/opengl/util/simple_porter_duff.glsl b/src/opengl/util/simple_porter_duff.glsl deleted file mode 100644 index 4cb0599ac5..0000000000 --- a/src/opengl/util/simple_porter_duff.glsl +++ /dev/null @@ -1,16 +0,0 @@ -uniform vec2 porterduff_ab; -uniform vec3 porterduff_xyz; - -vec4 composite(vec4 src, vec4 dst) -{ - vec4 result; - - result.xyz = porterduff_ab.x * src.xyz * dst.a - + porterduff_ab.y * dst.xyz * src.a - + porterduff_xyz.y * src.xyz * (1.0 - dst.a) - + porterduff_xyz.z * dst.xyz * (1.0 - src.a); - - result.a = dot(porterduff_xyz, vec3(src.a * dst.a, src.a * (1.0 - dst.a), dst.a * (1.0 - src.a))); - - return result; -} diff --git a/src/opengl/util/solid_brush.glsl b/src/opengl/util/solid_brush.glsl deleted file mode 100644 index 760afd1a72..0000000000 --- a/src/opengl/util/solid_brush.glsl +++ /dev/null @@ -1,4 +0,0 @@ -vec4 brush() -{ - return gl_Color; -} diff --git a/src/opengl/util/texture_brush.glsl b/src/opengl/util/texture_brush.glsl deleted file mode 100644 index 949825583f..0000000000 --- a/src/opengl/util/texture_brush.glsl +++ /dev/null @@ -1,21 +0,0 @@ -uniform sampler2D brush_texture; -uniform vec2 inv_brush_texture_size; -uniform vec3 inv_matrix_m0; -uniform vec3 inv_matrix_m1; -uniform vec3 inv_matrix_m2; - -vec4 brush() -{ - mat3 mat; - - mat[0] = inv_matrix_m0; - mat[1] = inv_matrix_m1; - mat[2] = inv_matrix_m2; - - vec3 hcoords = mat * vec3(gl_FragCoord.xy, 1); - vec2 coords = hcoords.xy / hcoords.z; - - coords *= inv_brush_texture_size; - - return texture2D(brush_texture, coords); -} diff --git a/src/opengl/util/trap_exact_aa.glsl b/src/opengl/util/trap_exact_aa.glsl deleted file mode 100644 index 1637f430b5..0000000000 --- a/src/opengl/util/trap_exact_aa.glsl +++ /dev/null @@ -1,58 +0,0 @@ -float quad_aa() -{ - float top = min(gl_FragCoord.y + 0.5, gl_TexCoord[0].x); - float bottom = max(gl_FragCoord.y - 0.5, gl_TexCoord[0].y); - - float area = top - bottom; - - float left = gl_FragCoord.x - 0.5; - float right = gl_FragCoord.x + 0.5; - - // use line equations to compute intersections of left/right edges with top/bottom of truncated pixel - vec4 vecX = gl_TexCoord[1].xxzz * vec2(top, bottom).xyxy + gl_TexCoord[1].yyww; - - vec2 invA = gl_TexCoord[0].zw; - - // transform right line to left to be able to use same calculations for both - vecX.zw = 2.0 * gl_FragCoord.x - vecX.zw; - - vec2 topX = vec2(vecX.x, vecX.z); - vec2 bottomX = vec2(vecX.y, vecX.w); - - // transform lines such that top intersection is to the right of bottom intersection - vec2 topXTemp = max(topX, bottomX); - vec2 bottomXTemp = min(topX, bottomX); - - // make sure line slope reflects mirrored lines - invA = mix(invA, -invA, step(topX, bottomX)); - - vec2 vecLeftRight = vec2(left, right); - - // compute the intersections of the lines with the left and right edges of the pixel - vec4 intersectY = bottom + (vecLeftRight.xyxy - bottomXTemp.xxyy) * invA.xxyy; - - vec2 temp = mix(area - 0.5 * (right - bottomXTemp) * (intersectY.yw - bottom), // left < bottom < right < top - (0.5 * (topXTemp + bottomXTemp) - left) * area, // left < bottom < top < right - step(topXTemp, right.xx)); - - vec2 excluded = 0.5 * (top - intersectY.xz) * (topXTemp - left); // bottom < left < top < right - - excluded = mix((top - 0.5 * (intersectY.yw + intersectY.xz)) * (right - left), // bottom < left < right < top - excluded, step(topXTemp, right.xx)); - - excluded = mix(temp, // left < bottom < right (see calculation of temp) - excluded, step(bottomXTemp, left.xx)); - - excluded = mix(vec2(area, area), // right < bottom < top - excluded, step(bottomXTemp, right.xx)); - - excluded *= step(left, topXTemp); - - return (area - excluded.x - excluded.y) * step(bottom, top); -} - -void main() -{ - gl_FragColor = quad_aa().xxxx; -} - |