Compositor memory leak fixes
[profile/ivi/qtwayland.git] / src / compositor / wayland_wrapper / wlcompositor.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 "wlcompositor.h"
42
43 #include "waylandinput.h"
44 #include "wldisplay.h"
45 #include "wlshmbuffer.h"
46 #include "wlsurface.h"
47 #include "waylandcompositor.h"
48 #include "wldatadevicemanager.h"
49 #include "wldatadevice.h"
50 #include "wlextendedoutput.h"
51 #include "wlextendedsurface.h"
52 #include "wlsubsurface.h"
53 #include "wlshellsurface.h"
54 #include "wltouch.h"
55 #include "wlinputdevice.h"
56
57 #include <QWindow>
58 #include <QSocketNotifier>
59 #include <QDebug>
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <stddef.h>
65 #include <errno.h>
66 #include <fcntl.h>
67 #include <unistd.h>
68
69 #include <sys/mman.h>
70 #include <sys/select.h>
71 #include <sys/time.h>
72
73 #include <wayland-server.h>
74
75 #include "hardware_integration/graphicshardwareintegration.h"
76 #include "waylandwindowmanagerintegration.h"
77
78 namespace Wayland {
79
80 static Compositor *compositor;
81
82 void compositor_create_surface(struct wl_client *client,
83                                struct wl_resource *resource, uint32_t id)
84 {
85      static_cast<Compositor *>(resource->data)->createSurface(client,id);
86 }
87
88 const static struct wl_compositor_interface compositor_interface = {
89     compositor_create_surface
90 };
91
92 void Compositor::bind_func(struct wl_client *client, void *data,
93                       uint32_t version, uint32_t id)
94 {
95     Q_UNUSED(version);
96     wl_client_add_object(client,&wl_compositor_interface, &compositor_interface, id,data);
97 }
98
99
100 Compositor *Compositor::instance()
101 {
102     return compositor;
103 }
104
105 Compositor::Compositor(WaylandCompositor *qt_compositor)
106     : m_display(new Display)
107     , m_default_input_device(0)
108     , m_shm(m_display)
109     , m_current_frame(0)
110     , m_last_queued_buf(-1)
111     , m_qt_compositor(qt_compositor)
112     , m_orientation(Qt::PrimaryOrientation)
113     , m_directRenderSurface(0)
114 #if defined (QT_COMPOSITOR_WAYLAND_GL)
115     , m_graphics_hw_integration(0)
116 #endif
117     , m_outputExtension(0)
118     , m_surfaceExtension(0)
119     , m_subSurfaceExtension(0)
120     , m_touchExtension(0)
121     , m_retainNotify(0)
122 {
123     compositor = this;
124     qDebug() << "Compositor instance is" << this;
125
126 #if defined (QT_COMPOSITOR_WAYLAND_GL)
127     QWindow *window = qt_compositor->window();
128     if (window && window->surfaceType() != QWindow::RasterSurface)
129         m_graphics_hw_integration = GraphicsHardwareIntegration::createGraphicsHardwareIntegration(qt_compositor);
130 #endif
131     m_windowManagerIntegration = new WindowManagerServerIntegration(this);
132
133     wl_display_add_global(m_display->handle(),&wl_compositor_interface,this,Compositor::bind_func);
134
135     m_data_device_manager =  new DataDeviceManager(this);
136
137     wl_display_add_global(m_display->handle(),&wl_output_interface, &m_output_global,OutputGlobal::output_bind_func);
138
139     m_shell = new Shell();
140     wl_display_add_global(m_display->handle(), &wl_shell_interface, m_shell, Shell::bind_func);
141
142     m_outputExtension = new OutputExtensionGlobal(this);
143     m_surfaceExtension = new SurfaceExtensionGlobal(this);
144
145     if (wl_display_add_socket(m_display->handle(), qt_compositor->socketName())) {
146         fprintf(stderr, "Fatal: Failed to open server socket\n");
147         exit(EXIT_FAILURE);
148     }
149
150     m_loop = wl_display_get_event_loop(m_display->handle());
151
152     int fd = wl_event_loop_get_fd(m_loop);
153
154     QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, this);
155     connect(sockNot, SIGNAL(activated(int)), this, SLOT(processWaylandEvents()));
156
157     //initialize distancefieldglyphcache here
158 }
159
160 Compositor::~Compositor()
161 {
162     delete m_shell;
163     delete m_outputExtension;
164     delete m_surfaceExtension;
165     delete m_subSurfaceExtension;
166     delete m_touchExtension;
167
168     delete m_default_wayland_input_device;
169     delete m_data_device_manager;
170
171 #ifdef QT_COMPOSITOR_WAYLAND_GL
172     delete m_graphics_hw_integration;
173 #endif
174
175     delete m_display;
176 }
177
178 void Compositor::frameFinished(Surface *surface)
179 {
180     if (surface && m_dirty_surfaces.contains(surface)) {
181         m_dirty_surfaces.remove(surface);
182         surface->sendFrameCallback();
183     } else if (!surface) {
184         QSet<Surface *> dirty = m_dirty_surfaces;
185         m_dirty_surfaces.clear();
186         foreach (Surface *surface, dirty)
187             surface->sendFrameCallback();
188     }
189 }
190
191 void Compositor::createSurface(struct wl_client *client, uint32_t id)
192 {
193     Surface *surface = new Surface(client,id, this);
194     printf("Compositor::createSurface: %p %d\n", client, id);
195
196     m_surfaces << surface;
197
198     m_qt_compositor->surfaceCreated(surface->waylandSurface());
199 }
200
201 struct wl_client *Compositor::getClientFromWinId(uint winId) const
202 {
203     Surface *surface = getSurfaceFromWinId(winId);
204     if (surface)
205         return surface->base()->resource.client;
206
207     return 0;
208 }
209
210 Surface *Compositor::getSurfaceFromWinId(uint winId) const
211 {
212     foreach (Surface *surface, m_surfaces) {
213         if (surface->id() == winId)
214             return surface;
215     }
216
217     return 0;
218 }
219
220 QImage Compositor::image(uint winId) const
221 {
222     printf("Compositor::image(%x)\n", winId);
223     foreach (Surface *surface, m_surfaces) {
224         if (surface->id() == winId) {
225             return surface->image();
226         }
227     }
228
229     return QImage();
230 }
231
232 uint Compositor::currentTimeMsecs()
233 {
234     //### we throw away the time information
235     struct timeval tv;
236     int ret = gettimeofday(&tv, 0);
237     if (ret == 0)
238         return tv.tv_sec*1000 + tv.tv_usec/1000;
239     return 0;
240 }
241
242 void Compositor::releaseBuffer(void *bufferHandle)
243 {
244     struct wl_buffer *buffer = static_cast<struct wl_buffer*>(bufferHandle);
245     if (buffer) {
246         //qDebug() << "WL_BUFFER_RELEASE" << buffer<< buffer->resource.client;
247         wl_resource_post_event(&buffer->resource, WL_BUFFER_RELEASE);
248     }
249
250 }
251
252 void Compositor::processWaylandEvents()
253 {
254     int ret = wl_event_loop_dispatch(m_loop, 0);
255     if (ret)
256         fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret);
257 }
258
259 void Compositor::surfaceDestroyed(Surface *surface)
260 {
261     if (defaultInputDevice()->mouseFocus() == surface)
262         defaultInputDevice()->setMouseFocus(0, QPoint(), QPoint());
263     m_surfaces.removeOne(surface);
264     m_dirty_surfaces.remove(surface);
265     if (m_directRenderSurface == surface)
266         setDirectRenderSurface(0);
267     waylandCompositor()->surfaceAboutToBeDestroyed(surface->waylandSurface());
268 }
269
270 void Compositor::markSurfaceAsDirty(Wayland::Surface *surface)
271 {
272     m_dirty_surfaces.insert(surface);
273 }
274
275 void Compositor::destroyClientForSurface(Surface *surface)
276 {
277     wl_client *client = surface->base()->resource.client;
278
279     if (client) {
280         m_windowManagerIntegration->removeClient(client);
281         wl_client_destroy(client);
282     }
283 }
284
285 QWindow *Compositor::window() const
286 {
287     return m_qt_compositor->window();
288 }
289
290 GraphicsHardwareIntegration * Compositor::graphicsHWIntegration() const
291 {
292 #ifdef QT_COMPOSITOR_WAYLAND_GL
293     return m_graphics_hw_integration;
294 #else
295     return 0;
296 #endif
297 }
298
299 void Compositor::initializeHardwareIntegration()
300 {
301 #ifdef QT_COMPOSITOR_WAYLAND_GL
302     if (m_graphics_hw_integration)
303         m_graphics_hw_integration->initializeHardware(m_display);
304 #endif
305 }
306
307 void Compositor::initializeDefaultInputDevice()
308 {
309     m_default_wayland_input_device = new WaylandInputDevice(m_qt_compositor);
310     m_default_input_device = m_default_wayland_input_device->handle();
311 }
312
313 void Compositor::initializeWindowManagerProtocol()
314 {
315     m_windowManagerIntegration->initialize(m_display);
316 }
317
318 void Compositor::enableSubSurfaceExtension()
319 {
320     if (!m_subSurfaceExtension) {
321         m_subSurfaceExtension = new SubSurfaceExtensionGlobal(this);
322     }
323 }
324
325 bool Compositor::setDirectRenderSurface(Surface *surface)
326 {
327 #ifdef QT_COMPOSITOR_WAYLAND_GL
328     if (m_graphics_hw_integration && m_graphics_hw_integration->setDirectRenderSurface(surface ? surface->waylandSurface() : 0)) {
329         m_directRenderSurface = surface;
330         return true;
331     }
332 #else
333     Q_UNUSED(surface);
334 #endif
335     return false;
336 }
337
338 QList<struct wl_client *> Compositor::clients() const
339 {
340     QList<struct wl_client *> list;
341     foreach (Surface *surface, m_surfaces) {
342         struct wl_client *client = surface->base()->resource.client;
343         if (!list.contains(client))
344             list.append(client);
345     }
346     return list;
347 }
348
349 void Compositor::setScreenOrientation(Qt::ScreenOrientation orientation)
350 {
351     m_orientation = orientation;
352
353     QList<struct wl_client*> clientList = clients();
354     for (int i = 0; i < clientList.length(); ++i) {
355         struct wl_client *client = clientList.at(i);
356         Output *output = m_output_global.outputForClient(client);
357         Q_ASSERT(output);
358         if (output->extendedOutput()){
359             output->extendedOutput()->sendOutputOrientation(orientation);
360         }
361     }
362 }
363
364 Qt::ScreenOrientation Compositor::screenOrientation() const
365 {
366     return m_orientation;
367 }
368
369 void Compositor::setOutputGeometry(const QRect &geometry)
370 {
371     m_output_global.setGeometry(geometry);
372 }
373
374 QRect Compositor::outputGeometry() const
375 {
376     return m_output_global.geometry();
377 }
378
379 InputDevice* Compositor::defaultInputDevice()
380 {
381     return m_default_input_device;
382 }
383
384 QList<Wayland::Surface *> Compositor::surfacesForClient(wl_client *client)
385 {
386     QList<Wayland::Surface *> ret;
387
388     for (int i=0; i < m_surfaces.count(); ++i) {
389         if (m_surfaces.at(i)->base()->resource.client == client) {
390             ret.append(m_surfaces.at(i));
391         }
392     }
393     return ret;
394 }
395
396 void Compositor::enableTouchExtension()
397 {
398     if (!m_touchExtension) {
399         m_touchExtension = new TouchExtensionGlobal(this);
400     }
401 }
402
403 void Compositor::configureTouchExtension(int flags)
404 {
405     if (m_touchExtension)
406         m_touchExtension->setFlags(flags);
407 }
408
409 void Compositor::setRetainedSelectionWatcher(RetainedSelectionFunc func, void *param)
410 {
411     m_retainNotify = func;
412     m_retainNotifyParam = param;
413 }
414
415 bool Compositor::wantsRetainedSelection() const
416 {
417     return m_retainNotify != 0;
418 }
419
420 void Compositor::feedRetainedSelectionData(QMimeData *data)
421 {
422     if (m_retainNotify) {
423         m_retainNotify(data, m_retainNotifyParam);
424     }
425 }
426
427 void Compositor::overrideSelection(QMimeData *data)
428 {
429     m_data_device_manager->overrideSelection(*data);
430 }
431
432 bool Compositor::isDragging() const
433 {
434     return false;
435 }
436
437 void Compositor::sendDragMoveEvent(const QPoint &global, const QPoint &local,
438                                             Surface *surface)
439 {
440     Q_UNUSED(global);
441     Q_UNUSED(local);
442     Q_UNUSED(surface);
443 //    Drag::instance()->dragMove(global, local, surface);
444 }
445
446 void Compositor::sendDragEndEvent()
447 {
448 //    Drag::instance()->dragEnd();
449 }
450
451 } // namespace Wayland