Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #ifndef CameraReadPixels_INCLUDE_ONCE 00033 #define CameraReadPixels_INCLUDE_ONCE 00034 00035 #include <vlGraphics/Camera.hpp> 00036 #include <vlCore/Say.hpp> 00037 #include <vlCore/Log.hpp> 00038 #include <vlGraphics/RenderEventCallback.hpp> 00039 #include <vlGraphics/BufferObject.hpp> 00040 #include <vlCore/Image.hpp> 00041 00042 namespace vl 00043 { 00044 //----------------------------------------------------------------------------- 00045 // vl::readPixels() 00046 //----------------------------------------------------------------------------- 00054 inline void readPixels(Image* image, int x, int y, int w, int h, EReadDrawBuffer read_buffer, bool store_in_pixel_buffer_object) 00055 { 00056 // clears OpenGL errors 00057 glGetError(); 00058 00059 #if defined(VL_OPENGL) 00060 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 00061 #endif 00062 00063 glPixelStorei( GL_PACK_ALIGNMENT, 1); 00064 #if defined(VL_OPENGL) 00065 glPixelStorei( GL_PACK_ROW_LENGTH, w); 00066 glPixelStorei( GL_PACK_SKIP_PIXELS, 0); 00067 glPixelStorei( GL_PACK_SKIP_ROWS, 0); 00068 glPixelStorei( GL_PACK_SWAP_BYTES, 0); 00069 glPixelStorei( GL_PACK_LSB_FIRST, 0); 00070 if (Has_GL_Version_1_2||Has_GL_Version_3_0||Has_GL_Version_4_0) // Texture 3D but excluding EOS 00071 { 00072 glPixelStorei( GL_PACK_IMAGE_HEIGHT, 0 ); 00073 glPixelStorei( GL_PACK_SKIP_IMAGES, 0 ); 00074 } 00075 00076 int prev = 0; 00077 glGetIntegerv( GL_READ_BUFFER, &prev ); VL_CHECK_OGL() 00078 glReadBuffer( read_buffer ); 00079 #endif 00080 00081 #ifndef NDEBUG 00082 if (glGetError() != GL_NO_ERROR) 00083 { 00084 Log::print(Say("Image::readPixels() error: %s:%n\n" 00085 "You seem to have specified a wrong read buffer for the bound render target,\n" 00086 "for example you might have specified a RDB_BACK_LEFT but the active camera\n" 00087 "is bound to a FBO (Framebuffer Object) render target or the selected\n" 00088 "read buffer is FBO-specific (like RDB_COLOR_ATTACHMENT0_EXT) but the active\n" 00089 "camera is not bound to a FBO render target. \n") << __FILE__ << __LINE__ 00090 ); 00091 VL_TRAP() 00092 } 00093 #endif 00094 00095 bool supports_pbo = Has_GL_ARB_pixel_buffer_object||Has_GL_EXT_pixel_buffer_object||Has_GL_Version_2_1; 00096 00097 if (store_in_pixel_buffer_object && supports_pbo) 00098 { 00099 // mic fixme: test 00100 BufferObject* glbuf = cast<BufferObject>(image->imageBuffer()); VL_CHECK(glbuf); 00101 00102 int bytes = image->requiredMemory2D(w, h, 1, image->format(), image->type()); 00103 // allocates the PBO 00104 glbuf->setBufferData( bytes, NULL, glbuf->usage() ); 00105 // bind the pbo 00106 VL_glBindBuffer( GL_PIXEL_PACK_BUFFER, glbuf->handle() ); 00107 // read pixels into the pbo 00108 glReadPixels( x, y, w, h, image->format(), image->type(), 0); 00109 // unbind the pbo 00110 VL_glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 ); 00111 00112 // deallocates the local storage and sets up the image configuration 00113 image->reset(w, h, 0, 1, image->format(), image->type(), false); 00114 00115 // test GPU -> local copy 00116 //if (w != image->width() || h != image->height() || image->dimension() != ID_2D || image->pixels() == NULL) 00117 // image->allocate2D( w, h, 1, image->format(), image->type() ); 00118 //glbuf->downloadBufferObject(); 00119 } 00120 else 00121 { 00122 if (w != image->width() || h != image->height() || image->dimension() != ID_2D || image->pixels() == NULL) 00123 image->allocate2D( w, h, 1, image->format(), image->type() ); 00124 glReadPixels( x, y, w, h, image->format(), image->type(), image->pixels() ); 00125 } 00126 00127 #if defined(VL_OPENGL) 00128 // restore read buffer 00129 glReadBuffer( prev ); 00130 00131 glPopClientAttrib(); 00132 #endif 00133 00134 VL_CHECK_OGL() 00135 } 00136 //----------------------------------------------------------------------------- 00137 // ReadPixels 00138 //----------------------------------------------------------------------------- 00152 class ReadPixels: public RenderEventCallback 00153 { 00154 VL_INSTRUMENT_CLASS(vl::ReadPixels, RenderEventCallback) 00155 00156 public: 00157 ReadPixels(): 00158 mX ( 0 ), 00159 mY ( 0 ), 00160 mWidth ( 0 ), 00161 mHeight ( 0 ), 00162 mReadBuffer ( RDB_BACK_LEFT ), 00163 mStoreInPixelBufferObject(false) 00164 { 00165 VL_DEBUG_SET_OBJECT_NAME() 00166 } 00167 00168 ReadPixels(int x, int y, int width, int height, EReadDrawBuffer read_buffer, Image* image, bool store_in_pbo): 00169 mX ( x ), 00170 mY ( y ), 00171 mWidth ( width ), 00172 mHeight ( height ), 00173 mReadBuffer ( read_buffer ), 00174 mImage ( image ), 00175 mStoreInPixelBufferObject( store_in_pbo ) 00176 { 00177 VL_DEBUG_SET_OBJECT_NAME() 00178 } 00179 00180 virtual bool onRenderingStarted(const RenderingAbstract*) 00181 { 00182 readPixels(); 00183 return true; 00184 } 00185 00186 virtual bool onRenderingFinished(const RenderingAbstract*) 00187 { 00188 readPixels(); 00189 return true; 00190 } 00191 00192 virtual bool onRendererStarted(const RendererAbstract*) 00193 { 00194 readPixels(); 00195 return true; 00196 } 00197 00198 virtual bool onRendererFinished(const RendererAbstract*) 00199 { 00200 readPixels(); 00201 return true; 00202 } 00203 00204 void setup(int x, int y, int width, int height, EReadDrawBuffer read_buffer, bool store_in_pbo) 00205 { 00206 mX = x; 00207 mY = y; 00208 mWidth = width; 00209 mHeight = height; 00210 mReadBuffer = read_buffer; 00211 mStoreInPixelBufferObject = store_in_pbo; 00212 } 00213 00214 void setX(int x) { mX = x; } 00215 void setY(int y) { mY = y; } 00216 void setWidth(int width) { mWidth = width; } 00217 void setHeight(int height) { mHeight = height; } 00218 void setReadBuffer(EReadDrawBuffer buffer) { mReadBuffer = buffer; } 00219 void setImage(Image* image) { mImage = image; } 00220 void setSavePath(const String& path) { mSavePath = path; } 00221 00222 int x() const { return mX; } 00223 int y() const { return mY; } 00224 int width() const { return mWidth; } 00225 int height() const { return mHeight; } 00226 EReadDrawBuffer readBuffer() const { return mReadBuffer; } 00227 Image* image() { return mImage.get(); } 00228 const Image* image() const { return mImage.get(); } 00229 const String& savePath() const { return mSavePath; } 00230 00231 void setStoreInPixelBufferObject( bool use_pbo ) { mStoreInPixelBufferObject = use_pbo; } 00232 bool storeInPixelBufferObject() const { return mStoreInPixelBufferObject; } 00233 00234 protected: 00235 void readPixels() 00236 { 00237 if (mImage.get() == NULL) 00238 mImage = new Image; 00239 vl::readPixels(mImage.get(), mX, mY, mWidth, mHeight, mReadBuffer, storeInPixelBufferObject() ); 00240 if ( savePath().length() ) 00241 { 00242 if (!saveImage(mImage.get(), savePath())) 00243 Log::error( Say("ReadPixels: unknown format for file: '%s'\n") << savePath() ); 00244 } 00245 } 00246 00247 protected: 00248 int mX; 00249 int mY; 00250 int mWidth; 00251 int mHeight; 00252 EReadDrawBuffer mReadBuffer; 00253 ref<Image> mImage; 00254 String mSavePath; 00255 bool mStoreInPixelBufferObject; 00256 }; 00257 } 00258 00259 #endif