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

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

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.11.2
    • 5.11
    • Qt3D
    • None
    • ec3fc2d48c3270f2dd63d10ad2202b10403b26ef

    Description

      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,
                           static_cast<QOpenGLTexture::CubeMapFace>(m_images[i].face),
                           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.

      Attachments

        Issue Links

          Activity

            People

              lagocs Laszlo Agocs
              lagocs Laszlo Agocs
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: