Merge "Dummy graphics controller for test suite" into devel/graphics
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / border / border-visual.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 // CLASS HEADER
19 #include "border-visual.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/rendering/renderer-devel.h>
23 #include <dali/integration-api/debug.h>
24
25 // INTERNAL INCLUDES
26 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
27 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
28 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
29 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
30 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
31 #include <dali-toolkit/public-api/visuals/border-visual-properties.h>
32 #include <dali-toolkit/public-api/visuals/visual-properties.h>
33
34 namespace Dali
35 {
36 namespace Toolkit
37 {
38 namespace Internal
39 {
40 namespace
41 {
42 const char* const POSITION_ATTRIBUTE_NAME("aPosition");
43 const char* const DRIFT_ATTRIBUTE_NAME("aDrift");
44 const char* const INDEX_NAME("indices");
45 } // namespace
46
47 BorderVisualPtr BorderVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties)
48 {
49   BorderVisualPtr borderVisualPtr(new BorderVisual(factoryCache));
50   borderVisualPtr->SetProperties(properties);
51   borderVisualPtr->Initialize();
52   return borderVisualPtr;
53 }
54
55 BorderVisual::BorderVisual(VisualFactoryCache& factoryCache)
56 : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::BORDER),
57   mBorderColor(Color::TRANSPARENT),
58   mBorderSize(0.f),
59   mBorderColorIndex(Property::INVALID_INDEX),
60   mBorderSizeIndex(Property::INVALID_INDEX),
61   mAntiAliasing(false)
62 {
63 }
64
65 BorderVisual::~BorderVisual()
66 {
67 }
68
69 void BorderVisual::DoSetProperties(const Property::Map& propertyMap)
70 {
71   for(Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter)
72   {
73     KeyValuePair keyValue = propertyMap.GetKeyValue(iter);
74     if(keyValue.first.type == Property::Key::INDEX)
75     {
76       DoSetProperty(keyValue.first.indexKey, keyValue.second);
77     }
78     else
79     {
80       if(keyValue.first == COLOR_NAME)
81       {
82         DoSetProperty(Toolkit::BorderVisual::Property::COLOR, keyValue.second);
83       }
84       else if(keyValue.first == SIZE_NAME)
85       {
86         DoSetProperty(Toolkit::BorderVisual::Property::SIZE, keyValue.second);
87       }
88       else if(keyValue.first == ANTI_ALIASING)
89       {
90         DoSetProperty(Toolkit::BorderVisual::Property::ANTI_ALIASING, keyValue.second);
91       }
92     }
93   }
94 }
95
96 void BorderVisual::DoSetProperty(Dali::Property::Index        index,
97                                  const Dali::Property::Value& value)
98 {
99   switch(index)
100   {
101     case Toolkit::BorderVisual::Property::COLOR:
102     {
103       if(!value.Get(mBorderColor))
104       {
105         DALI_LOG_ERROR("BorderVisual: borderColor property has incorrect type\n");
106       }
107       break;
108     }
109     case Toolkit::BorderVisual::Property::SIZE:
110     {
111       if(!value.Get(mBorderSize))
112       {
113         DALI_LOG_ERROR("BorderVisual: borderSize property has incorrect type\n");
114       }
115       break;
116     }
117     case Toolkit::BorderVisual::Property::ANTI_ALIASING:
118     {
119       if(!value.Get(mAntiAliasing))
120       {
121         DALI_LOG_ERROR("BorderVisual: antiAliasing property has incorrect type\n");
122       }
123       break;
124     }
125   }
126 }
127
128 void BorderVisual::DoSetOnScene(Actor& actor)
129 {
130   mBorderColorIndex = mImpl->mRenderer.RegisterProperty(Toolkit::BorderVisual::Property::COLOR, COLOR_NAME, mBorderColor);
131   if(mBorderColor.a < 1.f || mAntiAliasing)
132   {
133     mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
134   }
135   mBorderSizeIndex = mImpl->mRenderer.RegisterProperty(Toolkit::BorderVisual::Property::SIZE, SIZE_NAME, mBorderSize);
136
137   actor.AddRenderer(mImpl->mRenderer);
138
139   // Border Visual Generated and ready to display
140   ResourceReady(Toolkit::Visual::ResourceStatus::READY);
141 }
142
143 void BorderVisual::DoCreatePropertyMap(Property::Map& map) const
144 {
145   map.Clear();
146   map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::BORDER);
147   map.Insert(Toolkit::BorderVisual::Property::COLOR, mBorderColor);
148   map.Insert(Toolkit::BorderVisual::Property::SIZE, mBorderSize);
149   map.Insert(Toolkit::BorderVisual::Property::ANTI_ALIASING, mAntiAliasing);
150 }
151
152 void BorderVisual::DoCreateInstancePropertyMap(Property::Map& map) const
153 {
154   // Do nothing
155 }
156
157 void BorderVisual::OnSetTransform()
158 {
159   if(mImpl->mRenderer)
160   {
161     mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
162   }
163 }
164
165 void BorderVisual::OnInitialize()
166 {
167   Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::BORDER_GEOMETRY);
168   if(!geometry)
169   {
170     geometry = CreateBorderGeometry();
171     mFactoryCache.SaveGeometry(VisualFactoryCache::BORDER_GEOMETRY, geometry);
172   }
173
174   Shader shader    = GetBorderShader();
175   mImpl->mRenderer = Renderer::New(geometry, shader);
176
177   //Register transform properties
178   mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
179 }
180
181 Shader BorderVisual::GetBorderShader()
182 {
183   Shader shader;
184   if(mAntiAliasing)
185   {
186     shader = mFactoryCache.GetShader(VisualFactoryCache::BORDER_SHADER_ANTI_ALIASING);
187     if(!shader)
188     {
189       shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_BORDER_VISUAL_ANTI_ALIASING_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_BORDER_VISUAL_ANTI_ALIASING_SHADER_FRAG.data());
190       mFactoryCache.SaveShader(VisualFactoryCache::BORDER_SHADER_ANTI_ALIASING, shader);
191     }
192   }
193   else
194   {
195     shader = mFactoryCache.GetShader(VisualFactoryCache::BORDER_SHADER);
196     if(!shader)
197     {
198       shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_BORDER_VISUAL_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_BORDER_VISUAL_SHADER_FRAG.data());
199       mFactoryCache.SaveShader(VisualFactoryCache::BORDER_SHADER, shader);
200     }
201   }
202
203   return shader;
204 }
205
206 /**
207  * Vertices and triangles of the border geometry:
208  *
209  * vertex position = aPosition*uSize.xy + aDrift*uBorderSize;
210  *
211  * 0--1--2--3
212  * |\ | /| /|
213  * | \|/ |/ |
214  * 4--5--6--7
215  * |\ |  |\ |
216  * | \|  | \|
217  * 8--9--10-11
218  * | /| /|\ |
219  * |/ |/ | \|
220  * 12-13-14-15
221  */
222 Geometry BorderVisual::CreateBorderGeometry()
223 {
224   const float halfWidth  = 0.5f;
225   const float halfHeight = 0.5f;
226   struct BorderVertex
227   {
228     Vector2 position;
229     Vector2 drift;
230   };
231   BorderVertex borderVertexData[16] =
232     {
233       {Vector2(-halfWidth, -halfHeight), Vector2(0.f, 0.f)},
234       {Vector2(-halfWidth, -halfHeight), Vector2(1.f, 0.f)},
235       {Vector2(halfWidth, -halfHeight), Vector2(-1.f, 0.f)},
236       {Vector2(halfWidth, -halfHeight), Vector2(0.f, 0.f)},
237
238       {Vector2(-halfWidth, -halfHeight), Vector2(0.f, 1.f)},
239       {Vector2(-halfWidth, -halfHeight), Vector2(1.f, 1.f)},
240       {Vector2(halfWidth, -halfHeight), Vector2(-1.f, 1.f)},
241       {Vector2(halfWidth, -halfHeight), Vector2(0.f, 1.f)},
242
243       {Vector2(-halfWidth, halfHeight), Vector2(0.f, -1.f)},
244       {Vector2(-halfWidth, halfHeight), Vector2(1.f, -1.f)},
245       {Vector2(halfWidth, halfHeight), Vector2(-1.f, -1.f)},
246       {Vector2(halfWidth, halfHeight), Vector2(0.f, -1.f)},
247
248       {Vector2(-halfWidth, halfHeight), Vector2(0.f, 0.f)},
249       {Vector2(-halfWidth, halfHeight), Vector2(1.f, 0.f)},
250       {Vector2(halfWidth, halfHeight), Vector2(-1.f, 0.f)},
251       {Vector2(halfWidth, halfHeight), Vector2(0.f, 0.f)},
252     };
253
254   Property::Map borderVertexFormat;
255   borderVertexFormat[POSITION_ATTRIBUTE_NAME] = Property::VECTOR2;
256   borderVertexFormat[DRIFT_ATTRIBUTE_NAME]    = Property::VECTOR2;
257   VertexBuffer borderVertices                 = VertexBuffer::New(borderVertexFormat);
258   borderVertices.SetData(borderVertexData, 16);
259
260   // Create indices
261   unsigned short indexData[24] = {1, 5, 2, 6, 3, 7, 7, 6, 11, 10, 15, 14, 14, 10, 13, 9, 12, 8, 8, 9, 4, 5, 0, 1};
262
263   // Create the geometry object
264   Geometry geometry = Geometry::New();
265   geometry.AddVertexBuffer(borderVertices);
266   geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
267   geometry.SetType(Geometry::TRIANGLE_STRIP);
268
269   return geometry;
270 }
271
272 } // namespace Internal
273
274 } // namespace Toolkit
275
276 } // namespace Dali