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