Added recycling of Graphics resources.
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-buffer.cpp
1 /*
2  * Copyright (c) 2023 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 "gles-graphics-buffer.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/gl-defines.h>
24
25 // INTERNAL INCLUDES
26 #include "egl-graphics-controller.h"
27
28 namespace Dali::Graphics::GLES
29 {
30 Buffer::Buffer(const Graphics::BufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
31 : BufferResource(createInfo, controller)
32 {
33   // Check if buffer is CPU allocated
34   if(((0 | BufferUsage::UNIFORM_BUFFER) & mCreateInfo.usage) &&
35      (0 | BufferPropertiesFlagBit::CPU_ALLOCATED) & mCreateInfo.propertiesFlags)
36   {
37     // cpu allocated buffer
38     mCpuAllocated = true;
39   }
40
41   // Check if buffer is transient
42   if((0 | BufferPropertiesFlagBit::TRANSIENT_MEMORY) & mCreateInfo.propertiesFlags)
43   {
44     // memory is transient, may be lazily allocated when
45     // mapped, together with cpu allocated it may create emulated uniform
46     // buffer in this implementation
47     mTransient = true;
48   }
49
50   controller.AddBuffer(*this);
51 }
52
53 bool Buffer::TryRecycle(const Graphics::BufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
54 {
55   // Compare whether specs are same and the buffer is allocated
56   mSetForGLRecycling = false;
57
58   // if different buffer spec, we need new buffer
59   if(!(createInfo.size == mCreateInfo.size
60      && createInfo.allocationCallbacks == mCreateInfo.allocationCallbacks
61      && createInfo.propertiesFlags == mCreateInfo.propertiesFlags
62      && createInfo.usage == mCreateInfo.usage
63      && createInfo.nextExtension == mCreateInfo.nextExtension ))
64   {
65     return false;
66   }
67
68   // GL resource hasn't been allocated yet, we need new buffer
69   if(mBufferId == 0)
70   {
71     return false;
72   }
73
74   // Make sure the buffer will be reinitialized
75   controller.AddBuffer(*this);
76
77   mSetForGLRecycling = true;
78
79   return true;
80 }
81
82 bool Buffer::InitializeResource()
83 {
84   // CPU allocated uniform buffer is a special "compatibility" mode
85   // for older GLES
86   if(mCpuAllocated && !mTransient)
87   {
88     InitializeCPUBuffer();
89   }
90   else if(!mCpuAllocated)
91   {
92     InitializeGPUBuffer();
93   }
94
95   // make sure recycling mode is disabled after (re)initializing resource
96   mSetForGLRecycling = false;
97   return true;
98 }
99
100 void Buffer::InitializeCPUBuffer()
101 {
102   // Just allocate memory
103   // @TODO put better CPU memory management in place
104   const auto allocators = GetCreateInfo().allocationCallbacks;
105
106   // Early out if we recycle the buffer
107   if(mBufferPtr && mSetForGLRecycling)
108   {
109     return;
110   }
111
112   if(allocators)
113   {
114     mBufferPtr = allocators->allocCallback(mCreateInfo.size, 0, allocators->userData);
115   }
116   else
117   {
118     mBufferPtr = malloc(mCreateInfo.size);
119   }
120 }
121
122 void Buffer::InitializeGPUBuffer()
123 {
124   auto context = mController.GetCurrentContext();
125   auto gl      = mController.GetGL();
126   if(!gl || !context)
127   {
128     return;
129   }
130
131   // If mBufferId is already set and we recycling the buffer (orphaning)
132   if(!mSetForGLRecycling && !mBufferId)
133   {
134     gl->GenBuffers(1, &mBufferId);
135   }
136   context->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
137   gl->BufferData(GL_ARRAY_BUFFER, GLsizeiptr(mCreateInfo.size), nullptr, GL_STATIC_DRAW);
138 }
139
140 void Buffer::DestroyResource()
141 {
142   // Destroy CPU allocated buffer
143   if(mCpuAllocated && mBufferPtr)
144   {
145     const auto allocators = GetCreateInfo().allocationCallbacks;
146     if(allocators)
147     {
148       allocators->freeCallback(mBufferPtr, allocators->userData);
149     }
150     else
151     {
152       free(mBufferPtr);
153     }
154     mBufferPtr = nullptr;
155   }
156   // Deestroy GPU allocation
157   else
158   {
159     auto gl = mController.GetGL();
160     if(gl)
161     {
162       gl->DeleteBuffers(1, &mBufferId);
163     }
164   }
165 }
166
167 void Buffer::DiscardResource()
168 {
169   mController.DiscardResource(this);
170 }
171
172 void Buffer::Bind(Graphics::BufferUsage bindingTarget) const
173 {
174   auto context = mController.GetCurrentContext();
175   auto gl      = mController.GetGL();
176   if(!gl || !context)
177   {
178     return;
179   }
180
181   // CPU allocated buffer may be bound only as Uniform Buffer
182   // on special binding point
183   if(mCpuAllocated && mBufferPtr)
184   {
185     if(bindingTarget == Graphics::BufferUsage::UNIFORM_BUFFER)
186     {
187       // TODO: probably nothing to do, the GLES Context
188       //       we may use CPU backed buffer for future data
189       //       transfers (copy operations)
190     }
191   }
192   else
193   {
194     switch(bindingTarget)
195     {
196       case Graphics::BufferUsage::VERTEX_BUFFER:
197       {
198         context->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
199         break;
200       }
201       case Graphics::BufferUsage::INDEX_BUFFER:
202       {
203         context->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferId);
204         break;
205       }
206       default:
207       {
208         // Nothing to do
209       }
210     }
211   }
212 }
213
214 } // namespace Dali::Graphics::GLES