Use NPOT support if available.
authorJustin McPherson <justin.mcpherson@nokia.com>
Tue, 28 Feb 2012 05:08:43 +0000 (15:08 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 6 Mar 2012 05:34:32 +0000 (06:34 +0100)
In QQuickContext2DTexture.

Change-Id: If0311450658a837b7e2665c041ec2846e3c8c2dd
Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>
src/quick/items/context2d/qquickcontext2dtexture.cpp
src/quick/items/context2d/qquickcontext2dtexture_p.h

index 28460e2..7d9f65a 100644 (file)
@@ -75,10 +75,8 @@ Q_GLOBAL_STATIC(QThread, globalCanvasThreadRenderInstance)
 QQuickContext2DTexture::QQuickContext2DTexture()
     : m_context(0)
     , m_item(0)
-    , m_canvasSize(QSize(1, 1))
-    , m_tileSize(QSize(1, 1))
-    , m_canvasWindow(QRect(0, 0, 1, 1))
     , m_dirtyCanvas(false)
+    , m_canvasWindowChanged(false)
     , m_dirtyTexture(false)
     , m_threadRendering(false)
     , m_smooth(false)
@@ -144,6 +142,7 @@ bool QQuickContext2DTexture::setCanvasWindow(const QRect& r)
 {
     if (m_canvasWindow != r) {
         m_canvasWindow = r;
+        m_canvasWindowChanged = true;
         return true;
     }
     return false;
@@ -331,7 +330,7 @@ QRect QQuickContext2DTexture::createTiles(const QRect& window)
         return QRect();
     }
 
-    QRect r = tiledRect(window, m_tileSize);
+    QRect r = tiledRect(window, adjustedTileSize(m_tileSize));
 
     const int tw = m_tileSize.width();
     const int th = m_tileSize.height();
@@ -379,6 +378,30 @@ void QQuickContext2DTexture::clearTiles()
     m_tiles.clear();
 }
 
+QSize QQuickContext2DTexture::adjustedTileSize(const QSize &ts)
+{
+    return ts;
+}
+
+static inline QSize npotAdjustedSize(const QSize &size)
+{
+    static bool checked = false;
+    static bool npotSupported = false;
+
+    if (!checked) {
+        npotSupported = QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+        checked = true;
+    }
+
+    if (npotSupported) {
+        return QSize(qMax(QT_MINIMUM_FBO_SIZE, size.width()),
+                     qMax(QT_MINIMUM_FBO_SIZE, size.height()));
+    }
+
+    return QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width())),
+                       qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height())));
+}
+
 QQuickContext2DFBOTexture::QQuickContext2DFBOTexture()
     : QQuickContext2DTexture()
     , m_fbo(0)
@@ -395,47 +418,9 @@ QQuickContext2DFBOTexture::~QQuickContext2DFBOTexture()
     delete m_paint_device;
 }
 
-bool QQuickContext2DFBOTexture::setCanvasSize(const QSize &size)
+QSize QQuickContext2DFBOTexture::adjustedTileSize(const QSize &ts)
 {
-    QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width()))
-                  , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height())));
-
-    if (m_canvasSize != s) {
-        m_canvasSize = s;
-        m_dirtyCanvas = true;
-        return true;
-    }
-    return false;
-}
-
-bool QQuickContext2DFBOTexture::setTileSize(const QSize &size)
-{
-    QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width()))
-                  , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height())));
-    if (m_tileSize != s) {
-        m_tileSize = s;
-        m_dirtyCanvas = true;
-        return true;
-    }
-    return false;
-}
-
-bool QQuickContext2DFBOTexture::setCanvasWindow(const QRect& canvasWindow)
-{
-    QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(canvasWindow.size().width()))
-                  , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(canvasWindow.size().height())));
-
-
-    bool doChanged = false;
-    if (m_fboSize != s) {
-        m_fboSize = s;
-        doChanged = true;
-    }
-
-    if (m_canvasWindow != canvasWindow)
-        m_canvasWindow = canvasWindow;
-
-    return doChanged;
+    return npotAdjustedSize(ts);
 }
 
 void QQuickContext2DFBOTexture::bind()
@@ -550,9 +535,13 @@ QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
         m_fbo = 0;
         m_multisampledFbo = 0;
         return 0;
-    } else if (!m_fbo || m_fbo->size() != m_fboSize) {
+    } else if (!m_fbo || m_canvasWindowChanged) {
         delete m_fbo;
         delete m_multisampledFbo;
+
+        m_fboSize = npotAdjustedSize(m_canvasWindow.size());
+        m_canvasWindowChanged = false;
+
         if (doMultisampling()) {
             {
                 QOpenGLFramebufferObjectFormat format;
@@ -719,9 +708,10 @@ QPaintDevice* QQuickContext2DImageTexture::beginPainting()
     if (m_canvasWindow.size().isEmpty())
         return 0;
 
-    if (m_image.size() != m_canvasWindow.size()) {
+    if (m_canvasWindowChanged) {
         m_image = QImage(m_canvasWindow.size(), QImage::Format_ARGB32_Premultiplied);
         m_image.fill(0x00000000);
+        m_canvasWindowChanged = false;
     }
 
     return &m_image;
index 9e00ece..81b239d 100644 (file)
@@ -81,9 +81,9 @@ public:
     virtual QImage toImage(const QRectF& region = QRectF()) = 0;
     static QRect tiledRect(const QRectF& window, const QSize& tileSize);
 
-    virtual bool setCanvasSize(const QSize &size);
-    virtual bool setTileSize(const QSize &size);
-    virtual bool setCanvasWindow(const QRect& canvasWindow);
+    bool setCanvasSize(const QSize &size);
+    bool setTileSize(const QSize &size);
+    bool setCanvasWindow(const QRect& canvasWindow);
     void setSmooth(bool smooth);
     bool setDirtyRect(const QRect &dirtyRect);
     virtual void canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth);
@@ -104,6 +104,7 @@ protected:
     virtual void compositeTile(QQuickContext2DTile* tile) = 0;
 
     void clearTiles();
+    virtual QSize adjustedTileSize(const QSize &ts);
     QRect createTiles(const QRect& window);
 
     QList<QQuickContext2DTile*> m_tiles;
@@ -117,6 +118,7 @@ protected:
     QRect m_canvasWindow;
 
     uint m_dirtyCanvas : 1;
+    uint m_canvasWindowChanged : 1;
     uint m_dirtyTexture : 1;
     uint m_threadRendering : 1;
     uint m_smooth : 1;
@@ -144,9 +146,8 @@ public:
     virtual QQuickCanvasItem::RenderTarget renderTarget() const;
     virtual void compositeTile(QQuickContext2DTile* tile);
     virtual void bind();
-    virtual bool setCanvasSize(const QSize &size);
-    virtual bool setTileSize(const QSize &size);
-    virtual bool setCanvasWindow(const QRect& canvasWindow);
+    QSize adjustedTileSize(const QSize &ts);
+
 private Q_SLOTS:
     void grabImage();