⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qpaintengine_opengl.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    qreal min_y;    QDataBuffer<QPointF> tess_points;    QVector<int> tess_points_stops;    QImage pattern_image;    GLdouble projection_matrix[4][4];    QList<QDrawQueueItem> drawQueue;    GLuint drawable_texture;    QSize drawable_texture_size;    QGLPrivateCleanup ref_cleaner;    friend class QGLMaskTextureCache;};void QGLPrivateCleanup::cleanupGLContextRefs(const QGLContext *context){    p->cleanupGLContextRefs(context);}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());    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) :            stops(s), opacity(op) {}        GLuint texId;        QGradientStops stops;        qreal opacity;    };    typedef QMultiHash<quint64, CacheInfo> QGLGradientColorTableHash;public:    QGLGradientCache() : QObject(), buffer_ctx(0)    {        connect(QGLProxy::signalProxy(),                SIGNAL(aboutToDestroyContext(const QGLContext *)),                SLOT(cleanupGLContextRefs(const QGLContext *)));    }    inline GLuint getBuffer(const QGradientStops &stops, qreal opacity, QGLContext *ctx) {        if (buffer_ctx && !qgl_share_reg()->checkSharing(buffer_ctx, ctx))            cleanCache();        buffer_ctx = ctx;        quint64 hash_val = 0;        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, stops, opacity);        else {            do {                const CacheInfo &cache_info = it.value();                if (cache_info.stops == stops && cache_info.opacity == opacity) {                    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, stops, opacity);        }    }    inline int paletteSize() const { return 1024; }protected:    inline int maxCacheSize() const { return 60; }    inline void generateGradientColorTable(const QGradientStops& s,                                           uint *colorTable,                                           int size, qreal opacity) const;    GLuint addCacheElement(quint64 hash_val, const QGradientStops &stops, 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(stops, opacity);        uint buffer[1024];        generateGradientColorTable(stops, buffer, paletteSize(), opacity);        glGenTextures(1, &cache_entry.texId);#ifndef Q_WS_QWS        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() {        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;        }    }};void QGLGradientCache::generateGradientColorTable(const QGradientStops& s, uint *colorTable, int size, qreal opacity) const{    int pos = 0;    qreal fpos = 0.0;    qreal incr = 1.0 / qreal(size);    QVector<uint> colors(s.size());    for (int i = 0; i < s.size(); ++i)        colors[i] = s[i].second.rgba();    uint alpha = qRound(opacity * 256);    while (fpos < s.first().first) {        colorTable[pos] = PREMUL(ARGB_COMBINE_ALPHA(colors[0], alpha));        pos++;        fpos += incr;    }    for (int i = 0; i < s.size() - 1; ++i) {        qreal delta = 1/(s[i+1].first - s[i].first);        while (fpos < s[i+1].first && pos < size) {            int dist = int(256 * ((fpos - s[i].first) * delta));            int idist = 256 - dist;            uint current_color = PREMUL(ARGB_COMBINE_ALPHA(colors[i], alpha));            uint next_color = PREMUL(ARGB_COMBINE_ALPHA(colors[i+1], alpha));#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN            colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);#else            uint c = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);            colorTable[pos] = ( (c << 24) & 0xff000000)                              | ((c >> 24) & 0x000000ff)                              | ((c << 8) & 0x00ff0000)                              | ((c >> 8) & 0x0000ff00);#endif // Q_BYTE_ORDER            ++pos;            fpos += incr;        }    }    for (;pos < size; ++pos)        colorTable[pos] = colors[s.size() - 1];}#ifndef Q_WS_QWSQ_GLOBAL_STATIC(QGLGradientCache, qt_opengl_gradient_cache)#endifvoid QOpenGLPaintEnginePrivate::createGradientPaletteTexture(const QGradient& g){#ifdef Q_WS_QWS //###    Q_UNUSED(g);#else    GLuint texId = qt_opengl_gradient_cache()->getBuffer(g.stops(), opacity, drawable.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 Q_WS_QWS //### 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)                fragment_brush = FRAGMENT_PROGRAM_BRUSH_TEXTURE;            else                fragment_brush = FRAGMENT_PROGRAM_BRUSH_PATTERN;        }    }#endif}QOpenGLPaintEngine::QOpenGLPaintEngine()    : QPaintEngine(*(new QOpenGLPaintEnginePrivate),                   PaintEngineFeatures(AllFeatures                                       & ~(LinearGradientFill                                           | RadialGradientFill                                           | ConicalGradientFill                                           | PatternBrush                                           | BlendModes))){}QOpenGLPaintEngine::~QOpenGLPaintEngine(){}#ifndef Q_WS_QWSstatic bool qt_createFragmentProgram(QGLContext *ctx, GLuint &program, const char *shader_src){#ifndef Q_WS_WIN    Q_UNUSED(ctx);#endif    glGenProgramsARB(1, &program);    glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program);    const GLbyte *gl_shader_src = reinterpret_cast<const GLbyte *>(shader_src); /* MSVC.NET 2002 */    glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,                       int(strlen(shader_src)), gl_shader_src);    return glGetError() == GL_NO_ERROR;}#endif // !Q_WS_QWSbool QOpenGLPaintEngine::begin(QPaintDevice *pdev){    Q_D(QOpenGLPaintEngine);    d->drawable.setDevice(pdev);    d->offscreen.setDevice(pdev);    d->has_clipping = false;    d->has_fast_pen = false;    d->inverseScale = 1;    d->opacity = 1;    d->drawable.makeCurrent();    d->matrix = QTransform();    bool has_frag_program = (QGLExtensions::glExtensions & QGLExtensions::FragmentProgram)                            && (pdev->devType() != QInternal::Pixmap);    QGLContext *ctx = const_cast<QGLContext *>(d->drawable.context());    if (has_frag_program)        has_frag_program = qt_resolve_frag_program_extensions(ctx);    d->use_stencil_method = d->drawable.format().stencil() &&                            QGLExtensions::glExtensions & QGLExtensions::StencilWrap;    if (d->use_stencil_method && QGLExtensions::glExtensions & QGLExtensions::StencilTwoSide)        d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx);    if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_3)        qt_resolve_version_1_3_functions(ctx);#ifndef Q_WS_QWS    glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);    glPushAttrib(GL_ALL_ATTRIB_BITS);    glGetDoublev(GL_PROJECTION_MATRIX, &d->projection_matrix[0][0]);#endif    glMatrixMode(GL_MODELVIEW);    glPushMatrix();    glMatrixMode(GL_TEXTURE);    glPushMatrix();    glLoadIdentity();    glDisableClientState(GL_COLOR_ARRAY);    glDisableClientState(GL_EDGE_FLAG_ARRAY);    glDisableClientState(GL_INDEX_ARRAY);    glDisableClientState(GL_NORMAL_ARRAY);    glDisableClientState(GL_TEXTURE_COORD_ARRAY);    glDisableClientState(GL_VERTEX_ARRAY);    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);    if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)        glDisable(GL_MULTISAMPLE);#ifndef Q_WS_QWS    glDisable(GL_TEXTURE_1D);#endif    glDisable(GL_TEXTURE_2D);    if (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)        glDisable(GL_TEXTURE_RECTANGLE_NV);    glDisable(GL_DEPTH_TEST);    glDisable(GL_STENCIL_TEST);    glDisable(GL_CULL_FACE);    glDisable(GL_LIGHTING);    glShadeModel(GL_FLAT);    if (d->use_stencil_method) {        glStencilFunc(GL_ALWAYS, 0, ~0);        glClearStencil(0);    }    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);    d->offscreen.begin();    const QColor &c = d->drawable.backgroundColor();    glClearColor(c.redF(), c.greenF(), c.blueF(), 1.0);    if (d->drawable.context()->d_func()->clear_on_painter_begin && d->drawable.autoFillBackground()) {        GLbitfield clearBits = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;#ifndef Q_WS_QWS        clearBits |= GL_ACCUM_BUFFER_BIT;#endif        glClear(clearBits);    } else if (d->use_stencil_method) {        glClear(GL_STENCIL_BUFFER_BIT);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -