src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 
    41 
    42 #include "qtextureglyphcache_gl_p.h"
    42 #include "qtextureglyphcache_gl_p.h"
    43 #include "qpaintengineex_opengl2_p.h"
    43 #include "qpaintengineex_opengl2_p.h"
    44 
    44 
       
    45 #if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL)
       
    46 #include "private/qeglcontext_p.h"
       
    47 #endif
       
    48 
    45 QT_BEGIN_NAMESPACE
    49 QT_BEGIN_NAMESPACE
    46 
    50 
    47 #ifdef Q_WS_WIN
    51 #ifdef Q_WS_WIN
    48 extern Q_GUI_EXPORT bool qt_cleartype_enabled;
    52 extern Q_GUI_EXPORT bool qt_cleartype_enabled;
    49 #endif
    53 #endif
    50 
    54 
    51 QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
    55 QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
    52     : QTextureGlyphCache(type, matrix)
    56     : QImageTextureGlyphCache(type, matrix)
    53     , ctx(context)
    57     , ctx(context)
    54     , m_width(0)
    58     , m_width(0)
    55     , m_height(0)
    59     , m_height(0)
    56 {
    60 {
    57     glGenFramebuffers(1, &m_fbo);
    61     // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where
       
    62     // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The
       
    63     // workaround is to use a system-memory copy of the glyph cache for this device.
       
    64     // Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and
       
    65     // be slower, so that is not desireable.
       
    66     if (!ctx->d_ptr->workaround_brokenFBOReadBack)
       
    67         glGenFramebuffers(1, &m_fbo);
       
    68 
    58     connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
    69     connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
    59             SLOT(contextDestroyed(const QGLContext*)));
    70             SLOT(contextDestroyed(const QGLContext*)));
    60 }
    71 }
    61 
    72 
    62 QGLTextureGlyphCache::~QGLTextureGlyphCache()
    73 QGLTextureGlyphCache::~QGLTextureGlyphCache()
    63 {
    74 {
    64     if (ctx) {
    75     if (ctx) {
    65         QGLShareContextScope scope(ctx);
    76         QGLShareContextScope scope(ctx);
    66         glDeleteFramebuffers(1, &m_fbo);
    77 
       
    78         if (!ctx->d_ptr->workaround_brokenFBOReadBack)
       
    79             glDeleteFramebuffers(1, &m_fbo);
    67 
    80 
    68         if (m_width || m_height)
    81         if (m_width || m_height)
    69             glDeleteTextures(1, &m_texture);
    82             glDeleteTextures(1, &m_texture);
    70     }
    83     }
    71 }
    84 }
    72 
    85 
    73 void QGLTextureGlyphCache::createTextureData(int width, int height)
    86 void QGLTextureGlyphCache::createTextureData(int width, int height)
    74 {
    87 {
       
    88     // create in QImageTextureGlyphCache baseclass is meant to be called
       
    89     // only to create the initial image and does not preserve the content,
       
    90     // so we don't call when this function is called from resize.
       
    91     if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull())
       
    92         QImageTextureGlyphCache::createTextureData(width, height);
       
    93 
       
    94     // Make the lower glyph texture size 16 x 16.
       
    95     if (width < 16)
       
    96         width = 16;
       
    97     if (height < 16)
       
    98         height = 16;
       
    99 
    75     glGenTextures(1, &m_texture);
   100     glGenTextures(1, &m_texture);
    76     glBindTexture(GL_TEXTURE_2D, m_texture);
   101     glBindTexture(GL_TEXTURE_2D, m_texture);
    77 
   102 
    78     m_width = width;
   103     m_width = width;
    79     m_height = height;
   104     m_height = height;
    91     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   116     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    92 }
   117 }
    93 
   118 
    94 void QGLTextureGlyphCache::resizeTextureData(int width, int height)
   119 void QGLTextureGlyphCache::resizeTextureData(int width, int height)
    95 {
   120 {
       
   121     int oldWidth = m_width;
       
   122     int oldHeight = m_height;
       
   123 
       
   124     // Make the lower glyph texture size 16 x 16.
       
   125     if (width < 16)
       
   126         width = 16;
       
   127     if (height < 16)
       
   128         height = 16;
       
   129 
       
   130     GLuint oldTexture = m_texture;
       
   131     createTextureData(width, height);
       
   132     
       
   133     if (ctx->d_ptr->workaround_brokenFBOReadBack) {
       
   134         QImageTextureGlyphCache::resizeTextureData(width, height);
       
   135         Q_ASSERT(image().depth() == 8);
       
   136         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
       
   137         glDeleteTextures(1, &oldTexture);
       
   138         return;
       
   139     }
       
   140 
    96     // ### the QTextureGlyphCache API needs to be reworked to allow
   141     // ### the QTextureGlyphCache API needs to be reworked to allow
    97     // ### resizeTextureData to fail
   142     // ### resizeTextureData to fail
    98 
       
    99     int oldWidth = m_width;
       
   100     int oldHeight = m_height;
       
   101 
       
   102     GLuint oldTexture = m_texture;
       
   103     createTextureData(width, height);
       
   104 
   143 
   105     glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
   144     glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
   106 
   145 
   107     GLuint tmp_texture;
   146     GLuint tmp_texture;
   108     glGenTextures(1, &tmp_texture);
   147     glGenTextures(1, &tmp_texture);
   157 
   196 
   158     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
   197     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
   159 
   198 
   160     glBindTexture(GL_TEXTURE_2D, m_texture);
   199     glBindTexture(GL_TEXTURE_2D, m_texture);
   161 
   200 
   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
       
   174     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
   201     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
   175 #endif
       
   176 
   202 
   177     glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
   203     glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
   178                               GL_RENDERBUFFER_EXT, 0);
   204                               GL_RENDERBUFFER_EXT, 0);
   179     glDeleteTextures(1, &tmp_texture);
   205     glDeleteTextures(1, &tmp_texture);
   180     glDeleteTextures(1, &oldTexture);
   206     glDeleteTextures(1, &oldTexture);
   185     pex->updateClipScissorTest();
   211     pex->updateClipScissorTest();
   186 }
   212 }
   187 
   213 
   188 void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
   214 void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
   189 {
   215 {
       
   216     if (ctx->d_ptr->workaround_brokenFBOReadBack) {
       
   217         QImageTextureGlyphCache::fillTexture(c, glyph);
       
   218 
       
   219         glBindTexture(GL_TEXTURE_2D, m_texture);
       
   220         const QImage &texture = image();
       
   221         const uchar *bits = texture.constBits();
       
   222         bits += c.y * texture.bytesPerLine() + c.x;
       
   223         for (int i=0; i<c.h; ++i) {
       
   224             glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits);
       
   225             bits += texture.bytesPerLine();
       
   226         }
       
   227 
       
   228         return;
       
   229     }
       
   230 
   190     QImage mask = textureMapForGlyph(glyph);
   231     QImage mask = textureMapForGlyph(glyph);
   191     const int maskWidth = mask.width();
   232     const int maskWidth = mask.width();
   192     const int maskHeight = mask.height();
   233     const int maskHeight = mask.height();
   193 
   234 
   194     if (mask.format() == QImage::Format_Mono) {
   235     if (mask.format() == QImage::Format_Mono) {
   233             glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
   274             glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
   234 #endif
   275 #endif
   235     }
   276     }
   236 }
   277 }
   237 
   278 
   238 int QGLTextureGlyphCache::glyphMargin() const
   279 int QGLTextureGlyphCache::glyphPadding() const
   239 {
   280 {
   240 #if defined(Q_WS_MAC)
   281     return 1;
   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 }
   282 }
   248 
   283 
   249 QT_END_NAMESPACE
   284 QT_END_NAMESPACE