Browse Source

Ability to retrieve texture images.

pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
05531ad20b
  1. 69
      src/AbstractTexture.cpp
  2. 21
      src/AbstractTexture.h
  3. 30
      src/CubeMapTexture.h
  4. 30
      src/CubeMapTextureArray.h
  5. 41
      src/Texture.h

69
src/AbstractTexture.cpp

@ -28,6 +28,7 @@
#include "BufferImage.h"
#include "Context.h"
#include "Extensions.h"
#include "Image.h"
#include "Implementation/State.h"
#include "Implementation/TextureState.h"
@ -56,6 +57,8 @@ AbstractTexture::Storage2DImplementation AbstractTexture::storage2DImplementatio
AbstractTexture::Storage3DImplementation AbstractTexture::storage3DImplementation =
&AbstractTexture::storageImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::GetImageImplementation AbstractTexture::getImageImplementation =
&AbstractTexture::getImageImplementationDefault;
AbstractTexture::Image1DImplementation AbstractTexture::image1DImplementation =
&AbstractTexture::imageImplementationDefault;
#endif
@ -233,6 +236,7 @@ void AbstractTexture::initializeContextBasedFunctionality(Context* context) {
storage1DImplementation = &AbstractTexture::storageImplementationDSA;
storage2DImplementation = &AbstractTexture::storageImplementationDSA;
storage3DImplementation = &AbstractTexture::storageImplementationDSA;
getImageImplementation = &AbstractTexture::getImageImplementationDSA;
image1DImplementation = &AbstractTexture::imageImplementationDSA;
image2DImplementation = &AbstractTexture::imageImplementationDSA;
image3DImplementation = &AbstractTexture::imageImplementationDSA;
@ -247,6 +251,13 @@ void AbstractTexture::initializeContextBasedFunctionality(Context* context) {
invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationARB;
invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationARB;
}
if(context->isExtensionSupported<Extensions::GL::ARB::robustness>() &&
!context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::ARB::robustness::string() << "features";
getImageImplementation = &AbstractTexture::getImageImplementationRobustness;
}
#endif
}
@ -352,7 +363,35 @@ void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels
void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, AbstractTexture::InternalFormat internalFormat, const Vector3i& size) {
glTextureStorage3DEXT(_id, target, levels, GLenum(internalFormat), size.x(), size.y(), size.z());
}
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::getImageImplementationDefault(const GLenum target, const GLint level, const AbstractImage::Format format, const AbstractImage::Type type, const std::size_t, GLvoid* const data) {
bindInternal();
glGetTexImage(target, level, GLenum(format), GLenum(type), data);
}
void AbstractTexture::getImageImplementationDSA(const GLenum target, const GLint level, const AbstractImage::Format format, const AbstractImage::Type type, const std::size_t, GLvoid* const data) {
glGetTextureImageEXT(_id, target, level, GLenum(format), GLenum(type), data);
}
void AbstractTexture::getImageImplementationRobustness(const GLenum target, const GLint level, const AbstractImage::Format format, const AbstractImage::Type type, const std::size_t dataSize, GLvoid* const data) {
#ifndef MAGNUM_TARGET_GLES
bindInternal();
glGetnTexImageARB(target, level, GLenum(format), GLenum(type), dataSize, data);
#else
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(target);
static_cast<void>(level);
static_cast<void>(format);
static_cast<void>(type);
static_cast<void>(dataSize);
static_cast<void>(data);
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, InternalFormat internalFormat, const Math::Vector<1, GLsizei>& size, AbstractImage::Format format, AbstractImage::Type type, const GLvoid* data) {
bindInternal();
glTexImage1D(target, level, static_cast<GLint>(internalFormat), size[0], 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data);
@ -456,6 +495,36 @@ void AbstractTexture::invalidateSubImageImplementationARB(GLint level, const Vec
}
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt dimensions> void AbstractTexture::image(GLenum target, GLint level, Image<dimensions>* image) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(this, target, level);
const std::size_t dataSize = size.product()*image->pixelSize();
char* data = new char[dataSize];
(this->*getImageImplementation)(target, level, image->format(), image->type(), dataSize, data);
image->setData(size, image->format(), image->type(), data);
}
template void AbstractTexture::image<1>(GLenum, GLint, Image<1>*);
template void AbstractTexture::image<2>(GLenum, GLint, Image<2>*);
template void AbstractTexture::image<3>(GLenum, GLint, Image<3>*);
template<UnsignedInt dimensions> void AbstractTexture::image(GLenum target, GLint level, BufferImage<dimensions>* image, Buffer::Usage usage) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(this, target, level);
const std::size_t dataSize = size.product()*image->pixelSize();
if(image->size() != size)
image->setData(size, image->format(), image->type(), nullptr, usage);
image->buffer()->bind(Buffer::Target::PixelPack);
(this->*getImageImplementation)(target, level, image->format(), image->type(), dataSize, nullptr);
}
template void AbstractTexture::image<1>(GLenum, GLint, BufferImage<1>*, Buffer::Usage);
template void AbstractTexture::image<2>(GLenum, GLint, BufferImage<2>*, Buffer::Usage);
template void AbstractTexture::image<3>(GLenum, GLint, BufferImage<3>*, Buffer::Usage);
#endif
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_TARGET_GLES2
namespace Implementation {

21
src/AbstractTexture.h

@ -43,7 +43,7 @@ namespace Magnum {
See Texture, CubeMapTexture and CubeMapTextureArray documentation for more
information and usage examples.
@section AbstractTexture-performance-optimization Performance optimizations
@section AbstractTexture-performance-optimization Performance optimizations and security
The engine tracks currently bound textures in all available layers to avoid
unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. %Texture
@ -58,6 +58,12 @@ configuration and data updating functions use DSA functions to avoid
unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. See
respective function documentation for more information.
If extension @extension{ARB,robustness} is available, image reading operations
(such as Texture::image()) are protected from buffer overflow. However, if both
@extension{EXT,direct_state_access} and @extension{ARB,robustness} are
available, the DSA version is used, because it is better for performance and
there isn't any function combining both features.
To achieve least state changes, fully configure each texture in one run --
method chaining comes in handy -- and try to have often used textures in
dedicated layers, not occupied by other textures. First configure the texture
@ -1168,6 +1174,11 @@ class MAGNUM_EXPORT AbstractTexture {
/* Unlike bind() this also sets the binding layer as active */
void MAGNUM_LOCAL bindInternal();
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt dimensions> void MAGNUM_LOCAL image(GLenum target, GLint level, Image<dimensions>* image);
template<UnsignedInt dimensions> void MAGNUM_LOCAL image(GLenum target, GLint level, BufferImage<dimensions>* image, Buffer::Usage usage);
#endif
GLenum _target;
private:
@ -1236,6 +1247,14 @@ class MAGNUM_EXPORT AbstractTexture {
#endif
static Storage3DImplementation storage3DImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*GetImageImplementation)(GLenum, GLint, AbstractImage::Format, AbstractImage::Type, std::size_t, GLvoid*);
void MAGNUM_LOCAL getImageImplementationDefault(GLenum target, GLint level, AbstractImage::Format format, AbstractImage::Type type, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationDSA(GLenum target, GLint level, AbstractImage::Format format, AbstractImage::Type type, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationRobustness(GLenum target, GLint level, AbstractImage::Format format, AbstractImage::Type type, std::size_t dataSize, GLvoid* data);
static MAGNUM_LOCAL GetImageImplementation getImageImplementation;
#endif
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*Image1DImplementation)(GLenum, GLint, InternalFormat, const Math::Vector<1, GLsizei>&, AbstractImage::Format, AbstractImage::Type, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, InternalFormat internalFormat, const Math::Vector<1, GLsizei>& size, AbstractImage::Format format, AbstractImage::Type type, const GLvoid* data);

30
src/CubeMapTexture.h

@ -129,6 +129,36 @@ class CubeMapTexture: public AbstractTexture {
return this;
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Read given mip level of texture to image
* @param coordinate Coordinate
* @param level Mip level
* @param image %Image where to put the data
*
* See Texture::image(Int, Image*) for more information.
* @requires_gl %Texture image queries are not available in OpenGL ES.
*/
inline void image(Coordinate coordinate, Int level, Image2D* image) {
AbstractTexture::image<2>(GLenum(coordinate), level, image);
}
/**
* @brief Read given mip level of texture to buffer image
* @param coordinate Coordinate
* @param level Mip level
* @param image %Buffer image where to put the data
* @param usage %Buffer usage
*
* See Texture::image(Int, BufferImage*, Buffer::Usage) for more
* information.
* @requires_gl %Texture image queries are not available in OpenGL ES.
*/
inline void image(Coordinate coordinate, Int level, BufferImage2D* image, Buffer::Usage usage) {
AbstractTexture::image<2>(GLenum(coordinate), level, image, usage);
}
#endif
/**
* @brief Set image data
* @param coordinate Coordinate

30
src/CubeMapTextureArray.h

@ -129,6 +129,36 @@ class CubeMapTextureArray: public AbstractTexture {
return this;
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Read given mip level of texture to image
* @param coordinate Coordinate
* @param level Mip level
* @param image %Image where to put the data
*
* See Texture::image(Int, Image*) for more information.
* @requires_gl %Texture image queries are not available in OpenGL ES.
*/
inline void image(Coordinate coordinate, Int level, Image3D* image) {
AbstractTexture::image<3>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + GLenum(coordinate), level, image);
}
/**
* @brief Read given mip level of texture to buffer image
* @param coordinate Coordinate
* @param level Mip level
* @param image %Buffer image where to put the data
* @param usage %Buffer usage
*
* See Texture::image(Int, BufferImage*, Buffer::Usage) for more
* information.
* @requires_gl %Texture image queries are not available in OpenGL ES.
*/
inline void image(Coordinate coordinate, Int level, BufferImage3D* image, Buffer::Usage usage) {
AbstractTexture::image<3>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + GLenum(coordinate), level, image, usage);
}
#endif
/**
* @brief Set image data
* @param level Mip level

41
src/Texture.h

@ -250,6 +250,47 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
return this;
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Read given mip level of texture to image
* @param level Mip level
* @param image %Image where to put the data
*
* %Image parameters like format and type of pixel data are taken from
* given image, image size is taken from the texture using imageSize().
*
* If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some layer before the operation. If
* @extension{ARB,robustness} is available, the operation is protected
* from buffer overflow. However, if both @extension{EXT,direct_state_access}
* and @extension{ARB,robustness} are available, the DSA version is
* used, because it is better for performance and there isn't any
* function combining both features.
* @requires_gl %Texture image queries are not available in OpenGL ES.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or @def_gl{TEXTURE_DEPTH},
* then @fn_gl{GetTexImage}, @fn_gl_extension{GetTextureImage,EXT,direct_state_access}
* or @fn_gl_extension{GetnTexImage,ARB,robustness}
*/
inline void image(Int level, Image<dimensions>* image) {
AbstractTexture::image<dimensions>(_target, level, image);
}
/**
* @brief Read given mip level of texture to buffer image
* @param level Mip level
* @param image %Buffer image where to put the data
* @param usage %Buffer usage
*
* See image(Int, Image*) for more information.
* @requires_gl %Texture image queries are not available in OpenGL ES.
*/
inline void image(Int level, BufferImage<dimensions>* image, Buffer::Usage usage) {
AbstractTexture::image<dimensions>(_target, level, image, usage);
}
#endif
/**
* @brief Set image data
* @param level Mip level

Loading…
Cancel
Save