diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index b0faf4c564..a851f70748 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -33,7 +33,7 @@ static inline GLsizei getEvenNumber (const GLsizei theNumber) //! Notice - 0 is not power of two here static inline bool isPowerOfTwo (const GLsizei theNumber) { - return !(theNumber & (theNumber - 1)); + return !(theNumber & (theNumber - 1)); } // ======================================================================= @@ -41,15 +41,12 @@ static inline bool isPowerOfTwo (const GLsizei theNumber) // purpose : // ======================================================================= OpenGl_FrameBuffer::OpenGl_FrameBuffer (GLint theTextureFormat) -: mySizeX (0), - mySizeY (0), - myVPSizeX (0), +: myVPSizeX (0), myVPSizeY (0), myTextFormat (theTextureFormat), - myGlTextureId (NO_TEXTURE), myGlFBufferId (NO_FRAMEBUFFER), - myGlDepthRBId (NO_RENDERBUFFER), - myGlStencilRBId (NO_RENDERBUFFER) + myColorTexture (new OpenGl_Texture()), + myDepthStencilTexture (new OpenGl_Texture()) { // } @@ -69,8 +66,7 @@ OpenGl_FrameBuffer::~OpenGl_FrameBuffer() // ======================================================================= Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext, const GLsizei theViewportSizeX, - const GLsizei theViewportSizeY, - const GLboolean toForcePowerOfTwo) + const GLsizei theViewportSizeY) { if (theGlContext->arbFBO == NULL) { @@ -80,75 +76,31 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo // clean up previous state Release (theGlContext.operator->()); - // upscale width/height if numbers are odd - if (toForcePowerOfTwo) - { - mySizeX = OpenGl_Context::GetPowerOfTwo (theViewportSizeX, theGlContext->MaxTextureSize()); - mySizeY = OpenGl_Context::GetPowerOfTwo (theViewportSizeY, theGlContext->MaxTextureSize()); - } - else - { - mySizeX = getEvenNumber (theViewportSizeX); - mySizeY = getEvenNumber (theViewportSizeY); - } - // setup viewport sizes as is myVPSizeX = theViewportSizeX; myVPSizeY = theViewportSizeY; - // Create the texture (will be used as color buffer) - if (!initTrashTexture (theGlContext)) + // Create the textures (will be used as color buffer and depth-stencil buffer) + if (!initTrashTextures (theGlContext)) { - if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY)) - { - return Init (theGlContext, theViewportSizeX, theViewportSizeY, GL_TRUE); - } Release (theGlContext.operator->()); return Standard_False; } - if (!theGlContext->extPDS) - { - // Create RenderBuffer to be used as depth buffer - theGlContext->arbFBO->glGenRenderbuffers (1, &myGlDepthRBId); - theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBId); - theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mySizeX, mySizeY); - - // Create RenderBuffer to be used as stencil buffer - theGlContext->arbFBO->glGenRenderbuffers (1, &myGlStencilRBId); - theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlStencilRBId); - theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX, mySizeX, mySizeY); - } - else - { - // Create combined depth stencil buffer - theGlContext->arbFBO->glGenRenderbuffers (1, &myGlDepthRBId); - theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBId); - theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mySizeX, mySizeY); - myGlStencilRBId = myGlDepthRBId; - } - // Build FBO and setup it as texture theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId); theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); - glEnable (GL_TEXTURE_2D); - glBindTexture (GL_TEXTURE_2D, myGlTextureId); - theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, myGlTextureId, 0); - theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, myGlDepthRBId); - theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, myGlStencilRBId); + theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, myColorTexture->TextureId(), 0); + theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_TEXTURE_2D, myDepthStencilTexture->TextureId(), 0); if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY)) - { - return Init (theGlContext, theViewportSizeX, theViewportSizeY, GL_TRUE); - } Release (theGlContext.operator->()); return Standard_False; } - UnbindBuffer (theGlContext); - UnbindTexture (theGlContext); - theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); + UnbindBuffer (theGlContext); return Standard_True; } @@ -158,107 +110,34 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo // ======================================================================= void OpenGl_FrameBuffer::Release (const OpenGl_Context* theGlCtx) { - if (isValidDepthBuffer() - || isValidStencilBuffer() - || isValidTexture() - || isValidFrameBuffer()) + if (isValidFrameBuffer()) { // application can not handle this case by exception - this is bug in code Standard_ASSERT_RETURN (theGlCtx != NULL, "OpenGl_FrameBuffer destroyed without GL context! Possible GPU memory leakage...",); - } - if (isValidStencilBuffer()) - { - if (theGlCtx->IsValid() - && myGlStencilRBId != myGlDepthRBId) - { - theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlStencilRBId); - } - myGlStencilRBId = NO_RENDERBUFFER; - } - if (isValidDepthBuffer()) - { - if (theGlCtx->IsValid()) - { - theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlDepthRBId); - } - myGlDepthRBId = NO_RENDERBUFFER; - } - if (isValidTexture()) - { - if (theGlCtx->IsValid()) - { - glDeleteTextures (1, &myGlTextureId); - } - myGlTextureId = NO_TEXTURE; - } - mySizeX = mySizeY = myVPSizeX = myVPSizeY = 0; - if (isValidFrameBuffer()) - { if (theGlCtx->IsValid()) { theGlCtx->arbFBO->glDeleteFramebuffers (1, &myGlFBufferId); } myGlFBufferId = NO_FRAMEBUFFER; } -} -// ======================================================================= -// function : isProxySuccess -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_FrameBuffer::isProxySuccess() const -{ - // use proxy to check texture could be created or not - glTexImage2D (GL_PROXY_TEXTURE_2D, - 0, // LOD number: 0 - base image level; n is the nth mipmap reduction image - myTextFormat, // internalformat - mySizeX, mySizeY, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - GLint aTestParamX (0), aTestParamY (0); - glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestParamX); - glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestParamY); - return aTestParamX != 0 && aTestParamY != 0; + myColorTexture->Release (theGlCtx); + myDepthStencilTexture->Release (theGlCtx); } // ======================================================================= // function : initTrashTexture // purpose : // ======================================================================= -Standard_Boolean OpenGl_FrameBuffer::initTrashTexture (const Handle(OpenGl_Context)& theGlContext) +Standard_Boolean OpenGl_FrameBuffer::initTrashTextures (const Handle(OpenGl_Context)& theGlContext) { - // Check texture size is fit dimension maximum - GLint aMaxTexDim = 2048; - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aMaxTexDim); - if (mySizeX > aMaxTexDim || mySizeY > aMaxTexDim) - { - return Standard_False; - } - - // generate new id - glEnable (GL_TEXTURE_2D); - if (!isValidTexture()) - { - glGenTextures (1, &myGlTextureId); // Create The Texture - } - glBindTexture (GL_TEXTURE_2D, myGlTextureId); - - // texture interpolation parameters - could be overridden later - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - if (!isProxySuccess()) - { - Release (theGlContext.operator->()); - return Standard_False; - } - - glTexImage2D (GL_TEXTURE_2D, - 0, // LOD number: 0 - base image level; n is the nth mipmap reduction image - myTextFormat, // internalformat - mySizeX, mySizeY, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); // NULL pointer supported from OpenGL 1.1 - return Standard_True; + return myColorTexture->Init (theGlContext, myTextFormat, + GL_RGBA, GL_UNSIGNED_BYTE, + myVPSizeX, myVPSizeY, Graphic3d_TOT_2D) + && myDepthStencilTexture->Init (theGlContext, GL_DEPTH24_STENCIL8, + GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, + myVPSizeX, myVPSizeY, Graphic3d_TOT_2D); } // ======================================================================= @@ -298,23 +177,3 @@ void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx) { theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER); } - -// ======================================================================= -// function : BindTexture -// purpose : -// ======================================================================= -void OpenGl_FrameBuffer::BindTexture (const Handle(OpenGl_Context)& /*theGlCtx*/) -{ - glEnable (GL_TEXTURE_2D); // needed only for fixed pipeline rendering - glBindTexture (GL_TEXTURE_2D, myGlTextureId); -} - -// ======================================================================= -// function : UnbindTexture -// purpose : -// ======================================================================= -void OpenGl_FrameBuffer::UnbindTexture (const Handle(OpenGl_Context)& /*theGlCtx*/) -{ - glBindTexture (GL_TEXTURE_2D, NO_TEXTURE); - glDisable (GL_TEXTURE_2D); // needed only for fixed pipeline rendering -} diff --git a/src/OpenGl/OpenGl_FrameBuffer.hxx b/src/OpenGl/OpenGl_FrameBuffer.hxx index 4bdd5c924f..fae7cc7323 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.hxx +++ b/src/OpenGl/OpenGl_FrameBuffer.hxx @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -29,9 +30,7 @@ class OpenGl_FrameBuffer : public OpenGl_Resource public: //! Helpful constants - static const GLuint NO_TEXTURE = 0; static const GLuint NO_FRAMEBUFFER = 0; - static const GLuint NO_RENDERBUFFER = 0; public: @@ -44,16 +43,16 @@ public: //! Destroy object - will release GPU memory if any. Standard_EXPORT virtual void Release (const OpenGl_Context* theGlCtx); - //! Texture width. + //! Textures width. GLsizei GetSizeX() const { - return mySizeX; + return myColorTexture->SizeX(); } - //! Texture height. + //! Textures height. GLsizei GetSizeY() const { - return mySizeY; + return myColorTexture->SizeY(); } //! Viewport width. @@ -71,7 +70,7 @@ public: //! Returns true if current object was initialized Standard_Boolean IsValid() const { - return isValidFrameBuffer() && isValidTexture() && isValidDepthBuffer() && isValidStencilBuffer(); + return isValidFrameBuffer(); } //! Notice! Obsolete hardware (GeForce FX etc) @@ -84,8 +83,7 @@ public: //! 3) FBO rendering will be incorrect (some obsolete Catalyst drivers). Standard_EXPORT Standard_Boolean Init (const Handle(OpenGl_Context)& theGlCtx, const GLsizei theViewportSizeX, - const GLsizei theViewportSizeY, - const GLboolean toForcePowerOfTwo = GL_FALSE); + const GLsizei theViewportSizeY); //! Setup viewport to render into FBO Standard_EXPORT void SetupViewport (const Handle(OpenGl_Context)& theGlCtx); @@ -95,56 +93,41 @@ public: const GLsizei theVPSizeY); //! Bind frame buffer (to render into the texture). - Standard_EXPORT void BindBuffer (const Handle(OpenGl_Context)& theGlCtx); + Standard_EXPORT virtual void BindBuffer (const Handle(OpenGl_Context)& theGlCtx); //! Unbind frame buffer. - Standard_EXPORT void UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx); + Standard_EXPORT virtual void UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx); - //! Bind the texture. - Standard_EXPORT void BindTexture (const Handle(OpenGl_Context)& theGlCtx); - - //! Unbind the texture. - Standard_EXPORT void UnbindTexture (const Handle(OpenGl_Context)& theGlCtx); - -private: - - //! Check texture could be created - Standard_Boolean isProxySuccess() const; - - //! Generate texture with undefined data - Standard_Boolean initTrashTexture (const Handle(OpenGl_Context)& theGlContext); - - Standard_Boolean isValidTexture() const + //! Returns the color texture. + inline const Handle(OpenGl_Texture)& ColorTexture() const { - return myGlTextureId != NO_TEXTURE; + return myColorTexture; } + //! Returns the depth-stencil texture. + inline const Handle(OpenGl_Texture)& DepthStencilTexture() const + { + return myDepthStencilTexture; + } + +protected: + + //! Generate textures with undefined data + Standard_Boolean initTrashTextures (const Handle(OpenGl_Context)& theGlContext); + Standard_Boolean isValidFrameBuffer() const { return myGlFBufferId != NO_FRAMEBUFFER; } - Standard_Boolean isValidDepthBuffer() const - { - return myGlDepthRBId != NO_RENDERBUFFER; - } +protected: - Standard_Boolean isValidStencilBuffer() const - { - return myGlStencilRBId != NO_RENDERBUFFER; - } - -private: - - GLsizei mySizeX; //!< texture width - GLsizei mySizeY; //!< texture height - GLsizei myVPSizeX; //!< viewport width (should be <= texture width) - GLsizei myVPSizeY; //!< viewport height (should be <= texture height) - GLint myTextFormat; //!< GL_RGB, GL_RGBA,... - GLuint myGlTextureId; //!< GL texture ID - GLuint myGlFBufferId; //!< FBO object ID - GLuint myGlDepthRBId; //!< RenderBuffer object for depth ID - GLuint myGlStencilRBId; //!< RenderBuffer object for stencil ID + GLsizei myVPSizeX; //!< viewport width (should be <= texture width) + GLsizei myVPSizeY; //!< viewport height (should be <= texture height) + GLint myTextFormat; //!< GL_RGB, GL_RGBA,... + GLuint myGlFBufferId; //!< FBO object ID + Handle(OpenGl_Texture) myColorTexture; //!< color texture object + Handle(OpenGl_Texture) myDepthStencilTexture; //!< depth-stencil texture object public: diff --git a/src/OpenGl/OpenGl_Texture.cxx b/src/OpenGl/OpenGl_Texture.cxx index 98f4675c4d..70dbd0991f 100644 --- a/src/OpenGl/OpenGl_Texture.cxx +++ b/src/OpenGl/OpenGl_Texture.cxx @@ -162,38 +162,34 @@ void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx, glBindTexture (myTarget, NO_TEXTURE); } -// ======================================================================= -// function : Init -// purpose : -// ======================================================================= -bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, - const Image_PixMap& theImage, - const Graphic3d_TypeOfTexture theType) +//======================================================================= +//function : GetDataFormat +//purpose : +//======================================================================= +bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx, + const Image_PixMap& theData, + GLint& theTextFormat, + GLenum& thePixelFormat, + GLenum& theDataType) { - myHasMipmaps = Standard_False; - if (theImage.IsEmpty() || !Create (theCtx)) - { - return false; - } - - myTextFormat = GL_RGBA8; - GLenum aPixelFormat = 0; - GLenum aDataType = 0; - switch (theImage.Format()) + theTextFormat = GL_RGBA8; + thePixelFormat = 0; + theDataType = 0; + switch (theData.Format()) { case Image_PixMap::ImgGrayF: { - myTextFormat = GL_ALPHA8; // GL_R8, GL_R32F - aPixelFormat = GL_ALPHA; // GL_RED - aDataType = GL_FLOAT; - break; + theTextFormat = GL_ALPHA8; // GL_R8, GL_R32F + thePixelFormat = GL_ALPHA; // GL_RED + theDataType = GL_FLOAT; + return true; } case Image_PixMap::ImgRGBAF: { - myTextFormat = GL_RGBA8; // GL_RGBA32F - aPixelFormat = GL_RGBA; - aDataType = GL_FLOAT; - break; + theTextFormat = GL_RGBA8; // GL_RGBA32F + thePixelFormat = GL_RGBA; + theDataType = GL_FLOAT; + return true; } case Image_PixMap::ImgBGRAF: { @@ -201,31 +197,31 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, { return false; } - myTextFormat = GL_RGBA8; // GL_RGBA32F - aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT - aDataType = GL_FLOAT; - break; + theTextFormat = GL_RGBA8; // GL_RGBA32F + thePixelFormat = GL_BGRA; // equals to GL_BGRA_EXT + theDataType = GL_FLOAT; + return true; } case Image_PixMap::ImgRGBF: { - myTextFormat = GL_RGB8; // GL_RGB32F - aPixelFormat = GL_RGB; - aDataType = GL_FLOAT; - break; + theTextFormat = GL_RGB8; // GL_RGB32F + thePixelFormat = GL_RGB; + theDataType = GL_FLOAT; + return true; } case Image_PixMap::ImgBGRF: { - myTextFormat = GL_RGB8; // GL_RGB32F - aPixelFormat = GL_BGR; // equals to GL_BGR_EXT - aDataType = GL_FLOAT; - break; + theTextFormat = GL_RGB8; // GL_RGB32F + thePixelFormat = GL_BGR; // equals to GL_BGR_EXT + theDataType = GL_FLOAT; + return true; } case Image_PixMap::ImgRGBA: { - myTextFormat = GL_RGBA8; - aPixelFormat = GL_RGBA; - aDataType = GL_UNSIGNED_BYTE; - break; + theTextFormat = GL_RGBA8; + thePixelFormat = GL_RGBA; + theDataType = GL_UNSIGNED_BYTE; + return true; } case Image_PixMap::ImgBGRA: { @@ -233,17 +229,17 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, { return false; } - myTextFormat = GL_RGBA8; - aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT - aDataType = GL_UNSIGNED_BYTE; - break; + theTextFormat = GL_RGBA8; + thePixelFormat = GL_BGRA; // equals to GL_BGRA_EXT + theDataType = GL_UNSIGNED_BYTE; + return true; } case Image_PixMap::ImgRGB32: { - myTextFormat = GL_RGB8; - aPixelFormat = GL_RGBA; - aDataType = GL_UNSIGNED_BYTE; - break; + theTextFormat = GL_RGB8; + thePixelFormat = GL_RGBA; + theDataType = GL_UNSIGNED_BYTE; + return true; } case Image_PixMap::ImgBGR32: { @@ -251,17 +247,17 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, { return false; } - myTextFormat = GL_RGB8; - aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT - aDataType = GL_UNSIGNED_BYTE; - break; + theTextFormat = GL_RGB8; + thePixelFormat = GL_BGRA; // equals to GL_BGRA_EXT + theDataType = GL_UNSIGNED_BYTE; + return true; } case Image_PixMap::ImgRGB: { - myTextFormat = GL_RGB8; - aPixelFormat = GL_RGB; - aDataType = GL_UNSIGNED_BYTE; - break; + theTextFormat = GL_RGB8; + thePixelFormat = GL_RGB; + theDataType = GL_UNSIGNED_BYTE; + return true; } case Image_PixMap::ImgBGR: { @@ -269,27 +265,48 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, { return false; } - myTextFormat = GL_RGB8; - aPixelFormat = GL_BGR; // equals to GL_BGR_EXT - aDataType = GL_UNSIGNED_BYTE; - break; + theTextFormat = GL_RGB8; + thePixelFormat = GL_BGR; // equals to GL_BGR_EXT + theDataType = GL_UNSIGNED_BYTE; + return true; } case Image_PixMap::ImgGray: { - myTextFormat = GL_ALPHA8; // GL_R8 - aPixelFormat = GL_ALPHA; // GL_RED - aDataType = GL_UNSIGNED_BYTE; - break; + theTextFormat = GL_ALPHA8; // GL_R8 + thePixelFormat = GL_ALPHA; // GL_RED + theDataType = GL_UNSIGNED_BYTE; + return true; } default: { return false; } } +} +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, + const Standard_Integer theTextFormat, + const GLenum thePixelFormat, + const GLenum theDataType, + const Standard_Integer theSizeX, + const Standard_Integer theSizeY, + const Graphic3d_TypeOfTexture theType, + const Image_PixMap* theImage) +{ + if (!Create (theCtx)) + { + Release (theCtx.operator->()); + return false; + } + myHasMipmaps = Standard_False; + myTextFormat = theTextFormat; + const GLsizei aWidth = theSizeX; + const GLsizei aHeight = theSizeY; const GLsizei aMaxSize = theCtx->MaxTextureSize(); - const GLsizei aWidth = (GLsizei )theImage.SizeX(); - const GLsizei aHeight = (GLsizei )theImage.SizeY(); // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT! @@ -301,16 +318,20 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, GLint aTestWidth = 0; GLint aTestHeight = 0; + GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL; // setup the alignment OpenGl_UnpackAlignmentSentry anUnpackSentry; - const GLint anAligment = Min ((GLint )theImage.MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes - glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment); + if (aDataPtr != NULL) + { + const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes + glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment); - // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension - const GLint anExtraBytes = GLint(theImage.RowExtraBytes()); - const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes()); - glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0); + // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension + const GLint anExtraBytes = GLint(theImage->RowExtraBytes()); + const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes()); + glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0); + } switch (theType) { @@ -322,42 +343,47 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); Image_PixMap aCopy; - GLvoid* aDataPtr = (GLvoid* )theImage.Data(); - if (aWidth != aWidthOut) + if (aDataPtr != NULL) { - glPixelStorei (GL_PACK_ALIGNMENT, 1); - glPixelStorei (GL_PACK_ROW_LENGTH, 0); - if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), 1) - || gluScaleImage (aPixelFormat, - aWidth, 1, aDataType, theImage.Data(), - aWidthOut, 1, aDataType, aCopy.ChangeData()) != 0) + if (aWidth != aWidthOut) { - Unbind (theCtx); - return false; - } + glPixelStorei (GL_PACK_ALIGNMENT, 1); + glPixelStorei (GL_PACK_ROW_LENGTH, 0); + if (!aCopy.InitTrash (theImage->Format(), Standard_Size(aWidthOut), 1) + || gluScaleImage (thePixelFormat, + aWidth, 1, theDataType, theImage->Data(), + aWidthOut, 1, theDataType, aCopy.ChangeData()) != 0) + { + Unbind (theCtx); + Release (theCtx.operator->()); + return false; + } - aDataPtr = (GLvoid* )aCopy.Data(); - anUnpackSentry.Reset(); + aDataPtr = (GLvoid* )aCopy.Data(); + anUnpackSentry.Reset(); + } } // use proxy to check texture could be created or not glTexImage1D (GL_PROXY_TEXTURE_1D, 0, myTextFormat, aWidthOut, 0, - aPixelFormat, aDataType, NULL); + thePixelFormat, theDataType, NULL); glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth); if (aTestWidth == 0) { // no memory or broken input parameters Unbind (theCtx); + Release (theCtx.operator->()); return false; } glTexImage1D (GL_TEXTURE_1D, 0, myTextFormat, aWidthOut, 0, - aPixelFormat, aDataType, aDataPtr); + thePixelFormat, theDataType, aDataPtr); if (glGetError() != GL_NO_ERROR) { Unbind (theCtx); + Release (theCtx.operator->()); return false; } @@ -375,44 +401,49 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); Image_PixMap aCopy; - GLvoid* aDataPtr = (GLvoid* )theImage.Data(); - if (aWidth != aWidthOut || aHeight != aHeightOut) + if (aDataPtr != NULL) { - // scale texture - glPixelStorei (GL_PACK_ALIGNMENT, 1); - glPixelStorei (GL_PACK_ROW_LENGTH, 0); - if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut)) - || gluScaleImage (aPixelFormat, - aWidth, aHeight, aDataType, theImage.Data(), - aWidthOut, aHeightOut, aDataType, aCopy.ChangeData()) != 0) + if (aWidth != aWidthOut || aHeight != aHeightOut) { - Unbind (theCtx); - return false; - } + // scale texture + glPixelStorei (GL_PACK_ALIGNMENT, 1); + glPixelStorei (GL_PACK_ROW_LENGTH, 0); + if (!aCopy.InitTrash (theImage->Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut)) + || gluScaleImage (thePixelFormat, + aWidth, aHeight, theDataType, theImage->Data(), + aWidthOut, aHeightOut, theDataType, aCopy.ChangeData()) != 0) + { + Unbind (theCtx); + Release (theCtx.operator->()); + return false; + } - aDataPtr = (GLvoid* )aCopy.Data(); - anUnpackSentry.Reset(); + aDataPtr = (GLvoid* )aCopy.Data(); + anUnpackSentry.Reset(); + } } // use proxy to check texture could be created or not glTexImage2D (GL_PROXY_TEXTURE_2D, 0, myTextFormat, aWidthOut, aHeightOut, 0, - aPixelFormat, aDataType, NULL); + thePixelFormat, theDataType, NULL); glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth); glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight); if (aTestWidth == 0 || aTestHeight == 0) { // no memory or broken input parameters Unbind (theCtx); + Release (theCtx.operator->()); return false; } glTexImage2D (GL_TEXTURE_2D, 0, myTextFormat, aWidthOut, aHeightOut, 0, - aPixelFormat, aDataType, aDataPtr); + thePixelFormat, theDataType, aDataPtr); if (glGetError() != GL_NO_ERROR) { Unbind (theCtx); + Release (theCtx.operator->()); return false; } @@ -436,23 +467,25 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, // use proxy to check texture could be created or not glTexImage2D (GL_PROXY_TEXTURE_2D, 0, myTextFormat, aWidthOut, aHeightOut, 0, - aPixelFormat, aDataType, NULL); + thePixelFormat, theDataType, NULL); glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth); glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight); if (aTestWidth == 0 || aTestHeight == 0) { // no memory or broken input parameters Unbind (theCtx); + Release (theCtx.operator->()); return false; } // upload main picture glTexImage2D (GL_TEXTURE_2D, 0, myTextFormat, aWidthOut, aHeightOut, 0, - aPixelFormat, aDataType, theImage.Data()); + thePixelFormat, theDataType, theImage->Data()); if (glGetError() != GL_NO_ERROR) { Unbind (theCtx); + Release (theCtx.operator->()); return false; } @@ -470,7 +503,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, { bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, myTextFormat, aWidth, aHeight, - aPixelFormat, aDataType, theImage.Data()) == 0; + thePixelFormat, theDataType, theImage->Data()) == 0; if (isCreated) { glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &mySizeX); @@ -483,11 +516,42 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, } default: { + Release (theCtx.operator->()); return false; } } } +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, + const Image_PixMap& theImage, + const Graphic3d_TypeOfTexture theType) +{ + if (theImage.IsEmpty()) + { + Release (theCtx.operator->()); + return false; + } + + GLenum aPixelFormat; + GLenum aDataType; + GLint aTextFormat; + if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType)) + { + Release (theCtx.operator->()); + return false; + } + + return Init (theCtx, + aTextFormat, aPixelFormat, aDataType, + (Standard_Integer)theImage.SizeX(), + (Standard_Integer)theImage.SizeY(), + theType, &theImage); +} + // ======================================================================= // function : InitRectangle // purpose : diff --git a/src/OpenGl/OpenGl_Texture.hxx b/src/OpenGl/OpenGl_Texture.hxx index 3c277d7d81..3d1352bf66 100644 --- a/src/OpenGl/OpenGl_Texture.hxx +++ b/src/OpenGl/OpenGl_Texture.hxx @@ -221,6 +221,18 @@ public: const Image_PixMap& theImage, const Graphic3d_TypeOfTexture theType); + //! Initialize the texture with specified format, size and texture type. + //! If theImage is empty the texture data will contain trash. + //! Notice that texture will be unbound after this call. + Standard_EXPORT bool Init (const Handle(OpenGl_Context)& theCtx, + const GLint theTextFormat, + const GLenum thePixelFormat, + const GLenum theDataType, + const GLsizei theSizeX, + const GLsizei theSizeY, + const Graphic3d_TypeOfTexture theType, + const Image_PixMap* theImage = NULL); + //! Allocates texture rectangle with specified format and size. //! \note Texture data is not initialized (will contain trash). Standard_EXPORT bool InitRectangle (const Handle(OpenGl_Context)& theCtx, @@ -237,6 +249,13 @@ public: //! @param texture parameters Standard_EXPORT void SetParams (const Handle(Graphic3d_TextureParams)& theParams); + //! Return texture type and format by Image_PixMap data format. + Standard_EXPORT static bool GetDataFormat (const Handle(OpenGl_Context)& theCtx, + const Image_PixMap& theData, + GLint& theTextFormat, + GLenum& thePixelFormat, + GLenum& theDataType); + protected: GLuint myTextureId; //!< GL resource ID diff --git a/src/OpenGl/OpenGl_Workspace_Raytrace.cxx b/src/OpenGl/OpenGl_Workspace_Raytrace.cxx index cfd3500d41..308db40f86 100755 --- a/src/OpenGl/OpenGl_Workspace_Raytrace.cxx +++ b/src/OpenGl/OpenGl_Workspace_Raytrace.cxx @@ -1976,10 +1976,8 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th return Standard_True; } - myGlContext->core20fwd->glActiveTexture ( - GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture); // texture unit for FBO texture - - myRaytraceFBO1->BindTexture (myGlContext); + myRaytraceFBO1->ColorTexture()->Bind (myGlContext, + GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture); myPostFSAAProgram->Bind (myGlContext); @@ -2064,7 +2062,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th if (anIt != 3) // set input for the next pass { - aFramebuffer->BindTexture (myGlContext); + aFramebuffer->ColorTexture()->Bind (myGlContext); aFramebuffer->UnbindBuffer (myGlContext); } }