Merge "[AT-SPI] Rework intercepting key events" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-buffer.cpp
1 /*
2  * Copyright (c) 2024 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     if(DALI_UNLIKELY(mBufferPtr == nullptr))
120     {
121       DALI_LOG_ERROR("malloc is failed. request malloc size : %u\n", mCreateInfo.size);
122     }
123   }
124 }
125
126 void Buffer::InitializeGPUBuffer()
127 {
128   auto context = mController.GetCurrentContext();
129   auto gl      = mController.GetGL();
130   if(!gl || !context)
131   {
132     return;
133   }
134
135   // If mBufferId is already set and we recycling the buffer (orphaning)
136   if(!mSetForGLRecycling && !mBufferId)
137   {
138     gl->GenBuffers(1, &mBufferId);
139   }
140   context->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
141   gl->BufferData(GL_ARRAY_BUFFER, GLsizeiptr(mCreateInfo.size), nullptr, GL_STATIC_DRAW);
142 }
143
144 void Buffer::DestroyResource()
145 {
146   // Destroy CPU allocated buffer
147   if(mCpuAllocated && mBufferPtr)
148   {
149     const auto allocators = GetCreateInfo().allocationCallbacks;
150     if(allocators)
151     {
152       allocators->freeCallback(mBufferPtr, allocators->userData);
153     }
154     else
155     {
156       free(mBufferPtr);
157     }
158     mBufferPtr = nullptr;
159   }
160   // Deestroy GPU allocation
161   else
162   {
163     auto gl = mController.GetGL();
164     if(gl)
165     {
166       gl->DeleteBuffers(1, &mBufferId);
167     }
168   }
169 }
170
171 void Buffer::DiscardResource()
172 {
173   mController.DiscardResource(this);
174 }
175
176 void Buffer::Bind(Graphics::BufferUsage bindingTarget) const
177 {
178   auto context = mController.GetCurrentContext();
179   auto gl      = mController.GetGL();
180   if(!gl || !context)
181   {
182     return;
183   }
184
185   // CPU allocated buffer may be bound only as Uniform Buffer
186   // on special binding point
187   if(mCpuAllocated && mBufferPtr)
188   {
189     if(bindingTarget == Graphics::BufferUsage::UNIFORM_BUFFER)
190     {
191       // TODO: probably nothing to do, the GLES Context
192       //       we may use CPU backed buffer for future data
193       //       transfers (copy operations)
194     }
195   }
196   else
197   {
198     switch(bindingTarget)
199     {
200       case Graphics::BufferUsage::VERTEX_BUFFER:
201       {
202         context->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
203         break;
204       }
205       case Graphics::BufferUsage::INDEX_BUFFER:
206       {
207         context->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferId);
208         break;
209       }
210       default:
211       {
212         // Nothing to do
213       }
214     }
215   }
216 }
217
218 } // namespace Dali::Graphics::GLES