1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkFramebufferPass.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #include "vtkFramebufferPass.h"
17 #include "vtkObjectFactory.h"
18 #include <cassert>
19 
20 // #include "vtkCamera.h"
21 #include "vtkOpenGLError.h"
22 #include "vtkOpenGLFramebufferObject.h"
23 #include "vtkOpenGLRenderWindow.h"
24 #include "vtkOpenGLState.h"
25 #include "vtkRenderState.h"
26 #include "vtkRenderer.h"
27 #include "vtkTextureObject.h"
28 // #include "vtkShaderProgram.h"
29 // #include "vtkOpenGLShaderCache.h"
30 // #include "vtkOpenGLRenderWindow.h"
31 // #include "vtkOpenGLVertexArrayObject.h"
32 
33 #include "vtkOpenGLHelper.h"
34 
35 vtkStandardNewMacro(vtkFramebufferPass);
36 
37 //------------------------------------------------------------------------------
vtkFramebufferPass()38 vtkFramebufferPass::vtkFramebufferPass()
39 {
40   this->FrameBufferObject = nullptr;
41   this->ColorTexture = vtkTextureObject::New();
42   this->DepthTexture = vtkTextureObject::New();
43   this->DepthFormat = vtkTextureObject::Float32;
44   this->ColorFormat = vtkTextureObject::Fixed8;
45 }
46 
47 //------------------------------------------------------------------------------
~vtkFramebufferPass()48 vtkFramebufferPass::~vtkFramebufferPass()
49 {
50   if (this->FrameBufferObject != nullptr)
51   {
52     vtkErrorMacro(<< "FrameBufferObject should have been deleted in ReleaseGraphicsResources().");
53   }
54   if (this->ColorTexture != nullptr)
55   {
56     this->ColorTexture->Delete();
57     this->ColorTexture = nullptr;
58   }
59   if (this->DepthTexture != nullptr)
60   {
61     this->DepthTexture->Delete();
62     this->DepthTexture = nullptr;
63   }
64 }
65 
66 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)67 void vtkFramebufferPass::PrintSelf(ostream& os, vtkIndent indent)
68 {
69   this->Superclass::PrintSelf(os, indent);
70 }
71 
72 //------------------------------------------------------------------------------
73 // Description:
74 // Perform rendering according to a render state \p s.
75 // \pre s_exists: s!=0
Render(const vtkRenderState * s)76 void vtkFramebufferPass::Render(const vtkRenderState* s)
77 {
78   assert("pre: s_exists" && s != nullptr);
79 
80   vtkOpenGLClearErrorMacro();
81 
82   this->NumberOfRenderedProps = 0;
83 
84   vtkRenderer* r = s->GetRenderer();
85   vtkOpenGLRenderWindow* renWin = static_cast<vtkOpenGLRenderWindow*>(r->GetRenderWindow());
86   vtkOpenGLState* ostate = renWin->GetState();
87 
88   if (this->DelegatePass == nullptr)
89   {
90     vtkWarningMacro(<< " no delegate.");
91     return;
92   }
93 
94   // 1. Create a new render state with an FO.
95   if (s->GetFrameBuffer() == nullptr)
96   {
97     // get the viewport dimensions
98     r->GetTiledSizeAndOrigin(
99       &this->ViewportWidth, &this->ViewportHeight, &this->ViewportX, &this->ViewportY);
100   }
101   else
102   {
103     int size[2];
104     s->GetWindowSize(size);
105     this->ViewportWidth = size[0];
106     this->ViewportHeight = size[1];
107     this->ViewportX = 0;
108     this->ViewportY = 0;
109   }
110 
111   this->ColorTexture->SetContext(renWin);
112   if (!this->ColorTexture->GetHandle())
113   {
114     if (this->ColorFormat == vtkTextureObject::Float16)
115     {
116       this->ColorTexture->SetInternalFormat(GL_RGBA16F);
117       this->ColorTexture->SetDataType(GL_FLOAT);
118     }
119     if (this->ColorFormat == vtkTextureObject::Float32)
120     {
121       this->ColorTexture->SetInternalFormat(GL_RGBA32F);
122       this->ColorTexture->SetDataType(GL_FLOAT);
123     }
124     this->ColorTexture->Create2D(
125       this->ViewportWidth, this->ViewportHeight, 4, VTK_UNSIGNED_CHAR, false);
126   }
127   this->ColorTexture->Resize(this->ViewportWidth, this->ViewportHeight);
128 
129   // Depth texture
130   this->DepthTexture->SetContext(renWin);
131   if (!this->DepthTexture->GetHandle())
132   {
133     this->DepthTexture->AllocateDepth(this->ViewportWidth, this->ViewportHeight, this->DepthFormat);
134   }
135   this->DepthTexture->Resize(this->ViewportWidth, this->ViewportHeight);
136 
137   if (this->FrameBufferObject == nullptr)
138   {
139     this->FrameBufferObject = vtkOpenGLFramebufferObject::New();
140     this->FrameBufferObject->SetContext(renWin);
141   }
142 
143   ostate->PushFramebufferBindings();
144   this->RenderDelegate(s, this->ViewportWidth, this->ViewportHeight, this->ViewportWidth,
145     this->ViewportHeight, this->FrameBufferObject, this->ColorTexture, this->DepthTexture);
146 
147   ostate->PopFramebufferBindings();
148 
149   // now copy the result to the outer FO
150   ostate->PushReadFramebufferBinding();
151   this->FrameBufferObject->Bind(vtkOpenGLFramebufferObject::GetReadMode());
152 
153   ostate->vtkglViewport(
154     this->ViewportX, this->ViewportY, this->ViewportWidth, this->ViewportHeight);
155   ostate->vtkglScissor(this->ViewportX, this->ViewportY, this->ViewportWidth, this->ViewportHeight);
156 
157   ostate->vtkglBlitFramebuffer(0, 0, this->ViewportWidth, this->ViewportHeight, this->ViewportX,
158     this->ViewportY, this->ViewportX + this->ViewportWidth, this->ViewportY + this->ViewportHeight,
159     GL_COLOR_BUFFER_BIT, GL_LINEAR);
160 
161   ostate->PopReadFramebufferBinding();
162 
163   vtkOpenGLCheckErrorMacro("failed after Render");
164 }
165 
166 //------------------------------------------------------------------------------
167 // Description:
168 // Release graphics resources and ask components to release their own
169 // resources.
170 // \pre w_exists: w!=0
ReleaseGraphicsResources(vtkWindow * w)171 void vtkFramebufferPass::ReleaseGraphicsResources(vtkWindow* w)
172 {
173   assert("pre: w_exists" && w != nullptr);
174 
175   this->Superclass::ReleaseGraphicsResources(w);
176 
177   if (this->FrameBufferObject != nullptr)
178   {
179     this->FrameBufferObject->Delete();
180     this->FrameBufferObject = nullptr;
181   }
182   if (this->ColorTexture != nullptr)
183   {
184     this->ColorTexture->ReleaseGraphicsResources(w);
185   }
186   if (this->DepthTexture != nullptr)
187   {
188     this->DepthTexture->ReleaseGraphicsResources(w);
189   }
190 }
191