~ubuntu-branches/ubuntu/vivid/sflphone/vivid

« back to all changes in this revision

Viewing changes to kde/src/widgets/acceleratedvideowidget.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2013-06-30 11:40:56 UTC
  • mfrom: (4.1.18 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130630114056-0np50jkyqo6vnmii
Tags: 1.2.3-2
* changeset_r92d62cfc54732bbbcfff2b1d36c096b120b981a5.diff 
  - fixes automatic endian detection 
* Update Vcs: fixes vcs-field-not-canonical

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2009-2013 by Savoir-Faire Linux                         *
 
3
 *   Author : Emmanuel Lepage Valle <emmanuel.lepage@savoirfairelinux.com >*
 
4
 *            Nokia                                                        *
 
5
 *                                                                         *
 
6
 *   This program is free software; you can redistribute it and/or modify  *
 
7
 *   it under the terms of the GNU General Public License as published by  *
 
8
 *   the Free Software Foundation; either version 3 of the License, or     *
 
9
 *   (at your option) any later version.                                   *
 
10
 *                                                                         *
 
11
 *   This program is distributed in the hope that it will be useful,       *
 
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
14
 *   GNU General Public License for more details.                          *
 
15
 *                                                                         *
 
16
 *   You should have received a copy of the GNU General Public License     *
 
17
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 
18
 **************************************************************************/
 
19
#include "acceleratedvideowidget.h"
 
20
#include <QPixmap>
 
21
#include <KDebug>
 
22
#include "../lib/videomodel.h"
 
23
#include "../lib/videorenderer.h"
 
24
 
 
25
 
 
26
 
 
27
#include <QtGui/QImage>
 
28
 #include <QtCore/QPropertyAnimation>
 
29
 
 
30
static const qreal FACE_SIZE    = 0.4;
 
31
 
 
32
static const qreal speeds[]     = { 1.8f, 2.4f, 3.6f };
 
33
static const qreal amplitudes[] = { 2.0f, 2.5f, 3.0f };
 
34
 
 
35
static inline void qSetColor(float colorVec[], QColor c)
 
36
{
 
37
   colorVec[0] = c.redF();
 
38
   colorVec[1] = c.greenF();
 
39
   colorVec[2] = c.blueF();
 
40
   colorVec[3] = c.alphaF();
 
41
}
 
42
 
 
43
int Geometry::append(const QVector3D &a, const QVector3D &n, const QVector2D &t)
 
44
{
 
45
   int v = vertices.count();
 
46
   vertices.append(a);
 
47
   normals.append(n);
 
48
   texCoords.append(t);
 
49
   faces.append(v);
 
50
   colors.append(QVector4D(0.6f, 0.6f, 0.6f, 1.0f));
 
51
   return v;
 
52
}
 
53
 
 
54
void Geometry::addQuad(const QVector3D &a, const QVector3D &b,
 
55
                           const QVector3D &c, const QVector3D &d,
 
56
                           const QVector<QVector2D> &tex)
 
57
{
 
58
   QVector3D norm = QVector3D::normal(a, b, c);
 
59
   // append first triangle
 
60
   int aref = append(a, norm, tex[0]);
 
61
   append(b, norm, tex[1]);
 
62
   int cref = append(c, norm, tex[2]);
 
63
   // append second triangle
 
64
   faces.append(aref);
 
65
   faces.append(cref);
 
66
   append(d, norm, tex[3]);
 
67
}
 
68
 
 
69
void Geometry::loadArrays() const
 
70
{
 
71
   glEnableClientState(GL_VERTEX_ARRAY);
 
72
   glEnableClientState(GL_NORMAL_ARRAY);
 
73
   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
74
   glEnableClientState(GL_COLOR_ARRAY);
 
75
   glVertexPointer(3, GL_FLOAT, 0, vertices.constData());
 
76
   glNormalPointer(GL_FLOAT, 0, normals.constData());
 
77
   glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData());
 
78
   glColorPointer(4, GL_FLOAT, 0, colors.constData());
 
79
}
 
80
 
 
81
void Geometry::setColors(int start, GLfloat colorArray[4][4])
 
82
{
 
83
   int off = faces[start];
 
84
   for (int i = 0; i < 4; ++i)
 
85
      colors[i + off] = QVector4D(colorArray[i][0],
 
86
                                    colorArray[i][1],
 
87
                                    colorArray[i][2],
 
88
                                    colorArray[i][3]);
 
89
}
 
90
 
 
91
Tile::Tile(const QVector3D &loc)
 
92
   : location(loc)
 
93
   , start(0)
 
94
   , count(0)
 
95
   , useFlatColor(false)
 
96
   , geom(0)
 
97
{
 
98
   qSetColor(faceColor, QColor(Qt::darkGray));
 
99
}
 
100
 
 
101
void Tile::setColors(GLfloat colorArray[4][4])
 
102
{
 
103
   useFlatColor = true;
 
104
   geom->setColors(start, colorArray);
 
105
}
 
106
 
 
107
static inline void qMultMatrix(const QMatrix4x4 &mat)
 
108
{
 
109
   if (sizeof(qreal) == sizeof(GLfloat))
 
110
      glMultMatrixf((GLfloat*)mat.constData());
 
111
#ifndef QT_OPENGL_ES
 
112
   else if (sizeof(qreal) == sizeof(GLdouble))
 
113
      glMultMatrixd((GLdouble*)mat.constData());
 
114
#endif
 
115
   else
 
116
   {
 
117
      GLfloat fmat[16];
 
118
      qreal const *r = mat.constData();
 
119
      for (int i = 0; i < 16; ++i)
 
120
            fmat[i] = r[i];
 
121
      glMultMatrixf(fmat);
 
122
   }
 
123
}
 
124
 
 
125
void Tile::draw() const
 
126
{
 
127
   QMatrix4x4 mat;
 
128
   mat.translate(location);
 
129
   mat.rotate(orientation);
 
130
   glMatrixMode(GL_MODELVIEW);
 
131
   glPushMatrix();
 
132
   qMultMatrix(mat);
 
133
   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, faceColor);
 
134
   glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, geom->indices() + start);
 
135
   glPopMatrix();
 
136
}
 
137
 
 
138
TileBuilder::TileBuilder(Geometry *g, qreal depth, qreal size)
 
139
   : verts(4)
 
140
   , tex(4)
 
141
   , start(g->count())
 
142
   , count(0)
 
143
   , geom(g)
 
144
{
 
145
   // front face - make a square with bottom-left at origin
 
146
   verts[br].setX(size);
 
147
   verts[tr].setX(size);
 
148
   verts[tr].setY(size);
 
149
   verts[tl].setY(size);
 
150
 
 
151
   // these vert numbers are good for the tex-coords
 
152
   for (int i = 0; i < 4; ++i)
 
153
      tex[i] = verts[i].toVector2D();
 
154
 
 
155
   // now move verts half cube width across so cube is centered on origin
 
156
   for (int i = 0; i < 4; ++i)
 
157
      verts[i] -= QVector3D(size / 2.0f, size / 2.0f, -depth);
 
158
 
 
159
   // add the front face
 
160
   g->addQuad(verts[bl], verts[br], verts[tr], verts[tl], tex);
 
161
 
 
162
   count = g->count() - start;
 
163
}
 
164
 
 
165
void TileBuilder::initialize(Tile *tile) const
 
166
{
 
167
   tile->start = start;
 
168
   tile->count = count;
 
169
   tile->geom = geom;
 
170
   qSetColor(tile->faceColor, color);
 
171
}
 
172
 
 
173
Tile *TileBuilder::newTile(const QVector3D &loc) const
 
174
{
 
175
   Tile *tile = new Tile(loc);
 
176
   initialize(tile);
 
177
   return tile;
 
178
}
 
179
 
 
180
Cube::Cube(const QVector3D &loc)
 
181
   : Tile(loc)
 
182
   , rot(0.0f)
 
183
   , r(0), a(0),rtn(0)
 
184
{
 
185
}
 
186
 
 
187
Cube::~Cube()
 
188
{
 
189
}
 
190
 
 
191
void Cube::setAltitude(qreal a)
 
192
{
 
193
   if (location.y() != a)
 
194
   {
 
195
      location.setY(a);
 
196
      emit changed();
 
197
   }
 
198
}
 
199
 
 
200
void Cube::setRange(qreal r)
 
201
{
 
202
   if (location.x() != r)
 
203
   {
 
204
      location.setX(r);
 
205
      emit changed();
 
206
   }
 
207
}
 
208
 
 
209
void Cube::setRotation(qreal r)
 
210
{
 
211
   if (r != rot)
 
212
   {
 
213
      orientation = QQuaternion::fromAxisAndAngle(QVector3D(1.0f, 1.0f, 1.0f), r);
 
214
      emit changed();
 
215
   }
 
216
}
 
217
 
 
218
void Cube::removeBounce()
 
219
{
 
220
   delete a;
 
221
   a = 0;
 
222
   delete r;
 
223
   r = 0;
 
224
}
 
225
 
 
226
void Cube::startAnimation()
 
227
{
 
228
   if (r)
 
229
   {
 
230
      r->start();
 
231
      r->setCurrentTime(startx);
 
232
   }
 
233
   if (a)
 
234
      a->start();
 
235
   if (rtn)
 
236
      rtn->start();
 
237
}
 
238
 
 
239
void Cube::setAnimationPaused(bool paused)
 
240
{
 
241
   if (paused)
 
242
   {
 
243
      if (r)
 
244
            r->pause();
 
245
      if (a)
 
246
            a->pause();
 
247
      if (rtn)
 
248
            rtn->pause();
 
249
   }
 
250
   else
 
251
   {
 
252
      if (r)
 
253
            r->resume();
 
254
      if (a)
 
255
            a->resume();
 
256
      if (rtn)
 
257
            rtn->resume();
 
258
   }
 
259
}
 
260
 
 
261
CubeBuilder::CubeBuilder(Geometry *g, qreal depth, qreal size)
 
262
   : TileBuilder(g, depth)
 
263
   , ix(0)
 
264
{
 
265
   for (int i = 0; i < 4; ++i)
 
266
      verts[i].setZ(size / 2.0f);
 
267
   // back face - "extrude" verts down
 
268
   QVector<QVector3D> back(verts);
 
269
   for (int i = 0; i < 4; ++i)
 
270
      back[i].setZ(-size / 2.0f);
 
271
 
 
272
   // add the back face
 
273
   g->addQuad(back[br], back[bl], back[tl], back[tr], tex);
 
274
 
 
275
   // add the sides
 
276
   g->addQuad(back[bl], back[br], verts[br], verts[bl], tex);
 
277
   g->addQuad(back[br], back[tr], verts[tr], verts[br], tex);
 
278
   g->addQuad(back[tr], back[tl], verts[tl], verts[tr], tex);
 
279
   g->addQuad(back[tl], back[bl], verts[bl], verts[tl], tex);
 
280
 
 
281
   count = g->count() - start;
 
282
}
 
283
 
 
284
Cube *CubeBuilder::newCube(const QVector3D &loc) const
 
285
{
 
286
   Cube *c = new Cube(loc);
 
287
   initialize(c);
 
288
   qreal d = 4000.0f;
 
289
   qreal d3 = d / 3.0f;
 
290
   // Animate movement from left to right
 
291
   c->r = new QPropertyAnimation(c, "range");
 
292
   c->r->setStartValue(-1.3f);
 
293
   c->r->setEndValue(1.3f);
 
294
   c->startx = ix * d3 * 3.0f;
 
295
   c->r->setDuration(d * 4.0f);
 
296
   c->r->setLoopCount(-1);
 
297
   c->r->setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
 
298
   // Animate movement from bottom to top
 
299
   c->a = new QPropertyAnimation(c, "altitude");
 
300
   c->a->setEndValue(loc.y());
 
301
   c->a->setStartValue(loc.y() + amplitudes[ix]);
 
302
   c->a->setDuration(d / speeds[ix]);
 
303
   c->a->setLoopCount(-1);
 
304
   c->a->setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
 
305
   // Animate rotation
 
306
   c->rtn = new QPropertyAnimation(c, "rotation");
 
307
   c->rtn->setStartValue(c->rot);
 
308
   c->rtn->setEndValue(359.0f);
 
309
   c->rtn->setDuration(d * 2.0f);
 
310
   c->rtn->setLoopCount(-1);
 
311
   c->rtn->setDuration(d / 2);
 
312
   ix = (ix + 1) % 3;
 
313
   return c;
 
314
}
 
315
 
 
316
 
 
317
void AcceleratedVideoWidget::newFrameEvent()
 
318
{
 
319
   qDebug() << "New frame event";
 
320
   QSize size(VideoModel::getInstance()->getRenderer()->getActiveResolution().width, VideoModel::getInstance()->getRenderer()->getActiveResolution().height);
 
321
   m_Image = QImage((uchar*)VideoModel::getInstance()->getRenderer()->rawData() , size.width(), size.height(), QImage::Format_ARGB32 );
 
322
   paintGL();
 
323
}
 
324
 
 
325
static GLfloat colorArray[][4] = {
 
326
     {0.243f , 0.423f , 0.125f , 1.0f},
 
327
     {0.176f , 0.31f  , 0.09f  , 1.0f},
 
328
     {0.4f   , 0.69f  , 0.212f , 1.0f},
 
329
     {0.317f , 0.553f , 0.161f , 1.0f}
 
330
 };
 
331
 
 
332
 AcceleratedVideoWidget::AcceleratedVideoWidget(QWidget *parent)
 
333
     : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
 
334
     , geom(0)
 
335
     , cube(0)
 
336
 {
 
337
     // create the pbuffer
 
338
     QGLFormat pbufferFormat = format();
 
339
     pbufferFormat.setSampleBuffers(false);
 
340
     pbuffer = new QGLPixelBuffer(QSize(512, 512), pbufferFormat, this);
 
341
     setWindowTitle(tr("OpenGL pbuffers"));
 
342
     initializeGeometry();
 
343
     connect(VideoModel::getInstance(),SIGNAL(frameUpdated()),this,SLOT(newFrameEvent()));
 
344
 }
 
345
 
 
346
 AcceleratedVideoWidget::~AcceleratedVideoWidget()
 
347
 {
 
348
     pbuffer->releaseFromDynamicTexture();
 
349
     glDeleteTextures(1, &dynamicTexture);
 
350
     delete pbuffer;
 
351
 
 
352
     qDeleteAll(cubes);
 
353
     qDeleteAll(tiles);
 
354
     delete cube;
 
355
 }
 
356
 
 
357
 void AcceleratedVideoWidget::initializeGL()
 
358
 {
 
359
     initCommon();
 
360
     glShadeModel(GL_SMOOTH);
 
361
     glEnable(GL_LIGHTING);
 
362
     glEnable(GL_LIGHT0);
 
363
     static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
 
364
     glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
 
365
     initPbuffer();
 
366
     cube->startAnimation();
 
367
     connect(cube, SIGNAL(changed()), this, SLOT(update()));
 
368
     for (int i = 0; i < 3; ++i)
 
369
     {
 
370
         cubes[i]->startAnimation();
 
371
         connect(cubes[i], SIGNAL(changed()), this, SLOT(update()));
 
372
     }
 
373
 }
 
374
 
 
375
 void AcceleratedVideoWidget::paintGL()
 
376
 {
 
377
   QSize size(VideoModel::getInstance()->getRenderer()->getActiveResolution().width, VideoModel::getInstance()->getRenderer()->getActiveResolution().height);
 
378
   if (size != minimumSize())
 
379
      setMinimumSize(size);
 
380
   
 
381
   pbuffer->makeCurrent();
 
382
   drawPbuffer();
 
383
   // On direct render platforms, drawing onto the pbuffer context above
 
384
   // automatically updates the dynamic texture.  For cases where rendering
 
385
   // directly to a texture is not supported, explicitly copy.
 
386
   if (!hasDynamicTextureUpdate)
 
387
      pbuffer->updateDynamicTexture(dynamicTexture);
 
388
   makeCurrent();
 
389
 
 
390
   // Use the pbuffer as a texture to render the scene
 
391
   glBindTexture(GL_TEXTURE_2D, dynamicTexture);
 
392
 
 
393
   // set up to render the scene
 
394
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
395
   glLoadIdentity();
 
396
   glTranslatef(0.0f, 0.0f, -10.0f);
 
397
 
 
398
   // draw the background
 
399
   glPushMatrix();
 
400
   glScalef(aspect, 1.0f, 1.0f);
 
401
   for (int i = 0; i < tiles.count(); ++i)
 
402
      tiles[i]->draw();
 
403
   glPopMatrix();
 
404
 
 
405
   // draw the bouncing cubes
 
406
   for (int i = 0; i < cubes.count(); ++i)
 
407
      cubes[i]->draw();
 
408
 }
 
409
 
 
410
 void AcceleratedVideoWidget::initializeGeometry()
 
411
 {
 
412
     geom = new Geometry();
 
413
     CubeBuilder cBuilder(geom, 0.5);
 
414
     cBuilder.setColor(QColor(255, 255, 255, 212));
 
415
     // build the 3 bouncing, spinning cubes
 
416
     for (int i = 0; i < 3; ++i)
 
417
         cubes.append(cBuilder.newCube(QVector3D((float)(i-1), -1.5f, 5 - i)));
 
418
 
 
419
     // build the spinning cube which goes in the dynamic texture
 
420
     cube = cBuilder.newCube();
 
421
     cube->removeBounce();
 
422
 
 
423
     // build the background tiles
 
424
     TileBuilder tBuilder(geom);
 
425
     tBuilder.setColor(QColor(Qt::white));
 
426
     for (int c = -2; c <= +2; ++c)
 
427
         for (int r = -2; r <= +2; ++r)
 
428
             tiles.append(tBuilder.newTile(QVector3D(c, r, 0)));
 
429
 
 
430
     // graded backdrop for the pbuffer scene
 
431
     TileBuilder bBuilder(geom, 0.0f, 2.0f);
 
432
     bBuilder.setColor(QColor(102, 176, 54, 210));
 
433
     backdrop = bBuilder.newTile(QVector3D(0.0f, 0.0f, -1.5f));
 
434
     backdrop->setColors(colorArray);
 
435
 }
 
436
 
 
437
 void AcceleratedVideoWidget::initCommon()
 
438
 {
 
439
     qglClearColor(QColor(Qt::darkGray));
 
440
 
 
441
     glEnable(GL_DEPTH_TEST);
 
442
     glEnable(GL_CULL_FACE);
 
443
     glEnable(GL_MULTISAMPLE);
 
444
 
 
445
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
446
     glEnable(GL_BLEND);
 
447
 
 
448
     glEnable(GL_TEXTURE_2D);
 
449
 
 
450
     geom->loadArrays();
 
451
 }
 
452
 
 
453
 void AcceleratedVideoWidget::perspectiveProjection()
 
454
 {
 
455
     glMatrixMode(GL_PROJECTION);
 
456
     glLoadIdentity();
 
457
 #ifdef QT_OPENGL_ES
 
458
     glFrustumf(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0);
 
459
 #else
 
460
     glFrustum(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0);
 
461
 #endif
 
462
     glMatrixMode(GL_MODELVIEW);
 
463
 }
 
464
 
 
465
 void AcceleratedVideoWidget::orthographicProjection()
 
466
 {
 
467
     glMatrixMode(GL_PROJECTION);
 
468
     glLoadIdentity();
 
469
 #ifdef QT_OPENGL_ES
 
470
     glOrthof(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0);
 
471
 #else
 
472
     glOrtho(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0);
 
473
 #endif
 
474
     glMatrixMode(GL_MODELVIEW);
 
475
 }
 
476
 
 
477
 void AcceleratedVideoWidget::resizeGL(int width, int height)
 
478
 {
 
479
     glViewport(0, 0, width, height);
 
480
     aspect = (qreal)width / (qreal)(height ? height : 1);
 
481
     perspectiveProjection();
 
482
 }
 
483
 
 
484
void AcceleratedVideoWidget::drawPbuffer()
 
485
{
 
486
   cubeTexture = bindTexture(m_Image);
 
487
   //initPbuffer();
 
488
    
 
489
   orthographicProjection();
 
490
 
 
491
   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 
492
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
493
 
 
494
   glDisable(GL_TEXTURE_2D);
 
495
   backdrop->draw();
 
496
   glEnable(GL_TEXTURE_2D);
 
497
 
 
498
   glBindTexture(GL_TEXTURE_2D, cubeTexture);
 
499
   glDisable(GL_CULL_FACE);
 
500
   cube->draw();
 
501
   glEnable(GL_CULL_FACE);
 
502
 
 
503
   glFlush();
 
504
}
 
505
 
 
506
 void AcceleratedVideoWidget::initPbuffer()
 
507
 {
 
508
     pbuffer->makeCurrent();
 
509
 
 
510
//      cubeTexture = bindTexture(QImage("/home/lepagee/ccu_12.png"));
 
511
     cubeTexture = bindTexture(m_Image);
 
512
 
 
513
     initCommon();
 
514
 
 
515
     // generate a texture that has the same size/format as the pbuffer
 
516
     dynamicTexture = pbuffer->generateDynamicTexture();
 
517
 
 
518
     // bind the dynamic texture to the pbuffer - this is a no-op under X11
 
519
     hasDynamicTextureUpdate = pbuffer->bindToDynamicTexture(dynamicTexture);
 
520
     makeCurrent();
 
521
 }
 
522
 
 
523
 void AcceleratedVideoWidget::setAnimationPaused(bool enable)
 
524
 {
 
525
     cube->setAnimationPaused(enable);
 
526
     for (int i = 0; i < 3; ++i)
 
527
         cubes[i]->setAnimationPaused(enable);
 
528
 }