Merge pull request #7553 from zzmp/fix/tex-invoke-method

Fix ImageReader threading issues
This commit is contained in:
Brad Hefta-Gaub 2016-04-04 18:29:24 -07:00
commit ff4f693267

View file

@ -13,20 +13,22 @@
#include <mutex>
#include <glm/glm.hpp>
#include <glm/gtc/random.hpp>
#include <QNetworkReply>
#include <QPainter>
#include <QRunnable>
#include <QThreadPool>
#include <qimagereader.h>
#include <QImageReader>
#include <shared/NsightHelpers.h>
#include <PathUtils.h>
#include <glm/glm.hpp>
#include <glm/gtc/random.hpp>
#include <gpu/Batch.h>
#include <shared/NsightHelpers.h>
#include <Finally.h>
#include <PathUtils.h>
#include "ModelNetworkingLogging.h"
TextureCache::TextureCache() {
@ -242,14 +244,14 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
class ImageReader : public QRunnable {
public:
ImageReader(const QWeakPointer<Resource>& texture, const QByteArray& data, const QUrl& url = QUrl());
ImageReader(const QWeakPointer<Resource>& resource, const QByteArray& data, const QUrl& url = QUrl());
virtual void run();
private:
static void listSupportedImageFormats();
QWeakPointer<Resource> _texture;
QWeakPointer<Resource> _resource;
QUrl _url;
QByteArray _content;
};
@ -263,9 +265,9 @@ void NetworkTexture::loadContent(const QByteArray& content) {
QThreadPool::globalInstance()->start(new ImageReader(_self, content, _url));
}
ImageReader::ImageReader(const QWeakPointer<Resource>& texture, const QByteArray& data,
ImageReader::ImageReader(const QWeakPointer<Resource>& resource, const QByteArray& data,
const QUrl& url) :
_texture(texture),
_resource(resource),
_url(url),
_content(data)
{
@ -286,17 +288,19 @@ void ImageReader::run() {
originalPriority = QThread::NormalPriority;
}
QThread::currentThread()->setPriority(QThread::LowPriority);
Finally restorePriority([originalPriority]{
QThread::currentThread()->setPriority(originalPriority);
});
auto texture = _texture.toStrongRef();
if (!texture) {
qCWarning(modelnetworking) << "Could not get strong ref";
if (!_resource.data()) {
qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref";
return;
}
listSupportedImageFormats();
// try to help the QImage loader by extracting the image file format from the url filename ext
// Some tga are not created properly for example without it
// Help the QImage loader by extracting the image file format from the url filename ext.
// Some tga are not created properly without it.
auto filename = _url.fileName().toStdString();
auto filenameExtension = filename.substr(filename.find_last_of('.') + 1);
QImage image = QImage::fromData(_content, filenameExtension.c_str());
@ -315,17 +319,31 @@ void ImageReader::run() {
return;
}
gpu::Texture* theTexture = nullptr;
auto ntex = texture.dynamicCast<NetworkTexture>();
if (ntex) {
PROFILE_RANGE_EX(__FUNCTION__"::textureLoader", 0xffffff00, nullptr);
theTexture = ntex->getTextureLoader()(image, _url.toString().toStdString());
gpu::Texture* texture = nullptr;
{
// Double-check the resource still exists between long operations.
auto resource = _resource.toStrongRef();
if (!resource) {
qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref";
return;
}
QMetaObject::invokeMethod(texture.data(), "setImage",
Q_ARG(void*, theTexture),
auto url = _url.toString().toStdString();
PROFILE_RANGE_EX(__FUNCTION__"::textureLoader", 0xffffff00, nullptr);
texture = resource.dynamicCast<NetworkTexture>()->getTextureLoader()(image, url);
}
// Ensure the resource has not been deleted, and won't be while invokeMethod is in flight.
auto resource = _resource.toStrongRef();
if (!resource) {
qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref";
delete texture;
} else {
QMetaObject::invokeMethod(resource.data(), "setImage", Qt::BlockingQueuedConnection,
Q_ARG(void*, texture),
Q_ARG(int, originalWidth), Q_ARG(int, originalHeight));
QThread::currentThread()->setPriority(originalPriority);
}
}
void NetworkTexture::setImage(void* voidTexture, int originalWidth,