85qsizetype QOpenGLTextureUploader::textureImage(GLenum target,
const QImage &image, QOpenGLTextureUploader::BindOptions options, QSize maxSize)
87 QOpenGLContext *context = QOpenGLContext::currentContext();
88 QOpenGLExtensions *funcs =
static_cast<QOpenGLExtensions*>(context->functions());
91 GLenum externalFormat;
92 GLenum internalFormat;
94 QImage::Format targetFormat = QImage::Format_Invalid;
95 const bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
96 const bool isOpenGLES3orBetter = context->isOpenGLES() && context->format().majorVersion() >= 3;
97 const bool sRgbBinding = (options & SRgbBindOption);
98 Q_ASSERT(isOpenGL12orBetter || context->isOpenGLES());
99 Q_ASSERT((options & (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption)) != (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption));
101 switch (image.format()) {
102 case QImage::Format_RGB32:
103 case QImage::Format_ARGB32:
104 case QImage::Format_ARGB32_Premultiplied:
105 if (isOpenGL12orBetter) {
107 internalFormat = GL_RGBA;
109#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
111 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat) && !sRgbBinding) {
113 externalFormat = internalFormat =
GL_BGRA;
114 pixelType = GL_UNSIGNED_BYTE;
115 }
else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral(
"GL_APPLE_texture_format_BGRA8888"))) {
118 internalFormat = GL_RGBA;
119 pixelType = GL_UNSIGNED_BYTE;
121 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
122#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
126 funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_GREEN);
127 funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
128 funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_ALPHA);
129 funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_RED);
131 externalFormat = internalFormat = GL_RGBA;
132 pixelType = GL_UNSIGNED_BYTE;
137 targetFormat = image.format();
139 case QImage::Format_BGR30:
140 case QImage::Format_A2BGR30_Premultiplied:
144 }
else if (isOpenGL12orBetter || isOpenGLES3orBetter) {
146 externalFormat = GL_RGBA;
148 targetFormat = image.format();
151 case QImage::Format_RGB30:
152 case QImage::Format_A2RGB30_Premultiplied:
156 }
else if (isOpenGL12orBetter) {
160 targetFormat = image.format();
161 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
165 externalFormat = GL_RGBA;
167 targetFormat = image.format();
170 case QImage::Format_RGB444:
171 case QImage::Format_RGB555:
172 case QImage::Format_RGB16:
173 if (isOpenGL12orBetter || context->isOpenGLES()) {
174 externalFormat = internalFormat = GL_RGB;
175 pixelType = GL_UNSIGNED_SHORT_5_6_5;
176 targetFormat = QImage::Format_RGB16;
179 case QImage::Format_RGB666:
180 case QImage::Format_RGB888:
181 externalFormat = internalFormat = GL_RGB;
182 pixelType = GL_UNSIGNED_BYTE;
183 targetFormat = QImage::Format_RGB888;
185 case QImage::Format_BGR888:
186 if (isOpenGL12orBetter) {
188 internalFormat = GL_RGB;
189 pixelType = GL_UNSIGNED_BYTE;
190 targetFormat = QImage::Format_BGR888;
191 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
194 externalFormat = internalFormat = GL_RGB;
195 pixelType = GL_UNSIGNED_BYTE;
196 targetFormat = QImage::Format_BGR888;
199 case QImage::Format_RGBX8888:
200 case QImage::Format_RGBA8888:
201 case QImage::Format_RGBA8888_Premultiplied:
202 externalFormat = internalFormat = GL_RGBA;
203 pixelType = GL_UNSIGNED_BYTE;
204 targetFormat = image.format();
206 case QImage::Format_RGBX64:
207 case QImage::Format_RGBA64:
208 case QImage::Format_RGBA64_Premultiplied:
209 externalFormat = internalFormat = GL_RGBA;
210 if (isOpenGL12orBetter || (context->isOpenGLES() && context->format().majorVersion() >= 3))
212 pixelType = GL_UNSIGNED_SHORT;
213 targetFormat = image.format();
215 case QImage::Format_RGBX16FPx4:
216 case QImage::Format_RGBA16FPx4:
217 case QImage::Format_RGBA16FPx4_Premultiplied:
218 if (context->format().majorVersion() >= 3) {
219 externalFormat = GL_RGBA;
222 targetFormat = image.format();
225 case QImage::Format_RGBX32FPx4:
226 case QImage::Format_RGBA32FPx4:
227 case QImage::Format_RGBA32FPx4_Premultiplied:
228 externalFormat = internalFormat = GL_RGBA;
229 if (context->format().majorVersion() >= 3)
231 pixelType = GL_FLOAT;
232 targetFormat = image.format();
234 case QImage::Format_Indexed8:
238 }
else if (options & UseRedForAlphaAndLuminanceBindOption) {
239 externalFormat = internalFormat =
GL_RED;
240 pixelType = GL_UNSIGNED_BYTE;
241 targetFormat = image.format();
244 case QImage::Format_Alpha8:
248 }
else if (options & UseRedForAlphaAndLuminanceBindOption) {
249 externalFormat = internalFormat =
GL_RED;
250 pixelType = GL_UNSIGNED_BYTE;
251 targetFormat = image.format();
252 }
else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
253 externalFormat = internalFormat = GL_ALPHA;
254 pixelType = GL_UNSIGNED_BYTE;
255 targetFormat = image.format();
256 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
261 externalFormat = internalFormat =
GL_RED;
262 pixelType = GL_UNSIGNED_BYTE;
263 targetFormat = image.format();
266 case QImage::Format_Grayscale8:
270 }
else if (options & UseRedForAlphaAndLuminanceBindOption) {
271 externalFormat = internalFormat =
GL_RED;
272 pixelType = GL_UNSIGNED_BYTE;
273 targetFormat = image.format();
274 }
else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
275 externalFormat = internalFormat = GL_LUMINANCE;
276 pixelType = GL_UNSIGNED_BYTE;
277 targetFormat = image.format();
278 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
283 externalFormat = internalFormat =
GL_RED;
284 pixelType = GL_UNSIGNED_BYTE;
285 targetFormat = image.format();
288 case QImage::Format_Grayscale16:
292 }
else if (options & UseRedForAlphaAndLuminanceBindOption) {
293 externalFormat = internalFormat =
GL_RED;
294 pixelType = GL_UNSIGNED_SHORT;
295 targetFormat = image.format();
296 }
else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
297 externalFormat = internalFormat = GL_LUMINANCE;
298 pixelType = GL_UNSIGNED_SHORT;
299 targetFormat = image.format();
300 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
305 externalFormat = internalFormat =
GL_RED;
306 pixelType = GL_UNSIGNED_SHORT;
307 targetFormat = image.format();
315 if (targetFormat == QImage::Format_Invalid) {
316 externalFormat = internalFormat = GL_RGBA;
317 pixelType = GL_UNSIGNED_BYTE;
318 if (!image.hasAlphaChannel())
319 targetFormat = QImage::Format_RGBX8888;
321 targetFormat = QImage::Format_RGBA8888;
324 if (options & PremultipliedAlphaBindOption) {
325 if (targetFormat == QImage::Format_ARGB32)
326 targetFormat = QImage::Format_ARGB32_Premultiplied;
327 else if (targetFormat == QImage::Format_RGBA8888)
328 targetFormat = QImage::Format_RGBA8888_Premultiplied;
329 else if (targetFormat == QImage::Format_RGBA64)
330 targetFormat = QImage::Format_RGBA64_Premultiplied;
331 else if (targetFormat == QImage::Format_RGBA16FPx4)
332 targetFormat = QImage::Format_RGBA16FPx4_Premultiplied;
333 else if (targetFormat == QImage::Format_RGBA32FPx4)
334 targetFormat = QImage::Format_RGBA32FPx4_Premultiplied;
336 if (targetFormat == QImage::Format_ARGB32_Premultiplied)
337 targetFormat = QImage::Format_ARGB32;
338 else if (targetFormat == QImage::Format_RGBA8888_Premultiplied)
339 targetFormat = QImage::Format_RGBA8888;
340 else if (targetFormat == QImage::Format_RGBA64_Premultiplied)
341 targetFormat = QImage::Format_RGBA64;
342 else if (targetFormat == QImage::Format_RGBA16FPx4_Premultiplied)
343 targetFormat = QImage::Format_RGBA16FPx4;
344 else if (targetFormat == QImage::Format_RGBA32FPx4_Premultiplied)
345 targetFormat = QImage::Format_RGBA32FPx4;
349 Q_ASSERT(internalFormat == GL_RGBA || internalFormat == GL_RGB);
350 if (image.hasAlphaChannel())
356 if (image.format() != targetFormat)
357 tx = image.convertToFormat(targetFormat);
361 QSize newSize = tx.size();
362 if (!maxSize.isEmpty())
363 newSize = newSize.boundedTo(maxSize);
364 if (options & PowerOfTwoBindOption) {
365 newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1));
366 newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1));
369 if (newSize != tx.size())
370 tx = tx.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
373 qsizetype naturalBpl = ((qsizetype(tx.width()) * tx.depth() + 31) >> 5) << 2;
374 if (tx.bytesPerLine() != naturalBpl)
375 tx = tx.copy(tx.rect());
377 funcs->glTexImage2D(target, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, tx.constBits());
379 qsizetype cost = qint64(tx.width()) * tx.height() * tx.depth() / 8;