| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the Qt Data Visualization module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:GPL$ | 
| 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 The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
| 19 | ** General Public License version 3 or (at your option) any later version | 
| 20 | ** approved by the KDE Free Qt Foundation. The licenses are as published by | 
| 21 | ** the Free Software Foundation and appearing in the file LICENSE.GPL3 | 
| 22 | ** included in the packaging of this file. Please review the following | 
| 23 | ** information to ensure the GNU General Public License requirements will | 
| 24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 25 | ** | 
| 26 | ** $QT_END_LICENSE$ | 
| 27 | ** | 
| 28 | ****************************************************************************/ | 
| 29 |  | 
| 30 | #include "texturehelper_p.h" | 
| 31 | #include "utils_p.h" | 
| 32 |  | 
| 33 | #include <QtGui/QImage> | 
| 34 | #include <QtGui/QPainter> | 
| 35 | #include <QtCore/QTime> | 
| 36 |  | 
| 37 | QT_BEGIN_NAMESPACE_DATAVISUALIZATION | 
| 38 |  | 
| 39 | // Defined in shaderhelper.cpp | 
| 40 | extern void discardDebugMsgs(QtMsgType type, const QMessageLogContext &context, const QString &msg); | 
| 41 |  | 
| 42 | TextureHelper::TextureHelper() | 
| 43 | { | 
| 44 |     initializeOpenGLFunctions(); | 
| 45 | #if !defined(QT_OPENGL_ES_2) | 
| 46 |     if (!Utils::isOpenGLES()) { | 
| 47 |         // Discard warnings about deprecated functions | 
| 48 |         QtMessageHandler handler = qInstallMessageHandler(discardDebugMsgs); | 
| 49 |  | 
| 50 |         m_openGlFunctions_2_1 = | 
| 51 |                 QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_1>(); | 
| 52 |         if (m_openGlFunctions_2_1) | 
| 53 |             m_openGlFunctions_2_1->initializeOpenGLFunctions(); | 
| 54 |  | 
| 55 |         // Restore original message handler | 
| 56 |         qInstallMessageHandler(handler); | 
| 57 |  | 
| 58 |         if (!m_openGlFunctions_2_1) | 
| 59 |             qFatal(msg: "OpenGL version is too low, at least 2.1 is required" ); | 
| 60 |     } | 
| 61 | #endif | 
| 62 | } | 
| 63 |  | 
| 64 | TextureHelper::~TextureHelper() | 
| 65 | { | 
| 66 | } | 
| 67 |  | 
| 68 | GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFiltering, | 
| 69 |                                       bool convert, bool smoothScale, bool clampY) | 
| 70 | { | 
| 71 |     if (image.isNull()) | 
| 72 |         return 0; | 
| 73 |  | 
| 74 |     QImage texImage = image; | 
| 75 |  | 
| 76 |     if (Utils::isOpenGLES()) { | 
| 77 |         GLuint imageWidth = Utils::getNearestPowerOfTwo(value: image.width()); | 
| 78 |         GLuint imageHeight = Utils::getNearestPowerOfTwo(value: image.height()); | 
| 79 |         if (smoothScale) { | 
| 80 |             texImage = image.scaled(w: imageWidth, h: imageHeight, aspectMode: Qt::IgnoreAspectRatio, | 
| 81 |                                     mode: Qt::SmoothTransformation); | 
| 82 |         } else { | 
| 83 |             texImage = image.scaled(w: imageWidth, h: imageHeight, aspectMode: Qt::IgnoreAspectRatio); | 
| 84 |         } | 
| 85 |     } | 
| 86 |  | 
| 87 |     GLuint textureId; | 
| 88 |     glGenTextures(n: 1, textures: &textureId); | 
| 89 |     glBindTexture(GL_TEXTURE_2D, texture: textureId); | 
| 90 |     if (convert) | 
| 91 |         texImage = convertToGLFormat(srcImage: texImage); | 
| 92 |     glTexImage2D(GL_TEXTURE_2D, level: 0, GL_RGBA, width: texImage.width(), height: texImage.height(), | 
| 93 |                  border: 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels: texImage.bits()); | 
| 94 |     if (smoothScale) | 
| 95 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
| 96 |     else | 
| 97 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 
| 98 |     if (useTrilinearFiltering) { | 
| 99 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | 
| 100 |         glGenerateMipmap(GL_TEXTURE_2D); | 
| 101 |     } else { | 
| 102 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 
| 103 |     } | 
| 104 |     if (clampY) | 
| 105 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
| 106 |     glBindTexture(GL_TEXTURE_2D, texture: 0); | 
| 107 |  | 
| 108 |     return textureId; | 
| 109 | } | 
| 110 |  | 
| 111 | GLuint TextureHelper::create3DTexture(const QVector<uchar> *data, int width, int height, int depth, | 
| 112 |                                       QImage::Format dataFormat) | 
| 113 | { | 
| 114 |     if (Utils::isOpenGLES() || !width || !height || !depth) | 
| 115 |         return 0; | 
| 116 |  | 
| 117 |     GLuint textureId = 0; | 
| 118 | #if defined(QT_OPENGL_ES_2) | 
| 119 |     Q_UNUSED(dataFormat) | 
| 120 |     Q_UNUSED(data) | 
| 121 | #else | 
| 122 |     glEnable(GL_TEXTURE_3D); | 
| 123 |  | 
| 124 |     glGenTextures(n: 1, textures: &textureId); | 
| 125 |     glBindTexture(GL_TEXTURE_3D, texture: textureId); | 
| 126 |     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
| 127 |     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
| 128 |     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); | 
| 129 |     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 
| 130 |     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 
| 131 |  | 
| 132 |     GLenum status = glGetError(); | 
| 133 |     // glGetError docs advise to call glGetError in loop to clear all error flags | 
| 134 |     while (status) | 
| 135 |         status = glGetError(); | 
| 136 |  | 
| 137 |     GLint internalFormat = 4; | 
| 138 |     GLint format = GL_BGRA; | 
| 139 |     if (dataFormat == QImage::Format_Indexed8) { | 
| 140 |         internalFormat = 1; | 
| 141 |         format = GL_RED; | 
| 142 |         // Align width to 32bits | 
| 143 |         width = width + width % 4; | 
| 144 |     } | 
| 145 |     m_openGlFunctions_2_1->glTexImage3D(GL_TEXTURE_3D, level: 0, internalformat: internalFormat, width, height, depth, border: 0, | 
| 146 |                                         format, GL_UNSIGNED_BYTE, pixels: data->constData()); | 
| 147 |     status = glGetError(); | 
| 148 |     if (status) | 
| 149 |         qWarning() << __FUNCTION__ << "3D texture creation failed:"  << status; | 
| 150 |  | 
| 151 |     glBindTexture(GL_TEXTURE_3D, texture: 0); | 
| 152 |     glDisable(GL_TEXTURE_3D); | 
| 153 | #endif | 
| 154 |     return textureId; | 
| 155 | } | 
| 156 |  | 
| 157 | GLuint TextureHelper::createCubeMapTexture(const QImage &image, bool useTrilinearFiltering) | 
| 158 | { | 
| 159 |     if (image.isNull()) | 
| 160 |         return 0; | 
| 161 |  | 
| 162 |     GLuint textureId; | 
| 163 |     glGenTextures(n: 1, textures: &textureId); | 
| 164 |     glBindTexture(GL_TEXTURE_CUBE_MAP, texture: textureId); | 
| 165 |     QImage glTexture = convertToGLFormat(srcImage: image); | 
| 166 |     glTexImage2D(GL_TEXTURE_CUBE_MAP, level: 0, GL_RGBA, width: glTexture.width(), height: glTexture.height(), | 
| 167 |                  border: 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels: glTexture.bits()); | 
| 168 |     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
| 169 |     if (useTrilinearFiltering) { | 
| 170 |         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | 
| 171 |         glGenerateMipmap(GL_TEXTURE_CUBE_MAP); | 
| 172 |     } else { | 
| 173 |         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 
| 174 |     } | 
| 175 |     glBindTexture(GL_TEXTURE_2D, texture: 0); | 
| 176 |     return textureId; | 
| 177 | } | 
| 178 |  | 
| 179 | GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuffer, | 
| 180 |                                              GLuint &depthBuffer) | 
| 181 | { | 
| 182 |     GLuint textureid; | 
| 183 |  | 
| 184 |     // Create texture for the selection buffer | 
| 185 |     glGenTextures(n: 1, textures: &textureid); | 
| 186 |     glBindTexture(GL_TEXTURE_2D, texture: textureid); | 
| 187 |     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 
| 188 |     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
| 189 |     glTexImage2D(GL_TEXTURE_2D, level: 0, GL_RGBA, width: size.width(), height: size.height(), border: 0, GL_RGBA, | 
| 190 |                  GL_UNSIGNED_BYTE, NULL); | 
| 191 |     glBindTexture(GL_TEXTURE_2D, texture: 0); | 
| 192 |  | 
| 193 |     // Create render buffer | 
| 194 |     if (depthBuffer) | 
| 195 |         glDeleteRenderbuffers(n: 1, renderbuffers: &depthBuffer); | 
| 196 |  | 
| 197 |     glGenRenderbuffers(n: 1, renderbuffers: &depthBuffer); | 
| 198 |     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer: depthBuffer); | 
| 199 |     GLenum status = glGetError(); | 
| 200 |     // glGetError docs advise to call glGetError in loop to clear all error flags | 
| 201 |     while (status) | 
| 202 |         status = glGetError(); | 
| 203 |     if (Utils::isOpenGLES()) | 
| 204 |         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width: size.width(), height: size.height()); | 
| 205 |     else | 
| 206 |         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width: size.width(), height: size.height()); | 
| 207 |  | 
| 208 |     status = glGetError(); | 
| 209 |     if (status) { | 
| 210 |         qCritical() << "Selection texture render buffer creation failed:"  << status; | 
| 211 |         glDeleteTextures(n: 1, textures: &textureid); | 
| 212 |         glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer: 0); | 
| 213 |         return 0; | 
| 214 |     } | 
| 215 |     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer: 0); | 
| 216 |  | 
| 217 |     // Create frame buffer | 
| 218 |     if (!frameBuffer) | 
| 219 |         glGenFramebuffers(n: 1, framebuffers: &frameBuffer); | 
| 220 |     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: frameBuffer); | 
| 221 |  | 
| 222 |     // Attach texture to color attachment | 
| 223 |     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture: textureid, level: 0); | 
| 224 |     // Attach renderbuffer to depth attachment | 
| 225 |     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer: depthBuffer); | 
| 226 |  | 
| 227 |     // Verify that the frame buffer is complete | 
| 228 |     status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | 
| 229 |     if (status != GL_FRAMEBUFFER_COMPLETE) { | 
| 230 |         qCritical() << "Selection texture frame buffer creation failed:"  << status; | 
| 231 |         glDeleteTextures(n: 1, textures: &textureid); | 
| 232 |         textureid = 0; | 
| 233 |     } | 
| 234 |  | 
| 235 |     // Restore the default framebuffer | 
| 236 |     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: 0); | 
| 237 |  | 
| 238 |     return textureid; | 
| 239 | } | 
| 240 |  | 
| 241 | GLuint TextureHelper::createCursorPositionTexture(const QSize &size, GLuint &frameBuffer) | 
| 242 | { | 
| 243 |     GLuint textureid; | 
| 244 |     glGenTextures(n: 1, textures: &textureid); | 
| 245 |     glBindTexture(GL_TEXTURE_2D, texture: textureid); | 
| 246 |     glTexImage2D(GL_TEXTURE_2D, level: 0, GL_RGBA, width: size.width(), height: size.height(), border: 0, GL_RGBA, | 
| 247 |                  GL_UNSIGNED_BYTE, NULL); | 
| 248 |     glBindTexture(GL_TEXTURE_2D, texture: 0); | 
| 249 |  | 
| 250 |     glGenFramebuffers(n: 1, framebuffers: &frameBuffer); | 
| 251 |     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: frameBuffer); | 
| 252 |     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | 
| 253 |                            texture: textureid, level: 0); | 
| 254 |  | 
| 255 |     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | 
| 256 |     if (status != GL_FRAMEBUFFER_COMPLETE) { | 
| 257 |         qCritical() << "Cursor position mapper frame buffer creation failed:"  << status; | 
| 258 |         glDeleteTextures(n: 1, textures: &textureid); | 
| 259 |         textureid = 0; | 
| 260 |     } | 
| 261 |     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: 0); | 
| 262 |  | 
| 263 |     return textureid; | 
| 264 | } | 
| 265 |  | 
| 266 | GLuint TextureHelper::createUniformTexture(const QColor &color) | 
| 267 | { | 
| 268 |     QImage image(QSize(int(uniformTextureWidth), int(uniformTextureHeight)), | 
| 269 |                  QImage::Format_RGB32); | 
| 270 |     QPainter pmp(&image); | 
| 271 |     pmp.setBrush(QBrush(color)); | 
| 272 |     pmp.setPen(Qt::NoPen); | 
| 273 |     pmp.drawRect(x: 0, y: 0, w: int(uniformTextureWidth), h: int(uniformTextureHeight)); | 
| 274 |  | 
| 275 |     return create2DTexture(image, useTrilinearFiltering: false, convert: true, smoothScale: false, clampY: true); | 
| 276 | } | 
| 277 |  | 
| 278 | GLuint TextureHelper::createGradientTexture(const QLinearGradient &gradient) | 
| 279 | { | 
| 280 |     QImage image(QSize(int(gradientTextureWidth), int(gradientTextureHeight)), | 
| 281 |                  QImage::Format_RGB32); | 
| 282 |     QPainter pmp(&image); | 
| 283 |     pmp.setBrush(QBrush(gradient)); | 
| 284 |     pmp.setPen(Qt::NoPen); | 
| 285 |     pmp.drawRect(x: 0, y: 0, w: int(gradientTextureWidth), h: int(gradientTextureHeight)); | 
| 286 |  | 
| 287 |     return create2DTexture(image, useTrilinearFiltering: false, convert: true, smoothScale: false, clampY: true); | 
| 288 | } | 
| 289 |  | 
| 290 | GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint textureSize) | 
| 291 | { | 
| 292 |     GLuint depthtextureid = 0; | 
| 293 | #if defined(QT_OPENGL_ES_2) | 
| 294 |     Q_UNUSED(size) | 
| 295 |     Q_UNUSED(textureSize) | 
| 296 | #else | 
| 297 |     if (!Utils::isOpenGLES()) { | 
| 298 |         // Create depth texture for the shadow mapping | 
| 299 |         glGenTextures(n: 1, textures: &depthtextureid); | 
| 300 |         glBindTexture(GL_TEXTURE_2D, texture: depthtextureid); | 
| 301 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
| 302 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
| 303 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
| 304 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
| 305 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); | 
| 306 |         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); | 
| 307 |         glTexImage2D(GL_TEXTURE_2D, level: 0, GL_DEPTH_COMPONENT, width: size.width() * textureSize, | 
| 308 |                      height: size.height() * textureSize, border: 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); | 
| 309 |         glBindTexture(GL_TEXTURE_2D, texture: 0); | 
| 310 |     } | 
| 311 | #endif | 
| 312 |     return depthtextureid; | 
| 313 | } | 
| 314 |  | 
| 315 | GLuint TextureHelper::createDepthTextureFrameBuffer(const QSize &size, GLuint &frameBuffer, | 
| 316 |                                                     GLuint textureSize) | 
| 317 | { | 
| 318 |     GLuint depthtextureid = createDepthTexture(size, textureSize); | 
| 319 | #if defined(QT_OPENGL_ES_2) | 
| 320 |     Q_UNUSED(frameBuffer) | 
| 321 | #else | 
| 322 |     if (!Utils::isOpenGLES()) { | 
| 323 |         // Create frame buffer | 
| 324 |         if (!frameBuffer) | 
| 325 |             glGenFramebuffers(n: 1, framebuffers: &frameBuffer); | 
| 326 |         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: frameBuffer); | 
| 327 |  | 
| 328 |         // Attach texture to depth attachment | 
| 329 |         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture: depthtextureid, level: 0); | 
| 330 |  | 
| 331 |         m_openGlFunctions_2_1->glDrawBuffer(GL_NONE); | 
| 332 |         m_openGlFunctions_2_1->glReadBuffer(GL_NONE); | 
| 333 |  | 
| 334 |         // Verify that the frame buffer is complete | 
| 335 |         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | 
| 336 |         if (status != GL_FRAMEBUFFER_COMPLETE) { | 
| 337 |             qCritical() << "Depth texture frame buffer creation failed"  << status; | 
| 338 |             glDeleteTextures(n: 1, textures: &depthtextureid); | 
| 339 |             depthtextureid = 0; | 
| 340 |         } | 
| 341 |  | 
| 342 |         // Restore the default framebuffer | 
| 343 |         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: 0); | 
| 344 |     } | 
| 345 | #endif | 
| 346 |     return depthtextureid; | 
| 347 | } | 
| 348 |  | 
| 349 | void TextureHelper::deleteTexture(GLuint *texture) | 
| 350 | { | 
| 351 |     if (texture && *texture) { | 
| 352 |         if (QOpenGLContext::currentContext()) | 
| 353 |             glDeleteTextures(n: 1, textures: texture); | 
| 354 |         *texture = 0; | 
| 355 |     } | 
| 356 | } | 
| 357 |  | 
| 358 | QImage TextureHelper::convertToGLFormat(const QImage &srcImage) | 
| 359 | { | 
| 360 |     QImage res(srcImage.size(), QImage::Format_ARGB32); | 
| 361 |     convertToGLFormatHelper(dstImage&: res, srcImage: srcImage.convertToFormat(f: QImage::Format_ARGB32), GL_RGBA); | 
| 362 |     return res; | 
| 363 | } | 
| 364 |  | 
| 365 | void TextureHelper::convertToGLFormatHelper(QImage &dstImage, const QImage &srcImage, | 
| 366 |                                             GLenum texture_format) | 
| 367 | { | 
| 368 |     Q_ASSERT(dstImage.depth() == 32); | 
| 369 |     Q_ASSERT(srcImage.depth() == 32); | 
| 370 |  | 
| 371 |     if (dstImage.size() != srcImage.size()) { | 
| 372 |         int target_width = dstImage.width(); | 
| 373 |         int target_height = dstImage.height(); | 
| 374 |         float sx = target_width / float(srcImage.width()); | 
| 375 |         float sy = target_height / float(srcImage.height()); | 
| 376 |  | 
| 377 |         quint32 *dest = (quint32 *) dstImage.scanLine(0); // NB! avoid detach here | 
| 378 |         uchar *srcPixels = (uchar *) srcImage.scanLine(srcImage.height() - 1); | 
| 379 |         int sbpl = srcImage.bytesPerLine(); | 
| 380 |         int dbpl = dstImage.bytesPerLine(); | 
| 381 |  | 
| 382 |         int ix = int(0x00010000 / sx); | 
| 383 |         int iy = int(0x00010000 / sy); | 
| 384 |  | 
| 385 |         quint32 basex = int(0.5 * ix); | 
| 386 |         quint32 srcy = int(0.5 * iy); | 
| 387 |  | 
| 388 |         // scale, swizzle and mirror in one loop | 
| 389 |         while (target_height--) { | 
| 390 |             const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl); | 
| 391 |             int srcx = basex; | 
| 392 |             for (int x=0; x<target_width; ++x) { | 
| 393 |                 dest[x] = qt_gl_convertToGLFormatHelper(src_pixel: src[srcx >> 16], texture_format); | 
| 394 |                 srcx += ix; | 
| 395 |             } | 
| 396 |             dest = (quint32 *)(((uchar *) dest) + dbpl); | 
| 397 |             srcy += iy; | 
| 398 |         } | 
| 399 |     } else { | 
| 400 |         const int width = srcImage.width(); | 
| 401 |         const int height = srcImage.height(); | 
| 402 |         const uint *p = (const uint*) srcImage.scanLine(srcImage.height() - 1); | 
| 403 |         uint *q = (uint*) dstImage.scanLine(0); | 
| 404 |  | 
| 405 | #if !defined(QT_OPENGL_ES_2) | 
| 406 |         if (texture_format == GL_BGRA) { | 
| 407 | #else | 
| 408 |         if (texture_format == GL_BGRA8_EXT) { | 
| 409 | #endif | 
| 410 |             if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { | 
| 411 |                 // mirror + swizzle | 
| 412 |                 for (int i=0; i < height; ++i) { | 
| 413 |                     const uint *end = p + width; | 
| 414 |                     while (p < end) { | 
| 415 |                         *q = ((*p << 24) & 0xff000000) | 
| 416 |                                 | ((*p >> 24) & 0x000000ff) | 
| 417 |                                 | ((*p << 8) & 0x00ff0000) | 
| 418 |                                 | ((*p >> 8) & 0x0000ff00); | 
| 419 |                         p++; | 
| 420 |                         q++; | 
| 421 |                     } | 
| 422 |                     p -= 2 * width; | 
| 423 |                 } | 
| 424 |             } else { | 
| 425 |                 const uint bytesPerLine = srcImage.bytesPerLine(); | 
| 426 |                 for (int i=0; i < height; ++i) { | 
| 427 |                     memcpy(dest: q, src: p, n: bytesPerLine); | 
| 428 |                     q += width; | 
| 429 |                     p -= width; | 
| 430 |                 } | 
| 431 |             } | 
| 432 |         } else { | 
| 433 |             if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { | 
| 434 |                 for (int i=0; i < height; ++i) { | 
| 435 |                     const uint *end = p + width; | 
| 436 |                     while (p < end) { | 
| 437 |                         *q = (*p << 8) | ((*p >> 24) & 0xff); | 
| 438 |                         p++; | 
| 439 |                         q++; | 
| 440 |                     } | 
| 441 |                     p -= 2 * width; | 
| 442 |                 } | 
| 443 |             } else { | 
| 444 |                 for (int i=0; i < height; ++i) { | 
| 445 |                     const uint *end = p + width; | 
| 446 |                     while (p < end) { | 
| 447 |                         *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00); | 
| 448 |                         p++; | 
| 449 |                         q++; | 
| 450 |                     } | 
| 451 |                     p -= 2 * width; | 
| 452 |                 } | 
| 453 |             } | 
| 454 |         } | 
| 455 |     } | 
| 456 | } | 
| 457 |  | 
| 458 | QRgb TextureHelper::qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format) | 
| 459 | { | 
| 460 | #if !defined(QT_OPENGL_ES_2) | 
| 461 |     if (texture_format == GL_BGRA) { | 
| 462 | #else | 
| 463 |     if (texture_format == GL_BGRA8_EXT) { | 
| 464 | #endif | 
| 465 |         if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { | 
| 466 |             return ((src_pixel << 24) & 0xff000000) | 
| 467 |                     | ((src_pixel >> 24) & 0x000000ff) | 
| 468 |                     | ((src_pixel << 8) & 0x00ff0000) | 
| 469 |                     | ((src_pixel >> 8) & 0x0000ff00); | 
| 470 |         } else { | 
| 471 |             return src_pixel; | 
| 472 |         } | 
| 473 |     } else {  // GL_RGBA | 
| 474 |         if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { | 
| 475 |             return (src_pixel << 8) | ((src_pixel >> 24) & 0xff); | 
| 476 |         } else { | 
| 477 |             return ((src_pixel << 16) & 0xff0000) | 
| 478 |                     | ((src_pixel >> 16) & 0xff) | 
| 479 |                     | (src_pixel & 0xff00ff00); | 
| 480 |         } | 
| 481 |     } | 
| 482 | } | 
| 483 |  | 
| 484 | QT_END_NAMESPACE_DATAVISUALIZATION | 
| 485 |  |