HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RE_OGLFramebuffer.h
Go to the documentation of this file.
1  /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: RE_OGLFramebuffer.h ( RE Library, C++)
7  *
8  * COMMENTS:
9  *
10  * This class uses the Framebuffer object extension to do offscreen
11  * rendering to render buffers & textures. Note that rendering to texture
12  * is not supported on all platforms, so please check that the framebuffer
13  * is valid before rendering (either isValid(), or the return value of
14  * begin).
15  *
16  * You can attach many buffers, including GL_DEPTH_ATTACHMENT_EXT,
17  * GL_STENCIL_ATTACHMENT_EXT, and up to GL_MAX_COLOR_ATTACHMENTS color
18  * attachments (sequential from GL_COLOR_ATTACHMENT0_EXT). You must include
19  * a render buffer for depth or stencil if you intend to use depth or
20  * stencil tests.
21  *
22  * For color, you can render to either a texture or a renderbuffer.
23  * Generally, textures are used for passes, and renderbuffers are used to
24  * pull images from the GPU.
25  *
26  * Deleting the class will clean up the frame buffer object and any
27  * renderbuffers still attached, but textures will not be deleted.
28  */
29 #ifndef RE_OGLFramebuffer_h
30 #define RE_OGLFramebuffer_h
31 
32 #include "RE_API.h"
34 #include "RE_Render.h"
35 #include "RE_Texture.h"
36 
37 #include <UT/UT_NonCopyable.h>
38 #include <UT/UT_ValArray.h>
39 
40 #include <stdio.h>
41 
42 class re_FrameBufferAttachment;
43 class RE_OGLRenderbuffer;
44 
46 {
49  RE_DEPTH_STENCIL_BUFFER // a depth-stencil buffer instead.
50 };
51 
52 // The status of the framebuffer. Some implementations can support more varied
53 // FBO configs (different formats, res, color targets etc), which others will
54 // throw errors.
56 {
58 
59  RE_FBO_STATUS_ATTACHMENT_INCOMPLETE,// Not all attachments are FBO-complete
60  RE_FBO_STATUS_MISSING_ATTACHMENT, // A required attachment is missing
61  RE_FBO_STATUS_FORMAT_MISMATCH, // formats do not match
62  RE_FBO_STATUS_SIZE_MISMATCH, // resolutions do not match
63  RE_FBO_STATUS_UNSUPPORTED, // GL impl. doesn't support config
64  RE_FBO_STATUS_MULTISAMPLE_MISMATCH, // #buffer samples do not match
65 
66  RE_FBO_STATUS_DRAW_MISSING, // Attempt to draw to missing attach
67  RE_FBO_STATUS_READ_MISSING, // Attempt to read from missing attach
68 
69  RE_FBO_STATUS_LAYERS_MISMATCH, // GeoSh: attachments differ in #layers
70  RE_FBO_STATUS_LAYERS_COUNT, // Too many layers
71 
72  RE_FBO_STATUS_UNKNOWN_ERROR // Future-proof against upcoming errors
73 };
74 
75 
77 {
78 public:
79  RE_OGLFramebuffer(const char *name = nullptr);
80  ~RE_OGLFramebuffer() override;
81 
82  bool init(RE_Render *r) override;
83 
84  const char *getName() { return myName.isstring()?(const char *)myName:""; }
85 
86  /// Returns true if the framebuffer is w x h, with #samples = samples
87  bool matches(int width, int height, int samples = 1) const;
88 
89  /// Attach a texture to the framebuffer. You are still responsible for
90  /// deleting it. 'Level' is the mip level for 2D textures, the cube face
91  /// (RE_TextureCubeFace) for cube maps, and the Z-coord for 3D textures.
92  bool attachTexture(RE_Render *r, RE_Texture *t,
93  int level = -1,
95  int colorbufnum = 0);
96 
97  /// Setup a provided 2D texture to match framebuffer parameters.
98  // You are responsible for deleting it. Must still be mutable.
99  bool setupTexture(RE_Render *r,
100  RE_Texture *t,
101  RE_GPUType data_type, int vectorsize,
102  int miplevel = -1,
103  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER);
104 
105  /// Create a 2D texture and attach it to the framebuffer. You are still
106  /// responsible for deleting it. Specify rect = true to create a
107  /// texture rectangle (check to see that this extension
108  /// is supported before calling this method). Samples > 0 requires the
109  /// texture-multisample extension, and these can only be accessed via
110  /// shaders.
111  RE_Texture *createTexture(RE_Render *r,
112  RE_GPUType data_type, int vectorsize,
113  int miplevel = -1,
114  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
115  int colorbufnum = 0,
116  bool rect = false,
117  int samples = 0);
118 
119  /// Create a renderbuffer and attach it to the framebuffer. This will
120  /// be cleaned up when you delete the render buffer, or call
121  /// clearAttachment() on it. If 'samples' > 1, this is a multisample (AA)
122  /// Framebuffer, which must be blit'ed to a single-sample FBO before being
123  /// read.
124  RE_OGLRenderbuffer *createRenderbuffer(RE_Render *r,
125  RE_GPUType data_type, int vectorsize,
126  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
127  int colorbufnum = 0,
128  int samples=0);
129  bool attachRenderbuffer(RE_Render *r,
130  RE_OGLRenderbuffer *rbuf,
131  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
132  int colorbufnum = 0);
133 
134  bool hasAttachment(RE_Render *r,
135  RE_BufferAttachment buffer_type,
136  int colorbufnum = 0);
137  RE_OGLRenderbuffer *getBufferAttachment(RE_Render *r,
138  RE_BufferAttachment buffer_type,
139  int colorbufnum = 0);
140  RE_Texture *getTextureAttachment(RE_Render *r,
141  RE_BufferAttachment buffer_type,
142  int colorbufnum = 0);
143 
144  /// Pushes an attachment, setting the specified buffer to nullptr. Calls to
145  /// pop attachments will always pop to the original location, replacing
146  /// anything that has been put there in the mean time.
147  void pushAttachment(RE_Render *r,
148  RE_BufferAttachment buffer_type,
149  int colorbufnum = 0);
150  void popAttachment(RE_Render *r);
151 
152  /// Returns true if an attachment if framebuffer-complete.
153  bool verifyBufferAttachment(RE_Render *r,
154  RE_BufferAttachment buffer_type,
155  int colorbufnum = 0,
156  RE_FBOStatus *status = nullptr);
157 
158  /// You must call this if attaching textures (if you are creating textures,
159  /// the resulotion of the textures you pass is used).
160  void setResolution(int width, int height);
161  int getWidth() const { return myWidth; }
162  int getHeight() const { return myHeight; }
163 
164  void setSamples(int samples);
165  int getSamples() const { return mySamples; }
166 
167  /// Sets the origin for the lower-left corner. Normally 0,0.
168  void setOrigin(fpreal x, fpreal y);
169  void getOrigin(fpreal &x, fpreal &y) const;
170 
171  /// Returns true if the framebuffer is ready to render. Optionally returns
172  /// a more detailed failure description if 'status' is provided.
173  bool isValid(RE_Render *r, RE_FBOStatus *status = nullptr);
174 
175  /// Returns the error string for the given status.
176  static const char *getFBOErrorMessage(RE_FBOStatus status);
177 
178  /// Returns true if the texture is attached to this framebuffer.
179  bool isAttached(RE_Render *r, RE_Texture *tex);
180 
181  /// Binds the framebuffer as the active draw or read FBO
182  bool bind(RE_Render *r, bool for_draw = true);
183 
184  /// Unbind the current framebuffer. 'switch_only' indicates that you are
185  /// immediately changing to another FBO.
186  void unbind(RE_Render *r,
187  bool switch_only = false,
188  bool restore_ms = true);
189 
190  /// do all rendering between the begin/end statements. Renders to the
191  /// given attachment. Specify initview = true set the modelview matrix
192  /// to an orthographic projection the size of the framebuffer, the
193  /// viewport to the size of the framebuffer, and to push the current
194  /// GL state (via RE_OGLRender::pushState(1)).
196  int colorbufnum = 0, bool initview = true);
197  bool begin(RE_Render *r); // use last buffer setting, no view init
198  void end(RE_Render *r);
199 
200  bool beginRead(RE_Render *r,
201  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
202  int colorbufnum = 0);
203 
204  /// Returns true if the framebuffer is being drawn to.
205  bool isActiveDraw() { return myBegun && !myReadFlag; }
206 
207  void interruptDraw(RE_Render *r) { unbindFrameBuffer(r); }
208  void resumeDraw(RE_Render *r) { bindFrameBuffer(r); }
209 
210  void drawToBuffer(RE_Render *r,
211  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
212  int colorbufnum = 0);
213  void readFromBuffer(RE_Render *r,
214  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
215  int colorbufnum = 0);
216 
217  /// allows you to draw to multiple buffers at once.
218  /// The type RE_COLOR_BUFFER is assumed. There is a limit on the
219  /// number you can write to simultaneously, getMaxDrawBuffers().
220  void drawToBuffers(RE_Render *r, int num, const int *bufferlist);
221 
222  /// Draws to all color buffers up to getMaxDrawBuffers(). The Z/Stencil
223  /// buffers are written as well if depth or stencil writing is enabled.
224  void drawToAllBuffers(RE_Render *r);
225 
226  /// Initialize the GL state with the various settings in this FBO:
227  /// project_mat - set the projection matrix
228  /// scissor - set the scissor to the resolution of the view
229  /// clear - clear the contents
230  /// This always sets the viewport to the size of the FBO.
231  void initDraw(RE_Render *r,
232  bool project_mat,
233  bool scissor,
234  bool clear) const;
235 
236  // This method allows you to begin an ascyncronous read from a series of
237  // buffers. Note that it will only be asyncronous if the
238  // RE_PIXEL_BUFFER_OBJECT extension is supported.
239  bool readAsyncFromBuffers(RE_Render *r, int num, int *bufferlist);
240 
241  /// reads the data from the render buffer specified into 'buffer'.
242  /// 'buffer' must be large enough to contain the full renderbuffer size.
243  bool readFromRenderBuffer(RE_Render *r, void *image,
244  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
245  int colorbufnum = 0);
246 
247  /// Copies the framebuffer 'from_fbo' to this framebuffer. This is often
248  /// used for resolving multisample framebuffers into an image.
249  /// if destbufnum == -1, colorbufnum is used as the dest buffer as well.
250  bool blitFromFramebuffer(RE_Render *r,
251  RE_OGLFramebuffer *from_fbo,
252  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
253  int colorbufnum = 0,
254  int destbufnum = -1,
255  const UT_DimRect *from_area = nullptr);
256 
257  /// Removes the attachment, and frees the renderbuffer or texture if
258  /// freeme is true.
259  bool detach(RE_Render *r,
260  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
261  int colorbufnum = 0,
262  bool freeme = false);
263 
265  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
266  int colorbufnum = 0)
267  { return detach( r, buffer_type, colorbufnum ,true); }
268 
270  {
271  RE_BIND_NONE = 0, // Cannot be used as a parameter to bindFrameBuffer()
272  RE_BIND_READ = 1,
273  RE_BIND_DRAW = 2,
274  };
275 
276  /// Mostly for debug, this writes out the given attachment to an image file.
277  bool writeToFile(RE_Render *r, const char *filename,
278  RE_BufferAttachment buf, int colorbufnum = 0);
279 
280  void dumpConfig(RE_Render *r, FILE *);
281  // debug check.
282  static bool verifyBinding(RE_Render *r, RE_OGLFramebuffer *fbo,
283  RE_BufferBindMode bindmode = RE_BIND_DRAW);
284 
285  /// Raw GL ID of the FBO
286  GLuint getID() const { return myFramebuffer; }
287 
288 private:
289  bool initImpl(RE_Render *r, bool generate);
290 
291  bool privateReadFromBuffer(RE_Render *r,
292  re_FrameBufferAttachment *attach,
294  void *image_data);
295 
296  bool hasColorBuffer() const;
297  bool hasDepthBuffer() const;
298 
299  bool bindFrameBuffer(RE_Render *r,
300  RE_BufferBindMode bindmode = RE_BIND_DRAW);
301  void unbindFrameBuffer(RE_Render *r);
302  void restoreDrawBuffers(RE_Render *r, int mask);
303 
304  unsigned getGLBuffer() const;
305  RE_FBOStatus getREStatusFromGL(int glstatus);
306 
307  GLuint myFramebuffer;
308  /// ======================================================================
309  /// For new 2D UI drawing.
310  GLint myUnbindFramebuffer = -1;
311  /// ======================================================================
312  fpreal32 myX;
313  fpreal32 myY;
314  int myWidth;
315  int myHeight;
316  bool myBegun;
317  bool myRestoreView;
318  RE_BufferBindMode myOpenMode;
320  UT_Array<re_FrameBufferAttachment *> myPushedAttachments;
321  int mySamples;
322  bool myReadFlag;
323  UT_String myName;
324  int myDrawBuffersMask;
325  int myReadBuffer;
326  bool myPrevMultisample;
327  bool mySavedMultisample;
328 
329  // State values: 0=invalid, 1=valid, -1=not known
330  int myValidState;
331  RE_FBOStatus myLastStatus;
332 };
333 
334 // Renderbuffers are buffers that can be attached to framebuffers instead of
335 // textures.
337 {
338 public:
341 
343 
344  // These can be changed on an existing renderbuffer if not attached to a
345  // framebuffer.
346  void setBufferType(RE_BufferAttachment buffer_type);
347  void setFormat(RE_GPUType data_type, int vectorsize);
348  void setResolution(int w, int h);
349  void setSamples(int samples);
350 
351  // Creates the actual GL renderbuffer.
352  bool create(RE_Render *r);
353  void destroy();
354 
355  // Raw GL renderbuffer ID.
356  GLuint getID() const
357  { return myID; }
359  { return myFormatType; }
360 
361 private:
362  GLuint myID;
363  int myW;
364  int myH;
365  RE_GPUType myFormatType;
366  int myVectorSize;
367  int mySamples;
368  RE_BufferAttachment myBufferType;
369  bool myAttachedFlag;
370 
371  friend class RE_OGLFramebuffer;
372 };
373 
374 #endif
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
bool detachAndFree(RE_Render *r, RE_BufferAttachment buffer_type=RE_COLOR_BUFFER, int colorbufnum=0)
int GLint
Definition: cl.hpp:165
GT_API const UT_StringHolder filename
#define RE_API
Definition: RE_API.h:10
virtual bool init(RE_Render *r)=0
const char * getName()
GLint level
Definition: glcorearb.h:108
GLenum GLenum GLsizei void * image
Definition: glad.h:5132
GLint y
Definition: glcorearb.h:103
unsigned int GLuint
Definition: cl.hpp:167
float fpreal32
Definition: SYS_Types.h:200
RE_FBOStatus
RE_GPUType
Definition: RE_Types.h:52
GLint GLsizei GLsizei height
Definition: glcorearb.h:103
GLuint getID() const
void interruptDraw(RE_Render *r)
__hostdev__ void setOrigin(const T &ijk)
Definition: NanoVDB.h:5762
GLuint GLuint end
Definition: glcorearb.h:475
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
GLint GLuint mask
Definition: glcorearb.h:124
RE_BufferAttachment
GLuint const GLchar * name
Definition: glcorearb.h:786
GLint GLenum GLint x
Definition: glcorearb.h:409
int getSamples() const
GLdouble t
Definition: glad.h:2397
GLsizei samples
Definition: glcorearb.h:1298
GLuint getID() const
Raw GL ID of the FBO.
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
void resumeDraw(RE_Render *r)
fpreal64 fpreal
Definition: SYS_Types.h:278
RE_GPUType getFormatType() const
int getHeight() const
GLint GLsizei width
Definition: glcorearb.h:103
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
RE_RenderBuf
Definition: RE_Types.h:437
GLboolean r
Definition: glcorearb.h:1222
bool isActiveDraw()
Returns true if the framebuffer is being drawn to.
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:566