~ubuntu-branches/ubuntu/precise/stellarium/precise

« back to all changes in this revision

Viewing changes to src/core/StelTexture.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Howard
  • Date: 2010-02-15 20:48:39 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20100215204839-u3qgbv60rho997yk
Tags: 0.10.3-0ubuntu1
* New upstream release.
  - fixes intel rendering bug (LP: #480553)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Stellarium
3
3
 * Copyright (C) 2006 Fabien Chereau
4
 
 * 
 
4
 *
5
5
 * This program is free software; you can redistribute it and/or
6
6
 * modify it under the terms of the GNU General Public License
7
7
 * as published by the Free Software Foundation; either version 2
8
8
 * of the License, or (at your option) any later version.
9
 
 * 
 
9
 *
10
10
 * This program is distributed in the hope that it will be useful,
11
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
13
 * GNU General Public License for more details.
14
 
 * 
 
14
 *
15
15
 * You should have received a copy of the GNU General Public License
16
16
 * along with this program; if not, write to the Free Software
17
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
18
 */
19
19
 
20
20
#include <cstdlib>
 
21
#include "StelTextureMgr.hpp"
21
22
#include "StelTexture.hpp"
22
 
#include "StelTextureMgr.hpp"
 
23
#include "glues.h"
23
24
#include "StelFileMgr.hpp"
24
25
#include "StelApp.hpp"
 
26
#include "StelUtils.hpp"
 
27
#include "StelMainGraphicsView.hpp"
25
28
 
26
29
#include <QThread>
27
30
#include <QMutexLocker>
35
38
#include <QDebug>
36
39
#include <QUrl>
37
40
#include <QImage>
 
41
#include <QNetworkReply>
38
42
#include <QGLWidget>
39
 
#include <QNetworkReply>
40
 
 
41
 
#if defined(__APPLE__) && defined(__MACH__)
42
 
#include <OpenGL/glu.h> /* Header File For The GLU Library */
43
 
#else
44
 
#include <GL/glu.h>     /* Header File For The GLU Library */
45
 
#endif
46
43
 
47
44
// Initialize statics
48
45
QSemaphore* StelTexture::maxLoadThreadSemaphore = new QSemaphore(5);
49
46
 
50
 
/*************************************************************************
51
 
  Class used to load an image and set the texture parameters in a thread
52
 
 *************************************************************************/
 
47
 
 
48
//  Class used to load an image and set the texture parameters in a thread
53
49
class ImageLoadThread : public QThread
54
50
{
55
51
        public:
66
62
        StelTexture::maxLoadThreadSemaphore->release(1);
67
63
}
68
64
 
69
 
/*************************************************************************
70
 
  Constructor
71
 
 *************************************************************************/
72
65
StelTexture::StelTexture() : httpReply(NULL), loadThread(NULL), downloaded(false), isLoadingImage(false),
73
 
                                   errorOccured(false), id(0), avgLuminance(-1.f), texels(NULL), type(GL_UNSIGNED_BYTE)
 
66
                                   errorOccured(false), id(0), avgLuminance(-1.f)
74
67
{
75
68
        mutex = new QMutex();
76
 
        
77
 
        texCoordinates[0].set(1., 0.);
78
 
        texCoordinates[1].set(0., 0.);
79
 
        texCoordinates[2].set(1., 1.);
80
 
        texCoordinates[3].set(0., 1.);
81
 
        
82
69
        width = -1;
83
70
        height = -1;
84
71
}
89
76
        {
90
77
                reportError("Aborted (texture deleted)");
91
78
        }
92
 
        
 
79
 
93
80
        if (httpReply)
94
81
        {
95
82
                // HTTP is still doing something for this texture. We abort it.
97
84
                delete httpReply;
98
85
                httpReply = NULL;
99
86
        }
100
 
                
 
87
 
101
88
        if (loadThread && loadThread->isRunning())
102
89
        {
103
90
                // The thread is currently running, it needs to be properly stopped
104
91
                loadThread->terminate();
105
92
                loadThread->wait(500);
106
93
        }
107
 
        
108
 
        if (texels)
109
 
                TexMalloc::free(texels);
110
 
        texels = NULL;
 
94
 
111
95
        if (id!=0)
112
96
        {
113
97
                if (glIsTexture(id)==GL_FALSE)
116
100
                }
117
101
                else
118
102
                {
119
 
                        glDeleteTextures(1, &id);
 
103
                        StelMainGraphicsView::getInstance().getOpenGLWin()->deleteTexture(id);
120
104
                }
121
105
                id = 0;
122
106
        }
143
127
        if (id!=0)
144
128
        {
145
129
                // The texture is already fully loaded, just bind and return true;
 
130
                StelApp::makeMainGLContextCurrent();
 
131
#ifdef USE_OPENGL_ES2
 
132
                glActiveTexture(GL_TEXTURE0);
 
133
#endif
146
134
                glBindTexture(GL_TEXTURE_2D, id);
147
135
                return true;
148
136
        }
156
144
                QNetworkRequest req = QNetworkRequest(QUrl(fullPath));
157
145
                // Define that preference should be given to cached files (no etag checks)
158
146
                req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
159
 
                req.setRawHeader("User-Agent", StelApp::getApplicationName().toAscii());
 
147
                req.setRawHeader("User-Agent", StelUtils::getApplicationName().toAscii());
160
148
                httpReply = StelApp::getInstance().getNetworkAccessManager()->get(req);
161
149
                connect(httpReply, SIGNAL(finished()), this, SLOT(downloadFinished()));
162
150
                return false;
163
151
        }
164
 
        
 
152
 
165
153
        // From this point we assume that fullPath is valid
166
154
        // Start loading the image in a thread and return imediately
167
155
        if (!isLoadingImage && downloaded==true)
190
178
        }
191
179
        httpReply->deleteLater();
192
180
        httpReply=NULL;
193
 
        // Call bind to activate data loading
194
 
        //bind();
195
181
}
196
182
 
197
183
/*************************************************************************
203
189
}
204
190
 
205
191
/*************************************************************************
206
 
 Return the average texture luminance, 0 is black, 1 is white
207
 
 *************************************************************************/
208
 
bool StelTexture::getAverageLuminance(float& lum)
209
 
{
210
 
        if (id==0)
211
 
                return false;
212
 
        
213
 
        QMutexLocker lock(mutex);
214
 
        if (avgLuminance<0)
215
 
        {
216
 
                int size = width*height;
217
 
                glBindTexture(GL_TEXTURE_2D, id);
218
 
                GLfloat* p = (GLfloat*)calloc(size, sizeof(GLfloat));
219
 
                Q_ASSERT(p);
220
 
 
221
 
                glGetTexImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, GL_FLOAT, p);
222
 
                float sum = 0.f;
223
 
                for (int i=0;i<size;++i)
224
 
                {
225
 
                        sum += p[i];
226
 
                }
227
 
                free(p);
228
 
 
229
 
                avgLuminance = sum/size;
230
 
        }
231
 
        lum = avgLuminance;
232
 
        return true;
233
 
}
234
 
 
235
 
 
236
 
/*************************************************************************
237
192
 Return the width and heigth of the texture in pixels
238
193
*************************************************************************/
239
194
bool StelTexture::getDimensions(int &awidth, int &aheight)
240
195
{
241
 
        QMutexLocker lock(mutex);
242
196
        if (width<0 || height<0)
243
197
        {
244
198
                // Try to get the size from the file without loading data
256
210
        return true;
257
211
}
258
212
 
259
 
/*************************************************************************
260
 
 Load the image data
261
 
 *************************************************************************/
 
213
// Load the image data
262
214
bool StelTexture::imageLoad()
263
215
{
264
 
        bool res=true;
265
216
        if (downloadedData.isEmpty())
266
217
        {
267
218
                // Load the data from the file
268
219
                QMutexLocker lock(mutex);
269
 
                res = StelApp::getInstance().getTextureManager().loadImage(this);
 
220
                qImage = QImage(fullPath);
270
221
        }
271
222
        else
272
223
        {
273
 
                // Load the image from the buffer, not from a file
274
 
                if (fullPath.endsWith(".jpg", Qt::CaseInsensitive) || fullPath.endsWith(".jpeg", Qt::CaseInsensitive))
275
 
                {
276
 
                        // Special case optimized for loading jpeg
277
 
                        // Could be even more optimized by re-using the texels buffers instead of allocating one for each textures
278
 
                        ImageLoader::TexInfo texInfo;
279
 
                        res = JpgLoader::loadFromMemory(downloadedData, texInfo);
280
 
                        if (!res)
281
 
                                return false;
282
 
 
283
 
                        {
284
 
                                QMutexLocker lock(mutex);
285
 
                                format = texInfo.format;
286
 
                                width = texInfo.width;
287
 
                                height = texInfo.height;
288
 
                                type = GL_UNSIGNED_BYTE;
289
 
                                internalFormat = texInfo.internalFormat;
290
 
                                texels = texInfo.texels;
291
 
                        }
292
 
                }
293
 
                else
294
 
                {
295
 
                        // Use Qt QImage which is slower but works for many formats
296
 
                        // This is quite slow because Qt allocates twice the memory and needs to swap from ARGB to RGBA
297
 
                        qImage = QGLWidget::convertToGLFormat(QImage::fromData(downloadedData));
298
 
                        
299
 
                        // Update texture parameters from loaded image
300
 
                        {
301
 
                                QMutexLocker lock(mutex);
302
 
                                format = GL_RGBA;
303
 
                                width = qImage.width();
304
 
                                height = qImage.height();
305
 
                                type = GL_UNSIGNED_BYTE;
306
 
                                internalFormat = 4;
307
 
                        }
308
 
                }
 
224
                qImage = QImage::fromData(downloadedData);
309
225
                // Release the memory
310
226
                downloadedData = QByteArray();
311
227
        }
312
 
        return res;
 
228
        return !qImage.isNull();
313
229
}
314
230
 
315
 
/*************************************************************************
316
 
 Actually load the texture already in the RAM to openGL memory
317
 
*************************************************************************/
 
231
// Actually load the texture to openGL memory
318
232
bool StelTexture::glLoad()
319
233
{
320
 
        if (qImage.isNull() && !texels)
 
234
        if (qImage.isNull())
321
235
        {
322
236
                errorOccured = true;
323
237
                reportError("Unknown error");
324
238
                return false;
325
239
        }
326
240
 
327
 
        // generate texture
328
 
        glGenTextures (1, &id);
329
 
        glBindTexture (GL_TEXTURE_2D, id);
330
 
 
331
 
        // setup some parameters for texture filters and mipmapping
332
 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
333
 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
334
 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
335
 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
336
 
        
337
 
        if (!qImage.isNull())
338
 
        {
339
 
                // Load from qImage
340
 
                if (mipmapsMode==true)
341
 
                        gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat, width, height, format, type, qImage.bits());
342
 
                else
343
 
                        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, qImage.bits());
344
 
                
345
 
                // Release shared memory
346
 
                qImage = QImage();
 
241
#ifdef USE_OPENGL_ES2
 
242
        glActiveTexture(GL_TEXTURE0);
 
243
#endif
 
244
 
 
245
        QGLContext::BindOptions opt = QGLContext::InvertedYBindOption;
 
246
        if (loadParams.filtering==GL_LINEAR)
 
247
                opt |= QGLContext::LinearFilteringBindOption;
 
248
 
 
249
        // Mipmap seems to be pretty buggy on windows..
 
250
#ifndef WIN32
 
251
        if (loadParams.generateMipmaps==true)
 
252
                opt |= QGLContext::MipmapBindOption;
 
253
#endif
 
254
 
 
255
        GLint glformat;
 
256
        if (qImage.isGrayscale())
 
257
        {
 
258
                glformat = qImage.hasAlphaChannel() ? GL_LUMINANCE_ALPHA : GL_LUMINANCE;
 
259
        }
 
260
        else if (qImage.hasAlphaChannel())
 
261
        {
 
262
                glformat = GL_RGBA;
347
263
        }
348
264
        else
349
 
        {
350
 
                // Fixed the bug which caused shifted loading for LUMINANCE images with non multiple of 4 widths!
351
 
                glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
352
 
                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
353
 
                
354
 
                // Load from texels buffer
355
 
                if (mipmapsMode==true)
356
 
                        gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat, width, height, format, type, texels);
357
 
                else
358
 
                        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, texels);
359
 
                
360
 
                glPopClientAttrib();
361
 
                                
362
 
                // OpenGL has its own copy of texture data
363
 
                TexMalloc::free (texels);
364
 
                texels = NULL;
365
 
        }
366
 
        
 
265
                glformat = GL_RGB;
 
266
        id = StelMainGraphicsView::getInstance().getOpenGLWin()->bindTexture(qImage, GL_TEXTURE_2D, glformat, opt);
 
267
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, loadParams.wrapMode);
 
268
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, loadParams.wrapMode);
 
269
 
 
270
        StelApp::makeMainGLContextCurrent();
 
271
 
 
272
        // Release shared memory
 
273
        qImage = QImage();
 
274
 
367
275
        // Report success of texture loading
368
276
        emit(loadingProcessFinished(false));
369
 
        
370
277
        return true;
371
278
}