0025219: Visualization, TKOpenGl - disable code paths unavailable on OpenGL ES 2.0
[occt.git] / src / OpenGl / OpenGl_FrameBuffer.cxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2011-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <OpenGl_FrameBuffer.hxx>
16 #include <OpenGl_ArbFBO.hxx>
17
18 #include <Standard_Assert.hxx>
19
20 IMPLEMENT_STANDARD_HANDLE (OpenGl_FrameBuffer, OpenGl_Resource)
21 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer, OpenGl_Resource)
22
23 static inline bool isOddNumber (const GLsizei theNumber)
24 {
25   return theNumber & 0x01;
26 }
27
28 static inline GLsizei getEvenNumber (const GLsizei theNumber)
29 {
30   return isOddNumber (theNumber) ? (theNumber + 1) : theNumber;
31 }
32
33 //! Notice - 0 is not power of two here
34 static inline bool isPowerOfTwo (const GLsizei theNumber)
35 {
36   return !(theNumber & (theNumber - 1));
37 }
38
39 // =======================================================================
40 // function : OpenGl_FrameBuffer
41 // purpose  :
42 // =======================================================================
43 OpenGl_FrameBuffer::OpenGl_FrameBuffer (GLint theTextureFormat)
44 : myVPSizeX (0),
45   myVPSizeY (0),
46   myTextFormat (theTextureFormat),
47   myGlFBufferId (NO_FRAMEBUFFER),
48   myColorTexture (new OpenGl_Texture()),
49   myDepthStencilTexture (new OpenGl_Texture())
50 {
51   //
52 }
53
54 // =======================================================================
55 // function : ~OpenGl_FrameBuffer
56 // purpose  :
57 // =======================================================================
58 OpenGl_FrameBuffer::~OpenGl_FrameBuffer()
59 {
60   Release (NULL);
61 }
62
63 // =======================================================================
64 // function : Init
65 // purpose  :
66 // =======================================================================
67 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
68                                            const GLsizei   theViewportSizeX,
69                                            const GLsizei   theViewportSizeY)
70 {
71   if (theGlContext->arbFBO == NULL)
72   {
73     return Standard_False;
74   }
75
76   // clean up previous state
77   Release (theGlContext.operator->());
78
79   // setup viewport sizes as is
80   myVPSizeX = theViewportSizeX;
81   myVPSizeY = theViewportSizeY;
82
83   // Create the textures (will be used as color buffer and depth-stencil buffer)
84   if (!initTrashTextures (theGlContext))
85   {
86     Release (theGlContext.operator->());
87     return Standard_False;
88   }
89
90   // Build FBO and setup it as texture
91   theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
92   theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
93   theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
94                                                 GL_TEXTURE_2D, myColorTexture->TextureId(), 0);
95 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
96   theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
97                                                 GL_TEXTURE_2D, myDepthStencilTexture->TextureId(), 0);
98 #else
99   theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
100                                                 GL_TEXTURE_2D, myDepthStencilTexture->TextureId(), 0);
101   theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
102                                                 GL_TEXTURE_2D, myDepthStencilTexture->TextureId(), 0);
103 #endif
104   if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
105   {
106     Release (theGlContext.operator->());
107     return Standard_False;
108   }
109
110   UnbindBuffer (theGlContext);
111   return Standard_True;
112 }
113
114 // =======================================================================
115 // function : Release
116 // purpose  :
117 // =======================================================================
118 void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx)
119 {
120   if (isValidFrameBuffer())
121   {
122     // application can not handle this case by exception - this is bug in code
123     Standard_ASSERT_RETURN (theGlCtx != NULL,
124       "OpenGl_FrameBuffer destroyed without GL context! Possible GPU memory leakage...",);
125     if (theGlCtx->IsValid())
126     {
127       theGlCtx->arbFBO->glDeleteFramebuffers (1, &myGlFBufferId);
128     }
129     myGlFBufferId = NO_FRAMEBUFFER;
130   }
131
132   myColorTexture->Release (theGlCtx);
133   myDepthStencilTexture->Release (theGlCtx);
134 }
135
136 // =======================================================================
137 // function : initTrashTexture
138 // purpose  :
139 // =======================================================================
140 Standard_Boolean OpenGl_FrameBuffer::initTrashTextures (const Handle(OpenGl_Context)& theGlContext)
141 {
142   return    myColorTexture->Init (theGlContext, myTextFormat,
143                                   GL_RGBA, GL_UNSIGNED_BYTE,
144                                   myVPSizeX, myVPSizeY, Graphic3d_TOT_2D)
145   && myDepthStencilTexture->Init (theGlContext, GL_DEPTH24_STENCIL8,
146                                   GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
147                                   myVPSizeX, myVPSizeY, Graphic3d_TOT_2D);
148 }
149
150 // =======================================================================
151 // function : SetupViewport
152 // purpose  :
153 // =======================================================================
154 void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& /*theGlCtx*/)
155 {
156   glViewport (0, 0, myVPSizeX, myVPSizeY);
157 }
158
159 // =======================================================================
160 // function : ChangeViewport
161 // purpose  :
162 // =======================================================================
163 void OpenGl_FrameBuffer::ChangeViewport (const GLsizei theVPSizeX,
164                                          const GLsizei theVPSizeY)
165 {
166   myVPSizeX = theVPSizeX;
167   myVPSizeY = theVPSizeY;
168 }
169
170 // =======================================================================
171 // function : BindBuffer
172 // purpose  :
173 // =======================================================================
174 void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx)
175 {
176   theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
177 }
178
179 // =======================================================================
180 // function : UnbindBuffer
181 // purpose  :
182 // =======================================================================
183 void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx)
184 {
185   theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER);
186 }