HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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 = NULL);
78 
79  virtual bool init(RE_Render *r);
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  /// Create a 2D texture and attach it to the framebuffer. You are still
95  /// responsible for deleting it. Specify rect = true to create a
96  /// texture rectangle (check to see that this extension
97  /// is supported before calling this method). Samples > 0 requires the
98  /// texture-multisample extension, and these can only be accessed via
99  /// shaders.
100  RE_Texture *createTexture(RE_Render *r,
101  RE_GPUType data_type, int vectorsize,
102  int miplevel = -1,
103  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
104  int colorbufnum = 0,
105  bool rect = false,
106  int samples = 0);
107 
108  /// Create a renderbuffer and attach it to the framebuffer. This will
109  /// be cleaned up when you delete the render buffer, or call
110  /// clearAttachment() on it. If 'samples' > 1, this is a multisample (AA)
111  /// Framebuffer, which must be blit'ed to a single-sample FBO before being
112  /// read.
113  RE_OGLRenderbuffer *createRenderbuffer(RE_Render *r,
114  RE_GPUType data_type, int vectorsize,
115  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
116  int colorbufnum = 0,
117  int samples=0);
118  bool attachRenderbuffer(RE_Render *r,
119  RE_OGLRenderbuffer *rbuf,
120  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
121  int colorbufnum = 0);
122 
123  bool hasAttachment(RE_Render *r,
124  RE_BufferAttachment buffer_type,
125  int colorbufnum = 0);
126  RE_OGLRenderbuffer *getBufferAttachment(RE_Render *r,
127  RE_BufferAttachment buffer_type,
128  int colorbufnum = 0);
129  RE_Texture *getTextureAttachment(RE_Render *r,
130  RE_BufferAttachment buffer_type,
131  int colorbufnum = 0);
132 
133  /// Pushes an attachment, setting the specified buffer to NULL. Calls to
134  /// pop attachments will always pop to the original location, replacing
135  /// anything that has been put there in the mean time.
136  void pushAttachment(RE_Render *r,
137  RE_BufferAttachment buffer_type,
138  int colorbufnum = 0);
139  void popAttachment(RE_Render *r);
140 
141  /// Returns true if an attachment if framebuffer-complete.
142  bool verifyBufferAttachment(RE_Render *r,
143  RE_BufferAttachment buffer_type,
144  int colorbufnum = 0,
145  RE_FBOStatus *status = NULL);
146 
147  /// You must call this if attaching textures (if you are creating textures,
148  /// the resulotion of the textures you pass is used).
149  void setResolution(int width, int height);
150  int getWidth() const { return myWidth; }
151  int getHeight() const { return myHeight; }
152 
153  void setSamples(int samples);
154  int getSamples() const { return mySamples; }
155 
156  /// Sets the origin for the lower-left corner. Normally 0,0.
157  void setOrigin(fpreal x, fpreal y);
158  void getOrigin(fpreal &x, fpreal &y) const;
159 
160  /// Returns true if the framebuffer is ready to render. Optionally returns
161  /// a more detailed failure description if 'status' is provided.
162  bool isValid(RE_Render *r, RE_FBOStatus *status = NULL);
163 
164  /// Returns the error string for the given status.
165  static const char *getFBOErrorMessage(RE_FBOStatus status);
166 
167  /// Returns true if the texture is attached to this framebuffer.
168  bool isAttached(RE_Render *r, RE_Texture *tex);
169 
170  /// Binds the framebuffer as the active draw or read FBO
171  bool bind(RE_Render *r, bool for_draw = true);
172 
173  /// Unbind the current framebuffer. 'switch_only' indicates that you are
174  /// immediately changing to another FBO.
175  void unbind(RE_Render *r,
176  bool switch_only = false,
177  bool restore_ms = true);
178 
179  /// do all rendering between the begin/end statements. Renders to the
180  /// given attachment. Specify initview = true set the modelview matrix
181  /// to an orthographic projection the size of the framebuffer, the
182  /// viewport to the size of the framebuffer, and to push the current
183  /// GL state (via RE_OGLRender::pushState(1)).
184  bool begin(RE_Render *r, RE_BufferAttachment buf,
185  int colorbufnum = 0, bool initview = true);
186  bool begin(RE_Render *r); // use last buffer setting, no view init
187  void end(RE_Render *r);
188 
189  bool beginRead(RE_Render *r,
190  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
191  int colorbufnum = 0);
192 
193  /// Returns true if the framebuffer is being drawn to.
194  bool isActiveDraw() { return myBegun && !myReadFlag; }
195 
196  void interruptDraw(RE_Render *r) { unbindFrameBuffer(r); }
197  void resumeDraw(RE_Render *r) { bindFrameBuffer(r); }
198 
199  void drawToBuffer(RE_Render *r,
200  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
201  int colorbufnum = 0);
202  void readFromBuffer(RE_Render *r,
203  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
204  int colorbufnum = 0);
205 
206  /// allows you to draw to multiple buffers at once.
207  /// The type RE_COLOR_BUFFER is assumed. There is a limit on the
208  /// number you can write to simultaneously, getMaxDrawBuffers().
209  void drawToBuffers(RE_Render *r, int num, const int *bufferlist);
210 
211  /// Draws to all color buffers up to getMaxDrawBuffers(). The Z/Stencil
212  /// buffers are written as well if depth or stencil writing is enabled.
213  void drawToAllBuffers(RE_Render *r);
214 
215  /// Initialize the GL state with the various settings in this FBO:
216  /// project_mat - set the projection matrix
217  /// scissor - set the scissor to the resolution of the view
218  /// clear - clear the contents
219  /// This always sets the viewport to the size of the FBO.
220  void initDraw(RE_Render *r,
221  bool project_mat,
222  bool scissor,
223  bool clear) const;
224 
225  // This method allows you to begin an ascyncronous read from a series of
226  // buffers. Note that it will only be asyncronous if the
227  // RE_PIXEL_BUFFER_OBJECT extension is supported.
228  bool readAsyncFromBuffers(RE_Render *r, int num, int *bufferlist);
229 
230  /// reads the data from the render buffer specified into 'buffer'.
231  /// 'buffer' must be large enough to contain the full renderbuffer size.
232  bool readFromRenderBuffer(RE_Render *r, void *image,
233  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
234  int colorbufnum = 0);
235 
236  /// Copies the framebuffer 'from_fbo' to this framebuffer. This is often
237  /// used for resolving multisample framebuffers into an image.
238  /// if destbufnum == -1, colorbufnum is used as the dest buffer as well.
239  bool blitFromFramebuffer(RE_Render *r,
240  RE_OGLFramebuffer *from_fbo,
241  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
242  int colorbufnum = 0,
243  int destbufnum = -1,
244  const UT_DimRect *from_area = NULL);
245 
246  /// Removes the attachment, and frees the renderbuffer or texture if
247  /// freeme is true.
248  bool detach(RE_Render *r,
249  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
250  int colorbufnum = 0,
251  bool freeme = false);
252 
254  RE_BufferAttachment buffer_type = RE_COLOR_BUFFER,
255  int colorbufnum = 0)
256  { return detach( r, buffer_type, colorbufnum ,true); }
257 
259  {
260  RE_BIND_NONE = 0, // Cannot be used as a parameter to bindFrameBuffer()
261  RE_BIND_READ = 1,
262  RE_BIND_DRAW = 2,
263  };
264 
265  /// Mostly for debug, this writes out the given attachment to an image file.
266  bool writeToFile(RE_Render *r, const char *filename,
267  RE_BufferAttachment buf, int colorbufnum = 0);
268 
269  void dumpConfig(RE_Render *r, FILE *);
270  // debug check.
271  static bool verifyBinding(RE_Render *r, RE_OGLFramebuffer *fbo,
272  RE_BufferBindMode bindmode = RE_BIND_DRAW);
273 
274  /// Raw GL ID of the FBO
275  GLuint getID() const { return myFramebuffer; }
276 
277 private:
278  bool initImpl(RE_Render *r, bool generate);
279 
280  bool privateReadFromBuffer(RE_Render *r,
281  re_FrameBufferAttachment *attach,
283  void *image_data);
284 
285  bool hasColorBuffer() const;
286  bool hasDepthBuffer() const;
287 
288  bool bindFrameBuffer(RE_Render *r,
289  RE_BufferBindMode bindmode = RE_BIND_DRAW);
290  void unbindFrameBuffer(RE_Render *r);
291  void restoreDrawBuffers(RE_Render *r, int mask);
292 
293  unsigned getGLBuffer() const;
294  RE_FBOStatus getREStatusFromGL(int glstatus);
295 
296  GLuint myFramebuffer;
297  fpreal32 myX;
298  fpreal32 myY;
299  int myWidth;
300  int myHeight;
301  bool myBegun;
302  bool myRestoreView;
303  RE_BufferBindMode myOpenMode;
305  UT_Array<re_FrameBufferAttachment *> myPushedAttachments;
306  int mySamples;
307  bool myReadFlag;
308  UT_String myName;
309  int myDrawBuffersMask;
310  int myReadBuffer;
311  bool myPrevMultisample;
312  bool mySavedMultisample;
313 
314  // State values: 0=invalid, 1=valid, -1=not known
315  int myValidState;
316  RE_FBOStatus myLastStatus;
317 };
318 
319 // Renderbuffers are buffers that can be attached to framebuffers instead of
320 // textures.
322 {
323 public:
326 
327  // These can be changed on an existing renderbuffer if not attached to a
328  // framebuffer.
329  void setBufferType(RE_BufferAttachment buffer_type);
330  void setFormat(RE_GPUType data_type, int vectorsize);
331  void setResolution(int w, int h);
332  void setSamples(int samples);
333 
334  // Creates the actual GL renderbuffer.
335  bool create(RE_Render *r);
336  void destroy();
337 
338  // Raw GL renderbuffer ID.
339  GLuint getID() const
340  { return myID; }
342  { return myFormatType; }
343 
344 private:
345  GLuint myID;
346  int myW;
347  int myH;
348  RE_GPUType myFormatType;
349  int myVectorSize;
350  int mySamples;
351  RE_BufferAttachment myBufferType;
352  bool myAttachedFlag;
353 
354  friend class RE_OGLFramebuffer;
355 };
356 
357 #endif
bool detachAndFree(RE_Render *r, RE_BufferAttachment buffer_type=RE_COLOR_BUFFER, int colorbufnum=0)
#define RE_API
Definition: RE_API.h:10
virtual bool init(RE_Render *r)=0
const char * getName()
GLint level
Definition: glcorearb.h:107
GLint GLuint mask
Definition: glcorearb.h:123
GLint y
Definition: glcorearb.h:102
unsigned int GLuint
Definition: cl.hpp:167
GLint GLsizei width
Definition: glcorearb.h:102
png_bytepp image
Definition: png.h:1849
RE_FBOStatus
RE_GPUType
Definition: RE_Types.h:42
GLuint getID() const
void interruptDraw(RE_Render *r)
GLuint GLuint end
Definition: glcorearb.h:474
RE_BufferAttachment
GLuint const GLchar * name
Definition: glcorearb.h:785
int getSamples() const
GLsizei samples
Definition: glcorearb.h:1297
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2539
GLint GLsizei GLsizei height
Definition: glcorearb.h:102
GLuint getID() const
Raw GL ID of the FBO.
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2001
double fpreal
Definition: SYS_Types.h:263
void resumeDraw(RE_Render *r)
RE_GPUType getFormatType() const
GLint GLenum GLint x
Definition: glcorearb.h:408
int getHeight() const
png_infop png_uint_32 int num
Definition: png.h:2158
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
RE_RenderBuf
Definition: RE_Types.h:399
GLboolean r
Definition: glcorearb.h:1221
bool isActiveDraw()
Returns true if the framebuffer is being drawn to.
float fpreal32
Definition: SYS_Types.h:184