Multi-level context caching
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-buffer.cpp
1 /*
2  * Copyright (c) 2021 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::InitializeResource()
54 {
55   // CPU allocated uniform buffer is a special "compatibility" mode
56   // for older GLES
57   if(mCpuAllocated && !mTransient)
58   {
59     InitializeCPUBuffer();
60   }
61   else if(!mCpuAllocated)
62   {
63     InitializeGPUBuffer();
64   }
65
66   return true;
67 }
68
69 void Buffer::InitializeCPUBuffer()
70 {
71   // Just allocate memory
72   // @TODO put better CPU memory management in place
73   const auto allocators = GetCreateInfo().allocationCallbacks;
74   if(allocators)
75   {
76     mBufferPtr = allocators->allocCallback(mCreateInfo.size, 0, allocators->userData);
77   }
78   else
79   {
80     mBufferPtr = malloc(mCreateInfo.size);
81   }
82 }
83
84 void Buffer::InitializeGPUBuffer()
85 {
86   auto context = mController.GetCurrentContext();
87   auto gl      = mController.GetGL();
88   if(!gl || !context)
89   {
90     return;
91   }
92
93   gl->GenBuffers(1, &mBufferId);
94   context->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
95   gl->BufferData(GL_ARRAY_BUFFER, mCreateInfo.size, nullptr, GL_STATIC_DRAW);
96 }
97
98 void Buffer::DestroyResource()
99 {
100   // Destroy CPU allocated buffer
101   if(mCpuAllocated && mBufferPtr)
102   {
103     const auto allocators = GetCreateInfo().allocationCallbacks;
104     if(allocators)
105     {
106       allocators->freeCallback(mBufferPtr, allocators->userData);
107     }
108     else
109     {
110       free(mBufferPtr);
111     }
112     mBufferPtr = nullptr;
113   }
114   // Deestroy GPU allocation
115   else
116   {
117     auto gl = mController.GetGL();
118     if(gl)
119     {
120       gl->DeleteBuffers(1, &mBufferId);
121     }
122   }
123 }
124
125 void Buffer::DiscardResource()
126 {
127   mController.DiscardResource(this);
128 }
129
130 void Buffer::Bind(Graphics::BufferUsage bindingTarget) const
131 {
132   auto context = mController.GetCurrentContext();
133   auto gl      = mController.GetGL();
134   if(!gl || !context)
135   {
136     return;
137   }
138
139   // CPU allocated buffer may be bound only as Uniform Buffer
140   // on special binding point
141   if(mCpuAllocated && mBufferPtr)
142   {
143     if(bindingTarget == Graphics::BufferUsage::UNIFORM_BUFFER)
144     {
145       // TODO: probably nothing to do, the GLES Context
146       //       we may use CPU backed buffer for future data
147       //       transfers (copy operations)
148     }
149   }
150   else
151   {
152     switch(bindingTarget)
153     {
154       case Graphics::BufferUsage::VERTEX_BUFFER:
155       {
156         context->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
157         break;
158       }
159       case Graphics::BufferUsage::INDEX_BUFFER:
160       {
161         context->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferId);
162         break;
163       }
164       default:
165       {
166         // Nothing to do
167       }
168     }
169   }
170 }
171
172 } // namespace Dali::Graphics::GLES