1 /*
2     Copyright (C) 2012-2013 Collabora Ltd. <info@collabora.com>
3       @author George Kiagiadakis <george.kiagiadakis@collabora.com>
4 
5     This library is free software; you can redistribute it and/or modify
6     it under the terms of the GNU Lesser General Public License as published
7     by the Free Software Foundation; either version 2.1 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "videoitem.h"
20 #include "videosurface_p.h"
21 #include <QtQuick/QSGNode>
22 #include <QtQuick/QSGFlatColorMaterial>
23 #include "../../QGlib/Signal"
24 
25 namespace QGst {
26 namespace Quick {
27 
28 struct VideoItem::Private
29 {
30     QPointer<VideoSurface> surface;
31     bool surfaceDirty;
32     QRectF targetArea;
33 };
34 
VideoItem(QQuickItem * parent)35 VideoItem::VideoItem(QQuickItem *parent)
36     : QQuickItem(parent), d(new Private)
37 {
38     d->surfaceDirty = true;
39     setFlag(QQuickItem::ItemHasContents, true);
40 }
41 
~VideoItem()42 VideoItem::~VideoItem()
43 {
44     setSurface(0);
45     delete d;
46 }
47 
surface() const48 VideoSurface *VideoItem::surface() const
49 {
50     return d->surface.data();
51 }
52 
setSurface(VideoSurface * surface)53 void VideoItem::setSurface(VideoSurface *surface)
54 {
55     if (d->surface) {
56         d->surface.data()->d->items.remove(this);
57     }
58 
59     d->surface = surface;
60     d->surfaceDirty = true;
61 
62     if (d->surface) {
63         d->surface.data()->d->items.insert(this);
64     }
65 }
66 
updatePaintNode(QSGNode * oldNode,UpdatePaintNodeData * data)67 QSGNode* VideoItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
68 {
69     Q_UNUSED(data)
70 
71     QRectF r = boundingRect();
72     QSGNode *newNode = 0;
73 
74     if (d->surfaceDirty) {
75         delete oldNode;
76         oldNode = 0;
77         d->surfaceDirty = false;
78     }
79 
80     if (!d->surface || d->surface.data()->d->videoSink.isNull()) {
81         if (!oldNode) {
82             QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
83             material->setColor(Qt::black);
84 
85             QSGGeometryNode *node = new QSGGeometryNode;
86             node->setMaterial(material);
87             node->setFlag(QSGNode::OwnsMaterial);
88             node->setFlag(QSGNode::OwnsGeometry);
89 
90             newNode = node;
91             d->targetArea = QRectF(); //force geometry to be set
92         } else {
93             newNode = oldNode;
94         }
95 
96         if (r != d->targetArea) {
97             QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
98             geometry->vertexDataAsPoint2D()[0].set(r.x(), r.y());
99             geometry->vertexDataAsPoint2D()[1].set(r.x(), r.height());
100             geometry->vertexDataAsPoint2D()[2].set(r.width(), r.y());
101             geometry->vertexDataAsPoint2D()[3].set(r.width(), r.height());
102 
103             QSGGeometryNode *node = static_cast<QSGGeometryNode*>(newNode);
104             node->setGeometry(geometry);
105 
106             d->targetArea = r;
107         }
108     } else {
109         newNode = (QSGNode*) QGlib::emit<void*>(d->surface.data()->d->videoSink,
110                 "update-node", (void*)oldNode,
111                 r.x(), r.y(), r.width(), r.height());
112     }
113 
114     return newNode;
115 }
116 
117 } // namespace Quick
118 } // namespace QGst
119