Removing Wayland::SurfacePrivate
[profile/ivi/qtwayland.git] / src / compositor / wayland_wrapper / wlsurface.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the Qt Compositor.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
21 **     the names of its contributors may be used to endorse or promote
22 **     products derived from this software without specific prior written
23 **     permission.
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 #include "wlsurface.h"
42
43 #include "waylandsurface.h"
44
45 #include "wlcompositor.h"
46 #include "wlshmbuffer.h"
47 #include "wlinputdevice.h"
48 #include "wlextendedsurface.h"
49 #include "wlsubsurface.h"
50 #include "wlsurfacebuffer.h"
51
52 #include <QtCore/QDebug>
53 #include <QTouchEvent>
54
55 #include <wayland-server.h>
56
57 #ifdef QT_COMPOSITOR_WAYLAND_GL
58 #include "hardware_integration/graphicshardwareintegration.h"
59 #include <QtGui/QPlatformOpenGLContext>
60 #endif
61
62 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
63 #include "waylandwindowmanagerintegration.h"
64 #endif
65
66 namespace Wayland {
67
68 void destroy_surface(struct wl_resource *resource)
69 {
70     Surface *surface = wayland_cast<Surface *>((wl_surface *)resource);
71     delete surface;
72 }
73
74 Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor)
75     : m_compositor(compositor)
76     , m_waylandSurface(new WaylandSurface(this))
77     , m_surfaceBuffer(0)
78     , m_textureBuffer(0)
79     , m_surfaceMapped(false)
80     , m_extendedSurface(0)
81     , m_subSurface(0)
82     , m_shellSurface(0)
83 {
84     wl_list_init(&m_frame_callback_list);
85     addClientResource(client, &base()->resource, id, &wl_surface_interface,
86             &Surface::surface_interface, destroy_surface);
87 }
88
89 Surface::~Surface()
90 {
91     m_compositor->surfaceDestroyed(this);
92     delete m_waylandSurface;
93 }
94
95 WaylandSurface::Type Surface::type() const
96 {
97     if (m_surfaceBuffer && m_surfaceBuffer->handle()) {
98         if (m_surfaceBuffer && m_surfaceBuffer->isShmBuffer()) {
99             return WaylandSurface::Shm;
100         } else if (m_surfaceBuffer){
101             return WaylandSurface::Texture;
102         }
103     }
104     return WaylandSurface::Invalid;
105 }
106
107 bool Surface::isYInverted() const
108 {
109     bool ret = false;
110     static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt();
111
112 #ifdef QT_COMPOSITOR_WAYLAND_GL
113     if (!m_surfaceBuffer) {
114         ret = false;
115     } else if (m_compositor->graphicsHWIntegration() && m_surfaceBuffer->handle() && type() != WaylandSurface::Shm) {
116         ret = m_compositor->graphicsHWIntegration()->isYInverted(m_surfaceBuffer->handle());
117     } else
118 #endif
119         ret = true;
120
121     return ret != negateReturn;
122 }
123
124 bool Surface::visible() const
125 {
126     return m_surfaceBuffer && m_surfaceBuffer->handle();
127 }
128
129 QImage Surface::image() const
130 {
131     if (type() == WaylandSurface::Shm && m_surfaceBuffer && m_surfaceBuffer->handle()) {
132         ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(m_surfaceBuffer->handle()->user_data);
133         //TODO SHM: m_surfaceBuffer->bufferHandled = true;
134         return shmBuffer->image();
135     }
136     return QImage();
137 }
138
139 QPointF Surface::pos() const
140 {
141     return m_position;
142 }
143
144 void Surface::setPos(const QPointF &pos)
145 {
146     bool emitChange = pos != m_position;
147     m_position = pos;
148     if (emitChange)
149         m_waylandSurface->posChanged();
150 }
151
152 QSize Surface::size() const
153 {
154     return m_size;
155 }
156
157 void Surface::setSize(const QSize &size)
158 {
159     bool emitChange = size != m_size;
160     m_size = size;
161     if (emitChange)
162         m_waylandSurface->sizeChanged();
163 }
164
165 #ifdef QT_COMPOSITOR_WAYLAND_GL
166 GLuint Surface::textureId(QOpenGLContext *context) const
167 {
168     if (!m_surfaceBuffer) {
169         return 0;
170     }
171     if (m_compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture
172          && !m_surfaceBuffer->textureCreated()) {
173         Surface *that = const_cast<Surface *>(this);
174
175         if (m_textureBuffer) {
176             m_textureBuffer->destructBufferState();
177             that->m_textureBuffer = 0;
178         }
179         GraphicsHardwareIntegration *hwIntegration = m_compositor->graphicsHWIntegration();
180         that->m_textureBuffer = m_surfaceBuffer;
181         that->m_textureBuffer->setTexture(hwIntegration->createTextureFromBuffer(m_textureBuffer->handle(), context));
182     }
183     return m_textureBuffer->texture();
184 }
185 #endif // QT_COMPOSITOR_WAYLAND_GL
186
187 WaylandSurface * Surface::waylandSurface() const
188 {
189     return m_waylandSurface;
190 }
191
192 QPoint Surface::lastMousePos() const
193 {
194     return m_lastLocalMousePos;
195 }
196
197 void Surface::setExtendedSurface(ExtendedSurface *extendedSurface)
198 {
199     m_extendedSurface = extendedSurface;
200 }
201
202 ExtendedSurface *Surface::extendedSurface() const
203 {
204     return m_extendedSurface;
205 }
206
207 void Surface::setSubSurface(SubSurface *subSurface)
208 {
209     m_subSurface = subSurface;
210 }
211
212 SubSurface *Surface::subSurface() const
213 {
214     return m_subSurface;
215 }
216
217 void Surface::setShellSurface(ShellSurface *shellSurface)
218 {
219     m_shellSurface = shellSurface;
220 }
221
222 ShellSurface *Surface::shellSurface() const
223 {
224     return m_shellSurface;
225 }
226
227 Compositor *Surface::compositor() const
228 {
229     return m_compositor;
230 }
231
232 void Surface::sendFrameCallback()
233 {
234     frameFinished();
235
236     uint time = Compositor::currentTimeMsecs();
237     struct wl_resource *frame_callback;
238     wl_list_for_each(frame_callback, &m_frame_callback_list, link) {
239         wl_resource_post_event(frame_callback,WL_CALLBACK_DONE,time);
240         wl_resource_destroy(frame_callback,Compositor::currentTimeMsecs());
241     }
242
243     wl_list_init(&m_frame_callback_list);
244 }
245
246 void Surface::frameFinished()
247 {
248     m_compositor->frameFinished(this);
249 }
250
251 void Surface::doUpdate(const QRect &rect) {
252     if (postBuffer()) {
253         m_surfaceBuffer->setPosted();  // disown buffer....
254         if (m_textureBuffer) {
255             m_textureBuffer->destructBufferState();
256             m_textureBuffer = 0;
257         }
258         if (!m_bufferQueue.isEmpty()) {
259             qDebug() << "++++++++++++++++++++++++++++++++++++++++ recursive damage :-)";
260             newCurrentBuffer();
261             doUpdate(rect);
262         }
263     } else {
264         m_compositor->markSurfaceAsDirty(this);
265         emit m_waylandSurface->damaged(rect);
266     }
267 }
268
269 void Surface::newCurrentBuffer() {
270     //TODO release SHM buffer....
271     if (m_surfaceBuffer && m_surfaceBuffer->isPosted()) {
272         m_surfaceBuffer->destructBufferState();
273     } else if (m_surfaceBuffer && !m_surfaceBuffer->isDisplayed()) {
274         qDebug() << "### not skipping undisplayed buffer";
275         return;
276     }
277
278     m_surfaceBuffer = m_bufferQueue.takeFirst();
279
280     int width = 0;
281     int height = 0;
282     if (m_surfaceBuffer) {
283         width = m_surfaceBuffer->width();
284         height = m_surfaceBuffer->height();
285     }
286     setSize(QSize(width,height));
287
288     if (m_surfaceBuffer &&  (!m_subSurface || !m_subSurface->parent()) && !m_surfaceMapped) {
289         emit m_waylandSurface->mapped();
290         m_surfaceMapped = true;
291     } else if (!m_surfaceBuffer && m_surfaceMapped) {
292         emit m_waylandSurface->unmapped();
293         m_surfaceMapped = false;
294     }
295 }
296
297 SurfaceBuffer *Surface::createSurfaceBuffer(struct wl_buffer *buffer)
298 {
299     SurfaceBuffer *newBuffer = 0;
300     for (int i = 0; i < Surface::buffer_pool_size; i++) {
301         if (!m_bufferPool[i].isRegisteredWithBuffer()) {
302             newBuffer = &m_bufferPool[i];
303             newBuffer->initialize(buffer);
304             break;
305         }
306     }
307
308     Q_ASSERT(newBuffer);
309     return newBuffer;
310 }
311
312 void Surface::frameFinishedInternal() {
313     if (m_surfaceBuffer)
314         m_surfaceBuffer->setFinished();
315
316     if (!m_bufferQueue.isEmpty()) {
317         newCurrentBuffer();
318         if (m_surfaceBuffer)
319             doUpdate(m_surfaceBuffer->damageRect());
320     }
321 }
322
323 bool Surface::postBuffer() {
324 #ifdef QT_COMPOSITOR_WAYLAND_GL
325     if (m_compositor->graphicsHWIntegration() && m_waylandSurface->handle() == m_compositor->directRenderSurface()) {
326         //            qDebug() << "posting...." << bufferQueue;
327         if (m_surfaceBuffer && m_surfaceBuffer->handle() && m_compositor->graphicsHWIntegration()->postBuffer(m_surfaceBuffer->handle())) {
328             return true;
329         } else {
330             qDebug() << "could not post buffer";
331         }
332     }
333 #endif
334     return false;
335 }
336
337 void Surface::attach(struct wl_buffer *buffer)
338 {
339     static bool no_serverside_buffer_queue = qgetenv("QT_NO_SERVERSIDE_BUFFER_QUEUE").toInt();
340
341     SurfaceBuffer *newBuffer = 0;
342     if (no_serverside_buffer_queue) {
343         if (m_surfaceBuffer && !m_surfaceBuffer->textureCreated()) {
344             qDebug() << "releasing undisplayed buffer";
345             m_surfaceBuffer->destructBufferState();
346             m_surfaceBuffer = 0;
347         }
348     }
349     if (buffer) {
350         newBuffer = createSurfaceBuffer(buffer);
351     }
352
353     SurfaceBuffer *last = m_bufferQueue.size()?m_bufferQueue.last():0;
354     if (last && !last->damageRect().isValid()) {
355         last->destructBufferState();
356         m_bufferQueue.takeLast();
357     }
358     m_bufferQueue << newBuffer;
359 }
360
361 void Surface::damage(const QRect &rect)
362 {
363     if (!m_bufferQueue.isEmpty() && (!m_surfaceBuffer || m_surfaceBuffer->isFinished() || !m_surfaceBuffer->handle())) {
364             // Handle the "slow" case where we've finished the previous frame before the next damage comes.
365             newCurrentBuffer();
366             doUpdate(rect);
367     } else if (m_bufferQueue.isEmpty()) {
368         // we've receicved a second damage for the same buffer
369         doUpdate(rect);
370     } else {
371         // we're still composing the previous buffer, so just store the damage rect for later
372         SurfaceBuffer *b = m_bufferQueue.last();
373         if (b)
374             b->setDamage(rect);
375         else
376             qWarning() << "Surface::damage() null buffer";
377     }
378 }
379
380 const struct wl_surface_interface Surface::surface_interface = {
381         Surface::surface_destroy,
382         Surface::surface_attach,
383         Surface::surface_damage,
384         Surface::surface_frame
385 };
386
387 void Surface::surface_destroy(struct wl_client *, struct wl_resource *surface_resource)
388 {
389     wl_resource_destroy(surface_resource,Compositor::currentTimeMsecs());
390 }
391
392 void Surface::surface_attach(struct wl_client *client, struct wl_resource *surface,
393                     struct wl_resource *buffer, int x, int y)
394 {
395     Q_UNUSED(client);
396     Q_UNUSED(x);
397     Q_UNUSED(y);
398     reinterpret_cast<Surface *>(surface)->attach(reinterpret_cast<struct wl_buffer *>(buffer));
399 }
400
401 void Surface::surface_damage(struct wl_client *client, struct wl_resource *surface,
402                     int32_t x, int32_t y, int32_t width, int32_t height)
403 {
404     Q_UNUSED(client);
405     reinterpret_cast<Surface *>(surface)->damage(QRect(x, y, width, height));
406 }
407 void Surface::surface_frame(struct wl_client *client,
408                    struct wl_resource *resource,
409                    uint32_t callback)
410 {
411     Surface *surface = reinterpret_cast<Surface *>(resource);
412     struct wl_resource *frame_callback = wl_client_add_object(client,&wl_callback_interface,0,callback,surface);
413     wl_list_insert(&surface->m_frame_callback_list,&frame_callback->link);
414 }
415
416 } // namespace Wayland
417