Merge branch 'devel/graphics' into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-program.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 // CLASS HEADER
18 #include "gles-graphics-program.h"
19
20 // INTERNAL HEADERS
21 #include "egl-graphics-controller.h"
22 #include "gles-graphics-reflection.h"
23 #include "gles-graphics-shader.h"
24
25 // EXTERNAL HEADERS
26 #include <dali/integration-api/gl-abstraction.h>
27 #include <dali/integration-api/gl-defines.h>
28
29 namespace Dali::Graphics::GLES
30 {
31 struct ProgramImpl::Impl
32 {
33   explicit Impl(EglGraphicsController& _controller, const ProgramCreateInfo& info)
34   : controller(_controller)
35   {
36     createInfo = info;
37     if(info.shaderState)
38     {
39       createInfo.shaderState = new std::vector<ShaderState>(*info.shaderState);
40     }
41   }
42
43   ~Impl()
44   {
45     delete createInfo.shaderState;
46   }
47
48   EglGraphicsController& controller;
49   ProgramCreateInfo      createInfo;
50   uint32_t               glProgram{};
51   uint32_t               refCount{0u};
52
53   std::unique_ptr<GLES::Reflection> reflection{nullptr};
54 };
55
56 ProgramImpl::ProgramImpl(const Graphics::ProgramCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
57 {
58   // Create implementation
59   mImpl = std::make_unique<Impl>(controller, createInfo);
60
61   // Build reflection
62   mImpl->reflection = std::make_unique<GLES::Reflection>(*this, controller);
63 }
64
65 ProgramImpl::~ProgramImpl() = default;
66
67 bool ProgramImpl::Destroy()
68 {
69   if(mImpl->glProgram)
70   {
71     auto& gl = *mImpl->controller.GetGL();
72     gl.DeleteProgram(mImpl->glProgram);
73     return true;
74   }
75   return false;
76 }
77
78 bool ProgramImpl::Create()
79 {
80   // Create and link new program
81   auto& gl      = *mImpl->controller.GetGL();
82   auto  program = gl.CreateProgram();
83
84   const auto& info = mImpl->createInfo;
85   for(const auto& state : *info.shaderState)
86   {
87     const auto* shader = static_cast<const GLES::Shader*>(state.shader);
88
89     // Compile shader first (ignored when compiled)
90     shader->Compile();
91
92     gl.AttachShader(program, shader->GetGLShader());
93   }
94   gl.LinkProgram(program);
95
96   GLint status{0};
97   gl.GetProgramiv(program, GL_LINK_STATUS, &status);
98   if(status != GL_TRUE)
99   {
100     char    output[4096];
101     GLsizei size{0u};
102     gl.GetProgramInfoLog(program, 4096, &size, output);
103
104     // log on error
105     // TODO: un-printf-it
106     printf("Log: %s\n", output);
107     gl.DeleteProgram(program);
108     return false;
109   }
110
111   mImpl->glProgram = program;
112
113   // Initialize reflection
114   mImpl->reflection->BuildUniformReflection();
115   mImpl->reflection->BuildVertexAttributeReflection();
116
117   return true;
118 }
119
120 uint32_t ProgramImpl::GetGlProgram() const
121 {
122   return mImpl->glProgram;
123 }
124
125 uint32_t ProgramImpl::Retain()
126 {
127   return ++mImpl->refCount;
128 }
129
130 uint32_t ProgramImpl::Release()
131 {
132   return --mImpl->refCount;
133 }
134
135 const GLES::Reflection& ProgramImpl::GetReflection() const
136 {
137   return *mImpl->reflection;
138 }
139
140 bool ProgramImpl::GetParameter(uint32_t parameterId, void* out)
141 {
142   if(parameterId == 1) // a magic number to access program id
143   {
144     *reinterpret_cast<decltype(&mImpl->glProgram)>(out) = mImpl->glProgram;
145     return true;
146   }
147   return false;
148 }
149
150 EglGraphicsController& ProgramImpl::GetController() const
151 {
152   return mImpl->controller;
153 }
154
155 const ProgramCreateInfo& ProgramImpl::GetCreateInfo() const
156 {
157   return mImpl->createInfo;
158 }
159
160 Program::~Program()
161 {
162   // Destroy GL resources of implementation. This should happen
163   // only if there's no more pipelines using this program so
164   // it is safe to do it in the destructor
165   if(!mProgram->Release())
166   {
167     mProgram->Destroy();
168   }
169 }
170
171 const GLES::Reflection& Program::GetReflection() const
172 {
173   return mProgram->GetReflection();
174 }
175
176 EglGraphicsController& Program::GetController() const
177 {
178   return GetImplementation()->GetController();
179 }
180
181 const ProgramCreateInfo& Program::GetCreateInfo() const
182 {
183   return GetImplementation()->GetCreateInfo();
184 }
185
186 void Program::DiscardResource()
187 {
188   GetController().DiscardResource(this);
189 }
190
191 }; // namespace Dali::Graphics::GLES