2 * Copyright (c) 2022 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/adaptor-framework/render-surface-interface.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/gl-abstraction.h>
24 #include <dali/integration-api/gl-defines.h>
25 #include <dali/integration-api/graphics-sync-abstraction.h>
26 #include <dali/internal/graphics/gles-impl/egl-sync-object.h>
27 #include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
28 #include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
29 #include <dali/internal/graphics/gles-impl/gles-graphics-program.h>
30 #include <dali/internal/graphics/gles-impl/gles-graphics-render-pass.h>
31 #include <dali/internal/graphics/gles-impl/gles-graphics-render-target.h>
32 #include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
33 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
34 #include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
35 #include <dali/internal/graphics/gles-impl/gles-sync-object.h>
36 #include <dali/internal/graphics/gles-impl/gles3-graphics-memory.h>
37 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
38 #include <dali/public-api/common/dali-common.h>
40 // Uncomment the following define to turn on frame dumping
41 //#define ENABLE_COMMAND_BUFFER_FRAME_DUMP 1
42 #include <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
45 namespace Dali::Graphics
50 * @brief Custom deleter for all Graphics objects created
51 * with use of the Controller.
53 * When Graphics object dies the unique pointer (Graphics::UniquePtr)
54 * doesn't destroy it directly but passes the ownership back
55 * to the Controller. The GLESDeleter is responsible for passing
56 * the object to the discard queue (by calling Resource::DiscardResource()).
61 GLESDeleter() = default;
63 void operator()(T* object)
65 // Discard resource (add it to discard queue)
66 object->DiscardResource();
71 * @brief Helper function allocating graphics object
73 * @param[in] info Create info structure
74 * @param[in] controller Controller object
75 * @param[out] out Unique pointer to the return object
77 template<class GLESType, class GfxCreateInfo, class T>
78 auto NewObject(const GfxCreateInfo& info, EglGraphicsController& controller, T&& oldObject)
81 using Type = typename T::element_type;
82 using UPtr = Graphics::UniquePtr<Type>;
83 if(info.allocationCallbacks)
85 auto* memory = info.allocationCallbacks->allocCallback(
88 info.allocationCallbacks->userData);
89 return UPtr(new(memory) GLESType(info, controller), GLESDeleter<GLESType>());
91 else // Use standard allocator
93 return UPtr(new GLESType(info, controller), GLESDeleter<GLESType>());
97 template<class T0, class T1>
98 T0* CastObject(T1* apiObject)
100 return static_cast<T0*>(apiObject);
103 // Maximum size of texture upload buffer.
104 const uint32_t TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB = 1;
108 EglGraphicsController::~EglGraphicsController()
110 while(!mPresentationCommandBuffers.empty())
112 auto presentCommandBuffer = const_cast<GLES::CommandBuffer*>(mPresentationCommandBuffers.front());
113 delete presentCommandBuffer;
114 mPresentationCommandBuffers.pop();
118 void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
120 DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #1\n");
121 mGlAbstraction = &glAbstraction;
122 mContext = std::make_unique<GLES::Context>(*this);
123 mCurrentContext = mContext.get();
126 void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction& syncImplementation,
127 Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
128 Internal::Adaptor::GraphicsInterface& graphicsInterface)
130 DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #2\n");
131 auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
133 mEglSyncImplementation = syncImplPtr;
134 mGlContextHelperAbstraction = &glContextHelperAbstraction;
135 mGraphics = &graphicsInterface;
138 void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
140 for(auto& cmdbuf : submitInfo.cmdBuffer)
142 // Push command buffers
143 mCommandQueue.push(static_cast<GLES::CommandBuffer*>(cmdbuf));
146 // If flush bit set, flush all pending tasks
147 if(submitInfo.flags & (0 | SubmitFlagBits::FLUSH))
153 void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
155 GLES::CommandBuffer* presentCommandBuffer{nullptr};
156 if(mPresentationCommandBuffers.empty())
158 CommandBufferCreateInfo info;
159 info.SetLevel(CommandBufferLevel::PRIMARY);
160 info.fixedCapacity = 1; // only one command
161 presentCommandBuffer = new GLES::CommandBuffer(info, *this);
165 presentCommandBuffer = const_cast<GLES::CommandBuffer*>(mPresentationCommandBuffers.front());
166 presentCommandBuffer->Reset();
167 mPresentationCommandBuffers.pop();
169 presentCommandBuffer->PresentRenderTarget(static_cast<GLES::RenderTarget*>(renderTarget));
170 SubmitInfo submitInfo;
171 submitInfo.cmdBuffer = {presentCommandBuffer};
172 submitInfo.flags = 0 | SubmitFlagBits::FLUSH;
173 SubmitCommandBuffers(submitInfo);
176 void EglGraphicsController::ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget)
178 mCurrentContext->InvalidateDepthStencilBuffers();
180 auto* rt = static_cast<GLES::RenderTarget*>(renderTarget);
181 if(rt->GetCreateInfo().surface)
183 auto* surfaceInterface = reinterpret_cast<Dali::RenderSurfaceInterface*>(rt->GetCreateInfo().surface);
184 surfaceInterface->MakeContextCurrent();
185 surfaceInterface->PostRender();
189 Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
191 DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
192 return *mGlAbstraction;
195 Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelperAbstraction()
197 DALI_ASSERT_DEBUG(mGlContextHelperAbstraction && "Graphics controller not initialized");
198 return *mGlContextHelperAbstraction;
201 Internal::Adaptor::EglSyncImplementation& EglGraphicsController::GetEglSyncImplementation()
203 DALI_ASSERT_DEBUG(mEglSyncImplementation && "Sync implementation not initialized");
204 return *mEglSyncImplementation;
207 Graphics::UniquePtr<CommandBuffer> EglGraphicsController::CreateCommandBuffer(
208 const CommandBufferCreateInfo& commandBufferCreateInfo,
209 Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
211 return NewObject<GLES::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
214 Graphics::UniquePtr<RenderPass> EglGraphicsController::CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass)
216 return NewObject<GLES::RenderPass>(renderPassCreateInfo, *this, std::move(oldRenderPass));
219 Graphics::UniquePtr<Texture>
220 EglGraphicsController::CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture)
222 return NewObject<GLES::Texture>(textureCreateInfo, *this, std::move(oldTexture));
225 Graphics::UniquePtr<Buffer> EglGraphicsController::CreateBuffer(
226 const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
228 return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
231 Graphics::UniquePtr<Framebuffer> EglGraphicsController::CreateFramebuffer(
232 const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer)
234 return NewObject<GLES::Framebuffer>(framebufferCreateInfo, *this, std::move(oldFramebuffer));
237 Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(
238 const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
240 // Create pipeline cache if needed
243 mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
246 return mPipelineCache->GetPipeline(pipelineCreateInfo, std::move(oldPipeline));
249 Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
250 const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
252 // Create program cache if needed
255 mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
258 return mPipelineCache->GetProgram(programCreateInfo, std::move(oldProgram));
261 Graphics::UniquePtr<Shader> EglGraphicsController::CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader)
263 return NewObject<GLES::Shader>(shaderCreateInfo, *this, std::move(oldShader));
266 Graphics::UniquePtr<Sampler> EglGraphicsController::CreateSampler(const SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Sampler>&& oldSampler)
268 return NewObject<GLES::Sampler>(samplerCreateInfo, *this, std::move(oldSampler));
271 Graphics::UniquePtr<RenderTarget> EglGraphicsController::CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget)
273 return NewObject<GLES::RenderTarget>(renderTargetCreateInfo, *this, std::move(oldRenderTarget));
276 Graphics::UniquePtr<SyncObject> EglGraphicsController::CreateSyncObject(const SyncObjectCreateInfo& syncObjectCreateInfo,
277 UniquePtr<SyncObject>&& oldSyncObject)
279 if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
281 return NewObject<EGL::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
285 return NewObject<GLES::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
289 const Graphics::Reflection& EglGraphicsController::GetProgramReflection(const Graphics::Program& program)
291 return static_cast<const Graphics::GLES::Program*>(&program)->GetReflection();
294 void EglGraphicsController::CreateSurfaceContext(Dali::RenderSurfaceInterface* surface)
296 std::unique_ptr<GLES::Context> context = std::make_unique<GLES::Context>(*this);
297 mSurfaceContexts.push_back(std::move(std::make_pair(surface, std::move(context))));
300 void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface)
302 mSurfaceContexts.erase(std::remove_if(
303 mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
304 mSurfaceContexts.end());
307 void EglGraphicsController::ActivateResourceContext()
309 mCurrentContext = mContext.get();
310 mCurrentContext->GlContextCreated();
313 void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
315 if(surface && mGraphics->IsResourceContextSupported())
317 auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) {
318 return (iter.first == surface);
321 if(iter != mSurfaceContexts.end())
323 mCurrentContext = iter->second.get();
324 mCurrentContext->GlContextCreated();
329 void EglGraphicsController::AddTexture(GLES::Texture& texture)
331 // Assuming we are on the correct context
332 mCreateTextureQueue.push(&texture);
335 void EglGraphicsController::AddBuffer(GLES::Buffer& buffer)
337 // Assuming we are on the correct context
338 mCreateBufferQueue.push(&buffer);
341 void EglGraphicsController::AddFramebuffer(GLES::Framebuffer& framebuffer)
343 // Assuming we are on the correct context
344 mCreateFramebufferQueue.push(&framebuffer);
347 void EglGraphicsController::ProcessDiscardQueues()
350 ProcessDiscardQueue<GLES::Texture>(mDiscardTextureQueue);
353 ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
355 // Process Framebuffers
356 ProcessDiscardQueue<GLES::Framebuffer>(mDiscardFramebufferQueue);
358 // Process RenderPass
359 ProcessDiscardQueue<GLES::RenderPass>(mDiscardRenderPassQueue);
361 // Process RenderTarget
362 ProcessDiscardQueue<GLES::RenderTarget>(mDiscardRenderTargetQueue);
365 ProcessDiscardQueue(mDiscardPipelineQueue);
368 ProcessDiscardQueue<GLES::Program>(mDiscardProgramQueue);
371 ProcessDiscardQueue<GLES::Shader>(mDiscardShaderQueue);
374 ProcessDiscardQueue<GLES::Sampler>(mDiscardSamplerQueue);
376 // Process command buffers
377 ProcessDiscardQueue<GLES::CommandBuffer>(mDiscardCommandBufferQueue);
380 void EglGraphicsController::ProcessCreateQueues()
383 ProcessCreateQueue(mCreateTextureQueue);
386 ProcessCreateQueue(mCreateBufferQueue);
388 // Process framebuffers
389 ProcessCreateQueue(mCreateFramebufferQueue);
392 void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer)
395 const auto commands = commandBuffer.GetCommands(count);
396 for(auto i = 0u; i < count; ++i)
398 auto& cmd = commands[i];
402 case GLES::CommandType::FLUSH:
404 // Nothing to do here
407 case GLES::CommandType::BIND_TEXTURES:
409 mCurrentContext->BindTextures(cmd.bindTextures.textureBindings.Ptr(), cmd.bindTextures.textureBindingsCount);
412 case GLES::CommandType::BIND_VERTEX_BUFFERS:
414 auto bindings = cmd.bindVertexBuffers.vertexBufferBindings.Ptr();
415 mCurrentContext->BindVertexBuffers(bindings, cmd.bindVertexBuffers.vertexBufferBindingsCount);
418 case GLES::CommandType::BIND_UNIFORM_BUFFER:
420 auto& bindings = cmd.bindUniformBuffers;
421 mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindingsCount ? bindings.uniformBufferBindings.Ptr() : nullptr, bindings.uniformBufferBindingsCount, bindings.standaloneUniformsBufferBinding);
424 case GLES::CommandType::BIND_INDEX_BUFFER:
426 mCurrentContext->BindIndexBuffer(cmd.bindIndexBuffer);
429 case GLES::CommandType::BIND_SAMPLERS:
433 case GLES::CommandType::BIND_PIPELINE:
435 auto pipeline = static_cast<const GLES::Pipeline*>(cmd.bindPipeline.pipeline);
436 mCurrentContext->BindPipeline(pipeline);
439 case GLES::CommandType::DRAW:
441 mCurrentContext->Flush(false, cmd.draw);
444 case GLES::CommandType::DRAW_INDEXED:
446 mCurrentContext->Flush(false, cmd.draw);
449 case GLES::CommandType::DRAW_INDEXED_INDIRECT:
451 mCurrentContext->Flush(false, cmd.draw);
454 case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
456 mGlAbstraction->Scissor(cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
459 case GLES::CommandType::SET_SCISSOR_TEST:
461 mCurrentContext->SetScissorTestEnabled(cmd.scissorTest.enable);
464 case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
466 mGlAbstraction->Viewport(cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
470 case GLES::CommandType::SET_COLOR_MASK:
472 mCurrentContext->ColorMask(cmd.colorMask.enabled);
475 case GLES::CommandType::CLEAR_STENCIL_BUFFER:
477 mCurrentContext->ClearStencilBuffer();
480 case GLES::CommandType::CLEAR_DEPTH_BUFFER:
482 mCurrentContext->ClearDepthBuffer();
486 case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
488 mCurrentContext->SetStencilTestEnable(cmd.stencilTest.enabled);
492 case GLES::CommandType::SET_STENCIL_FUNC:
494 mCurrentContext->StencilFunc(cmd.stencilFunc.compareOp,
495 cmd.stencilFunc.reference,
496 cmd.stencilFunc.compareMask);
500 case GLES::CommandType::SET_STENCIL_WRITE_MASK:
502 mCurrentContext->StencilMask(cmd.stencilWriteMask.mask);
506 case GLES::CommandType::SET_STENCIL_OP:
508 mCurrentContext->StencilOp(cmd.stencilOp.failOp,
509 cmd.stencilOp.depthFailOp,
510 cmd.stencilOp.passOp);
514 case GLES::CommandType::SET_DEPTH_COMPARE_OP:
516 mCurrentContext->SetDepthCompareOp(cmd.depth.compareOp);
519 case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
521 mCurrentContext->SetDepthTestEnable(cmd.depth.testEnabled);
524 case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
526 mCurrentContext->SetDepthWriteEnable(cmd.depth.writeEnabled);
530 case GLES::CommandType::BEGIN_RENDERPASS:
532 auto& renderTarget = *cmd.beginRenderPass.renderTarget;
533 const auto& targetInfo = renderTarget.GetCreateInfo();
535 if(targetInfo.surface)
537 // switch to surface context
538 mGraphics->ActivateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(targetInfo.surface));
540 else if(targetInfo.framebuffer)
542 // switch to resource context
543 mGraphics->ActivateResourceContext();
546 mCurrentContext->BeginRenderPass(cmd.beginRenderPass);
549 case GLES::CommandType::END_RENDERPASS:
551 mCurrentContext->EndRenderPass();
553 auto syncObject = const_cast<GLES::SyncObject*>(static_cast<const GLES::SyncObject*>(cmd.endRenderPass.syncObject));
556 syncObject->InitializeResource();
560 case GLES::CommandType::PRESENT_RENDER_TARGET:
562 ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent);
564 // The command buffer will be pushed into the queue of presentation command buffers
565 // for further reuse.
566 if(commandBuffer.GetCreateInfo().fixedCapacity == 1)
568 mPresentationCommandBuffers.push(&commandBuffer);
572 case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
574 // Process secondary command buffers
575 // todo: check validity of the secondaries
576 // there are operations which are illigal to be done
577 // within secondaries.
578 auto buffers = cmd.executeCommandBuffers.buffers.Ptr();
579 for(auto j = 0u; j < cmd.executeCommandBuffers.buffersCount; ++j)
581 auto& buf = buffers[j];
582 ProcessCommandBuffer(*static_cast<const GLES::CommandBuffer*>(buf));
586 case GLES::CommandType::DRAW_NATIVE:
588 auto* info = &cmd.drawNative.drawNativeInfo;
590 mCurrentContext->PrepareForNativeRendering();
592 CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
594 mCurrentContext->RestoreFromNativeRendering();
601 void EglGraphicsController::ProcessCommandQueues()
605 while(!mCommandQueue.empty())
607 auto cmdBuf = mCommandQueue.front();
609 DUMP_FRAME_COMMAND_BUFFER(cmdBuf);
610 ProcessCommandBuffer(*cmdBuf);
616 void EglGraphicsController::ProcessTextureUpdateQueue()
618 while(!mTextureUpdateRequests.empty())
620 TextureUpdateRequest& request = mTextureUpdateRequests.front();
622 auto& info = request.first;
623 auto& source = request.second;
625 if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
627 // GPU memory must be already allocated.
629 // Check if it needs conversion
630 auto* texture = static_cast<GLES::Texture*>(info.dstTexture);
631 const auto& createInfo = texture->GetCreateInfo();
632 auto srcFormat = GLES::GLTextureFormatType(info.srcFormat).format;
633 auto srcType = GLES::GLTextureFormatType(info.srcFormat).type;
634 auto destInternalFormat = GLES::GLTextureFormatType(createInfo.format).internalFormat;
635 auto destFormat = GLES::GLTextureFormatType(createInfo.format).format;
637 // From render-texture.cpp
638 const bool isSubImage(info.dstOffset2D.x != 0 || info.dstOffset2D.y != 0 ||
639 info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) ||
640 info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
642 auto* sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
643 std::vector<uint8_t> tempBuffer;
644 if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
646 // Convert RGB to RGBA if necessary.
647 texture->TryConvertPixelData(source.memorySource.memory, info.srcFormat, createInfo.format, info.srcSize, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer);
648 sourceBuffer = &tempBuffer[0];
649 srcFormat = destFormat;
650 srcType = GLES::GLTextureFormatType(createInfo.format).type;
653 // Calculate the maximum mipmap level for the texture
654 texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
656 GLenum bindTarget{GL_TEXTURE_2D};
657 GLenum target{GL_TEXTURE_2D};
659 if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
661 bindTarget = GL_TEXTURE_CUBE_MAP;
662 target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
665 mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
666 mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
670 if(!texture->IsCompressed())
672 mGlAbstraction->TexImage2D(target,
675 info.srcExtent2D.width,
676 info.srcExtent2D.height,
684 mGlAbstraction->CompressedTexImage2D(target,
687 info.srcExtent2D.width,
688 info.srcExtent2D.height,
696 if(!texture->IsCompressed())
698 mGlAbstraction->TexSubImage2D(target,
702 info.srcExtent2D.width,
703 info.srcExtent2D.height,
710 mGlAbstraction->CompressedTexSubImage2D(target,
714 info.srcExtent2D.width,
715 info.srcExtent2D.height,
721 // free staging memory
722 free(source.memorySource.memory);
726 // TODO: other sources
729 mTextureUpdateRequests.pop();
733 void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>& updateInfoList,
734 const std::vector<TextureUpdateSourceInfo>& sourceList)
737 for(auto& info : updateInfoList)
739 mTextureUpdateRequests.push(std::make_pair(info, sourceList[info.srcReference]));
740 auto& pair = mTextureUpdateRequests.back();
741 switch(pair.second.sourceType)
743 case Graphics::TextureUpdateSourceInfo::Type::MEMORY:
745 auto& info = pair.first;
746 auto& source = pair.second;
748 // allocate staging memory and copy the data
749 // TODO: using PBO with GLES3, this is just naive
752 char* stagingBuffer = reinterpret_cast<char*>(malloc(info.srcSize));
753 std::copy(&reinterpret_cast<char*>(source.memorySource.memory)[info.srcOffset],
754 reinterpret_cast<char*>(source.memorySource.memory) + info.srcSize,
757 mTextureUploadTotalCPUMemoryUsed += info.srcSize;
759 // store staging buffer
760 source.memorySource.memory = stagingBuffer;
763 case Graphics::TextureUpdateSourceInfo::Type::BUFFER:
765 // TODO, with PBO support
768 case Graphics::TextureUpdateSourceInfo::Type::TEXTURE:
770 // TODO texture 2 texture in-GPU copy
776 // If upload buffer exceeds maximum size, flush.
777 if(mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB * 1024)
780 mTextureUploadTotalCPUMemoryUsed = 0;
784 void EglGraphicsController::ProcessTextureMipmapGenerationQueue()
786 while(!mTextureMipmapGenerationRequests.empty())
788 auto* texture = mTextureMipmapGenerationRequests.front();
790 mCurrentContext->BindTexture(texture->GetGlTarget(), texture->GetTextureTypeId(), texture->GetGLTexture());
791 mCurrentContext->GenerateMipmap(texture->GetGlTarget());
793 mTextureMipmapGenerationRequests.pop();
797 void EglGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
799 mTextureMipmapGenerationRequests.push(static_cast<const GLES::Texture*>(&texture));
802 Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
804 mGraphics->ActivateResourceContext();
806 // Mapping buffer requires the object to be created NOW
807 // Workaround - flush now, otherwise there will be given a staging buffer
808 // in case when the buffer is not there yet
809 ProcessCreateQueues();
811 if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
813 return Graphics::UniquePtr<Memory>(new GLES::Memory2(mapInfo, *this));
817 return Graphics::UniquePtr<Memory>(new GLES::Memory3(mapInfo, *this));
821 bool EglGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData)
823 return static_cast<GLES::Program*>(&program)->GetImplementation()->GetParameter(parameterId, outData);
826 GLES::PipelineCache& EglGraphicsController::GetPipelineCache() const
828 return *mPipelineCache;
831 } // namespace Dali::Graphics