~ubuntu-branches/debian/jessie/stellarium/jessie

« back to all changes in this revision

Viewing changes to src/stelutils/STexture.cpp

Tags: upstream-0.9.1
Import upstream version 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
18
 */
19
19
 
20
 
#include <cassert>
21
20
#include "STexture.hpp"
22
 
 
23
 
/*************************************************************************
24
 
 Constructor for the STexture class
25
 
*************************************************************************/
26
 
STexture::STexture() : texels(NULL), type(GL_UNSIGNED_BYTE)
 
21
#include "StelTextureMgr.hpp"
 
22
#include "StelFileMgr.hpp"
 
23
#include "StelApp.hpp"
 
24
 
 
25
#include <QThread>
 
26
#include <QMutexLocker>
 
27
#include <QSemaphore>
 
28
#include <QImageReader>
 
29
#include <QDir>
 
30
#include <QFile>
 
31
#include <QTemporaryFile>
 
32
#include <QSize>
 
33
#include <QHttp>
 
34
#include <QDebug>
 
35
#include <QUrl>
 
36
 
 
37
#if defined(__APPLE__) && defined(__MACH__)
 
38
#include <OpenGL/glu.h> /* Header File For The GLU Library */
 
39
#else
 
40
#include <GL/glu.h>     /* Header File For The GLU Library */
 
41
#endif
 
42
 
 
43
// Initialize statics
 
44
QSemaphore* STexture::maxLoadThreadSemaphore = new QSemaphore(20);
 
45
 
 
46
STexture::STexture() : downloaded(false), downloadId(0), isLoadingImage(false), imageFile(NULL), 
 
47
   errorOccured(false), id(0), avgLuminance(-1.f), texels(NULL), type(GL_UNSIGNED_BYTE)
27
48
{
 
49
        mutex = new QMutex();
 
50
        
28
51
        texCoordinates[0].set(1., 0.);
29
52
        texCoordinates[1].set(0., 0.);
30
53
        texCoordinates[2].set(1., 1.);
31
54
        texCoordinates[3].set(0., 1.);
 
55
        
 
56
        width = -1;
 
57
        height = -1;
32
58
}
33
59
 
34
 
/*************************************************************************
35
 
 Destructor for the STexture class
36
 
*************************************************************************/
37
60
STexture::~STexture()
38
61
{
39
62
        if (texels)
40
63
                delete texels;
41
64
        texels = NULL;
42
 
        glDeleteTextures(1, &id);
43
 
}
44
 
 
45
 
 
46
 
/*************************************************************************
47
 
 Return the average texture luminance : 0 is black, 1 is white
48
 
*************************************************************************/
49
 
float STexture::getAverageLuminance(void)
50
 
{
51
 
        int size = width*height;
52
 
        glBindTexture(GL_TEXTURE_2D, id);
53
 
        GLfloat* p = (GLfloat*)calloc(size, sizeof(GLfloat));
54
 
        assert(p);
55
 
 
56
 
        glGetTexImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, GL_FLOAT, p);
57
 
        float sum = 0.f;
58
 
        for (int i=0;i<size;++i)
59
 
        {
60
 
                sum += p[i];
61
 
        }
62
 
        free(p);
63
 
 
64
 
        return sum/size;
65
 
}
 
65
        if (glIsTexture(id)==GL_FALSE)
 
66
        {
 
67
                // std::cerr << "Warning: in STexture::~STexture() tried to delete invalid texture with ID=" << id << " Current GL ERROR status is " << glGetError() << std::endl;
 
68
        }
 
69
        else
 
70
        {
 
71
                glDeleteTextures(1, &id);
 
72
                // std::cerr << "Delete texture with ID=" << id << std::endl;
 
73
        }
 
74
        id = 0;
 
75
        delete mutex;
 
76
        mutex = NULL;
 
77
}
 
78
 
 
79
/*************************************************************************
 
80
 This method should be called if the texture loading failed for any reasons
 
81
 *************************************************************************/
 
82
void STexture::reportError(const QString& aerrorMessage)
 
83
{
 
84
        errorOccured = true;
 
85
        errorMessage = aerrorMessage;
 
86
        // Report failure of texture loading
 
87
        emit(loadingProcessFinished(this, true));
 
88
}
 
89
 
 
90
/*************************************************************************
 
91
  Class used to load an image and set the texture parameters in a thread
 
92
 *************************************************************************/
 
93
class ImageLoadThread : public QThread
 
94
{
 
95
        public:
 
96
                ImageLoadThread(STexture* tex) : QThread((QObject*)tex), texture(tex) {;}
 
97
                virtual void run();
 
98
        private:
 
99
                STexture* texture;
 
100
};
 
101
 
 
102
void ImageLoadThread::run()
 
103
{
 
104
        STexture::maxLoadThreadSemaphore->acquire(1);
 
105
        texture->imageLoad();
 
106
        STexture::maxLoadThreadSemaphore->release(1);
 
107
}
 
108
 
 
109
/*************************************************************************
 
110
 Bind the texture so that it can be used for openGL drawing (calls glBindTexture)
 
111
 *************************************************************************/
 
112
bool STexture::bind()
 
113
{
 
114
        if (id!=0)
 
115
        {
 
116
                // The texture is already fully loaded, just bind and return true;
 
117
                glBindTexture(GL_TEXTURE_2D, id);
 
118
                return true;
 
119
        }
 
120
        if (errorOccured)
 
121
                return false;
 
122
 
 
123
        // The texture is not yet fully loaded
 
124
        if (downloaded==false && downloadId==0 && fullPath.startsWith("http://"))
 
125
        {
 
126
                // We need to start download
 
127
                imageFile = new QTemporaryFile(QDir::tempPath() + "XXXXXX." + fileExtension, this);
 
128
                if (!imageFile->open(QIODevice::ReadWrite))
 
129
                {
 
130
                        qWarning() << "STexture::bind(): can't create temporary file " << QDir::tempPath() + "XXXXXX." + fileExtension;
 
131
                        errorOccured = true;
 
132
                        return false;
 
133
                }
 
134
                QHttp* http = StelApp::getInstance().getTextureManager().getDownloader();
 
135
                connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadFinished(int, bool)));
 
136
                QUrl url(fullPath);
 
137
                http->setHost(url.host(), url.port(80));
 
138
                downloadId = http->get(fullPath, imageFile);
 
139
                fullPath = imageFile->fileName();
 
140
                return false;
 
141
        }
 
142
        
 
143
        // From this point we assume that fullPath is valid
 
144
        // Start loading the image in a thread and return imediately
 
145
        if (!isLoadingImage)
 
146
        {
 
147
                isLoadingImage = true;
 
148
                ImageLoadThread* thread = new ImageLoadThread(this);
 
149
                connect(thread, SIGNAL(finished()), this, SLOT(fileLoadFinished()));
 
150
                thread->start();
 
151
        }
 
152
        return false;
 
153
}
 
154
 
 
155
 
 
156
/*************************************************************************
 
157
 Called when the download for the texture file terminated
 
158
*************************************************************************/
 
159
void STexture::downloadFinished(int did, bool error)
 
160
{
 
161
        if (did!=downloadId)
 
162
                return;
 
163
        imageFile->close();
 
164
        downloaded=true;
 
165
        downloadId=0;
 
166
        if (error)
 
167
        {
 
168
                qWarning() << "Texture download failed for " + imageFile->fileName()+ ": " + StelApp::getInstance().getTextureManager().getDownloader()->errorString();
 
169
                errorOccured = true;
 
170
        }
 
171
        QHttp* http = StelApp::getInstance().getTextureManager().getDownloader();
 
172
        disconnect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadFinished(int, bool)));
 
173
        
 
174
        // Call bind to activate data loading
 
175
        bind();
 
176
}
 
177
 
 
178
/*************************************************************************
 
179
 Called when the file loading thread has terminated
 
180
*************************************************************************/
 
181
void STexture::fileLoadFinished()
 
182
{
 
183
        glLoad();
 
184
}
 
185
 
 
186
/*************************************************************************
 
187
 Actually load the texture already in the RAM to openGL memory
 
188
*************************************************************************/
 
189
bool STexture::glLoad()
 
190
{
 
191
        if (!texels)
 
192
        {
 
193
                errorOccured = true;
 
194
                return false;
 
195
        }
 
196
        
 
197
        // generate texture
 
198
        glGenTextures (1, &id);
 
199
        glBindTexture (GL_TEXTURE_2D, id);
 
200
 
 
201
        // setup some parameters for texture filters and mipmapping
 
202
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
 
203
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
 
204
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
 
205
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
 
206
 
 
207
        glTexImage2D (GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, texels);
 
208
        if (mipmapsMode==true)
 
209
                gluBuild2DMipmaps (GL_TEXTURE_2D, internalFormat, width, height, format, type, texels);
 
210
        
 
211
        // OpenGL has its own copy of texture data
 
212
        free (texels);
 
213
        texels = NULL;
 
214
        
 
215
        // Report success of texture loading
 
216
        emit(loadingProcessFinished(this, false));
 
217
        
 
218
        return true;
 
219
}
 
220
 
 
221
/*************************************************************************
 
222
 Return the average texture luminance, 0 is black, 1 is white
 
223
 *************************************************************************/
 
224
bool STexture::getAverageLuminance(float& lum)
 
225
{
 
226
        if (id==0)
 
227
                return false;
 
228
        
 
229
        QMutexLocker lock(mutex);
 
230
        if (avgLuminance<0)
 
231
        {
 
232
                int size = width*height;
 
233
                glBindTexture(GL_TEXTURE_2D, id);
 
234
                GLfloat* p = (GLfloat*)calloc(size, sizeof(GLfloat));
 
235
                assert(p);
 
236
 
 
237
                glGetTexImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, GL_FLOAT, p);
 
238
                float sum = 0.f;
 
239
                for (int i=0;i<size;++i)
 
240
                {
 
241
                        sum += p[i];
 
242
                }
 
243
                free(p);
 
244
 
 
245
                avgLuminance = sum/size;
 
246
        }
 
247
        lum = avgLuminance;
 
248
        return true;
 
249
}
 
250
 
66
251
 
67
252
/*************************************************************************
68
253
 Return the width and heigth of the texture in pixels
69
254
*************************************************************************/
70
 
void STexture::getDimensions(int &awidth, int &aheight) const
 
255
bool STexture::getDimensions(int &awidth, int &aheight)
71
256
{
 
257
        QMutexLocker lock(mutex);
 
258
        if (width<0 || height<0)
 
259
        {
 
260
                // Try to get the size from the file without loading data
 
261
                QImageReader im(fullPath);
 
262
                if (!im.canRead())
 
263
                {
 
264
                        return false;
 
265
                }
 
266
                QSize size = im.size();
 
267
                width = size.width();
 
268
                height = size.height();
 
269
        }
72
270
        awidth = width;
73
271
        aheight = height;
74
 
}
 
272
        return true;
 
273
}
 
274
 
 
275
/*************************************************************************
 
276
 Load the image data
 
277
 *************************************************************************/
 
278
bool STexture::imageLoad()
 
279
{
 
280
        QMutexLocker lock(mutex);
 
281
        return StelApp::getInstance().getTextureManager().loadImage(this);
 
282
}
 
283