~saviq/ubuntu/saucy/qtdeclarative-opensource-src/add-qtquick-delegate-range

« back to all changes in this revision

Viewing changes to src/quick/scenegraph/util/qsgtexture.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 14:17:19 UTC
  • Revision ID: package-import@ubuntu.com-20130205141719-qqeyml8wslpyez52
Tags: upstream-5.0.1
ImportĀ upstreamĀ versionĀ 5.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtQml module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#define GL_GLEXT_PROTOTYPES
 
43
 
 
44
#include "qsgtexture_p.h"
 
45
#include <qopenglfunctions.h>
 
46
#include <QtQuick/private/qsgcontext_p.h>
 
47
#include <qthread.h>
 
48
#include <private/qqmlprofilerservice_p.h>
 
49
#include <private/qqmlglobal_p.h>
 
50
 
 
51
#if defined(Q_OS_LINUX) && !defined(Q_OS_LINUX_ANDROID)
 
52
#define CAN_BACKTRACE_EXECINFO
 
53
#endif
 
54
 
 
55
#if defined(Q_OS_MAC)
 
56
#define CAN_BACKTRACE_EXECINFO
 
57
#endif
 
58
 
 
59
#if defined(QT_NO_DEBUG)
 
60
#undef CAN_BACKTRACE_EXECINFO
 
61
#endif
 
62
 
 
63
#if defined(CAN_BACKTRACE_EXECINFO)
 
64
#include <execinfo.h>
 
65
#include <QHash>
 
66
#endif
 
67
 
 
68
QT_BEGIN_NAMESPACE
 
69
 
 
70
inline static bool isPowerOfTwo(int x)
 
71
{
 
72
    // Assumption: x >= 1
 
73
    return x == (x & -x);
 
74
}
 
75
 
 
76
QSGTexturePrivate::QSGTexturePrivate()
 
77
    : wrapChanged(false)
 
78
    , filteringChanged(false)
 
79
    , horizontalWrap(QSGTexture::ClampToEdge)
 
80
    , verticalWrap(QSGTexture::ClampToEdge)
 
81
    , mipmapMode(QSGTexture::None)
 
82
    , filterMode(QSGTexture::Nearest)
 
83
{
 
84
}
 
85
 
 
86
#ifndef QT_NO_DEBUG
 
87
 
 
88
static int qt_debug_texture_count = 0;
 
89
 
 
90
#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
 
91
DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE)
 
92
 
 
93
#define BACKTRACE_SIZE 20
 
94
class SGTextureTraceItem
 
95
{
 
96
public:
 
97
    void *backTrace[BACKTRACE_SIZE];
 
98
    size_t backTraceSize;
 
99
};
 
100
 
 
101
static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures;
 
102
#endif
 
103
 
 
104
inline static void qt_debug_print_texture_count()
 
105
{
 
106
    qDebug("Number of leaked textures: %i", qt_debug_texture_count);
 
107
    qt_debug_texture_count = -1;
 
108
 
 
109
#if defined(CAN_BACKTRACE_EXECINFO)
 
110
    if (qmlDebugLeakBacktrace()) {
 
111
        while (!qt_debug_allocated_textures.isEmpty()) {
 
112
            QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin();
 
113
            QSGTexture* texture = it.key();
 
114
            SGTextureTraceItem* item = it.value();
 
115
 
 
116
            qt_debug_allocated_textures.erase(it);
 
117
 
 
118
            qDebug() << "------";
 
119
            qDebug() << "Leaked" << texture << "backtrace:";
 
120
 
 
121
            char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize);
 
122
 
 
123
            if (symbols) {
 
124
                for (int i=0; i<(int) item->backTraceSize; i++)
 
125
                    qDebug("Backtrace <%02d>: %s", i, symbols[i]);
 
126
                free(symbols);
 
127
            }
 
128
 
 
129
            qDebug() << "------";
 
130
 
 
131
            delete item;
 
132
        }
 
133
    }
 
134
#endif
 
135
}
 
136
 
 
137
inline static void qt_debug_add_texture(QSGTexture* texture)
 
138
{
 
139
#if defined(CAN_BACKTRACE_EXECINFO)
 
140
    if (qmlDebugLeakBacktrace()) {
 
141
        SGTextureTraceItem* item = new SGTextureTraceItem;
 
142
        item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE);
 
143
        qt_debug_allocated_textures.insert(texture, item);
 
144
    }
 
145
#else
 
146
    Q_UNUSED(texture);
 
147
#endif // Q_OS_LINUX
 
148
 
 
149
    ++qt_debug_texture_count;
 
150
 
 
151
    static bool atexit_registered = false;
 
152
    if (!atexit_registered) {
 
153
        atexit(qt_debug_print_texture_count);
 
154
        atexit_registered = true;
 
155
    }
 
156
}
 
157
 
 
158
static void qt_debug_remove_texture(QSGTexture* texture)
 
159
{
 
160
#if defined(CAN_BACKTRACE_EXECINFO)
 
161
    if (qmlDebugLeakBacktrace()) {
 
162
        SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0);
 
163
        if (item) {
 
164
            qt_debug_allocated_textures.remove(texture);
 
165
            delete item;
 
166
        }
 
167
    }
 
168
#else
 
169
    Q_UNUSED(texture)
 
170
#endif
 
171
 
 
172
    --qt_debug_texture_count;
 
173
 
 
174
    if (qt_debug_texture_count < 0)
 
175
        qDebug("Material destroyed after qt_debug_print_texture_count() was called.");
 
176
}
 
177
 
 
178
#endif // QT_NO_DEBUG
 
179
 
 
180
/*!
 
181
    \class QSGTexture
 
182
 
 
183
    \inmodule QtQuick
 
184
 
 
185
    \brief The QSGTexture class is a baseclass for textures used in
 
186
    the scene graph.
 
187
 
 
188
 
 
189
    Users can freely implement their own texture classes to support
 
190
    arbitrary input textures, such as YUV video frames or 8 bit alpha
 
191
    masks. The scene graph backend provides a default implementation
 
192
    of normal color textures. As the implementation of these may be
 
193
    hardware specific, they are are constructed via the factory
 
194
    function QQuickWindow::createTextureFromImage().
 
195
 
 
196
    The texture is a wrapper around an OpenGL texture, which texture
 
197
    id is given by textureId() and which size in pixels is given by
 
198
    textureSize(). hasAlphaChannel() reports if the texture contains
 
199
    opacity values and hasMipmaps() reports if the texture contains
 
200
    mipmap levels.
 
201
 
 
202
    To use a texture, call the bind() function. The texture parameters
 
203
    specifying how the texture is bound, can be specified with
 
204
    setMipmapFiltering(), setFiltering(), setHorizontalWrapMode() and
 
205
    setVerticalWrapMode(). The texture will internally try to store
 
206
    these values to minimize the OpenGL state changes when the texture
 
207
    is bound.
 
208
 
 
209
    \section1 Texture Atlasses
 
210
 
 
211
    Some scene graph backens use texture atlasses, grouping multiple
 
212
    small textures into one large texture. If this is the case, the
 
213
    function isAtlasTexture() will return true. Atlasses are used to
 
214
    aid the rendering algorithm to do better sorting which increases
 
215
    performance. The location of the texture inside the atlas is
 
216
    given with the normalizedTextureSubRect() function.
 
217
 
 
218
    If the texture is used in such a way that atlas is not preferable,
 
219
    the function removedFromAtlas() can be used to extract a
 
220
    non-atlassed copy.
 
221
 */
 
222
 
 
223
/*!
 
224
    \enum QSGTexture::WrapMode
 
225
 
 
226
    Specifies how the texture should treat texture coordinates.
 
227
 
 
228
    \value Repeat Only the factional part of the texture coordiante is
 
229
    used, causing values above 1 and below 0 to repeat.
 
230
 
 
231
    \value ClampToEdge Values above 1 are clamped to 1 and values
 
232
    below 0 are clamped to 0.
 
233
 */
 
234
 
 
235
/*!
 
236
    \enum QSGTexture::Filtering
 
237
 
 
238
    Specifies how sampling of texels should filter when texture
 
239
    coordinates are not pixel aligned.
 
240
 
 
241
    \value None No filtering should occur. This value is only used
 
242
    together with setMipmapFiltering().
 
243
 
 
244
    \value Nearest Sampling returns the nearest texel.
 
245
 
 
246
    \value Linear Sampling returns a linear interpolation of the
 
247
    neighboring texels.
 
248
*/
 
249
 
 
250
/*!
 
251
    \fn QSGTexture::QSGTexture(QSGTexturePrivate &dd)
 
252
    \internal
 
253
 */
 
254
 
 
255
/*!
 
256
    Constructs the QSGTexture base class.
 
257
 */
 
258
QSGTexture::QSGTexture()
 
259
    : QObject(*(new QSGTexturePrivate))
 
260
{
 
261
#ifndef QT_NO_DEBUG
 
262
    qt_debug_add_texture(this);
 
263
#endif
 
264
}
 
265
 
 
266
/*!
 
267
    Destroys the QSGTexture.
 
268
 */
 
269
QSGTexture::~QSGTexture()
 
270
{
 
271
#ifndef QT_NO_DEBUG
 
272
    qt_debug_remove_texture(this);
 
273
#endif
 
274
}
 
275
 
 
276
 
 
277
/*!
 
278
    \fn void QSGTexture::bind()
 
279
 
 
280
    Call this function to bind this texture to the current texture
 
281
    target.
 
282
 
 
283
    Binding a texture may also include uploading the texture data from
 
284
    a previously set QImage.
 
285
 
 
286
    \warning This function can only be called from the rendering thread.
 
287
 */
 
288
 
 
289
/*!
 
290
    \fn QRectF QSGTexture::convertToNormalizedSourceRect(const QRectF &rect) const
 
291
 
 
292
    Returns \a rect converted to normalized coordinates.
 
293
 
 
294
    \sa normalizedTextureSubRect()
 
295
 */
 
296
 
 
297
/*!
 
298
    This function returns a copy of the current texture which is removed
 
299
    from its atlas.
 
300
 
 
301
    The current texture remains unchanged, so texture coordinates do not
 
302
    need to be updated.
 
303
 
 
304
    Removing a texture from an atlas is primarily useful when passing
 
305
    it to a shader that operates on the texture coordinates 0-1 instead
 
306
    of the texture subrect inside the atlas.
 
307
 
 
308
    If the texture is not part of a texture atlas, this function returns 0.
 
309
 
 
310
    Implementations of this function are recommended to return the same instance
 
311
    for multiple calls to limit memory usage.
 
312
 
 
313
    \warning This function can only be called from the rendering thread.
 
314
 */
 
315
 
 
316
QSGTexture *QSGTexture::removedFromAtlas() const
 
317
{
 
318
    Q_ASSERT_X(!isAtlasTexture(), "QSGTexture::removedFromAtlas()", "Called on a non-atlas texture");
 
319
    return 0;
 
320
}
 
321
 
 
322
/*!
 
323
    Returns weither this texture is part of an atlas or not.
 
324
 
 
325
    The default implementation returns false.
 
326
 */
 
327
bool QSGTexture::isAtlasTexture() const
 
328
{
 
329
    return false;
 
330
}
 
331
 
 
332
/*!
 
333
    \fn int QSGTexture::textureId() const
 
334
 
 
335
    Returns the OpenGL texture id for this texture.
 
336
 
 
337
    The default value is 0, indicating that it is an invalid texture id.
 
338
 
 
339
    The function should at all times return the correct texture id.
 
340
 
 
341
    \warning This function can only be called from the rendering thread.
 
342
 */
 
343
 
 
344
/*!
 
345
    \fn QSize QSGTexture::textureSize() const
 
346
 
 
347
    Returns the size of the texture.
 
348
 */
 
349
 
 
350
/*!
 
351
    Returns the rectangle inside textureSize() that this texture
 
352
    represents in normalized coordinates.
 
353
 
 
354
    The default implementation returns a rect at position (0, 0) with
 
355
    width and height of 1.
 
356
 */
 
357
QRectF QSGTexture::normalizedTextureSubRect() const
 
358
{
 
359
    return QRectF(0, 0, 1, 1);
 
360
}
 
361
 
 
362
/*!
 
363
    \fn bool QSGTexture::hasAlphaChannel() const
 
364
 
 
365
    Returns true if the texture data contains an alpha channel.
 
366
 */
 
367
 
 
368
/*!
 
369
    \fn bool QSGTexture::hasMipmaps() const
 
370
 
 
371
    Returns true if the texture data contains mipmap levels.
 
372
 */
 
373
 
 
374
 
 
375
/*!
 
376
    Sets the mipmap sampling mode to be used for the upcoming bind() call to \a filter.
 
377
 
 
378
    Setting the mipmap filtering has no effect it the texture does not have mipmaps.
 
379
 
 
380
    \sa hasMipmaps()
 
381
 */
 
382
void QSGTexture::setMipmapFiltering(Filtering filter)
 
383
{
 
384
    Q_D(QSGTexture);
 
385
    if (d->mipmapMode != (uint) filter) {
 
386
        d->mipmapMode = filter;
 
387
        d->filteringChanged = true;
 
388
    }
 
389
}
 
390
 
 
391
/*!
 
392
    Returns whether mipmapping should be used when sampling from this texture.
 
393
 */
 
394
QSGTexture::Filtering QSGTexture::mipmapFiltering() const
 
395
{
 
396
    return (QSGTexture::Filtering) d_func()->mipmapMode;
 
397
}
 
398
 
 
399
 
 
400
/*!
 
401
    Sets the sampling mode to be used for the upcoming bind() call to \a filter.
 
402
 */
 
403
void QSGTexture::setFiltering(QSGTexture::Filtering filter)
 
404
{
 
405
    Q_D(QSGTexture);
 
406
    if (d->filterMode != (uint) filter) {
 
407
        d->filterMode = filter;
 
408
        d->filteringChanged = true;
 
409
    }
 
410
}
 
411
 
 
412
/*!
 
413
    Returns the sampling mode to be used for this texture.
 
414
 */
 
415
QSGTexture::Filtering QSGTexture::filtering() const
 
416
{
 
417
    return (QSGTexture::Filtering) d_func()->filterMode;
 
418
}
 
419
 
 
420
 
 
421
 
 
422
/*!
 
423
    Sets the horizontal wrap mode to be used for the upcoming bind() call to \a hwrap
 
424
 */
 
425
 
 
426
void QSGTexture::setHorizontalWrapMode(WrapMode hwrap)
 
427
{
 
428
    Q_D(QSGTexture);
 
429
    if ((uint) hwrap != d->horizontalWrap) {
 
430
        d->horizontalWrap = hwrap;
 
431
        d->wrapChanged = true;
 
432
    }
 
433
}
 
434
 
 
435
/*!
 
436
    Returns the horizontal wrap mode to be used for this texture.
 
437
 */
 
438
QSGTexture::WrapMode QSGTexture::horizontalWrapMode() const
 
439
{
 
440
    return (QSGTexture::WrapMode) d_func()->horizontalWrap;
 
441
}
 
442
 
 
443
 
 
444
 
 
445
/*!
 
446
    Sets the vertical wrap mode to be used for the upcoming bind() call to \a vwrap
 
447
 */
 
448
void QSGTexture::setVerticalWrapMode(WrapMode vwrap)
 
449
{
 
450
    Q_D(QSGTexture);
 
451
    if ((uint) vwrap != d->verticalWrap) {
 
452
        d->verticalWrap = vwrap;
 
453
        d->wrapChanged = true;
 
454
    }
 
455
}
 
456
 
 
457
/*!
 
458
    Returns the vertical wrap mode to be used for this texture.
 
459
 */
 
460
QSGTexture::WrapMode QSGTexture::verticalWrapMode() const
 
461
{
 
462
    return (QSGTexture::WrapMode) d_func()->verticalWrap;
 
463
}
 
464
 
 
465
 
 
466
/*!
 
467
    Update the texture state to match the filtering, mipmap and wrap options
 
468
    currently set.
 
469
 
 
470
    If \a force is true, all properties will be updated regardless of weither
 
471
    they have changed or not.
 
472
 */
 
473
void QSGTexture::updateBindOptions(bool force)
 
474
{
 
475
    Q_D(QSGTexture);
 
476
    if (force || d->filteringChanged) {
 
477
        bool linear = d->filterMode == Linear;
 
478
        GLint minFilter = linear ? GL_LINEAR : GL_NEAREST;
 
479
        GLint magFilter = linear ? GL_LINEAR : GL_NEAREST;
 
480
 
 
481
        if (hasMipmaps()) {
 
482
            if (d->mipmapMode == Nearest)
 
483
                minFilter = linear ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST;
 
484
            else if (d->mipmapMode == Linear)
 
485
                minFilter = linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_LINEAR;
 
486
        }
 
487
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
 
488
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
 
489
        d->filteringChanged = false;
 
490
    }
 
491
 
 
492
    if (force || d->wrapChanged) {
 
493
#if !defined(QT_NO_DEBUG) && defined(QT_OPENGL_ES_2)
 
494
        if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat) {
 
495
            bool npotSupported = QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
 
496
            QSize size = textureSize();
 
497
            bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
 
498
            if (!npotSupported && isNpot)
 
499
                qWarning("Scene Graph: This system does not support the REPEAT wrap mode for non-power-of-two textures.");
 
500
        }
 
501
#endif
 
502
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, d->horizontalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
 
503
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, d->verticalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
 
504
        d->wrapChanged = false;
 
505
    }
 
506
}
 
507
 
 
508
QSGPlainTexture::QSGPlainTexture()
 
509
    : QSGTexture()
 
510
    , m_texture_id(0)
 
511
    , m_has_alpha(false)
 
512
    , m_has_mipmaps(false)
 
513
    , m_dirty_bind_options(false)
 
514
    , m_owns_texture(true)
 
515
    , m_mipmaps_generated(false)
 
516
{
 
517
}
 
518
 
 
519
 
 
520
QSGPlainTexture::~QSGPlainTexture()
 
521
{
 
522
    if (m_texture_id && m_owns_texture)
 
523
        glDeleteTextures(1, &m_texture_id);
 
524
}
 
525
 
 
526
#ifdef QT_OPENGL_ES
 
527
void qsg_swizzleBGRAToRGBA(QImage *image)
 
528
{
 
529
    const int width = image->width();
 
530
    const int height = image->height();
 
531
    for (int i = 0; i < height; ++i) {
 
532
        uint *p = (uint *) image->scanLine(i);
 
533
        for (int x = 0; x < width; ++x)
 
534
            p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
 
535
    }
 
536
}
 
537
#endif
 
538
 
 
539
void QSGPlainTexture::setImage(const QImage &image)
 
540
{
 
541
    m_image = image;
 
542
    m_texture_size = image.size();
 
543
    m_has_alpha = image.hasAlphaChannel();
 
544
    m_dirty_texture = true;
 
545
    m_dirty_bind_options = true;
 
546
 }
 
547
 
 
548
int QSGPlainTexture::textureId() const
 
549
{
 
550
    if (m_dirty_texture) {
 
551
        if (m_image.isNull()) {
 
552
            // The actual texture and id will be updated/deleted in a later bind()
 
553
            // or ~QSGPlainTexture so just keep it minimal here.
 
554
            return 0;
 
555
        } else if (m_texture_id == 0){
 
556
            // Generate a texture id for use later and return it.
 
557
            glGenTextures(1, &const_cast<QSGPlainTexture *>(this)->m_texture_id);
 
558
            return m_texture_id;
 
559
        }
 
560
    }
 
561
    return m_texture_id;
 
562
}
 
563
 
 
564
void QSGPlainTexture::setTextureId(int id)
 
565
{
 
566
    if (m_texture_id && m_owns_texture)
 
567
        glDeleteTextures(1, &m_texture_id);
 
568
 
 
569
    m_texture_id = id;
 
570
    m_dirty_texture = false;
 
571
    m_dirty_bind_options = true;
 
572
    m_image = QImage();
 
573
    m_mipmaps_generated = false;
 
574
}
 
575
 
 
576
void QSGPlainTexture::setHasMipmaps(bool mm)
 
577
{
 
578
    m_has_mipmaps = mm;
 
579
    m_mipmaps_generated = false;
 
580
}
 
581
 
 
582
 
 
583
void QSGPlainTexture::bind()
 
584
{
 
585
    if (!m_dirty_texture) {
 
586
        glBindTexture(GL_TEXTURE_2D, m_texture_id);
 
587
        if (m_has_mipmaps && !m_mipmaps_generated) {
 
588
            QOpenGLContext *ctx = QOpenGLContext::currentContext();
 
589
            ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
 
590
            m_mipmaps_generated = true;
 
591
        }
 
592
        updateBindOptions(m_dirty_bind_options);
 
593
        m_dirty_bind_options = false;
 
594
        return;
 
595
    }
 
596
 
 
597
    m_dirty_texture = false;
 
598
 
 
599
 
 
600
    if (m_image.isNull()) {
 
601
        if (m_texture_id && m_owns_texture)
 
602
            glDeleteTextures(1, &m_texture_id);
 
603
        m_texture_id = 0;
 
604
        m_texture_size = QSize();
 
605
        m_has_mipmaps = false;
 
606
        m_has_alpha = false;
 
607
        return;
 
608
    }
 
609
 
 
610
    if (m_texture_id == 0)
 
611
        glGenTextures(1, &m_texture_id);
 
612
    glBindTexture(GL_TEXTURE_2D, m_texture_id);
 
613
 
 
614
    // ### TODO: check for out-of-memory situations...
 
615
    int w = m_image.width();
 
616
    int h = m_image.height();
 
617
 
 
618
    QImage tmp = (m_image.format() == QImage::Format_RGB32 || m_image.format() == QImage::Format_ARGB32_Premultiplied)
 
619
                 ? m_image
 
620
                 : m_image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
 
621
 
 
622
    updateBindOptions(m_dirty_bind_options);
 
623
 
 
624
#ifdef QT_OPENGL_ES
 
625
        qsg_swizzleBGRAToRGBA(&tmp);
 
626
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp.constBits());
 
627
#else
 
628
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, tmp.constBits());
 
629
#endif
 
630
 
 
631
    if (m_has_mipmaps) {
 
632
        QOpenGLContext *ctx = QOpenGLContext::currentContext();
 
633
        ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
 
634
        m_mipmaps_generated = true;
 
635
    }
 
636
 
 
637
    m_texture_size = QSize(w, h);
 
638
    m_texture_rect = QRectF(0, 0, 1, 1);
 
639
 
 
640
    m_dirty_bind_options = false;
 
641
}
 
642
 
 
643
 
 
644
/*!
 
645
    \class QSGDynamicTexture
 
646
    \brief The QSGDynamicTexture class serves as a baseclass for dynamically changing textures,
 
647
    such as content that is rendered to FBO's.
 
648
    \inmodule QtQuick
 
649
 
 
650
    To update the content of the texture, call updateTexture() explicitly. Simply calling bind()
 
651
    will not update the texture.
 
652
 */
 
653
 
 
654
 
 
655
/*!
 
656
    \fn bool QSGDynamicTexture::updateTexture()
 
657
 
 
658
    Call this function to explicitly update the dynamic texture. Calling bind() will bind
 
659
    the content that was previously updated.
 
660
 
 
661
    The function returns true if the texture was changed as a resul of the update; otherwise
 
662
    returns false.
 
663
 */
 
664
 
 
665
 
 
666
 
 
667
QT_END_NAMESPACE