From 12e6a23451fa4ba4a02e39ad2e81a21843bb2418 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 7 Oct 2010 10:51:22 +0000 Subject: [PATCH] Introduced new gluScaleImage function that uses a PixelStorageModes structure to pass in details on image packing, rather than relying upon glGet's to get the values. --- examples/osgphotoalbum/PhotoArchive.cpp | 59 ++-------- include/osg/GLU | 44 +++++++- include/osg/Image | 8 +- src/osg/Image.cpp | 17 +-- src/osg/Texture.cpp | 21 ++-- src/osg/glu/libutil/mipmap.cpp | 137 +++++++++++++----------- 6 files changed, 152 insertions(+), 134 deletions(-) diff --git a/examples/osgphotoalbum/PhotoArchive.cpp b/examples/osgphotoalbum/PhotoArchive.cpp index 2734c403e..a7f94b69e 100644 --- a/examples/osgphotoalbum/PhotoArchive.cpp +++ b/examples/osgphotoalbum/PhotoArchive.cpp @@ -30,46 +30,6 @@ const std::string FILE_IDENTIFER("osgphotoalbum photo archive"); -class MyGraphicsContext { - public: - MyGraphicsContext() - { - osg::ref_ptr traits = new osg::GraphicsContext::Traits; - traits->x = 0; - traits->y = 0; - traits->width = 1; - traits->height = 1; - traits->windowDecoration = false; - traits->doubleBuffer = false; - traits->sharedContext = 0; - traits->pbuffer = true; - - _gc = osg::GraphicsContext::createGraphicsContext(traits.get()); - - if (!_gc) - { - osg::notify(osg::NOTICE)<<"Failed to create pbuffer, failing back to normal graphics window."<pbuffer = false; - _gc = osg::GraphicsContext::createGraphicsContext(traits.get()); - } - - if (_gc.valid()) - - - { - _gc->realize(); - _gc->makeCurrent(); - std::cout<<"Realized window"<isRealized(); } - - private: - osg::ref_ptr _gc; -}; - PhotoArchive::PhotoArchive(const std::string& filename) { readPhotoIndex(filename); @@ -206,10 +166,7 @@ void PhotoArchive::buildArchive(const std::string& filename, const FileNameList& std::cout<<"Building photo archive containing "<getPacking()); - glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking()); + PixelStorageModes psm; + psm.pack_alignment = image->getPacking(); + psm.unpack_alignment = image->getPacking(); - GLint status = gluScaleImage(image->getPixelFormat(), + GLint status = gluScaleImage(&psm, image->getPixelFormat(), image->s(), image->t(), image->getDataType(), @@ -324,10 +282,11 @@ void PhotoArchive::buildArchive(const std::string& filename, const FileNameList& return; } - glPixelStorei(GL_PACK_ALIGNMENT,image->getPacking()); - glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking()); + PixelStorageModes psm; + psm.pack_alignment = image->getPacking(); + psm.unpack_alignment = image->getPacking(); - GLint status = gluScaleImage(image->getPixelFormat(), + GLint status = gluScaleImage(&psm, image->getPixelFormat(), image->s(), image->t(), image->getDataType(), diff --git a/include/osg/GLU b/include/osg/GLU index 8a16f6b9e..8432c963b 100644 --- a/include/osg/GLU +++ b/include/osg/GLU @@ -16,8 +16,50 @@ #include -extern OSG_EXPORT GLint gluScaleImage (GLenum format, GLsizei wIn, GLsizei hIn, GLenum typeIn, const void *dataIn, GLsizei wOut, GLsizei hOut, GLenum typeOut, GLvoid* dataOut); +/* Pixel storage modes, used by gluScaleImage */ +struct OSG_EXPORT PixelStorageModes +{ + // sets defaults as per glGet docs in OpenGL red book + PixelStorageModes(); + + // use glGet's to retrieve all the current settings + void retrieveStoreModes(); + + // use glGet's to retrieve all the current 3D settings + void retrieveStoreModes3D(); + + GLint pack_alignment; + GLint pack_row_length; + GLint pack_skip_rows; + GLint pack_skip_pixels; + GLint pack_lsb_first; + GLint pack_swap_bytes; + GLint pack_skip_images; + GLint pack_image_height; + + GLint unpack_alignment; + GLint unpack_row_length; + GLint unpack_skip_rows; + GLint unpack_skip_pixels; + GLint unpack_lsb_first; + GLint unpack_swap_bytes; + GLint unpack_skip_images; + GLint unpack_image_height; +} ; + extern OSG_EXPORT const GLubyte * gluErrorString (GLenum error); + +/** OSG specific gluScaleImage function that allows you to pass in the PixelStoreModes, which + * enables the code to avoid glGet's that are associated with the conventional gluScaleImage function. + * Avoiding glGet's allows this gluScaleImage function to be called at any time, from any thread, there + * is no need to have a graphics context current.*/ +extern OSG_EXPORT GLint gluScaleImage (PixelStorageModes* psm, GLenum format, GLsizei wIn, GLsizei hIn, GLenum typeIn, const void *dataIn, GLsizei wOut, GLsizei hOut, GLenum typeOut, GLvoid* dataOut); + +/** Traditional GLU gluScaleImage function that sets up the PixelStoreModes automatically by doing glGets.; + * The use of glGet's means that you can only call this function from a thread with a valid graphics context. + * The use of glGet's will also result in lower performance due to the round trip to the OpenGL driver.*/ +extern OSG_EXPORT GLint gluScaleImage (GLenum format, GLsizei wIn, GLsizei hIn, GLenum typeIn, const void *dataIn, GLsizei wOut, GLsizei hOut, GLenum typeOut, GLvoid* dataOut); + extern OSG_EXPORT GLint gluBuild1DMipmapLevels (GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, GLint level, GLint base, GLint max, const void *data); extern OSG_EXPORT GLint gluBuild1DMipmaps (GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, const void *data); extern OSG_EXPORT GLint gluBuild2DMipmapLevels (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint level, GLint base, GLint max, const void *data); diff --git a/include/osg/Image b/include/osg/Image index 0af83f535..150ba9292 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -172,14 +172,10 @@ class OSG_EXPORT Image : public BufferData virtual void readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable, GLenum type = GL_UNSIGNED_BYTE); - /** Scale image to specified size. - * \warning The method uses gluScaleImage() and thus needs a valid rendering context. - */ + /** Scale image to specified size. */ void scaleImage(int s,int t,int r) { scaleImage(s,t,r, getDataType()); } - /** Scale image to specified size and with specified data type. - * \warning The method uses gluScaleImage() and thus needs a valid rendering context. - */ + /** Scale image to specified size and with specified data type. */ virtual void scaleImage(int s,int t,int r, GLenum newDataType); /** Copy a source Image into a subpart of this Image at specified position. diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index 80df12860..796be4126 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -936,10 +936,11 @@ void Image::scaleImage(int s,int t,int r, GLenum newDataType) return; } - glPixelStorei(GL_PACK_ALIGNMENT,_packing); - glPixelStorei(GL_UNPACK_ALIGNMENT,_packing); + PixelStorageModes psm; + psm.pack_alignment = _packing; + psm.unpack_alignment = _packing; - GLint status = gluScaleImage(_pixelFormat, + GLint status = gluScaleImage(&psm, _pixelFormat, _s, _t, _dataType, @@ -1000,12 +1001,12 @@ void Image::copySubImage(int s_offset, int t_offset, int r_offset, const osg::Im void* data_destination = data(s_offset,t_offset,r_offset); - glPixelStorei(GL_PACK_ALIGNMENT,source->getPacking()); - glPixelStorei(GL_PACK_ROW_LENGTH,_s); + PixelStorageModes psm; + psm.pack_alignment = _packing; + psm.pack_row_length = _packing; + psm.unpack_alignment = _packing; - glPixelStorei(GL_UNPACK_ALIGNMENT,_packing); - - GLint status = gluScaleImage(_pixelFormat, + GLint status = gluScaleImage(&psm, _pixelFormat, source->s(), source->t(), source->getDataType(), diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index e863b51c2..9630faf74 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -1651,12 +1651,16 @@ void Texture::applyTexImage2D_load(State& state, GLenum target, const Image* ima if (!image->getFileName().empty()) { OSG_NOTICE << "Scaling image '"<getFileName()<<"' from ("<s()<<","<t()<<") to ("<s()<<","<t()<<") to ("<getPacking(); + psm.unpack_alignment = image->getPacking(); + // rescale the image to the correct size. - glPixelStorei(GL_PACK_ALIGNMENT,image->getPacking()); - gluScaleImage(image->getPixelFormat(), - image->s(),image->t(),image->getDataType(),image->data(), - inwidth,inheight,image->getDataType(), - dataPtr); + gluScaleImage(&psm, image->getPixelFormat(), + image->s(),image->t(),image->getDataType(),image->data(), + inwidth,inheight,image->getDataType(), + dataPtr); + } bool mipmappingRequired = _min_filter != LINEAR && _min_filter != NEAREST; @@ -1890,8 +1894,11 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image* else { OSG_NOTICE << "Scaling image from ("<s()<<","<t()<<") to ("<getPacking()); - gluScaleImage(image->getPixelFormat(), + PixelStorageModes psm; + psm.pack_alignment = image->getPacking(); + psm.unpack_alignment = image->getPacking(); + + gluScaleImage(&psm, image->getPixelFormat(), image->s(),image->t(),image->getDataType(),image->data(), inwidth,inheight,image->getDataType(), dataPtr); diff --git a/src/osg/glu/libutil/mipmap.cpp b/src/osg/glu/libutil/mipmap.cpp index 2b9ff9399..8632c63b9 100644 --- a/src/osg/glu/libutil/mipmap.cpp +++ b/src/osg/glu/libutil/mipmap.cpp @@ -48,6 +48,7 @@ #include #include /* UINT_MAX */ #include +#include typedef union { unsigned char ub[4]; @@ -59,27 +60,6 @@ typedef union { float f; } Type_Widget; -/* Pixel storage modes */ -typedef struct { - GLint pack_alignment; - GLint pack_row_length; - GLint pack_skip_rows; - GLint pack_skip_pixels; - GLint pack_lsb_first; - GLint pack_swap_bytes; - GLint pack_skip_images; - GLint pack_image_height; - - GLint unpack_alignment; - GLint unpack_row_length; - GLint unpack_skip_rows; - GLint unpack_skip_pixels; - GLint unpack_lsb_first; - GLint unpack_swap_bytes; - GLint unpack_skip_images; - GLint unpack_image_height; -} PixelStorageModes; - static int gluBuild1DMipmapLevelsCore(GLenum, GLint, GLsizei, GLsizei, @@ -258,42 +238,64 @@ static void emptyImage3D(const PixelStorageModes *, static void scaleInternal3D(GLint, GLint, GLint, GLint, const GLushort *, GLint, GLint, GLint, GLushort *); -static void retrieveStoreModes(PixelStorageModes *psm) +PixelStorageModes::PixelStorageModes() { - glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment); - glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length); - glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows); - glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels); - glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first); - glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes); + // Default Settings set from values specified in glGet docs in the OpenGL red book. + pack_alignment = 4; + pack_row_length = 0; + pack_skip_rows = 0; + pack_skip_pixels = 0; + pack_lsb_first = GL_FALSE; + pack_swap_bytes = GL_FALSE; + pack_skip_images = 0; + pack_image_height = 0; - glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment); - glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length); - glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows); - glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels); - glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first); - glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes); + unpack_alignment = 4; + unpack_row_length = 0; + unpack_skip_rows = 0; + unpack_skip_pixels = 0; + unpack_lsb_first = GL_FALSE; + unpack_swap_bytes = GL_FALSE; + unpack_skip_images = 0; + unpack_image_height = 0; } -static void retrieveStoreModes3D(PixelStorageModes *psm) +void PixelStorageModes::retrieveStoreModes() { - glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment); - glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length); - glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows); - glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels); - glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first); - glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes); - glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &psm->unpack_skip_images); - glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &psm->unpack_image_height); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpack_skip_rows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpack_skip_pixels); + glGetIntegerv(GL_UNPACK_LSB_FIRST, &unpack_lsb_first); + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &unpack_swap_bytes); - glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment); - glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length); - glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows); - glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels); - glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first); - glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes); - glGetIntegerv(GL_PACK_SKIP_IMAGES, &psm->pack_skip_images); - glGetIntegerv(GL_PACK_IMAGE_HEIGHT, &psm->pack_image_height); + glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment); + glGetIntegerv(GL_PACK_ROW_LENGTH, &pack_row_length); + glGetIntegerv(GL_PACK_SKIP_ROWS, &pack_skip_rows); + glGetIntegerv(GL_PACK_SKIP_PIXELS, &pack_skip_pixels); + glGetIntegerv(GL_PACK_LSB_FIRST, &pack_lsb_first); + glGetIntegerv(GL_PACK_SWAP_BYTES, &pack_swap_bytes); +} + +void PixelStorageModes::retrieveStoreModes3D() +{ + glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpack_skip_rows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpack_skip_pixels); + glGetIntegerv(GL_UNPACK_LSB_FIRST, &unpack_lsb_first); + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &unpack_swap_bytes); + glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &unpack_skip_images); + glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &unpack_image_height); + + glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment); + glGetIntegerv(GL_PACK_ROW_LENGTH, &pack_row_length); + glGetIntegerv(GL_PACK_SKIP_ROWS, &pack_skip_rows); + glGetIntegerv(GL_PACK_SKIP_PIXELS, &pack_skip_pixels); + glGetIntegerv(GL_PACK_LSB_FIRST, &pack_lsb_first); + glGetIntegerv(GL_PACK_SWAP_BYTES, &pack_swap_bytes); + glGetIntegerv(GL_PACK_SKIP_IMAGES, &pack_skip_images); + glGetIntegerv(GL_PACK_IMAGE_HEIGHT, &pack_image_height); } static int computeLog(GLuint value) @@ -3507,7 +3509,7 @@ noProxyTextures: } /* closestFit() */ GLint GLAPIENTRY -gluScaleImage(GLenum format, GLsizei widthin, GLsizei heightin, +gluScaleImage(PixelStorageModes* psm, GLenum format, GLsizei widthin, GLsizei heightin, GLenum typein, const void *datain, GLsizei widthout, GLsizei heightout, GLenum typeout, void *dataout) @@ -3515,8 +3517,6 @@ gluScaleImage(GLenum format, GLsizei widthin, GLsizei heightin, int components; GLushort *beforeImage; GLushort *afterImage; - PixelStorageModes psm; - if (widthin == 0 || heightin == 0 || widthout == 0 || heightout == 0) { return 0; } @@ -3542,13 +3542,12 @@ gluScaleImage(GLenum format, GLsizei widthin, GLsizei heightin, return GLU_OUT_OF_MEMORY; } - retrieveStoreModes(&psm); - fill_image(&psm,widthin, heightin, format, typein, is_index(format), + fill_image(psm,widthin, heightin, format, typein, is_index(format), datain, beforeImage); components = elements_per_group(format, 0); scale_internal(components, widthin, heightin, beforeImage, widthout, heightout, afterImage); - empty_image(&psm,widthout, heightout, format, typeout, + empty_image(psm,widthout, heightout, format, typeout, is_index(format), afterImage, dataout); free((GLbyte *) beforeImage); free((GLbyte *) afterImage); @@ -3556,6 +3555,20 @@ gluScaleImage(GLenum format, GLsizei widthin, GLsizei heightin, return 0; } +GLint GLAPIENTRY +gluScaleImage(GLenum format, GLsizei widthin, GLsizei heightin, + GLenum typein, const void *datain, + GLsizei widthout, GLsizei heightout, GLenum typeout, + void *dataout) +{ + PixelStorageModes psm; + psm.retrieveStoreModes(); + return gluScaleImage(&psm, format, widthin, heightin, + typein, datain, + widthout, heightout, typeout, + dataout); +} + int gluBuild1DMipmapLevelsCore(GLenum target, GLint internalFormat, GLsizei width, GLsizei widthPowerOf2, @@ -3583,7 +3596,7 @@ int gluBuild1DMipmapLevelsCore(GLenum target, GLint internalFormat, levels+= userLevel; - retrieveStoreModes(&psm); + psm.retrieveStoreModes(); newImage = (GLushort *) malloc(image_size(width, 1, format, GL_UNSIGNED_SHORT)); newImage_width = width; @@ -3720,7 +3733,7 @@ static int bitmapBuild2DMipmaps(GLenum target, GLint internalFormat, GLint cmpts; PixelStorageModes psm; - retrieveStoreModes(&psm); + psm.retrieveStoreModes(); #if 0 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize); @@ -3850,7 +3863,7 @@ static int gluBuild2DMipmapLevelsCore(GLenum target, GLint internalFormat, levels+= userLevel; - retrieveStoreModes(&psm); + psm.retrieveStoreModes(); myswap_bytes = psm.unpack_swap_bytes; cmpts = elements_per_group(format,type); if (psm.unpack_row_length > 0) { @@ -7410,7 +7423,7 @@ int gluScaleImage3D(GLenum format, free(afterImage); return GLU_OUT_OF_MEMORY; } - retrieveStoreModes3D(&psm); + psm.retrieveStoreModes3D(); fillImage3D(&psm,widthIn,heightIn,depthIn,format,typeIn, is_index(format), dataIn, beforeImage); @@ -7778,7 +7791,7 @@ static int gluBuild3DMipmapLevelsCore(GLenum target, GLint internalFormat, levels+= userLevel; - retrieveStoreModes3D(&psm); + psm.retrieveStoreModes3D(); myswapBytes = psm.unpack_swap_bytes; cmpts = elements_per_group(format,type); if (psm.unpack_row_length > 0) {