Browse Source

Pixel storage support, part 8: functions to apply storage state.

Not yet tested/used anywhere.
pull/107/head
Vladimír Vondruš 11 years ago
parent
commit
baa03a7b30
  1. 111
      src/Magnum/PixelStorage.cpp
  2. 51
      src/Magnum/PixelStorage.h

111
src/Magnum/PixelStorage.cpp

@ -27,9 +27,14 @@
#include <Corrade/Utility/Assert.h>
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/Math/Vector4.h"
#include "Implementation/RendererState.h"
#include "Implementation/State.h"
namespace Magnum {
std::size_t PixelStorage::pixelSize(PixelFormat format, PixelType type) {
@ -187,4 +192,110 @@ std::tuple<std::size_t, Math::Vector3<std::size_t>, std::size_t> CompressedPixel
}
#endif
void PixelStorage::applyInternal(const bool isUnpack) {
Implementation::RendererState::PixelStorage& state = isUnpack ?
Context::current()->state().renderer->unpackPixelStorage :
Context::current()->state().renderer->packPixelStorage;
#ifndef MAGNUM_TARGET_GLES
/* Byte swap */
if(state.swapBytes == std::nullopt || state.swapBytes != _swapBytes)
glPixelStorei(isUnpack ? GL_UNPACK_SWAP_BYTES : GL_PACK_SWAP_BYTES,
*(state.swapBytes = _swapBytes));
#endif
/* Alignment */
if(state.alignment == Implementation::RendererState::PixelStorage::DisengagedValue || state.alignment != _alignment)
glPixelStorei(isUnpack ? GL_UNPACK_ALIGNMENT : GL_PACK_ALIGNMENT,
state.alignment = _alignment);
/* Row length */
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
if(state.rowLength == Implementation::RendererState::PixelStorage::DisengagedValue || state.rowLength != _rowLength)
{
/** @todo Use real value for GL_PACK_ROW_LENGTH_NV when it is in headers */
#ifndef MAGNUM_TARGET_GLES2
glPixelStorei(isUnpack ? GL_UNPACK_ROW_LENGTH : GL_PACK_ROW_LENGTH,
state.rowLength = _rowLength);
#elif !defined(MAGNUM_TARGET_WEBGL)
glPixelStorei(isUnpack ? GL_UNPACK_ROW_LENGTH_EXT : 0xD02 /*GL_PACK_ROW_LENGTH_NV*/,
state.rowLength = _rowLength);
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES
/* Image height (on ES for unpack only, taken care of below) */
if(state.imageHeight == Implementation::RendererState::PixelStorage::DisengagedValue || state.imageHeight != _imageHeight)
glPixelStorei(isUnpack ? GL_UNPACK_IMAGE_HEIGHT : GL_PACK_IMAGE_HEIGHT,
state.imageHeight = _imageHeight);
#endif
/* On ES2 done by modifying data pointer */
#ifndef MAGNUM_TARGET_GLES2
/* Skip pixels */
if(state.skip.x() == Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.x() != _skip.x())
glPixelStorei(isUnpack ? GL_UNPACK_SKIP_PIXELS : GL_PACK_SKIP_PIXELS,
state.skip.x() = _skip.x());
/* Skip rows */
if(state.skip.y() == Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.y() != _skip.y())
glPixelStorei(isUnpack ? GL_UNPACK_SKIP_ROWS : GL_PACK_SKIP_ROWS,
state.skip.y() = _skip.y());
#ifndef MAGNUM_TARGET_GLES
/* Skip images (on ES for unpack only, taken care of below) */
if(state.skip.z() == Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.z() != _skip.z())
glPixelStorei(isUnpack ? GL_UNPACK_SKIP_IMAGES : GL_PACK_SKIP_IMAGES,
state.skip.z() = _skip.z());
#endif
#endif
}
void PixelStorage::applyUnpack() {
applyInternal(true);
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2)
Implementation::RendererState::PixelStorage& state = Context::current()->state().renderer->unpackPixelStorage;
/* Image height (on ES for unpack only) */
if(state.imageHeight == Implementation::RendererState::PixelStorage::DisengagedValue || state.imageHeight != _imageHeight)
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, state.imageHeight = _imageHeight);
/* Skip images (on ES for unpack only) */
if(state.skip.z() == Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.z() != _skip.z())
glPixelStorei(GL_UNPACK_SKIP_IMAGES, state.skip.z() = _skip.z());
#endif
}
#ifndef MAGNUM_TARGET_GLES
void CompressedPixelStorage::applyInternal(const bool isUnpack) {
PixelStorage::applyInternal(isUnpack);
Implementation::RendererState::PixelStorage& state = isUnpack ?
Context::current()->state().renderer->unpackPixelStorage :
Context::current()->state().renderer->packPixelStorage;
/* Compressed block width */
if(state.compressedBlockSize.x() == Implementation::RendererState::PixelStorage::DisengagedValue || state.compressedBlockSize.x() != _blockSize.x())
glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_WIDTH : GL_PACK_COMPRESSED_BLOCK_WIDTH,
state.compressedBlockSize.x() = _blockSize.x());
/* Compressed block height */
if(state.compressedBlockSize.y() == Implementation::RendererState::PixelStorage::DisengagedValue || state.compressedBlockSize.y() != _blockSize.y())
glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_HEIGHT : GL_PACK_COMPRESSED_BLOCK_HEIGHT,
state.compressedBlockSize.y() = _blockSize.y());
/* Compressed block depth */
if(state.compressedBlockSize.z() == Implementation::RendererState::PixelStorage::DisengagedValue || state.compressedBlockSize.z() != _blockSize.z())
glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_DEPTH : GL_PACK_COMPRESSED_BLOCK_DEPTH,
state.compressedBlockSize.z() = _blockSize.z());
/* Compressed block size */
if(state.compressedBlockDataSize == Implementation::RendererState::PixelStorage::DisengagedValue || state.compressedBlockDataSize != _blockDataSize)
glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_SIZE : GL_PACK_COMPRESSED_BLOCK_SIZE,
state.compressedBlockDataSize = _blockDataSize);
}
#endif
}

51
src/Magnum/PixelStorage.h

@ -38,6 +38,8 @@
namespace Magnum {
namespace Implementation { struct RendererState; }
/**
@brief Pixel storage parameters
@ -59,6 +61,10 @@ currently used pixel pack/unpack parameters to avoid unnecessary calls to
@see @ref CompressedPixelStorage
*/
class MAGNUM_EXPORT PixelStorage {
friend AbstractFramebuffer;
friend AbstractTexture;
friend CubeMapTexture;
public:
/**
* @brief Pixel size for given format/type combination (in bytes)
@ -211,6 +217,10 @@ class MAGNUM_EXPORT PixelStorage {
#else
private:
#endif
/* Bool parameter is ugly, but this is implementation detail of
internal API so who cares */
void MAGNUM_LOCAL applyInternal(bool isUnpack);
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
Int _rowLength;
#endif
@ -220,6 +230,12 @@ class MAGNUM_EXPORT PixelStorage {
Vector3i _skip;
private:
/* Used internally in *Texture::image(), *Texture::subImage(),
*Texture::setImage(), *Texture::setSubImage() and
*Framebuffer::read() */
void MAGNUM_LOCAL applyUnpack();
void MAGNUM_LOCAL applyPack() { applyInternal(false); }
#ifndef MAGNUM_TARGET_GLES
bool _swapBytes;
#endif
@ -244,6 +260,9 @@ Includes all parameters from @ref PixelStorage, except for @ref swapBytes() and
@requires_gl Compressed pixel storage is hardcoded in OpenGL ES and WebGL.
*/
class MAGNUM_EXPORT CompressedPixelStorage: public PixelStorage {
friend AbstractTexture;
friend CubeMapTexture;
public:
/**
* @brief Default constructor
@ -318,6 +337,15 @@ class MAGNUM_EXPORT CompressedPixelStorage: public PixelStorage {
using PixelStorage::alignment;
using PixelStorage::setAlignment;
/* Bool parameter is ugly, but this is implementation detail of
internal API so who cares */
void MAGNUM_LOCAL applyInternal(bool isUnpack);
/* Used internally in *Texture::compressedImage(), *Texture::compressedSubImage(),
*Texture::setCompressedImage() and *Texture::setCompressedSubImage() */
void MAGNUM_LOCAL applyUnpack() { applyInternal(true); }
void MAGNUM_LOCAL applyPack() { applyInternal(false); }
Vector3i _blockSize;
Int _blockDataSize;
};
@ -383,6 +411,20 @@ namespace Implementation {
}
#endif
/* Use in compressed image upload functions */
#ifndef MAGNUM_TARGET_GLES
template<class T> std::size_t occupiedCompressedImageDataSize(const T& image, std::size_t dataSize) {
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
return dataSize;
return ((Vector3i::pad(image.size(), 1) + image.storage().compressedBlockSize() - Vector3i{1})/image.storage().compressedBlockSize()).product()*image.storage().compressedBlockDataSize();
}
#else
template<class T> std::size_t occupiedCompressedImageDataSize(const T&, std::size_t dataSize) {
return dataSize;
}
#endif
#ifndef MAGNUM_TARGET_GLES
/* Used in image query functions */
template<std::size_t dimensions, class T> std::size_t compressedImageDataSizeFor(const T& image, const Math::Vector<dimensions, Int>& size, std::size_t dataSize) {
@ -399,6 +441,15 @@ namespace Implementation {
return offset + (blockCount.product() - (blockCount.x() - realBlockCount.x()) - (blockCount.y() - realBlockCount.y())*blockCount.x())*blockDataSize;
}
#endif
#ifdef MAGNUM_TARGET_GLES2
template<std::size_t dimensions, class T> std::ptrdiff_t pixelStorageSkipOffsetFor(const T& image, const Math::Vector<dimensions, Int>& size) {
return std::get<0>(image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(size, 1)));
}
template<class T> std::ptrdiff_t pixelStorageSkipOffset(const T& image) {
return pixelStorageSkipOffsetFor(image, image.size());
}
#endif
}
}

Loading…
Cancel
Save