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_Render.h"
33 
34 #include <stdio.h>
35 #include <UT/UT_ValArray.h>
37 #include "RE_Texture.h"
38 
39 class re_FrameBufferAttachment;
40 class RE_OGLRenderbuffer;
41 
43 {
46  RE_DEPTH_STENCIL_BUFFER // a depth-stencil buffer instead.
47 };
48 
49 // The status of the framebuffer. Some implementations can support more varied
50 // FBO configs (different formats, res, color targets etc), which others will
51 // throw errors.
53 {
55 
56  RE_FBO_STATUS_ATTACHMENT_INCOMPLETE,// Not all attachments are FBO-complete
57  RE_FBO_STATUS_MISSING_ATTACHMENT, // A required attachment is missing
58  RE_FBO_STATUS_FORMAT_MISMATCH, // formats do not match
59  RE_FBO_STATUS_SIZE_MISMATCH, // resolutions do not match
60  RE_FBO_STATUS_UNSUPPORTED, // GL impl. doesn't support config
61  RE_FBO_STATUS_MULTISAMPLE_MISMATCH, // #buffer samples do not match
62 
63  RE_FBO_STATUS_DRAW_MISSING, // Attempt to draw to missing attach
64  RE_FBO_STATUS_READ_MISSING, // Attempt to read from missing attach
65 
66  RE_FBO_STATUS_LAYERS_MISMATCH, // GeoSh: attachments differ in #layers
67  RE_FBO_STATUS_LAYERS_COUNT, // Too many layers
68 
69  RE_FBO_STATUS_UNKNOWN_ERROR // Future-proof against upcoming errors
70 };
71 
72 
74 {
75 public:
76  RE_OGLFramebuffer(const char *name = nullptr);
77  ~RE_OGLFramebuffer() override;
78 
79  bool init(RE_Render *r) override;
80 
81  const char *getName() { return myName.isstring()?(const char *)myName:""; }
82 
83  /// Returns true if the framebuffer is w x h, with #samples = samples
84  bool matches(int width, int height, int samples = 1) const;
85 
86  /// Attach a texture to the framebuffer. You are still responsible for
87  /// deleting it. 'Level' is the mip level for 2D textures, the cube face
88  /// (RE_TextureCubeFace) for cube maps, and the Z-coord for 3D textures.
89  bool attachTexture(RE_Render *r, RE_Texture *t,
90  int level = -1,
92  int colorbufnum = 0);
93 
94  /// Setup a provided 2D texture to match framebuffer parameters.
95  // You are responsible for deleting it. Must still be mutable.
96  bool setupTexture(RE_Render *r,
97  RE_Texture *t,
98  RE_GPUType data_type, int vectorsize,
99  int miplevel = -1,
100  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER);
101 
102  /// Create a 2D texture and attach it to the framebuffer. You are still
103  /// responsible for deleting it. Specify rect = true to create a
104  /// texture rectangle (check to see that this extension
105  /// is supported before calling this method). Samples > 0 requires the
106  /// texture-multisample extension, and these can only be accessed via
107  /// shaders.
108  RE_Texture *createTexture(RE_Render *r,
109  RE_GPUType data_type, int vectorsize,
110  int miplevel = -1,
111  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
112  int colorbufnum = 0,
113  bool rect = false,
114  int samples = 0);
115 
116  /// Create a renderbuffer and attach it to the framebuffer. This will
117  /// be cleaned up when you delete the render buffer, or call
118  /// clearAttachment() on it. If 'samples' > 1, this is a multisample (AA)
119  /// Framebuffer, which must be blit'ed to a single-sample FBO before being
120  /// read.
121  RE_OGLRenderbuffer *createRenderbuffer(RE_Render *r,
122  RE_GPUType data_type, int vectorsize,
123  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
124  int colorbufnum = 0,
125  int samples=0);
126  bool attachRenderbuffer(RE_Render *r,
127  RE_OGLRenderbuffer *rbuf,
128  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
129  int colorbufnum = 0);
130 
131  bool hasAttachment(RE_Render *r,
132  RE_BufferAttachment buffer_type,
133  int colorbufnum = 0);
134  RE_OGLRenderbuffer *getBufferAttachment(RE_Render *r,
135  RE_BufferAttachment buffer_type,
136  int colorbufnum = 0);
137  RE_Texture *getTextureAttachment(RE_Render *r,
138  RE_BufferAttachment buffer_type,
139  int colorbufnum = 0);
140 
141  /// Pushes an attachment, setting the specified buffer to nullptr. Calls to
142  /// pop attachments will always pop to the original location, replacing
143  /// anything that has been put there in the mean time.
144  void pushAttachment(RE_Render *r,
145  RE_BufferAttachment buffer_type,
146  int colorbufnum = 0);
147  void popAttachment(RE_Render *r);
148 
149  /// Returns true if an attachment if framebuffer-complete.
150  bool verifyBufferAttachment(RE_Render *r,
151  RE_BufferAttachment buffer_type,
152  int colorbufnum = 0,
153  RE_FBOStatus *status = nullptr);
154 
155  /// You must call this if attaching textures (if you are creating textures,
156  /// the resulotion of the textures you pass is used).
157  void setResolution(int width, int height);
158  int getWidth() const { return myWidth; }
159  int getHeight() const { return myHeight; }
160 
161  void setSamples(int samples);
162  int getSamples() const { return mySamples; }
163 
164  /// Sets the origin for the lower-left corner. Normally 0,0.
165  void setOrigin(fpreal x, fpreal y);
166  void getOrigin(fpreal &x, fpreal &y) const;
167 
168  /// Returns true if the framebuffer is ready to render. Optionally returns
169  /// a more detailed failure description if 'status' is provided.
170  bool isValid(RE_Render *r, RE_FBOStatus *status = nullptr);
171 
172  /// Returns the error string for the given status.
173  static const char *getFBOErrorMessage(RE_FBOStatus status);
174 
175  /// Returns true if the texture is attached to this framebuffer.
176  bool isAttached(RE_Render *r, RE_Texture *tex);
177 
178  /// Binds the framebuffer as the active draw or read FBO
179  bool bind(RE_Render *r, bool for_draw = true);
180 
181  /// Unbind the current framebuffer. 'switch_only' indicates that you are
182  /// immediately changing to another FBO.
183  void unbind(RE_Render *r,
184  bool switch_only = false,
185  bool restore_ms = true);
186 
187  /// do all rendering between the begin/end statements. Renders to the
188  /// given attachment. Specify initview = true set the modelview matrix
189  /// to an orthographic projection the size of the framebuffer, the
190  /// viewport to the size of the framebuffer, and to push the current
191  /// GL state (via RE_OGLRender::pushState(1)).
193  int colorbufnum = 0, bool initview = true);
194  bool begin(RE_Render *r); // use last buffer setting, no view init
195  void end(RE_Render *r);
196 
197  bool beginRead(RE_Render *r,
198  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
199  int colorbufnum = 0);
200 
201  /// Returns true if the framebuffer is being drawn to.
202  bool isActiveDraw() { return myBegun && !myReadFlag; }
203 
204  void interruptDraw(RE_Render *r) { unbindFrameBuffer(r); }
205  void resumeDraw(RE_Render *r) { bindFrameBuffer(r); }
206 
207  void drawToBuffer(RE_Render *r,
208  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
209  int colorbufnum = 0);
210  void readFromBuffer(RE_Render *r,
211  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
212  int colorbufnum = 0);
213 
214  /// allows you to draw to multiple buffers at once.
215  /// The type RE_COLOR_BUFFER is assumed. There is a limit on the
216  /// number you can write to simultaneously, getMaxDrawBuffers().
217  void drawToBuffers(RE_Render *r, int num, const int *bufferlist);
218 
219  /// Draws to all color buffers up to getMaxDrawBuffers(). The Z/Stencil
220  /// buffers are written as well if depth or stencil writing is enabled.
221  void drawToAllBuffers(RE_Render *r);
222 
223  /// Initialize the GL state with the various settings in this FBO:
224  /// project_mat - set the projection matrix
225  /// scissor - set the scissor to the resolution of the view
226  /// clear - clear the contents
227  /// This always sets the viewport to the size of the FBO.
228  void initDraw(RE_Render *r,
229  bool project_mat,
230  bool scissor,
231  bool clear) const;
232 
233  // This method allows you to begin an ascyncronous read from a series of
234  // buffers. Note that it will only be asyncronous if the
235  // RE_PIXEL_BUFFER_OBJECT extension is supported.
236  bool readAsyncFromBuffers(RE_Render *r, int num, int *bufferlist);
237 
238  /// reads the data from the render buffer specified into 'buffer'.
239  /// 'buffer' must be large enough to contain the full renderbuffer size.
240  bool readFromRenderBuffer(RE_Render *r, void *image,
241  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
242  int colorbufnum = 0);
243 
244  /// Copies the framebuffer 'from_fbo' to this framebuffer. This is often
245  /// used for resolving multisample framebuffers into an image.
246  /// if destbufnum == -1, colorbufnum is used as the dest buffer as well.
247  bool blitFromFramebuffer(RE_Render *r,
248  RE_OGLFramebuffer *from_fbo,
249  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
250  int colorbufnum = 0,
251  int destbufnum = -1,
252  const UT_DimRect *from_area = nullptr);
253 
254  /// Removes the attachment, and frees the renderbuffer or texture if
255  /// freeme is true.
256  bool detach(RE_Render *r,
257  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
258  int colorbufnum = 0,
259  bool freeme = false);
260 
262  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
263  int colorbufnum = 0)
264  { return detach( r, buffer_type, colorbufnum ,true); }
265 
267  {
268  RE_BIND_NONE = 0, // Cannot be used as a parameter to bindFrameBuffer()
269  RE_BIND_READ = 1,
270  RE_BIND_DRAW = 2,
271  };
272 
273  /// Mostly for debug, this writes out the given attachment to an image file.
274  bool writeToFile(RE_Render *r, const char *filename,
275  RE_BufferAttachment buf, int colorbufnum = 0);
276 
277  void dumpConfig(RE_Render *r, FILE *);
278  // debug check.
279  static bool verifyBinding(RE_Render *r, RE_OGLFramebuffer *fbo,
280  RE_BufferBindMode bindmode = RE_BIND_DRAW);
281 
282  /// Raw GL ID of the FBO
283  GLuint getID() const { return myFramebuffer; }
284 
285 private:
286  bool initImpl(RE_Render *r, bool generate);
287 
288  bool privateReadFromBuffer(RE_Render *r,
289  re_FrameBufferAttachment *attach,
291  void *image_data);
292 
293  bool hasColorBuffer() const;
294  bool hasDepthBuffer() const;
295 
296  bool bindFrameBuffer(RE_Render *r,
297  RE_BufferBindMode bindmode = RE_BIND_DRAW);
298  void unbindFrameBuffer(RE_Render *r);
299  void restoreDrawBuffers(RE_Render *r, int mask);
300 
301  unsigned getGLBuffer() const;
302  RE_FBOStatus getREStatusFromGL(int glstatus);
303 
304  GLuint myFramebuffer;
305 #if defined(EXPERIMENTAL_QOPENGLWIDGET)
306  GLint myUnbindFramebuffer = -1;
307 #endif
308  fpreal32 myX;
309  fpreal32 myY;
310  int myWidth;
311  int myHeight;
312  bool myBegun;
313  bool myRestoreView;
314  RE_BufferBindMode myOpenMode;
316  UT_Array<re_FrameBufferAttachment *> myPushedAttachments;
317  int mySamples;
318  bool myReadFlag;
319  UT_String myName;
320  int myDrawBuffersMask;
321  int myReadBuffer;
322  bool myPrevMultisample;
323  bool mySavedMultisample;
324 
325  // State values: 0=invalid, 1=valid, -1=not known
326  int myValidState;
327  RE_FBOStatus myLastStatus;
328 };
329 
330 // Renderbuffers are buffers that can be attached to framebuffers instead of
331 // textures.
333 {
334 public:
337 
338  // These can be changed on an existing renderbuffer if not attached to a
339  // framebuffer.
340  void setBufferType(RE_BufferAttachment buffer_type);
341  void setFormat(RE_GPUType data_type, int vectorsize);
342  void setResolution(int w, int h);
343  void setSamples(int samples);
344 
345  // Creates the actual GL renderbuffer.
346  bool create(RE_Render *r);
347  void destroy();
348 
349  // Raw GL renderbuffer ID.
350  GLuint getID() const
351  { return myID; }
353  { return myFormatType; }
354 
355 private:
356  GLuint myID;
357  int myW;
358  int myH;
359  RE_GPUType myFormatType;
360  int myVectorSize;
361  int mySamples;
362  RE_BufferAttachment myBufferType;
363  bool myAttachedFlag;
364 
365  friend class RE_OGLFramebuffer;
366 };
367 
368 #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:44
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
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:277
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:430
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:558