From 274cea19bf9ae0e8e598dde3686c2671b50e1623 Mon Sep 17 00:00:00 2001 From: Laurens Voerman Date: Fri, 13 Oct 2017 16:54:04 +0200 Subject: [PATCH] copySubImage support for block compressed images, added support for astc compressed type. --- include/osg/Image | 39 ++++++ src/osg/Image.cpp | 327 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 319 insertions(+), 47 deletions(-) diff --git a/include/osg/Image b/include/osg/Image index 663761c80..4bf7df74b 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -118,6 +119,38 @@ #define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 #endif +#ifndef GL_KHR_texture_compression_astc_hdr +#define GL_KHR_texture_compression_astc_hdr 1 +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD +#endif /* GL_KHR_texture_compression_astc_hdr */ + #ifndef GL_DEPTH_COMPONENT #define GL_DEPTH_COMPONENT 0x1902 #endif @@ -408,11 +441,17 @@ class OSG_EXPORT Image : public BufferData static bool isPackedType(GLenum type); static GLenum computePixelFormat(GLenum pixelFormat); static GLenum computeFormatDataType(GLenum pixelFormat); + + /** return the dimensions of a block of compressed pixels */ + static osg::Vec3i computeBlockFootprint(GLenum pixelFormat); + + /** return the size in bytes of a block of compressed pixels */ static unsigned int computeBlockSize(GLenum pixelFormat, GLenum packing); static unsigned int computeNumComponents(GLenum pixelFormat); static unsigned int computePixelSizeInBits(GLenum pixelFormat,GLenum type); static unsigned int computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing); static unsigned int computeImageSizeInBytes(int width,int height, int depth, GLenum pixelFormat, GLenum type, int packing = 1, int slice_packing = 1, int image_packing = 1); + static int roudUpToMultiple(int s, int pack); static int computeNearestPowerOfTwo(int s,float bias=0.5f); static int computeNumberOfMipmapLevels(int s,int t = 1, int r = 1); diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index ed8175e46..e755cc65a 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -241,11 +241,17 @@ Image::Image(const Image& image,const CopyOp& copyop): { unsigned int size = image.getTotalSizeInBytesIncludingMipmaps(); setData(new unsigned char [size],USE_NEW_DELETE); - unsigned char* dest_ptr = _data; - for(DataIterator itr(&image); itr.valid(); ++itr) + if (unsigned char* dest_ptr = _data) { - memcpy(dest_ptr, itr.data(), itr.size()); - dest_ptr += itr.size(); + for(DataIterator itr(&image); itr.valid(); ++itr) + { + memcpy(dest_ptr, itr.data(), itr.size()); + dest_ptr += itr.size(); + } + } + else + { + OSG_WARN<<"Warning: Image::Image(const Image&, const CopyOp&) out of memory, no image copy made."<= GL_COMPRESSED_RGB_S3TC_DXT1_EXT && - pixelFormat <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ) - { - width = (width + 3) & ~3; - height = (height + 3) & ~3; - } - - // 3dc ATI formats - // GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB - // GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC - // GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD - // GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE - if( pixelFormat >= GL_COMPRESSED_RED_RGTC1_EXT && - pixelFormat <= GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT ) - { - width = (width + 3) & ~3; - height = (height + 3) & ~3; + int blockSize = computeBlockSize(pixelFormat, 0); + if (blockSize > 0) { + osg::Vec3i footprint = computeBlockFootprint(pixelFormat); + width = (width + footprint.x() - 1) / footprint.x(); + height = (height + footprint.y() - 1) / footprint.y(); + unsigned int size = blockSize * width; + size = roudUpToMultiple(size, packing); + size *= height; + size = roudUpToMultiple(size, slice_packing); + size *= depth; + size = roudUpToMultiple(size, image_packing); + return size; } // compute size of one row @@ -821,6 +984,13 @@ unsigned int Image::computeImageSizeInBytes(int width,int height, int depth, GLe return osg::maximum( size, computeBlockSize(pixelFormat, packing) ); } +int Image::roudUpToMultiple(int s, int pack) { + if (pack < 2) return s; + s += pack - 1; + s -= s % pack; + return s; +} + int Image::computeNearestPowerOfTwo(int s,float bias) { if ((s & (s-1))!=0) @@ -880,6 +1050,34 @@ bool Image::isCompressed() const case(GL_COMPRESSED_SIGNED_R11_EAC): case(GL_COMPRESSED_RG11_EAC): case(GL_COMPRESSED_SIGNED_RG11_EAC): + case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) : return true; default: return false; @@ -1189,7 +1387,7 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps unsigned char* data = new unsigned char[total_size]; if (!data) { - OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, now image read."<s() & 0x3) || (source->t() & 0x3) || (s_offset & 0x3) || (t_offset & 0x3)) + { + OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset<< "," << t_offset << " not multiple of 4." << std::endl; + return; + } + } else { + if ((source->s() % footprint.x()) || (source->t() % footprint.y()) || (s_offset % footprint.x()) || (t_offset% footprint.y())) + { + OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset << "," << t_offset << " not multiple of footprint " << footprint.x() << "x" << footprint.y() << std::endl; + return; + } + } + unsigned int rowWidthInBlocks = (_s + footprint.x() - 1) / footprint.x(); + unsigned int blockSize = computeBlockSize(_pixelFormat, 0); + data_destination = _data + blockSize * (rowWidthInBlocks * t_offset + (s_offset / footprint.x())); + unsigned int copy_width = (osg::minimum(source->s(), _s - s_offset) + footprint.x() - 1) / footprint.x(); + unsigned int copy_height = (osg::minimum(source->t(), _t - t_offset) + footprint.y() - 1) / footprint.y(); + unsigned int dstRowStep = blockSize * rowWidthInBlocks; + unsigned int srcRowStep = blockSize * (source->_s + footprint.x() - 1) / footprint.x(); + const unsigned char* data_source = source->data(0, 0, 0); + for (unsigned int row = 0; row < copy_height; row += 1) { //copy blocks in a row, footprint.y() rows at a time + memcpy(data_destination, data_source, copy_width * blockSize); + data_source += srcRowStep; + data_destination += dstRowStep; + } + return; + } PixelStorageModes psm; psm.pack_alignment = _packing; psm.pack_row_length = _rowLength!=0 ? _rowLength : _s; @@ -1919,24 +2147,29 @@ Vec4 _readColor(GLenum pixelFormat, T* data,float scale) Vec4 Image::getColor(unsigned int s,unsigned t,unsigned r) const { - if (dxtc_tool::isDXTC(_pixelFormat)) { - unsigned char color[4]; - if (dxtc_tool::CompressedImageGetColor(color, s, t, r, _s, _t, _r, _pixelFormat, _data)) { - return Vec4(((float)color[0]) / 255.0f, ((float)color[1]) / 255.0f, ((float)color[2]) / 255.0f, ((float)color[3]) / 255.0f ); + if (isCompressed(_pixelFormat)) + { + if (dxtc_tool::isDXTC(_pixelFormat)) { + unsigned char color[4]; + if (dxtc_tool::CompressedImageGetColor(color, s, t, r, _s, _t, _r, _pixelFormat, _data)) { + return Vec4(((float)color[0]) / 255.0f, ((float)color[1]) / 255.0f, ((float)color[2]) / 255.0f, ((float)color[3]) / 255.0f ); + } } } - const unsigned char* ptr = data(s,t,r); - - switch(_dataType) + else { - case(GL_BYTE): return _readColor(_pixelFormat, (char*)ptr, 1.0f/128.0f); - case(GL_UNSIGNED_BYTE): return _readColor(_pixelFormat, (unsigned char*)ptr, 1.0f/255.0f); - case(GL_SHORT): return _readColor(_pixelFormat, (short*)ptr, 1.0f/32768.0f); - case(GL_UNSIGNED_SHORT): return _readColor(_pixelFormat, (unsigned short*)ptr, 1.0f/65535.0f); - case(GL_INT): return _readColor(_pixelFormat, (int*)ptr, 1.0f/2147483648.0f); - case(GL_UNSIGNED_INT): return _readColor(_pixelFormat, (unsigned int*)ptr, 1.0f/4294967295.0f); - case(GL_FLOAT): return _readColor(_pixelFormat, (float*)ptr, 1.0f); - case(GL_DOUBLE): return _readColor(_pixelFormat, (double*)ptr, 1.0f); + const unsigned char* ptr = data(s,t,r); + switch(_dataType) + { + case(GL_BYTE): return _readColor(_pixelFormat, (char*)ptr, 1.0f/128.0f); + case(GL_UNSIGNED_BYTE): return _readColor(_pixelFormat, (unsigned char*)ptr, 1.0f/255.0f); + case(GL_SHORT): return _readColor(_pixelFormat, (short*)ptr, 1.0f/32768.0f); + case(GL_UNSIGNED_SHORT): return _readColor(_pixelFormat, (unsigned short*)ptr, 1.0f/65535.0f); + case(GL_INT): return _readColor(_pixelFormat, (int*)ptr, 1.0f/2147483648.0f); + case(GL_UNSIGNED_INT): return _readColor(_pixelFormat, (unsigned int*)ptr, 1.0f/4294967295.0f); + case(GL_FLOAT): return _readColor(_pixelFormat, (float*)ptr, 1.0f); + case(GL_DOUBLE): return _readColor(_pixelFormat, (double*)ptr, 1.0f); + } } return Vec4(1.0f,1.0f,1.0f,1.0f); }