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 "gles-context.h"
19 #include <dali/integration-api/gl-abstraction.h>
20 #include <dali/integration-api/gl-defines.h>
21 #include "gles-graphics-buffer.h"
22 #include "gles-graphics-command-buffer.h"
23 #include "gles-graphics-pipeline.h"
25 namespace Dali::Graphics::GLES
29 Impl(EglGraphicsController& controller)
30 : mController(controller)
36 EglGraphicsController& mController;
38 const GLES::Pipeline* mCurrentPipeline{nullptr}; ///< Currently bound pipeline
39 const GLES::Pipeline* mNewPipeline{nullptr}; ///< New pipeline to be set on flush
41 std::vector<Graphics::TextureBinding> mCurrentTextureBindings{};
42 std::vector<Graphics::SamplerBinding> mCurrentSamplerBindings{};
43 GLES::IndexBufferBindingDescriptor mCurrentIndexBufferBinding{};
45 struct VertexBufferBinding
47 GLES::Buffer* buffer{nullptr};
51 // Currently bound buffers
52 std::vector<VertexBufferBindingDescriptor> mCurrentVertexBufferBindings{};
55 Context::Context(EglGraphicsController& controller)
57 mImpl = std::make_unique<Impl>(controller);
60 Context::~Context() = default;
62 void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
64 auto& gl = *mImpl->mController.GetGL();
67 if(mImpl->mNewPipeline)
69 // Execute states if different
70 mImpl->mCurrentPipeline = mImpl->mNewPipeline;
71 mImpl->mNewPipeline = nullptr;
73 mImpl->mCurrentPipeline->GetPipeline().Bind(nullptr);
78 // Resolve rasterization state
79 ResolveRasterizationState();
82 for(const auto& binding : mImpl->mCurrentTextureBindings)
84 gl.ActiveTexture(GL_TEXTURE0 + binding.binding);
85 gl.BindTexture(GL_TEXTURE_2D,
86 static_cast<const GLES::Texture*>(binding.texture)
90 // for each attribute bind vertices
91 const auto& pipelineState = mImpl->mCurrentPipeline->GetCreateInfo();
92 const auto& vi = pipelineState.vertexInputState;
93 for(const auto& attr : vi->attributes)
96 gl.EnableVertexAttribArray(attr.location);
97 const auto& bufferSlot = mImpl->mCurrentVertexBufferBindings[attr.binding];
98 const auto& bufferBinding = vi->bufferBindings[attr.binding];
100 auto glesBuffer = bufferSlot.buffer->GetGLBuffer();
103 gl.BindBuffer(GL_ARRAY_BUFFER, glesBuffer);
104 gl.VertexAttribPointer(attr.location,
105 GLVertexFormat(attr.format).size,
106 GLVertexFormat(attr.format).format,
108 bufferBinding.stride,
109 reinterpret_cast<void*>(attr.offset));
113 const auto& ia = mImpl->mCurrentPipeline->GetCreateInfo().inputAssemblyState;
116 switch(drawCall.type)
118 case DrawCallDescriptor::Type::DRAW:
120 gl.DrawArrays(GLESTopology(ia->topology),
121 drawCall.draw.firstVertex,
122 drawCall.draw.vertexCount);
125 case DrawCallDescriptor::Type::DRAW_INDEXED:
127 const auto& binding = mImpl->mCurrentIndexBufferBinding;
128 const auto* glesBuffer = binding.buffer;
129 gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, glesBuffer->GetGLBuffer());
130 auto indexBufferFormat = GLIndexFormat(binding.format).format;
131 gl.DrawElements(GLESTopology(ia->topology),
132 drawCall.drawIndexed.indexCount,
134 reinterpret_cast<void*>(binding.offset));
137 case DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT:
144 void Context::BindTextures(const std::vector<Graphics::TextureBinding>& bindings)
146 // for each texture allocate slot
147 for(const auto& binding : bindings)
149 // Resize binding array if needed
150 if(mImpl->mCurrentTextureBindings.size() <= binding.binding)
152 mImpl->mCurrentTextureBindings.resize(binding.binding + 1);
154 // Store the binding details
155 mImpl->mCurrentTextureBindings[binding.binding] = binding;
159 void Context::BindVertexBuffers(const std::vector<GLES::VertexBufferBindingDescriptor>& bindings)
161 if(bindings.size() > mImpl->mCurrentVertexBufferBindings.size())
163 mImpl->mCurrentVertexBufferBindings.resize(bindings.size());
165 // Copy only set slots
166 std::copy_if(bindings.begin(), bindings.end(), mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) {
167 return (nullptr != item.buffer);
171 void Context::BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding)
173 mImpl->mCurrentIndexBufferBinding = indexBufferBinding;
176 void Context::BindPipeline(const GLES::Pipeline* newPipeline)
178 mImpl->mNewPipeline = newPipeline;
181 void Context::ResolveBlendState()
183 const auto& state = mImpl->mCurrentPipeline->GetCreateInfo();
184 const auto& bs = state.colorBlendState;
185 auto& gl = *mImpl->mController.GetGL();
187 // TODO: prevent leaking the state
193 bs->blendEnable ? gl.Enable(GL_BLEND) : gl.Disable(GL_BLEND);
199 gl.BlendFunc(GLBlendFunc(bs->srcColorBlendFactor), GLBlendFunc(bs->dstColorBlendFactor));
201 if((GLBlendFunc(bs->srcColorBlendFactor) == GLBlendFunc(bs->srcAlphaBlendFactor)) &&
202 (GLBlendFunc(bs->dstColorBlendFactor) == GLBlendFunc(bs->dstAlphaBlendFactor)))
204 gl.BlendFunc(GLBlendFunc(bs->srcColorBlendFactor), GLBlendFunc(bs->dstColorBlendFactor));
208 gl.BlendFuncSeparate(GLBlendFunc(bs->srcColorBlendFactor),
209 GLBlendFunc(bs->dstColorBlendFactor),
210 GLBlendFunc(bs->srcAlphaBlendFactor),
211 GLBlendFunc(bs->dstAlphaBlendFactor));
213 if(GLBlendOp(bs->colorBlendOp) == GLBlendOp(bs->alphaBlendOp))
215 gl.BlendEquation(GLBlendOp(bs->colorBlendOp));
219 gl.BlendEquationSeparate(GLBlendOp(bs->colorBlendOp), GLBlendOp(bs->alphaBlendOp));
223 void Context::ResolveRasterizationState()
225 const auto& state = mImpl->mCurrentPipeline->GetCreateInfo();
226 const auto& rs = state.rasterizationState;
227 auto& gl = *mImpl->mController.GetGL();
229 // TODO: prevent leaking the state
235 if(rs->cullMode == CullMode::NONE)
237 gl.Disable(GL_CULL_FACE);
241 gl.Enable(GL_CULL_FACE);
242 gl.CullFace(GLCullMode(rs->cullMode));
245 // TODO: implement polygon mode (fill, line, points)
246 // seems like we don't support it (no glPolygonMode())
249 } // namespace Dali::Graphics::GLES