src/opengl/qgl.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
    94 #include <qmutex.h>
    94 #include <qmutex.h>
    95 
    95 
    96 
    96 
    97 QT_BEGIN_NAMESPACE
    97 QT_BEGIN_NAMESPACE
    98 
    98 
    99 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
    99 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
   100 QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
   100 QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
   101 #endif
   101 #endif
   102 
   102 
   103 #ifdef Q_WS_X11
   103 #ifdef Q_WS_X11
   104 extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
   104 extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
  1686     default_fbo = 0;
  1686     default_fbo = 0;
  1687     active_engine = 0;
  1687     active_engine = 0;
  1688     workaround_needsFullClearOnEveryFrame = false;
  1688     workaround_needsFullClearOnEveryFrame = false;
  1689     workaround_brokenFBOReadBack = false;
  1689     workaround_brokenFBOReadBack = false;
  1690     workaroundsCached = false;
  1690     workaroundsCached = false;
       
  1691 
       
  1692     workaround_brokenTextureFromPixmap = false;
       
  1693     workaround_brokenTextureFromPixmap_init = false;
       
  1694 
  1691     for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
  1695     for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
  1692         vertexAttributeArraysEnabledState[i] = false;
  1696         vertexAttributeArraysEnabledState[i] = false;
  1693 }
  1697 }
  1694 
  1698 
  1695 QGLContext* QGLContext::currentCtx = 0;
  1699 QGLContext* QGLContext::currentCtx = 0;
  1989     \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
  1993     \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
  1990     would mirror the image and automatically generate mipmaps. This
  1994     would mirror the image and automatically generate mipmaps. This
  1991     option helps preserve this default behavior.
  1995     option helps preserve this default behavior.
  1992 
  1996 
  1993     \omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
  1997     \omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
  1994     wether or not it can bind the pixmap upside down or not.
  1998     whether or not it can bind the pixmap upside down or not.
  1995 
  1999 
  1996     \omitvalue MemoryManagedBindOption Used by paint engines to
  2000     \omitvalue MemoryManagedBindOption Used by paint engines to
  1997     indicate that the pixmap should be memory managed along side with
  2001     indicate that the pixmap should be memory managed along side with
  1998     the pixmap/image that it stems from, e.g. installing destruction
  2002     the pixmap/image that it stems from, e.g. installing destruction
  1999     hooks in them.
  2003     hooks in them.
  2097 #undef ctx
  2101 #undef ctx
  2098 
  2102 
  2099 #ifdef QT_NO_EGL
  2103 #ifdef QT_NO_EGL
  2100 void QGLContextPrivate::swapRegion(const QRegion *)
  2104 void QGLContextPrivate::swapRegion(const QRegion *)
  2101 {
  2105 {
  2102     static bool firstWarning = true;
  2106     Q_Q(QGLContext);
  2103     if (firstWarning) {
  2107     q->swapBuffers();
  2104         qWarning() << "::swapRegion called but not supported!";
       
  2105         firstWarning = false;
       
  2106     }
       
  2107 }
  2108 }
  2108 #endif
  2109 #endif
  2109 
  2110 
  2110 /*!
  2111 /*!
  2111     \overload
  2112     \overload
  2258             }
  2259             }
  2259         }
  2260         }
  2260     }
  2261     }
  2261 }
  2262 }
  2262 
  2263 
  2263 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
  2264 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
  2264 QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *)
  2265 QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *)
  2265 {
  2266 {
  2266     return qt_extensionFuncs;
  2267     return qt_extensionFuncs;
  2267 }
  2268 }
  2268 #endif
  2269 #endif
  2281 
  2282 
  2282 /*! \internal */
  2283 /*! \internal */
  2283 QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
  2284 QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
  2284                                            QGLContext::BindOptions options)
  2285                                            QGLContext::BindOptions options)
  2285 {
  2286 {
       
  2287     Q_Q(QGLContext);
       
  2288 
  2286     const qint64 key = image.cacheKey();
  2289     const qint64 key = image.cacheKey();
  2287     QGLTexture *texture = textureCacheLookup(key, target);
  2290     QGLTexture *texture = textureCacheLookup(key, target);
  2288     if (texture) {
  2291     if (texture) {
  2289         glBindTexture(target, texture->id);
  2292         if (image.paintingActive()) {
  2290         return texture;
  2293             // A QPainter is active on the image - take the safe route and replace the texture.
       
  2294             q->deleteTexture(texture->id);
       
  2295             texture = 0;
       
  2296         } else {
       
  2297             glBindTexture(target, texture->id);
       
  2298             return texture;
       
  2299         }
  2291     }
  2300     }
  2292 
  2301 
  2293     if (!texture)
  2302     if (!texture)
  2294         texture = bindTexture(image, target, format, key, options);
  2303         texture = bindTexture(image, target, format, key, options);
  2295     // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
  2304     // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
  2551             return data->texture();
  2560             return data->texture();
  2552         }
  2561         }
  2553     }
  2562     }
  2554 #else
  2563 #else
  2555     Q_UNUSED(pd);
  2564     Q_UNUSED(pd);
  2556     Q_UNUSED(q);
       
  2557 #endif
  2565 #endif
  2558 
  2566 
  2559     const qint64 key = pixmap.cacheKey();
  2567     const qint64 key = pixmap.cacheKey();
  2560     QGLTexture *texture = textureCacheLookup(key, target);
  2568     QGLTexture *texture = textureCacheLookup(key, target);
  2561     if (texture) {
  2569     if (texture) {
  2562         glBindTexture(target, texture->id);
  2570         if (pixmap.paintingActive()) {
  2563         return texture;
  2571             // A QPainter is active on the pixmap - take the safe route and replace the texture.
       
  2572             q->deleteTexture(texture->id);
       
  2573             texture = 0;
       
  2574         } else {
       
  2575             glBindTexture(target, texture->id);
       
  2576             return texture;
       
  2577         }
  2564     }
  2578     }
  2565 
  2579 
  2566 #if defined(Q_WS_X11)
  2580 #if defined(Q_WS_X11)
  2567     // Try to use texture_from_pixmap
  2581     // Try to use texture_from_pixmap
  2568     const QX11Info *xinfo = qt_x11Info(paintDevice);
  2582     const QX11Info *xinfo = qt_x11Info(paintDevice);
  2569     if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
  2583     if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
  2570         && xinfo && xinfo->screen() == pixmap.x11Info().screen()
  2584         && xinfo && xinfo->screen() == pixmap.x11Info().screen()
  2571         && target == GL_TEXTURE_2D)
  2585         && target == GL_TEXTURE_2D)
  2572     {
  2586     {
  2573         texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
  2587         if (!workaround_brokenTextureFromPixmap_init) {
  2574         if (texture) {
  2588             workaround_brokenTextureFromPixmap_init = true;
  2575             texture->options |= QGLContext::MemoryManagedBindOption;
  2589 
  2576             texture->boundPixmap = pd;
  2590             const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
  2577             boundPixmaps.insert(pd, QPixmap(pixmap));
  2591             const int pos = versionString.indexOf("NVIDIA ");
       
  2592 
       
  2593             if (pos >= 0) {
       
  2594                 const QByteArray nvidiaVersionString = versionString.mid(pos + strlen("NVIDIA "));
       
  2595 
       
  2596                 if (nvidiaVersionString.startsWith("195") || nvidiaVersionString.startsWith("256"))
       
  2597                     workaround_brokenTextureFromPixmap = true;
       
  2598             }
       
  2599         }
       
  2600 
       
  2601         if (!workaround_brokenTextureFromPixmap) {
       
  2602             texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
       
  2603             if (texture) {
       
  2604                 texture->options |= QGLContext::MemoryManagedBindOption;
       
  2605                 texture->boundPixmap = pd;
       
  2606                 boundPixmaps.insert(pd, QPixmap(pixmap));
       
  2607             }
  2578         }
  2608         }
  2579     }
  2609     }
  2580 #endif
  2610 #endif
  2581 
  2611 
  2582     if (!texture) {
  2612     if (!texture) {
  4175 #  if defined(QT_MAC_USE_COCOA)
  4205 #  if defined(QT_MAC_USE_COCOA)
  4176     } else if (e->type() == QEvent::MacGLClearDrawable) {
  4206     } else if (e->type() == QEvent::MacGLClearDrawable) {
  4177         d->glcx->d_ptr->clearDrawable();
  4207         d->glcx->d_ptr->clearDrawable();
  4178 #  endif
  4208 #  endif
  4179     }
  4209     }
       
  4210 #elif defined(Q_OS_SYMBIAN)
       
  4211     // prevents errors on some systems, where we get a flush to a
       
  4212     // hidden widget
       
  4213     if (e->type() == QEvent::Hide) {
       
  4214         makeCurrent();
       
  4215         glFinish();
       
  4216         doneCurrent();
       
  4217     } else if (e->type() == QEvent::ParentChange) {
       
  4218         // if we've reparented a window that has the current context
       
  4219         // bound, we need to rebind that context to the new window id
       
  4220         if (d->glcx == QGLContext::currentContext())
       
  4221             makeCurrent();
       
  4222 
       
  4223         if (testAttribute(Qt::WA_TranslucentBackground))
       
  4224             setContext(new QGLContext(d->glcx->requestedFormat(), this));
       
  4225     }
       
  4226 
       
  4227     // A re-parent is likely to destroy the Symbian window and re-create it. It is important
       
  4228     // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
       
  4229     if (e->type() == QEvent::ParentAboutToChange)
       
  4230         d->glcx->d_func()->destroyEglSurfaceForDevice();
       
  4231 
       
  4232     if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
       
  4233         // The window may have been re-created during re-parent or state change - if so, the EGL
       
  4234         // surface will need to be re-created.
       
  4235         d->recreateEglSurface();
       
  4236     }
       
  4237 
  4180 #endif
  4238 #endif
  4181 
  4239 
  4182     return QWidget::event(e);
  4240     return QWidget::event(e);
  4183 }
  4241 }
  4184 #endif
  4242 #endif
  4382 void QGLWidget::glDraw()
  4440 void QGLWidget::glDraw()
  4383 {
  4441 {
  4384     Q_D(QGLWidget);
  4442     Q_D(QGLWidget);
  4385     if (!isValid())
  4443     if (!isValid())
  4386         return;
  4444         return;
       
  4445 #ifdef Q_OS_SYMBIAN
       
  4446     // Crashes on Symbian if trying to render to invisible surfaces
       
  4447     if (!isVisible() && d->glcx->device()->devType() == QInternal::Widget)
       
  4448         return;
       
  4449 #endif
  4387     makeCurrent();
  4450     makeCurrent();
  4388 #ifndef QT_OPENGL_ES
  4451 #ifndef QT_OPENGL_ES
  4389     if (d->glcx->deviceIsPixmap())
  4452     if (d->glcx->deviceIsPixmap())
  4390         glDrawBuffer(GL_FRONT);
  4453         glDrawBuffer(GL_FRONT);
  4391 #endif
  4454 #endif
  5194         glExtensions |= PVRTCTextureCompression;
  5257         glExtensions |= PVRTCTextureCompression;
  5195     if (extensions.match("GL_ARB_fragment_program"))
  5258     if (extensions.match("GL_ARB_fragment_program"))
  5196         glExtensions |= FragmentProgram;
  5259         glExtensions |= FragmentProgram;
  5197     if (extensions.match("GL_ARB_fragment_shader"))
  5260     if (extensions.match("GL_ARB_fragment_shader"))
  5198         glExtensions |= FragmentShader;
  5261         glExtensions |= FragmentShader;
       
  5262     if (extensions.match("GL_ARB_ES2_compatibility"))
       
  5263         glExtensions |= ES2Compatibility;
  5199     if (extensions.match("GL_ARB_texture_mirrored_repeat"))
  5264     if (extensions.match("GL_ARB_texture_mirrored_repeat"))
  5200         glExtensions |= MirroredRepeat;
  5265         glExtensions |= MirroredRepeat;
  5201     if (extensions.match("GL_EXT_framebuffer_object"))
  5266     if (extensions.match("GL_EXT_framebuffer_object"))
  5202         glExtensions |= FramebufferObject;
  5267         glExtensions |= FramebufferObject;
  5203     if (extensions.match("GL_EXT_stencil_two_side"))
  5268     if (extensions.match("GL_EXT_stencil_two_side"))
  5214         glExtensions |= BGRATextureFormat;
  5279         glExtensions |= BGRATextureFormat;
  5215 #if defined(QT_OPENGL_ES_2)
  5280 #if defined(QT_OPENGL_ES_2)
  5216     glExtensions |= FramebufferObject;
  5281     glExtensions |= FramebufferObject;
  5217     glExtensions |= GenerateMipmap;
  5282     glExtensions |= GenerateMipmap;
  5218     glExtensions |= FragmentShader;
  5283     glExtensions |= FragmentShader;
       
  5284     glExtensions |= ES2Compatibility;
  5219 #endif
  5285 #endif
  5220 #if defined(QT_OPENGL_ES_1)
  5286 #if defined(QT_OPENGL_ES_1)
  5221     if (extensions.match("GL_OES_framebuffer_object"))
  5287     if (extensions.match("GL_OES_framebuffer_object"))
  5222         glExtensions |= FramebufferObject;
  5288         glExtensions |= FramebufferObject;
  5223 #endif
  5289 #endif