64de7080dc153555117cbe2abaaee18d76f6d94e
[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     if(!gl)
73     {
74       return false;
75     }
76     gl->DeleteProgram(mImpl->glProgram);
77     return true;
78   }
79   return false;
80 }
81
82 bool ProgramImpl::Create()
83 {
84   // Create and link new program
85   auto gl = mImpl->controller.GetGL();
86   if(!gl)
87   {
88     // Do nothing during shutdown
89     return false;
90   }
91
92   auto program = gl->CreateProgram();
93
94   const auto& info = mImpl->createInfo;
95   for(const auto& state : *info.shaderState)
96   {
97     const auto* shader = static_cast<const GLES::Shader*>(state.shader);
98
99     // Compile shader first (ignored when compiled)
100     if(shader->Compile())
101     {
102       gl->AttachShader(program, shader->GetGLShader());
103     }
104   }
105   gl->LinkProgram(program);
106
107   GLint status{0};
108   gl->GetProgramiv(program, GL_LINK_STATUS, &status);
109   if(status != GL_TRUE)
110   {
111     char    output[4096];
112     GLsizei size{0u};
113     gl->GetProgramInfoLog(program, 4096, &size, output);
114
115     // log on error
116     // TODO: un-printf-it
117     printf("Log: %s\n", output);
118     gl->DeleteProgram(program);
119     return false;
120   }
121
122   mImpl->glProgram = program;
123
124   // Initialize reflection
125   mImpl->reflection->BuildUniformReflection();
126   mImpl->reflection->BuildVertexAttributeReflection();
127
128   return true;
129 }
130
131 uint32_t ProgramImpl::GetGlProgram() const
132 {
133   return mImpl->glProgram;
134 }
135
136 uint32_t ProgramImpl::Retain()
137 {
138   return ++mImpl->refCount;
139 }
140
141 uint32_t ProgramImpl::Release()
142 {
143   return --mImpl->refCount;
144 }
145
146 const GLES::Reflection& ProgramImpl::GetReflection() const
147 {
148   return *mImpl->reflection;
149 }
150
151 bool ProgramImpl::GetParameter(uint32_t parameterId, void* out)
152 {
153   if(parameterId == 1) // a magic number to access program id
154   {
155     *reinterpret_cast<decltype(&mImpl->glProgram)>(out) = mImpl->glProgram;
156     return true;
157   }
158   return false;
159 }
160
161 EglGraphicsController& ProgramImpl::GetController() const
162 {
163   return mImpl->controller;
164 }
165
166 const ProgramCreateInfo& ProgramImpl::GetCreateInfo() const
167 {
168   return mImpl->createInfo;
169 }
170
171 Program::~Program()
172 {
173   // Destroy GL resources of implementation. This should happen
174   // only if there's no more pipelines using this program so
175   // it is safe to do it in the destructor
176   if(!mProgram->Release())
177   {
178     mProgram->Destroy();
179   }
180 }
181
182 const GLES::Reflection& Program::GetReflection() const
183 {
184   return mProgram->GetReflection();
185 }
186
187 EglGraphicsController& Program::GetController() const
188 {
189   return GetImplementation()->GetController();
190 }
191
192 const ProgramCreateInfo& Program::GetCreateInfo() const
193 {
194   return GetImplementation()->GetCreateInfo();
195 }
196
197 void Program::DiscardResource()
198 {
199   GetController().DiscardResource(this);
200 }
201
202 }; // namespace Dali::Graphics::GLES