diff options
Diffstat (limited to 'src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp')
-rw-r--r-- | src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp | 310 |
1 files changed, 106 insertions, 204 deletions
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp index 1229d286f..f48dd3400 100644 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp +++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp @@ -3,36 +3,32 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the Qt Compositor. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -40,9 +36,6 @@ #include "qwlsurfacebuffer_p.h" -#include "qwlsurface_p.h" -#include "qwlcompositor_p.h" - #ifdef QT_COMPOSITOR_WAYLAND_GL #include "hardware_integration/qwlclientbufferintegration_p.h" #include <qpa/qplatformopenglcontext.h> @@ -53,11 +46,13 @@ #include <wayland-server-protocol.h> #include "qwaylandshmformathelper.h" +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> + QT_BEGIN_NAMESPACE namespace QtWayland { -SurfaceBuffer::SurfaceBuffer(Surface *surface) +SurfaceBuffer::SurfaceBuffer(QWaylandSurface *surface) : m_surface(surface) , m_compositor(surface->compositor()) , m_buffer(0) @@ -66,14 +61,8 @@ SurfaceBuffer::SurfaceBuffer(Surface *surface) , m_surface_has_buffer(false) , m_destroyed(false) , m_is_displayed(false) - , m_texture(0) - , m_is_shm_resolved(false) - , m_shmBuffer(0) - , m_isSizeResolved(false) - , m_size() , m_used(false) , m_destroyIfUnused(false) - , m_image(0) { } @@ -86,81 +75,30 @@ SurfaceBuffer::~SurfaceBuffer() void SurfaceBuffer::initialize(struct ::wl_resource *buffer) { m_buffer = buffer; - m_texture = 0; m_committed = false; m_is_registered_for_buffer = true; m_surface_has_buffer = true; m_is_displayed = false; m_destroyed = false; - m_handle = 0; - m_is_shm_resolved = false; - m_shmBuffer = 0; - m_isSizeResolved = false; - m_size = QSize(); m_destroy_listener.surfaceBuffer = this; m_destroy_listener.listener.notify = destroy_listener_callback; if (buffer) { - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - hwIntegration->unlockNativeBuffer(m_handle); - hwIntegration->initialize(buffer); + if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) + integration->initializeBuffer(buffer); wl_signal_add(&buffer->destroy_signal, &m_destroy_listener.listener); } } void SurfaceBuffer::destructBufferState() { - destroyTexture(); if (m_buffer) { sendRelease(); - - if (m_handle) { - if (m_shmBuffer) { - delete static_cast<QImage *>(m_handle); -#ifdef QT_COMPOSITOR_WAYLAND_GL - } else { - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - hwIntegration->unlockNativeBuffer(m_handle); -#endif - } - } wl_list_remove(&m_destroy_listener.listener.link); } m_buffer = 0; - m_handle = 0; m_committed = false; m_is_registered_for_buffer = false; m_is_displayed = false; - m_image = QImage(); -} - -QSize SurfaceBuffer::size() const -{ - if (!m_isSizeResolved) { - if (isShmBuffer()) { - m_size = QSize(wl_shm_buffer_get_width(m_shmBuffer), wl_shm_buffer_get_height(m_shmBuffer)); -#ifdef QT_COMPOSITOR_WAYLAND_GL - } else { - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - m_size = hwIntegration->bufferSize(m_buffer); -#endif - } - } - - return m_size; -} - -bool SurfaceBuffer::isShmBuffer() const -{ - if (!m_is_shm_resolved) { -#if (WAYLAND_VERSION_MAJOR >= 1) && (WAYLAND_VERSION_MINOR >= 2) - m_shmBuffer = wl_shm_buffer_get(m_buffer); -#else - if (wl_buffer_is_shm(static_cast<struct ::wl_buffer*>(m_buffer->data))) - m_shmBuffer = static_cast<struct ::wl_buffer*>(m_buffer->data); -#endif - m_is_shm_resolved = true; - } - return m_shmBuffer != 0; } void SurfaceBuffer::sendRelease() @@ -181,156 +119,120 @@ void SurfaceBuffer::setDisplayed() m_is_displayed = true; } -void SurfaceBuffer::destroyTexture() -{ -#ifdef QT_COMPOSITOR_WAYLAND_GL - if (m_texture) { - Q_ASSERT(QOpenGLContext::currentContext()); - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - if (hwIntegration->textureForBuffer(m_buffer) == 0) - glDeleteTextures(1, &m_texture); - else - hwIntegration->destroyTextureForBuffer(m_buffer, m_texture); - m_texture = 0; - } -#endif -} - -uint SurfaceBuffer::textureTarget() const +void SurfaceBuffer::destroy_listener_callback(wl_listener *listener, void *data) { -#ifdef QT_COMPOSITOR_WAYLAND_GL - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - return hwIntegration->textureTargetForBuffer(m_buffer); -#endif + Q_UNUSED(data); + struct surface_buffer_destroy_listener *destroy_listener = + reinterpret_cast<struct surface_buffer_destroy_listener *>(listener); + SurfaceBuffer *d = destroy_listener->surfaceBuffer; - return 0; + // Mark the buffer as destroyed and clear m_buffer right away to avoid + // touching it before it is properly cleaned up. + d->m_destroyed = true; + d->m_buffer = 0; } -void SurfaceBuffer::handleAboutToBeDisplayed() +void SurfaceBuffer::ref() { - qDebug() << Q_FUNC_INFO; + m_used = m_refCount.ref(); } -void SurfaceBuffer::handleDisplayed() +void SurfaceBuffer::deref() { - qDebug() << Q_FUNC_INFO; + m_used = m_refCount.deref(); + if (!m_used) + disown(); } -void *SurfaceBuffer::handle() const +void SurfaceBuffer::setDestroyIfUnused(bool destroy) { - if (!m_buffer) - return 0; - - if (!m_handle) { - SurfaceBuffer *that = const_cast<SurfaceBuffer *>(this); - if (isShmBuffer()) { - const uchar *data = static_cast<const uchar *>(wl_shm_buffer_get_data(m_shmBuffer)); - int stride = wl_shm_buffer_get_stride(m_shmBuffer); - int width = wl_shm_buffer_get_width(m_shmBuffer); - int height = wl_shm_buffer_get_height(m_shmBuffer); - QImage *image = new QImage(data,width,height,stride, QImage::Format_ARGB32_Premultiplied); - that->m_handle = image; -#ifdef QT_COMPOSITOR_WAYLAND_GL - } else { - ClientBufferIntegration *clientBufferIntegration = m_compositor->clientBufferIntegration(); - that->m_handle = clientBufferIntegration->lockNativeBuffer(m_buffer); -#endif - } - } - return m_handle; + m_destroyIfUnused = destroy; + destroyIfUnused(); } -QImage SurfaceBuffer::image() +void SurfaceBuffer::destroyIfUnused() { - /* This api may be available on non-shm buffer. But be sure about it's format. */ - if (!m_buffer || !isShmBuffer()) - return QImage(); - - if (m_image.isNull()) - { - const uchar *data = static_cast<const uchar *>(wl_shm_buffer_get_data(m_shmBuffer)); - int stride = wl_shm_buffer_get_stride(m_shmBuffer); - int width = wl_shm_buffer_get_width(m_shmBuffer); - int height = wl_shm_buffer_get_height(m_shmBuffer); - QImage::Format format = QWaylandShmFormatHelper::fromWaylandShmFormat(wl_shm_format(wl_shm_buffer_get_format(m_shmBuffer))); - m_image = QImage(data, width, height, stride, format); - } - - return m_image; + if (!m_used && m_destroyIfUnused) + delete this; } -void SurfaceBuffer::destroy_listener_callback(wl_listener *listener, void *data) +QSize SurfaceBuffer::size() const { - Q_UNUSED(data); - struct surface_buffer_destroy_listener *destroy_listener = - reinterpret_cast<struct surface_buffer_destroy_listener *>(listener); - SurfaceBuffer *d = destroy_listener->surfaceBuffer; - - // Mark the buffer as destroyed and clear m_buffer right away to avoid - // touching it before it is properly cleaned up. - d->m_destroyed = true; - d->m_buffer = 0; -} + if (!m_buffer) + return QSize(); -void SurfaceBuffer::createTexture() -{ - destroyTexture(); + if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) { + int width = wl_shm_buffer_get_width(shmBuffer); + int height = wl_shm_buffer_get_height(shmBuffer); + return QSize(width, height); + } + if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) { + return integration->bufferSize(m_buffer); + } - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); -#ifdef QT_COMPOSITOR_WAYLAND_GL - m_texture = hwIntegration->textureForBuffer(m_buffer); - hwIntegration->bindTextureToBuffer(m_buffer); -#else - Q_UNUSED(hwIntegration); -#endif + return QSize(); } -void SurfaceBuffer::updateTexture() +QWaylandSurface::Origin SurfaceBuffer::origin() const { -#ifdef QT_COMPOSITOR_WAYLAND_GL - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - hwIntegration->updateTextureForBuffer(m_buffer); -#endif + if (isShm()) { + return QWaylandSurface::OriginTopLeft; + } + + if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) { + return integration->origin(m_buffer); + } + return QWaylandSurface::OriginTopLeft; } -bool SurfaceBuffer::isYInverted() const +QImage SurfaceBuffer::image() const { - bool ret = false; - static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt(); - ClientBufferIntegration *clientBufferIntegration = m_compositor->clientBufferIntegration(); - -#ifdef QT_COMPOSITOR_WAYLAND_GL - if (clientBufferIntegration && waylandBufferHandle() && !isShmBuffer()) { - ret = clientBufferIntegration->isYInverted(waylandBufferHandle()); - } else -#endif - ret = true; + if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) { + int width = wl_shm_buffer_get_width(shmBuffer); + int height = wl_shm_buffer_get_height(shmBuffer); + int bytesPerLine = wl_shm_buffer_get_stride(shmBuffer); + uchar *data = static_cast<uchar *>(wl_shm_buffer_get_data(shmBuffer)); + return QImage(data, width, height, bytesPerLine, QImage::Format_ARGB32_Premultiplied); + } - return ret != negateReturn; + return QImage(); } -void SurfaceBuffer::ref() +void SurfaceBuffer::bindToTexture() const { - m_used = m_refCount.ref(); + Q_ASSERT(m_compositor); + if (isShm()) { + QImage image = this->image(); + if (image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGBA8888) { + image = image.convertToFormat(QImage::Format_RGBA8888); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits()); + } else { + if (image.format() != QImage::Format_RGBX8888) { + image = image.convertToFormat(QImage::Format_RGBX8888); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); + } + } else { + if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) { + clientInt->bindTextureToBuffer(m_buffer); + } + } } -void SurfaceBuffer::deref() +int SurfaceBuffer::textureTarget() const { - m_used = m_refCount.deref(); - if (!m_used) - disown(); -} + if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) + return clientInt->textureTargetForBuffer(m_buffer); -void SurfaceBuffer::setDestroyIfUnused(bool destroy) -{ - m_destroyIfUnused = destroy; - destroyIfUnused(); + return 0; } -void SurfaceBuffer::destroyIfUnused() +void SurfaceBuffer::updateTexture() const { - if (!m_used && m_destroyIfUnused) - delete this; + if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) + clientInt->updateTextureForBuffer(m_buffer); } } |