eb2f3d012ab5a8d11aad2f5442b40a80f17eaaf0
[platform/core/uifw/dali-core.git] / dali / internal / render / gl-resources / gpu-buffer.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/gl-resources/gpu-buffer.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23
24 namespace Dali
25 {
26
27 namespace Internal
28 {
29
30 namespace
31 {
32
33 /**
34  * Helper to get our drawmode enum as GL enum
35  * @param type to convert
36  * @return the corresponding GL enum or -1
37  */
38 inline GLenum ModeAsGlEnum( GpuBuffer::Usage type )
39 {
40   GLenum retval( -1 );
41   switch( type )
42   {
43     case GpuBuffer::STREAM_DRAW :
44     {
45       retval = GL_STREAM_DRAW;
46       break;
47     }
48     case GpuBuffer::STATIC_DRAW :
49     {
50       retval = GL_STATIC_DRAW;
51       break;
52     }
53     case GpuBuffer::DYNAMIC_DRAW :
54     {
55       retval = GL_DYNAMIC_DRAW;
56       break;
57     }
58   }
59   return retval;
60 }
61
62 }
63
64 GpuBuffer::GpuBuffer( Context& context )
65 : mContext( context ),
66   mCapacity( 0 ),
67   mSize( 0 ),
68   mBufferId( 0 ),
69   mBufferCreated( false )
70 {
71 }
72
73 GpuBuffer::~GpuBuffer()
74 {
75   // If we have a buffer then delete it.
76   if (mBufferId)
77   {
78     // If a buffer object that is currently bound is deleted, the binding reverts to 0
79     // (the absence of any buffer object, which reverts to client memory usage)
80     mContext.DeleteBuffers(1,&mBufferId);
81   }
82 }
83
84 /*
85  * Creates or updates the buffer data depending on whether it
86  * already exists or not.
87  */
88 void GpuBuffer::UpdateDataBuffer(GLsizeiptr size, const GLvoid *data, Usage usage, Target target)
89 {
90   DALI_ASSERT_DEBUG( size > 0 );
91   mSize = size;
92   // make sure we have a buffer name/id before uploading
93   if (mBufferId == 0)
94   {
95     mContext.GenBuffers(1,&mBufferId);
96     DALI_ASSERT_DEBUG(mBufferId);
97   }
98
99   GLenum glTargetEnum = GL_ARRAY_BUFFER;
100
101   if(ELEMENT_ARRAY_BUFFER == target)
102   {
103     glTargetEnum = GL_ELEMENT_ARRAY_BUFFER;
104   }
105   else if(TRANSFORM_FEEDBACK_BUFFER == target)
106   {
107     glTargetEnum = GL_TRANSFORM_FEEDBACK_BUFFER;
108   }
109
110   // make sure the buffer is bound, don't perform any checks because size may be zero
111   if(ARRAY_BUFFER == target)
112   {
113     mContext.BindArrayBuffer( mBufferId );
114   }
115   else if(ELEMENT_ARRAY_BUFFER == target)
116   {
117     mContext.BindElementArrayBuffer( mBufferId );
118   }
119   else if(TRANSFORM_FEEDBACK_BUFFER == target)
120   {
121     mContext.BindTransformFeedbackBuffer( mBufferId );
122   }
123
124   // if the buffer has already been created, just update the data providing it fits
125   if (mBufferCreated )
126   {
127     // if the data will fit in the existing buffer, just update it
128     if (size <= mCapacity )
129     {
130       mContext.BufferSubData( glTargetEnum, 0, size, data );
131     }
132     else
133     {
134       // create a new buffer of the larger size,
135       // gl should automatically deallocate the old buffer
136       mContext.BufferData( glTargetEnum, size, data, ModeAsGlEnum( usage ) );
137       mCapacity = size;
138     }
139   }
140   else
141   {
142     // create the buffer
143     mContext.BufferData( glTargetEnum, size, data, ModeAsGlEnum( usage ) );
144     mBufferCreated = true;
145     mCapacity = size;
146   }
147
148   if(ARRAY_BUFFER == target)
149   {
150     mContext.BindArrayBuffer( 0 );
151   }
152   else if(ELEMENT_ARRAY_BUFFER == target)
153   {
154     mContext.BindElementArrayBuffer( 0 );
155   }
156   else if(TRANSFORM_FEEDBACK_BUFFER == target)
157   {
158     mContext.BindTransformFeedbackBuffer( 0 );
159   }
160 }
161
162 void GpuBuffer::Bind(Target target) const
163 {
164   DALI_ASSERT_DEBUG(mCapacity);
165
166   if (target == ARRAY_BUFFER)
167   {
168     mContext.BindArrayBuffer(mBufferId);
169   }
170   else if (target == ELEMENT_ARRAY_BUFFER)
171   {
172     mContext.BindElementArrayBuffer(mBufferId);
173   }
174   else if (target == TRANSFORM_FEEDBACK_BUFFER)
175   {
176     mContext.BindTransformFeedbackBuffer(mBufferId);
177   }
178 }
179
180 bool GpuBuffer::BufferIsValid() const
181 {
182   return mBufferCreated && (0 != mCapacity );
183 }
184
185 void GpuBuffer::GlContextDestroyed()
186 {
187   // If the context is destroyed, GL would have released the buffer.
188   mCapacity = 0;
189   mSize = 0;
190   mBufferId = 0;
191   mBufferCreated = false;
192 }
193
194 } // namespace Internal
195
196 } //namespace Dali