src/opengl/qpixmapdata_gl.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    51 #include <private/qimage_p.h>
    51 #include <private/qimage_p.h>
    52 
    52 
    53 #include <private/qpaintengineex_opengl2_p.h>
    53 #include <private/qpaintengineex_opengl2_p.h>
    54 
    54 
    55 #include <qdesktopwidget.h>
    55 #include <qdesktopwidget.h>
       
    56 #include <qfile.h>
       
    57 #include <qimagereader.h>
    56 
    58 
    57 QT_BEGIN_NAMESPACE
    59 QT_BEGIN_NAMESPACE
    58 
    60 
    59 extern QGLWidget* qt_gl_share_widget();
    61 extern QGLWidget* qt_gl_share_widget();
    60 
    62 
    74 static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
    76 static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
    75 {
    77 {
    76     return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
    78     return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
    77 }
    79 }
    78 
    80 
    79 QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat)
    81 extern int qt_next_power_of_two(int v);
       
    82 
       
    83 static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz)
       
    84 {
       
    85 #ifdef QT_OPENGL_ES_2
       
    86     QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height()));
       
    87     if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height())
       
    88         return rounded;
       
    89 #endif
       
    90     return sz;
       
    91 }
       
    92 
       
    93 
       
    94 QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize)
    80 {
    95 {
    81     QGLFramebufferObject *chosen = 0;
    96     QGLFramebufferObject *chosen = 0;
    82     QGLFramebufferObject *candidate = 0;
    97     QGLFramebufferObject *candidate = 0;
    83     for (int i = 0; !chosen && i < m_fbos.size(); ++i) {
    98     for (int i = 0; !chosen && i < m_fbos.size(); ++i) {
    84         QGLFramebufferObject *fbo = m_fbos.at(i);
    99         QGLFramebufferObject *fbo = m_fbos.at(i);
    85 
   100 
       
   101         if (strictSize) {
       
   102             if (fbo->size() == requestSize && fbo->format() == requestFormat) {
       
   103                 chosen = fbo;
       
   104                 break;
       
   105             } else {
       
   106                 continue;
       
   107             }
       
   108         }
       
   109 
    86         if (fbo->format() == requestFormat) {
   110         if (fbo->format() == requestFormat) {
    87             // choose the fbo with a matching format and the closest size
   111             // choose the fbo with a matching format and the closest size
    88             if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo))
   112             if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo))
    89                 candidate = fbo;
   113                 candidate = fbo;
    90         }
   114         }
   104             if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4)
   128             if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4)
   105                 sz = requestSize;
   129                 sz = requestSize;
   106 
   130 
   107             if (sz != fboSize) {
   131             if (sz != fboSize) {
   108                 delete candidate;
   132                 delete candidate;
   109                 candidate = new QGLFramebufferObject(sz, requestFormat);
   133                 candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat);
   110             }
   134             }
   111 
   135 
   112             chosen = candidate;
   136             chosen = candidate;
   113         }
   137         }
   114     }
   138     }
   115 
   139 
   116     if (!chosen) {
   140     if (!chosen) {
   117         chosen = new QGLFramebufferObject(requestSize, requestFormat);
   141         if (strictSize)
       
   142             chosen = new QGLFramebufferObject(requestSize, requestFormat);
       
   143         else
       
   144             chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat);
   118     }
   145     }
   119 
   146 
   120     if (!chosen->isValid()) {
   147     if (!chosen->isValid()) {
   121         delete chosen;
   148         delete chosen;
   122         chosen = 0;
   149         chosen = 0;
   125     return chosen;
   152     return chosen;
   126 }
   153 }
   127 
   154 
   128 void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
   155 void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
   129 {
   156 {
   130     m_fbos << fbo;
   157     if (fbo)
       
   158         m_fbos << fbo;
   131 }
   159 }
   132 
   160 
   133 
   161 
   134 QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const
   162 QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const
   135 {
   163 {
   293     m_dirty = false;
   321     m_dirty = false;
   294 
   322 
   295     QGLShareContextScope ctx(qt_gl_share_widget()->context());
   323     QGLShareContextScope ctx(qt_gl_share_widget()->context());
   296     m_ctx = ctx;
   324     m_ctx = ctx;
   297 
   325 
   298     const GLenum format = qt_gl_preferredTextureFormat();
   326     const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB;
       
   327 #ifdef QT_OPENGL_ES_2
       
   328     const GLenum external_format = internal_format;
       
   329 #else
       
   330     const GLenum external_format = qt_gl_preferredTextureFormat();
       
   331 #endif
   299     const GLenum target = GL_TEXTURE_2D;
   332     const GLenum target = GL_TEXTURE_2D;
   300 
   333 
   301     if (!m_texture.id) {
   334     if (!m_texture.id) {
   302         glGenTextures(1, &m_texture.id);
   335         glGenTextures(1, &m_texture.id);
   303         glBindTexture(target, m_texture.id);
   336         glBindTexture(target, m_texture.id);
   304         GLenum format = m_hasAlpha ? GL_RGBA : GL_RGB;
   337         glTexImage2D(target, 0, internal_format, w, h, 0, external_format, GL_UNSIGNED_BYTE, 0);
   305         glTexImage2D(target, 0, format, w, h, 0,
       
   306                 GL_RGBA, GL_UNSIGNED_BYTE, 0);
       
   307         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   338         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   308         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   339         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   309     }
   340     }
   310 
   341 
   311     if (!m_source.isNull()) {
   342     if (!m_source.isNull()) {
   312         const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format);
   343         if (external_format == GL_RGB) {
   313 
   344             const QImage tx = m_source.convertToFormat(QImage::Format_RGB888);
   314         glBindTexture(target, m_texture.id);
   345 
   315         glTexSubImage2D(target, 0, 0, 0, w, h, format,
   346             glBindTexture(target, m_texture.id);
   316                         GL_UNSIGNED_BYTE, tx.bits());
   347             glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
       
   348                             GL_UNSIGNED_BYTE, tx.bits());
       
   349         } else {
       
   350             const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format);
       
   351 
       
   352             glBindTexture(target, m_texture.id);
       
   353             glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
       
   354                             GL_UNSIGNED_BYTE, tx.bits());
       
   355         }
   317 
   356 
   318         if (useFramebufferObjects())
   357         if (useFramebufferObjects())
   319             m_source = QImage();
   358             m_source = QImage();
   320     }
   359     }
   321 
   360 
   355     if (m_texture.id) {
   394     if (m_texture.id) {
   356         QGLShareContextScope ctx(qt_gl_share_widget()->context());
   395         QGLShareContextScope ctx(qt_gl_share_widget()->context());
   357         glDeleteTextures(1, &m_texture.id);
   396         glDeleteTextures(1, &m_texture.id);
   358         m_texture.id = 0;
   397         m_texture.id = 0;
   359     }
   398     }
       
   399 }
       
   400 
       
   401 bool QGLPixmapData::fromFile(const QString &filename, const char *format,
       
   402                              Qt::ImageConversionFlags flags)
       
   403 {
       
   404     if (pixelType() == QPixmapData::BitmapType)
       
   405         return QPixmapData::fromFile(filename, format, flags);
       
   406     QFile file(filename);
       
   407     if (!file.open(QIODevice::ReadOnly))
       
   408         return false;
       
   409     QByteArray data = file.peek(64);
       
   410     bool alpha;
       
   411     if (m_texture.canBindCompressedTexture
       
   412             (data.constData(), data.size(), format, &alpha)) {
       
   413         resize(0, 0);
       
   414         data = file.readAll();
       
   415         file.close();
       
   416         QGLShareContextScope ctx(qt_gl_share_widget()->context());
       
   417         QSize size = m_texture.bindCompressedTexture
       
   418             (data.constData(), data.size(), format);
       
   419         if (!size.isEmpty()) {
       
   420             w = size.width();
       
   421             h = size.height();
       
   422             is_null = false;
       
   423             d = 32;
       
   424             m_hasAlpha = alpha;
       
   425             m_source = QImage();
       
   426             m_dirty = isValid();
       
   427             return true;
       
   428         }
       
   429         return false;
       
   430     }
       
   431     fromImage(QImageReader(&file, format).read(), flags);
       
   432     return !isNull();
       
   433 }
       
   434 
       
   435 bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
       
   436                              Qt::ImageConversionFlags flags)
       
   437 {
       
   438     bool alpha;
       
   439     const char *buf = reinterpret_cast<const char *>(buffer);
       
   440     if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) {
       
   441         resize(0, 0);
       
   442         QGLShareContextScope ctx(qt_gl_share_widget()->context());
       
   443         QSize size = m_texture.bindCompressedTexture(buf, int(len), format);
       
   444         if (!size.isEmpty()) {
       
   445             w = size.width();
       
   446             h = size.height();
       
   447             is_null = false;
       
   448             d = 32;
       
   449             m_hasAlpha = alpha;
       
   450             m_source = QImage();
       
   451             m_dirty = isValid();
       
   452             return true;
       
   453         }
       
   454     }
       
   455     return QPixmapData::fromData(buffer, len, format, flags);
   360 }
   456 }
   361 
   457 
   362 bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
   458 bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
   363 {
   459 {
   364     Q_UNUSED(dx);
   460     Q_UNUSED(dx);
   424 {
   520 {
   425     QImage img;
   521     QImage img;
   426     if (pixelType() == BitmapType) {
   522     if (pixelType() == BitmapType) {
   427         img = QImage(w, h, QImage::Format_MonoLSB);
   523         img = QImage(w, h, QImage::Format_MonoLSB);
   428 
   524 
   429         img.setNumColors(2);
   525         img.setColorCount(2);
   430         img.setColor(0, QColor(Qt::color0).rgba());
   526         img.setColor(0, QColor(Qt::color0).rgba());
   431         img.setColor(1, QColor(Qt::color1).rgba());
   527         img.setColor(1, QColor(Qt::color1).rgba());
   432 
   528 
   433         if (color == Qt::color1)
   529         if (color == Qt::color1)
   434             img.fill(1);
   530             img.fill(1);