#include <dali/integration-api/scene.h>
#include <dali/integration-api/trace.h>
-#include <dali/internal/graphics/gles/egl-graphics-controller.h>
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
#include <dali/public-api/common/dali-common.h>
#include <test-gl-abstraction.h>
#include <dali-test-suite-utils.h>
#include <dali/graphics-api/graphics-controller.h>
-#include <dali/internal/graphics/gles/egl-graphics-controller.h>
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
#include <test-graphics-application.h>
//#include <dali/graphics-api/graphics-api-buffer.h>
#include <dali/integration-api/gl-abstraction.h>
#include <dali/integration-api/gl-defines.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
-
#include <dali/public-api/common/dali-common.h>
namespace Dali::Graphics
void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
{
mGlAbstraction = &glAbstraction;
+ mContext = std::make_unique<GLES::Context>(*this);
}
void EglGraphicsController::Initialize(Integration::GlSyncAbstraction& glSyncAbstraction,
return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
}
+Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Pipeline>&& oldPipeline)
+{
+ return NewObject<GLES::Pipeline>(pipelineCreateInfo, *this, std::move(oldPipeline));
+}
+
void EglGraphicsController::AddTexture(GLES::Texture& texture)
{
// Assuming we are on the correct context
void EglGraphicsController::ProcessCommandQueues()
{
+ // TODO: command queue per context, sync between queues should be
+ // done externally
+
while(!mCommandQueue.empty())
{
auto cmdBuf = mCommandQueue.front();
{
case GLES::CommandType::FLUSH:
{
+ // Nothing to do here
break;
}
-
- // Bind textures
case GLES::CommandType::BIND_TEXTURES:
{
- for(auto& binding : cmd.bindTextures.textureBindings)
- {
- static_cast<const GLES::Texture*>(binding.texture)->Bind(binding);
- }
+ mContext->BindTextures(cmd.bindTextures.textureBindings);
break;
}
-
case GLES::CommandType::BIND_VERTEX_BUFFERS:
{
auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
- auto index = 0u;
- for(auto& binding : bindings)
- {
- // TODO: this is all wrong, just hack to work with current DALi
- if(binding.buffer)
- {
- CastObject<const GLES::Buffer>(binding.buffer)->Bind(BufferUsage::VERTEX_BUFFER);
- index++;
- }
- }
-
+ mContext->BindVertexBuffers(bindings);
break;
}
case GLES::CommandType::BIND_INDEX_BUFFER:
{
- auto buffer = static_cast<const GLES::Buffer*>(cmd.bindIndexBuffer.buffer);
- buffer->Bind(BufferUsage::INDEX_BUFFER);
+ mContext->BindIndexBuffer(cmd.bindIndexBuffer);
break;
}
case GLES::CommandType::BIND_SAMPLERS:
{
break;
}
+ case GLES::CommandType::BIND_PIPELINE:
+ {
+ mContext->BindPipeline(cmd.bindPipeline.pipeline);
+ break;
+ }
+ case GLES::CommandType::DRAW:
+ {
+ mContext->Flush(false, cmd.draw);
+ break;
+ }
+ case GLES::CommandType::DRAW_INDEXED:
+ {
+ mContext->Flush(false, cmd.draw);
+ break;
+ }
+ case GLES::CommandType::DRAW_INDEXED_INDIRECT:
+ {
+ mContext->Flush(false, cmd.draw);
+ break;
+ }
}
}
}
// store staging buffer
source.memorySource.memory = stagingBuffer;
-
- printf("Update ptr: %p\n", source.memorySource.memory);
break;
}
case Graphics::TextureUpdateSourceInfo::Type::BUFFER:
#include <queue>
// INTERNAL INCLUDES
+#include "gles-context.h"
#include "gles-graphics-buffer.h"
#include "gles-graphics-memory.h"
#include "gles-graphics-texture.h"
/**
* @copydoc Dali::Graphics::CreatePipeline()
*/
- Graphics::UniquePtr<Pipeline> CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Pipeline>&& oldPipeline) override
- {
- return nullptr;
- }
+ Graphics::UniquePtr<Pipeline> CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Pipeline>&& oldPipeline) override;
/**
* @copydoc Dali::Graphics::CreateShader()
using TextureUpdateRequest = std::pair<TextureUpdateInfo, TextureUpdateSourceInfo>;
std::queue<TextureUpdateRequest> mTextureUpdateRequests;
+
+ std::unique_ptr<GLES::Context> mContext{nullptr}; ///< Context object handling command buffers execution
};
} // namespace Graphics
${adaptor_graphics_dir}/gles-impl/gles-graphics-sampler.cpp
${adaptor_graphics_dir}/gles-impl/gles-graphics-shader.cpp
${adaptor_graphics_dir}/gles-impl/gles-graphics-texture.cpp
+ ${adaptor_graphics_dir}/gles-impl/gles-context.cpp
)
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "gles-context.h"
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+#include "gles-graphics-buffer.h"
+#include "gles-graphics-command-buffer.h"
+#include "gles-graphics-pipeline.h"
+
+namespace Dali::Graphics::GLES
+{
+struct Context::Impl
+{
+ Impl(EglGraphicsController& controller)
+ : mController(controller)
+ {
+ }
+
+ ~Impl() = default;
+
+ EglGraphicsController& mController;
+
+ const GLES::Pipeline* mCurrentPipeline{nullptr}; ///< Currently bound pipeline
+ const GLES::Pipeline* mNewPipeline{nullptr}; ///< New pipeline to be set on flush
+
+ std::vector<Graphics::TextureBinding> mCurrentTextureBindings{};
+ std::vector<Graphics::SamplerBinding> mCurrentSamplerBindings{};
+ GLES::IndexBufferBindingDescriptor mCurrentIndexBufferBinding{};
+
+ struct VertexBufferBinding
+ {
+ GLES::Buffer* buffer{nullptr};
+ uint32_t offset{0u};
+ };
+
+ // Currently bound buffers
+ std::vector<VertexBufferBindingDescriptor> mCurrentVertexBufferBindings{};
+};
+
+Context::Context(EglGraphicsController& controller)
+{
+ mImpl = std::make_unique<Impl>(controller);
+}
+
+Context::~Context() = default;
+
+void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
+{
+ auto& gl = *mImpl->mController.GetGL();
+
+ // Change pipeline
+ if(mImpl->mNewPipeline)
+ {
+ // Execute states if different
+ mImpl->mCurrentPipeline = mImpl->mNewPipeline;
+ mImpl->mNewPipeline = nullptr;
+ }
+
+ // Bind textures
+ for(const auto& binding : mImpl->mCurrentTextureBindings)
+ {
+ gl.ActiveTexture(GL_TEXTURE0 + binding.binding);
+ gl.BindTexture(GL_TEXTURE_2D,
+ static_cast<const GLES::Texture*>(binding.texture)
+ ->GetGLTexture());
+ }
+
+ // for each attribute bind vertices
+ const auto& pipelineState = mImpl->mCurrentPipeline->GetCreateInfo();
+ const auto& vi = pipelineState.vertexInputState;
+ for(const auto& attr : vi->attributes)
+ {
+ // Enable location
+ gl.EnableVertexAttribArray(attr.location);
+ const auto& bufferSlot = mImpl->mCurrentVertexBufferBindings[attr.binding];
+ const auto& bufferBinding = vi->bufferBindings[attr.binding];
+
+ auto glesBuffer = bufferSlot.buffer->GetGLBuffer();
+
+ // Bind buffer
+ gl.BindBuffer(GL_ARRAY_BUFFER, glesBuffer);
+ gl.VertexAttribPointer(attr.location,
+ GLVertexFormat(attr.format).size,
+ GLVertexFormat(attr.format).format,
+ GL_FALSE,
+ bufferBinding.stride,
+ reinterpret_cast<void*>(attr.offset));
+ }
+
+ // Resolve topology
+ const auto& ia = mImpl->mCurrentPipeline->GetCreateInfo().inputAssemblyState;
+ // Resolve drawcall
+
+ switch(drawCall.type)
+ {
+ case DrawCallDescriptor::Type::DRAW:
+ {
+ gl.DrawArrays(GLESTopology(ia->topology),
+ drawCall.draw.firstVertex,
+ drawCall.draw.vertexCount);
+ break;
+ }
+ case DrawCallDescriptor::Type::DRAW_INDEXED:
+ {
+ const auto& binding = mImpl->mCurrentIndexBufferBinding;
+ const auto* glesBuffer = binding.buffer;
+ gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, glesBuffer->GetGLBuffer());
+ auto indexBufferFormat = GLIndexFormat(binding.format).format;
+ gl.DrawElements(GLESTopology(ia->topology),
+ drawCall.drawIndexed.indexCount,
+ indexBufferFormat,
+ reinterpret_cast<void*>(binding.offset));
+ break;
+ }
+ case DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT:
+ {
+ break;
+ }
+ }
+}
+
+void Context::BindTextures(const std::vector<Graphics::TextureBinding>& bindings)
+{
+ // for each texture allocate slot
+ for(const auto& binding : bindings)
+ {
+ // Resize binding array if needed
+ if(mImpl->mCurrentTextureBindings.size() <= binding.binding)
+ {
+ mImpl->mCurrentTextureBindings.resize(binding.binding + 1);
+ }
+ // Store the binding details
+ mImpl->mCurrentTextureBindings[binding.binding] = binding;
+ }
+}
+
+void Context::BindVertexBuffers(const std::vector<GLES::VertexBufferBindingDescriptor>& bindings)
+{
+ if(bindings.size() > mImpl->mCurrentVertexBufferBindings.size())
+ {
+ mImpl->mCurrentVertexBufferBindings.resize(bindings.size());
+ }
+ // Copy only set slots
+ std::copy_if(bindings.begin(), bindings.end(), mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) {
+ return (nullptr != item.buffer);
+ });
+}
+
+void Context::BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding)
+{
+ mImpl->mCurrentIndexBufferBinding = indexBufferBinding;
+}
+
+void Context::BindPipeline(const GLES::Pipeline* newPipeline)
+{
+ mImpl->mNewPipeline = newPipeline;
+}
+
+} // namespace Dali::Graphics::GLES
--- /dev/null
+#ifndef DALI_GRAPHICS_GLES_CONTEXT_H
+#define DALI_GRAPHICS_GLES_CONTEXT_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/graphics-api/graphics-command-buffer.h>
+#include "gles-graphics-types.h"
+
+namespace Dali::Graphics
+{
+class EglGraphicsController;
+namespace GLES
+{
+class Pipeline;
+class Texture;
+
+/**
+ * @brief Context represents single GLES context
+ */
+class Context
+{
+public:
+ explicit Context(EglGraphicsController& controller);
+
+ ~Context();
+
+ /**
+ * @brief Flushes the context
+ *
+ * Flushes the context by issuing GL calls to set the required
+ * state.
+ *
+ * @param[in] reset If true then state is reset unconditionally
+ */
+ void Flush(bool reset, const GLES::DrawCallDescriptor& drawCall);
+
+ /**
+ * @brief Returns context Id
+ * @return
+ */
+ uint32_t GetContextId() const
+ {
+ return 0;
+ }
+
+ /**
+ * @brief Binds textures to the context
+ *
+ * Bindings are merged, they are resolved at later time
+ * when the draw call is issued. Then the texture binding
+ * slots (GL active texture binding) are enabled/disabled accordingly
+ * to the uniform layout.
+ *
+ * @param[in] bindings List of bindings
+ *
+ */
+ void BindTextures(const std::vector<Graphics::TextureBinding>& bindings);
+
+ /**
+ * @brief Vertex buffers to bind
+ *
+ * The bindings are taken from a command buffer being
+ * currently processed and copied into the local storage.
+ */
+
+ void BindVertexBuffers(const std::vector<GLES::VertexBufferBindingDescriptor>& bindings);
+
+ /**
+ * @brief Binds index buffer
+ *
+ * @param indexBufferBinding
+ */
+ void BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding);
+
+ /**
+ * @brief Binds pipeline to the context
+ * @param newPipeline
+ */
+ void BindPipeline(const GLES::Pipeline* newPipeline);
+
+private:
+ struct Impl;
+ std::unique_ptr<Impl> mImpl;
+};
+} // namespace GLES
+} // namespace Dali::Graphics
+#endif //DALI_GRAPHICS_GLES_CONTEXT_H
// INTERNAL INCLUDES
#include "egl-graphics-controller.h"
+#include "gles-graphics-pipeline.h"
+#include "gles-graphics-types.h"
-namespace Dali
+namespace Dali::Graphics::GLES
{
-namespace Graphics
-{
-namespace GLES
-{
-class EglController;
class Texture;
class Buffer;
class Sampler;
+class Pipeline;
enum class CommandType
{
BIND_TEXTURES,
BIND_SAMPLERS,
BIND_VERTEX_BUFFERS,
- BIND_INDEX_BUFFER
+ BIND_INDEX_BUFFER,
+ BIND_PIPELINE,
+ DRAW,
+ DRAW_INDEXED,
+ DRAW_INDEXED_INDIRECT
};
/**
bindTextures = rhs.bindTextures;
break;
}
+ case CommandType::BIND_PIPELINE:
+ {
+ bindPipeline = rhs.bindPipeline;
+ break;
+ }
+ case CommandType::DRAW:
+ {
+ draw.type = rhs.draw.type;
+ draw.draw = rhs.draw.draw;
+ break;
+ }
+ case CommandType::DRAW_INDEXED:
+ {
+ draw.type = rhs.draw.type;
+ draw.drawIndexed = rhs.draw.drawIndexed;
+ break;
+ }
+ case CommandType::DRAW_INDEXED_INDIRECT:
+ {
+ draw.type = rhs.draw.type;
+ draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
+ break;
+ }
case CommandType::FLUSH:
{
// Nothing to do
bindTextures = std::move(rhs.bindTextures);
break;
}
+ case CommandType::BIND_PIPELINE:
+ {
+ bindPipeline = rhs.bindPipeline;
+ break;
+ }
+ case CommandType::DRAW:
+ {
+ draw.type = rhs.draw.type;
+ draw.draw = rhs.draw.draw;
+ break;
+ }
+ case CommandType::DRAW_INDEXED:
+ {
+ draw.type = rhs.draw.type;
+ draw.drawIndexed = rhs.draw.drawIndexed;
+ break;
+ }
+ case CommandType::DRAW_INDEXED_INDIRECT:
+ {
+ draw.type = rhs.draw.type;
+ draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
+ break;
+ }
case CommandType::FLUSH:
{
// Nothing to do
type = rhs.type;
}
- CommandType type{CommandType::FLUSH};
+ CommandType type{CommandType::FLUSH}; ///< Type of command
union
{
struct
{
- struct Binding
- {
- const Graphics::Buffer* buffer{nullptr};
- uint32_t offset{0u};
- };
+ using Binding = GLES::VertexBufferBindingDescriptor;
std::vector<Binding> vertexBufferBindings;
} bindVertexBuffers;
- struct
+ struct : public IndexBufferBindingDescriptor
{
- const Graphics::Buffer* buffer{nullptr};
- uint32_t offset{};
- Graphics::Format format{};
} bindIndexBuffer;
+
+ struct
+ {
+ const GLES::Pipeline* pipeline{nullptr};
+ } bindPipeline;
+
+ struct : public DrawCallDescriptor
+ {
+ } draw;
};
};
{
}
+ ~CommandBuffer() override = default;
+
void BindVertexBuffers(uint32_t firstBinding,
std::vector<const Graphics::Buffer*> buffers,
std::vector<uint32_t> offsets) override
auto index = firstBinding;
for(auto& buf : buffers)
{
- bindings[index].buffer = buf;
+ bindings[index].buffer = static_cast<const GLES::Buffer*>(buf);
bindings[index].offset = offsets[index - firstBinding];
index++;
}
void BindPipeline(const Graphics::Pipeline& pipeline) override
{
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::BIND_PIPELINE;
+ mCommands.back().bindPipeline.pipeline = static_cast<const GLES::Pipeline*>(&pipeline);
}
void BindTextures(std::vector<TextureBinding>& textureBindings) override
{
mCommands.emplace_back();
mCommands.back().type = CommandType::BIND_INDEX_BUFFER;
- mCommands.back().bindIndexBuffer.buffer = &buffer;
+ mCommands.back().bindIndexBuffer.buffer = static_cast<const GLES::Buffer*>(&buffer);
mCommands.back().bindIndexBuffer.offset = offset;
mCommands.back().bindIndexBuffer.format = format;
}
uint32_t firstVertex,
uint32_t firstInstance) override
{
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::DRAW;
+ auto& cmd = mCommands.back().draw;
+ cmd.type = DrawCallDescriptor::Type::DRAW;
+ cmd.draw.vertexCount = vertexCount;
+ cmd.draw.instanceCount = instanceCount;
+ cmd.draw.firstInstance = firstInstance;
+ cmd.draw.firstVertex = firstVertex;
}
void DrawIndexed(
int32_t vertexOffset,
uint32_t firstInstance) override
{
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::DRAW_INDEXED;
+ auto& cmd = mCommands.back().draw;
+ cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED;
+ cmd.drawIndexed.firstIndex = firstIndex;
+ cmd.drawIndexed.firstInstance = firstInstance;
+ cmd.drawIndexed.indexCount = indexCount;
+ cmd.drawIndexed.vertexOffset = vertexOffset;
+ cmd.drawIndexed.instanceCount = instanceCount;
}
void DrawIndexedIndirect(
uint32_t drawCount,
uint32_t stride) override
{
+ mCommands.emplace_back();
+ mCommands.back().type = CommandType::DRAW_INDEXED_INDIRECT;
+ auto& cmd = mCommands.back().draw;
+ cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
+ cmd.drawIndexedIndirect.buffer = static_cast<const GLES::Buffer*>(&buffer);
+ cmd.drawIndexedIndirect.offset = offset;
+ cmd.drawIndexedIndirect.drawCount = drawCount;
+ cmd.drawIndexedIndirect.stride = stride;
}
void Reset(Graphics::CommandBuffer& commandBuffer) override
private:
std::vector<Command> mCommands;
};
-} // Namespace GLES
-} // Namespace Graphics
-} // Namespace Dali
+} // namespace Dali::Graphics::GLES
#endif
\ No newline at end of file
*
*/
-// CLASS HEADER
#include "gles-graphics-pipeline.h"
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+#include <memory>
+#include "egl-graphics-controller.h"
+#include "gles-graphics-shader.h"
+
+namespace Dali::Graphics::GLES
+{
+/**
+ * Copy of pipeline state, can be also used for internal caching
+ */
+struct Pipeline::PipelineState
+{
+ PipelineState() = default;
+
+ ColorBlendState colorBlendState;
+ DepthStencilState depthStencilState;
+ std::vector<ShaderState> shaderState;
+ ViewportState viewportState;
+ FramebufferState framebufferState;
+ RasterizationState rasterizationState;
+ VertexInputState vertexInputState;
+ InputAssemblyState inputAssemblyState;
+};
+
+Pipeline::Pipeline(const Graphics::PipelineCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: PipelineResource(createInfo, controller)
+{
+ // the creation is deferred so it's needed to copy certain parts of the CreateInfo structure
+ mPipelineState = std::make_unique<Pipeline::PipelineState>();
+
+ // Make copies of structured pass by pointers and replace
+ // stored create info structure fields
+ CopyStateIfSet(createInfo.inputAssemblyState, mPipelineState->inputAssemblyState, &mCreateInfo.inputAssemblyState);
+ CopyStateIfSet(createInfo.vertexInputState, mPipelineState->vertexInputState, &mCreateInfo.vertexInputState);
+ CopyStateIfSet(createInfo.rasterizationState, mPipelineState->rasterizationState, &mCreateInfo.rasterizationState);
+ CopyStateIfSet(createInfo.framebufferState, mPipelineState->framebufferState, &mCreateInfo.framebufferState);
+ CopyStateIfSet(createInfo.colorBlendState, mPipelineState->colorBlendState, &mCreateInfo.colorBlendState);
+ CopyStateIfSet(createInfo.depthStencilState, mPipelineState->depthStencilState, &mCreateInfo.depthStencilState);
+ CopyStateIfSet(createInfo.shaderState, mPipelineState->shaderState, &mCreateInfo.shaderState);
+ CopyStateIfSet(createInfo.viewportState, mPipelineState->viewportState, &mCreateInfo.viewportState);
+}
+
+bool Pipeline::InitializeResource()
+{
+ auto& gl = *GetController().GetGL();
+ mGlProgram = gl.CreateProgram();
+
+ for(auto& shader : mPipelineState->shaderState)
+ {
+ // TODO: Compile shader (shouldn't compile if already did so)
+ const auto glesShader = static_cast<const GLES::Shader*>(shader.shader);
+ if(glesShader->Compile())
+ {
+ // Attach shader
+ gl.AttachShader(mGlProgram, glesShader->GetGLShader());
+ }
+ else
+ {
+ // failure
+ gl.DeleteProgram(mGlProgram);
+ return false;
+ }
+ }
+
+ // Link program
+ gl.LinkProgram(mGlProgram);
+
+ // Check for errors
+ // TODO:
+
+ return true;
+}
+
+void Pipeline::DestroyResource()
+{
+ if(mGlProgram)
+ {
+ auto& gl = *GetController().GetGL();
+ gl.DeleteProgram(mGlProgram);
+ }
+}
+
+void Pipeline::DiscardResource()
+{
+ // Pass program to discard queue
+}
+
+uint32_t Pipeline::GetGLProgram() const
+{
+ return mGlProgram;
+}
+
+// FIXME: THIS FUNCTION IS NOT IN USE YET, REQUIRES PROPER PIPELINE
+void Pipeline::Bind(GLES::Pipeline* prevPipeline)
+{
+ // Same pipeline to bind, nothing to do
+ if(prevPipeline == this)
+ {
+ return;
+ }
+
+ auto& gl = *GetController().GetGL();
+
+ // ------------------ VIEWPORT
+
+ const auto& viewportState = mPipelineState->viewportState;
+ auto setViewportState = [this, &gl, viewportState]() {
+ if(viewportState.scissorTestEnable)
+ {
+ gl.Enable(GL_SCISSOR_TEST);
+ const auto& scissor = mPipelineState->viewportState.scissor;
+ gl.Scissor(scissor.x, scissor.y, scissor.width, scissor.height);
+ }
+ else
+ {
+ gl.Disable(GL_SCISSOR_TEST);
+ const auto& scissor = mPipelineState->viewportState.scissor;
+ gl.Scissor(scissor.x, scissor.y, scissor.width, scissor.height);
+ }
+ };
+
+ // Resolve viewport/scissor state change
+ ExecuteStateChange(setViewportState, prevPipeline->GetCreateInfo().viewportState, &mPipelineState->viewportState);
+
+ // ---------------------- PROGRAM
+ auto program = mGlProgram;
+
+ gl.UseProgram(program);
+}
+
+} // namespace Dali::Graphics::GLES
\ No newline at end of file
// EXTERNAL INCLUDES
#include <dali/graphics-api/graphics-pipeline-create-info.h>
#include <dali/graphics-api/graphics-pipeline.h>
+#include <string.h>
// INTERNAL INCLUDES
#include "gles-graphics-resource.h"
public:
/**
* @brief Constructor
- * @param[in] createInfo Valid createInfo structure
- * @param[in] controller Reference to the controller
+ * @param[in] createInfo valid TextureCreateInfo structure
+ * @param[in] controller Reference to the Controller
*/
- Pipeline(const Graphics::PipelineCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
- : PipelineResource(createInfo, controller)
- {
- }
+ Pipeline(const Graphics::PipelineCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
+
+ /**
+ * @brief Destroys all the low-level resources used by the class
+ */
+ void DestroyResource() override;
+
+ /**
+ * @brief Initializes low-level resources
+ *
+ * @return Tron success
+ */
+ bool InitializeResource() override;
+
+ /**
+ * @brief Discards object
+ */
+ void DiscardResource() override;
/**
- * @brief Destructor
+ * @brief returns GL program id
+ * @return GL program id
*/
- ~Pipeline() override = default;
+ [[nodiscard]] uint32_t GetGLProgram() const;
/**
- * @brief Called when GL resources are destroyed
+ * @brief Binds pipeline
+ *
+ * Binds Pipeline by binding GL program and flushing state.
+ *
+ * If previous pipeline specified, it will be used in order to
+ * avoid redundant state swiches.
+ *
+ * @param[in] prevPipeline previous pipeline
*/
- void DestroyResource() override
+ void Bind(GLES::Pipeline* prevPipeline);
+
+ /**
+ * Executes state change function if condition met
+ */
+ template<typename FUNC, typename STATE>
+ void ExecuteStateChange(FUNC& func, const STATE* prevPipelineState, const STATE* thisPipelineState)
{
- // TODO: Implement destroying the resource
+ if(!prevPipelineState)
+ {
+ func();
+ }
+ else
+ {
+ // binary test and execute when different
+ if(memcmp(prevPipelineState, thisPipelineState, sizeof(STATE)) != 0)
+ {
+ func();
+ }
+ }
}
+private:
/**
- * @brief Called when initializing the resource
- *
- * @return True on success
+ * @brief Helper function. Copies state if pointer is set
*/
- bool InitializeResource() override
+ template<class T>
+ void CopyStateIfSet(const T* sourceState, T& copyState, T** destState)
{
- // TODO: Implement initializing resource
- return {};
+ *destState = nullptr;
+ if(sourceState)
+ {
+ copyState = *sourceState;
+ *destState = ©State;
+ }
}
/**
- * @brief Called when UniquePtr<> on client-side dies
+ * @brief Helper function. Copies const state if pointer is set
*/
- void DiscardResource() override
+ template<class T>
+ void CopyStateIfSet(const T* sourceState, T& copyState, const T** destState)
{
- // TODO: Implement moving to the discard queue
+ *destState = nullptr;
+ if(sourceState)
+ {
+ copyState = *sourceState;
+ *destState = ©State;
+ }
}
+
+ // Pipeline state is stored as a copy of create info
+ // data.
+ struct PipelineState;
+ std::unique_ptr<PipelineState> mPipelineState{};
+
+ uint32_t mGlProgram{0u};
};
} // namespace Dali::Graphics::GLES
-
-#endif
+#endif
\ No newline at end of file
/**
* @brief Base class for the Graphics resource.
*/
-template<class T, class CreateInfo>
-class Resource : public T
+template<class BASE, class CreateInfo>
+class Resource : public BASE
{
public:
/**
*/
virtual void DiscardResource() = 0;
+ /**
+ * @brief returns pointer to base
+ * @return
+ */
+ BASE* GetBase()
+ {
+ return this;
+ }
+
protected:
CreateInfo mCreateInfo; ///< CreateInfo structure
Graphics::EglGraphicsController& mController; ///< Reference to the Controller object
}
/**
+ * @brief Compiles shader
+ * @return
+ */
+ bool Compile() const
+ {
+ mGlShader = 0;
+ return true;
+ }
+
+ /**
* @brief Called when UniquePtr<> on client-side dies
*/
void DiscardResource() override
{
// TODO: Implement moving to the discard queue
}
+
+ uint32_t GetGLShader() const
+ {
+ return mGlShader;
+ }
+
+private:
+ mutable uint32_t mGlShader;
};
} // namespace Dali::Graphics::GLES
{
Graphics::GLES::GLTextureFormatType format(mCreateInfo.format);
- if(format.format && format.type)
+ // TODO: find better condition, with this test the L8 doesn't work
+ if(1) //format.format && format.type)
{
// Bind texture
gl->GenTextures(1, &texture);
namespace Dali::Graphics::GLES
{
+class Buffer;
// Conversion functions
/**
* Stucture delivers format and type that can be used
// Luminance formats
case Graphics::Format::L8:
{
- Assign(0, 0);
+ Assign(GL_RED, GL_UNSIGNED_BYTE);
break;
}
case Graphics::Format::L8A8:
Assign(0, 0);
break;
}
+
// TBD which of the formats are supported
case Graphics::Format::A2R10G10B10_UNORM_PACK32:
{
uint32_t glFilter{0};
};
+/** Converts vertex format to GL */
+struct GLVertexFormat
+{
+ constexpr explicit GLVertexFormat(Graphics::VertexInputFormat gfxFormat)
+ {
+ switch(gfxFormat)
+ {
+ case VertexInputFormat::FVECTOR2:
+ {
+ format = GL_FLOAT;
+ size = 2;
+ break;
+ }
+ case VertexInputFormat::FVECTOR3:
+ {
+ format = GL_FLOAT;
+ size = 3;
+ break;
+ }
+ case VertexInputFormat::FVECTOR4:
+ {
+ format = GL_FLOAT;
+ size = 4;
+ break;
+ }
+ case VertexInputFormat::FLOAT:
+ {
+ format = GL_FLOAT;
+ size = 1;
+ break;
+ }
+ case VertexInputFormat::INTEGER:
+ {
+ format = GL_INT;
+ size = 1;
+ break;
+ }
+ case VertexInputFormat::IVECTOR2:
+ {
+ format = GL_INT;
+ size = 2;
+ break;
+ }
+ case VertexInputFormat::IVECTOR3:
+ {
+ format = GL_INT;
+ size = 3;
+ break;
+ }
+ case VertexInputFormat::IVECTOR4:
+ {
+ format = GL_INT;
+ size = 4;
+ break;
+ }
+ case VertexInputFormat::UNDEFINED:
+ {
+ format = 0;
+ size = 0;
+ break;
+ }
+ }
+ }
+
+ GLenum format{0u};
+ uint32_t size{0u};
+};
+
+/**
+ * @brief Descriptor of single buffer binding within
+ * command buffer.
+ */
+struct VertexBufferBindingDescriptor
+{
+ const GLES::Buffer* buffer{nullptr};
+ uint32_t offset{0u};
+};
+
+/**
+ * @brief Descriptor of ix buffer binding within
+ * command buffer.
+ */
+struct IndexBufferBindingDescriptor
+{
+ const GLES::Buffer* buffer{nullptr};
+ uint32_t offset{};
+ Graphics::Format format{};
+};
+
+/**
+ * @brief The descriptor of draw call
+ */
+struct DrawCallDescriptor
+{
+ /**
+ * @brief Enum specifying type of the draw call
+ */
+ enum class Type
+ {
+ DRAW,
+ DRAW_INDEXED,
+ DRAW_INDEXED_INDIRECT
+ };
+
+ Type type{}; ///< Type of the draw call
+
+ /**
+ * Union contains data for all types of draw calls.
+ */
+ union
+ {
+ /**
+ * @brief Vertex array draw
+ */
+ struct
+ {
+ uint32_t vertexCount;
+ uint32_t instanceCount;
+ uint32_t firstVertex;
+ uint32_t firstInstance;
+ } draw;
+
+ /**
+ * @brief Indexed draw
+ */
+ struct
+ {
+ uint32_t indexCount;
+ uint32_t instanceCount;
+ uint32_t firstIndex;
+ int32_t vertexOffset;
+ uint32_t firstInstance;
+ } drawIndexed;
+
+ /**
+ * @brief Indexed draw indirect
+ */
+ struct
+ {
+ const GLES::Buffer* buffer;
+ uint32_t offset;
+ uint32_t drawCount;
+ uint32_t stride;
+ } drawIndexedIndirect;
+ };
+};
+
+/**
+ * @brief Topologu conversion from Graphics to GLES
+ */
+struct GLESTopology
+{
+ explicit constexpr GLESTopology(PrimitiveTopology topology)
+ {
+ switch(topology)
+ {
+ case PrimitiveTopology::POINT_LIST:
+ {
+ primitiveTopology = GL_POINTS;
+ break;
+ }
+ case PrimitiveTopology::LINE_LIST:
+ {
+ primitiveTopology = GL_LINES;
+ break;
+ }
+ case PrimitiveTopology::LINE_LOOP:
+ {
+ primitiveTopology = GL_LINE_LOOP;
+ break;
+ }
+ case PrimitiveTopology::LINE_STRIP:
+ {
+ primitiveTopology = GL_LINE_STRIP;
+ break;
+ }
+ case PrimitiveTopology::TRIANGLE_LIST:
+ {
+ primitiveTopology = GL_TRIANGLES;
+ break;
+ }
+ case PrimitiveTopology::TRIANGLE_STRIP:
+ {
+ primitiveTopology = GL_TRIANGLE_STRIP;
+ break;
+ }
+ case PrimitiveTopology::TRIANGLE_FAN:
+ {
+ primitiveTopology = GL_TRIANGLE_FAN;
+ break;
+ }
+ }
+ }
+
+ /**
+ * @brief Explicit type conversion operator
+ * @return converted value
+ */
+ constexpr inline operator GLenum() const
+ {
+ return primitiveTopology;
+ }
+
+ GLenum primitiveTopology{0}; ///< Topology
+};
+
+/**
+ * @brief Index format conversion structure
+ */
+struct GLIndexFormat
+{
+ explicit constexpr GLIndexFormat(Format _format)
+ {
+ switch(_format)
+ {
+ // TODO: add more formats
+ case Format::R16_UINT:
+ {
+ format = GL_UNSIGNED_SHORT;
+ break;
+ }
+ default:
+ {
+ format = 0;
+ }
+ }
+ }
+
+ /**
+ * @brief Explicit type conversion operator
+ * @return converted value
+ */
+ constexpr inline operator GLenum() const
+ {
+ return format;
+ }
+
+ GLenum format{0}; ///< Converted format
+};
+
} // namespace Dali::Graphics::GLES
#endif //DALI_GRAPHICS_API_TYPES_H
+++ /dev/null
-#ifndef DALI_EGL_GRAPHICS_CONTROLLER_H
-#define DALI_EGL_GRAPHICS_CONTROLLER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <dali/graphics-api/graphics-controller.h>
-
-namespace Dali
-{
-namespace Integration
-{
-class GlAbstraction;
-class GlSyncAbstraction;
-class GlContextHelperAbstraction;
-} // namespace Integration
-
-namespace Graphics
-{
-/**
- * EGL Implementation of the graphics controller.
- *
- * Temporarily holds the old GL abstractions whilst dali-core is migrated to the new API.
- */
-DALI_IMPORT_API class EglGraphicsController : public Graphics::Controller
-{
-public:
- EglGraphicsController() = default;
-
- ~EglGraphicsController() override = default;
-
- /**
- * Initialize the GLES abstraction. This can be called from the main thread.
- */
- void InitializeGLES(Integration::GlAbstraction& glAbstraction);
-
- /**
- * Initialize with a reference to the GL abstractions.
- *
- * Note, this is now executed in the render thread, after core initialization
- */
- void Initialize(Integration::GlSyncAbstraction& glSyncAbstraction,
- Integration::GlContextHelperAbstraction& glContextHelperAbstraction);
-
- Integration::GlAbstraction& GetGlAbstraction() override;
- Integration::GlSyncAbstraction& GetGlSyncAbstraction() override;
- Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override;
-
- /**
- * @copydoc Dali::Graphics::SubmitCommandBuffers()
- */
- void SubmitCommandBuffers(const SubmitInfo& submitInfo) override
- {
- }
-
- /**
- * @copydoc Dali::Graphics::PresentRenderTarget()
- */
- void PresentRenderTarget(RenderTarget* renderTarget) override
- {
- }
-
- /**
- * @copydoc Dali::Graphics::WaitIdle()
- */
- void WaitIdle() override
- {
- }
-
- /**
- * @copydoc Dali::Graphics::Pause()
- */
- void Pause() override
- {
- }
-
- /**
- * @copydoc Dali::Graphics::Resume()
- */
- void Resume() override
- {
- }
-
- /**
- * @copydoc Dali::Graphics::UpdateTextures()
- */
- void UpdateTextures(const std::vector<TextureUpdateInfo>& updateInfoList,
- const std::vector<TextureUpdateSourceInfo>& sourceList) override
- {
- }
-
- /**
- * @copydoc Dali::Graphics::EnableDepthStencilBuffer()
- */
- bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override
- {
- return {};
- }
-
- /**
- * @copydoc Dali::Graphics::RunGarbageCollector()
- */
- void RunGarbageCollector(size_t numberOfDiscardedRenderers) override
- {
- }
-
- /**
- * @copydoc Dali::Graphics::DiscardUnusedResources()
- */
- void DiscardUnusedResources() override
- {
- }
-
- /**
- * @copydoc Dali::Graphics::IsDiscardQueueEmpty()
- */
- bool IsDiscardQueueEmpty() override
- {
- return {};
- }
-
- /**
- * @copydoc Dali::Graphics::IsDrawOnResumeRequired()
- */
- bool IsDrawOnResumeRequired() override
- {
- return {};
- }
-
- /**
- * @copydoc Dali::Graphics::CreateBuffer()
- */
- Graphics::UniquePtr<Buffer> CreateBuffer(const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::CreateCommandBuffer()
- */
- Graphics::UniquePtr<CommandBuffer> CreateCommandBuffer(const CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::CreateRenderPass()
- */
- Graphics::UniquePtr<RenderPass> CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::CreateTexture()
- */
- Graphics::UniquePtr<Texture> CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::CreateFramebuffer()
- */
- Graphics::UniquePtr<Framebuffer> CreateFramebuffer(const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::CreatePipeline()
- */
- Graphics::UniquePtr<Pipeline> CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Pipeline>&& oldPipeline) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::CreateShader()
- */
- Graphics::UniquePtr<Shader> CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::CreateSampler()
- */
- Graphics::UniquePtr<Sampler> CreateSampler(const SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Sampler>&& oldSampler) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::CreateRenderTarget()
- */
- Graphics::UniquePtr<RenderTarget> CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::MapBufferRange()
- */
- Graphics::UniquePtr<Memory> MapBufferRange(const MapBufferInfo& mapInfo) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::MapTextureRange()
- */
- Graphics::UniquePtr<Memory> MapTextureRange(const MapTextureInfo& mapInfo) override
- {
- return nullptr;
- }
-
- /**
- * @copydoc Dali::Graphics::UnmapMemory()
- */
- void UnmapMemory(Graphics::UniquePtr<Memory> memory) override
- {
- }
- /**
- * @copydoc Dali::Graphics::GetTextureMemoryRequirements()
- */
- MemoryRequirements GetTextureMemoryRequirements(Texture& texture) const override
- {
- return {};
- }
-
- /**
- * @copydoc Dali::Graphics::GetBufferMemoryRequirements()
- */
- MemoryRequirements GetBufferMemoryRequirements(Buffer& buffer) const override
- {
- return {};
- }
-
- /**
- * @copydoc Dali::Graphics::GetTextureProperties()
- */
- const TextureProperties& GetTextureProperties(const Texture& texture) override
- {
- // for compiler not to moan
- static TextureProperties dummy{};
- return dummy;
- }
-
- /**
- * @copydoc Dali::Graphics::PipelineEquals()
- */
- [[nodiscard]] bool PipelineEquals(const Pipeline& pipeline0, const Pipeline& pipeline1) const override
- {
- return {};
- }
-
- [[nodiscard]] Integration::GlAbstraction* GetGL() const
- {
- return mGlAbstraction;
- }
-
-private:
- Integration::GlAbstraction* mGlAbstraction{nullptr};
- Integration::GlSyncAbstraction* mGlSyncAbstraction{nullptr};
- Integration::GlContextHelperAbstraction* mGlContextHelperAbstraction{nullptr};
-};
-
-} // namespace Graphics
-
-} // namespace Dali
-
-#endif //DALI_EGL_GRAPHICS_CONTROLLER_H