StelTexture.cpp   StelTexture.cpp 
skipping to change at line 44 skipping to change at line 44
#include <QFile> #include <QFile>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QSize> #include <QSize>
#include <QHttp> #include <QHttp>
#include <QDebug> #include <QDebug>
#include <QUrl> #include <QUrl>
#include <QImage> #include <QImage>
#include <QNetworkReply> #include <QNetworkReply>
#include <QGLWidget> #include <QGLWidget>
// Initialize statics ImageLoader::ImageLoader(const QString& path, int delay)
QSemaphore* StelTexture::maxLoadThreadSemaphore = new QSemaphore(5); : QObject(), path(path), networkReply(NULL)
{
QTimer::singleShot(delay, this, SLOT(start()));
}
// Class used to load an image and set the texture parameters in a thread void ImageLoader::abort()
class ImageLoadThread : public QThread
{ {
public: // XXX: Assert that we are in the main thread.
ImageLoadThread(StelTexture* tex) : QThread((QObject*)tex), if (networkReply != NULL)
texture(tex) {;} {
virtual void run(); networkReply->abort();
private: }
StelTexture* texture; }
};
void ImageLoadThread::run() void ImageLoader::start()
{ {
StelTexture::maxLoadThreadSemaphore->acquire(1); if (path.startsWith("http://")) {
texture->imageLoad(); QNetworkRequest req = QNetworkRequest(QUrl(path));
StelTexture::maxLoadThreadSemaphore->release(1); // Define that preference should be given to cached files (n
o etag checks)
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
QNetworkRequest::PreferCache);
req.setRawHeader("User-Agent", StelUtils::getApplicationName
().toAscii());
networkReply = StelApp::getInstance().getNetworkAccessManage
r()->get(req);
connect(networkReply, SIGNAL(finished()), this, SLOT(onNetwo
rkReply()));
} else {
// At next loop iteration we start to load from the file.
QTimer::singleShot(0, this, SLOT(directLoad()));
}
// Move this object outside of the main thread.
StelTextureMgr* textureMgr = &StelApp::getInstance().getTextureManag
er();
moveToThread(textureMgr->loaderThread);
}
void ImageLoader::onNetworkReply()
{
if (networkReply->error() != QNetworkReply::NoError) {
emit error(networkReply->errorString());
} else {
QByteArray data = networkReply->readAll();
QImage image = QImage::fromData(data);
if (image.isNull()) {
emit error("Unable to parse image data");
} else {
emit finished(image);
}
}
networkReply->deleteLater();
networkReply = NULL;
}
void ImageLoader::directLoad() {
QImage image = QImage(path);
emit finished(image);
} }
StelTexture::StelTexture() : httpReply(NULL), loadThread(NULL), downloaded( false), isLoadingImage(false), StelTexture::StelTexture() : loader(NULL), downloaded(false), isLoadingImag e(false),
errorOccured(false), id(0), avgLuminance( -1.f) errorOccured(false), id(0), avgLuminance( -1.f)
{ {
mutex = new QMutex();
width = -1; width = -1;
height = -1; height = -1;
} }
StelTexture::~StelTexture() StelTexture::~StelTexture()
{ {
if (httpReply || (loadThread && loadThread->isRunning())) if (id != 0)
{
reportError("Aborted (texture deleted)");
}
if (httpReply)
{
// HTTP is still doing something for this texture. We abort
it.
httpReply->abort();
delete httpReply;
httpReply = NULL;
}
if (loadThread && loadThread->isRunning())
{
// The thread is currently running, it needs to be properly
stopped
loadThread->terminate();
loadThread->wait(500);
}
if (id!=0)
{ {
StelPainter::makeMainGLContextCurrent(); StelPainter::makeMainGLContextCurrent();
if (glIsTexture(id)==GL_FALSE) if (glIsTexture(id)==GL_FALSE)
{ {
qDebug() << "WARNING: in StelTexture::~StelTexture() tried to delete invalid texture with ID=" << id << " Current GL ERROR stat us is " << glGetError(); qDebug() << "WARNING: in StelTexture::~StelTexture() tried to delete invalid texture with ID=" << id << " Current GL ERROR stat us is " << glGetError();
} }
else else
{ {
StelPainter::glContext->deleteTexture(id); StelPainter::glContext->deleteTexture(id);
} }
id = 0; id = 0;
} }
delete mutex; if (loader != NULL) {
mutex = NULL; loader->abort();
// Don't forget that the loader has no parent.
loader->deleteLater();
loader = NULL;
}
} }
/************************************************************************* /*************************************************************************
This method should be called if the texture loading failed for any reasons This method should be called if the texture loading failed for any reasons
*************************************************************************/ *************************************************************************/
void StelTexture::reportError(const QString& aerrorMessage) void StelTexture::reportError(const QString& aerrorMessage)
{ {
errorOccured = true; errorOccured = true;
errorMessage = aerrorMessage; errorMessage = aerrorMessage;
isLoadingImage = false;
// Report failure of texture loading // Report failure of texture loading
emit(loadingProcessFinished(true)); emit(loadingProcessFinished(true));
} }
/************************************************************************* /*************************************************************************
Bind the texture so that it can be used for openGL drawing (calls glBindTe xture) Bind the texture so that it can be used for openGL drawing (calls glBindTe xture)
*************************************************************************/ *************************************************************************/
bool StelTexture::bind() bool StelTexture::bind()
{ {
if (id!=0) // qDebug() << "TEST bind" << fullPath;
if (id != 0)
{ {
// The texture is already fully loaded, just bind and return true; // The texture is already fully loaded, just bind and return true;
#ifdef USE_OPENGL_ES2 #ifdef USE_OPENGL_ES2
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
#endif #endif
glBindTexture(GL_TEXTURE_2D, id); glBindTexture(GL_TEXTURE_2D, id);
return true; return true;
} }
if (errorOccured) if (errorOccured)
return false; return false;
// The texture is not yet fully loaded if (!isLoadingImage && loader == NULL) {
if (downloaded==false && httpReply==NULL && fullPath.startsWith("htt
p://"))
{
// We need to start download
QNetworkRequest req = QNetworkRequest(QUrl(fullPath));
// Define that preference should be given to cached files (n
o etag checks)
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
QNetworkRequest::PreferCache);
req.setRawHeader("User-Agent", StelUtils::getApplicationName
().toAscii());
httpReply = StelApp::getInstance().getNetworkAccessManager()
->get(req);
connect(httpReply, SIGNAL(finished()), this, SLOT(downloadFi
nished()));
return false;
}
// From this point we assume that fullPath is valid
// Start loading the image in a thread and return imediately
if (!isLoadingImage && downloaded==true)
{
isLoadingImage = true; isLoadingImage = true;
loadThread = new ImageLoadThread(this); loader = new ImageLoader(fullPath, 100);
connect(loadThread, SIGNAL(finished()), this, SLOT(fileLoadF connect(loader, SIGNAL(finished(QImage)), this, SLOT(onImage
inished())); Loaded(QImage)));
loadThread->start(QThread::LowestPriority); connect(loader, SIGNAL(error(QString)), this, SLOT(onLoading
Error(QString)));
} }
return false;
}
/************************************************************************* return false;
Called when the download for the texture file terminated
*************************************************************************/
void StelTexture::downloadFinished()
{
downloadedData = httpReply->readAll();
downloaded=true;
if (httpReply->error()!=QNetworkReply::NoError || errorOccured)
{
if (httpReply->error()!=QNetworkReply::OperationCanceledErro
r)
qWarning() << "Texture download failed for " + fullP
ath+ ": " + httpReply->errorString();
errorOccured = true;
}
httpReply->deleteLater();
httpReply=NULL;
} }
/************************************************************************* void StelTexture::onImageLoaded(QImage image)
Called when the file loading thread has terminated
*************************************************************************/
void StelTexture::fileLoadFinished()
{ {
qImage = image;
Q_ASSERT(!qImage.isNull());
glLoad(); glLoad();
isLoadingImage = false;
loader->deleteLater();
loader = NULL;
} }
/************************************************************************* /*************************************************************************
Return the width and heigth of the texture in pixels Return the width and heigth of the texture in pixels
*************************************************************************/ *************************************************************************/
bool StelTexture::getDimensions(int &awidth, int &aheight) bool StelTexture::getDimensions(int &awidth, int &aheight)
{ {
if (width<0 || height<0) if (width<0 || height<0)
{ {
if (!qImage.isNull()) if (!qImage.isNull())
skipping to change at line 219 skipping to change at line 210
QSize size = im.size(); QSize size = im.size();
width = size.width(); width = size.width();
height = size.height(); height = size.height();
} }
} }
awidth = width; awidth = width;
aheight = height; aheight = height;
return true; return true;
} }
// Load the image data
bool StelTexture::imageLoad()
{
if (downloadedData.isEmpty())
{
// Load the data from the file
QMutexLocker lock(mutex);
qImage = QImage(fullPath);
}
else
{
qImage = QImage::fromData(downloadedData);
// Release the memory
downloadedData = QByteArray();
}
return !qImage.isNull();
}
// Actually load the texture to openGL memory // Actually load the texture to openGL memory
bool StelTexture::glLoad() bool StelTexture::glLoad()
{ {
if (qImage.isNull()) if (qImage.isNull())
{ {
errorOccured = true; errorOccured = true;
reportError("Unknown error"); reportError("Unknown error");
return false; return false;
} }
 End of changes. 19 change blocks. 
111 lines changed or deleted 80 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/