1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the Qt Compositor.
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
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
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
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."
39 ****************************************************************************/
41 #include "wlsurface.h"
43 #include "waylandsurface.h"
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 #include "wlshellsurface.h"
53 #include <QtCore/QDebug>
54 #include <QTouchEvent>
56 #include <wayland-server.h>
58 #ifdef QT_COMPOSITOR_WAYLAND_GL
59 #include "hardware_integration/graphicshardwareintegration.h"
60 #include <QtGui/QPlatformOpenGLContext>
63 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
64 #include "waylandwindowmanagerintegration.h"
69 void destroy_surface(struct wl_resource *resource)
71 Surface *surface = wayland_cast<Surface *>((wl_surface *)resource);
72 surface->compositor()->surfaceDestroyed(surface);
76 Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor)
77 : m_compositor(compositor)
78 , m_waylandSurface(new WaylandSurface(this))
81 , m_surfaceMapped(false)
82 , m_extendedSurface(0)
86 wl_list_init(&m_frame_callback_list);
87 addClientResource(client, &base()->resource, id, &wl_surface_interface,
88 &Surface::surface_interface, destroy_surface);
93 delete m_waylandSurface;
94 delete m_extendedSurface;
96 delete m_shellSurface;
99 WaylandSurface::Type Surface::type() const
101 if (m_surfaceBuffer && m_surfaceBuffer->handle()) {
102 if (m_surfaceBuffer && m_surfaceBuffer->isShmBuffer()) {
103 return WaylandSurface::Shm;
104 } else if (m_surfaceBuffer){
105 return WaylandSurface::Texture;
108 return WaylandSurface::Invalid;
111 bool Surface::isYInverted() const
114 static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt();
116 #ifdef QT_COMPOSITOR_WAYLAND_GL
117 if (!m_surfaceBuffer) {
119 } else if (m_compositor->graphicsHWIntegration() && m_surfaceBuffer->handle() && type() != WaylandSurface::Shm) {
120 ret = m_compositor->graphicsHWIntegration()->isYInverted(m_surfaceBuffer->handle());
125 return ret != negateReturn;
128 bool Surface::visible() const
130 return m_surfaceBuffer && m_surfaceBuffer->handle();
133 QImage Surface::image() const
135 if (type() == WaylandSurface::Shm && m_surfaceBuffer && m_surfaceBuffer->handle()) {
136 ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(m_surfaceBuffer->handle()->user_data);
137 //TODO SHM: m_surfaceBuffer->bufferHandled = true;
138 return shmBuffer->image();
143 QPointF Surface::pos() const
148 void Surface::setPos(const QPointF &pos)
150 bool emitChange = pos != m_position;
153 m_waylandSurface->posChanged();
156 QSize Surface::size() const
161 void Surface::setSize(const QSize &size)
163 bool emitChange = size != m_size;
166 m_waylandSurface->sizeChanged();
169 #ifdef QT_COMPOSITOR_WAYLAND_GL
170 GLuint Surface::textureId(QOpenGLContext *context) const
172 if (!m_surfaceBuffer) {
175 if (m_compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture
176 && !m_surfaceBuffer->textureCreated()) {
177 Surface *that = const_cast<Surface *>(this);
179 if (m_textureBuffer) {
180 m_textureBuffer->destructBufferState();
181 that->m_textureBuffer = 0;
183 GraphicsHardwareIntegration *hwIntegration = m_compositor->graphicsHWIntegration();
184 that->m_textureBuffer = m_surfaceBuffer;
185 that->m_textureBuffer->setTexture(hwIntegration->createTextureFromBuffer(m_textureBuffer->handle(), context));
187 return m_textureBuffer->texture();
189 #endif // QT_COMPOSITOR_WAYLAND_GL
191 WaylandSurface * Surface::waylandSurface() const
193 return m_waylandSurface;
196 QPoint Surface::lastMousePos() const
198 return m_lastLocalMousePos;
201 void Surface::setExtendedSurface(ExtendedSurface *extendedSurface)
203 m_extendedSurface = extendedSurface;
206 ExtendedSurface *Surface::extendedSurface() const
208 return m_extendedSurface;
211 void Surface::setSubSurface(SubSurface *subSurface)
213 m_subSurface = subSurface;
216 SubSurface *Surface::subSurface() const
221 void Surface::setShellSurface(ShellSurface *shellSurface)
223 m_shellSurface = shellSurface;
226 ShellSurface *Surface::shellSurface() const
228 return m_shellSurface;
231 Compositor *Surface::compositor() const
236 void Surface::sendFrameCallback()
240 uint time = Compositor::currentTimeMsecs();
241 struct wl_resource *frame_callback;
242 wl_list_for_each(frame_callback, &m_frame_callback_list, link) {
243 wl_resource_post_event(frame_callback,WL_CALLBACK_DONE,time);
244 wl_resource_destroy(frame_callback,Compositor::currentTimeMsecs());
247 wl_list_init(&m_frame_callback_list);
250 void Surface::frameFinished()
252 m_compositor->frameFinished(this);
255 void Surface::doUpdate(const QRect &rect) {
257 m_surfaceBuffer->setPosted(); // disown buffer....
258 if (m_textureBuffer) {
259 m_textureBuffer->destructBufferState();
262 if (!m_bufferQueue.isEmpty()) {
263 qDebug() << "++++++++++++++++++++++++++++++++++++++++ recursive damage :-)";
268 m_compositor->markSurfaceAsDirty(this);
269 emit m_waylandSurface->damaged(rect);
273 void Surface::newCurrentBuffer() {
274 //TODO release SHM buffer....
275 if (m_surfaceBuffer && m_surfaceBuffer->isPosted()) {
276 m_surfaceBuffer->destructBufferState();
277 } else if (m_surfaceBuffer && !m_surfaceBuffer->isDisplayed()) {
278 qDebug() << "### not skipping undisplayed buffer";
282 m_surfaceBuffer = m_bufferQueue.takeFirst();
286 if (m_surfaceBuffer) {
287 width = m_surfaceBuffer->width();
288 height = m_surfaceBuffer->height();
290 setSize(QSize(width,height));
292 if (m_surfaceBuffer && (!m_subSurface || !m_subSurface->parent()) && !m_surfaceMapped) {
293 emit m_waylandSurface->mapped();
294 m_surfaceMapped = true;
295 } else if (!m_surfaceBuffer && m_surfaceMapped) {
296 emit m_waylandSurface->unmapped();
297 m_surfaceMapped = false;
301 SurfaceBuffer *Surface::createSurfaceBuffer(struct wl_buffer *buffer)
303 SurfaceBuffer *newBuffer = 0;
304 for (int i = 0; i < Surface::buffer_pool_size; i++) {
305 if (!m_bufferPool[i].isRegisteredWithBuffer()) {
306 newBuffer = &m_bufferPool[i];
307 newBuffer->initialize(buffer);
316 void Surface::frameFinishedInternal() {
318 m_surfaceBuffer->setFinished();
320 if (!m_bufferQueue.isEmpty()) {
323 doUpdate(m_surfaceBuffer->damageRect());
327 bool Surface::postBuffer() {
328 #ifdef QT_COMPOSITOR_WAYLAND_GL
329 if (m_compositor->graphicsHWIntegration() && m_waylandSurface->handle() == m_compositor->directRenderSurface()) {
330 // qDebug() << "posting...." << bufferQueue;
331 if (m_surfaceBuffer && m_surfaceBuffer->handle() && m_compositor->graphicsHWIntegration()->postBuffer(m_surfaceBuffer->handle())) {
334 qDebug() << "could not post buffer";
341 void Surface::attach(struct wl_buffer *buffer)
343 static bool no_serverside_buffer_queue = qgetenv("QT_NO_SERVERSIDE_BUFFER_QUEUE").toInt();
345 SurfaceBuffer *newBuffer = 0;
346 if (no_serverside_buffer_queue) {
347 if (m_surfaceBuffer && !m_surfaceBuffer->textureCreated()) {
348 qDebug() << "releasing undisplayed buffer";
349 m_surfaceBuffer->destructBufferState();
354 newBuffer = createSurfaceBuffer(buffer);
357 SurfaceBuffer *last = m_bufferQueue.size()?m_bufferQueue.last():0;
358 if (last && !last->damageRect().isValid()) {
359 last->destructBufferState();
360 m_bufferQueue.takeLast();
362 m_bufferQueue << newBuffer;
365 void Surface::damage(const QRect &rect)
367 if (!m_bufferQueue.isEmpty() && (!m_surfaceBuffer || m_surfaceBuffer->isFinished() || !m_surfaceBuffer->handle())) {
368 // Handle the "slow" case where we've finished the previous frame before the next damage comes.
371 } else if (m_bufferQueue.isEmpty()) {
372 // we've receicved a second damage for the same buffer
375 // we're still composing the previous buffer, so just store the damage rect for later
376 SurfaceBuffer *b = m_bufferQueue.last();
380 qWarning() << "Surface::damage() null buffer";
384 const struct wl_surface_interface Surface::surface_interface = {
385 Surface::surface_destroy,
386 Surface::surface_attach,
387 Surface::surface_damage,
388 Surface::surface_frame
391 void Surface::surface_destroy(struct wl_client *, struct wl_resource *surface_resource)
393 wl_resource_destroy(surface_resource,Compositor::currentTimeMsecs());
396 void Surface::surface_attach(struct wl_client *client, struct wl_resource *surface,
397 struct wl_resource *buffer, int x, int y)
402 reinterpret_cast<Surface *>(surface)->attach(reinterpret_cast<struct wl_buffer *>(buffer));
405 void Surface::surface_damage(struct wl_client *client, struct wl_resource *surface,
406 int32_t x, int32_t y, int32_t width, int32_t height)
409 reinterpret_cast<Surface *>(surface)->damage(QRect(x, y, width, height));
411 void Surface::surface_frame(struct wl_client *client,
412 struct wl_resource *resource,
415 Surface *surface = reinterpret_cast<Surface *>(resource);
416 struct wl_resource *frame_callback = wl_client_add_object(client,&wl_callback_interface,0,callback,surface);
417 wl_list_insert(&surface->m_frame_callback_list,&frame_callback->link);
420 } // namespace Wayland