Remove dummy impl. of shared graphics cache in XCB plugin

This implementation was disabled and didn't really work
properly, so it doesn't make sense to update or do
bug fixes to it. Removing it completely instead.

Change-Id: I62abe35f0f9a91bb207b87296d25c3c62d58228e
Reviewed-by: Jiang Jiang <jiang.jiang@nokia.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2012-03-23 14:45:51 +01:00 committed by Qt by Nokia
parent eac97c5830
commit cb33c3b2b6
7 changed files with 2 additions and 1279 deletions

View File

@ -47,7 +47,6 @@
#include "qxcbnativeinterface.h"
#include "qxcbclipboard.h"
#include "qxcbdrag.h"
#include "qxcbsharedgraphicscache.h"
#include <xcb/xcb.h>
@ -118,10 +117,6 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters)
#ifndef QT_NO_ACCESSIBILITY
m_accessibility.reset(new QPlatformAccessibility());
#endif
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
m_sharedGraphicsCache.reset(new QXcbSharedGraphicsCache);
#endif
}
QXcbIntegration::~QXcbIntegration()
@ -203,10 +198,6 @@ QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *wind
bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
case SharedGraphicsCache: return true;
#endif
case ThreadedPixmaps: return true;
case OpenGL: return true;
case ThreadedOpenGL: return false;
@ -257,26 +248,6 @@ QPlatformAccessibility *QXcbIntegration::accessibility() const
}
#endif
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
static bool sharedGraphicsCacheDisabled()
{
static const char *environmentVariable = "QT_DISABLE_SHARED_CACHE";
static bool cacheDisabled = !qgetenv(environmentVariable).isEmpty()
&& qgetenv(environmentVariable).toInt() != 0;
return cacheDisabled;
}
QPlatformSharedGraphicsCache *QXcbIntegration::createPlatformSharedGraphicsCache(const char *cacheId) const
{
Q_UNUSED(cacheId);
if (sharedGraphicsCacheDisabled())
return 0;
return m_sharedGraphicsCache.data();
}
#endif
QPlatformServices *QXcbIntegration::services() const
{
return m_services.data();

View File

@ -81,10 +81,6 @@ public:
QPlatformAccessibility *accessibility() const;
#endif
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
QPlatformSharedGraphicsCache *createPlatformSharedGraphicsCache(const char *cacheId) const;
#endif
QPlatformServices *services() const;
QStringList themeNames() const;
@ -103,10 +99,6 @@ private:
QScopedPointer<QPlatformAccessibility> m_accessibility;
#endif
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
QScopedPointer<QPlatformSharedGraphicsCache> m_sharedGraphicsCache;
#endif
QScopedPointer<QPlatformServices> m_services;
};

View File

@ -1,640 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
#include "qxcbsharedbuffermanager.h"
#include <QtCore/quuid.h>
#include <QtGui/qimage.h>
#include <stdio.h>
#if !defined(SHAREDGRAPHICSCACHE_MAX_MEMORY_USED)
# define SHAREDGRAPHICSCACHE_MAX_MEMORY_USED 16 * 1024 * 1024 // 16 MB limit
#endif
#if !defined(SHAREDGRAPHICSCACHE_MAX_TEXTURES_PER_CACHE)
# define SHAREDGRAPHICSCACHE_MAX_TEXTURES_PER_CACHE 1
#endif
#if !defined(SHAREDGRAPHICSCACHE_TEXTURE_SIZE)
# define SHAREDGRAPHICSCACHE_TEXTURE_SIZE 2048
#endif
#define SHAREDBUFFERMANAGER_DEBUG 1
QT_BEGIN_NAMESPACE
QXcbSharedBufferManager::QXcbSharedBufferManager()
: m_memoryUsed(0)
, m_mostRecentlyUsed(0)
, m_leastRecentlyUsed(0)
{
}
QXcbSharedBufferManager::~QXcbSharedBufferManager()
{
{
QHash<QByteArray, Buffer *>::const_iterator it = m_buffers.constBegin();
while (it != m_buffers.constEnd()) {
Buffer *buffer = it.value();
delete buffer;
++it;
}
}
{
QHash<QByteArray, Items *>::const_iterator it = m_items.constBegin();
while (it != m_items.constEnd()) {
Items *items = it.value();
QHash<quint32, Item *>::const_iterator itemIt = items->items.constBegin();
while (itemIt != items->items.constEnd()) {
delete itemIt.value();
++itemIt;
}
delete it.value();
++it;
}
}
}
void QXcbSharedBufferManager::getBufferForItem(const QByteArray &cacheId, quint32 itemId,
Buffer **buffer, int *x, int *y) const
{
Q_ASSERT_X(m_currentCacheId.isEmpty(), Q_FUNC_INFO,
"Call endSharedBufferAction before accessing data");
Q_ASSERT(buffer != 0);
Q_ASSERT(x != 0);
Q_ASSERT(y != 0);
Items *items = itemsForCache(cacheId);
Item *item = items->items.value(itemId);
if (item != 0) {
*buffer = item->buffer;
*x = item->x;
*y = item->y;
} else {
*buffer = 0;
*x = -1;
*y = -1;
}
}
QPair<QByteArray, int> QXcbSharedBufferManager::serializeBuffer(QSharedMemory *buffer) const
{
Q_ASSERT_X(m_currentCacheId.isEmpty(), Q_FUNC_INFO,
"Call endSharedBufferAction before accessing data");
return qMakePair(buffer->key().toLatin1(), 0);
}
void QXcbSharedBufferManager::beginSharedBufferAction(const QByteArray &cacheId)
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::beginSharedBufferAction() called for %s", cacheId.constData());
#endif
Q_ASSERT(m_currentCacheId.isEmpty());
Q_ASSERT(!cacheId.isEmpty());
m_pendingInvalidatedItems.clear();
m_pendingReadyItems.clear();
m_pendingMissingItems.clear();
m_currentCacheId = cacheId;
}
void QXcbSharedBufferManager::requestItems(const QSet<quint32> &itemIds)
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::requestItems for %d items", itemIds.size());
#endif
Q_ASSERT_X(!m_currentCacheId.isEmpty(), Q_FUNC_INFO,
"Call beginSharedBufferAction before requesting items");
Items *items = itemsForCache(m_currentCacheId);
QSet<quint32>::const_iterator it = itemIds.constBegin();
while (it != itemIds.constEnd()) {
if (items->items.contains(*it))
m_pendingReadyItems[m_currentCacheId].insert(*it);
else
m_pendingMissingItems[m_currentCacheId].insert(*it);
++it;
}
}
void QXcbSharedBufferManager::releaseItems(const QSet<quint32> &itemIds)
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::releaseItems for %d items", itemIds.size());
#endif
Items *items = itemsForCache(m_currentCacheId);
QSet<quint32>::const_iterator it;
for (it = itemIds.constBegin(); it != itemIds.constEnd(); ++it) {
Item *item = items->items.value(*it);
if (item != 0)
pushItemToBack(items, item);
m_pendingReadyItems[m_currentCacheId].remove(*it);
m_pendingMissingItems[m_currentCacheId].remove(*it);
}
}
void QXcbSharedBufferManager::insertItem(quint32 itemId, uchar *data,
int itemWidth, int itemHeight)
{
Q_ASSERT_X(!m_currentCacheId.isEmpty(), Q_FUNC_INFO,
"Call beginSharedBufferAction before inserting items");
Items *items = itemsForCache(m_currentCacheId);
if (!items->items.contains(itemId)) {
Buffer *sharedBuffer = 0;
int x = 0;
int y = 0;
findAvailableBuffer(itemWidth, itemHeight, &sharedBuffer, &x, &y);
copyIntoBuffer(sharedBuffer, x, y, itemWidth, itemHeight, data);
// static int counter=0;
// QString fileName = QString::fromLatin1("buffer%1.png").arg(counter++);
// saveBuffer(sharedBuffer, fileName);
Item *item = new Item;
item->itemId = itemId;
item->buffer = sharedBuffer;
item->x = x;
item->y = y;
items->items[itemId] = item;
touchItem(items, item);
}
}
void QXcbSharedBufferManager::endSharedBufferAction()
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::endSharedBufferAction() called for %s",
m_currentCacheId.constData());
#endif
Q_ASSERT(!m_currentCacheId.isEmpty());
// Do an extra validation pass on the invalidated items since they may have been re-inserted
// after they were invalidated
if (m_pendingInvalidatedItems.contains(m_currentCacheId)) {
QSet<quint32> &invalidatedItems = m_pendingInvalidatedItems[m_currentCacheId];
QSet<quint32>::iterator it = invalidatedItems.begin();
while (it != invalidatedItems.end()) {
Items *items = m_items.value(m_currentCacheId);
if (items->items.contains(*it)) {
m_pendingReadyItems[m_currentCacheId].insert(*it);
it = invalidatedItems.erase(it);
} else {
++it;
}
}
}
m_currentCacheId.clear();
}
void QXcbSharedBufferManager::pushItemToBack(Items *items, Item *item)
{
if (items->leastRecentlyUsed == item)
return;
if (item->next != 0)
item->next->prev = item->prev;
if (item->prev != 0)
item->prev->next = item->next;
if (items->mostRecentlyUsed == item)
items->mostRecentlyUsed = item->prev;
if (items->leastRecentlyUsed != 0)
items->leastRecentlyUsed->prev = item;
item->prev = 0;
item->next = items->leastRecentlyUsed;
items->leastRecentlyUsed = item;
if (items->mostRecentlyUsed == 0)
items->mostRecentlyUsed = item;
}
void QXcbSharedBufferManager::touchItem(Items *items, Item *item)
{
if (items->mostRecentlyUsed == item)
return;
if (item->next != 0)
item->next->prev = item->prev;
if (item->prev != 0)
item->prev->next = item->next;
if (items->leastRecentlyUsed == item)
items->leastRecentlyUsed = item->next;
if (items->mostRecentlyUsed != 0)
items->mostRecentlyUsed->next = item;
item->next = 0;
item->prev = items->mostRecentlyUsed;
items->mostRecentlyUsed = item;
if (items->leastRecentlyUsed == 0)
items->leastRecentlyUsed = item;
}
void QXcbSharedBufferManager::deleteItem(Items *items, Item *item)
{
Q_ASSERT(items != 0);
Q_ASSERT(item != 0);
if (items->mostRecentlyUsed == item)
items->mostRecentlyUsed = item->prev;
if (items->leastRecentlyUsed == item)
items->leastRecentlyUsed = item->next;
if (item->next != 0)
item->next->prev = item->prev;
if (item->prev != 0)
item->prev->next = item->next;
m_pendingInvalidatedItems[items->cacheId].insert(item->itemId);
{
QHash<quint32, Item *>::iterator it = items->items.find(item->itemId);
while (it != items->items.end() && it.value()->itemId == item->itemId)
it = items->items.erase(it);
}
delete item;
}
void QXcbSharedBufferManager::recycleItem(Buffer **sharedBuffer, int *glyphX, int *glyphY)
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::recycleItem() called for %s", m_currentCacheId.constData());
#endif
Items *items = itemsForCache(m_currentCacheId);
Item *recycledItem = items->leastRecentlyUsed;
Q_ASSERT(recycledItem != 0);
*sharedBuffer = recycledItem->buffer;
*glyphX = recycledItem->x;
*glyphY = recycledItem->y;
deleteItem(items, recycledItem);
}
void QXcbSharedBufferManager::touchBuffer(Buffer *buffer)
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::touchBuffer() called for %s", buffer->cacheId.constData());
#endif
if (buffer == m_mostRecentlyUsed)
return;
if (buffer->next != 0)
buffer->next->prev = buffer->prev;
if (buffer->prev != 0)
buffer->prev->next = buffer->next;
if (m_leastRecentlyUsed == buffer)
m_leastRecentlyUsed = buffer->next;
buffer->next = 0;
buffer->prev = m_mostRecentlyUsed;
if (m_mostRecentlyUsed != 0)
m_mostRecentlyUsed->next = buffer;
if (m_leastRecentlyUsed == 0)
m_leastRecentlyUsed = buffer;
m_mostRecentlyUsed = buffer;
}
void QXcbSharedBufferManager::deleteLeastRecentlyUsed()
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::deleteLeastRecentlyUsed() called");
#endif
if (m_leastRecentlyUsed == 0)
return;
Buffer *old = m_leastRecentlyUsed;
m_leastRecentlyUsed = old->next;
m_leastRecentlyUsed->prev = 0;
QByteArray cacheId = old->cacheId;
Items *items = itemsForCache(cacheId);
QHash<quint32, Item *>::iterator it = items->items.begin();
while (it != items->items.end()) {
Item *item = it.value();
if (item->buffer == old) {
deleteItem(items, item);
it = items->items.erase(it);
} else {
++it;
}
}
m_buffers.remove(cacheId, old);
m_memoryUsed -= old->width * old->height * old->bytesPerPixel;
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::deleteLeastRecentlyUsed: Memory used: %d / %d (%6.2f %%)",
m_memoryUsed, SHAREDGRAPHICSCACHE_MAX_MEMORY_USED,
100.0f * float(m_memoryUsed) / float(SHAREDGRAPHICSCACHE_MAX_MEMORY_USED));
#endif
delete old;
}
QXcbSharedBufferManager::Buffer *QXcbSharedBufferManager::createNewBuffer(const QByteArray &cacheId,
int heightRequired)
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::createNewBuffer() called for %s", cacheId.constData());
#endif
// ###
// if (bufferCount of cacheId == SHAREDGRAPHICACHE_MAX_TEXTURES_PER_CACHE)
// deleteLeastRecentlyUsedBufferForCache(cacheId);
// ### Take pixel format into account
while (m_memoryUsed + SHAREDGRAPHICSCACHE_TEXTURE_SIZE * heightRequired >= SHAREDGRAPHICSCACHE_MAX_MEMORY_USED)
deleteLeastRecentlyUsed();
Buffer *buffer = allocateBuffer(SHAREDGRAPHICSCACHE_TEXTURE_SIZE, heightRequired);
buffer->cacheId = cacheId;
buffer->currentLineMaxHeight = 0;
m_buffers.insert(cacheId, buffer);
return buffer;
}
static inline int qt_next_power_of_two(int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
++v;
return v;
}
QXcbSharedBufferManager::Buffer *QXcbSharedBufferManager::resizeBuffer(Buffer *oldBuffer, const QSize &newSize)
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::resizeBuffer() called for %s (current size: %dx%d, new size: %dx%d)",
oldBuffer->cacheId.constData(), oldBuffer->width, oldBuffer->height,
newSize.width(), newSize.height());
#endif
// Remove old buffer from lists to avoid deleting it under our feet
if (m_leastRecentlyUsed == oldBuffer)
m_leastRecentlyUsed = oldBuffer->next;
if (m_mostRecentlyUsed == oldBuffer)
m_mostRecentlyUsed = oldBuffer->prev;
if (oldBuffer->prev != 0)
oldBuffer->prev->next = oldBuffer->next;
if (oldBuffer->next != 0)
oldBuffer->next->prev = oldBuffer->prev;
m_memoryUsed -= oldBuffer->width * oldBuffer->height * oldBuffer->bytesPerPixel;
m_buffers.remove(oldBuffer->cacheId, oldBuffer);
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::resizeBuffer: Memory used: %d / %d (%6.2f %%)",
m_memoryUsed, SHAREDGRAPHICSCACHE_MAX_MEMORY_USED,
100.0f * float(m_memoryUsed) / float(SHAREDGRAPHICSCACHE_MAX_MEMORY_USED));
#endif
Buffer *resizedBuffer = createNewBuffer(oldBuffer->cacheId, newSize.height());
copyIntoBuffer(resizedBuffer, 0, 0, oldBuffer->width, oldBuffer->height,
reinterpret_cast<uchar *>(oldBuffer->buffer->data()));
resizedBuffer->currentLineMaxHeight = oldBuffer->currentLineMaxHeight;
Items *items = itemsForCache(oldBuffer->cacheId);
QHash<quint32, Item *>::const_iterator it = items->items.constBegin();
while (it != items->items.constEnd()) {
Item *item = it.value();
if (item->buffer == oldBuffer) {
m_pendingReadyItems[oldBuffer->cacheId].insert(item->itemId);
item->buffer = resizedBuffer;
}
++it;
}
resizedBuffer->nextX = oldBuffer->nextX;
resizedBuffer->nextY = oldBuffer->nextY;
resizedBuffer->currentLineMaxHeight = oldBuffer->currentLineMaxHeight;
delete oldBuffer;
return resizedBuffer;
}
void QXcbSharedBufferManager::findAvailableBuffer(int itemWidth, int itemHeight,
Buffer **sharedBuffer, int *glyphX, int *glyphY)
{
Q_ASSERT(sharedBuffer != 0);
Q_ASSERT(glyphX != 0);
Q_ASSERT(glyphY != 0);
QMultiHash<QByteArray, Buffer *>::iterator it = m_buffers.find(m_currentCacheId);
int bufferCount = 0;
while (it != m_buffers.end() && it.key() == m_currentCacheId) {
Buffer *buffer = it.value();
int x = buffer->nextX;
int y = buffer->nextY;
int width = buffer->width;
int height = buffer->height;
if (x + itemWidth <= width && y + itemHeight <= height) {
// There is space on the current line, put the item there
buffer->currentLineMaxHeight = qMax(buffer->currentLineMaxHeight, itemHeight);
*sharedBuffer = buffer;
*glyphX = x;
*glyphY = y;
buffer->nextX += itemWidth;
return;
} else if (itemWidth <= width && y + buffer->currentLineMaxHeight + itemHeight <= height) {
// There is space for a new line, put the item on the new line
buffer->nextX = 0;
buffer->nextY += buffer->currentLineMaxHeight;
buffer->currentLineMaxHeight = 0;
*sharedBuffer = buffer;
*glyphX = buffer->nextX;
*glyphY = buffer->nextY;
buffer->nextX += itemWidth;
return;
} else if (y + buffer->currentLineMaxHeight + itemHeight <= SHAREDGRAPHICSCACHE_TEXTURE_SIZE) {
// There is space if we resize the buffer, so we do that
int newHeight = qt_next_power_of_two(y + buffer->currentLineMaxHeight + itemHeight);
buffer = resizeBuffer(buffer, QSize(width, newHeight));
buffer->nextX = 0;
buffer->nextY += buffer->currentLineMaxHeight;
buffer->currentLineMaxHeight = 0;
*sharedBuffer = buffer;
*glyphX = buffer->nextX;
*glyphY = buffer->nextY;
buffer->nextX += itemWidth;
return;
}
bufferCount++;
++it;
}
if (bufferCount == SHAREDGRAPHICSCACHE_MAX_TEXTURES_PER_CACHE) {
// There is no space in any buffer, and there is no space for a new buffer
// recycle an old item
recycleItem(sharedBuffer, glyphX, glyphY);
} else {
// Create a new buffer for the item
*sharedBuffer = createNewBuffer(m_currentCacheId, qt_next_power_of_two(itemHeight));
if (*sharedBuffer == 0) {
Q_ASSERT(false);
return;
}
*glyphX = (*sharedBuffer)->nextX;
*glyphY = (*sharedBuffer)->nextY;
(*sharedBuffer)->nextX += itemWidth;
}
}
QXcbSharedBufferManager::Buffer *QXcbSharedBufferManager::allocateBuffer(int width, int height)
{
Buffer *buffer = new Buffer;
buffer->nextX = 0;
buffer->nextY = 0;
buffer->width = width;
buffer->height = height;
buffer->bytesPerPixel = 1; // ### Use pixel format here
buffer->buffer = new QSharedMemory(QUuid::createUuid().toString());
bool ok = buffer->buffer->create(buffer->width * buffer->height * buffer->bytesPerPixel,
QSharedMemory::ReadWrite);
if (!ok) {
qWarning("QXcbSharedBufferManager::findAvailableBuffer: Can't create new buffer (%s)",
qPrintable(buffer->buffer->errorString()));
delete buffer;
return 0;
}
qMemSet(buffer->buffer->data(), 0, buffer->buffer->size());
m_memoryUsed += buffer->width * buffer->height * buffer->bytesPerPixel;
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::allocateBuffer: Memory used: %d / %d (%6.2f %%)",
int(m_memoryUsed), int(SHAREDGRAPHICSCACHE_MAX_MEMORY_USED),
100.0f * float(m_memoryUsed) / float(SHAREDGRAPHICSCACHE_MAX_MEMORY_USED));
#endif
return buffer;
}
void QXcbSharedBufferManager::copyIntoBuffer(Buffer *buffer,
int bufferX, int bufferY, int width, int height,
uchar *data)
{
#if defined(SHAREDBUFFERMANAGER_DEBUG)
qDebug("QXcbSharedBufferManager::copyIntoBuffer() called for %s (coords: %d, %d)",
buffer->cacheId.constData(), bufferX, bufferY);
#endif
Q_ASSERT(bufferX >= 0);
Q_ASSERT(bufferX + width <= buffer->width);
Q_ASSERT(bufferY >= 0);
Q_ASSERT(bufferY + height <= buffer->height);
uchar *dest = reinterpret_cast<uchar *>(buffer->buffer->data());
dest += bufferX + bufferY * buffer->width;
for (int y=0; y<height; ++y) {
qMemCopy(dest, data, width);
data += width;
dest += buffer->width;
}
}
QXcbSharedBufferManager::Items *QXcbSharedBufferManager::itemsForCache(const QByteArray &cacheId) const
{
Items *items = m_items.value(cacheId);
if (items == 0) {
items = new Items;
items->cacheId = cacheId;
m_items[cacheId] = items;
}
return items;
}
QT_END_NAMESPACE
#endif // QT_USE_XCB_SHARED_GRAPHICS_CACHE

View File

@ -1,215 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef XCBSHAREDBUFFERMANAGER_H
#define XCBSHAREDBUFFERMANAGER_H
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
#include <QtCore/qset.h>
#include <QtCore/qhash.h>
#include <QtCore/qsharedmemory.h>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
class wl_resource;
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QXcbSharedBufferManager
{
public:
struct Buffer {
Buffer()
: width(-1)
, height(-1)
, bytesPerPixel(1)
, nextX(-1)
, nextY(-1)
, currentLineMaxHeight(0)
, next(0)
, prev(0)
, buffer(0)
, textureId(0)
{
}
~Buffer()
{
delete buffer;
if (textureId != 0)
glDeleteTextures(1, &textureId);
}
QByteArray cacheId;
int width;
int height;
int bytesPerPixel;
int nextX;
int nextY;
int currentLineMaxHeight;
Buffer *next;
Buffer *prev;
QSharedMemory *buffer;
GLuint textureId;
QAtomicInt ref;
};
typedef QHash<QByteArray, QSet<quint32> > PendingItemIds;
QXcbSharedBufferManager();
~QXcbSharedBufferManager();
void beginSharedBufferAction(const QByteArray &cacheId);
void insertItem(quint32 itemId, uchar *data, int itemWidth, int itemHeight);
void requestItems(const QSet<quint32> &itemIds);
void releaseItems(const QSet<quint32> &itemIds);
void endSharedBufferAction();
void getBufferForItem(const QByteArray &cacheId, quint32 itemId, Buffer **buffer,
int *x, int *y) const;
QPair<QByteArray, int> serializeBuffer(QSharedMemory *buffer) const;
PendingItemIds pendingItemsInvalidated() const
{
Q_ASSERT_X(m_currentCacheId.isEmpty(), Q_FUNC_INFO,
"Call endSharedBufferAction() before accessing data");
return m_pendingInvalidatedItems;
}
PendingItemIds pendingItemsReady() const
{
Q_ASSERT_X(m_currentCacheId.isEmpty(), Q_FUNC_INFO,
"Call endSharedBufferAction() before accessing data");
return m_pendingReadyItems;
}
PendingItemIds pendingItemsMissing() const
{
Q_ASSERT_X(m_currentCacheId.isEmpty(), Q_FUNC_INFO,
"Call endSharedBufferAction() before accessing data");
return m_pendingMissingItems;
}
private:
struct Item {
Item()
: next(0)
, prev(0)
, buffer(0)
, itemId(0)
, x(-1)
, y(-1)
, width(-1)
, height(-1)
{
}
Item *next;
Item *prev;
Buffer *buffer;
quint32 itemId;
int x;
int y;
int width;
int height;
};
struct Items
{
Items() : leastRecentlyUsed(0), mostRecentlyUsed(0) {}
Item *leastRecentlyUsed;
Item *mostRecentlyUsed;
QByteArray cacheId;
QHash<quint32, Item *> items;
};
void findAvailableBuffer(int itemWidth, int itemHeight, Buffer **buffer, int *x, int *y);
void recycleItem(Buffer **buffer, int *x, int *y);
void copyIntoBuffer(Buffer *buffer, int x, int y, int itemWidth, int itemHeight, uchar *data);
void touchBuffer(Buffer *buffer);
void deleteLeastRecentlyUsed();
Buffer *createNewBuffer(const QByteArray &cacheId, int heightRequired);
Buffer *resizeBuffer(Buffer *buffer, const QSize &newSize);
Buffer *allocateBuffer(int width, int height);
Items *itemsForCache(const QByteArray &cacheId) const;
void pushItemToBack(Items *items, Item *item);
void touchItem(Items *items, Item *item);
void deleteItem(Items *items, Item *item);
void recycleItem(const QByteArray &cacheId, Buffer **sharedBuffer, int *glyphX, int *glyphY);
QByteArray m_currentCacheId;
quint32 m_memoryUsed;
Buffer *m_mostRecentlyUsed;
Buffer *m_leastRecentlyUsed;
mutable QHash<QByteArray, Items *> m_items;
QMultiHash<QByteArray, Buffer *> m_buffers;
PendingItemIds m_pendingInvalidatedItems;
PendingItemIds m_pendingReadyItems;
PendingItemIds m_pendingMissingItems;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QT_USE_XCB_SHARED_GRAPHICS_CACHE
#endif // XCBSHAREDBUFFERMANAGER_H

View File

@ -1,290 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
#include "qxcbsharedgraphicscache.h"
#include "qxcbsharedbuffermanager.h"
#include <QtCore/qsharedmemory.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qscreen.h>
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2ext.h>
#define SHAREDGRAPHICSCACHE_DEBUG 1
QT_BEGIN_NAMESPACE
QXcbSharedGraphicsCache::QXcbSharedGraphicsCache(QObject *parent)
: QPlatformSharedGraphicsCache(parent)
, m_bufferManager(new QXcbSharedBufferManager)
{
}
void QXcbSharedGraphicsCache::requestItems(const QByteArray &cacheId,
const QVector<quint32> &itemIds)
{
m_bufferManager->beginSharedBufferAction(cacheId);
QSet<quint32> itemsForRequest;
for (int i=0; i<itemIds.size(); ++i)
itemsForRequest.insert(itemIds.at(i));
m_bufferManager->requestItems(itemsForRequest);
m_bufferManager->endSharedBufferAction();
processPendingItems();
}
void QXcbSharedGraphicsCache::insertItems(const QByteArray &cacheId,
const QVector<quint32> &itemIds,
const QVector<QImage> &items)
{
m_bufferManager->beginSharedBufferAction(cacheId);
QSet<quint32> itemsForRequest;
for (int i=0; i<itemIds.size(); ++i) {
QImage image = items.at(i);
m_bufferManager->insertItem(itemIds.at(i), image.bits(), image.width(), image.height());
itemsForRequest.insert(itemIds.at(i));
}
// ### To avoid loops, we could check missing items here and notify the client
m_bufferManager->requestItems(itemsForRequest);
m_bufferManager->endSharedBufferAction();
processPendingItems();
}
void QXcbSharedGraphicsCache::ensureCacheInitialized(const QByteArray &cacheId,
BufferType bufferType,
PixelFormat pixelFormat)
{
Q_UNUSED(cacheId);
Q_UNUSED(bufferType);
Q_UNUSED(pixelFormat);
}
void QXcbSharedGraphicsCache::releaseItems(const QByteArray &cacheId,
const QVector<quint32> &itemIds)
{
m_bufferManager->beginSharedBufferAction(cacheId);
QSet<quint32> itemsToRelease;
for (int i=0; i<itemIds.size(); ++i)
itemsToRelease.insert(itemIds.at(i));
m_bufferManager->releaseItems(itemsToRelease);
m_bufferManager->endSharedBufferAction();
processPendingItems();
}
void QXcbSharedGraphicsCache::serializeBuffer(void *bufferId,
QByteArray *serializedData,
int *fileDescriptor) const
{
QXcbSharedBufferManager::Buffer *buffer =
reinterpret_cast<QXcbSharedBufferManager::Buffer *>(bufferId);
QPair<QByteArray, int> bufferName = m_bufferManager->serializeBuffer(buffer->buffer);
*serializedData = bufferName.first;
*fileDescriptor = bufferName.second;
}
GLuint QXcbSharedGraphicsCache::textureIdForBuffer(void *bufferId)
{
# if defined(SHAREDGRAPHICSCACHE_DEBUG)
qDebug("QXcbSharedGraphicsCache::textureIdForBuffer");
# endif
QXcbSharedBufferManager::Buffer *buffer =
reinterpret_cast<QXcbSharedBufferManager::Buffer *>(bufferId);
if (buffer->textureId == 0) {
glGenTextures(1, &buffer->textureId);
if (buffer->textureId == 0) {
qWarning("QXcbSharedGraphicsCache::textureIdForBuffer: Failed to generate texture (gl error: 0x%x)",
glGetError());
return 0;
}
glBindTexture(GL_TEXTURE_2D, buffer->textureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
glBindTexture(GL_TEXTURE_2D, buffer->textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, buffer->width, buffer->height, 0, GL_ALPHA,
GL_UNSIGNED_BYTE, buffer->buffer->data());
glBindTexture(GL_TEXTURE_2D, 0);
return buffer->textureId;
}
void QXcbSharedGraphicsCache::referenceBuffer(void *bufferId)
{
QXcbSharedBufferManager::Buffer *buffer =
reinterpret_cast<QXcbSharedBufferManager::Buffer *>(bufferId);
buffer->ref.ref();
}
bool QXcbSharedGraphicsCache::dereferenceBuffer(void *bufferId)
{
QXcbSharedBufferManager::Buffer *buffer =
reinterpret_cast<QXcbSharedBufferManager::Buffer *>(bufferId);
if (buffer->ref.deref())
return true;
if (buffer->textureId != 0) {
glDeleteTextures(1, &buffer->textureId);
buffer->textureId = 0;
}
return false;
}
void QXcbSharedGraphicsCache::processPendingItems()
{
# if defined(SHAREDGRAPHICSCACHE_DEBUG)
qDebug("QXcbSharedGraphicsCache::processPendingItems");
# endif
{
QXcbSharedBufferManager::PendingItemIds pendingMissingItems = m_bufferManager->pendingItemsMissing();
QXcbSharedBufferManager::PendingItemIds::const_iterator it;
for (it = pendingMissingItems.constBegin(); it != pendingMissingItems.constEnd(); ++it) {
QVector<quint32> missingItems;
const QSet<quint32> &items = it.value();
QSet<quint32>::const_iterator itemIt;
for (itemIt = items.constBegin(); itemIt != items.constEnd(); ++itemIt)
missingItems.append(*itemIt);
# if defined(SHAREDGRAPHICSCACHE_DEBUG)
qDebug("QXcbSharedGraphicsCache::processPendingItems: %d missing items",
missingItems.size());
# endif
if (!missingItems.isEmpty())
emit itemsMissing(it.key(), missingItems);
}
}
{
QXcbSharedBufferManager::PendingItemIds pendingInvalidatedItems = m_bufferManager->pendingItemsInvalidated();
QXcbSharedBufferManager::PendingItemIds::const_iterator it;
for (it = pendingInvalidatedItems.constBegin(); it != pendingInvalidatedItems.constEnd(); ++it) {
QVector<quint32> invalidatedItems;
const QSet<quint32> &items = it.value();
QSet<quint32>::const_iterator itemIt;
for (itemIt = items.constBegin(); itemIt != items.constEnd(); ++itemIt)
invalidatedItems.append(*itemIt);
# if defined(SHAREDGRAPHICSCACHE_DEBUG)
qDebug("QXcbSharedGraphicsCache::processPendingItems: %d invalidated items",
invalidatedItems.size());
# endif
if (!invalidatedItems.isEmpty())
emit itemsInvalidated(it.key(), invalidatedItems);
}
}
{
QXcbSharedBufferManager::PendingItemIds pendingReadyItems = m_bufferManager->pendingItemsReady();
QXcbSharedBufferManager::PendingItemIds::const_iterator it;
for (it = pendingReadyItems.constBegin(); it != pendingReadyItems.constEnd(); ++it) {
QHash<QXcbSharedBufferManager::Buffer *, ReadyItem> readyItemsForBuffer;
const QSet<quint32> &items = it.value();
QByteArray cacheId = it.key();
QSet<quint32>::const_iterator itemIt;
for (itemIt = items.constBegin(); itemIt != items.constEnd(); ++itemIt) {
QXcbSharedBufferManager::Buffer *buffer;
int x = -1;
int y = -1;
m_bufferManager->getBufferForItem(cacheId, *itemIt, &buffer, &x, &y);
readyItemsForBuffer[buffer].itemIds.append(*itemIt);
readyItemsForBuffer[buffer].positions.append(QPoint(x, y));
}
QHash<QXcbSharedBufferManager::Buffer*, ReadyItem>::iterator readyItemIt
= readyItemsForBuffer.begin();
while (readyItemIt != readyItemsForBuffer.end()) {
QXcbSharedBufferManager::Buffer *buffer = readyItemIt.key();
if (!readyItemIt.value().itemIds.isEmpty()) {
# if defined(SHAREDGRAPHICSCACHE_DEBUG)
qDebug("QXcbSharedGraphicsCache::processPendingItems: %d ready items",
readyItemIt.value().itemIds.size());
# endif
emit itemsAvailable(cacheId, buffer, QSize(buffer->width, buffer->height),
readyItemIt.value().itemIds, readyItemIt.value().positions);
}
++readyItemIt;
}
}
}
}
QT_END_NAMESPACE
#endif // QT_USE_XCB_SHARED_GRAPHICS_CACHE

View File

@ -1,91 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QXCBSHAREDGRAPHICSCACHE
#define QXCBSHAREDGRAPHICSCACHE
#if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE)
#include <QtGui/qplatformsharedgraphicscache_qpa.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QXcbSharedBufferManager;
class QXcbSharedGraphicsCache : public QPlatformSharedGraphicsCache
{
Q_OBJECT
public:
explicit QXcbSharedGraphicsCache(QObject *parent = 0);
virtual void ensureCacheInitialized(const QByteArray &cacheId, BufferType bufferType,
PixelFormat pixelFormat);
virtual void requestItems(const QByteArray &cacheId, const QVector<quint32> &itemIds);
virtual void insertItems(const QByteArray &cacheId,
const QVector<quint32> &itemIds,
const QVector<QImage> &items);
virtual void releaseItems(const QByteArray &cacheId, const QVector<quint32> &itemIds);
virtual void serializeBuffer(void *bufferId, QByteArray *serializedData, int *fileDescriptor) const;
virtual uint textureIdForBuffer(void *bufferId);
virtual void referenceBuffer(void *bufferId);
virtual bool dereferenceBuffer(void *bufferId);
private:
struct ReadyItem {
QVector<quint32> itemIds;
QVector<QPoint> positions;
};
void processPendingItems();
QXcbSharedBufferManager *m_bufferManager;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QT_USE_XCB_SHARED_GRAPHICS_CACHE
#endif // QXCBSHAREDGRAPHICSCACHE

View File

@ -20,9 +20,7 @@ SOURCES = \
main.cpp \
qxcbnativeinterface.cpp \
qxcbcursor.cpp \
qxcbimage.cpp \
qxcbsharedbuffermanager.cpp \
qxcbsharedgraphicscache.cpp
qxcbimage.cpp
HEADERS = \
qxcbclipboard.h \
@ -38,9 +36,7 @@ HEADERS = \
qxcbwmsupport.h \
qxcbnativeinterface.h \
qxcbcursor.h \
qxcbimage.h \
qxcbsharedbuffermanager.h \
qxcbsharedgraphicscache.h
qxcbimage.h
contains(QT_CONFIG, xcb-poll-for-queued-event) {
DEFINES += XCB_POLL_FOR_QUEUED_EVENT