Browse Source

Workaround broken full cube map compressed image query on NVidia.

The query returns only data of the first cube map face and not the
others, worked around that by querying each face separately.
pull/132/head
Vladimír Vondruš 10 years ago
parent
commit
f746eaaf7d
  1. 29
      src/Magnum/CubeMapTexture.cpp
  2. 3
      src/Magnum/CubeMapTexture.h
  3. 9
      src/Magnum/Implementation/TextureState.cpp
  4. 1
      src/Magnum/Implementation/TextureState.h
  5. 4
      src/Magnum/Implementation/driverSpecific.cpp

29
src/Magnum/CubeMapTexture.cpp

@ -110,18 +110,19 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image)
const Vector3i size{imageSize(level), 6};
const GLint textureDataSize = (this->*Context::current()->state().texture->getCubeLevelCompressedImageSizeImplementation)(level);
const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize);
std::size_t dataOffset, dataSize;
std::tie(dataOffset, dataSize) = Implementation::compressedImageDataOffsetSizeFor(image, size, textureDataSize);
GLint format;
(this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Reallocate only if needed */
Containers::Array<char> data{image.release()};
if(data.size() < dataSize)
data = Containers::Array<char>{dataSize};
if(data.size() < dataOffset + dataSize)
data = Containers::Array<char>{dataOffset + dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
image.storage().applyPack();
glGetCompressedTextureImage(_id, level, data.size(), data);
(this->*Context::current()->state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffset, dataSize, data);
image.setData(image.storage(), CompressedPixelFormat(format), size, std::move(data));
}
@ -135,19 +136,20 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i
const Vector3i size{imageSize(level), 6};
const GLint textureDataSize = (this->*Context::current()->state().texture->getCubeLevelCompressedImageSizeImplementation)(level);
const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize);
std::size_t dataOffset, dataSize;
std::tie(dataOffset, dataSize) = Implementation::compressedImageDataOffsetSizeFor(image, size, textureDataSize);
GLint format;
(this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Reallocate only if needed */
if(image.dataSize() < dataSize)
image.setData(image.storage(), CompressedPixelFormat(format), size, {nullptr, dataSize}, usage);
if(image.dataSize() < dataOffset + dataSize)
image.setData(image.storage(), CompressedPixelFormat(format), size, {nullptr, dataOffset + dataSize}, usage);
else
image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
image.storage().applyPack();
glGetCompressedTextureImage(_id, level, dataSize, nullptr);
(this->*Context::current()->state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffset, dataSize, nullptr);
}
CompressedBufferImage3D CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D&& image, const BufferUsage usage) {
@ -417,6 +419,17 @@ GLint CubeMapTexture::getLevelCompressedImageSizeImplementationDSAEXTImmutableWo
#endif
#ifndef MAGNUM_TARGET_GLES
void CubeMapTexture::getCompressedImageImplementationDSA(const GLint level, const Vector2i&, const std::size_t dataOffset, const std::size_t dataSize, GLvoid* const data) {
glGetCompressedTextureImage(_id, level, dataOffset + dataSize, data);
}
void CubeMapTexture::getCompressedImageImplementationDSASingleSliceWorkaround(const GLint level, const Vector2i& size, const std::size_t dataOffset, const std::size_t dataSize, GLvoid* const data) {
/* On NVidia (358.16) calling glGetCompressedTextureImage() extracts only
the first face */
for(Int face = 0; face != 6; ++face)
glGetCompressedTextureSubImage(_id, level, 0, 0, face, size.x(), size.y(), 1, dataOffset + dataSize/6, static_cast<char*>(data) + dataSize*face/6);
}
void CubeMapTexture::getImageImplementationDefault(const Coordinate coordinate, const GLint level, const Vector2i&, const PixelFormat format, const PixelType type, std::size_t, GLvoid* const data) {
bindInternal();
glGetTexImage(GLenum(coordinate), level, GLenum(format), GLenum(type), data);

3
src/Magnum/CubeMapTexture.h

@ -962,6 +962,9 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture {
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL getCompressedImageImplementationDSA(GLint level, const Vector2i& size, std::size_t dataOffset, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getCompressedImageImplementationDSASingleSliceWorkaround(GLint level, const Vector2i& size, std::size_t dataOffset, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationDefault(Coordinate coordinate, GLint level, const Vector2i& size, PixelFormat format, PixelType type, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationDSA(Coordinate coordinate, GLint level, const Vector2i& size, PixelFormat format, PixelType type, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationDSAEXT(Coordinate coordinate, GLint level, const Vector2i& size, PixelFormat format, PixelType type, std::size_t dataSize, GLvoid* data);

9
src/Magnum/Implementation/TextureState.cpp

@ -277,6 +277,15 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
getCubeImageImplementation = &CubeMapTexture::getImageImplementationDefault;
getCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDefault;
}
/* Full compressed cubemap image query implementation (extensions added
above) */
if((context.detectedDriver() & Context::DetectedDriver::NVidia) &&
context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>() &&
!context.isDriverWorkaroundDisabled("nv-cubemap-broken-full-compressed-image-query"))
getFullCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSASingleSliceWorkaround;
else
getFullCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSA;
#endif
/* Texture storage implementation for desktop and ES */

1
src/Magnum/Implementation/TextureState.h

@ -103,6 +103,7 @@ struct TextureState {
#ifndef MAGNUM_TARGET_GLES
GLint(CubeMapTexture::*getCubeLevelCompressedImageSizeImplementation)(GLint);
void(CubeMapTexture::*getCubeImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, PixelFormat, PixelType, std::size_t, GLvoid*);
void(CubeMapTexture::*getFullCompressedCubeImageImplementation)(GLint, const Vector2i&, std::size_t, std::size_t, GLvoid*);
void(CubeMapTexture::*getCompressedCubeImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, std::size_t, GLvoid*);
#endif
void(CubeMapTexture::*cubeSubImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*);

4
src/Magnum/Implementation/driverSpecific.cpp

@ -57,6 +57,10 @@ namespace {
based on whether I'm querying all faces (ARB_DSA) or a single face
(non-DSA, EXT_DSA) */
"nv-cubemap-inconsistent-compressed-image-size",
/* NVidia drivers (358.16) return only the first slice of compressed
cube map image when querying all six slice using ARB_DSA API */
"nv-cubemap-broken-full-compressed-image-query",
#endif
#ifdef CORRADE_TARGET_NACL

Loading…
Cancel
Save