diff options
Diffstat (limited to 'src/declarative/items/context2d/qquickcontext2dtexture.cpp')
-rw-r--r-- | src/declarative/items/context2d/qquickcontext2dtexture.cpp | 778 |
1 files changed, 0 insertions, 778 deletions
diff --git a/src/declarative/items/context2d/qquickcontext2dtexture.cpp b/src/declarative/items/context2d/qquickcontext2dtexture.cpp deleted file mode 100644 index 1128fa224f..0000000000 --- a/src/declarative/items/context2d/qquickcontext2dtexture.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module 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$ -** -****************************************************************************/ - -#include "qquickcontext2dtexture_p.h" -#include "qquickcontext2dtile_p.h" -#include "qquickcanvasitem_p.h" -#include <private/qquickitem_p.h> -#include <private/qsgtexture_p.h> -#include "qquickcontext2dcommandbuffer_p.h" -#include <QOpenGLPaintDevice> - -#include <QOpenGLFramebufferObject> -#include <QOpenGLFramebufferObjectFormat> -#include <QtCore/QThread> - -#define QT_MINIMUM_FBO_SIZE 64 - -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; -} - - -Q_GLOBAL_STATIC(QThread, globalCanvasThreadRenderInstance) - - -QQuickContext2DTexture::QQuickContext2DTexture() - : QSGDynamicTexture() - , m_context(0) - , m_item(0) - , m_canvasSize(QSize(1, 1)) - , m_tileSize(QSize(1, 1)) - , m_canvasWindow(QRect(0, 0, 1, 1)) - , m_dirtyCanvas(false) - , m_dirtyTexture(false) - , m_threadRendering(false) - , m_smooth(false) - , m_tiledCanvas(false) - , m_doGrabImage(false) - , m_painting(false) -{ -} - -QQuickContext2DTexture::~QQuickContext2DTexture() -{ - clearTiles(); -} - -QSize QQuickContext2DTexture::textureSize() const -{ - return m_canvasWindow.size(); -} - -void QQuickContext2DTexture::markDirtyTexture() -{ - lock(); - m_dirtyTexture = true; - unlock(); - emit textureChanged(); -} - -bool QQuickContext2DTexture::setCanvasSize(const QSize &size) -{ - if (m_canvasSize != size) { - m_canvasSize = size; - m_dirtyCanvas = true; - return true; - } - return false; -} - -bool QQuickContext2DTexture::setTileSize(const QSize &size) -{ - if (m_tileSize != size) { - m_tileSize = size; - m_dirtyCanvas = true; - return true; - } - return false; -} - -void QQuickContext2DTexture::setSmooth(bool smooth) -{ - m_smooth = smooth; -} - -void QQuickContext2DTexture::setItem(QQuickCanvasItem* item) -{ - if (!item) { - lock(); - m_item = 0; - m_context = 0; - unlock(); - wake(); - } else if (m_item != item) { - lock(); - m_item = item; - m_context = item->context(); - m_state = m_context->state; - unlock(); - connect(this, SIGNAL(textureChanged()), m_item, SIGNAL(painted())); - } -} - -bool QQuickContext2DTexture::setCanvasWindow(const QRect& r) -{ - if (m_canvasWindow != r) { - m_canvasWindow = r; - return true; - } - return false; -} - -bool QQuickContext2DTexture::setDirtyRect(const QRect &r) -{ - bool doDirty = false; - if (m_tiledCanvas) { - foreach (QQuickContext2DTile* t, m_tiles) { - bool dirty = t->rect().intersected(r).isValid(); - t->markDirty(dirty); - if (dirty) - doDirty = true; - } - } else { - doDirty = m_canvasWindow.intersected(r).isValid(); - } - return doDirty; -} - -void QQuickContext2DTexture::canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth) -{ - lock(); - - QSize ts = tileSize; - if (ts.width() > canvasSize.width()) - ts.setWidth(canvasSize.width()); - - if (ts.height() > canvasSize.height()) - ts.setHeight(canvasSize.height()); - - setCanvasSize(canvasSize); - setTileSize(ts); - - if (canvasSize == canvasWindow.size()) { - m_tiledCanvas = false; - m_dirtyCanvas = false; - } else { - m_tiledCanvas = true; - } - - bool doDirty = false; - if (dirtyRect.isValid()) - doDirty = setDirtyRect(dirtyRect); - - bool windowChanged = setCanvasWindow(canvasWindow); - if (windowChanged || doDirty) { - if (m_threadRendering) - QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection); - else if (supportDirectRendering()) { - QMetaObject::invokeMethod(this, "paint", Qt::DirectConnection); - } - } - - setSmooth(smooth); - unlock(); -} - -void QQuickContext2DTexture::paintWithoutTiles() -{ - QQuickContext2DCommandBuffer* ccb = m_context->buffer(); - - if (ccb->isEmpty() && m_threadRendering && !m_doGrabImage) { - lock(); - if (m_item) - QMetaObject::invokeMethod(m_item, "_doPainting", Qt::QueuedConnection, Q_ARG(QRectF, QRectF(0, 0, m_canvasSize.width(), m_canvasSize.height()))); - wait(); - unlock(); - } - if (ccb->isEmpty()) { - return; - } - - QPaintDevice* device = beginPainting(); - if (!device) { - endPainting(); - return; - } - - QPainter p; - p.begin(device); - if (m_smooth) - p.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing - | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - else - p.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing - | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, false); - p.setCompositionMode(QPainter::CompositionMode_SourceOver); - ccb->replay(&p, m_state); - - ccb->clear(); - markDirtyTexture(); - endPainting(); -} - -bool QQuickContext2DTexture::canvasDestroyed() -{ - bool noCanvas = false; - lock(); - noCanvas = m_item == 0; - unlock(); - return noCanvas; -} - -void QQuickContext2DTexture::paint() -{ - if (canvasDestroyed()) - return; - - if (!m_tiledCanvas) { - paintWithoutTiles(); - } else { - lock(); - QRect tiledRegion = createTiles(m_canvasWindow.intersected(QRect(QPoint(0, 0), m_canvasSize))); - unlock(); - - if (!tiledRegion.isEmpty()) { - if (m_threadRendering && !m_doGrabImage) { - QRect dirtyRect; - - lock(); - foreach (QQuickContext2DTile* tile, m_tiles) { - if (tile->dirty()) { - if (dirtyRect.isEmpty()) - dirtyRect = tile->rect(); - else - dirtyRect |= tile->rect(); - } - } - unlock(); - - if (dirtyRect.isValid()) { - lock(); - if (m_item) - QMetaObject::invokeMethod(m_item, "_doPainting", Qt::QueuedConnection, Q_ARG(QRectF, dirtyRect)); - wait(); - unlock(); - } - } - - if (beginPainting()) { - QQuickContext2D::State oldState = m_state; - QQuickContext2DCommandBuffer* ccb = m_context->buffer(); - foreach (QQuickContext2DTile* tile, m_tiles) { - bool dirtyTile = false, dirtyCanvas = false, smooth = false; - - lock(); - dirtyTile = tile->dirty(); - smooth = m_smooth; - dirtyCanvas = m_dirtyCanvas; - unlock(); - - //canvas size or tile size may change during painting tiles - if (dirtyCanvas) { - if (m_threadRendering) - QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection); - endPainting(); - return; - } else if (dirtyTile) { - ccb->replay(tile->createPainter(smooth), oldState); - tile->drawFinished(); - lock(); - tile->markDirty(false); - unlock(); - } - - compositeTile(tile); - } - ccb->clear(); - endPainting(); - m_state = oldState; - markDirtyTexture(); - } - } - } -} - -QRect QQuickContext2DTexture::tiledRect(const QRectF& window, const QSize& tileSize) -{ - if (window.isEmpty()) - return QRect(); - - const int tw = tileSize.width(); - const int th = tileSize.height(); - const int h1 = window.left() / tw; - const int v1 = window.top() / th; - - const int htiles = ((window.right() - h1 * tw) + tw - 1)/tw; - const int vtiles = ((window.bottom() - v1 * th) + th - 1)/th; - - return QRect(h1 * tw, v1 * th, htiles * tw, vtiles * th); -} - -QRect QQuickContext2DTexture::createTiles(const QRect& window) -{ - QList<QQuickContext2DTile*> oldTiles = m_tiles; - m_tiles.clear(); - - if (window.isEmpty()) { - m_dirtyCanvas = false; - return QRect(); - } - - QRect r = tiledRect(window, m_tileSize); - - const int tw = m_tileSize.width(); - const int th = m_tileSize.height(); - const int h1 = window.left() / tw; - const int v1 = window.top() / th; - - - const int htiles = r.width() / tw; - const int vtiles = r.height() / th; - - for (int yy = 0; yy < vtiles; ++yy) { - for (int xx = 0; xx < htiles; ++xx) { - int ht = xx + h1; - int vt = yy + v1; - - QQuickContext2DTile* tile = 0; - - QPoint pos(ht * tw, vt * th); - QRect rect(pos, m_tileSize); - - for (int i = 0; i < oldTiles.size(); i++) { - if (oldTiles[i]->rect() == rect) { - tile = oldTiles.takeAt(i); - break; - } - } - - if (!tile) - tile = createTile(); - - tile->setRect(rect); - m_tiles.append(tile); - } - } - - qDeleteAll(oldTiles); - - m_dirtyCanvas = false; - return r; -} - -void QQuickContext2DTexture::clearTiles() -{ - qDeleteAll(m_tiles); - m_tiles.clear(); -} - -QQuickContext2DFBOTexture::QQuickContext2DFBOTexture() - : QQuickContext2DTexture() - , m_fbo(0) - , m_multisampledFbo(0) - , m_paint_device(0) -{ - m_threadRendering = false; -} - -QQuickContext2DFBOTexture::~QQuickContext2DFBOTexture() -{ - delete m_fbo; - delete m_multisampledFbo; - delete m_paint_device; -} - -bool QQuickContext2DFBOTexture::setCanvasSize(const QSize &size) -{ - QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width())) - , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height()))); - - if (m_canvasSize != s) { - m_canvasSize = s; - m_dirtyCanvas = true; - return true; - } - return false; -} - -bool QQuickContext2DFBOTexture::setTileSize(const QSize &size) -{ - QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width())) - , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height()))); - if (m_tileSize != s) { - m_tileSize = s; - m_dirtyCanvas = true; - return true; - } - return false; -} - -bool QQuickContext2DFBOTexture::setCanvasWindow(const QRect& canvasWindow) -{ - QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(canvasWindow.size().width())) - , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(canvasWindow.size().height()))); - - - bool doChanged = false; - if (m_fboSize != s) { - m_fboSize = s; - doChanged = true; - } - - if (m_canvasWindow != canvasWindow) - m_canvasWindow = canvasWindow; - - return doChanged; -} - -void QQuickContext2DFBOTexture::bind() -{ - glBindTexture(GL_TEXTURE_2D, textureId()); - updateBindOptions(); -} - -QRectF QQuickContext2DFBOTexture::textureSubRect() const -{ - return QRectF(0 - , 0 - , qreal(m_canvasWindow.width()) / m_fboSize.width() - , qreal(m_canvasWindow.height()) / m_fboSize.height()); -} - - -int QQuickContext2DFBOTexture::textureId() const -{ - return m_fbo? m_fbo->texture() : 0; -} - - -bool QQuickContext2DFBOTexture::updateTexture() -{ - if (!m_context->buffer()->isEmpty()) { - paint(); - } - - bool textureUpdated = m_dirtyTexture; - - m_dirtyTexture = false; - - if (m_doGrabImage) { - grabImage(); - m_condition.wakeOne(); - m_doGrabImage = false; - } - return textureUpdated; -} - -QQuickContext2DTile* QQuickContext2DFBOTexture::createTile() const -{ - return new QQuickContext2DFBOTile(); -} - -void QQuickContext2DFBOTexture::grabImage() -{ - if (m_fbo) { - m_grabedImage = m_fbo->toImage(); - } -} - -bool QQuickContext2DFBOTexture::doMultisampling() const -{ - static bool extensionsChecked = false; - static bool multisamplingSupported = false; - - if (!extensionsChecked) { - QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' '); - multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample") - && extensions.contains("GL_EXT_framebuffer_blit"); - extensionsChecked = true; - } - - return multisamplingSupported && m_smooth; -} - -QImage QQuickContext2DFBOTexture::toImage(const QRectF& region) -{ -#define QML_CONTEXT2D_WAIT_MAX 5000 - - m_doGrabImage = true; - if (m_item) - m_item->update(); - - QImage grabbed; - m_mutex.lock(); - bool ok = m_condition.wait(&m_mutex, QML_CONTEXT2D_WAIT_MAX); - - if (!ok) - grabbed = QImage(); - - if (region.isValid()) - grabbed = m_grabedImage.copy(region.toRect()); - else - grabbed = m_grabedImage; - m_grabedImage = QImage(); - return grabbed; -} - -void QQuickContext2DFBOTexture::compositeTile(QQuickContext2DTile* tile) -{ - QQuickContext2DFBOTile* t = static_cast<QQuickContext2DFBOTile*>(tile); - QRect target = t->rect().intersect(m_canvasWindow); - if (target.isValid()) { - QRect source = target; - - source.moveTo(source.topLeft() - t->rect().topLeft()); - target.moveTo(target.topLeft() - m_canvasWindow.topLeft()); - - QOpenGLFramebufferObject::blitFramebuffer(m_fbo, target, t->fbo(), source); - } -} -QQuickCanvasItem::RenderTarget QQuickContext2DFBOTexture::renderTarget() const -{ - return QQuickCanvasItem::FramebufferObject; -} -QPaintDevice* QQuickContext2DFBOTexture::beginPainting() -{ - QQuickContext2DTexture::beginPainting(); - - if (m_canvasWindow.size().isEmpty() && !m_threadRendering) { - delete m_fbo; - delete m_multisampledFbo; - m_fbo = 0; - m_multisampledFbo = 0; - return 0; - } else if (!m_fbo || m_fbo->size() != m_fboSize) { - delete m_fbo; - delete m_multisampledFbo; - if (doMultisampling()) { - { - QOpenGLFramebufferObjectFormat format; - format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); - format.setSamples(8); - m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format); - } - { - QOpenGLFramebufferObjectFormat format; - format.setAttachment(QOpenGLFramebufferObject::NoAttachment); - m_fbo = new QOpenGLFramebufferObject(m_fboSize, format); - } - } else { - QOpenGLFramebufferObjectFormat format; - format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); - - m_fbo = new QOpenGLFramebufferObject(m_fboSize, format); - } - } - - if (doMultisampling()) - m_multisampledFbo->bind(); - else - m_fbo->bind(); - - - if (!m_paint_device) { - QOpenGLPaintDevice *gl_device = new QOpenGLPaintDevice(m_fbo->size()); - gl_device->setPaintFlipped(true); - m_paint_device = gl_device; - } - - return m_paint_device; -} - -void QQuickContext2DFBOTexture::endPainting() -{ - QQuickContext2DTexture::endPainting(); - if (m_multisampledFbo) { - QOpenGLFramebufferObject::blitFramebuffer(m_fbo, m_multisampledFbo); - m_multisampledFbo->release(); - } else if (m_fbo) - m_fbo->release(); -} -void qt_quit_context2d_render_thread() -{ - QThread* thread = globalCanvasThreadRenderInstance(); - - if (thread->isRunning()) { - thread->exit(0); - thread->wait(1000); - } -} - -QQuickContext2DImageTexture::QQuickContext2DImageTexture(bool threadRendering) - : QQuickContext2DTexture() - , m_texture(new QSGPlainTexture()) -{ - m_texture->setOwnsTexture(true); - m_texture->setHasMipmaps(false); - - m_threadRendering = threadRendering; - - if (m_threadRendering) { - QThread* thread = globalCanvasThreadRenderInstance(); - moveToThread(thread); - - if (!thread->isRunning()) { - qAddPostRoutine(qt_quit_context2d_render_thread); - thread->start(); - } - } -} - -QQuickContext2DImageTexture::~QQuickContext2DImageTexture() -{ - delete m_texture; -} - -int QQuickContext2DImageTexture::textureId() const -{ - return m_texture->textureId(); -} - -void QQuickContext2DImageTexture::lock() -{ - if (m_threadRendering) - m_mutex.lock(); -} -void QQuickContext2DImageTexture::unlock() -{ - if (m_threadRendering) - m_mutex.unlock(); -} - -void QQuickContext2DImageTexture::wait() -{ - if (m_threadRendering) - m_waitCondition.wait(&m_mutex); -} - -void QQuickContext2DImageTexture::wake() -{ - if (m_threadRendering) - m_waitCondition.wakeOne(); -} - -bool QQuickContext2DImageTexture::supportDirectRendering() const -{ - return !m_threadRendering; -} - -QQuickCanvasItem::RenderTarget QQuickContext2DImageTexture::renderTarget() const -{ - return QQuickCanvasItem::Image; -} - -void QQuickContext2DImageTexture::bind() -{ - m_texture->bind(); -} - -bool QQuickContext2DImageTexture::updateTexture() -{ - lock(); - bool textureUpdated = m_dirtyTexture; - if (m_dirtyTexture) { - m_texture->setImage(m_image); - m_dirtyTexture = false; - } - unlock(); - return textureUpdated; -} - -QQuickContext2DTile* QQuickContext2DImageTexture::createTile() const -{ - return new QQuickContext2DImageTile(); -} - -void QQuickContext2DImageTexture::grabImage(const QRect& r) -{ - m_doGrabImage = true; - paint(); - m_doGrabImage = false; - m_grabedImage = m_image.copy(r); -} - -QImage QQuickContext2DImageTexture::toImage(const QRectF& region) -{ - QRect r = region.isValid() ? region.toRect() : QRect(QPoint(0, 0), m_canvasWindow.size()); - if (threadRendering()) { - wake(); - QMetaObject::invokeMethod(this, "grabImage", Qt::BlockingQueuedConnection, Q_ARG(QRect, r)); - } else { - QMetaObject::invokeMethod(this, "grabImage", Qt::DirectConnection, Q_ARG(QRect, r)); - } - QImage image = m_grabedImage; - m_grabedImage = QImage(); - return image; -} - -QPaintDevice* QQuickContext2DImageTexture::beginPainting() -{ - QQuickContext2DTexture::beginPainting(); - - if (m_canvasWindow.size().isEmpty()) - return 0; - - lock(); - if (m_image.size() != m_canvasWindow.size()) { - m_image = QImage(m_canvasWindow.size(), QImage::Format_ARGB32_Premultiplied); - m_image.fill(0x00000000); - } - unlock(); - return &m_image; -} - -void QQuickContext2DImageTexture::compositeTile(QQuickContext2DTile* tile) -{ - Q_ASSERT(!tile->dirty()); - QQuickContext2DImageTile* t = static_cast<QQuickContext2DImageTile*>(tile); - QRect target = t->rect().intersect(m_canvasWindow); - if (target.isValid()) { - QRect source = target; - source.moveTo(source.topLeft() - t->rect().topLeft()); - target.moveTo(target.topLeft() - m_canvasWindow.topLeft()); - - lock(); - m_painter.begin(&m_image); - m_painter.setCompositionMode(QPainter::CompositionMode_Source); - m_painter.drawImage(target, t->image(), source); - m_painter.end(); - unlock(); - } -} |