CanvasRenderer: Refactoring tvgObject management
[platform/core/uifw/dali-adaptor.git] / dali / internal / canvas-renderer / tizen / canvas-renderer-impl-tizen.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 <dali/internal/canvas-renderer/tizen/canvas-renderer-impl-tizen.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/object/type-registry.h>
24
25 // INTERNAL INCLUDES
26 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
27 #include <dali/internal/canvas-renderer/common/drawable-group-impl.h>
28 #include <dali/internal/canvas-renderer/common/drawable-impl.h>
29 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
30
31 namespace Dali
32 {
33 namespace Internal
34 {
35 namespace Adaptor
36 {
37 namespace // unnamed namespace
38 {
39 // Type Registration
40 Dali::BaseHandle Create()
41 {
42   return Dali::BaseHandle();
43 }
44
45 Dali::TypeRegistration type(typeid(Dali::CanvasRenderer), typeid(Dali::BaseHandle), Create);
46
47 } // unnamed namespace
48
49 CanvasRendererTizen* CanvasRendererTizen::New(const Vector2& viewBox)
50 {
51   return new CanvasRendererTizen(viewBox);
52 }
53
54 CanvasRendererTizen::CanvasRendererTizen(const Vector2& viewBox)
55 : mPixelBuffer(nullptr),
56 #ifdef THORVG_SUPPORT
57   mTvgCanvas(nullptr),
58   mTvgRoot(nullptr),
59 #endif
60   mSize(0, 0),
61   mViewBox(0, 0),
62   mChanged(false)
63 {
64   Initialize(viewBox);
65 }
66
67 CanvasRendererTizen::~CanvasRendererTizen()
68 {
69 #ifdef THORVG_SUPPORT
70   //This clear function will do free all tvg::Paint object that added.
71   if(mTvgCanvas->clear() != tvg::Result::Success)
72   {
73     DALI_LOG_ERROR("ThorVG canvas clear fail [%p]\n", this);
74   }
75
76   mDrawables.clear();
77
78   //Terminate ThorVG Engine
79   tvg::Initializer::term(tvg::CanvasEngine::Sw);
80 #endif
81 }
82
83 void CanvasRendererTizen::Initialize(const Vector2& viewBox)
84 {
85 #ifdef THORVG_SUPPORT
86   if(tvg::Initializer::init(tvg::CanvasEngine::Sw, 0 /*threads*/) != tvg::Result::Success)
87   {
88     DALI_LOG_ERROR("ThorVG engine initialize failed\n");
89   }
90   mTvgCanvas = tvg::SwCanvas::gen();
91
92   mSize = mViewBox = viewBox;
93   if(viewBox.width < 1.0f || viewBox.height < 1.0f)
94   {
95     return;
96   }
97
98   MakeTargetBuffer(mSize);
99 #endif
100 }
101
102 bool CanvasRendererTizen::Commit()
103 {
104 #ifdef THORVG_SUPPORT
105   bool changed = false;
106
107   for(auto& it : mDrawables)
108   {
109     Internal::Adaptor::Drawable& drawableImpl = GetImplementation(it);
110     if(drawableImpl.GetChanged())
111     {
112       changed = true;
113       drawableImpl.SetChanged(false);
114     }
115   }
116
117   if(!changed && !mChanged)
118   {
119     return false;
120   }
121   else
122   {
123     if(!mPixelBuffer.GetBuffer())
124     {
125       MakeTargetBuffer(mSize);
126       mChanged = false;
127     }
128   }
129
130   if(mSize.width < 1.0f || mSize.height < 1.0f)
131   {
132     DALI_LOG_ERROR("Size is zero [%p]\n", this);
133     return false;
134   }
135
136   if(mTvgCanvas->clear() != tvg::Result::Success)
137   {
138     DALI_LOG_ERROR("ThorVG canvas clear fail [%p]\n", this);
139     return false;
140   }
141
142   auto scene = tvg::Scene::gen();
143   mTvgRoot   = scene.get();
144   if(mTvgCanvas->push(move(scene)) != tvg::Result::Success)
145   {
146     DALI_LOG_ERROR("ThorVG canvas push fail [%p]\n", this);
147     return false;
148   }
149
150   for(auto& it : mDrawables)
151   {
152     PushDrawableToParent(it, mTvgRoot);
153   }
154
155   if(mViewBox != mSize)
156   {
157     auto scaleX = mSize.width / mViewBox.width;
158     auto scaleY = mSize.height / mViewBox.height;
159     mTvgRoot->scale(scaleX < scaleY ? scaleX : scaleY);
160   }
161   mTvgCanvas->update(mTvgRoot);
162
163   if(mTvgCanvas->draw() != tvg::Result::Success)
164   {
165     DALI_LOG_ERROR("ThorVG Draw fail [%p]\n", this);
166     return false;
167   }
168
169   mTvgCanvas->sync();
170
171   return true;
172 #else
173   return false;
174 #endif
175 }
176
177 Devel::PixelBuffer CanvasRendererTizen::GetPixelBuffer()
178 {
179   return mPixelBuffer;
180 }
181
182 bool CanvasRendererTizen::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
183 {
184 #ifdef THORVG_SUPPORT
185   for(auto& it : mDrawables)
186   {
187     if(it == drawable)
188     {
189       DALI_LOG_ERROR("Already added [%p]\n", this);
190       return false;
191     }
192   }
193
194   Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
195   if(mSize.width < 1.0f || mSize.height < 1.0f)
196   {
197     DALI_LOG_ERROR("Size is zero [%p]\n", this);
198     return false;
199   }
200
201   drawableImpl.SetDrawableAdded(true);
202   mDrawables.push_back(drawable);
203   mChanged = true;
204
205   return true;
206 #else
207   return false;
208 #endif
209 }
210
211 bool CanvasRendererTizen::SetSize(const Vector2& size)
212 {
213   if(size.width < 1.0f || size.height < 1.0f)
214   {
215     return false;
216   }
217
218   if(size != mSize)
219   {
220     mSize = size;
221     MakeTargetBuffer(size);
222   }
223
224   mChanged = true;
225
226   return true;
227 }
228
229 const Vector2& CanvasRendererTizen::GetSize()
230 {
231   return mSize;
232 }
233
234 void CanvasRendererTizen::MakeTargetBuffer(const Vector2& size)
235 {
236 #ifdef THORVG_SUPPORT
237   mPixelBuffer = Devel::PixelBuffer::New(size.width, size.height, Dali::Pixel::RGBA8888);
238
239   unsigned char* pBuffer;
240   pBuffer = mPixelBuffer.GetBuffer();
241
242   if(!pBuffer)
243   {
244     DALI_LOG_ERROR("Pixel buffer create to fail [%p]\n", this);
245     return;
246   }
247
248   mTvgCanvas->target(reinterpret_cast<uint32_t*>(pBuffer), size.width, size.width, size.height, tvg::SwCanvas::ABGR8888);
249 #endif
250 }
251
252 #ifdef THORVG_SUPPORT
253 void CanvasRendererTizen::PushDrawableToParent(Dali::CanvasRenderer::Drawable& drawable, tvg::Scene* parent)
254 {
255   Internal::Adaptor::Drawable& drawableImpl        = Dali::GetImplementation(drawable);
256   tvg::Paint*                  tvgDuplicatedObject = static_cast<tvg::Paint*>(drawableImpl.GetObject())->duplicate();
257   if(!tvgDuplicatedObject)
258   {
259     DALI_LOG_ERROR("Invalid drawable object [%p]\n", this);
260     return;
261   }
262   Drawable::DrawableTypes type = drawableImpl.GetDrawableType();
263
264   if(type == Drawable::DrawableTypes::DRAWABLE_GROUP)
265   {
266     Dali::CanvasRenderer::DrawableGroup&        group             = static_cast<Dali::CanvasRenderer::DrawableGroup&>(drawable);
267     Internal::Adaptor::DrawableGroup&           drawableGroupImpl = Dali::GetImplementation(group);
268     std::vector<Dali::CanvasRenderer::Drawable> drawables         = drawableGroupImpl.GetDrawables();
269     for(auto& it : drawables)
270     {
271       PushDrawableToParent(it, static_cast<tvg::Scene*>(tvgDuplicatedObject));
272     }
273   }
274
275   if(parent->push(std::move(std::unique_ptr<tvg::Paint>(tvgDuplicatedObject))) != tvg::Result::Success)
276   {
277     DALI_LOG_ERROR("Tvg push fail [%p]\n", this);
278     return;
279   }
280 }
281 #endif
282
283 } // namespace Adaptor
284
285 } // namespace Internal
286
287 } // namespace Dali