Calculate vertex positions on CPU
authorAlan Alpert <alan.alpert@nokia.com>
Fri, 11 May 2012 10:38:26 +0000 (20:38 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 14 May 2012 05:02:54 +0000 (07:02 +0200)
Easier for SG to optimize with, not really gaining anything putting it
on the GPU for these Elements.

Change-Id: I239e70dafce441f5281ded185de63bc1afd7d85a
Reviewed-by: Glenn Watson <glenn.watson@nokia.com>
src/quick/items/qquickanimatedsprite.cpp
src/quick/items/qquickanimatedsprite_p.h
src/quick/items/qquickspritesequence.cpp
src/quick/items/qquickspritesequence_p.h

index a5e5d99..52b9f1c 100644 (file)
 QT_BEGIN_NAMESPACE
 
 static const char vertexShaderCode[] =
+    "attribute highp vec2 vPos;\n"
     "attribute highp vec2 vTex;\n"
     "uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress\n"
     "uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)\n"
-    "uniform highp vec2 size;//w,h of element\n"
     "\n"
     "uniform highp mat4 qt_Matrix;\n"
     "\n"
@@ -75,7 +75,7 @@ static const char vertexShaderCode[] =
     "    //Next frame is also passed, for interpolation\n"
     "    fTexS.zw = animPos.zw + vTex.xy * animData.xy;\n"
     "\n"
-    "    gl_Position = qt_Matrix * vec4(size.x * vTex.x, size.y * vTex.y, 0, 1);\n"
+    "    gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1);\n"
     "}\n";
 
 static const char fragmentShaderCode[] =
@@ -110,8 +110,6 @@ public:
     float animY2;
     float animW;
     float animH;
-    float elementWidth;
-    float elementHeight;
 };
 
 QQuickAnimatedSpriteMaterial::QQuickAnimatedSpriteMaterial()
@@ -123,8 +121,6 @@ QQuickAnimatedSpriteMaterial::QQuickAnimatedSpriteMaterial()
     , animY2(0.0f)
     , animW(1.0f)
     , animH(1.0f)
-    , elementWidth(1.0f)
-    , elementHeight(1.0f)
 {
     setFlag(Blending, true);
 }
@@ -157,7 +153,6 @@ public:
         program()->setUniformValue(m_opacity_id, state.opacity());
         program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT);
         program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2);
-        program()->setUniformValue(m_size_id, m->elementWidth, m->elementHeight);
 
         if (state.isMatrixDirty())
             program()->setUniformValue(m_matrix_id, state.combinedMatrix());
@@ -168,7 +163,6 @@ public:
         m_opacity_id = program()->uniformLocation("qt_Opacity");
         m_animData_id = program()->uniformLocation("animData");
         m_animPos_id = program()->uniformLocation("animPos");
-        m_size_id = program()->uniformLocation("size");
     }
 
     virtual const char *vertexShader() const { return vertexShaderCode; }
@@ -176,6 +170,7 @@ public:
 
     virtual char const *const *attributeNames() const {
         static const char *attr[] = {
+           "vPos",
            "vTex",
             0
         };
@@ -186,7 +181,6 @@ public:
     int m_opacity_id;
     int m_animData_id;
     int m_animPos_id;
-    int m_size_id;
 
     static float chunkOfBytes[1024];
 };
@@ -199,6 +193,8 @@ QSGMaterialShader *QQuickAnimatedSpriteMaterial::createShader() const
 }
 
 struct AnimatedSpriteVertex {
+    float x;
+    float y;
     float tx;
     float ty;
 };
@@ -374,6 +370,10 @@ QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) :
     setFlag(ItemHasContents);
     connect(this, SIGNAL(runningChanged(bool)),
             this, SLOT(update()));
+    connect(this, SIGNAL(widthChanged()),
+            this, SLOT(sizeVertices()));
+    connect(this, SIGNAL(heightChanged()),
+            this, SLOT(sizeVertices()));
 }
 
 void QQuickAnimatedSprite::reloadImage()
@@ -458,16 +458,36 @@ void QQuickAnimatedSprite::createEngine()
 }
 
 static QSGGeometry::Attribute AnimatedSprite_Attributes[] = {
-    QSGGeometry::Attribute::create(0, 2, GL_FLOAT),         // tex
+    QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),   // pos
+    QSGGeometry::Attribute::create(1, 2, GL_FLOAT),         // tex
 };
 
 static QSGGeometry::AttributeSet AnimatedSprite_AttributeSet =
 {
-    1, // Attribute Count
-    2 * sizeof(float),
+    2, // Attribute Count
+    (2+2) * sizeof(float),
     AnimatedSprite_Attributes
 };
 
+void QQuickAnimatedSprite::sizeVertices()
+{
+    if (!m_node)
+        return;
+
+    AnimatedSpriteVertices *p = (AnimatedSpriteVertices *) m_node->geometry()->vertexData();
+    p->v1.x = 0;
+    p->v1.y = 0;
+
+    p->v2.x = width();
+    p->v2.y = 0;
+
+    p->v3.x = 0;
+    p->v3.y = height();
+
+    p->v4.x = width();
+    p->v4.y = height();
+}
+
 QSGGeometryNode* QQuickAnimatedSprite::buildNode()
 {
     if (!m_spriteEngine) {
@@ -498,8 +518,6 @@ QSGGeometryNode* QQuickAnimatedSprite::buildNode()
     m_material->animY2 = m_material->animY1;
     m_material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width();
     m_material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height();
-    m_material->elementWidth = width();
-    m_material->elementHeight = height();
 
     int vCount = 4;
     int iCount = 6;
@@ -520,6 +538,7 @@ QSGGeometryNode* QQuickAnimatedSprite::buildNode()
     p->v4.tx = 1.0;
     p->v4.ty = 1.0;
 
+
     quint16 *indices = g->indexDataAsUShort();
     indices[0] = 0;
     indices[1] = 1;
@@ -534,6 +553,7 @@ QSGGeometryNode* QQuickAnimatedSprite::buildNode()
     m_node->setGeometry(g);
     m_node->setMaterial(m_material);
     m_node->setFlag(QSGGeometryNode::OwnsMaterial);
+    sizeVertices();
     return m_node;
 }
 
@@ -572,8 +592,6 @@ void QQuickAnimatedSprite::prepareNextFrame()
 
     int timeInt = m_timestamp.elapsed() + m_pauseOffset;
     qreal time =  timeInt / 1000.;
-    m_material->elementHeight = height();
-    m_material->elementWidth = width();
 
     double frameAt; //double just for modf
     qreal progress;
index bb9c7ac..c9a74b2 100644 (file)
@@ -346,6 +346,8 @@ public slots:
 
 private slots:
     void createEngine();
+    void sizeVertices();
+
 protected:
     void reset();
     void componentComplete();
index 7f7d1cc..28849ac 100644 (file)
 QT_BEGIN_NAMESPACE
 
 static const char vertexShaderCode[] =
+    "attribute highp vec2 vPos;\n"
     "attribute highp vec2 vTex;\n"
     "uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress\n"
     "uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)\n"
-    "uniform highp vec2 size;//w,h of element\n"
     "\n"
     "uniform highp mat4 qt_Matrix;\n"
     "\n"
@@ -75,7 +75,7 @@ static const char vertexShaderCode[] =
     "    //Next frame is also passed, for interpolation\n"
     "    fTexS.zw = animPos.zw + vTex.xy * animData.xy;\n"
     "\n"
-    "    gl_Position = qt_Matrix * vec4(size.x * vTex.x, size.y * vTex.y, 0, 1);\n"
+    "    gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1);\n"
     "}\n";
 
 static const char fragmentShaderCode[] =
@@ -110,8 +110,6 @@ public:
     float animY2;
     float animW;
     float animH;
-    float elementWidth;
-    float elementHeight;
 };
 
 QQuickSpriteSequenceMaterial::QQuickSpriteSequenceMaterial()
@@ -122,8 +120,6 @@ QQuickSpriteSequenceMaterial::QQuickSpriteSequenceMaterial()
     , animY2(0.0f)
     , animW(1.0f)
     , animH(1.0f)
-    , elementWidth(1.0f)
-    , elementHeight(1.0f)
 {
     setFlag(Blending, true);
 }
@@ -156,7 +152,6 @@ public:
         program()->setUniformValue(m_opacity_id, state.opacity());
         program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT);
         program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2);
-        program()->setUniformValue(m_size_id, m->elementWidth, m->elementHeight);
 
         if (state.isMatrixDirty())
             program()->setUniformValue(m_matrix_id, state.combinedMatrix());
@@ -167,7 +162,6 @@ public:
         m_opacity_id = program()->uniformLocation("qt_Opacity");
         m_animData_id = program()->uniformLocation("animData");
         m_animPos_id = program()->uniformLocation("animPos");
-        m_size_id = program()->uniformLocation("size");
     }
 
     virtual const char *vertexShader() const { return vertexShaderCode; }
@@ -175,6 +169,7 @@ public:
 
     virtual char const *const *attributeNames() const {
         static const char *attr[] = {
+           "vPos",
            "vTex",
             0
         };
@@ -185,7 +180,6 @@ public:
     int m_opacity_id;
     int m_animData_id;
     int m_animPos_id;
-    int m_size_id;
 
     static float chunkOfBytes[1024];
 };
@@ -198,6 +192,8 @@ QSGMaterialShader *QQuickSpriteSequenceMaterial::createShader() const
 }
 
 struct SpriteVertex {
+    float x;
+    float y;
     float tx;
     float ty;
 };
@@ -279,6 +275,10 @@ QQuickSpriteSequence::QQuickSpriteSequence(QQuickItem *parent) :
     setFlag(ItemHasContents);
     connect(this, SIGNAL(runningChanged(bool)),
             this, SLOT(update()));
+    connect(this, SIGNAL(widthChanged()),
+            this, SLOT(sizeVertices()));
+    connect(this, SIGNAL(heightChanged()),
+            this, SLOT(sizeVertices()));
 }
 
 void QQuickSpriteSequence::jumpTo(const QString &sprite)
@@ -315,16 +315,36 @@ void QQuickSpriteSequence::createEngine()
 }
 
 static QSGGeometry::Attribute SpriteSequence_Attributes[] = {
-    QSGGeometry::Attribute::create(0, 2, GL_FLOAT),         // tex
+    QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),   // pos
+    QSGGeometry::Attribute::create(1, 2, GL_FLOAT),         // tex
 };
 
 static QSGGeometry::AttributeSet SpriteSequence_AttributeSet =
 {
-    1, // Attribute Count
-    2 * sizeof(float),
+    2, // Attribute Count
+    (2+2) * sizeof(float),
     SpriteSequence_Attributes
 };
 
+void QQuickSpriteSequence::sizeVertices()
+{
+    if (!m_node)
+        return;
+
+    SpriteVertices *p = (SpriteVertices *) m_node->geometry()->vertexData();
+    p->v1.x = 0;
+    p->v1.y = 0;
+
+    p->v2.x = width();
+    p->v2.y = 0;
+
+    p->v3.x = 0;
+    p->v3.y = height();
+
+    p->v4.x = width();
+    p->v4.y = height();
+}
+
 QSGGeometryNode* QQuickSpriteSequence::buildNode()
 {
     if (!m_spriteEngine) {
@@ -355,8 +375,6 @@ QSGGeometryNode* QQuickSpriteSequence::buildNode()
     m_material->animY2 = m_material->animY1;
     m_material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width();
     m_material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height();
-    m_material->elementWidth = width();
-    m_material->elementHeight = height();
     m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name();
     emit currentSpriteChanged(m_curState);
 
@@ -393,6 +411,7 @@ QSGGeometryNode* QQuickSpriteSequence::buildNode()
     m_node->setGeometry(g);
     m_node->setMaterial(m_material);
     m_node->setFlag(QSGGeometryNode::OwnsMaterial);
+    sizeVertices();
     return m_node;
 }
 
@@ -431,8 +450,6 @@ void QQuickSpriteSequence::prepareNextFrame()
 
     uint timeInt = m_timestamp.elapsed();
     qreal time =  timeInt / 1000.;
-    m_material->elementHeight = height();
-    m_material->elementWidth = width();
 
     //Advance State
     m_spriteEngine->updateSprites(timeInt);
index a2f9e41..ce5d92d 100644 (file)
@@ -120,6 +120,8 @@ public slots:
 
 private slots:
     void createEngine();
+    void sizeVertices();
+
 protected:
     void reset();
     QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);