src/opengl/qgl.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   125 Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
   125 Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
   126 
   126 
   127 QGLExtensions::Extensions QGLExtensions::glExtensions = 0;
   127 QGLExtensions::Extensions QGLExtensions::glExtensions = 0;
   128 bool QGLExtensions::nvidiaFboNeedsFinish = false;
   128 bool QGLExtensions::nvidiaFboNeedsFinish = false;
   129 
   129 
   130 #ifndef APIENTRY
       
   131 # define APIENTRY
       
   132 #endif
       
   133 typedef void (APIENTRY *pfn_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
       
   134                                                         GLsizei, GLint, GLsizei, const GLvoid *);
       
   135 static pfn_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB = 0;
       
   136 
       
   137 
       
   138 #ifndef APIENTRY
       
   139 #define APIENTRY
       
   140 #endif
       
   141 
       
   142 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
   130 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
   143 QGLSignalProxy *QGLSignalProxy::instance()
   131 QGLSignalProxy *QGLSignalProxy::instance()
   144 {
   132 {
   145     return theSignalProxy();
   133     return theSignalProxy();
   146 }
   134 }
   182             // No user-set engine - use the defaults
   170             // No user-set engine - use the defaults
   183 #if defined(QT_OPENGL_ES_2)
   171 #if defined(QT_OPENGL_ES_2)
   184             engineType = QPaintEngine::OpenGL2;
   172             engineType = QPaintEngine::OpenGL2;
   185 #else
   173 #else
   186             // We can't do this in the constructor for this object because it
   174             // We can't do this in the constructor for this object because it
   187             // needs to be called *before* the QApplication constructor
   175             // needs to be called *before* the QApplication constructor.
       
   176             // Also check for the FragmentShader extension in conjunction with
       
   177             // the 2.0 version flag, to cover the case where we export the display
       
   178             // from an old GL 1.1 server to a GL 2.x client. In that case we can't
       
   179             // use GL 2.0.
   188             if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
   180             if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
       
   181                 && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader)
   189                 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
   182                 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
   190                 engineType = QPaintEngine::OpenGL2;
   183                 engineType = QPaintEngine::OpenGL2;
   191             else
   184             else
   192                 engineType = QPaintEngine::OpenGL;
   185                 engineType = QPaintEngine::OpenGL;
   193 #endif
   186 #endif
   402     \i \link setStencil() Stencil buffer:\endlink Enabled.
   395     \i \link setStencil() Stencil buffer:\endlink Enabled.
   403     \i \link setStereo() Stereo:\endlink Disabled.
   396     \i \link setStereo() Stereo:\endlink Disabled.
   404     \i \link setDirectRendering() Direct rendering:\endlink Enabled.
   397     \i \link setDirectRendering() Direct rendering:\endlink Enabled.
   405     \i \link setOverlay() Overlay:\endlink Disabled.
   398     \i \link setOverlay() Overlay:\endlink Disabled.
   406     \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
   399     \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
   407     \i \link setSampleBuffers() Multisample buffers:\endlink Enabled on
   400     \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
   408        OpenGL/ES 2.0, disabled on other platforms.
       
   409     \endlist
   401     \endlist
   410 */
   402 */
   411 
   403 
   412 QGLFormat::QGLFormat()
   404 QGLFormat::QGLFormat()
   413 {
   405 {
  1488     sharing = false;
  1480     sharing = false;
  1489     max_texture_size = -1;
  1481     max_texture_size = -1;
  1490     version_flags_cached = false;
  1482     version_flags_cached = false;
  1491     version_flags = QGLFormat::OpenGL_Version_None;
  1483     version_flags = QGLFormat::OpenGL_Version_None;
  1492     current_fbo = 0;
  1484     current_fbo = 0;
       
  1485     default_fbo = 0;
  1493     active_engine = 0;
  1486     active_engine = 0;
  1494 }
  1487 }
  1495 
  1488 
  1496 QGLContext* QGLContext::currentCtx = 0;
  1489 QGLContext* QGLContext::currentCtx = 0;
  1497 
  1490 
  1771     Please note that QGLContext is not thread safe.
  1764     Please note that QGLContext is not thread safe.
  1772 */
  1765 */
  1773 
  1766 
  1774 /*!
  1767 /*!
  1775     \enum QGLContext::BindOption
  1768     \enum QGLContext::BindOption
       
  1769     \since 4.6
       
  1770 
  1776     A set of options to decide how to bind a texture using bindTexture().
  1771     A set of options to decide how to bind a texture using bindTexture().
  1777 
  1772 
  1778     \value NoBindOption Don't do anything, pass the texture straight
  1773     \value NoBindOption Don't do anything, pass the texture straight
  1779     thru.
  1774     through.
  1780 
  1775 
  1781     \value InvertedYBindOption Specifies that the texture should be flipped
  1776     \value InvertedYBindOption Specifies that the texture should be flipped
  1782     over the X axis so that the texture coordinate 0,0 corresponds to
  1777     over the X axis so that the texture coordinate 0,0 corresponds to
  1783     the top left corner. Inverting the texture implies a deep copy
  1778     the top left corner. Inverting the texture implies a deep copy
  1784     prior to upload.
  1779     prior to upload.
  1877 
  1872 
  1878 void QGLContextPrivate::cleanup()
  1873 void QGLContextPrivate::cleanup()
  1879 {
  1874 {
  1880 }
  1875 }
  1881 
  1876 
  1882 typedef QHash<QString, GLuint> QGLDDSCache;
       
  1883 Q_GLOBAL_STATIC(QGLDDSCache, qgl_dds_cache)
       
  1884 
       
  1885 /*!
  1877 /*!
  1886     \overload
  1878     \overload
  1887 
  1879 
  1888     Reads the DirectDrawSurface (DDS) compressed file \a fileName and
  1880     Reads the compressed texture file \a fileName and generates a 2D GL
  1889     generates a 2D GL texture from it.
  1881     texture from it.
  1890 
  1882 
  1891     Only the DXT1, DXT3 and DXT5 DDS formats are supported.
  1883     This function can load DirectDrawSurface (DDS) textures in the
  1892 
  1884     DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression
  1893     Note that this will only work if the implementation supports the
  1885     and \c GL_EXT_texture_compression_s3tc extensions are supported.
  1894     \c GL_ARB_texture_compression and \c GL_EXT_texture_compression_s3tc
  1886 
  1895     extensions.
  1887     Since 4.6.1, textures in the ETC1 format can be loaded if the
       
  1888     \c GL_OES_compressed_ETC1_RGB8_texture extension is supported
       
  1889     and the ETC1 texture has been encapsulated in the PVR container format.
       
  1890     Also, textures in the PVRTC2 and PVRTC4 formats can be loaded
       
  1891     if the \c GL_IMG_texture_compression_pvrtc extension is supported.
  1896 
  1892 
  1897     \sa deleteTexture()
  1893     \sa deleteTexture()
  1898 */
  1894 */
  1899 
  1895 
  1900 GLuint QGLContext::bindTexture(const QString &fileName)
  1896 GLuint QGLContext::bindTexture(const QString &fileName)
  1901 {
  1897 {
  1902     if (!qt_glCompressedTexImage2DARB) {
  1898     Q_D(QGLContext);
  1903         qWarning("QGLContext::bindTexture(): The GL implementation does not support texture"
  1899     QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
  1904                  "compression extensions.");
  1900     QGLDDSCache::const_iterator it = dds_cache->constFind(fileName);
  1905         return 0;
  1901     if (it != dds_cache->constEnd()) {
  1906     }
       
  1907 
       
  1908     QGLDDSCache::const_iterator it = qgl_dds_cache()->constFind(fileName);
       
  1909     if (it != qgl_dds_cache()->constEnd()) {
       
  1910         glBindTexture(GL_TEXTURE_2D, it.value());
  1902         glBindTexture(GL_TEXTURE_2D, it.value());
  1911         return it.value();
  1903         return it.value();
  1912     }
  1904     }
  1913 
  1905 
  1914     QFile f(fileName);
  1906     QGLTexture texture(this);
  1915     f.open(QIODevice::ReadOnly);
  1907     QSize size = texture.bindCompressedTexture(fileName);
  1916 
  1908     if (!size.isValid())
  1917     char tag[4];
       
  1918     f.read(&tag[0], 4);
       
  1919     if (strncmp(tag,"DDS ", 4) != 0) {
       
  1920         qWarning("QGLContext::bindTexture(): not a DDS image file.");
       
  1921         return 0;
  1909         return 0;
  1922     }
  1910 
  1923 
  1911     dds_cache->insert(fileName, texture.id);
  1924     DDSFormat ddsHeader;
  1912     return texture.id;
  1925     f.read((char *) &ddsHeader, sizeof(DDSFormat));
       
  1926 
       
  1927     if (!ddsHeader.dwLinearSize) {
       
  1928         qWarning("QGLContext::bindTexture() DDS image size is not valid.");
       
  1929         return 0;
       
  1930     }
       
  1931 
       
  1932     int factor = 4;
       
  1933     int bufferSize = 0;
       
  1934     int blockSize = 16;
       
  1935     GLenum format;
       
  1936 
       
  1937     switch(ddsHeader.ddsPixelFormat.dwFourCC) {
       
  1938     case FOURCC_DXT1:
       
  1939         format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
       
  1940         factor = 2;
       
  1941         blockSize = 8;
       
  1942         break;
       
  1943     case FOURCC_DXT3:
       
  1944         format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
       
  1945         break;
       
  1946     case FOURCC_DXT5:
       
  1947         format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
       
  1948         break;
       
  1949     default:
       
  1950         qWarning("QGLContext::bindTexture() DDS image format not supported.");
       
  1951         return 0;
       
  1952     }
       
  1953 
       
  1954     if (ddsHeader.dwMipMapCount > 1)
       
  1955         bufferSize = ddsHeader.dwLinearSize * factor;
       
  1956     else
       
  1957         bufferSize = ddsHeader.dwLinearSize;
       
  1958 
       
  1959     GLubyte *pixels = (GLubyte *) malloc(bufferSize*sizeof(GLubyte));
       
  1960     f.seek(ddsHeader.dwSize + 4);
       
  1961     f.read((char *) pixels, bufferSize);
       
  1962     f.close();
       
  1963 
       
  1964     GLuint tx_id;
       
  1965     glGenTextures(1, &tx_id);
       
  1966     glBindTexture(GL_TEXTURE_2D, tx_id);
       
  1967     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       
  1968     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
       
  1969 
       
  1970     int size;
       
  1971     int offset = 0;
       
  1972     int w = ddsHeader.dwWidth;
       
  1973     int h = ddsHeader.dwHeight;
       
  1974 
       
  1975     // load mip-maps
       
  1976     for(int i = 0; i < (int) ddsHeader.dwMipMapCount; ++i) {
       
  1977         if (w == 0) w = 1;
       
  1978         if (h == 0) h = 1;
       
  1979 
       
  1980         size = ((w+3)/4) * ((h+3)/4) * blockSize;
       
  1981         qt_glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, w, h, 0,
       
  1982                                      size, pixels + offset);
       
  1983         offset += size;
       
  1984 
       
  1985         // half size for each mip-map level
       
  1986         w = w/2;
       
  1987         h = h/2;
       
  1988     }
       
  1989 
       
  1990     free(pixels);
       
  1991 
       
  1992     qgl_dds_cache()->insert(fileName, tx_id);
       
  1993     return tx_id;
       
  1994 }
  1913 }
  1995 
  1914 
  1996 static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
  1915 static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
  1997 {
  1916 {
  1998     if (texture_format == GL_BGRA) {
  1917     if (texture_format == GL_BGRA) {
  2135         texture = bindTexture(image, target, format, key, options);
  2054         texture = bindTexture(image, target, format, key, options);
  2136     // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
  2055     // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
  2137     Q_ASSERT(texture);
  2056     Q_ASSERT(texture);
  2138 
  2057 
  2139     if (texture->id > 0)
  2058     if (texture->id > 0)
  2140         const_cast<QImage &>(image).data_ptr()->is_cached = true;
  2059         QImagePixmapCleanupHooks::enableCleanupHooks(image);
  2141 
  2060 
  2142     return texture;
  2061     return texture;
  2143 }
  2062 }
  2144 
  2063 
  2145 // #define QGL_BIND_TEXTURE_DEBUG
  2064 // #define QGL_BIND_TEXTURE_DEBUG
       
  2065 
       
  2066 // map from Qt's ARGB endianness-dependent format to GL's big-endian RGBA layout
       
  2067 static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
       
  2068 {
       
  2069     const int width = img.width();
       
  2070     const int height = img.height();
       
  2071 
       
  2072     if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
       
  2073         || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
       
  2074     {
       
  2075         for (int i = 0; i < height; ++i) {
       
  2076             uint *p = (uint *) img.scanLine(i);
       
  2077             for (int x = 0; x < width; ++x)
       
  2078                 p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
       
  2079         }
       
  2080     } else {
       
  2081         for (int i = 0; i < height; ++i) {
       
  2082             uint *p = (uint *) img.scanLine(i);
       
  2083             for (int x = 0; x < width; ++x)
       
  2084                 p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
       
  2085         }
       
  2086     }
       
  2087 }
  2146 
  2088 
  2147 QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat,
  2089 QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat,
  2148                                            const qint64 key, QGLContext::BindOptions options)
  2090                                            const qint64 key, QGLContext::BindOptions options)
  2149 {
  2091 {
  2150     Q_Q(QGLContext);
  2092     Q_Q(QGLContext);
  2154            image.width(), image.height(), internalFormat, int(options));
  2096            image.width(), image.height(), internalFormat, int(options));
  2155     QTime time;
  2097     QTime time;
  2156     time.start();
  2098     time.start();
  2157 #endif
  2099 #endif
  2158 
  2100 
       
  2101 #ifndef QT_NO_DEBUG
       
  2102     // Reset the gl error stack...git
       
  2103     while (glGetError() != GL_NO_ERROR) ;
       
  2104 #endif
       
  2105 
  2159     // Scale the pixmap if needed. GL textures needs to have the
  2106     // Scale the pixmap if needed. GL textures needs to have the
  2160     // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
  2107     // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
  2161     // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
  2108     // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
  2162     int tx_w = qt_next_power_of_two(image.width());
  2109     int tx_w = qt_next_power_of_two(image.width());
  2163     int tx_h = qt_next_power_of_two(image.height());
  2110     int tx_h = qt_next_power_of_two(image.height());
  2164 
  2111 
  2165     QImage img = image;
  2112     QImage img = image;
  2166     if (( !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) &&
  2113     if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures)
  2167           !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) )
  2114         && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
  2168         && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
  2115         && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
  2169     {
  2116     {
  2170         img = img.scaled(tx_w, tx_h);
  2117         img = img.scaled(tx_w, tx_h);
  2171 #ifdef QGL_BIND_TEXTURE_DEBUG
  2118 #ifdef QGL_BIND_TEXTURE_DEBUG
  2172         printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed());
  2119         printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed());
  2183 
  2130 
  2184 #if defined(QT_OPENGL_ES_2)
  2131 #if defined(QT_OPENGL_ES_2)
  2185     bool genMipmap = false;
  2132     bool genMipmap = false;
  2186 #endif
  2133 #endif
  2187     if (glFormat.directRendering()
  2134     if (glFormat.directRendering()
  2188         && QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap
  2135         && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap)
  2189         && target == GL_TEXTURE_2D
  2136         && target == GL_TEXTURE_2D
  2190         && options & QGLContext::MipmapBindOption)
  2137         && (options & QGLContext::MipmapBindOption))
  2191     {
  2138     {
  2192 #ifdef QGL_BIND_TEXTURE_DEBUG
  2139 #ifdef QGL_BIND_TEXTURE_DEBUG
  2193         printf(" - generating mipmaps (%d ms)\n", time.elapsed());
  2140         printf(" - generating mipmaps (%d ms)\n", time.elapsed());
  2194 #endif
  2141 #endif
  2195 #if !defined(QT_OPENGL_ES_2)
  2142 #if !defined(QT_OPENGL_ES_2)
  2211 
  2158 
  2212     QImage::Format target_format = img.format();
  2159     QImage::Format target_format = img.format();
  2213     bool premul = options & QGLContext::PremultipliedAlphaBindOption;
  2160     bool premul = options & QGLContext::PremultipliedAlphaBindOption;
  2214     GLenum externalFormat;
  2161     GLenum externalFormat;
  2215     GLuint pixel_type;
  2162     GLuint pixel_type;
  2216     if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) {
  2163     if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) {
  2217         externalFormat = GL_BGRA;
  2164         externalFormat = GL_BGRA;
  2218         pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
  2165         pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
  2219     } else {
  2166     } else {
  2220         externalFormat = GL_RGBA;
  2167         externalFormat = GL_RGBA;
  2221         pixel_type = GL_UNSIGNED_BYTE;
  2168         pixel_type = GL_UNSIGNED_BYTE;
  2263 
  2210 
  2264     if (options & QGLContext::InvertedYBindOption) {
  2211     if (options & QGLContext::InvertedYBindOption) {
  2265 #ifdef QGL_BIND_TEXTURE_DEBUG
  2212 #ifdef QGL_BIND_TEXTURE_DEBUG
  2266             printf(" - flipping bits over y (%d ms)\n", time.elapsed());
  2213             printf(" - flipping bits over y (%d ms)\n", time.elapsed());
  2267 #endif
  2214 #endif
  2268         int ipl = img.bytesPerLine() / 4;
  2215         if (img.isDetached()) {
  2269         int h = img.height();
  2216             int ipl = img.bytesPerLine() / 4;
  2270         for (int y=0; y<h/2; ++y) {
  2217             int h = img.height();
  2271             int *a = (int *) img.scanLine(y);
  2218             for (int y=0; y<h/2; ++y) {
  2272             int *b = (int *) img.scanLine(h - y - 1);
  2219                 int *a = (int *) img.scanLine(y);
  2273             for (int x=0; x<ipl; ++x)
  2220                 int *b = (int *) img.scanLine(h - y - 1);
  2274                 qSwap(a[x], b[x]);
  2221                 for (int x=0; x<ipl; ++x)
       
  2222                     qSwap(a[x], b[x]);
       
  2223             }
       
  2224         } else {
       
  2225             // Create a new image and copy across.  If we use the
       
  2226             // above in-place code then a full copy of the image is
       
  2227             // made before the lines are swapped, which processes the
       
  2228             // data twice.  This version should only do it once.
       
  2229             img = img.mirrored();
  2275         }
  2230         }
  2276     }
  2231     }
  2277 
  2232 
  2278     if (externalFormat == GL_RGBA) {
  2233     if (externalFormat == GL_RGBA) {
  2279 #ifdef QGL_BIND_TEXTURE_DEBUG
  2234 #ifdef QGL_BIND_TEXTURE_DEBUG
  2281 #endif
  2236 #endif
  2282         // The only case where we end up with a depth different from
  2237         // The only case where we end up with a depth different from
  2283         // 32 in the switch above is for the RGB16 case, where we set
  2238         // 32 in the switch above is for the RGB16 case, where we set
  2284         // the format to GL_RGB
  2239         // the format to GL_RGB
  2285         Q_ASSERT(img.depth() == 32);
  2240         Q_ASSERT(img.depth() == 32);
  2286         const int width = img.width();
  2241         qgl_byteSwapImage(img, pixel_type);
  2287         const int height = img.height();
  2242     }
  2288 
  2243 #ifdef QT_OPENGL_ES
  2289         if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
  2244     // OpenGL/ES requires that the internal and external formats be identical.
  2290             || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) {
  2245     // This is typically used to convert GL_RGBA into GL_BGRA.
  2291             for (int i=0; i < height; ++i) {
  2246     // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA.
  2292                 uint *p = (uint *) img.scanLine(i);
  2247     internalFormat = externalFormat;
  2293                 for (int x=0; x<width; ++x)
  2248     if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV)
  2294                     p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
  2249         pixel_type = GL_UNSIGNED_BYTE;
  2295             }
  2250 #endif
  2296         } else {
       
  2297             for (int i=0; i < height; ++i) {
       
  2298                 uint *p = (uint *) img.scanLine(i);
       
  2299                 for (int x=0; x<width; ++x)
       
  2300                     p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
       
  2301             }
       
  2302         }
       
  2303     }
       
  2304 #ifdef QGL_BIND_TEXTURE_DEBUG
  2251 #ifdef QGL_BIND_TEXTURE_DEBUG
  2305     printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
  2252     printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
  2306            img.format(), externalFormat, internalFormat, pixel_type);
  2253            img.format(), externalFormat, internalFormat, pixel_type);
  2307 #endif
  2254 #endif
  2308 
  2255 
  2389         texture = bindTexture(pixmap.toImage(), target, format, key, options);
  2336         texture = bindTexture(pixmap.toImage(), target, format, key, options);
  2390     // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
  2337     // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
  2391     Q_ASSERT(texture);
  2338     Q_ASSERT(texture);
  2392 
  2339 
  2393     if (texture->id > 0)
  2340     if (texture->id > 0)
  2394         const_cast<QPixmap &>(pixmap).data_ptr()->is_cached = true;
  2341         QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
  2395 
  2342 
  2396     return texture;
  2343     return texture;
  2397 }
  2344 }
  2398 
  2345 
  2399 /*! \internal */
  2346 /*! \internal */
  2438 
  2385 
  2439   \overload
  2386   \overload
  2440 */
  2387 */
  2441 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
  2388 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
  2442 {
  2389 {
       
  2390     if (image.isNull())
       
  2391         return 0;
       
  2392 
  2443     Q_D(QGLContext);
  2393     Q_D(QGLContext);
  2444     QGLTexture *texture = d->bindTexture(image, target, format, false, DefaultBindOption);
  2394     QGLTexture *texture = d->bindTexture(image, target, format, false, DefaultBindOption);
  2445     return texture->id;
  2395     return texture->id;
  2446 }
  2396 }
  2447 
  2397 
  2470 
  2420 
  2471     \sa deleteTexture()
  2421     \sa deleteTexture()
  2472 */
  2422 */
  2473 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
  2423 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
  2474 {
  2424 {
       
  2425     if (image.isNull())
       
  2426         return 0;
       
  2427 
  2475     Q_D(QGLContext);
  2428     Q_D(QGLContext);
  2476     QGLTexture *texture = d->bindTexture(image, target, format, false, options);
  2429     QGLTexture *texture = d->bindTexture(image, target, format, false, options);
  2477     return texture->id;
  2430     return texture->id;
  2478 }
  2431 }
  2479 
  2432 
  2480 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
  2433 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
  2481 /*! \internal */
  2434 /*! \internal */
  2482 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
  2435 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
  2483 {
  2436 {
       
  2437     if (image.isNull())
       
  2438         return 0;
       
  2439 
  2484     Q_D(QGLContext);
  2440     Q_D(QGLContext);
  2485     QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, DefaultBindOption);
  2441     QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, DefaultBindOption);
  2486     return texture->id;
  2442     return texture->id;
  2487 }
  2443 }
  2488 
  2444 
  2489 /*! \internal */
  2445 /*! \internal */
  2490 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
  2446 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
  2491                                BindOptions options)
  2447                                BindOptions options)
  2492 {
  2448 {
       
  2449     if (image.isNull())
       
  2450         return 0;
       
  2451 
  2493     Q_D(QGLContext);
  2452     Q_D(QGLContext);
  2494     QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, options);
  2453     QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, options);
  2495     return texture->id;
  2454     return texture->id;
  2496 }
  2455 }
  2497 #endif
  2456 #endif
  2500 
  2459 
  2501     Generates and binds a 2D GL texture based on \a pixmap.
  2460     Generates and binds a 2D GL texture based on \a pixmap.
  2502 */
  2461 */
  2503 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
  2462 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
  2504 {
  2463 {
       
  2464     if (pixmap.isNull())
       
  2465         return 0;
       
  2466 
  2505     Q_D(QGLContext);
  2467     Q_D(QGLContext);
  2506     QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
  2468     QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
  2507     return texture->id;
  2469     return texture->id;
  2508 }
  2470 }
  2509 
  2471 
  2514   Generates and binds a 2D GL texture to the current context, based
  2476   Generates and binds a 2D GL texture to the current context, based
  2515   on \a pixmap.
  2477   on \a pixmap.
  2516 */
  2478 */
  2517 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
  2479 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
  2518 {
  2480 {
       
  2481     if (pixmap.isNull())
       
  2482         return 0;
       
  2483 
  2519     Q_D(QGLContext);
  2484     Q_D(QGLContext);
  2520     QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
  2485     QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
  2521     return texture->id;
  2486     return texture->id;
  2522 }
  2487 }
  2523 
  2488 
  2524 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
  2489 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
  2525 /*! \internal */
  2490 /*! \internal */
  2526 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
  2491 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
  2527 {
  2492 {
       
  2493     if (pixmap.isNull())
       
  2494         return 0;
       
  2495 
  2528     Q_D(QGLContext);
  2496     Q_D(QGLContext);
  2529     QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption);
  2497     QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption);
  2530     return texture->id;
  2498     return texture->id;
  2531 }
  2499 }
  2532 /*! \internal */
  2500 /*! \internal */
  2533 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
  2501 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
  2534                                BindOptions options)
  2502                                BindOptions options)
  2535 {
  2503 {
       
  2504     if (pixmap.isNull())
       
  2505         return 0;
       
  2506 
  2536     Q_D(QGLContext);
  2507     Q_D(QGLContext);
  2537     QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options);
  2508     QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options);
  2538     return texture->id;
  2509     return texture->id;
  2539 }
  2510 }
  2540 #endif
  2511 #endif
  2546 
  2517 
  2547     \sa bindTexture()
  2518     \sa bindTexture()
  2548 */
  2519 */
  2549 void QGLContext::deleteTexture(GLuint id)
  2520 void QGLContext::deleteTexture(GLuint id)
  2550 {
  2521 {
       
  2522     Q_D(QGLContext);
       
  2523 
  2551     if (QGLTextureCache::instance()->remove(this, id))
  2524     if (QGLTextureCache::instance()->remove(this, id))
  2552         return;
  2525         return;
  2553 
  2526 
  2554     // check the DDS cache if the texture wasn't found in the pixmap/image
  2527     // check the DDS cache if the texture wasn't found in the pixmap/image
  2555     // cache
  2528     // cache
  2556     QList<QString> ddsKeys = qgl_dds_cache()->keys();
  2529     QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
       
  2530     QList<QString> ddsKeys = dds_cache->keys();
  2557     for (int i = 0; i < ddsKeys.size(); ++i) {
  2531     for (int i = 0; i < ddsKeys.size(); ++i) {
  2558         GLuint texture = qgl_dds_cache()->value(ddsKeys.at(i));
  2532         GLuint texture = dds_cache->value(ddsKeys.at(i));
  2559         if (id == texture) {
  2533         if (id == texture) {
  2560             glDeleteTextures(1, &texture);
  2534             glDeleteTextures(1, &texture);
  2561             qgl_dds_cache()->remove(ddsKeys.at(i));
  2535             dds_cache->remove(ddsKeys.at(i));
  2562             return;
  2536             return;
  2563         }
  2537         }
  2564     }
  2538     }
  2565 }
  2539 }
  2566 
  2540 
  2997 }
  2971 }
  2998 
  2972 
  2999 bool QGLContext::isSharing() const
  2973 bool QGLContext::isSharing() const
  3000 {
  2974 {
  3001     Q_D(const QGLContext);
  2975     Q_D(const QGLContext);
  3002     return d->sharing;
  2976     return d->group->isSharing();
  3003 }
  2977 }
  3004 
  2978 
  3005 QGLFormat QGLContext::format() const
  2979 QGLFormat QGLContext::format() const
  3006 {
  2980 {
  3007     Q_D(const QGLContext);
  2981     Q_D(const QGLContext);
  3834             // ### recreating the overlay isn't supported atm
  3808             // ### recreating the overlay isn't supported atm
  3835         }
  3809         }
  3836     }
  3810     }
  3837 
  3811 
  3838 #if defined(QT_OPENGL_ES)
  3812 #if defined(QT_OPENGL_ES)
       
  3813     // A re-parent is likely to destroy the X11 window and re-create it. It is important
       
  3814     // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
       
  3815     if (e->type() == QEvent::ParentAboutToChange)
       
  3816         d->glcx->d_func()->destroyEglSurfaceForDevice();
       
  3817 
  3839     if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
  3818     if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
  3840         // The window may have been re-created during re-parent or state change - if so, the EGL
  3819         // The window may have been re-created during re-parent or state change - if so, the EGL
  3841         // surface will need to be re-created.
  3820         // surface will need to be re-created.
  3842         d->recreateEglSurface(false);
  3821         d->recreateEglSurface(false);
  3843     }
  3822     }
  4045 #if defined (Q_WS_WIN) && !defined(QT_OPENGL_ES)
  4024 #if defined (Q_WS_WIN) && !defined(QT_OPENGL_ES)
  4046         res = QImage(w, h, QImage::Format_Indexed8);
  4025         res = QImage(w, h, QImage::Format_Indexed8);
  4047         glReadPixels(0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, res.bits());
  4026         glReadPixels(0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, res.bits());
  4048         const QVector<QColor> pal = QColormap::instance().colormap();
  4027         const QVector<QColor> pal = QColormap::instance().colormap();
  4049         if (pal.size()) {
  4028         if (pal.size()) {
  4050             res.setNumColors(pal.size());
  4029             res.setColorCount(pal.size());
  4051             for (int i = 0; i < pal.size(); i++)
  4030             for (int i = 0; i < pal.size(); i++)
  4052                 res.setColor(i, pal.at(i).rgb());
  4031                 res.setColor(i, pal.at(i).rgb());
  4053         }
  4032         }
  4054         res = res.mirrored();
  4033         res = res.mirrored();
  4055 #endif
  4034 #endif
  4124 #else
  4103 #else
  4125     Q_D(const QGLWidget);
  4104     Q_D(const QGLWidget);
  4126     const QGLContext *ctx = QGLContext::currentContext();
  4105     const QGLContext *ctx = QGLContext::currentContext();
  4127     if (ctx) {
  4106     if (ctx) {
  4128         if (ctx->format().rgba())
  4107         if (ctx->format().rgba())
  4129             glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
  4108             glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
  4130         else if (!d->cmap.isEmpty()) { // QGLColormap in use?
  4109         else if (!d->cmap.isEmpty()) { // QGLColormap in use?
  4131             int i = d->cmap.find(c.rgb());
  4110             int i = d->cmap.find(c.rgb());
  4132             if (i < 0)
  4111             if (i < 0)
  4133                 i = d->cmap.findNearest(c.rgb());
  4112                 i = d->cmap.findNearest(c.rgb());
  4134             glIndexi(i);
  4113             glIndexi(i);
  4321 
  4300 
  4322     glShadeModel(GL_FLAT);
  4301     glShadeModel(GL_FLAT);
  4323     glDisable(GL_CULL_FACE);
  4302     glDisable(GL_CULL_FACE);
  4324     glDisable(GL_LIGHTING);
  4303     glDisable(GL_LIGHTING);
  4325     glDisable(GL_STENCIL_TEST);
  4304     glDisable(GL_STENCIL_TEST);
       
  4305     glDisable(GL_DEPTH_TEST);
  4326     glEnable(GL_BLEND);
  4306     glEnable(GL_BLEND);
  4327     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  4307     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  4328 }
  4308 }
  4329 
  4309 
  4330 static void qt_restore_gl_state()
  4310 static void qt_restore_gl_state()
  4374    future version of Qt.
  4354    future version of Qt.
  4375 
  4355 
  4376    \note This function clears the stencil buffer.
  4356    \note This function clears the stencil buffer.
  4377 
  4357 
  4378    \note This function is not supported on OpenGL/ES systems.
  4358    \note This function is not supported on OpenGL/ES systems.
       
  4359 
       
  4360    \note This function temporarily disables depth-testing when the
       
  4361    text is drawn.
       
  4362 
  4379    \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
  4363    \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
  4380 */
  4364 */
  4381 
  4365 
  4382 void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int)
  4366 void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int)
  4383 {
  4367 {
  4464     relative to the currently set projection and model matrices. This
  4448     relative to the currently set projection and model matrices. This
  4465     can be useful if you want to annotate models with text labels and
  4449     can be useful if you want to annotate models with text labels and
  4466     have the labels move with the model as it is rotated etc.
  4450     have the labels move with the model as it is rotated etc.
  4467 
  4451 
  4468     \note This function is not supported on OpenGL/ES systems.
  4452     \note This function is not supported on OpenGL/ES systems.
       
  4453 
       
  4454     \note If depth testing is enabled before this function is called,
       
  4455     then the drawn text will be depth-tested against the models that
       
  4456     have already been drawn in the scene.  Use \c{glDisable(GL_DEPTH_TEST)}
       
  4457     before calling this function to annotate the models without
       
  4458     depth-testing the text.
       
  4459 
  4469     \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
  4460     \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
  4470 */
  4461 */
  4471 void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font, int)
  4462 void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font, int)
  4472 {
  4463 {
  4473 #ifndef QT_OPENGL_ES
  4464 #ifndef QT_OPENGL_ES
  4588 
  4579 
  4589     \sa deleteTexture()
  4580     \sa deleteTexture()
  4590 */
  4581 */
  4591 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format)
  4582 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format)
  4592 {
  4583 {
       
  4584     if (image.isNull())
       
  4585         return 0;
       
  4586 
  4593     Q_D(QGLWidget);
  4587     Q_D(QGLWidget);
  4594     return d->glcx->bindTexture(image, target, format, QGLContext::DefaultBindOption);
  4588     return d->glcx->bindTexture(image, target, format, QGLContext::DefaultBindOption);
  4595 }
  4589 }
  4596 
  4590 
  4597 /*!
  4591 /*!
  4601   The binding \a options are a set of options used to decide how to
  4595   The binding \a options are a set of options used to decide how to
  4602   bind the texture to the context.
  4596   bind the texture to the context.
  4603  */
  4597  */
  4604 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options)
  4598 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options)
  4605 {
  4599 {
       
  4600     if (image.isNull())
       
  4601         return 0;
       
  4602 
  4606     Q_D(QGLWidget);
  4603     Q_D(QGLWidget);
  4607     return d->glcx->bindTexture(image, target, format, options);
  4604     return d->glcx->bindTexture(image, target, format, options);
  4608 }
  4605 }
  4609 
  4606 
  4610 
  4607 
  4611 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
  4608 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
  4612 /*! \internal */
  4609 /*! \internal */
  4613 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
  4610 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
  4614 {
  4611 {
       
  4612     if (image.isNull())
       
  4613         return 0;
       
  4614 
  4615    Q_D(QGLWidget);
  4615    Q_D(QGLWidget);
  4616    return d->glcx->bindTexture(image, GLenum(target), GLint(format), QGLContext::DefaultBindOption);
  4616    return d->glcx->bindTexture(image, GLenum(target), GLint(format), QGLContext::DefaultBindOption);
  4617 }
  4617 }
  4618 
  4618 
  4619 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
  4619 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
  4620                               QGLContext::BindOptions options)
  4620                               QGLContext::BindOptions options)
  4621 {
  4621 {
       
  4622     if (image.isNull())
       
  4623         return 0;
       
  4624 
  4622    Q_D(QGLWidget);
  4625    Q_D(QGLWidget);
  4623    return d->glcx->bindTexture(image, GLenum(target), GLint(format), options);
  4626    return d->glcx->bindTexture(image, GLenum(target), GLint(format), options);
  4624 }
  4627 }
  4625 #endif
  4628 #endif
  4626 
  4629 
  4630 
  4633 
  4631     \sa deleteTexture()
  4634     \sa deleteTexture()
  4632 */
  4635 */
  4633 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
  4636 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
  4634 {
  4637 {
       
  4638     if (pixmap.isNull())
       
  4639         return 0;
       
  4640 
  4635     Q_D(QGLWidget);
  4641     Q_D(QGLWidget);
  4636     return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
  4642     return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
  4637 }
  4643 }
  4638 
  4644 
  4639 /*!
  4645 /*!
  4838 
  4844 
  4839 #endif // QT3_SUPPORT
  4845 #endif // QT3_SUPPORT
  4840 
  4846 
  4841 void QGLExtensions::init_extensions()
  4847 void QGLExtensions::init_extensions()
  4842 {
  4848 {
  4843     QString extensions = QLatin1String(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
  4849     QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
  4844     if (extensions.contains(QLatin1String("texture_rectangle")))
  4850 
       
  4851     if (extensions.match("GL_ARB_texture_rectangle"))
  4845         glExtensions |= TextureRectangle;
  4852         glExtensions |= TextureRectangle;
  4846     if (extensions.contains(QLatin1String("multisample")))
  4853     if (extensions.match("GL_ARB_multisample"))
  4847         glExtensions |= SampleBuffers;
  4854         glExtensions |= SampleBuffers;
  4848     if (extensions.contains(QLatin1String("generate_mipmap")))
  4855     if (extensions.match("GL_SGIS_generate_mipmap"))
  4849         glExtensions |= GenerateMipmap;
  4856         glExtensions |= GenerateMipmap;
  4850     if (extensions.contains(QLatin1String("texture_compression_s3tc")))
  4857     if (extensions.match("GL_ARB_texture_compression"))
  4851         glExtensions |= TextureCompression;
  4858         glExtensions |= TextureCompression;
  4852     if (extensions.contains(QLatin1String("ARB_fragment_program")))
  4859     if (extensions.match("GL_EXT_texture_compression_s3tc"))
       
  4860         glExtensions |= DDSTextureCompression;
       
  4861     if (extensions.match("GL_OES_compressed_ETC1_RGB8_texture"))
       
  4862         glExtensions |= ETC1TextureCompression;
       
  4863     if (extensions.match("GL_IMG_texture_compression_pvrtc"))
       
  4864         glExtensions |= PVRTCTextureCompression;
       
  4865     if (extensions.match("GL_ARB_fragment_program"))
  4853         glExtensions |= FragmentProgram;
  4866         glExtensions |= FragmentProgram;
  4854     if (extensions.contains(QLatin1String("mirrored_repeat")))
  4867     if (extensions.match("GL_ARB_fragment_shader"))
       
  4868         glExtensions |= FragmentShader;
       
  4869     if (extensions.match("GL_ARB_texture_mirrored_repeat"))
  4855         glExtensions |= MirroredRepeat;
  4870         glExtensions |= MirroredRepeat;
  4856     if (extensions.contains(QLatin1String("EXT_framebuffer_object")))
  4871     if (extensions.match("GL_EXT_framebuffer_object"))
  4857         glExtensions |= FramebufferObject;
  4872         glExtensions |= FramebufferObject;
  4858     if (extensions.contains(QLatin1String("EXT_stencil_two_side")))
  4873     if (extensions.match("GL_EXT_stencil_two_side"))
  4859         glExtensions |= StencilTwoSide;
  4874         glExtensions |= StencilTwoSide;
  4860     if (extensions.contains(QLatin1String("EXT_stencil_wrap")))
  4875     if (extensions.match("GL_EXT_stencil_wrap"))
  4861         glExtensions |= StencilWrap;
  4876         glExtensions |= StencilWrap;
  4862     if (extensions.contains(QLatin1String("EXT_packed_depth_stencil")))
  4877     if (extensions.match("GL_EXT_packed_depth_stencil"))
  4863         glExtensions |= PackedDepthStencil;
  4878         glExtensions |= PackedDepthStencil;
  4864     if (extensions.contains(QLatin1String("GL_NV_float_buffer")))
  4879     if (extensions.match("GL_NV_float_buffer"))
  4865         glExtensions |= NVFloatBuffer;
  4880         glExtensions |= NVFloatBuffer;
  4866     if (extensions.contains(QLatin1String("ARB_pixel_buffer_object")))
  4881     if (extensions.match("GL_ARB_pixel_buffer_object"))
  4867         glExtensions |= PixelBufferObject;
  4882         glExtensions |= PixelBufferObject;
  4868 #if defined(QT_OPENGL_ES_2)
  4883 #if defined(QT_OPENGL_ES_2)
  4869     glExtensions |= FramebufferObject;
  4884     glExtensions |= FramebufferObject;
  4870     glExtensions |= GenerateMipmap;
  4885     glExtensions |= GenerateMipmap;
       
  4886     glExtensions |= FragmentShader;
  4871 #endif
  4887 #endif
  4872 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
  4888 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
  4873     if (extensions.contains(QLatin1String("OES_framebuffer_object")))
  4889     if (extensions.match("GL_OES_framebuffer_object"))
  4874         glExtensions |= FramebufferObject;
  4890         glExtensions |= FramebufferObject;
  4875 #endif
  4891 #endif
  4876 #if defined(QT_OPENGL_ES)
  4892 #if defined(QT_OPENGL_ES)
  4877     if (extensions.contains(QLatin1String("OES_packed_depth_stencil")))
  4893     if (extensions.match("GL_OES_packed_depth_stencil"))
  4878         glExtensions |= PackedDepthStencil;
  4894         glExtensions |= PackedDepthStencil;
  4879 #endif
  4895 #endif
  4880     if (extensions.contains(QLatin1String("ARB_framebuffer_object"))) {
  4896     if (extensions.match("GL_ARB_framebuffer_object")) {
  4881         // ARB_framebuffer_object also includes EXT_framebuffer_blit.
  4897         // ARB_framebuffer_object also includes EXT_framebuffer_blit.
  4882         glExtensions |= FramebufferObject;
  4898         glExtensions |= FramebufferObject;
  4883         glExtensions |= FramebufferBlit;
  4899         glExtensions |= FramebufferBlit;
  4884     }
  4900     }
  4885     if (extensions.contains(QLatin1String("EXT_framebuffer_blit")))
  4901 
       
  4902     if (extensions.match("GL_EXT_framebuffer_blit"))
  4886         glExtensions |= FramebufferBlit;
  4903         glExtensions |= FramebufferBlit;
  4887 
  4904 
  4888     if (extensions.contains(QLatin1String("GL_ARB_texture_non_power_of_two")))
  4905     if (extensions.match("GL_ARB_texture_non_power_of_two"))
  4889         glExtensions |= NPOTTextures;
  4906         glExtensions |= NPOTTextures;
  4890 
  4907 
  4891     QGLContext cx(QGLFormat::defaultFormat());
  4908     if (extensions.match("GL_EXT_bgra"))
  4892     if (glExtensions & TextureCompression) {
  4909         glExtensions |= BGRATextureFormat;
  4893         qt_glCompressedTexImage2DARB = (pfn_glCompressedTexImage2DARB) cx.getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
       
  4894     }
       
  4895 }
  4910 }
  4896 
  4911 
  4897 /*
  4912 /*
  4898   This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init()
  4913   This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init()
  4899 */
  4914 */
  5045     } else {
  5060     } else {
  5046         m_group = 0;
  5061         m_group = 0;
  5047     }
  5062     }
  5048 }
  5063 }
  5049 
  5064 
       
  5065 QSize QGLTexture::bindCompressedTexture
       
  5066     (const QString& fileName, const char *format)
       
  5067 {
       
  5068     QFile file(fileName);
       
  5069     if (!file.open(QIODevice::ReadOnly))
       
  5070         return QSize();
       
  5071     QByteArray contents = file.readAll();
       
  5072     file.close();
       
  5073     return bindCompressedTexture
       
  5074         (contents.constData(), contents.size(), format);
       
  5075 }
       
  5076 
       
  5077 // PVR header format for container files that store textures compressed
       
  5078 // with the ETC1, PVRTC2, and PVRTC4 encodings.  Format information from the
       
  5079 // PowerVR SDK at http://www.imgtec.com/powervr/insider/powervr-sdk.asp
       
  5080 // "PVRTexTool Reference Manual, version 1.11f".
       
  5081 struct PvrHeader
       
  5082 {
       
  5083     quint32 headerSize;
       
  5084     quint32 height;
       
  5085     quint32 width;
       
  5086     quint32 mipMapCount;
       
  5087     quint32 flags;
       
  5088     quint32 dataSize;
       
  5089     quint32 bitsPerPixel;
       
  5090     quint32 redMask;
       
  5091     quint32 greenMask;
       
  5092     quint32 blueMask;
       
  5093     quint32 alphaMask;
       
  5094     quint32 magic;
       
  5095     quint32 surfaceCount;
       
  5096 };
       
  5097 
       
  5098 #define PVR_MAGIC               0x21525650      // "PVR!" in little-endian
       
  5099 
       
  5100 #define PVR_FORMAT_MASK         0x000000FF
       
  5101 #define PVR_FORMAT_PVRTC2       0x00000018
       
  5102 #define PVR_FORMAT_PVRTC4       0x00000019
       
  5103 #define PVR_FORMAT_ETC1         0x00000036
       
  5104 
       
  5105 #define PVR_HAS_MIPMAPS         0x00000100
       
  5106 #define PVR_TWIDDLED            0x00000200
       
  5107 #define PVR_NORMAL_MAP          0x00000400
       
  5108 #define PVR_BORDER_ADDED        0x00000800
       
  5109 #define PVR_CUBE_MAP            0x00001000
       
  5110 #define PVR_FALSE_COLOR_MIPMAPS 0x00002000
       
  5111 #define PVR_VOLUME_TEXTURE      0x00004000
       
  5112 #define PVR_ALPHA_IN_TEXTURE    0x00008000
       
  5113 #define PVR_VERTICAL_FLIP       0x00010000
       
  5114 
       
  5115 #ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
       
  5116 #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG      0x8C00
       
  5117 #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG      0x8C01
       
  5118 #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG     0x8C02
       
  5119 #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG     0x8C03
       
  5120 #endif
       
  5121 
       
  5122 #ifndef GL_ETC1_RGB8_OES
       
  5123 #define GL_ETC1_RGB8_OES                        0x8D64
       
  5124 #endif
       
  5125 
       
  5126 bool QGLTexture::canBindCompressedTexture
       
  5127     (const char *buf, int len, const char *format, bool *hasAlpha)
       
  5128 {
       
  5129     if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
       
  5130         // Compressed texture loading only supported on little-endian
       
  5131         // systems such as x86 and ARM at the moment.
       
  5132         return false;
       
  5133     }
       
  5134     if (!format) {
       
  5135         // Auto-detect the format from the header.
       
  5136         if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
       
  5137             *hasAlpha = true;
       
  5138             return true;
       
  5139         } else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
       
  5140             const PvrHeader *pvrHeader =
       
  5141                 reinterpret_cast<const PvrHeader *>(buf);
       
  5142             *hasAlpha = (pvrHeader->alphaMask != 0);
       
  5143             return true;
       
  5144         }
       
  5145     } else {
       
  5146         // Validate the format against the header.
       
  5147         if (!qstricmp(format, "DDS")) {
       
  5148             if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
       
  5149                 *hasAlpha = true;
       
  5150                 return true;
       
  5151             }
       
  5152         } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
       
  5153             if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
       
  5154                 const PvrHeader *pvrHeader =
       
  5155                     reinterpret_cast<const PvrHeader *>(buf);
       
  5156                 *hasAlpha = (pvrHeader->alphaMask != 0);
       
  5157                 return true;
       
  5158             }
       
  5159         }
       
  5160     }
       
  5161     return false;
       
  5162 }
       
  5163 
       
  5164 #define ctx QGLContext::currentContext()
       
  5165 
       
  5166 QSize QGLTexture::bindCompressedTexture
       
  5167     (const char *buf, int len, const char *format)
       
  5168 {
       
  5169     if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
       
  5170         // Compressed texture loading only supported on little-endian
       
  5171         // systems such as x86 and ARM at the moment.
       
  5172         return QSize();
       
  5173     }
       
  5174 #if !defined(QT_OPENGL_ES)
       
  5175     if (!glCompressedTexImage2D) {
       
  5176         if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) {
       
  5177             qWarning("QGLContext::bindTexture(): The GL implementation does "
       
  5178                      "not support texture compression extensions.");
       
  5179             return QSize();
       
  5180         }
       
  5181         glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
       
  5182         if (!glCompressedTexImage2D) {
       
  5183             qWarning("QGLContext::bindTexture(): could not resolve "
       
  5184                      "glCompressedTexImage2DARB.");
       
  5185             return QSize();
       
  5186         }
       
  5187     }
       
  5188 #endif
       
  5189     if (!format) {
       
  5190         // Auto-detect the format from the header.
       
  5191         if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
       
  5192             return bindCompressedTextureDDS(buf, len);
       
  5193         else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
       
  5194             return bindCompressedTexturePVR(buf, len);
       
  5195     } else {
       
  5196         // Validate the format against the header.
       
  5197         if (!qstricmp(format, "DDS")) {
       
  5198             if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
       
  5199                 return bindCompressedTextureDDS(buf, len);
       
  5200         } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
       
  5201             if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
       
  5202                 return bindCompressedTexturePVR(buf, len);
       
  5203         }
       
  5204     }
       
  5205     return QSize();
       
  5206 }
       
  5207 
       
  5208 QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
       
  5209 {
       
  5210     // We only support 2D texture loading at present.
       
  5211     if (target != GL_TEXTURE_2D)
       
  5212         return QSize();
       
  5213 
       
  5214     // Bail out if the necessary extension is not present.
       
  5215     if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) {
       
  5216         qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
       
  5217         return QSize();
       
  5218     }
       
  5219 
       
  5220     const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4);
       
  5221     if (!ddsHeader->dwLinearSize) {
       
  5222         qWarning("QGLContext::bindTexture(): DDS image size is not valid.");
       
  5223         return QSize();
       
  5224     }
       
  5225 
       
  5226     int blockSize = 16;
       
  5227     GLenum format;
       
  5228 
       
  5229     switch(ddsHeader->ddsPixelFormat.dwFourCC) {
       
  5230     case FOURCC_DXT1:
       
  5231         format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
       
  5232         blockSize = 8;
       
  5233         break;
       
  5234     case FOURCC_DXT3:
       
  5235         format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
       
  5236         break;
       
  5237     case FOURCC_DXT5:
       
  5238         format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
       
  5239         break;
       
  5240     default:
       
  5241         qWarning("QGLContext::bindTexture(): DDS image format not supported.");
       
  5242         return QSize();
       
  5243     }
       
  5244 
       
  5245     const GLubyte *pixels =
       
  5246         reinterpret_cast<const GLubyte *>(buf + ddsHeader->dwSize + 4);
       
  5247 
       
  5248     glGenTextures(1, &id);
       
  5249     glBindTexture(GL_TEXTURE_2D, id);
       
  5250     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       
  5251     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
       
  5252 
       
  5253     int size;
       
  5254     int offset = 0;
       
  5255     int available = len - int(ddsHeader->dwSize + 4);
       
  5256     int w = ddsHeader->dwWidth;
       
  5257     int h = ddsHeader->dwHeight;
       
  5258 
       
  5259     // load mip-maps
       
  5260     for(int i = 0; i < (int) ddsHeader->dwMipMapCount; ++i) {
       
  5261         if (w == 0) w = 1;
       
  5262         if (h == 0) h = 1;
       
  5263 
       
  5264         size = ((w+3)/4) * ((h+3)/4) * blockSize;
       
  5265         if (size > available)
       
  5266             break;
       
  5267         glCompressedTexImage2D(GL_TEXTURE_2D, i, format, w, h, 0,
       
  5268                                size, pixels + offset);
       
  5269         offset += size;
       
  5270         available -= size;
       
  5271 
       
  5272         // half size for each mip-map level
       
  5273         w = w/2;
       
  5274         h = h/2;
       
  5275     }
       
  5276 
       
  5277     // DDS images are not inverted.
       
  5278     options &= ~QGLContext::InvertedYBindOption;
       
  5279 
       
  5280     return QSize(ddsHeader->dwWidth, ddsHeader->dwHeight);
       
  5281 }
       
  5282 
       
  5283 QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
       
  5284 {
       
  5285     // We only support 2D texture loading at present.  Cube maps later.
       
  5286     if (target != GL_TEXTURE_2D)
       
  5287         return QSize();
       
  5288 
       
  5289     // Determine which texture format we will be loading.
       
  5290     const PvrHeader *pvrHeader = reinterpret_cast<const PvrHeader *>(buf);
       
  5291     GLenum textureFormat;
       
  5292     quint32 minWidth, minHeight;
       
  5293     switch (pvrHeader->flags & PVR_FORMAT_MASK) {
       
  5294     case PVR_FORMAT_PVRTC2:
       
  5295         if (pvrHeader->alphaMask)
       
  5296             textureFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
       
  5297         else
       
  5298             textureFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
       
  5299         minWidth = 16;
       
  5300         minHeight = 8;
       
  5301         break;
       
  5302 
       
  5303     case PVR_FORMAT_PVRTC4:
       
  5304         if (pvrHeader->alphaMask)
       
  5305             textureFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
       
  5306         else
       
  5307             textureFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
       
  5308         minWidth = 8;
       
  5309         minHeight = 8;
       
  5310         break;
       
  5311 
       
  5312     case PVR_FORMAT_ETC1:
       
  5313         textureFormat = GL_ETC1_RGB8_OES;
       
  5314         minWidth = 4;
       
  5315         minHeight = 4;
       
  5316         break;
       
  5317 
       
  5318     default:
       
  5319         qWarning("QGLContext::bindTexture(): PVR image format 0x%x not supported.", int(pvrHeader->flags & PVR_FORMAT_MASK));
       
  5320         return QSize();
       
  5321     }
       
  5322 
       
  5323     // Bail out if the necessary extension is not present.
       
  5324     if (textureFormat == GL_ETC1_RGB8_OES) {
       
  5325         if (!(QGLExtensions::glExtensions &
       
  5326                     QGLExtensions::ETC1TextureCompression)) {
       
  5327             qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
       
  5328             return QSize();
       
  5329         }
       
  5330     } else {
       
  5331         if (!(QGLExtensions::glExtensions &
       
  5332                     QGLExtensions::PVRTCTextureCompression)) {
       
  5333             qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
       
  5334             return QSize();
       
  5335         }
       
  5336     }
       
  5337 
       
  5338     // Boundary check on the buffer size.
       
  5339     quint32 bufferSize = pvrHeader->headerSize + pvrHeader->dataSize;
       
  5340     if (bufferSize > quint32(len)) {
       
  5341         qWarning("QGLContext::bindTexture(): PVR image size is not valid.");
       
  5342         return QSize();
       
  5343     }
       
  5344 
       
  5345     // Create the texture.
       
  5346     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
       
  5347     glGenTextures(1, &id);
       
  5348     glBindTexture(GL_TEXTURE_2D, id);
       
  5349     if (pvrHeader->mipMapCount) {
       
  5350         if ((options & QGLContext::LinearFilteringBindOption) != 0) {
       
  5351             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       
  5352             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
       
  5353         } else {
       
  5354             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
       
  5355             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
       
  5356         }
       
  5357     } else if ((options & QGLContext::LinearFilteringBindOption) != 0) {
       
  5358         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       
  5359         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
       
  5360     } else {
       
  5361         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
       
  5362         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
       
  5363     }
       
  5364 
       
  5365     // Load the compressed mipmap levels.
       
  5366     const GLubyte *buffer =
       
  5367         reinterpret_cast<const GLubyte *>(buf + pvrHeader->headerSize);
       
  5368     bufferSize = pvrHeader->dataSize;
       
  5369     quint32 level = 0;
       
  5370     quint32 width = pvrHeader->width;
       
  5371     quint32 height = pvrHeader->height;
       
  5372     while (bufferSize > 0 && level < pvrHeader->mipMapCount) {
       
  5373         quint32 size =
       
  5374             (qMax(width, minWidth) * qMax(height, minHeight) *
       
  5375              pvrHeader->bitsPerPixel) / 8;
       
  5376         if (size > bufferSize)
       
  5377             break;
       
  5378         glCompressedTexImage2D(GL_TEXTURE_2D, GLint(level), textureFormat,
       
  5379                                GLsizei(width), GLsizei(height), 0,
       
  5380                                GLsizei(size), buffer);
       
  5381         width /= 2;
       
  5382         height /= 2;
       
  5383         buffer += size;
       
  5384         ++level;
       
  5385     }
       
  5386 
       
  5387     // Restore the default pixel alignment for later texture uploads.
       
  5388     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
       
  5389 
       
  5390     // Set the invert flag for the texture.  The "vertical flip"
       
  5391     // flag in PVR is the opposite sense to our sense of inversion.
       
  5392     if ((pvrHeader->flags & PVR_VERTICAL_FLIP) != 0)
       
  5393         options &= ~QGLContext::InvertedYBindOption;
       
  5394     else
       
  5395         options |= QGLContext::InvertedYBindOption;
       
  5396 
       
  5397     return QSize(pvrHeader->width, pvrHeader->height);
       
  5398 }
       
  5399 
       
  5400 #undef ctx
       
  5401 
  5050 QT_END_NAMESPACE
  5402 QT_END_NAMESPACE