Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 58 additions & 41 deletions src/private/dbackdropnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,34 +161,51 @@ class Q_DECL_HIDDEN DataManager : public DataManagerBase
return static_cast<QQuickWindow*>(parent());
}

Data *resolve(Data *data, DataKeys&&... keys) {
if (data && get()->check(data->data, std::forward<DataKeys>(keys)...)
&& dataList.contains(data)) {
return data;
std::weak_ptr<Data> resolve(std::weak_ptr<Data> data, DataKeys&&... keys) {
struct TryClean {
TryClean(DataManager *m)
: manager(m) {}
~TryClean() {
manager->tryClean();
}
DataManager *manager;
};

TryClean cleanJob(this);
Q_UNUSED(cleanJob)

{
auto d = data.lock();
if (d && dataList.contains(d)) {
if (get()->check(d->data, std::forward<DataKeys>(keys)...)) {
d->released = 0;
return data;
}
release(data);
}
}
if (data)
release(data);

for (auto data : dataList) {
for (auto data : std::as_const(dataList)) {
if (get()->check(data->data, std::forward<DataKeys>(keys)...)) {
data->released = 0;
return data;
}
}

data = new Data();
if ((data->data = get()->create(std::forward<DataKeys>(keys)...))) {
dataList.append(data);
return data;
auto newData = std::shared_ptr<Data>(new Data());
if ((newData->data = get()->create(std::forward<DataKeys>(keys)...))) {
dataList.append(newData);
return newData;
}

delete data;
return nullptr;
return {};
}

inline void release(Data *data) {
data->released++;
ensureCleanJob();
inline void release(std::weak_ptr<Data> data) {
auto d = data.lock();
if (!d)
return;
d->released++;
}

protected:
Expand All @@ -202,30 +219,27 @@ class Q_DECL_HIDDEN DataManager : public DataManagerBase

manager->cleanJob = nullptr;

QList<Data*> tmp;
QList<std::shared_ptr<Data>> tmp;
std::swap(manager->dataList, tmp);
manager->dataList.reserve(tmp.size());

for (Data *data : tmp) {
for (const auto &data : std::as_const(tmp)) {
if (data->released > 2) {
manager->get()->destroy(data->data);
delete data;
} else {
manager->dataList << data;

if (data->released > 0) {
data->released++;
manager->ensureCleanJob();
}
if (data->released > 0)
++data->released;
}
}
}

QPointer<DataManager> manager;
};

inline void ensureCleanJob() {
if (!cleanJob) {
inline void tryClean() {
if (Q_LIKELY(!cleanJob)) {
cleanJob = new CleanJob(this);
owner()->scheduleRenderJob(cleanJob, QQuickWindow::AfterRenderingStage);
}
Expand All @@ -246,13 +260,12 @@ class Q_DECL_HIDDEN DataManager : public DataManagerBase

using QObject::deleteLater;
~DataManager() {
for (auto data : dataList) {
for (auto data : std::as_const(dataList)) {
Derive::destroy(data->data);
delete data;
}
}

QList<Data*> dataList;
QList<std::shared_ptr<Data>> dataList;
QRunnable *cleanJob = nullptr;
};

Expand Down Expand Up @@ -706,8 +719,9 @@ class Q_DECL_HIDDEN RhiNode : public DBackdropNode {

if (oldManager != manager) {
sgTexture()->setTexture(nullptr);
if (oldManager && texture)
if (oldManager)
oldManager->release(texture);
texture.reset();
}

rhi = rhi->resolve(rhi, window);
Expand Down Expand Up @@ -747,10 +761,11 @@ class Q_DECL_HIDDEN RhiNode : public DBackdropNode {
}

texture = manager->resolve(texture, ct ? ct->format() : glfbManager->format(), itemPixelSize);
if (Q_UNLIKELY(!texture)) {
if (Q_UNLIKELY(texture.expired())) {
reset();
return;
}
auto texture = this->texture.lock();
Q_ASSERT(texture->data);

if (renderData) {
Expand Down Expand Up @@ -800,6 +815,7 @@ class Q_DECL_HIDDEN RhiNode : public DBackdropNode {
texture->data->pixelSize().height() / float(m_rect.height() * devicePixelRatio)});
rhi->render(renderData->rt.get());
} else {
auto rhi = this->rhi->rhi();
QPointF sourcePos = renderMatrix.map(m_rect.topLeft()) * devicePixelRatio;

if (ct) {
Expand Down Expand Up @@ -914,9 +930,9 @@ class Q_DECL_HIDDEN RhiNode : public DBackdropNode {
if (!sgTexture()->rhiTexture() && notifyTexture)
doNotifyTextureChanged();
sgTexture()->setTexture(nullptr);
if (texture && manager)
manager->release(texture);
texture = nullptr;
if (!texture.expired() && manager)
manager->release(texture.lock());
texture.reset();

#ifndef QT_NO_OPENGL
if (glfbManager)
Expand All @@ -929,14 +945,14 @@ class Q_DECL_HIDDEN RhiNode : public DBackdropNode {
renderData.reset();
node.reset();
manager = nullptr;
texture = nullptr;
texture.reset();
#ifndef QT_NO_OPENGL
glfbManager = nullptr;
#endif
}

DataManagerPointer<RhiTextureManager> manager;
RhiTextureManager::Data *texture = nullptr;
std::weak_ptr<RhiTextureManager::Data> texture;
DataManagerPointer<RhiManager> rhi;

#ifndef QT_NO_OPENGL
Expand Down Expand Up @@ -1078,7 +1094,7 @@ class Q_DECL_HIDDEN SoftwareNode : public DBackdropNode {

QImage toImage() const override
{
return image ? *image->data : QImage();
return image.expired() ? QImage() : *image.lock()->data;
}

void render(const RenderState *state) override {
Expand All @@ -1097,8 +1113,9 @@ class Q_DECL_HIDDEN SoftwareNode : public DBackdropNode {

if (oldManager != manager) {
texture()->setTexture(nullptr);
if (oldManager && image)
if (oldManager)
oldManager->release(image);
image.reset();
}

const bool hasRotation = matrix.flags().testAnyFlags(QMatrix4x4::Rotation2D | QMatrix4x4::Rotation);
Expand Down Expand Up @@ -1137,6 +1154,7 @@ class Q_DECL_HIDDEN SoftwareNode : public DBackdropNode {
image = manager->resolve(image, sourceImage.format(), pixelSize);
}

auto image = this->image.lock();
painter.begin(image->data);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setCompositionMode(QPainter::CompositionMode_Source);
Expand Down Expand Up @@ -1170,20 +1188,19 @@ class Q_DECL_HIDDEN SoftwareNode : public DBackdropNode {
if (!texture()->image().isNull() && notifyTexture)
doNotifyTextureChanged();
texture()->setTexture(nullptr);
if (image && manager)
if (manager)
manager->release(image);
image = nullptr;
image.reset();
}

void destroy() {
reset(false);
manager = nullptr;
image = nullptr;
}

friend class DBackdropNode;
DataManagerPointer<QImageManager> manager;
QImageManager::Data *image = nullptr;
std::weak_ptr<QImageManager::Data> image;
QPainter painter;
};

Expand Down
39 changes: 19 additions & 20 deletions src/private/dquickbackdropblitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ class Q_DECL_HIDDEN DQuickBackdropBlitterPrivate : public DCORE_NAMESPACE::DObje

}

~DQuickBackdropBlitterPrivate() {
cleanTextureProvider();
}

static inline DQuickBackdropBlitterPrivate *get(DQuickBackdropBlitter *qq) {
return qq->d_func();
}
Expand All @@ -59,6 +63,7 @@ class Q_DECL_HIDDEN DQuickBackdropBlitterPrivate : public DCORE_NAMESPACE::DObje
}

BlitTextureProvider *ensureTextureProvider() const;
void cleanTextureProvider();

D_DECLARE_PUBLIC(DQuickBackdropBlitter)
Content *content;
Expand Down Expand Up @@ -178,6 +183,14 @@ BlitTextureProvider *DQuickBackdropBlitterPrivate::ensureTextureProvider() const
return tp;
}

void DQuickBackdropBlitterPrivate::cleanTextureProvider()
{
if (tp) {
QQuickWindowQObjectCleanupJob::schedule(q_func()->window(), tp);
tp = nullptr;
}
}

DQuickBackdropBlitter::DQuickBackdropBlitter(QQuickItem *parent)
: QQuickItem(parent)
, DObject(*new DQuickBackdropBlitterPrivate(this))
Expand Down Expand Up @@ -240,23 +253,8 @@ static void onTextureChanged(DBackdropNode *node, void *data) {
if (!d->tp)
return;

const bool textureChanged = node->texture() != d->tp->texture();
d->tp->setTexture(node->texture());

struct Notifer : public QRunnable {
void run() override {
if (tp)
Q_EMIT tp->textureChanged();
}

QPointer<QSGTextureProvider> tp;
};

auto notifer = new Notifer();
notifer->tp = d->tp;

if (textureChanged)
d->content->window()->scheduleRenderJob(notifer, QQuickWindow::BeforeSynchronizingStage);
Q_EMIT d->tp->textureChanged();
}

QSGNode *DQuickBackdropBlitter::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *oldData)
Expand All @@ -278,6 +276,10 @@ QSGNode *DQuickBackdropBlitter::updatePaintNode(QSGNode *oldNode, QQuickItem::Up

node->setContentItem(d->container);
node->setTextureChangedCallback(onTextureChanged, d);
connect(this, &QObject::destroyed, this, [node](){
// fix callback crashed...
node->setTextureChangedCallback(nullptr, nullptr);
});
node->resize(size());
onTextureChanged(node, d);

Expand Down Expand Up @@ -307,10 +309,7 @@ void DQuickBackdropBlitter::geometryChange(const QRectF &newGeometry, const QRec
void DQuickBackdropBlitter::releaseResources()
{
D_D(DQuickBackdropBlitter);
if (d->tp) {
QQuickWindowQObjectCleanupJob::schedule(window(), d->tp);
d->tp = nullptr;
}
d->cleanTextureProvider();
}

DQUICK_END_NAMESPACE
Expand Down