Support multiple window rendering
[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(Context& context, 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   // make sure the buffer is bound, don't perform any checks because size may be zero
102   if(ARRAY_BUFFER == target)
103   {
104     context.BindArrayBuffer( mBufferId );
105   }
106   else if(ELEMENT_ARRAY_BUFFER == target)
107   {
108     glTargetEnum = GL_ELEMENT_ARRAY_BUFFER;
109     context.BindElementArrayBuffer( mBufferId );
110   }
111   else if(TRANSFORM_FEEDBACK_BUFFER == target)
112   {
113     glTargetEnum = GL_TRANSFORM_FEEDBACK_BUFFER;
114     context.BindTransformFeedbackBuffer( mBufferId );
115   }
116
117   // if the buffer has already been created, just update the data providing it fits
118   if (mBufferCreated )
119   {
120     // if the data will fit in the existing buffer, just update it
121     if (size <= mCapacity )
122     {
123       context.BufferSubData( glTargetEnum, 0, size, data );
124     }
125     else
126     {
127       // create a new buffer of the larger size,
128       // gl should automatically deallocate the old buffer
129       context.BufferData( glTargetEnum, size, data, ModeAsGlEnum( usage ) );
130       mCapacity = size;
131     }
132   }
133   else
134   {
135     // create the buffer
136     context.BufferData( glTargetEnum, size, data, ModeAsGlEnum( usage ) );
137     mBufferCreated = true;
138     mCapacity = size;
139   }
140
141   if(ARRAY_BUFFER == target)
142   {
143     context.BindArrayBuffer( 0 );
144   }
145   else if(ELEMENT_ARRAY_BUFFER == target)
146   {
147     context.BindElementArrayBuffer( 0 );
148   }
149   else if(TRANSFORM_FEEDBACK_BUFFER == target)
150   {
151     context.BindTransformFeedbackBuffer( 0 );
152   }
153 }
154
155 void GpuBuffer::Bind(Context& context, Target target) const
156 {
157   DALI_ASSERT_DEBUG(mCapacity);
158
159   if (target == ARRAY_BUFFER)
160   {
161     context.BindArrayBuffer(mBufferId);
162   }
163   else if (target == ELEMENT_ARRAY_BUFFER)
164   {
165     context.BindElementArrayBuffer(mBufferId);
166   }
167   else if (target == TRANSFORM_FEEDBACK_BUFFER)
168   {
169     context.BindTransformFeedbackBuffer(mBufferId);
170   }
171 }
172
173 bool GpuBuffer::BufferIsValid() const
174 {
175   return mBufferCreated && (0 != mCapacity );
176 }
177
178 void GpuBuffer::GlContextDestroyed()
179 {
180   // If the context is destroyed, GL would have released the buffer.
181   mCapacity = 0;
182   mSize = 0;
183   mBufferId = 0;
184   mBufferCreated = false;
185 }
186
187 } // namespace Internal
188
189 } //namespace Dali