50eb479b1c766daa8ccf0909610a434bd72f7743
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-context.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
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"
24
25 namespace Dali::Graphics::GLES
26 {
27 struct Context::Impl
28 {
29   Impl(EglGraphicsController& controller)
30   : mController(controller)
31   {
32   }
33
34   ~Impl() = default;
35
36   EglGraphicsController& mController;
37
38   const GLES::Pipeline* mCurrentPipeline{nullptr}; ///< Currently bound pipeline
39   const GLES::Pipeline* mNewPipeline{nullptr};     ///< New pipeline to be set on flush
40
41   std::vector<Graphics::TextureBinding> mCurrentTextureBindings{};
42   std::vector<Graphics::SamplerBinding> mCurrentSamplerBindings{};
43   GLES::IndexBufferBindingDescriptor    mCurrentIndexBufferBinding{};
44
45   struct VertexBufferBinding
46   {
47     GLES::Buffer* buffer{nullptr};
48     uint32_t      offset{0u};
49   };
50
51   // Currently bound buffers
52   std::vector<VertexBufferBindingDescriptor> mCurrentVertexBufferBindings{};
53 };
54
55 Context::Context(EglGraphicsController& controller)
56 {
57   mImpl = std::make_unique<Impl>(controller);
58 }
59
60 Context::~Context() = default;
61
62 void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
63 {
64   auto& gl = *mImpl->mController.GetGL();
65
66   // Change pipeline
67   if(mImpl->mNewPipeline)
68   {
69     // Execute states if different
70     mImpl->mCurrentPipeline = mImpl->mNewPipeline;
71     mImpl->mNewPipeline     = nullptr;
72   }
73   mImpl->mCurrentPipeline->GetPipeline().Bind(nullptr);
74
75   // Blend state
76   ResolveBlendState();
77
78   // Resolve rasterization state
79   ResolveRasterizationState();
80
81   // Bind textures
82   for(const auto& binding : mImpl->mCurrentTextureBindings)
83   {
84     gl.ActiveTexture(GL_TEXTURE0 + binding.binding);
85     gl.BindTexture(GL_TEXTURE_2D,
86                    static_cast<const GLES::Texture*>(binding.texture)
87                      ->GetGLTexture());
88   }
89
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)
94   {
95     // Enable location
96     gl.EnableVertexAttribArray(attr.location);
97     const auto& bufferSlot    = mImpl->mCurrentVertexBufferBindings[attr.binding];
98     const auto& bufferBinding = vi->bufferBindings[attr.binding];
99
100     auto glesBuffer = bufferSlot.buffer->GetGLBuffer();
101
102     // Bind buffer
103     gl.BindBuffer(GL_ARRAY_BUFFER, glesBuffer);
104     gl.VertexAttribPointer(attr.location,
105                            GLVertexFormat(attr.format).size,
106                            GLVertexFormat(attr.format).format,
107                            GL_FALSE,
108                            bufferBinding.stride,
109                            reinterpret_cast<void*>(attr.offset));
110   }
111
112   // Resolve topology
113   const auto& ia = mImpl->mCurrentPipeline->GetCreateInfo().inputAssemblyState;
114
115   // Resolve draw call
116   switch(drawCall.type)
117   {
118     case DrawCallDescriptor::Type::DRAW:
119     {
120       gl.DrawArrays(GLESTopology(ia->topology),
121                     drawCall.draw.firstVertex,
122                     drawCall.draw.vertexCount);
123       break;
124     }
125     case DrawCallDescriptor::Type::DRAW_INDEXED:
126     {
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,
133                       indexBufferFormat,
134                       reinterpret_cast<void*>(binding.offset));
135       break;
136     }
137     case DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT:
138     {
139       break;
140     }
141   }
142 }
143
144 void Context::BindTextures(const std::vector<Graphics::TextureBinding>& bindings)
145 {
146   // for each texture allocate slot
147   for(const auto& binding : bindings)
148   {
149     // Resize binding array if needed
150     if(mImpl->mCurrentTextureBindings.size() <= binding.binding)
151     {
152       mImpl->mCurrentTextureBindings.resize(binding.binding + 1);
153     }
154     // Store the binding details
155     mImpl->mCurrentTextureBindings[binding.binding] = binding;
156   }
157 }
158
159 void Context::BindVertexBuffers(const std::vector<GLES::VertexBufferBindingDescriptor>& bindings)
160 {
161   if(bindings.size() > mImpl->mCurrentVertexBufferBindings.size())
162   {
163     mImpl->mCurrentVertexBufferBindings.resize(bindings.size());
164   }
165   // Copy only set slots
166   std::copy_if(bindings.begin(), bindings.end(), mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) {
167     return (nullptr != item.buffer);
168   });
169 }
170
171 void Context::BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding)
172 {
173   mImpl->mCurrentIndexBufferBinding = indexBufferBinding;
174 }
175
176 void Context::BindPipeline(const GLES::Pipeline* newPipeline)
177 {
178   mImpl->mNewPipeline = newPipeline;
179 }
180
181 void Context::ResolveBlendState()
182 {
183   const auto& state = mImpl->mCurrentPipeline->GetCreateInfo();
184   const auto& bs    = state.colorBlendState;
185   auto&       gl    = *mImpl->mController.GetGL();
186
187   // TODO: prevent leaking the state
188   if(!bs)
189   {
190     return;
191   }
192
193   bs->blendEnable ? gl.Enable(GL_BLEND) : gl.Disable(GL_BLEND);
194   if(!bs->blendEnable)
195   {
196     return;
197   }
198
199   gl.BlendFunc(GLBlendFunc(bs->srcColorBlendFactor), GLBlendFunc(bs->dstColorBlendFactor));
200
201   if((GLBlendFunc(bs->srcColorBlendFactor) == GLBlendFunc(bs->srcAlphaBlendFactor)) &&
202      (GLBlendFunc(bs->dstColorBlendFactor) == GLBlendFunc(bs->dstAlphaBlendFactor)))
203   {
204     gl.BlendFunc(GLBlendFunc(bs->srcColorBlendFactor), GLBlendFunc(bs->dstColorBlendFactor));
205   }
206   else
207   {
208     gl.BlendFuncSeparate(GLBlendFunc(bs->srcColorBlendFactor),
209                          GLBlendFunc(bs->dstColorBlendFactor),
210                          GLBlendFunc(bs->srcAlphaBlendFactor),
211                          GLBlendFunc(bs->dstAlphaBlendFactor));
212   }
213   if(GLBlendOp(bs->colorBlendOp) == GLBlendOp(bs->alphaBlendOp))
214   {
215     gl.BlendEquation(GLBlendOp(bs->colorBlendOp));
216   }
217   else
218   {
219     gl.BlendEquationSeparate(GLBlendOp(bs->colorBlendOp), GLBlendOp(bs->alphaBlendOp));
220   }
221 }
222
223 void Context::ResolveRasterizationState()
224 {
225   const auto& state = mImpl->mCurrentPipeline->GetCreateInfo();
226   const auto& rs    = state.rasterizationState;
227   auto&       gl    = *mImpl->mController.GetGL();
228
229   // TODO: prevent leaking the state
230   if(!rs)
231   {
232     return;
233   }
234
235   if(rs->cullMode == CullMode::NONE)
236   {
237     gl.Disable(GL_CULL_FACE);
238   }
239   else
240   {
241     gl.Enable(GL_CULL_FACE);
242     gl.CullFace(GLCullMode(rs->cullMode));
243   }
244
245   // TODO: implement polygon mode (fill, line, points)
246   //       seems like we don't support it (no glPolygonMode())
247 }
248
249 } // namespace Dali::Graphics::GLES