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"
52 #include <QtCore/QDebug>
53 #include <QTouchEvent>
55 #include <wayland-server.h>
57 #ifdef QT_COMPOSITOR_WAYLAND_GL
58 #include "hardware_integration/graphicshardwareintegration.h"
59 #include <QtGui/QPlatformOpenGLContext>
62 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
63 #include "waylandwindowmanagerintegration.h"
68 void destroy_surface(struct wl_resource *resource)
70 Surface *surface = wayland_cast<Surface *>((wl_surface *)resource);
74 Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor)
75 : m_compositor(compositor)
76 , m_waylandSurface(new WaylandSurface(this))
79 , m_surfaceMapped(false)
80 , m_extendedSurface(0)
84 wl_list_init(&m_frame_callback_list);
85 addClientResource(client, &base()->resource, id, &wl_surface_interface,
86 &Surface::surface_interface, destroy_surface);
91 m_compositor->surfaceDestroyed(this);
92 delete m_waylandSurface;
95 WaylandSurface::Type Surface::type() const
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;
104 return WaylandSurface::Invalid;
107 bool Surface::isYInverted() const
110 static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt();
112 #ifdef QT_COMPOSITOR_WAYLAND_GL
113 if (!m_surfaceBuffer) {
115 } else if (m_compositor->graphicsHWIntegration() && m_surfaceBuffer->handle() && type() != WaylandSurface::Shm) {
116 ret = m_compositor->graphicsHWIntegration()->isYInverted(m_surfaceBuffer->handle());
121 return ret != negateReturn;
124 bool Surface::visible() const
126 return m_surfaceBuffer && m_surfaceBuffer->handle();
129 QImage Surface::image() const
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();
139 QPointF Surface::pos() const
144 void Surface::setPos(const QPointF &pos)
146 bool emitChange = pos != m_position;
149 m_waylandSurface->posChanged();
152 QSize Surface::size() const
157 void Surface::setSize(const QSize &size)
159 bool emitChange = size != m_size;
162 m_waylandSurface->sizeChanged();
165 #ifdef QT_COMPOSITOR_WAYLAND_GL
166 GLuint Surface::textureId(QOpenGLContext *context) const
168 if (!m_surfaceBuffer) {
171 if (m_compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture
172 && !m_surfaceBuffer->textureCreated()) {
173 Surface *that = const_cast<Surface *>(this);
175 if (m_textureBuffer) {
176 m_textureBuffer->destructBufferState();
177 that->m_textureBuffer = 0;
179 GraphicsHardwareIntegration *hwIntegration = m_compositor->graphicsHWIntegration();
180 that->m_textureBuffer = m_surfaceBuffer;
181 that->m_textureBuffer->setTexture(hwIntegration->createTextureFromBuffer(m_textureBuffer->handle(), context));
183 return m_textureBuffer->texture();
185 #endif // QT_COMPOSITOR_WAYLAND_GL
187 WaylandSurface * Surface::waylandSurface() const
189 return m_waylandSurface;
192 QPoint Surface::lastMousePos() const
194 return m_lastLocalMousePos;
197 void Surface::setExtendedSurface(ExtendedSurface *extendedSurface)
199 m_extendedSurface = extendedSurface;
202 ExtendedSurface *Surface::extendedSurface() const
204 return m_extendedSurface;
207 void Surface::setSubSurface(SubSurface *subSurface)
209 m_subSurface = subSurface;
212 SubSurface *Surface::subSurface() const
217 void Surface::setShellSurface(ShellSurface *shellSurface)
219 m_shellSurface = shellSurface;
222 ShellSurface *Surface::shellSurface() const
224 return m_shellSurface;
227 Compositor *Surface::compositor() const
232 void Surface::sendFrameCallback()
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());
243 wl_list_init(&m_frame_callback_list);
246 void Surface::frameFinished()
248 m_compositor->frameFinished(this);
251 void Surface::doUpdate(const QRect &rect) {
253 m_surfaceBuffer->setPosted(); // disown buffer....
254 if (m_textureBuffer) {
255 m_textureBuffer->destructBufferState();
258 if (!m_bufferQueue.isEmpty()) {
259 qDebug() << "++++++++++++++++++++++++++++++++++++++++ recursive damage :-)";
264 m_compositor->markSurfaceAsDirty(this);
265 emit m_waylandSurface->damaged(rect);
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";
278 m_surfaceBuffer = m_bufferQueue.takeFirst();
282 if (m_surfaceBuffer) {
283 width = m_surfaceBuffer->width();
284 height = m_surfaceBuffer->height();
286 setSize(QSize(width,height));
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;
297 SurfaceBuffer *Surface::createSurfaceBuffer(struct wl_buffer *buffer)
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);
312 void Surface::frameFinishedInternal() {
314 m_surfaceBuffer->setFinished();
316 if (!m_bufferQueue.isEmpty()) {
319 doUpdate(m_surfaceBuffer->damageRect());
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())) {
330 qDebug() << "could not post buffer";
337 void Surface::attach(struct wl_buffer *buffer)
339 static bool no_serverside_buffer_queue = qgetenv("QT_NO_SERVERSIDE_BUFFER_QUEUE").toInt();
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();
350 newBuffer = createSurfaceBuffer(buffer);
353 SurfaceBuffer *last = m_bufferQueue.size()?m_bufferQueue.last():0;
354 if (last && !last->damageRect().isValid()) {
355 last->destructBufferState();
356 m_bufferQueue.takeLast();
358 m_bufferQueue << newBuffer;
361 void Surface::damage(const QRect &rect)
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.
367 } else if (m_bufferQueue.isEmpty()) {
368 // we've receicved a second damage for the same buffer
371 // we're still composing the previous buffer, so just store the damage rect for later
372 SurfaceBuffer *b = m_bufferQueue.last();
376 qWarning() << "Surface::damage() null buffer";
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
387 void Surface::surface_destroy(struct wl_client *, struct wl_resource *surface_resource)
389 wl_resource_destroy(surface_resource,Compositor::currentTimeMsecs());
392 void Surface::surface_attach(struct wl_client *client, struct wl_resource *surface,
393 struct wl_resource *buffer, int x, int y)
398 reinterpret_cast<Surface *>(surface)->attach(reinterpret_cast<struct wl_buffer *>(buffer));
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)
405 reinterpret_cast<Surface *>(surface)->damage(QRect(x, y, width, height));
407 void Surface::surface_frame(struct wl_client *client,
408 struct wl_resource *resource,
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);
416 } // namespace Wayland