0023457: Slow text rendering
[occt.git] / src / OpenGl / OpenGl_VertexBufferEditor.hxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 #ifndef _OpenGl_VertexBufferEditor_H__
20 #define _OpenGl_VertexBufferEditor_H__
21
22 #include <OpenGl_VertexBuffer.hxx>
23 #include <OpenGl_Context.hxx>
24
25 #include <NCollection_Array1.hxx>
26
27 //! Auxiliary class to iteratively modify data of existing VBO.
28 //! It provides iteration interface with delayed CPU->GPU memory transfer to avoid slow per-element data transfer.
29 //! User should explicitly call Flush() method to ensure that all data is transferred to VBO.
30 //! Temporary buffer on CPU side can be initialized with lesser capacity than  VBO
31 //! to allow re-usage of shared buffer with fixed size between VBOs.
32 //!
33 //! You should use NCollection_Vec2/NCollection_Vec3/NCollection_Vec4 with appropriate length
34 //! to instantiate this template and access elements in VBO.
35 //!
36 //! Notice that this technique designed for VBO streaming scenarios (when VBO is modified from time to time).
37 //! Also this class doesn't retrieve existing data from VBO - data transferred only in one direction!
38 //! In case of static data this is preferred to upload it within one call during VBO initialization.
39 template<typename theVec_t>
40 class OpenGl_VertexBufferEditor
41 {
42
43 public:
44
45   //! Creates empty editor
46   //! theTmpBufferLength - temporary buffer length
47   OpenGl_VertexBufferEditor (const Standard_Integer theTmpBufferLength = 0)
48   : myElemFrom (0),
49     myElemsNb (0),
50     myTmpBuffer (0, theTmpBufferLength > 0 ? (theTmpBufferLength - 1) : 2047) {}
51
52   //! Creates empty editor
53   //! theTmpBuffer       - pointer to temporary buffer
54   //! theTmpBufferLength - temporary buffer length
55   OpenGl_VertexBufferEditor (theVec_t*              theTmpBuffer,
56                              const Standard_Integer theTmpBufferLength)
57   : myElemFrom (0),
58     myElemsNb (0),
59     myTmpBuffer (theTmpBuffer[0], 0, theTmpBufferLength - 1) {}
60
61   //! Initialize editor for specified VBO.
62   //! theGlCtx - bound OpenGL context to edit VBO
63   //! theVbo   - VBO to edit
64   Standard_Boolean Init (const Handle(OpenGl_Context)&      theGlCtx,
65                          const Handle(OpenGl_VertexBuffer)& theVbo)
66   {
67     myGlCtx = theGlCtx;
68     myVbo   = theVbo;
69     if (myGlCtx.IsNull() || myVbo.IsNull() || !myVbo->IsValid() || myVbo->GetComponentsNb() != GLuint (theVec_t::Length()))
70     {
71       return Standard_False;
72     }
73
74     myElemFrom = myElemsNb = 0;
75     return Standard_True;
76   }
77
78   //! Modify current element in VBO.
79   theVec_t& Value()
80   {
81     return myTmpBuffer.ChangeValue (myElemsNb);
82   }
83
84   //! Move to the next position in VBO.
85   Standard_Boolean Next()
86   {
87     if (++myElemsNb > myTmpBuffer.Upper())
88     {
89       return Flush();
90     }
91     return Standard_True;
92   }
93
94   //! Push current data from local buffer to VBO.
95   Standard_Boolean Flush()
96   {
97     if (myElemsNb <= 0)
98     {
99       return Standard_True;
100     }
101
102     if (myVbo.IsNull()
103      || !myVbo->SubData (myGlCtx, myElemFrom, myElemsNb, &myTmpBuffer.Value (0)[0]))
104     {
105       // should never happens
106       return Standard_False;
107     }
108     myElemFrom += myElemsNb;
109     myElemsNb = 0;
110
111     return Standard_True;
112   }
113
114 private:
115
116   Handle(OpenGl_Context)       myGlCtx;     //!< handle to current OpenGL context
117   Handle(OpenGl_VertexBuffer)  myVbo;       //!< edited VBO
118   Standard_Integer             myElemFrom;  //!< element in VBO to upload from
119   Standard_Integer             myElemsNb;   //!< current element in temporary buffer
120   NCollection_Array1<theVec_t> myTmpBuffer; //!< temporary array
121
122 };
123
124 #endif // _OpenGl_VertexBufferEditor_H__