1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2013-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 #ifndef _OpenGl_Buffer_H__
16 #define _OpenGl_Buffer_H__
17 
18 #include <OpenGl_Resource.hxx>
19 #include <TCollection_AsciiString.hxx>
20 
21 //! Buffer Object - is a general storage object for arbitrary data (see sub-classes).
22 class OpenGl_Buffer : public OpenGl_Resource
23 {
24   DEFINE_STANDARD_RTTIEXT(OpenGl_Buffer, OpenGl_Resource)
25 public:
26 
27   //! Helpful constants
28   static const unsigned int NO_BUFFER = 0;
29 
30   //! Format VBO target enumeration value.
31   Standard_EXPORT static TCollection_AsciiString FormatTarget (unsigned int theTarget);
32 
33 public:
34 
35   //! Create uninitialized buffer.
36   Standard_EXPORT OpenGl_Buffer();
37 
38   //! Destroy object.
39   Standard_EXPORT virtual ~OpenGl_Buffer();
40 
41   //! Return buffer target.
42   virtual unsigned int GetTarget() const = 0;
43 
44   //! Return TRUE if this is a virtual (for backward compatibility) VBO object.
IsVirtual() const45   virtual bool IsVirtual() const { return false; }
46 
47   //! @return true if current object was initialized
IsValid() const48   bool IsValid() const { return myBufferId != NO_BUFFER; }
49 
50   //! @return the number of components per generic vertex attribute.
GetComponentsNb() const51   unsigned int GetComponentsNb() const { return myComponentsNb; }
52 
53   //! @return number of vertex attributes / number of vertices specified within ::Init()
GetElemsNb() const54   Standard_Integer GetElemsNb() const { return myElemsNb; }
55 
56   //! Overrides the number of vertex attributes / number of vertexes.
57   //! It is up to user specifying this number correct (e.g. below initial value)!
SetElemsNb(Standard_Integer theNbElems)58   void SetElemsNb (Standard_Integer theNbElems) { myElemsNb = theNbElems; }
59 
60   //! @return data type of each component in the array.
GetDataType() const61   unsigned int GetDataType() const { return myDataType; }
62 
63   //! @return offset to data, NULL by default
GetDataOffset() const64   Standard_Byte* GetDataOffset() const { return myOffset; }
65 
66   //! Creates buffer object name (id) if not yet generated.
67   //! Data should be initialized by another method.
68   Standard_EXPORT virtual bool Create (const Handle(OpenGl_Context)& theGlCtx);
69 
70   //! Destroy object - will release GPU memory if any.
71   Standard_EXPORT virtual void Release (OpenGl_Context* theGlCtx) Standard_OVERRIDE;
72 
73   //! Bind this buffer object.
74   Standard_EXPORT virtual void Bind (const Handle(OpenGl_Context)& theGlCtx) const;
75 
76   //! Unbind this buffer object.
77   Standard_EXPORT virtual void Unbind (const Handle(OpenGl_Context)& theGlCtx) const;
78 
79   //! Notice that buffer object will be unbound after this call.
80   //! @param theComponentsNb [in] specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
81   //! @param theElemsNb      [in] elements count;
82   //! @param theData         [in] pointer to float data (vertices/normals etc.).
83   Standard_EXPORT bool Init (const Handle(OpenGl_Context)& theGlCtx,
84                              const unsigned int     theComponentsNb,
85                              const Standard_Integer theElemsNb,
86                              const float*   theData);
87 
88   //! Notice that buffer object will be unbound after this call.
89   //! @param theComponentsNb [in] specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
90   //! @param theElemsNb      [in] elements count;
91   //! @param theData         [in] pointer to unsigned int data (indices etc.).
92   Standard_EXPORT bool Init (const Handle(OpenGl_Context)& theGlCtx,
93                              const unsigned int     theComponentsNb,
94                              const Standard_Integer theElemsNb,
95                              const unsigned int* theData);
96 
97   //! Notice that buffer object will be unbound after this call.
98   //! @param theComponentsNb [in] specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
99   //! @param theElemsNb      [in] elements count;
100   //! @param theData         [in] pointer to unsigned short data (indices etc.).
101   Standard_EXPORT bool Init (const Handle(OpenGl_Context)& theGlCtx,
102                              const unsigned int     theComponentsNb,
103                              const Standard_Integer theElemsNb,
104                              const unsigned short*  theData);
105 
106   //! Notice that buffer object will be unbound after this call.
107   //! @param theComponentsNb [in] specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
108   //! @param theElemsNb      [in] elements count;
109   //! @param theData         [in] pointer to Standard_Byte data (indices/colors etc.).
110   Standard_EXPORT bool Init (const Handle(OpenGl_Context)& theGlCtx,
111                              const unsigned int     theComponentsNb,
112                              const Standard_Integer theElemsNb,
113                              const Standard_Byte*   theData);
114 
115   //! Notice that buffer object will be unbound after this call.
116   //! Function replaces portion of data within this buffer object using glBufferSubData().
117   //! The buffer object should be initialized before call.
118   //! @param theElemFrom [in] element id from which replace buffer data (>=0);
119   //! @param theElemsNb  [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
120   //! @param theData     [in] pointer to float data.
121   Standard_EXPORT bool SubData (const Handle(OpenGl_Context)& theGlCtx,
122                                 const Standard_Integer theElemFrom,
123                                 const Standard_Integer theElemsNb,
124                                 const float* theData);
125 
126   //! Read back buffer sub-range.
127   //! Notice that buffer object will be unbound after this call.
128   //! Function reads portion of data from this buffer object using glGetBufferSubData().
129   //! @param theElemFrom [in] element id from which replace buffer data (>=0);
130   //! @param theElemsNb  [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
131   //! @param theData    [out] destination pointer to float data.
132   Standard_EXPORT bool GetSubData (const Handle(OpenGl_Context)& theGlCtx,
133                                    const Standard_Integer theElemFrom,
134                                    const Standard_Integer theElemsNb,
135                                    float* theData);
136 
137   //! Notice that buffer object will be unbound after this call.
138   //! Function replaces portion of data within this buffer object using glBufferSubData().
139   //! The buffer object should be initialized before call.
140   //! @param theElemFrom [in] element id from which replace buffer data (>=0);
141   //! @param theElemsNb  [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
142   //! @param theData     [in] pointer to unsigned int data.
143   Standard_EXPORT bool SubData (const Handle(OpenGl_Context)& theGlCtx,
144                                 const Standard_Integer theElemFrom,
145                                 const Standard_Integer theElemsNb,
146                                 const unsigned int* theData);
147 
148   //! Read back buffer sub-range.
149   //! Notice that buffer object will be unbound after this call.
150   //! Function reads portion of data from this buffer object using glGetBufferSubData().
151   //! @param theElemFrom [in] element id from which replace buffer data (>=0);
152   //! @param theElemsNb  [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
153   //! @param theData    [out] destination pointer to unsigned int data.
154   Standard_EXPORT bool GetSubData (const Handle(OpenGl_Context)& theGlCtx,
155                                    const Standard_Integer theElemFrom,
156                                    const Standard_Integer theElemsNb,
157                                    unsigned int* theData);
158 
159   //! Notice that buffer object will be unbound after this call.
160   //! Function replaces portion of data within this buffer object using glBufferSubData().
161   //! The buffer object should be initialized before call.
162   //! @param theElemFrom [in] element id from which replace buffer data (>=0);
163   //! @param theElemsNb  [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
164   //! @param theData     [in] pointer to unsigned short data.
165   Standard_EXPORT bool SubData (const Handle(OpenGl_Context)& theGlCtx,
166                                 const Standard_Integer theElemFrom,
167                                 const Standard_Integer theElemsNb,
168                                 const unsigned short*  theData);
169 
170   //! Read back buffer sub-range.
171   //! Notice that buffer object will be unbound after this call.
172   //! Function reads portion of data from this buffer object using glGetBufferSubData().
173   //! @param theElemFrom [in] element id from which replace buffer data (>=0);
174   //! @param theElemsNb  [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
175   //! @param theData    [out] destination pointer to unsigned short data.
176   Standard_EXPORT bool GetSubData (const Handle(OpenGl_Context)& theGlCtx,
177                                    const Standard_Integer theElemFrom,
178                                    const Standard_Integer theElemsNb,
179                                    unsigned short* theData);
180 
181   //! Notice that buffer object will be unbound after this call.
182   //! Function replaces portion of data within this buffer object using glBufferSubData().
183   //! The buffer object should be initialized before call.
184   //! @param theElemFrom [in] element id from which replace buffer data (>=0);
185   //! @param theElemsNb  [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
186   //! @param theData     [in] pointer to Standard_Byte data.
187   Standard_EXPORT bool SubData (const Handle(OpenGl_Context)& theGlCtx,
188                                 const Standard_Integer theElemFrom,
189                                 const Standard_Integer theElemsNb,
190                                 const Standard_Byte* theData);
191 
192   //! Read back buffer sub-range.
193   //! Notice that buffer object will be unbound after this call.
194   //! Function reads portion of data from this buffer object using glGetBufferSubData().
195   //! @param theElemFrom [in] element id from which replace buffer data (>=0);
196   //! @param theElemsNb  [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
197   //! @param theData    [out] destination pointer to Standard_Byte data.
198   Standard_EXPORT bool GetSubData (const Handle(OpenGl_Context)& theGlCtx,
199                                    const Standard_Integer theElemFrom,
200                                    const Standard_Integer theElemsNb,
201                                    Standard_Byte* theData);
202 
203 public: //! @name advanced methods
204 
205   //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
EstimatedDataSize() const206   virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE
207   {
208     return IsValid()
209          ? sizeOfGlType (myDataType) * myComponentsNb * myElemsNb
210          : 0;
211   }
212 
213   //! @return size of specified GL type
214   Standard_EXPORT static size_t sizeOfGlType (unsigned int theType);
215 
216   //! Initialize buffer with new data.
217   Standard_EXPORT virtual bool init (const Handle(OpenGl_Context)& theGlCtx,
218                                      const unsigned int     theComponentsNb,
219                                      const Standard_Integer theElemsNb,
220                                      const void*            theData,
221                                      const unsigned int     theDataType,
222                                      const Standard_Integer theStride);
223 
224   //! Initialize buffer with new data.
init(const Handle (OpenGl_Context)& theGlCtx,const unsigned int theComponentsNb,const Standard_Integer theElemsNb,const void * theData,const unsigned int theDataType)225   bool init (const Handle(OpenGl_Context)& theGlCtx,
226              const unsigned int     theComponentsNb,
227              const Standard_Integer theElemsNb,
228              const void*            theData,
229              const unsigned int     theDataType)
230   {
231     return init (theGlCtx, theComponentsNb, theElemsNb, theData, theDataType,
232                  Standard_Integer(theComponentsNb) * Standard_Integer(sizeOfGlType (theDataType)));
233   }
234 
235   //! Update part of the buffer with new data.
236   Standard_EXPORT virtual bool subData (const Handle(OpenGl_Context)& theGlCtx,
237                                         const Standard_Integer theElemFrom,
238                                         const Standard_Integer theElemsNb,
239                                         const void*            theData,
240                                         const unsigned int     theDataType);
241 
242   //! Read back buffer sub-range.
243   Standard_EXPORT virtual bool getSubData (const Handle(OpenGl_Context)& theGlCtx,
244                                            const Standard_Integer theElemFrom,
245                                            const Standard_Integer theElemsNb,
246                                            void*                  theData,
247                                            const unsigned int     theDataType);
248 
249 public:
250 
251   //! Dumps the content of me into the stream
252   Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE;
253 
254 protected:
255 
256   //! Binds a buffer object to an indexed buffer target.
257   //! Wrapper for glBindBufferBase().
258   //! @param theGlCtx [in] active OpenGL context
259   //! @param theIndex [in] index to bind
260   Standard_EXPORT void BindBufferBase (const Handle(OpenGl_Context)& theGlCtx,
261                                        unsigned int theIndex);
262 
263   //! Unbinds a buffer object from an indexed buffer target.
264   //! Wrapper for glBindBufferBase().
265   //! @param theGlCtx [in] active OpenGL context
266   //! @param theIndex [in] index to bind
267   Standard_EXPORT void UnbindBufferBase (const Handle(OpenGl_Context)& theGlCtx,
268                                          unsigned int theIndex);
269 
270   //! Binds a buffer object to an indexed buffer target with specified offset and size.
271   //! Wrapper for glBindBufferRange().
272   //! @param theGlCtx  [in] active OpenGL context
273   //! @param theIndex  [in] index to bind (@sa GL_MAX_UNIFORM_BUFFER_BINDINGS in case of uniform buffer)
274   //! @param theOffset [in] offset within the buffer (@sa GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT in case of uniform buffer)
275   //! @param theSize   [in] sub-section length starting from offset
276   Standard_EXPORT void BindBufferRange (const Handle(OpenGl_Context)& theGlCtx,
277                                         unsigned int   theIndex,
278                                         const intptr_t theOffset,
279                                         const size_t   theSize);
280 
281 protected:
282 
283   Standard_Byte*   myOffset;       //!< offset to data
284   unsigned int     myBufferId;     //!< VBO name (index)
285   unsigned int     myComponentsNb; //!< Number of components per generic vertex attribute, must be 1, 2, 3, or 4
286   Standard_Integer myElemsNb;      //!< Number of vertex attributes / number of vertices
287   unsigned int     myDataType;     //!< Data type (GL_FLOAT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE etc.)
288 
289 };
290 
291 DEFINE_STANDARD_HANDLE(OpenGl_Buffer, OpenGl_Resource)
292 
293 #endif // _OpenGl_Buffer_H__
294