Introducing QPlatformGraphicsBuffer
Change-Id: Idcf8f75bd151a877c7097b79df998c1ffd56871c Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
This commit is contained in:
parent
517fb90268
commit
37956e6605
@ -71,7 +71,9 @@ HEADERS += \
|
||||
kernel/qpixelformat.h \
|
||||
kernel/qpaintdevicewindow.h \
|
||||
kernel/qpaintdevicewindow_p.h \
|
||||
kernel/qrasterwindow.h
|
||||
kernel/qrasterwindow.h \
|
||||
kernel/qplatformgraphicsbuffer.h \
|
||||
kernel/qplatformgraphicsbufferhelper.h
|
||||
|
||||
SOURCES += \
|
||||
kernel/qgenericpluginfactory.cpp \
|
||||
@ -124,7 +126,9 @@ SOURCES += \
|
||||
kernel/qplatformmenu.cpp \
|
||||
kernel/qpixelformat.cpp \
|
||||
kernel/qpaintdevicewindow.cpp \
|
||||
kernel/qrasterwindow.cpp
|
||||
kernel/qrasterwindow.cpp \
|
||||
kernel/qplatformgraphicsbuffer.cpp \
|
||||
kernel/qplatformgraphicsbufferhelper.cpp
|
||||
|
||||
contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) {
|
||||
HEADERS += \
|
||||
|
277
src/gui/kernel/qplatformgraphicsbuffer.cpp
Normal file
277
src/gui/kernel/qplatformgraphicsbuffer.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 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 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qplatformgraphicsbuffer.h"
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QOpenGLFunctions>
|
||||
#include <QtGui/qopengl.h>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
/*!
|
||||
\class QPlatformGraphicsBuffer
|
||||
\inmodule QtGui
|
||||
\since 5.5
|
||||
\brief The QPlatformGraphicsBuffer is a windowsystem abstraction for native graphics buffers
|
||||
|
||||
Different platforms have different ways of representing graphics buffers. On
|
||||
some platforms, it is possible to create one graphics buffer that you can bind
|
||||
to a texture and also get main memory access to the image bits. On the
|
||||
other hand, on some platforms all graphics buffer abstraction is completely
|
||||
hidden.
|
||||
|
||||
QPlatformGraphicsBuffer is an abstraction of a single Graphics Buffer.
|
||||
|
||||
There is no public constructor nor any public factory function.
|
||||
|
||||
QPlatformGraphicsBuffer is intended to be created by using platform specific
|
||||
APIs available from QtPlatformHeaders, or there might be accessor functions
|
||||
similar to the accessor function that QPlatformBackingstore has.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QPlatformGraphicsBuffer::AccessType
|
||||
|
||||
This enum describes the access that is desired or granted for the graphics
|
||||
buffer.
|
||||
|
||||
\value None
|
||||
\value SWReadAccess
|
||||
\value SWWriteAccess
|
||||
\value TextureAccess
|
||||
\value HWCompositor
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QPlatformGraphicsBuffer::Origin
|
||||
|
||||
This enum describes the origin of the content of the buffer.
|
||||
|
||||
\value OriginTopLeft
|
||||
\value OriginBottomLeft
|
||||
*/
|
||||
|
||||
/*!
|
||||
Protected constructor to initialize the private members.
|
||||
|
||||
\a size is the size of the buffer.
|
||||
\a format is the format of the buffer.
|
||||
|
||||
\sa size() format()
|
||||
*/
|
||||
QPlatformGraphicsBuffer::QPlatformGraphicsBuffer(const QSize &size, const QPixelFormat &format)
|
||||
: m_size(size)
|
||||
, m_format(format)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Virtual destructor.
|
||||
*/
|
||||
QPlatformGraphicsBuffer::~QPlatformGraphicsBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Binds the content of this graphics buffer into the currently bound texture.
|
||||
|
||||
This function should fail for buffers not capable of locking to TextureAccess.
|
||||
|
||||
\a rect is the subrect which is desired to be bounded to the texture. This
|
||||
argument has a no less than semantic, meaning more (if not all) of the buffer
|
||||
can be bounded to the texture. An empty QRect is interpreted as entire buffer
|
||||
should be bound.
|
||||
|
||||
This function only supports binding buffers to the GL_TEXTURE_2D texture
|
||||
target.
|
||||
|
||||
Returns true on success, otherwise false.
|
||||
*/
|
||||
bool QPlatformGraphicsBuffer::bindToTexture(const QRect &rect) const
|
||||
{
|
||||
Q_UNUSED(rect);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QPlatformGraphicsBuffer::AccessTypes QPlatformGraphicsBuffer::isLocked() const
|
||||
Function to check if the buffer is locked.
|
||||
|
||||
\sa lock()
|
||||
*/
|
||||
|
||||
/*!
|
||||
Before the data can be retrieved or before a buffer can be bound to a
|
||||
texture it needs to be locked. This is a separate function call since this
|
||||
operation might be time consuming, and it would not be satisfactory to do
|
||||
it per function call.
|
||||
|
||||
\a access is the access type wanted.
|
||||
|
||||
\a rect is the subrect which is desired to be locked. This
|
||||
argument has a no less than semantic, meaning more (if not all) of the buffer
|
||||
can be locked. An empty QRect is interpreted as entire buffer should be locked.
|
||||
|
||||
Return true on successfully locking all AccessTypes specified \a access
|
||||
otherwise returns false and no locks have been granted.
|
||||
*/
|
||||
bool QPlatformGraphicsBuffer::lock(AccessTypes access, const QRect &rect)
|
||||
{
|
||||
bool locked = doLock(access, rect);
|
||||
if (locked)
|
||||
m_lock_access |= access;
|
||||
|
||||
return locked;
|
||||
}
|
||||
|
||||
/*!
|
||||
Unlocks the current buffer lock.
|
||||
|
||||
This function calls doUnlock, and then emits the unlocked signal with the
|
||||
AccessTypes from before doUnlock was called.
|
||||
*/
|
||||
void QPlatformGraphicsBuffer::unlock()
|
||||
{
|
||||
if (m_lock_access == None)
|
||||
return;
|
||||
AccessTypes previous = m_lock_access;
|
||||
doUnlock();
|
||||
m_lock_access = None;
|
||||
emit unlocked(previous);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\fn QPlatformGraphicsBuffer::doLock(AccessTypes access, const QRect &rect = QRect())
|
||||
|
||||
This function should be reimplemented by subclasses. If one of the \a
|
||||
access types specified can not be locked, then all should fail and this
|
||||
function should return false.
|
||||
|
||||
\a rect is the subrect which is desired to be locked. This
|
||||
argument has a no less than semantic, meaning more (if not all) of the
|
||||
buffer can be locked. An empty QRect should be interpreted as the entire buffer
|
||||
should be locked.
|
||||
|
||||
It is safe to call isLocked() to verify the current lock state.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QPlatformGraphicsBuffer::doUnlock()
|
||||
|
||||
This function should remove all locks set on the buffer.
|
||||
|
||||
It is safe to call isLocked() to verify the current lock state.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QPlatformGraphicsBuffer::unlocked(AccessTypes previousAccessTypes)
|
||||
|
||||
Signal that is emitted after unlocked has been called.
|
||||
|
||||
\a previousAccessTypes is the access types locked before unlock was called.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Accessor for the bytes of the buffer. This function needs to be called on a
|
||||
buffer with SWReadAccess access lock. Behavior is undefined for modifying
|
||||
the memory returned when not having a SWWriteAccess.
|
||||
*/
|
||||
const uchar *QPlatformGraphicsBuffer::data() const
|
||||
{ return Q_NULLPTR; }
|
||||
|
||||
/*!
|
||||
Accessor for the bytes of the buffer. This function needs to be called on a
|
||||
buffer with SWReadAccess access lock. Behavior is undefined for modifying
|
||||
the memory returned when not having a SWWriteAccess.
|
||||
*/
|
||||
uchar *QPlatformGraphicsBuffer::data()
|
||||
{
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
/*!
|
||||
Accessor for the length of the data buffer. This function is a convenience
|
||||
function multiplying height of buffer with bytesPerLine().
|
||||
|
||||
\sa data() bytesPerLine() size()
|
||||
*/
|
||||
int QPlatformGraphicsBuffer::byteCount() const
|
||||
{
|
||||
Q_ASSERT(isLocked() & SWReadAccess);
|
||||
return size().height() * bytesPerLine();
|
||||
}
|
||||
|
||||
/*!
|
||||
Accessor for bytes per line in the graphics buffer.
|
||||
*/
|
||||
int QPlatformGraphicsBuffer::bytesPerLine() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
In origin of the content of the graphics buffer.
|
||||
|
||||
Default implementation is OriginTopLeft, as this is the coordinate
|
||||
system default for Qt. However, for most regular OpenGL textures
|
||||
this will be OriginBottomLeft.
|
||||
*/
|
||||
QPlatformGraphicsBuffer::Origin QPlatformGraphicsBuffer::origin() const
|
||||
{
|
||||
return OriginTopLeft;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QPlatformGraphicsBuffer::size() const
|
||||
|
||||
Accessor for content size.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QPlatformGraphicsBuffer::format() const
|
||||
|
||||
Accessor for the pixel format of the buffer.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
117
src/gui/kernel/qplatformgraphicsbuffer.h
Normal file
117
src/gui/kernel/qplatformgraphicsbuffer.h
Normal file
@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 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 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QPLATFORMGRAPHICSBUFFER_H
|
||||
#define QPLATFORMGRAPHICSBUFFER_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is part of the QPA API and is not meant to be used
|
||||
// in applications. Usage of this API may make your code
|
||||
// source and binary incompatible with future versions of Qt.
|
||||
//
|
||||
|
||||
|
||||
#include <QtCore/QSize>
|
||||
#include <QtCore/QRect>
|
||||
#include <QtGui/QPixelFormat>
|
||||
#include <QtCore/qflags.h>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_GUI_EXPORT QPlatformGraphicsBuffer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum AccessType
|
||||
{
|
||||
None = 0x00,
|
||||
SWReadAccess = 0x01,
|
||||
SWWriteAccess = 0x02,
|
||||
TextureAccess = 0x04,
|
||||
HWCompositor = 0x08
|
||||
};
|
||||
Q_DECLARE_FLAGS(AccessTypes, AccessType);
|
||||
|
||||
enum Origin {
|
||||
OriginBottomLeft,
|
||||
OriginTopLeft
|
||||
};
|
||||
|
||||
virtual ~QPlatformGraphicsBuffer();
|
||||
|
||||
AccessTypes isLocked() const { return m_lock_access; }
|
||||
bool lock(AccessTypes access, const QRect &rect = QRect());
|
||||
void unlock();
|
||||
|
||||
virtual bool bindToTexture(const QRect &rect = QRect()) const;
|
||||
|
||||
virtual const uchar *data() const;
|
||||
virtual uchar *data();
|
||||
virtual int bytesPerLine() const;
|
||||
int byteCount() const;
|
||||
|
||||
virtual Origin origin() const;
|
||||
|
||||
QSize size() const { return m_size; }
|
||||
QPixelFormat format() const { return m_format; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void unlocked(AccessTypes previousAccessTypes);
|
||||
|
||||
protected:
|
||||
QPlatformGraphicsBuffer(const QSize &size, const QPixelFormat &format);
|
||||
|
||||
virtual bool doLock(AccessTypes access, const QRect &rect = QRect()) = 0;
|
||||
virtual void doUnlock() = 0;
|
||||
|
||||
private:
|
||||
QSize m_size;
|
||||
QPixelFormat m_format;
|
||||
AccessTypes m_lock_access;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif //QPLATFORMGRAPHICSBUFFER_H
|
185
src/gui/kernel/qplatformgraphicsbufferhelper.cpp
Normal file
185
src/gui/kernel/qplatformgraphicsbufferhelper.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtPlatformSupport module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 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 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtGui/qpa/qplatformgraphicsbuffer.h>
|
||||
|
||||
#include "qplatformgraphicsbufferhelper.h"
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/qopengl.h>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QOpenGLFunctions>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
Convenience function to both lock and bind the buffer to a texture. This
|
||||
function will first try and lock with texture read and texture write
|
||||
access. If this succeeds it will use the bindToTexture function to bind the
|
||||
content to the currently bound texture. If this fail it will try and lock
|
||||
with SWReadAccess and then use the bindSWToTexture convenience function.
|
||||
|
||||
\a swizzle is suppose to be used by the caller to figure out if the Red and
|
||||
Blue color channels need to be swizzled when rendering.
|
||||
|
||||
\a rect is the subrect which is desired to be bounded to the texture. This
|
||||
argument has a no less than semantic, meaning more (if not all) of the buffer
|
||||
can be bounded to the texture. An empty QRect is interpreted as entire buffer
|
||||
should be bound.
|
||||
|
||||
The user should use the AccessTypes returned by isLocked to figure out what
|
||||
lock has been obtained.
|
||||
|
||||
returns true if the buffer has successfully been bound to the currently
|
||||
bound texture, otherwise returns false.
|
||||
*/
|
||||
bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer,
|
||||
bool *swizzle,
|
||||
const QRect &rect)
|
||||
{
|
||||
if (graphicsBuffer->lock(QPlatformGraphicsBuffer::TextureAccess)) {
|
||||
if (!graphicsBuffer->bindToTexture(rect)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to bind graphicsbuffer to texture";
|
||||
return false;
|
||||
}
|
||||
if (swizzle)
|
||||
*swizzle = false;
|
||||
} else if (graphicsBuffer->lock(QPlatformGraphicsBuffer::SWReadAccess)) {
|
||||
if (!bindSWToTexture(graphicsBuffer, swizzle, rect)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to bind SW graphcisbuffer to texture";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to lock";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Convenience function that uploads the current raster content to the currently bound texture.
|
||||
|
||||
\a swizzleRandB is suppose to be used by the caller to figure out if the Red and
|
||||
Blue color channels need to be swizzled when rendering. This is an
|
||||
optimization. Qt often renders to software buffers interpreting pixels as
|
||||
unsigned ints. When these buffers are uploaded to textures and each color
|
||||
channel per pixel is interpreted as a byte (read sequentially), then the
|
||||
Red and Blue channels are swapped. Conveniently the Alpha buffer will be
|
||||
correct since Qt historically has had the alpha channel as the first
|
||||
channel, while OpenGL typically expects the alpha channel to be the last
|
||||
channel.
|
||||
|
||||
\a subRect is the subrect which is desired to be bounded to the texture. This
|
||||
argument has a no less than semantic, meaning more (if not all) of the buffer
|
||||
can be bounded to the texture. An empty QRect is interpreted as entire buffer
|
||||
should be bound.
|
||||
|
||||
This function fails for buffers not capable of locking to SWAccess.
|
||||
|
||||
Returns true on success, otherwise false.
|
||||
*/
|
||||
bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer,
|
||||
bool *swizzleRandB,
|
||||
const QRect &subRect)
|
||||
{
|
||||
if (!QOpenGLContext::currentContext())
|
||||
return false;
|
||||
|
||||
if (!(graphicsBuffer->isLocked() & QPlatformGraphicsBuffer::SWReadAccess))
|
||||
return false;
|
||||
|
||||
QSize size = graphicsBuffer->size();
|
||||
|
||||
Q_ASSERT(subRect.isEmpty() || QRect(QPoint(0,0), size).contains(subRect));
|
||||
|
||||
bool swizzle = false;
|
||||
QImage::Format imageformat = QImage::toImageFormat(graphicsBuffer->format());
|
||||
QImage image(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), imageformat);
|
||||
if (graphicsBuffer->bytesPerLine() != (size.width() * 4)) {
|
||||
image = image.convertToFormat(QImage::Format_RGBA8888);
|
||||
} else if (imageformat == QImage::Format_RGB32) {
|
||||
swizzle = true;
|
||||
} else if (imageformat != QImage::Format_RGBA8888) {
|
||||
image = image.convertToFormat(QImage::Format_RGBA8888);
|
||||
}
|
||||
|
||||
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
|
||||
|
||||
QRect rect = subRect;
|
||||
if (rect.isNull() || rect == QRect(QPoint(0,0),size)) {
|
||||
funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits());
|
||||
} else {
|
||||
#ifndef QT_OPENGL_ES_2
|
||||
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
||||
funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width());
|
||||
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
image.constScanLine(rect.y()) + rect.x() * 4);
|
||||
funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// if the rect is wide enough it's cheaper to just
|
||||
// extend it instead of doing an image copy
|
||||
if (rect.width() >= size.width() / 2) {
|
||||
rect.setX(0);
|
||||
rect.setWidth(size.width());
|
||||
}
|
||||
|
||||
// if the sub-rect is full-width we can pass the image data directly to
|
||||
// OpenGL instead of copying, since there's no gap between scanlines
|
||||
|
||||
if (rect.width() == size.width()) {
|
||||
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
image.constScanLine(rect.y()));
|
||||
} else {
|
||||
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
image.copy(rect).constBits());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (swizzleRandB)
|
||||
*swizzleRandB = swizzle;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
56
src/gui/kernel/qplatformgraphicsbufferhelper.h
Normal file
56
src/gui/kernel/qplatformgraphicsbufferhelper.h
Normal file
@ -0,0 +1,56 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtPlatformSupport module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 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 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QPLATFORMGRAPHICSBUFFERHELPER_H
|
||||
#define QPLATFORMGRAPHICSBUFFERHELPER_H
|
||||
|
||||
#include <QtGui/qpa/qplatformgraphicsbuffer.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QPlatformGraphicsBufferHelper {
|
||||
bool lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, const QRect &rect = QRect());
|
||||
bool bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB = Q_NULLPTR, const QRect &rect = QRect());
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -45,6 +45,8 @@
|
||||
#ifndef QT_NO_OPENGL
|
||||
#include <QtGui/private/qopengltextureblitter_p.h>
|
||||
#endif
|
||||
#include <qpa/qplatformgraphicsbuffer.h>
|
||||
#include <qpa/qplatformgraphicsbufferhelper.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -69,7 +71,6 @@ public:
|
||||
#endif
|
||||
}
|
||||
QWindow *window;
|
||||
QSize size;
|
||||
#ifndef QT_NO_OPENGL
|
||||
mutable GLuint textureId;
|
||||
mutable QSize textureSize;
|
||||
@ -267,13 +268,50 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i
|
||||
// semi-transparency even when it is not wanted.
|
||||
funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
||||
|
||||
// Backingstore texture with the normal widgets.
|
||||
GLuint textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &d_ptr->needsSwizzle);
|
||||
GLuint textureId = 0;
|
||||
QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft;
|
||||
if (QPlatformGraphicsBuffer *graphicsBuffer = this->graphicsBuffer()) {
|
||||
if (graphicsBuffer->size() != d_ptr->textureSize) {
|
||||
if (d_ptr->textureId)
|
||||
funcs->glDeleteTextures(1, &d_ptr->textureId);
|
||||
funcs->glGenTextures(1, &d_ptr->textureId);
|
||||
funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
|
||||
#ifndef QT_OPENGL_ES_2
|
||||
if (!QOpenGLContext::currentContext()->isOpenGLES()) {
|
||||
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
#endif
|
||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle)) {
|
||||
d_ptr->textureSize = graphicsBuffer->size();
|
||||
} else {
|
||||
d_ptr->textureSize = QSize(0,0);
|
||||
}
|
||||
|
||||
graphicsBuffer->unlock();
|
||||
} else if (!region.isEmpty()){
|
||||
funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
|
||||
QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle);
|
||||
}
|
||||
|
||||
if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft)
|
||||
origin = QOpenGLTextureBlitter::OriginBottomLeft;
|
||||
textureId = d_ptr->textureId;
|
||||
} else {
|
||||
// Backingstore texture with the normal widgets.
|
||||
textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &d_ptr->needsSwizzle);
|
||||
}
|
||||
|
||||
if (textureId) {
|
||||
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), windowRect);
|
||||
if (d_ptr->needsSwizzle)
|
||||
d_ptr->blitter->setSwizzleRB(true);
|
||||
d_ptr->blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
|
||||
d_ptr->blitter->blit(textureId, target, origin);
|
||||
if (d_ptr->needsSwizzle)
|
||||
d_ptr->blitter->setSwizzleRB(false);
|
||||
}
|
||||
@ -462,6 +500,14 @@ void QPlatformBackingStore::endPaint()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Accessor for a backingstores graphics buffer abstraction
|
||||
*/
|
||||
QPlatformGraphicsBuffer *QPlatformBackingStore::graphicsBuffer() const
|
||||
{
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
/*!
|
||||
Scrolls the given \a area \a dx pixels to the right and \a dy
|
||||
downward; both \a dx and \a dy may be negative.
|
||||
|
@ -62,6 +62,7 @@ class QPlatformWindow;
|
||||
class QPlatformTextureList;
|
||||
class QPlatformTextureListPrivate;
|
||||
class QOpenGLContext;
|
||||
class QPlatformGraphicsBuffer;
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
class Q_GUI_EXPORT QPlatformTextureList : public QObject
|
||||
@ -116,6 +117,8 @@ public:
|
||||
virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, bool *needsSwizzle) const;
|
||||
#endif
|
||||
|
||||
virtual QPlatformGraphicsBuffer *graphicsBuffer() const;
|
||||
|
||||
virtual void resize(const QSize &size, const QRegion &staticContents) = 0;
|
||||
|
||||
virtual bool scroll(const QRegion &area, int dx, int dy);
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <qdebug.h>
|
||||
#include <qpainter.h>
|
||||
#include <qscreen.h>
|
||||
#include <qpa/qplatformgraphicsbuffer.h>
|
||||
|
||||
#include <algorithm>
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -60,6 +61,8 @@ public:
|
||||
~QXcbShmImage() { destroy(); }
|
||||
|
||||
QImage *image() { return &m_qimage; }
|
||||
QPlatformGraphicsBuffer *graphicsBuffer() { return m_graphics_buffer; }
|
||||
|
||||
QSize size() const { return m_qimage.size(); }
|
||||
|
||||
void put(xcb_window_t window, const QPoint &dst, const QRect &source);
|
||||
@ -73,6 +76,7 @@ private:
|
||||
xcb_image_t *m_xcb_image;
|
||||
|
||||
QImage m_qimage;
|
||||
QPlatformGraphicsBuffer *m_graphics_buffer;
|
||||
|
||||
xcb_gcontext_t m_gc;
|
||||
xcb_window_t m_gc_window;
|
||||
@ -80,8 +84,39 @@ private:
|
||||
QRegion m_dirty;
|
||||
};
|
||||
|
||||
class QXcbShmGraphicsBuffer : public QPlatformGraphicsBuffer
|
||||
{
|
||||
public:
|
||||
QXcbShmGraphicsBuffer(QImage *image)
|
||||
: QPlatformGraphicsBuffer(image->size(), QImage::toPixelFormat(image->format()))
|
||||
, m_access_lock(QPlatformGraphicsBuffer::None)
|
||||
, m_image(image)
|
||||
{ }
|
||||
|
||||
bool doLock(AccessTypes access, const QRect &rect) Q_DECL_OVERRIDE
|
||||
{
|
||||
Q_UNUSED(rect);
|
||||
if (access & ~(QPlatformGraphicsBuffer::SWReadAccess | QPlatformGraphicsBuffer::SWWriteAccess))
|
||||
return false;
|
||||
|
||||
m_access_lock |= access;
|
||||
return true;
|
||||
}
|
||||
void doUnlock() Q_DECL_OVERRIDE { m_access_lock = None; }
|
||||
|
||||
const uchar *data() const Q_DECL_OVERRIDE { return m_image->bits(); }
|
||||
uchar *data() Q_DECL_OVERRIDE { return m_image->bits(); }
|
||||
int bytesPerLine() const Q_DECL_OVERRIDE { return m_image->bytesPerLine(); }
|
||||
|
||||
Origin origin() const Q_DECL_OVERRIDE { return QPlatformGraphicsBuffer::OriginTopLeft; }
|
||||
private:
|
||||
AccessTypes m_access_lock;
|
||||
QImage *m_image;
|
||||
};
|
||||
|
||||
QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format)
|
||||
: QXcbObject(screen->connection())
|
||||
, m_graphics_buffer(Q_NULLPTR)
|
||||
, m_gc(0)
|
||||
, m_gc_window(0)
|
||||
{
|
||||
@ -137,6 +172,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
|
||||
}
|
||||
|
||||
m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format);
|
||||
m_graphics_buffer = new QXcbShmGraphicsBuffer(&m_qimage);
|
||||
}
|
||||
|
||||
void QXcbShmImage::destroy()
|
||||
@ -158,6 +194,8 @@ void QXcbShmImage::destroy()
|
||||
|
||||
if (m_gc)
|
||||
Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
|
||||
delete m_graphics_buffer;
|
||||
m_graphics_buffer = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source)
|
||||
@ -294,6 +332,11 @@ QImage QXcbBackingStore::toImage() const
|
||||
}
|
||||
#endif
|
||||
|
||||
QPlatformGraphicsBuffer *QXcbBackingStore::graphicsBuffer() const
|
||||
{
|
||||
return m_image ? m_image->graphicsBuffer() : Q_NULLPTR;
|
||||
}
|
||||
|
||||
void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
if (!m_image || m_image->size().isEmpty())
|
||||
|
@ -58,6 +58,9 @@ public:
|
||||
bool translucentBackground) Q_DECL_OVERRIDE;
|
||||
QImage toImage() const Q_DECL_OVERRIDE;
|
||||
#endif
|
||||
|
||||
QPlatformGraphicsBuffer *graphicsBuffer() const Q_DECL_OVERRIDE;
|
||||
|
||||
void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
|
||||
bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user