2 * Copyright (c) 2023 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/public-api/common/dali-common.h>
24 #include <dali/integration-api/adaptor-framework/render-surface-interface.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/gl-abstraction.h>
27 #include <dali/integration-api/gl-defines.h>
28 #include <dali/integration-api/graphics-sync-abstraction.h>
29 #include <dali/integration-api/pixel-data-integ.h>
30 #include <dali/internal/graphics/gles-impl/egl-sync-object.h>
31 #include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
32 #include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
33 #include <dali/internal/graphics/gles-impl/gles-graphics-program.h>
34 #include <dali/internal/graphics/gles-impl/gles-graphics-render-pass.h>
35 #include <dali/internal/graphics/gles-impl/gles-graphics-render-target.h>
36 #include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
37 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
38 #include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
39 #include <dali/internal/graphics/gles-impl/gles-sync-object.h>
40 #include <dali/internal/graphics/gles-impl/gles3-graphics-memory.h>
41 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
43 #include <dali/internal/graphics/gles/egl-graphics.h>
47 // Uncomment the following define to turn on frame dumping
48 //#define ENABLE_COMMAND_BUFFER_FRAME_DUMP 1
49 #include <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
52 namespace Dali::Graphics
57 * @brief Custom deleter for all Graphics objects created
58 * with use of the Controller.
60 * When Graphics object dies the unique pointer (Graphics::UniquePtr)
61 * doesn't destroy it directly but passes the ownership back
62 * to the Controller. The GLESDeleter is responsible for passing
63 * the object to the discard queue (by calling Resource::DiscardResource()).
68 GLESDeleter() = default;
70 void operator()(T* object)
72 // Discard resource (add it to discard queue)
73 object->DiscardResource();
78 * @brief Helper function allocating graphics object
80 * @param[in] info Create info structure
81 * @param[in] controller Controller object
82 * @param[out] out Unique pointer to the return object
84 template<class GLESType, class GfxCreateInfo, class T>
85 auto NewObject(const GfxCreateInfo& info, EglGraphicsController& controller, T&& oldObject)
88 using Type = typename T::element_type;
89 using UPtr = Graphics::UniquePtr<Type>;
90 if(info.allocationCallbacks)
92 auto* memory = info.allocationCallbacks->allocCallback(
95 info.allocationCallbacks->userData);
96 return UPtr(new(memory) GLESType(info, controller), GLESDeleter<GLESType>());
98 else // Use standard allocator
100 return UPtr(new GLESType(info, controller), GLESDeleter<GLESType>());
104 template<class T0, class T1>
105 T0* CastObject(T1* apiObject)
107 return static_cast<T0*>(apiObject);
110 // Maximum size of texture upload buffer.
111 const uint32_t TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB = 1;
115 EglGraphicsController::EglGraphicsController()
116 : mTextureDependencyChecker(*this),
121 EglGraphicsController::~EglGraphicsController()
123 while(!mPresentationCommandBuffers.empty())
125 auto presentCommandBuffer = const_cast<GLES::CommandBuffer*>(mPresentationCommandBuffers.front());
126 delete presentCommandBuffer;
127 mPresentationCommandBuffers.pop();
131 void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
133 DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 1\n");
134 mGlAbstraction = &glAbstraction;
135 mContext = std::make_unique<GLES::Context>(*this);
136 mCurrentContext = mContext.get();
139 void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction& syncImplementation,
140 Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
141 Internal::Adaptor::GraphicsInterface& graphicsInterface)
143 DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 2\n");
144 auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
146 mEglSyncImplementation = syncImplPtr;
147 mGlContextHelperAbstraction = &glContextHelperAbstraction;
148 mGraphics = &graphicsInterface;
151 void EglGraphicsController::FrameStart()
153 mCapacity = 0; // Reset the command buffer capacity at the start of the frame.
156 void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
158 for(auto& cmdbuf : submitInfo.cmdBuffer)
160 // Push command buffers
161 auto* commandBuffer = static_cast<GLES::CommandBuffer*>(cmdbuf);
162 mCapacity += commandBuffer->GetCapacity();
163 mCommandQueue.push(commandBuffer);
166 // If flush bit set, flush all pending tasks
167 if(submitInfo.flags & (0 | SubmitFlagBits::FLUSH))
173 void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
175 GLES::CommandBuffer* presentCommandBuffer{nullptr};
176 if(mPresentationCommandBuffers.empty())
178 CommandBufferCreateInfo info;
179 info.SetLevel(CommandBufferLevel::PRIMARY);
180 info.fixedCapacity = 1; // only one command
181 presentCommandBuffer = new GLES::CommandBuffer(info, *this);
185 presentCommandBuffer = const_cast<GLES::CommandBuffer*>(mPresentationCommandBuffers.front());
186 presentCommandBuffer->Reset();
187 mPresentationCommandBuffers.pop();
189 presentCommandBuffer->PresentRenderTarget(static_cast<GLES::RenderTarget*>(renderTarget));
190 SubmitInfo submitInfo;
191 submitInfo.cmdBuffer = {presentCommandBuffer};
192 submitInfo.flags = 0 | SubmitFlagBits::FLUSH;
193 SubmitCommandBuffers(submitInfo);
196 void EglGraphicsController::ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget)
198 mCurrentContext->InvalidateDepthStencilBuffers();
200 auto* rt = static_cast<GLES::RenderTarget*>(renderTarget);
201 if(rt->GetCreateInfo().surface)
203 auto* surfaceInterface = reinterpret_cast<Dali::RenderSurfaceInterface*>(rt->GetCreateInfo().surface);
204 surfaceInterface->MakeContextCurrent();
205 surfaceInterface->PostRender();
209 void EglGraphicsController::PostRender()
211 mTextureDependencyChecker.Reset();
212 mSyncPool.AgeSyncObjects();
215 Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
217 DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
218 return *mGlAbstraction;
221 Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelperAbstraction()
223 DALI_ASSERT_DEBUG(mGlContextHelperAbstraction && "Graphics controller not initialized");
224 return *mGlContextHelperAbstraction;
227 Internal::Adaptor::EglSyncImplementation& EglGraphicsController::GetEglSyncImplementation()
229 DALI_ASSERT_DEBUG(mEglSyncImplementation && "Sync implementation not initialized");
230 return *mEglSyncImplementation;
233 Graphics::UniquePtr<CommandBuffer> EglGraphicsController::CreateCommandBuffer(
234 const CommandBufferCreateInfo& commandBufferCreateInfo,
235 Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
237 return NewObject<GLES::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
240 Graphics::UniquePtr<RenderPass> EglGraphicsController::CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass)
242 return NewObject<GLES::RenderPass>(renderPassCreateInfo, *this, std::move(oldRenderPass));
245 Graphics::UniquePtr<Texture>
246 EglGraphicsController::CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture)
248 return NewObject<GLES::Texture>(textureCreateInfo, *this, std::move(oldTexture));
251 Graphics::UniquePtr<Buffer> EglGraphicsController::CreateBuffer(
252 const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
254 return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
257 Graphics::UniquePtr<Framebuffer> EglGraphicsController::CreateFramebuffer(
258 const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer)
260 return NewObject<GLES::Framebuffer>(framebufferCreateInfo, *this, std::move(oldFramebuffer));
263 Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(
264 const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
266 // Create pipeline cache if needed
269 mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
272 return mPipelineCache->GetPipeline(pipelineCreateInfo, std::move(oldPipeline));
275 Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
276 const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
278 // Create program cache if needed
281 mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
284 return mPipelineCache->GetProgram(programCreateInfo, std::move(oldProgram));
287 Graphics::UniquePtr<Shader> EglGraphicsController::CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader)
289 return NewObject<GLES::Shader>(shaderCreateInfo, *this, std::move(oldShader));
292 Graphics::UniquePtr<Sampler> EglGraphicsController::CreateSampler(const SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Sampler>&& oldSampler)
294 return NewObject<GLES::Sampler>(samplerCreateInfo, *this, std::move(oldSampler));
297 Graphics::UniquePtr<RenderTarget> EglGraphicsController::CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget)
299 return NewObject<GLES::RenderTarget>(renderTargetCreateInfo, *this, std::move(oldRenderTarget));
302 Graphics::UniquePtr<SyncObject> EglGraphicsController::CreateSyncObject(const SyncObjectCreateInfo& syncObjectCreateInfo,
303 UniquePtr<SyncObject>&& oldSyncObject)
305 if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
307 return NewObject<EGL::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
311 return NewObject<GLES::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
315 TextureProperties EglGraphicsController::GetTextureProperties(const Texture& texture)
317 const GLES::Texture* glesTexture = static_cast<const GLES::Texture*>(&texture);
318 auto createInfo = glesTexture->GetCreateInfo();
320 TextureProperties properties{};
321 properties.format = createInfo.format;
322 properties.compressed = glesTexture->IsCompressed();
323 properties.extent2D = createInfo.size;
324 properties.nativeHandle = glesTexture->GetGLTexture();
325 // TODO: Skip format1, emulated, packed, directWriteAccessEnabled of TextureProperties for now
330 const Graphics::Reflection& EglGraphicsController::GetProgramReflection(const Graphics::Program& program)
332 return static_cast<const Graphics::GLES::Program*>(&program)->GetReflection();
335 void EglGraphicsController::CreateSurfaceContext(Dali::RenderSurfaceInterface* surface)
337 std::unique_ptr<GLES::Context> context = std::make_unique<GLES::Context>(*this);
338 mSurfaceContexts.push_back(std::move(std::make_pair(surface, std::move(context))));
341 void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface)
343 mSurfaceContexts.erase(std::remove_if(
344 mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
345 mSurfaceContexts.end());
348 void EglGraphicsController::ActivateResourceContext()
350 mCurrentContext = mContext.get();
351 mCurrentContext->GlContextCreated();
354 auto eglGraphics = dynamic_cast<Dali::Internal::Adaptor::EglGraphics*>(mGraphics);
357 mSharedContext = eglGraphics->GetEglImplementation().GetContext();
362 void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
364 if(surface && mGraphics->IsResourceContextSupported())
366 auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return (iter.first == surface); });
368 if(iter != mSurfaceContexts.end())
370 mCurrentContext = iter->second.get();
371 mCurrentContext->GlContextCreated();
376 void EglGraphicsController::AddTexture(GLES::Texture& texture)
378 // Assuming we are on the correct context
379 mCreateTextureQueue.push(&texture);
382 void EglGraphicsController::AddBuffer(GLES::Buffer& buffer)
384 // Assuming we are on the correct context
385 mCreateBufferQueue.push(&buffer);
388 void EglGraphicsController::AddFramebuffer(GLES::Framebuffer& framebuffer)
390 // Assuming we are on the correct context
391 mCreateFramebufferQueue.push(&framebuffer);
394 void EglGraphicsController::ProcessDiscardQueues()
397 ProcessDiscardQueue<GLES::Texture>(mDiscardTextureQueue);
400 ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
402 // Process Framebuffers
403 ProcessDiscardQueue<GLES::Framebuffer>(mDiscardFramebufferQueue);
405 // Process RenderPass
406 ProcessDiscardQueue<GLES::RenderPass>(mDiscardRenderPassQueue);
408 // Process RenderTarget
409 ProcessDiscardQueue<GLES::RenderTarget>(mDiscardRenderTargetQueue);
412 ProcessDiscardQueue(mDiscardPipelineQueue);
415 ProcessDiscardQueue<GLES::Program>(mDiscardProgramQueue);
418 ProcessDiscardQueue<GLES::Shader>(mDiscardShaderQueue);
421 ProcessDiscardQueue<GLES::Sampler>(mDiscardSamplerQueue);
423 // Process command buffers
424 ProcessDiscardQueue<GLES::CommandBuffer>(mDiscardCommandBufferQueue);
427 void EglGraphicsController::ProcessCreateQueues()
430 ProcessCreateQueue(mCreateTextureQueue);
433 ProcessCreateQueue(mCreateBufferQueue);
435 // Process framebuffers
436 ProcessCreateQueue(mCreateFramebufferQueue);
439 void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer)
442 const auto commands = commandBuffer.GetCommands(count);
443 for(auto i = 0u; i < count; ++i)
445 auto& cmd = commands[i];
449 case GLES::CommandType::FLUSH:
451 // Nothing to do here
454 case GLES::CommandType::BIND_TEXTURES:
456 mCurrentContext->BindTextures(cmd.bindTextures.textureBindings.Ptr(), cmd.bindTextures.textureBindingsCount);
459 case GLES::CommandType::BIND_VERTEX_BUFFERS:
461 auto bindings = cmd.bindVertexBuffers.vertexBufferBindings.Ptr();
462 mCurrentContext->BindVertexBuffers(bindings, cmd.bindVertexBuffers.vertexBufferBindingsCount);
465 case GLES::CommandType::BIND_UNIFORM_BUFFER:
467 auto& bindings = cmd.bindUniformBuffers;
468 mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindingsCount ? bindings.uniformBufferBindings.Ptr() : nullptr, bindings.uniformBufferBindingsCount, bindings.standaloneUniformsBufferBinding);
471 case GLES::CommandType::BIND_INDEX_BUFFER:
473 mCurrentContext->BindIndexBuffer(cmd.bindIndexBuffer);
476 case GLES::CommandType::BIND_SAMPLERS:
480 case GLES::CommandType::BIND_PIPELINE:
482 auto pipeline = static_cast<const GLES::Pipeline*>(cmd.bindPipeline.pipeline);
483 mCurrentContext->BindPipeline(pipeline);
486 case GLES::CommandType::DRAW:
488 mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
491 case GLES::CommandType::DRAW_INDEXED:
493 mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
496 case GLES::CommandType::DRAW_INDEXED_INDIRECT:
498 mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
501 case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
503 mGlAbstraction->Scissor(cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
506 case GLES::CommandType::SET_SCISSOR_TEST:
508 mCurrentContext->SetScissorTestEnabled(cmd.scissorTest.enable);
511 case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
513 mGlAbstraction->Viewport(cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
517 case GLES::CommandType::SET_COLOR_MASK:
519 mCurrentContext->ColorMask(cmd.colorMask.enabled);
522 case GLES::CommandType::CLEAR_STENCIL_BUFFER:
524 mCurrentContext->ClearStencilBuffer();
527 case GLES::CommandType::CLEAR_DEPTH_BUFFER:
529 mCurrentContext->ClearDepthBuffer();
533 case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
535 mCurrentContext->SetStencilTestEnable(cmd.stencilTest.enabled);
539 case GLES::CommandType::SET_STENCIL_FUNC:
541 mCurrentContext->StencilFunc(cmd.stencilFunc.compareOp,
542 cmd.stencilFunc.reference,
543 cmd.stencilFunc.compareMask);
547 case GLES::CommandType::SET_STENCIL_WRITE_MASK:
549 mCurrentContext->StencilMask(cmd.stencilWriteMask.mask);
553 case GLES::CommandType::SET_STENCIL_OP:
555 mCurrentContext->StencilOp(cmd.stencilOp.failOp,
556 cmd.stencilOp.depthFailOp,
557 cmd.stencilOp.passOp);
561 case GLES::CommandType::SET_DEPTH_COMPARE_OP:
563 mCurrentContext->SetDepthCompareOp(cmd.depth.compareOp);
566 case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
568 mCurrentContext->SetDepthTestEnable(cmd.depth.testEnabled);
571 case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
573 mCurrentContext->SetDepthWriteEnable(cmd.depth.writeEnabled);
577 case GLES::CommandType::BEGIN_RENDERPASS:
579 auto& renderTarget = *cmd.beginRenderPass.renderTarget;
580 const auto& targetInfo = renderTarget.GetCreateInfo();
582 if(targetInfo.surface)
584 // switch to surface context
585 mGraphics->ActivateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(targetInfo.surface));
587 else if(targetInfo.framebuffer)
589 // switch to resource context
590 mGraphics->ActivateResourceContext();
593 mCurrentContext->BeginRenderPass(cmd.beginRenderPass);
597 case GLES::CommandType::END_RENDERPASS:
599 mCurrentContext->EndRenderPass(mTextureDependencyChecker);
601 // This sync object is to enable cpu to wait for rendering to complete, not gpu.
602 // It's only needed for reading the framebuffer texture in the client.
603 auto syncObject = const_cast<GLES::SyncObject*>(static_cast<const GLES::SyncObject*>(cmd.endRenderPass.syncObject));
606 syncObject->InitializeResource();
610 case GLES::CommandType::PRESENT_RENDER_TARGET:
612 ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent);
614 // The command buffer will be pushed into the queue of presentation command buffers
615 // for further reuse.
616 if(commandBuffer.GetCreateInfo().fixedCapacity == 1)
618 mPresentationCommandBuffers.push(&commandBuffer);
622 case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
624 // Process secondary command buffers
625 // todo: check validity of the secondaries
626 // there are operations which are illigal to be done
627 // within secondaries.
628 auto buffers = cmd.executeCommandBuffers.buffers.Ptr();
629 for(auto j = 0u; j < cmd.executeCommandBuffers.buffersCount; ++j)
631 auto& buf = buffers[j];
632 ProcessCommandBuffer(*static_cast<const GLES::CommandBuffer*>(buf));
636 case GLES::CommandType::DRAW_NATIVE:
638 auto* info = &cmd.drawNative.drawNativeInfo;
640 mCurrentContext->PrepareForNativeRendering();
642 if(info->glesNativeInfo.eglSharedContextStoragePointer)
644 auto* anyContext = reinterpret_cast<std::any*>(info->glesNativeInfo.eglSharedContextStoragePointer);
645 *anyContext = mSharedContext;
648 CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
650 mCurrentContext->RestoreFromNativeRendering();
657 void EglGraphicsController::ProcessCommandQueues()
661 while(!mCommandQueue.empty())
663 auto cmdBuf = mCommandQueue.front();
665 DUMP_FRAME_COMMAND_BUFFER(cmdBuf);
666 ProcessCommandBuffer(*cmdBuf);
672 void EglGraphicsController::ProcessTextureUpdateQueue()
674 while(!mTextureUpdateRequests.empty())
676 TextureUpdateRequest& request = mTextureUpdateRequests.front();
678 auto& info = request.first;
679 auto& source = request.second;
681 switch(source.sourceType)
683 case Graphics::TextureUpdateSourceInfo::Type::MEMORY:
684 case Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA:
686 // GPU memory must be already allocated.
688 // Check if it needs conversion
689 auto* texture = static_cast<GLES::Texture*>(info.dstTexture);
690 const auto& createInfo = texture->GetCreateInfo();
691 auto srcFormat = GLES::GLTextureFormatType(info.srcFormat).format;
692 auto srcType = GLES::GLTextureFormatType(info.srcFormat).type;
693 auto destInternalFormat = GLES::GLTextureFormatType(createInfo.format).internalFormat;
694 auto destFormat = GLES::GLTextureFormatType(createInfo.format).format;
696 // From render-texture.cpp
697 const bool isSubImage(info.dstOffset2D.x != 0 || info.dstOffset2D.y != 0 ||
698 info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) ||
699 info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
701 uint8_t* sourceBuffer;
702 if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
704 sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
708 // Get buffer of PixelData
709 Dali::Integration::PixelDataBuffer pixelBufferData = Dali::Integration::GetPixelDataBuffer(source.pixelDataSource.pixelData);
711 sourceBuffer = pixelBufferData.buffer + info.srcOffset;
714 auto sourceStride = info.srcStride;
715 std::vector<uint8_t> tempBuffer;
717 if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
719 // Convert RGB to RGBA if necessary.
720 if(texture->TryConvertPixelData(sourceBuffer, info.srcFormat, createInfo.format, info.srcSize, info.srcStride, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer))
722 sourceBuffer = &tempBuffer[0];
723 sourceStride = 0u; // Converted buffer compacted. make stride as 0.
724 srcFormat = destFormat;
725 srcType = GLES::GLTextureFormatType(createInfo.format).type;
729 // Calculate the maximum mipmap level for the texture
730 texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
732 GLenum bindTarget{GL_TEXTURE_2D};
733 GLenum target{GL_TEXTURE_2D};
735 if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
737 bindTarget = GL_TEXTURE_CUBE_MAP;
738 target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
741 mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
742 mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
744 mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
748 if(!texture->IsCompressed())
750 mGlAbstraction->TexImage2D(target,
753 info.srcExtent2D.width,
754 info.srcExtent2D.height,
762 mGlAbstraction->CompressedTexImage2D(target,
765 info.srcExtent2D.width,
766 info.srcExtent2D.height,
774 if(!texture->IsCompressed())
776 mGlAbstraction->TexSubImage2D(target,
780 info.srcExtent2D.width,
781 info.srcExtent2D.height,
788 mGlAbstraction->CompressedTexSubImage2D(target,
792 info.srcExtent2D.width,
793 info.srcExtent2D.height,
800 if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
802 // free staging memory
803 free(source.memorySource.memory);
809 // TODO: other sources
814 mTextureUpdateRequests.pop();
818 void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>& updateInfoList,
819 const std::vector<TextureUpdateSourceInfo>& sourceList)
822 for(auto& info : updateInfoList)
824 mTextureUpdateRequests.push(std::make_pair(info, sourceList[info.srcReference]));
825 auto& pair = mTextureUpdateRequests.back();
826 switch(pair.second.sourceType)
828 case Graphics::TextureUpdateSourceInfo::Type::MEMORY:
830 auto& info = pair.first;
831 auto& source = pair.second;
833 // allocate staging memory and copy the data
834 // TODO: using PBO with GLES3, this is just naive
837 uint8_t* stagingBuffer = reinterpret_cast<uint8_t*>(malloc(info.srcSize));
839 uint8_t* srcMemory = &reinterpret_cast<uint8_t*>(source.memorySource.memory)[info.srcOffset];
841 std::copy(srcMemory, srcMemory + info.srcSize, stagingBuffer);
843 mTextureUploadTotalCPUMemoryUsed += info.srcSize;
845 // store staging buffer
846 source.memorySource.memory = stagingBuffer;
849 case Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA:
851 // Increase CPU memory usage since ownership of PixelData is now on mTextureUpdateRequests.
852 mTextureUploadTotalCPUMemoryUsed += info.srcSize;
855 case Graphics::TextureUpdateSourceInfo::Type::BUFFER:
857 // TODO, with PBO support
860 case Graphics::TextureUpdateSourceInfo::Type::TEXTURE:
862 // TODO texture 2 texture in-GPU copy
868 // If upload buffer exceeds maximum size, flush.
869 if(mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB * 1024 * 1024)
872 mTextureUploadTotalCPUMemoryUsed = 0;
876 void EglGraphicsController::ProcessTextureMipmapGenerationQueue()
878 while(!mTextureMipmapGenerationRequests.empty())
880 auto* texture = mTextureMipmapGenerationRequests.front();
882 mCurrentContext->BindTexture(texture->GetGlTarget(), texture->GetTextureTypeId(), texture->GetGLTexture());
883 mCurrentContext->GenerateMipmap(texture->GetGlTarget());
885 mTextureMipmapGenerationRequests.pop();
889 void EglGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
891 mTextureMipmapGenerationRequests.push(static_cast<const GLES::Texture*>(&texture));
894 Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
896 mGraphics->ActivateResourceContext();
898 // Mapping buffer requires the object to be created NOW
899 // Workaround - flush now, otherwise there will be given a staging buffer
900 // in case when the buffer is not there yet
901 ProcessCreateQueues();
903 if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
905 return Graphics::UniquePtr<Memory>(new GLES::Memory2(mapInfo, *this));
909 return Graphics::UniquePtr<Memory>(new GLES::Memory3(mapInfo, *this));
913 bool EglGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData)
915 return static_cast<GLES::Program*>(&program)->GetImplementation()->GetParameter(parameterId, outData);
918 GLES::PipelineCache& EglGraphicsController::GetPipelineCache() const
920 return *mPipelineCache;
923 } // namespace Dali::Graphics