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