86qsizetype QOpenGLTextureUploader::textureImage(GLenum target,
const QImage &image, QOpenGLTextureUploader::BindOptions options, QSize maxSize)
88 QOpenGLContext *context = QOpenGLContext::currentContext();
89 QOpenGLExtensions *funcs =
static_cast<QOpenGLExtensions*>(context->functions());
92 GLenum externalFormat;
93 GLenum internalFormat;
95 QImage::Format targetFormat = QImage::Format_Invalid;
96 const bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
97 const bool isOpenGLES3orBetter = context->isOpenGLES() && context->format().majorVersion() >= 3;
98 const bool sRgbBinding = (options & SRgbBindOption);
99 Q_ASSERT(isOpenGL12orBetter || context->isOpenGLES());
100 Q_ASSERT((options & (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption)) != (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption));
102 switch (image.format()) {
103 case QImage::Format_RGB32:
104 case QImage::Format_ARGB32:
105 case QImage::Format_ARGB32_Premultiplied:
106 if (isOpenGL12orBetter) {
108 internalFormat = GL_RGBA;
110#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
112 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat) && !sRgbBinding) {
114 externalFormat = internalFormat =
GL_BGRA;
115 pixelType = GL_UNSIGNED_BYTE;
116 }
else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral(
"GL_APPLE_texture_format_BGRA8888"))) {
119 internalFormat = GL_RGBA;
120 pixelType = GL_UNSIGNED_BYTE;
122 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
123#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
127 funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_GREEN);
128 funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
129 funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_ALPHA);
130 funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_RED);
132 externalFormat = internalFormat = GL_RGBA;
133 pixelType = GL_UNSIGNED_BYTE;
138 targetFormat = image.format();
140 case QImage::Format_BGR30:
141 case QImage::Format_A2BGR30_Premultiplied:
145 }
else if (isOpenGL12orBetter || isOpenGLES3orBetter) {
147 externalFormat = GL_RGBA;
149 targetFormat = image.format();
152 case QImage::Format_RGB30:
153 case QImage::Format_A2RGB30_Premultiplied:
157 }
else if (isOpenGL12orBetter) {
161 targetFormat = image.format();
162 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
166 externalFormat = GL_RGBA;
168 targetFormat = image.format();
171 case QImage::Format_RGB444:
172 case QImage::Format_RGB555:
173 case QImage::Format_RGB16:
174 if (isOpenGL12orBetter || context->isOpenGLES()) {
175 externalFormat = internalFormat = GL_RGB;
176 pixelType = GL_UNSIGNED_SHORT_5_6_5;
177 targetFormat = QImage::Format_RGB16;
180 case QImage::Format_RGB666:
181 case QImage::Format_RGB888:
182 externalFormat = internalFormat = GL_RGB;
183 pixelType = GL_UNSIGNED_BYTE;
184 targetFormat = QImage::Format_RGB888;
186 case QImage::Format_BGR888:
187 if (isOpenGL12orBetter) {
189 internalFormat = GL_RGB;
190 pixelType = GL_UNSIGNED_BYTE;
191 targetFormat = QImage::Format_BGR888;
192 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
195 externalFormat = internalFormat = GL_RGB;
196 pixelType = GL_UNSIGNED_BYTE;
197 targetFormat = QImage::Format_BGR888;
200 case QImage::Format_RGBX8888:
201 case QImage::Format_RGBA8888:
202 case QImage::Format_RGBA8888_Premultiplied:
203 externalFormat = internalFormat = GL_RGBA;
204 pixelType = GL_UNSIGNED_BYTE;
205 targetFormat = image.format();
207 case QImage::Format_RGBX64:
208 case QImage::Format_RGBA64:
209 case QImage::Format_RGBA64_Premultiplied:
210 externalFormat = internalFormat = GL_RGBA;
211 if (isOpenGL12orBetter || (context->isOpenGLES() && context->format().majorVersion() >= 3))
213 pixelType = GL_UNSIGNED_SHORT;
214 targetFormat = image.format();
216 case QImage::Format_RGBX16FPx4:
217 case QImage::Format_RGBA16FPx4:
218 case QImage::Format_RGBA16FPx4_Premultiplied:
219 if (context->format().majorVersion() >= 3) {
220 externalFormat = GL_RGBA;
223 targetFormat = image.format();
226 case QImage::Format_RGBX32FPx4:
227 case QImage::Format_RGBA32FPx4:
228 case QImage::Format_RGBA32FPx4_Premultiplied:
229 externalFormat = internalFormat = GL_RGBA;
230 if (context->format().majorVersion() >= 3)
232 pixelType = GL_FLOAT;
233 targetFormat = image.format();
235 case QImage::Format_Indexed8:
239 }
else if (options & UseRedForAlphaAndLuminanceBindOption) {
240 externalFormat = internalFormat =
GL_RED;
241 pixelType = GL_UNSIGNED_BYTE;
242 targetFormat = image.format();
245 case QImage::Format_Alpha8:
249 }
else if (options & UseRedForAlphaAndLuminanceBindOption) {
250 externalFormat = internalFormat =
GL_RED;
251 pixelType = GL_UNSIGNED_BYTE;
252 targetFormat = image.format();
253 }
else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
254 externalFormat = internalFormat = GL_ALPHA;
255 pixelType = GL_UNSIGNED_BYTE;
256 targetFormat = image.format();
257 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
262 externalFormat = internalFormat =
GL_RED;
263 pixelType = GL_UNSIGNED_BYTE;
264 targetFormat = image.format();
267 case QImage::Format_Grayscale8:
271 }
else if (options & UseRedForAlphaAndLuminanceBindOption) {
272 externalFormat = internalFormat =
GL_RED;
273 pixelType = GL_UNSIGNED_BYTE;
274 targetFormat = image.format();
275 }
else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
276 externalFormat = internalFormat = GL_LUMINANCE;
277 pixelType = GL_UNSIGNED_BYTE;
278 targetFormat = image.format();
279 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
284 externalFormat = internalFormat =
GL_RED;
285 pixelType = GL_UNSIGNED_BYTE;
286 targetFormat = image.format();
289 case QImage::Format_Grayscale16:
293 }
else if (options & UseRedForAlphaAndLuminanceBindOption) {
294 externalFormat = internalFormat =
GL_RED;
295 pixelType = GL_UNSIGNED_SHORT;
296 targetFormat = image.format();
297 }
else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
298 externalFormat = internalFormat = GL_LUMINANCE;
299 pixelType = GL_UNSIGNED_SHORT;
300 targetFormat = image.format();
301 }
else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
306 externalFormat = internalFormat =
GL_RED;
307 pixelType = GL_UNSIGNED_SHORT;
308 targetFormat = image.format();
316 if (targetFormat == QImage::Format_Invalid) {
317 externalFormat = internalFormat = GL_RGBA;
318 pixelType = GL_UNSIGNED_BYTE;
319 if (!image.hasAlphaChannel())
320 targetFormat = QImage::Format_RGBX8888;
322 targetFormat = QImage::Format_RGBA8888;
325 if (options & PremultipliedAlphaBindOption) {
326 if (targetFormat == QImage::Format_ARGB32)
327 targetFormat = QImage::Format_ARGB32_Premultiplied;
328 else if (targetFormat == QImage::Format_RGBA8888)
329 targetFormat = QImage::Format_RGBA8888_Premultiplied;
330 else if (targetFormat == QImage::Format_RGBA64)
331 targetFormat = QImage::Format_RGBA64_Premultiplied;
332 else if (targetFormat == QImage::Format_RGBA16FPx4)
333 targetFormat = QImage::Format_RGBA16FPx4_Premultiplied;
334 else if (targetFormat == QImage::Format_RGBA32FPx4)
335 targetFormat = QImage::Format_RGBA32FPx4_Premultiplied;
337 if (targetFormat == QImage::Format_ARGB32_Premultiplied)
338 targetFormat = QImage::Format_ARGB32;
339 else if (targetFormat == QImage::Format_RGBA8888_Premultiplied)
340 targetFormat = QImage::Format_RGBA8888;
341 else if (targetFormat == QImage::Format_RGBA64_Premultiplied)
342 targetFormat = QImage::Format_RGBA64;
343 else if (targetFormat == QImage::Format_RGBA16FPx4_Premultiplied)
344 targetFormat = QImage::Format_RGBA16FPx4;
345 else if (targetFormat == QImage::Format_RGBA32FPx4_Premultiplied)
346 targetFormat = QImage::Format_RGBA32FPx4;
350 Q_ASSERT(internalFormat == GL_RGBA || internalFormat == GL_RGB);
351 if (image.hasAlphaChannel())
357 if (image.format() != targetFormat)
358 tx = image.convertToFormat(targetFormat);
362 QSize newSize = tx.size();
363 if (!maxSize.isEmpty())
364 newSize = newSize.boundedTo(maxSize);
365 if (options & PowerOfTwoBindOption) {
366 newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1));
367 newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1));
370 if (newSize != tx.size())
371 tx = tx.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
374 qsizetype naturalBpl = ((qsizetype(tx.width()) * tx.depth() + 31) >> 5) << 2;
375 if (tx.bytesPerLine() != naturalBpl)
376 tx = tx.copy(tx.rect());
378 funcs->glTexImage2D(target, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, tx.constBits());
380 qsizetype cost = qint64(tx.width()) * tx.height() * tx.depth() / 8;