6304afdee405125a403fbfd2971037da0da9e67c
[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 // =======================================================================
24 // function : OpenGl_FrameBuffer
25 // purpose  :
26 // =======================================================================
27 OpenGl_FrameBuffer::OpenGl_FrameBuffer (GLint theTextureFormat)
28 : myVPSizeX (0),
29   myVPSizeY (0),
30   myTextFormat (theTextureFormat),
31   myGlFBufferId (NO_FRAMEBUFFER),
32   myColorTexture (new OpenGl_Texture()),
33   myDepthStencilTexture (new OpenGl_Texture())
34 {
35   //
36 }
37
38 // =======================================================================
39 // function : ~OpenGl_FrameBuffer
40 // purpose  :
41 // =======================================================================
42 OpenGl_FrameBuffer::~OpenGl_FrameBuffer()
43 {
44   Release (NULL);
45 }
46
47 // =======================================================================
48 // function : Init
49 // purpose  :
50 // =======================================================================
51 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
52                                            const GLsizei   theViewportSizeX,
53                                            const GLsizei   theViewportSizeY)
54 {
55   if (theGlContext->arbFBO == NULL)
56   {
57     return Standard_False;
58   }
59
60   // clean up previous state
61   Release (theGlContext.operator->());
62
63   // setup viewport sizes as is
64   myVPSizeX = theViewportSizeX;
65   myVPSizeY = theViewportSizeY;
66
67   // Create the textures (will be used as color buffer and depth-stencil buffer)
68   if (!initTrashTextures (theGlContext))
69   {
70     Release (theGlContext.operator->());
71     return Standard_False;
72   }
73
74   // Build FBO and setup it as texture
75   theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
76   theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
77   theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
78                                                 GL_TEXTURE_2D, myColorTexture->TextureId(), 0);
79 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
80   theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
81                                                 GL_TEXTURE_2D, myDepthStencilTexture->TextureId(), 0);
82 #else
83   theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
84                                                 GL_TEXTURE_2D, myDepthStencilTexture->TextureId(), 0);
85   theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
86                                                 GL_TEXTURE_2D, myDepthStencilTexture->TextureId(), 0);
87 #endif
88   if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
89   {
90     Release (theGlContext.operator->());
91     return Standard_False;
92   }
93
94   UnbindBuffer (theGlContext);
95   return Standard_True;
96 }
97
98 // =======================================================================
99 // function : Release
100 // purpose  :
101 // =======================================================================
102 void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx)
103 {
104   if (isValidFrameBuffer())
105   {
106     // application can not handle this case by exception - this is bug in code
107     Standard_ASSERT_RETURN (theGlCtx != NULL,
108       "OpenGl_FrameBuffer destroyed without GL context! Possible GPU memory leakage...",);
109     if (theGlCtx->IsValid())
110     {
111       theGlCtx->arbFBO->glDeleteFramebuffers (1, &myGlFBufferId);
112     }
113     myGlFBufferId = NO_FRAMEBUFFER;
114   }
115
116   myColorTexture->Release (theGlCtx);
117   myDepthStencilTexture->Release (theGlCtx);
118 }
119
120 // =======================================================================
121 // function : initTrashTexture
122 // purpose  :
123 // =======================================================================
124 Standard_Boolean OpenGl_FrameBuffer::initTrashTextures (const Handle(OpenGl_Context)& theGlContext)
125 {
126   return    myColorTexture->Init (theGlContext, myTextFormat,
127                                   GL_RGBA, GL_UNSIGNED_BYTE,
128                                   myVPSizeX, myVPSizeY, Graphic3d_TOT_2D)
129   && myDepthStencilTexture->Init (theGlContext, GL_DEPTH24_STENCIL8,
130                                   GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
131                                   myVPSizeX, myVPSizeY, Graphic3d_TOT_2D);
132 }
133
134 // =======================================================================
135 // function : SetupViewport
136 // purpose  :
137 // =======================================================================
138 void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& /*theGlCtx*/)
139 {
140   glViewport (0, 0, myVPSizeX, myVPSizeY);
141 }
142
143 // =======================================================================
144 // function : ChangeViewport
145 // purpose  :
146 // =======================================================================
147 void OpenGl_FrameBuffer::ChangeViewport (const GLsizei theVPSizeX,
148                                          const GLsizei theVPSizeY)
149 {
150   myVPSizeX = theVPSizeX;
151   myVPSizeY = theVPSizeY;
152 }
153
154 // =======================================================================
155 // function : BindBuffer
156 // purpose  :
157 // =======================================================================
158 void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx)
159 {
160   theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
161 }
162
163 // =======================================================================
164 // function : BindDrawBuffer
165 // purpose  :
166 // =======================================================================
167 void OpenGl_FrameBuffer::BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx)
168 {
169   theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId);
170 }
171
172 // =======================================================================
173 // function : BindReadBuffer
174 // purpose  :
175 // =======================================================================
176 void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx)
177 {
178   theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId);
179 }
180
181 // =======================================================================
182 // function : UnbindBuffer
183 // purpose  :
184 // =======================================================================
185 void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx)
186 {
187   theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER);
188 }