Fix ImageReader threading issues

This commit is contained in:
Zach Pomerantz 2016-04-03 11:53:59 -07:00
parent d899d7d696
commit 79e5286335

View file

@ -240,14 +240,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;
};
@ -261,9 +261,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)
{
@ -284,16 +284,16 @@ void ImageReader::run() {
}
QThread::currentThread()->setPriority(QThread::LowPriority);
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";
QThread::currentThread()->setPriority(originalPriority);
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());
@ -312,15 +312,31 @@ void ImageReader::run() {
return;
}
gpu::Texture* theTexture = nullptr;
auto ntex = texture.dynamicCast<NetworkTexture>();
if (ntex) {
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";
QThread::currentThread()->setPriority(originalPriority);
return;
}
QMetaObject::invokeMethod(texture.data(), "setImage",
Q_ARG(void*, theTexture),
auto url = _url.toString().toStdString();
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);
}