Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4343#include "qpaintengineex_opengl2_p.h"
    4444
     45#if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL)
     46#include "private/qeglcontext_p.h"
     47#endif
     48
    4549QT_BEGIN_NAMESPACE
    4650
     
    5054
    5155QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
    52     : QTextureGlyphCache(type, matrix)
    53     , ctx(context)
     56    : QImageTextureGlyphCache(type, matrix)
     57    , ctx(0)
    5458    , m_width(0)
    5559    , m_height(0)
    56 {
    57     glGenFramebuffers(1, &m_fbo);
     60    , m_filterMode(Nearest)
     61{
     62    setContext(context);
     63}
     64
     65void QGLTextureGlyphCache::setContext(QGLContext *context)
     66{
     67    ctx = context;
     68
     69    // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where
     70    // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The
     71    // workaround is to use a system-memory copy of the glyph cache for this device.
     72    // Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and
     73    // be slower, so that is not desireable.
     74    if (!ctx->d_ptr->workaround_brokenFBOReadBack)
     75        glGenFramebuffers(1, &m_fbo);
     76
    5877    connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
    5978            SLOT(contextDestroyed(const QGLContext*)));
    6079}
    6180
    62 QGLTextureGlyphCache::~QGLTextureGlyphCache()
     81void QGLTextureGlyphCache::clear()
    6382{
    6483    if (ctx) {
    6584        QGLShareContextScope scope(ctx);
    66         glDeleteFramebuffers(1, &m_fbo);
    6785
    6886        if (m_width || m_height)
    6987            glDeleteTextures(1, &m_texture);
    70     }
     88
     89        m_texture = 0;
     90        m_width = 0;
     91        m_height = 0;
     92        m_w = 0;
     93        m_h = 0;
     94        m_cx = 0;
     95        m_cy = 0;
     96        m_currentRowHeight = 0;
     97        coords.clear();
     98    }
     99 
     100}
     101
     102QGLTextureGlyphCache::~QGLTextureGlyphCache()
     103{
     104    if (ctx) {
     105        QGLShareContextScope scope(ctx);
     106
     107        if (!ctx->d_ptr->workaround_brokenFBOReadBack)
     108            glDeleteFramebuffers(1, &m_fbo);
     109    }
     110
     111    clear();
    71112}
    72113
    73114void QGLTextureGlyphCache::createTextureData(int width, int height)
    74115{
     116    // create in QImageTextureGlyphCache baseclass is meant to be called
     117    // only to create the initial image and does not preserve the content,
     118    // so we don't call when this function is called from resize.
     119    if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull())
     120        QImageTextureGlyphCache::createTextureData(width, height);
     121
     122    // Make the lower glyph texture size 16 x 16.
     123    if (width < 16)
     124        width = 16;
     125    if (height < 16)
     126        height = 16;
     127
    75128    glGenTextures(1, &m_texture);
    76129    glBindTexture(GL_TEXTURE_2D, m_texture);
     
    79132    m_height = height;
    80133
    81     QVarLengthArray<uchar> data(width * height);
    82     for (int i = 0; i < data.size(); ++i)
    83         data[i] = 0;
    84 
    85     if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
    86         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
    87     else
     134    if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {
     135        QVarLengthArray<uchar> data(width * height * 4);
     136        for (int i = 0; i < data.size(); ++i)
     137            data[i] = 0;
     138        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
     139    } else {
     140        QVarLengthArray<uchar> data(width * height);
     141        for (int i = 0; i < data.size(); ++i)
     142            data[i] = 0;
    88143        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
     144    }
    89145
    90146    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    91147    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     148    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     149    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     150    m_filterMode = Nearest;
    92151}
    93152
    94153void QGLTextureGlyphCache::resizeTextureData(int width, int height)
    95154{
     155    int oldWidth = m_width;
     156    int oldHeight = m_height;
     157
     158    // Make the lower glyph texture size 16 x 16.
     159    if (width < 16)
     160        width = 16;
     161    if (height < 16)
     162        height = 16;
     163
     164    GLuint oldTexture = m_texture;
     165    createTextureData(width, height);
     166
     167    if (ctx->d_ptr->workaround_brokenFBOReadBack) {
     168        QImageTextureGlyphCache::resizeTextureData(width, height);
     169        Q_ASSERT(image().depth() == 8);
     170        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
     171        glDeleteTextures(1, &oldTexture);
     172        return;
     173    }
     174
    96175    // ### the QTextureGlyphCache API needs to be reworked to allow
    97176    // ### resizeTextureData to fail
    98 
    99     int oldWidth = m_width;
    100     int oldHeight = m_height;
    101 
    102     GLuint oldTexture = m_texture;
    103     createTextureData(width, height);
    104177
    105178    glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
     
    114187    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    115188    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     189    m_filterMode = Nearest;
    116190    glBindTexture(GL_TEXTURE_2D, 0);
    117191    glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     
    160234    glBindTexture(GL_TEXTURE_2D, m_texture);
    161235
    162 #ifdef QT_OPENGL_ES_2
    163     QDataBuffer<uchar> buffer(4*oldWidth*oldHeight);
    164     buffer.resize(4*oldWidth*oldHeight);
    165     glReadPixels(0, 0, oldWidth, oldHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
    166 
    167     // do an in-place conversion from GL_RGBA to GL_ALPHA
    168     for (int i=0; i<oldWidth*oldHeight; ++i)
    169         buffer.data()[i] = buffer.at(4*i + 3);
    170 
    171     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight,
    172                     GL_ALPHA, GL_UNSIGNED_BYTE, buffer.data());
    173 #else
    174236    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
    175 #endif
    176237
    177238    glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     
    188249void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
    189250{
     251    if (ctx->d_ptr->workaround_brokenFBOReadBack) {
     252        QImageTextureGlyphCache::fillTexture(c, glyph);
     253
     254        glBindTexture(GL_TEXTURE_2D, m_texture);
     255        const QImage &texture = image();
     256        const uchar *bits = texture.constBits();
     257        bits += c.y * texture.bytesPerLine() + c.x;
     258        for (int i=0; i<c.h; ++i) {
     259            glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits);
     260            bits += texture.bytesPerLine();
     261        }
     262
     263        return;
     264    }
     265
    190266    QImage mask = textureMapForGlyph(glyph);
    191267    const int maskWidth = mask.width();
     
    218294        glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
    219295    } else {
    220 #ifdef QT_OPENGL_ES2
    221         glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
    222 #else
    223296        // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is
    224297        // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista
     
    232305        for (int i = 0; i < maskHeight; ++i)
    233306            glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
    234 #endif
    235     }
    236 }
    237 
    238 int QGLTextureGlyphCache::glyphMargin() const
    239 {
    240 #if defined(Q_WS_MAC)
    241     return 2;
    242 #elif defined (Q_WS_X11)
    243     return 0;
    244 #else
    245     return m_type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0;
    246 #endif
    247 }
    248 
     307    }
     308}
     309
     310int QGLTextureGlyphCache::glyphPadding() const
     311{
     312    return 1;
     313}
     314
     315int QGLTextureGlyphCache::maxTextureWidth() const
     316{
     317    return ctx->d_ptr->maxTextureSize();
     318}
     319
     320int QGLTextureGlyphCache::maxTextureHeight() const
     321{
     322    if (ctx->d_ptr->workaround_brokenTexSubImage)
     323        return qMin(1024, ctx->d_ptr->maxTextureSize());
     324    else
     325        return ctx->d_ptr->maxTextureSize();
     326}
    249327QT_END_NAMESPACE
Note: See TracChangeset for help on using the changeset viewer.