68void QSGPlainTexture::setTextureFromNativeTexture(QRhi *rhi,
69 quint64 nativeObjectHandle,
70 int nativeLayoutOrState,
73 QQuickWindow::CreateTextureOptions options,
74 QQuickWindowPrivate::TextureFromNativeTextureFlags flags)
76 QRhiTexture::Flags texFlags;
77 if (options.testFlag(QQuickWindow::TextureHasMipmaps))
78 texFlags |= QRhiTexture::MipMapped | QRhiTexture::UsedWithGenerateMips;
79 if (flags.testFlag(QQuickWindowPrivate::NativeTextureIsExternalOES))
80 texFlags |= QRhiTexture::ExternalOES;
82 QRhiTexture::Format format = QRhiTexture::RGBA8;
84 QRhiTexture::Flags formatFlags;
85 auto rhiFormat = QSGRhiSupport::instance()->toRhiTextureFormat(nativeFormat, &formatFlags);
86 if (rhiFormat != QRhiTexture::UnknownFormat) {
88 texFlags |= formatFlags;
91 QRhiTexture *t = rhi->newTexture(format, size, 1, texFlags);
94 t->createFrom({nativeObjectHandle, nativeLayoutOrState});
113void QSGPlainTexture::commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
115 Q_D(QSGPlainTexture);
117 const bool hasMipMaps = mipmapFiltering() != QSGTexture::None;
118 const bool mipmappingChanged = m_texture && ((hasMipMaps && !m_texture->flags().testFlag(QRhiTexture::MipMapped))
119 || (!hasMipMaps && m_texture->flags().testFlag(QRhiTexture::MipMapped)));
121 if (!m_dirty_texture) {
124 if (m_texture && !mipmappingChanged) {
125 if (hasMipMaps && !m_mipmaps_generated) {
126 resourceUpdates->generateMips(m_texture);
127 m_mipmaps_generated =
true;
133 if (m_image.isNull()) {
134 if (!m_dirty_texture && mipmappingChanged) {
136 if (!m_mipmap_warned) {
137 qWarning(
"QSGPlainTexture: Mipmap settings changed without having image data available. "
138 "Call setImage() again or enable m_retain_image. "
139 "Falling back to previous mipmap filtering mode.");
140 m_mipmap_warned =
true;
143 setMipmapFiltering(d->m_last_mipmap_filter);
147 if (m_texture && m_owns_texture)
151 m_texture_size = QSize();
154 m_dirty_texture =
false;
158 m_dirty_texture =
false;
164 bool needsConvert8 =
false;
165 bool needsConvertFP16 =
false;
166 bool needsConvertFP32 =
false;
168 if (m_image.format() == QImage::Format_RGB32 || m_image.format() == QImage::Format_ARGB32_Premultiplied) {
169#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
170 if (rhi->isTextureFormatSupported(QRhiTexture::BGRA8)) {
174 needsConvert8 =
true;
177 needsConvert8 =
true;
179 }
else if (m_image.format() == QImage::Format_RGBX16FPx4 || m_image.format() == QImage::Format_RGBA16FPx4_Premultiplied) {
180#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
181 if (rhi->isTextureFormatSupported(QRhiTexture::RGBA16F)) {
185 needsConvert8 =
true;
188 needsConvert8 =
true;
190 }
else if (m_image.format() == QImage::Format_RGBX32FPx4 || m_image.format() == QImage::Format_RGBA32FPx4_Premultiplied) {
191#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
192 if (rhi->isTextureFormatSupported(QRhiTexture::RGBA32F)) {
195 }
else if (rhi->isTextureFormatSupported(QRhiTexture::RGBA16F)) {
199 needsConvert8 =
true;
202 needsConvert8 =
true;
204 }
else if (m_image.format() == QImage::Format_RGBX8888 || m_image.format() == QImage::Format_RGBA8888_Premultiplied) {
206 }
else if (m_image.format() == QImage::Format_RGBA16FPx4) {
207 needsConvertFP16 =
true;
208 }
else if (m_image.format() == QImage::Format_RGBA32FPx4) {
209 needsConvertFP32 =
true;
211 needsConvert8 =
true;
214 if (needsConvertFP16) {
215 tmp = m_image.convertToFormat(QImage::Format_RGBA16FPx4_Premultiplied);
217 }
else if (needsConvertFP32) {
218 tmp = m_image.convertToFormat(QImage::Format_RGBA32FPx4_Premultiplied);
220 }
else if (needsConvert8) {
221 tmp = m_image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
230 const int max = rhi->resourceLimit(QRhi::TextureSizeMax);
231 if (tmp.width() > max || tmp.height() > max) {
232 tmp = tmp.scaled(qMin(max, tmp.width()), qMin(max, tmp.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
233 m_texture_size = tmp.size();
236 if ((mipmapFiltering() != QSGTexture::None
237 || horizontalWrapMode() != QSGTexture::ClampToEdge
238 || verticalWrapMode() != QSGTexture::ClampToEdge)
239 && !rhi->isFeatureSupported(QRhi::NPOTTextureRepeat))
241 const int w = qNextPowerOfTwo(tmp.width() - 1);
242 const int h = qNextPowerOfTwo(tmp.height() - 1);
243 if (tmp.width() != w || tmp.height() != h) {
244 tmp = tmp.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
245 m_texture_size = tmp.size();
249 bool needsRebuild =
false;
251 if (m_texture && m_texture->pixelSize() != m_texture_size) {
252 m_texture->setPixelSize(m_texture_size);
256 if (mipmappingChanged) {
257 QRhiTexture::Flags f = m_texture->flags();
258 f.setFlag(QRhiTexture::MipMapped, hasMipMaps);
259 f.setFlag(QRhiTexture::UsedWithGenerateMips, hasMipMaps);
260 m_texture->setFlags(f);
265 QRhiTexture::Flags f;
267 f |= QRhiTexture::MipMapped | QRhiTexture::UsedWithGenerateMips;
269 QRhiTexture::Format format = QRhiTexture::RGBA8;
271 format = QRhiTexture::RGBA16F;
273 format = QRhiTexture::RGBA32F;
275 format = QRhiTexture::BGRA8;
277 m_texture = rhi->newTexture(format, m_texture_size, 1, f);
282 if (!m_texture->create()) {
283 qWarning(
"Failed to build texture for QSGPlainTexture (size %dx%d)",
284 m_texture_size.width(), m_texture_size.height());
289 if (tmp.width() * 4 != tmp.bytesPerLine())
292 resourceUpdates->uploadTexture(m_texture, tmp);
295 resourceUpdates->generateMips(m_texture);
296 m_mipmaps_generated =
true;
299 d->m_last_mipmap_filter = mipmapFiltering();
300 m_texture_rect = QRectF(0, 0, 1, 1);