1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the Declarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qsgspriteimage_p.h"
43 #include "qsgsprite_p.h"
44 #include "qsgspriteengine_p.h"
45 #include <private/qsgcontext_p.h>
46 #include <private/qsgadaptationlayer_p.h>
48 #include <qsgengine.h>
49 #include <qsgtexturematerial.h>
50 #include <qsgtexture.h>
58 class QSGSpriteMaterial : public QSGMaterial
62 virtual ~QSGSpriteMaterial();
63 virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
64 virtual QSGMaterialShader *createShader() const;
65 virtual int compare(const QSGMaterial *other) const
67 return this - static_cast<const QSGSpriteMaterial *>(other);
80 QSGSpriteMaterial::QSGSpriteMaterial()
88 setFlag(Blending, true);
91 QSGSpriteMaterial::~QSGSpriteMaterial()
96 class SpriteMaterialData : public QSGMaterialShader
99 SpriteMaterialData(const char *vertexFile = 0, const char *fragmentFile = 0)
101 QFile vf(vertexFile ? vertexFile : ":defaultshaders/spriteimagevertex.shader");
102 vf.open(QFile::ReadOnly);
103 m_vertex_code = vf.readAll();
105 QFile ff(fragmentFile ? fragmentFile : ":defaultshaders/spriteimagefragment.shader");
106 ff.open(QFile::ReadOnly);
107 m_fragment_code = ff.readAll();
109 Q_ASSERT(!m_vertex_code.isNull());
110 Q_ASSERT(!m_fragment_code.isNull());
114 QSGMaterialShader::deactivate();
116 for (int i=0; i<8; ++i) {
117 program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
121 virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
123 QSGSpriteMaterial *m = static_cast<QSGSpriteMaterial *>(newEffect);
126 program()->setUniformValue(m_opacity_id, state.opacity());
127 program()->setUniformValue(m_timestamp_id, (float) m->timestamp);
128 program()->setUniformValue(m_framecount_id, (float) m->framecount);
129 program()->setUniformValue(m_animcount_id, (float) m->animcount);
130 program()->setUniformValue(m_width_id, (float) m->width);
131 program()->setUniformValue(m_height_id, (float) m->height);
133 if (state.isMatrixDirty())
134 program()->setUniformValue(m_matrix_id, state.combinedMatrix());
137 virtual void initialize() {
138 m_matrix_id = program()->uniformLocation("matrix");
139 m_opacity_id = program()->uniformLocation("opacity");
140 m_timestamp_id = program()->uniformLocation("timestamp");
141 m_framecount_id = program()->uniformLocation("framecount");
142 m_animcount_id = program()->uniformLocation("animcount");
143 m_width_id = program()->uniformLocation("width");
144 m_height_id = program()->uniformLocation("height");
147 virtual const char *vertexShader() const { return m_vertex_code.constData(); }
148 virtual const char *fragmentShader() const { return m_fragment_code.constData(); }
150 virtual char const *const *attributeNames() const {
151 static const char *attr[] = {
159 virtual bool isColorTable() const { return false; }
169 QByteArray m_vertex_code;
170 QByteArray m_fragment_code;
172 static float chunkOfBytes[1024];
174 float SpriteMaterialData::chunkOfBytes[1024];
176 QSGMaterialShader *QSGSpriteMaterial::createShader() const
178 return new SpriteMaterialData;
181 struct SpriteVertex {
190 struct SpriteVertices {
197 QSGSpriteImage::QSGSpriteImage(QSGItem *parent) :
202 , m_pleaseReset(false)
205 setFlag(ItemHasContents);
206 connect(this, SIGNAL(runningChanged(bool)),
207 this, SLOT(update()));
210 QDeclarativeListProperty<QSGSprite> QSGSpriteImage::sprites()
212 return QDeclarativeListProperty<QSGSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear);
215 void QSGSpriteImage::createEngine()
217 //TODO: delay until component complete
219 delete m_spriteEngine;
220 if(m_sprites.count())
221 m_spriteEngine = new QSGSpriteEngine(m_sprites, this);
227 static QSGGeometry::Attribute SpriteImage_Attributes[] = {
228 QSGGeometry::Attribute::create(0, 2, GL_FLOAT), // tex
229 QSGGeometry::Attribute::create(1, 4, GL_FLOAT) // animData
232 static QSGGeometry::AttributeSet SpriteImage_AttributeSet =
234 2, // Attribute Count
235 (4 + 2) * sizeof(float),
236 SpriteImage_Attributes
239 QSGGeometryNode* QSGSpriteImage::buildNode()
241 if (!m_spriteEngine) {
242 qWarning() << "SpriteImage: No sprite engine...";
251 m_material = new QSGSpriteMaterial();
253 QImage image = m_spriteEngine->assembledImage();
256 m_material->texture = sceneGraphEngine()->createTextureFromImage(image);
257 m_material->texture->setFiltering(QSGTexture::Linear);
258 m_material->framecount = m_spriteEngine->maxFrames();
262 QSGGeometry *g = new QSGGeometry(SpriteImage_AttributeSet, vCount, iCount);
263 g->setDrawingMode(GL_TRIANGLES);
265 SpriteVertices *p = (SpriteVertices *) g->vertexData();
266 m_spriteEngine->start(0);
267 p->v1.animT = p->v2.animT = p->v3.animT = p->v4.animT = 0;
268 p->v1.animIdx = p->v2.animIdx = p->v3.animIdx = p->v4.animIdx = 0;
269 p->v1.frameCount = p->v2.frameCount = p->v3.frameCount = p->v4.frameCount = m_spriteEngine->spriteFrames();
270 p->v1.frameDuration = p->v2.frameDuration = p->v3.frameDuration = p->v4.frameDuration = m_spriteEngine->spriteDuration();
284 quint16 *indices = g->indexDataAsUShort();
294 m_node = new QSGGeometryNode();
295 m_node->setGeometry(g);
296 m_node->setMaterial(m_material);
300 void QSGSpriteImage::reset()
302 m_pleaseReset = true;
305 QSGNode *QSGSpriteImage::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
313 m_pleaseReset = false;
321 m_node->markDirty(QSGNode::DirtyMaterial);
327 void QSGSpriteImage::prepareNextFrame()
330 m_node = buildNode();
331 if (m_node == 0) //error creating node
334 uint timeInt = m_timestamp.elapsed();
335 qreal time = timeInt / 1000.;
336 m_material->timestamp = time;
337 m_material->animcount = m_spriteEngine->spriteCount();
338 m_material->height = height();
339 m_material->width = width();
342 SpriteVertices *p = (SpriteVertices *) m_node->geometry()->vertexData();
343 m_spriteEngine->updateSprites(timeInt);
344 int curIdx = m_spriteEngine->spriteState();
345 if(curIdx != p->v1.animIdx){
346 p->v1.animIdx = p->v2.animIdx = p->v3.animIdx = p->v4.animIdx = curIdx;
347 p->v1.animT = p->v2.animT = p->v3.animT = p->v4.animT = m_spriteEngine->spriteStart()/1000.0;
348 p->v1.frameCount = p->v2.frameCount = p->v3.frameCount = p->v4.frameCount = m_spriteEngine->spriteFrames();
349 p->v1.frameDuration = p->v2.frameDuration = p->v3.frameDuration = p->v4.frameDuration = m_spriteEngine->spriteDuration();