Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-69138

QTextureImage handling broken making it impossible to use mipmaps, layers, cubemaps



    • Type: Bug
    • Status: Closed
    • Priority: P2: Important
    • Resolution: Done
    • Affects Version/s: 5.11
    • Fix Version/s: 5.11.2
    • Component/s: Qt3D
    • Labels:
    • Commits:


      Add a set of QAbstractTextureImage implementations to a texture, each of the images providing the data for a different mipmap level.

      Unfortunately this breaks or crashes in various ways due to GLTexture getting confused internally.

      void GLTexture::uploadGLTextureData()
          // Upload all QTexImageData set by the QTextureGenerator
          if (m_textureData) {
              const QVector<QTextureImageDataPtr> imgData = m_textureData->imageData();
              for (const QTextureImageDataPtr &data : imgData) {
                  const int mipLevels = m_properties.generateMipMaps ? 1 : data->mipLevels();
                  for (int layer = 0; layer < data->layers(); layer++) {
                      for (int face = 0; face < data->faces(); face++) {
                          for (int level = 0; level < mipLevels; level++) {
                              // ensure we don't accidentally cause a detach / copy of the raw bytes
                              const QByteArray bytes(data->data(layer, face, level));
                              uploadGLData(m_gl, level, layer,
                                           static_cast<QOpenGLTexture::CubeMapFace>(QOpenGLTexture::CubeMapPositiveX + face),
                                           bytes, data);
          // Upload all QTexImageData references by the TextureImages
          for (int i = 0; i < m_images.size(); i++) {
              const QTextureImageDataPtr &imgData = m_imageData.at(i);
              // ensure we don't accidentally cause a detach / copy of the raw bytes
              const QByteArray bytes(imgData->data());
              uploadGLData(m_gl, m_images[i].mipLevel, m_images[i].layer,
                           bytes, imgData);

      The first half is not relevant since we do not use a QTextureData generator (since this is not exposed in the public API so cannot be utilized in any meaningful way outside Qt3D itself - which is unfortunate). So we are stuck with separate textureimages.

      Here the data() in the images contain data for a single mipmap level (or cubemap face etc.). This is unlike the other case where data() contains all mipmap levels, faces and layers in one single blob.

      Now check the const QByteArray bytes(imgData->data()); call and note that it is
      QByteArray QTextureImageData::data(int layer, int face, int mipmapLevel) const which has default values of 0 for all the parameters. This function is only prepared to handle the everything-in-single-blob case and ends up in a

      return QByteArray::fromRawData(m_data.constData() + offset, mipmapLevelSize(mipmapLevel));

      which is all wrong in our case since mipmapLevel is 0 but the returned QByteArray's size cannot be the size of the data for mipmap level 0 since m_data contains data only for a given mipmap level, not for all of them.

      What should have been done instead in the textureimage case is to take m_data as-is without any fancy calculations.


          Issue Links

          For Gerrit Dashboard: QTBUG-69138
          # Subject Branch Project Status CR V



              lagocs Laszlo Agocs
              lagocs Laszlo Agocs
              0 Vote for this issue
              1 Start watching this issue



                  Gerrit Reviews

                  There are no open Gerrit changes