Browse Source

SVGA3D: work around broken glTex[ture][Sub]Image*D() for arrays.

SVGA3D has broken handling of glTex[ture][Sub]Image*D() for 1D arrays,
2D arrays, 3D textures and cube map textures where it uploads just the
first slice in the last dimension. This is only with copies from host
memory, not with buffer images. Seems to be fixed in Mesa 13, but I have
no such system to verify that on. Relevant commit in the Mesa sources:
2aa9ff0cda

This is one of the uglier workarounds -- I had to reintroduce multiple
code paths for glTexImage() which were removed when implementing ARB_DSA
and the workaround consists of basically a bunch of functions that are
slicing the image and calling the original implementations with each
slice.
pull/203/merge
Vladimír Vondruš 9 years ago
parent
commit
0371ebd9a3
  1. 151
      src/Magnum/AbstractTexture.cpp
  2. 36
      src/Magnum/AbstractTexture.h
  3. 14
      src/Magnum/CubeMapTexture.cpp
  4. 5
      src/Magnum/CubeMapTexture.h
  5. 49
      src/Magnum/Implementation/TextureState.cpp
  6. 7
      src/Magnum/Implementation/TextureState.h
  7. 8
      src/Magnum/Implementation/driverSpecific.cpp

151
src/Magnum/AbstractTexture.cpp

@ -1471,18 +1471,57 @@ void AbstractTexture::compressedSubImageImplementationDSAEXT(const GLint level,
}
#endif
void AbstractTexture::subImageImplementationDefault(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data) {
void AbstractTexture::imageImplementationDefault(const GLenum target, const GLint level, const TextureFormat internalFormat, const Vector2i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage&) {
bindInternal();
glTexImage2D(target, level, GLint(internalFormat), size.x(), size.y(), 0, GLenum(format), GLenum(type), data);
}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::imageImplementationSvga3DSliceBySlice(const GLenum target, const GLint level, const TextureFormat internalFormat, const Vector2i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage& storage) {
/* Allocate and upload the first slice */
imageImplementationDefault(target, level, internalFormat, size, format, type, data, storage);
/* Upload the next slices slice by slice only if this is an array texture
with more than one slice and we are copying from user memory (not from a
buffer). The hard work is done by the subImage() implementation.
Moreover, I am simply calling the default implementation and not the DSA
one as just using glTexImage() pollutes the state already anyway so the
DSA cleanness is not worth it. */
/** @todo this will break when we support uploading from buffer offset (i.e. data != nullptr) */
if(target == GL_TEXTURE_1D_ARRAY && data && size.y() > 1)
subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage2DImplementationDefault>(level, {0, 1}, {size.x(), size.y() - 1}, format, type, static_cast<const char*>(data) + std::get<1>(storage.dataProperties(format, type, {size, 1})).x(), storage);
}
#endif
void AbstractTexture::subImage2DImplementationDefault(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&) {
bindInternal();
glTexSubImage2D(_target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data);
}
#ifndef MAGNUM_TARGET_GLES
template<void(AbstractTexture::*original)(GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&)> void AbstractTexture::subImageImplementationSvga3DSliceBySlice(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* const data, const PixelStorage& storage) {
/* Upload the data slice by slice only if this is an array texture and we
are copying from user memory (not from a buffer) */
if(_target == GL_TEXTURE_1D_ARRAY && data) {
const std::size_t stride = std::get<1>(storage.dataProperties(format, type, {size, 1})).x();
for(Int i = 0; i != size.y(); ++i)
(this->*original)(level, {offset.x(), offset.y() + i}, {size.x(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage);
/* Otherwise just pass-though to the default implementation */
} else (this->*original)(level, offset, size, format, type, data, storage);
}
template void AbstractTexture::subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage2DImplementationDefault>(GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
template void AbstractTexture::subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage2DImplementationDSA>(GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
#endif
void AbstractTexture::compressedSubImageImplementationDefault(const GLint level, const Vector2i& offset, const Vector2i& size, const CompressedPixelFormat format, const GLvoid* const data, const GLsizei dataSize) {
bindInternal();
glCompressedTexSubImage2D(_target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), dataSize, data);
}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::subImageImplementationDSA(const GLint level, const Vector2i& offset, const Vector2i& size, const PixelFormat format, const PixelType type, const GLvoid* const data) {
void AbstractTexture::subImage2DImplementationDSA(const GLint level, const Vector2i& offset, const Vector2i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage&) {
glTextureSubImage2D(_id, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data);
}
@ -1490,7 +1529,7 @@ void AbstractTexture::compressedSubImageImplementationDSA(const GLint level, con
glCompressedTextureSubImage2D(_id, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), dataSize, data);
}
void AbstractTexture::subImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data) {
void AbstractTexture::subImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&) {
_flags |= ObjectFlag::Created;
glTextureSubImage2DEXT(_id, _target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data);
}
@ -1502,7 +1541,52 @@ void AbstractTexture::compressedSubImageImplementationDSAEXT(GLint level, const
#endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractTexture::subImageImplementationDefault(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data) {
void AbstractTexture::imageImplementationDefault(GLint level, TextureFormat internalFormat, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&) {
bindInternal();
#ifndef CORRADE_TARGET_NACL
#ifndef MAGNUM_TARGET_GLES2
glTexImage3D
#else
glTexImage3DOES
#endif
(_target, level, GLint(internalFormat), size.x(), size.y(), size.z(), 0, GLenum(format), GLenum(type), data);
#else
static_cast<void>(level);
static_cast<void>(internalFormat);
static_cast<void>(size);
static_cast<void>(format);
static_cast<void>(type);
static_cast<void>(data);
CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
#endif
}
#ifndef MAGNUM_TARGET_WEBGL
void AbstractTexture::imageImplementationSvga3DSliceBySlice(GLint level, TextureFormat internalFormat, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage& storage) {
/* Allocate and upload the first slice */
imageImplementationDefault(level, internalFormat, size, format, type, data, storage);
/* Upload the next slices slice by slice only if this is an array texture
with more than one slice or a 3D texture and we are copying from user
memory (not from a buffer). The hard work is done by the subImage()
implementation. Moreover, I am simply calling the default implementation
and not the DSA one as just using glTexImage() pollutes the state
already anyway so the DSA cleanness is not worth it. */
/** @todo this will break when we support uploading from buffer offset (i.e. data != nullptr) */
if((
#ifndef MAGNUM_TARGET_GLES2
_target == GL_TEXTURE_2D_ARRAY || _target == GL_TEXTURE_3D
#else
_target == GL_TEXTURE_3D_OES
#endif
) && data && size.z() > 1)
{
subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage3DImplementationDefault>(level, {0, 0, 1}, {size.xy(), size.z() - 1}, format, type, static_cast<const char*>(data) + std::get<1>(storage.dataProperties(format, type, size)).xy().product(), storage);
}
}
#endif
void AbstractTexture::subImage3DImplementationDefault(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&) {
bindInternal();
#ifndef MAGNUM_TARGET_GLES2
glTexSubImage3D(_target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), GLenum(type), data);
@ -1519,6 +1603,32 @@ void AbstractTexture::subImageImplementationDefault(GLint level, const Vector3i&
#endif
}
#ifndef MAGNUM_TARGET_WEBGL
template<void(AbstractTexture::*original)(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&)> void AbstractTexture::subImageImplementationSvga3DSliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage& storage) {
/* Upload the data slice by slice only if this is an array texture and we
are copying from user memory (not from a buffer) */
if(
#ifndef MAGNUM_TARGET_GLES2
_target == GL_TEXTURE_2D_ARRAY || _target == GL_TEXTURE_3D
#else
_target == GL_TEXTURE_3D_OES
#endif
)
{
const std::size_t stride = std::get<1>(storage.dataProperties(format, type, size)).xy().product();
for(Int i = 0; i != size.z(); ++i)
(this->*original)(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage);
/* Otherwise just pass-though to the default implementation */
} else (this->*original)(level, offset, size, format, type, data, storage);
}
template void AbstractTexture::subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage3DImplementationDefault>(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
#ifndef MAGNUM_TARGET_GLES
template void AbstractTexture::subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage3DImplementationDSA>(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
#endif
#endif
void AbstractTexture::compressedSubImageImplementationDefault(const GLint level, const Vector3i& offset, const Vector3i& size, const CompressedPixelFormat format, const GLvoid* const data, const GLsizei dataSize) {
bindInternal();
#ifndef MAGNUM_TARGET_GLES2
@ -1537,7 +1647,7 @@ void AbstractTexture::compressedSubImageImplementationDefault(const GLint level,
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::subImageImplementationDSA(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data) {
void AbstractTexture::subImage3DImplementationDSA(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage&) {
glTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), GLenum(type), data);
}
@ -1545,7 +1655,7 @@ void AbstractTexture::compressedSubImageImplementationDSA(const GLint level, con
glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), dataSize, data);
}
void AbstractTexture::subImageImplementationDSAEXT(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data) {
void AbstractTexture::subImageImplementationDSAEXT(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&) {
_flags |= ObjectFlag::Created;
glTextureSubImage3DEXT(_id, _target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), GLenum(type), data);
}
@ -1935,12 +2045,11 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GL
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
image.storage().applyUnpack();
texture.bindInternal();
glTexImage2D(target, level, GLint(internalFormat), image.size().x(), image.size().y(), 0, GLenum(image.format()), GLenum(image.type()), image.data()
(texture.*Context::current().state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()
#ifdef MAGNUM_TARGET_GLES2
+ Implementation::pixelStorageSkipOffset(image)
#endif
);
, image.storage());
}
void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture, const GLenum target, const GLint level, const CompressedImageView2D& image) {
@ -1985,7 +2094,7 @@ void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const
#ifdef MAGNUM_TARGET_GLES2
+ Implementation::pixelStorageSkipOffset(image)
#endif
);
, image.storage());
}
void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, const CompressedImageView2D& image) {
@ -2004,7 +2113,7 @@ void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& text
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
image.storage().applyUnpack();
(texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr);
(texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage());
}
void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, CompressedBufferImage2D& image) {
@ -2024,17 +2133,11 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
image.storage().applyUnpack();
texture.bindInternal();
#ifndef MAGNUM_TARGET_GLES2
glTexImage3D(texture._target, level, GLint(internalFormat), image.size().x(), image.size().y(), image.size().z(), 0, GLenum(image.format()), GLenum(image.type()), image.data());
#elif !defined(CORRADE_TARGET_NACL)
glTexImage3DOES(texture._target, level, GLint(internalFormat), image.size().x(), image.size().y(), image.size().z(), 0, GLenum(image.format()), GLenum(image.type()), image.data() + Implementation::pixelStorageSkipOffset(image));
#else
static_cast<void>(level);
static_cast<void>(internalFormat);
static_cast<void>(image);
CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
#endif
(texture.*Context::current().state().texture->image3DImplementation)(level, internalFormat, image.size(), image.format(), image.type(), image.data()
#ifdef MAGNUM_TARGET_GLES2
+ Implementation::pixelStorageSkipOffset(image)
#endif
, image.storage());
}
void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, const CompressedImageView3D& image) {
@ -2089,7 +2192,7 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const
#ifdef MAGNUM_TARGET_GLES2
+ Implementation::pixelStorageSkipOffset(image)
#endif
);
, image.storage());
}
void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, const CompressedImageView3D& image) {
@ -2109,7 +2212,7 @@ void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& text
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, BufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
image.storage().applyUnpack();
(texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr);
(texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage());
}
void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, CompressedBufferImage3D& image) {

36
src/Magnum/AbstractTexture.h

@ -632,22 +632,46 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void MAGNUM_LOCAL compressedSubImageImplementationDSAEXT(GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, CompressedPixelFormat format, const GLvoid* data, GLsizei dataSize);
#endif
void MAGNUM_LOCAL subImageImplementationDefault(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL imageImplementationSvga3DSliceBySlice(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#endif
/* Had to put explicit "2D" in the name so it's not overloaded and
Clang is able to pass it as template parameter to
subImageImplementationSvga3DSliceBySlice(). GCC had no problem with
the original. */
void MAGNUM_LOCAL subImage2DImplementationDefault(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#ifndef MAGNUM_TARGET_GLES
template<void(AbstractTexture::*original)(GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&)> void MAGNUM_LOCAL subImageImplementationSvga3DSliceBySlice(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage& storage);
#endif
void MAGNUM_LOCAL compressedSubImageImplementationDefault(GLint level, const Vector2i& offset, const Vector2i& size, CompressedPixelFormat format, const GLvoid* data, GLsizei dataSize);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subImageImplementationDSA(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data);
void MAGNUM_LOCAL subImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data);
void MAGNUM_LOCAL subImage2DImplementationDSA(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
void MAGNUM_LOCAL subImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
void MAGNUM_LOCAL compressedSubImageImplementationDSA(GLint level, const Vector2i& offset, const Vector2i& size, CompressedPixelFormat format, const GLvoid* data, GLsizei dataSize);
void MAGNUM_LOCAL compressedSubImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, CompressedPixelFormat format, const GLvoid* data, GLsizei dataSize);
#endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void MAGNUM_LOCAL subImageImplementationDefault(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data);
void MAGNUM_LOCAL imageImplementationDefault(GLint level, TextureFormat internalFormat, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#ifndef MAGNUM_TARGET_WEBGL
void MAGNUM_LOCAL imageImplementationSvga3DSliceBySlice(GLint level, TextureFormat internalFormat, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#endif
/* Had to put explicit "3D" in the name so it's not overloaded and
Clang is able to pass it as template parameter to
subImageImplementationSvga3DSliceBySlice(). GCC had no problem with
the original. */
void MAGNUM_LOCAL subImage3DImplementationDefault(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#ifndef MAGNUM_TARGET_WEBGL
template<void(AbstractTexture::*original)(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&)> void MAGNUM_LOCAL subImageImplementationSvga3DSliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage& storage);
#endif
void MAGNUM_LOCAL compressedSubImageImplementationDefault(GLint level, const Vector3i& offset, const Vector3i& size, CompressedPixelFormat format, const GLvoid* data, GLsizei dataSize);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subImageImplementationDSA(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data);
void MAGNUM_LOCAL subImageImplementationDSAEXT(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data);
void MAGNUM_LOCAL subImage3DImplementationDSA(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#ifndef MAGNUM_TARGET_WEBGL
void MAGNUM_LOCAL subImageImplementationDSAEXT(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#endif
void MAGNUM_LOCAL compressedSubImageImplementationDSA(GLint level, const Vector3i& offset, const Vector3i& size, CompressedPixelFormat format, const GLvoid* data, GLsizei dataSize);
void MAGNUM_LOCAL compressedSubImageImplementationDSAEXT(GLint level, const Vector3i& offset, const Vector3i& size, CompressedPixelFormat format, const GLvoid* data, GLsizei dataSize);
#endif

14
src/Magnum/CubeMapTexture.cpp

@ -298,7 +298,7 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& off
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
image.storage().applyUnpack();
glTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), GLenum(image.type()), image.data());
(this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data(), image.storage());
return *this;
}
@ -503,6 +503,18 @@ void CubeMapTexture::getCompressedImageImplementationRobustness(const CubeMapCoo
}
#endif
#ifndef MAGNUM_TARGET_GLES
void CubeMapTexture::subImageImplementationDefault(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage&) {
glTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), GLenum(type), data);
}
void CubeMapTexture::subImageImplementationSvga3DSliceBySlice(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage& storage) {
const std::size_t stride = std::get<1>(storage.dataProperties(format, type, size)).xy().product();
for(Int i = 0; i != size.z(); ++i)
subImageImplementationDefault(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage);
}
#endif
void CubeMapTexture::subImageImplementationDefault(const CubeMapCoordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const PixelFormat format, const PixelType type, const GLvoid* const data) {
bindInternal();
glTexSubImage2D(GLenum(coordinate), level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data);

5
src/Magnum/CubeMapTexture.h

@ -1120,6 +1120,11 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture {
void MAGNUM_LOCAL getCompressedImageImplementationRobustness(CubeMapCoordinate coordinate, GLint level, const Vector2i& size, std::size_t dataSize, GLvoid* data);
#endif
void MAGNUM_LOCAL subImageImplementationDefault(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#ifndef MAGNUM_TARGET_WEBGL
void MAGNUM_LOCAL subImageImplementationSvga3DSliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#endif
void MAGNUM_LOCAL subImageImplementationDefault(CubeMapCoordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subImageImplementationDSA(CubeMapCoordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data);

49
src/Magnum/Implementation/TextureState.cpp

@ -127,8 +127,8 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA;
subImage1DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage2DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage3DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage2DImplementation = &AbstractTexture::subImage2DImplementationDSA;
subImage3DImplementation = &AbstractTexture::subImage3DImplementationDSA;
compressedSubImage1DImplementation = &AbstractTexture::compressedSubImageImplementationDSA;
compressedSubImage2DImplementation = &AbstractTexture::compressedSubImageImplementationDSA;
compressedSubImage3DImplementation = &AbstractTexture::compressedSubImageImplementationDSA;
@ -186,10 +186,10 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
subImage1DImplementation = &AbstractTexture::subImageImplementationDefault;
compressedSubImage1DImplementation = &AbstractTexture::compressedSubImageImplementationDefault;
#endif
subImage2DImplementation = &AbstractTexture::subImageImplementationDefault;
subImage2DImplementation = &AbstractTexture::subImage2DImplementationDefault;
compressedSubImage2DImplementation = &AbstractTexture::compressedSubImageImplementationDefault;
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
subImage3DImplementation = &AbstractTexture::subImageImplementationDefault;
subImage3DImplementation = &AbstractTexture::subImage3DImplementationDefault;
compressedSubImage3DImplementation = &AbstractTexture::compressedSubImageImplementationDefault;
#endif
@ -384,6 +384,47 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
compressedBlockDataSizeImplementation = &AbstractTexture::compressedBlockDataSizeImplementationDefault;
#endif
#ifndef MAGNUM_TARGET_WEBGL
/* SVGA3D workaround for array / 3D / cube map texture upload. Overrides
the DSA / non-DSA function pointers set above. */
if((context.detectedDriver() & Context::DetectedDriver::Svga3D) &&
!context.isDriverWorkaroundDisabled("svga3d-texture-upload-slice-by-slice")) {
#ifndef MAGNUM_TARGET_GLES
image2DImplementation = &AbstractTexture::imageImplementationSvga3DSliceBySlice;
#endif
image3DImplementation = &AbstractTexture::imageImplementationSvga3DSliceBySlice;
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
#ifndef MAGNUM_TARGET_GLES
subImage2DImplementation = &AbstractTexture::subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage2DImplementationDSA>;
#endif
subImage3DImplementation = &AbstractTexture::subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage3DImplementationDSA>;
cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationSvga3DSliceBySlice;
} else
#endif
{
#ifndef MAGNUM_TARGET_GLES
subImage2DImplementation = &AbstractTexture::subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage2DImplementationDefault>;
#endif
subImage3DImplementation = &AbstractTexture::subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage3DImplementationDefault>;
#ifndef MAGNUM_TARGET_GLES
cubeSubImage3DImplementation = nullptr;
#endif
}
} else
#endif
{
/* These need to be set up in any case */
image2DImplementation = &AbstractTexture::imageImplementationDefault;
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
image3DImplementation = &AbstractTexture::imageImplementationDefault;
#endif
/* The other subImage implementations were set already above */
#ifndef MAGNUM_TARGET_GLES
cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationDefault;
#endif
}
/* Allocate texture bindings array to hold all possible texture units */
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0);

7
src/Magnum/Implementation/TextureState.h

@ -91,10 +91,12 @@ struct TextureState {
void(AbstractTexture::*subImage1DImplementation)(GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, PixelFormat, PixelType, const GLvoid*);
void(AbstractTexture::*compressedSubImage1DImplementation)(GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, CompressedPixelFormat, const GLvoid*, GLsizei);
#endif
void(AbstractTexture::*subImage2DImplementation)(GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*);
void (AbstractTexture::*image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
void(AbstractTexture::*subImage2DImplementation)(GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
void(AbstractTexture::*compressedSubImage2DImplementation)(GLint, const Vector2i&, const Vector2i&, CompressedPixelFormat, const GLvoid*, GLsizei);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void(AbstractTexture::*subImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*);
void (AbstractTexture::*image3DImplementation)(GLint, TextureFormat, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
void(AbstractTexture::*subImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
void(AbstractTexture::*compressedSubImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, CompressedPixelFormat, const GLvoid*, GLsizei);
#endif
void(AbstractTexture::*invalidateImageImplementation)(GLint);
@ -113,6 +115,7 @@ struct TextureState {
void(CubeMapTexture::*getCubeImageImplementation)(CubeMapCoordinate, 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)(CubeMapCoordinate, GLint, const Vector2i&, std::size_t, GLvoid*);
void(CubeMapTexture::*cubeSubImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&);
#endif
void(CubeMapTexture::*cubeSubImageImplementation)(CubeMapCoordinate, GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*);
void(CubeMapTexture::*cubeCompressedSubImageImplementation)(CubeMapCoordinate, GLint, const Vector2i&, const Vector2i&, CompressedPixelFormat, const GLvoid*, GLsizei);

8
src/Magnum/Implementation/driverSpecific.cpp

@ -103,6 +103,14 @@ namespace {
whole ARB_get_texture_sub_image is disabled. */
"svga3d-gettexsubimage-oob-write",
#endif
/* SVGA3D has broken handling of glTex[ture][Sub]Image*D() for 1D
arrays, 2D arrays, 3D textures and cube map textures where it
uploads just the first slice in the last dimension. This is only
with copies from host memory, not with buffer images. Seems to be
fixed in Mesa 13, but I have no such system to verify that on.
https://github.com/mesa3d/mesa/commit/2aa9ff0cda1f6ad97c83d5583fab7a84efabe19e */
"svga3d-texture-upload-slice-by-slice"
};
}

Loading…
Cancel
Save