2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
21 #include <dali/integration-api/gl-abstraction.h>
22 #include <dali/integration-api/gl-defines.h>
23 #include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
24 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
25 #include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
27 #include <dali/public-api/common/dali-common.h>
29 namespace Dali::Graphics
34 * @brief Custom deleter for all Graphics objects created
35 * with use of the Controller.
37 * When Graphics object dies the unique pointer (Graphics::UniquePtr)
38 * doesn't destroy it directly but passes the ownership back
39 * to the Controller. The GLESDeleter is responsible for passing
40 * the object to the discard queue (by calling Resource::DiscardResource()).
45 GLESDeleter() = default;
47 void operator()(T* object)
49 // Discard resource (add it to discard queue)
50 object->DiscardResource();
55 * @brief Helper function allocating graphics object
57 * @param[in] info Create info structure
58 * @param[in] controller Controller object
59 * @param[out] out Unique pointer to the return object
61 template<class GLESType, class GfxCreateInfo, class T>
62 auto NewObject(const GfxCreateInfo& info, EglGraphicsController& controller, T&& oldObject)
65 using Type = typename T::element_type;
66 using UPtr = Graphics::UniquePtr<Type>;
67 if(info.allocationCallbacks)
69 auto* memory = info.allocationCallbacks->allocCallback(
72 info.allocationCallbacks->userData);
73 return UPtr(new(memory) GLESType(info, controller), GLESDeleter<GLESType>());
75 else // Use standard allocator
77 return UPtr(new GLESType(info, controller), GLESDeleter<GLESType>());
81 template<class T0, class T1>
82 T0* CastObject(T1* apiObject)
84 return static_cast<T0*>(apiObject);
89 void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
91 mGlAbstraction = &glAbstraction;
94 void EglGraphicsController::Initialize(Integration::GlSyncAbstraction& glSyncAbstraction,
95 Integration::GlContextHelperAbstraction& glContextHelperAbstraction)
97 mGlSyncAbstraction = &glSyncAbstraction;
98 mGlContextHelperAbstraction = &glContextHelperAbstraction;
101 void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
103 for(auto& cmdbuf : submitInfo.cmdBuffer)
105 // Push command buffers
106 mCommandQueue.push(static_cast<GLES::CommandBuffer*>(cmdbuf));
109 // If flush bit set, flush all pending tasks
110 if(submitInfo.flags & (0 | SubmitFlagBits::FLUSH))
116 Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
118 DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
119 return *mGlAbstraction;
122 Integration::GlSyncAbstraction& EglGraphicsController::GetGlSyncAbstraction()
124 DALI_ASSERT_DEBUG(mGlSyncAbstraction && "Graphics controller not initialized");
125 return *mGlSyncAbstraction;
128 Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelperAbstraction()
130 DALI_ASSERT_DEBUG(mGlContextHelperAbstraction && "Graphics controller not initialized");
131 return *mGlContextHelperAbstraction;
134 Graphics::UniquePtr<CommandBuffer>
135 EglGraphicsController::CreateCommandBuffer(const CommandBufferCreateInfo& commandBufferCreateInfo,
136 Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
138 return NewObject<GLES::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
141 Graphics::UniquePtr<Texture>
142 EglGraphicsController::CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture)
144 return NewObject<GLES::Texture>(textureCreateInfo, *this, std::move(oldTexture));
147 Graphics::UniquePtr<Buffer>
148 EglGraphicsController::CreateBuffer(const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
150 return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
153 void EglGraphicsController::AddTexture(GLES::Texture& texture)
155 // Assuming we are on the correct context
156 mCreateTextureQueue.push(&texture);
159 void EglGraphicsController::AddBuffer(GLES::Buffer& buffer)
161 // Assuming we are on the correct context
162 mCreateBufferQueue.push(&buffer);
165 void EglGraphicsController::ProcessDiscardQueues()
168 ProcessDiscardQueue<GLES::Texture>(mDiscardTextureQueue);
171 ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
174 void EglGraphicsController::ProcessCreateQueues()
177 ProcessCreateQueue(mCreateTextureQueue);
180 ProcessCreateQueue(mCreateBufferQueue);
183 void EglGraphicsController::ProcessCommandQueues()
185 while(!mCommandQueue.empty())
187 auto cmdBuf = mCommandQueue.front();
190 for(auto& cmd : cmdBuf->GetCommands())
195 case GLES::CommandType::FLUSH:
201 case GLES::CommandType::BIND_TEXTURES:
203 for(auto& binding : cmd.bindTextures.textureBindings)
205 static_cast<const GLES::Texture*>(binding.texture)->Bind(binding);
210 case GLES::CommandType::BIND_VERTEX_BUFFERS:
212 auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
214 for(auto& binding : bindings)
216 // TODO: this is all wrong, just hack to work with current DALi
219 CastObject<const GLES::Buffer>(binding.buffer)->Bind(BufferUsage::VERTEX_BUFFER);
226 case GLES::CommandType::BIND_INDEX_BUFFER:
228 auto buffer = static_cast<const GLES::Buffer*>(cmd.bindIndexBuffer.buffer);
229 buffer->Bind(BufferUsage::INDEX_BUFFER);
232 case GLES::CommandType::BIND_SAMPLERS:
241 void EglGraphicsController::ProcessTextureUpdateQueue()
243 while(!mTextureUpdateRequests.empty())
245 TextureUpdateRequest& request = mTextureUpdateRequests.front();
247 auto& info = request.first;
248 auto& source = request.second;
250 if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
252 // GPU memory must be already allocated (glTexImage2D())
253 auto* texture = static_cast<GLES::Texture*>(info.dstTexture);
254 const auto& createInfo = texture->GetCreateInfo();
256 mGlAbstraction->BindTexture(GL_TEXTURE_2D, texture->GetGLTexture());
257 mGlAbstraction->TexSubImage2D(GL_TEXTURE_2D,
261 info.srcExtent2D.width,
262 info.srcExtent2D.height,
263 GLES::GLTextureFormatType(createInfo.format).format,
264 GLES::GLTextureFormatType(createInfo.format).type,
265 source.memorySource.memory);
267 // free staging memory
268 free(source.memorySource.memory);
272 // TODO: other sources
275 mTextureUpdateRequests.pop();
279 void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>& updateInfoList,
280 const std::vector<TextureUpdateSourceInfo>& sourceList)
283 for(auto& info : updateInfoList)
285 mTextureUpdateRequests.push(std::make_pair(info, sourceList[info.srcReference]));
286 auto& pair = mTextureUpdateRequests.back();
287 switch(pair.second.sourceType)
289 case Graphics::TextureUpdateSourceInfo::Type::MEMORY:
291 auto& info = pair.first;
292 auto& source = pair.second;
294 // allocate staging memory and copy the data
295 // TODO: using PBO with GLES3, this is just naive
298 char* stagingBuffer = reinterpret_cast<char*>(malloc(info.srcSize));
299 std::copy(&reinterpret_cast<char*>(source.memorySource.memory)[info.srcOffset],
300 reinterpret_cast<char*>(source.memorySource.memory) + info.srcSize,
303 // store staging buffer
304 source.memorySource.memory = stagingBuffer;
306 printf("Update ptr: %p\n", source.memorySource.memory);
309 case Graphics::TextureUpdateSourceInfo::Type::BUFFER:
311 // TODO, with PBO support
314 case Graphics::TextureUpdateSourceInfo::Type::TEXTURE:
316 // TODO texture 2 texture in-GPU copy
323 Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
325 // Mapping buffer requires the object to be created NOW
326 // Workaround - flush now, otherwise there will be given a staging buffer
327 // in case when the buffer is not there yet
328 ProcessCreateQueues();
330 return Graphics::UniquePtr<Memory>(new GLES::Memory(mapInfo, *this));
333 } // namespace Dali::Graphics