Revert "[4.0] (AnimatedVectorImageVisual) Change renderer on stage again"
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / animated-vector-image-visual.cpp
1 /*
2  * Copyright (c) 2018 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-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/stage-devel.h>
24 #include <dali/integration-api/debug.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
28 #include <dali-toolkit/public-api/visuals/visual-properties.h>
29 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
30 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
31 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h>
32 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
33 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
34 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
35 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
36 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
37
38 namespace Dali
39 {
40
41 namespace Toolkit
42 {
43
44 namespace Internal
45 {
46
47 namespace
48 {
49
50 const Dali::Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
51 constexpr auto LOOP_FOREVER = -1;
52
53 } // unnamed namespace
54
55 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
56 {
57   AnimatedVectorImageVisualPtr visual( new AnimatedVectorImageVisual( factoryCache, shaderFactory, imageUrl ) );
58   visual->SetProperties( properties );
59
60   return visual;
61 }
62
63 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
64 {
65   AnimatedVectorImageVisualPtr visual( new AnimatedVectorImageVisual( factoryCache, shaderFactory, imageUrl ) );
66
67   return visual;
68 }
69
70 AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
71 : Visual::Base( factoryCache ),
72   mImageVisualShaderFactory( shaderFactory ),
73   mUrl( imageUrl ),
74   mVisualSize(),
75   mPlayRange( 0.0f, 1.0f ),
76   mPlacementActor(),
77   mVectorRasterizeThread(),
78   mLoopCount( LOOP_FOREVER ),
79   mActionStatus( DevelAnimatedVectorImageVisual::Action::STOP )
80 {
81   // the rasterized image is with pre-multiplied alpha format
82   mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
83 }
84
85 AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
86 {
87 }
88
89 void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize )
90 {
91   naturalSize = mVisualSize;
92 }
93
94 void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const
95 {
96   map.Clear();
97   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::ANIMATED_VECTOR_IMAGE );
98   if( mUrl.IsValid() )
99   {
100     map.Insert( Toolkit::ImageVisual::Property::URL, mUrl.GetUrl() );
101   }
102   map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast< int >( mLoopCount ) );
103   map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, static_cast< Vector2 >( mPlayRange ) );
104
105   if( mVectorRasterizeThread )
106   {
107     map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( mVectorRasterizeThread->GetPlayState() ) );
108   }
109   else
110   {
111     map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( DevelImageVisual::PlayState::STOPPED ) );
112   }
113 }
114
115 void AnimatedVectorImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
116 {
117   // Do nothing
118 }
119
120 void AnimatedVectorImageVisual::DoSetProperties( const Property::Map& propertyMap )
121 {
122   // url already passed in from constructor
123   for( Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter )
124   {
125     KeyValuePair keyValue = propertyMap.GetKeyValue( iter );
126     if( keyValue.first.type == Property::Key::INDEX )
127     {
128       DoSetProperty( keyValue.first.indexKey, keyValue.second );
129     }
130     else
131     {
132        if( keyValue.first == LOOP_COUNT_NAME )
133        {
134           DoSetProperty( Toolkit::DevelImageVisual::Property::LOOP_COUNT, keyValue.second );
135        }
136        else if( keyValue.first == PLAY_RANGE_NAME )
137        {
138           DoSetProperty( Toolkit::DevelImageVisual::Property::PLAY_RANGE, keyValue.second );
139        }
140     }
141   }
142 }
143
144 void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Property::Value& value )
145 {
146   switch(index)
147   {
148     case Toolkit::DevelImageVisual::Property::LOOP_COUNT:
149     {
150       int32_t loopCount;
151       if( value.Get( loopCount ) )
152       {
153         mLoopCount = loopCount;
154         if( mVectorRasterizeThread )
155         {
156           mVectorRasterizeThread->SetLoopCount( loopCount );
157         }
158       }
159       break;
160     }
161     case Toolkit::DevelImageVisual::Property::PLAY_RANGE:
162     {
163       Vector2 range;
164       if( value.Get( range ) )
165       {
166         // Make sure the range specified is between 0.0 and 1.0
167         if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
168         {
169           Vector2 orderedRange( range );
170           // If the range is not in order swap values
171           if( range.x > range.y )
172           {
173             orderedRange = Vector2( range.y, range.x );
174           }
175
176           mPlayRange = orderedRange;
177
178           if( mVectorRasterizeThread )
179           {
180             mVectorRasterizeThread->SetPlayRange( mPlayRange );
181           }
182         }
183       }
184       break;
185     }
186   }
187 }
188
189 void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor )
190 {
191   Shader shader;
192
193   if( mImpl->mCustomShader )
194   {
195     shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
196                           mImpl->mCustomShader->mFragmentShader.empty() ? mImageVisualShaderFactory.GetFragmentShaderSource() : mImpl->mCustomShader->mFragmentShader,
197                           mImpl->mCustomShader->mHints );
198
199     shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
200   }
201   else
202   {
203     shader = mImageVisualShaderFactory.GetShader( mFactoryCache, false, true );
204   }
205
206   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
207
208   mImpl->mRenderer = Renderer::New( geometry, shader );
209
210   TextureSet textureSet = TextureSet::New();
211   mImpl->mRenderer.SetTextures( textureSet );
212
213   // Register transform properties
214   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
215
216   // Defer the rasterisation task until we get given a size (by Size Negotiation algorithm)
217
218   // Hold the weak handle of the placement actor and delay the adding of renderer until the rasterization is finished.
219   mPlacementActor = actor;
220
221   // This visual needs it's size set before it can be rasterized hence set ResourceReady once on stage
222   ResourceReady( Toolkit::Visual::ResourceStatus::READY );
223 }
224
225 void AnimatedVectorImageVisual::DoSetOffStage( Actor& actor )
226 {
227   if( mVectorRasterizeThread )
228   {
229     mVectorRasterizeThread->PauseAnimation();
230     DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
231     mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
232   }
233
234   if( mImpl->mRenderer )
235   {
236     actor.RemoveRenderer( mImpl->mRenderer );
237     mImpl->mRenderer.Reset();
238   }
239
240   mPlacementActor.Reset();
241
242   // Reset the visual size to zero so that when adding the actor back to stage the rasterization is forced
243   mVisualSize = Vector2::ZERO;
244 }
245
246 void AnimatedVectorImageVisual::OnSetTransform()
247 {
248   Vector2 visualSize = mImpl->mTransform.GetVisualSize( mImpl->mControlSize );
249
250   if( IsOnStage() )
251   {
252     if( visualSize != mVisualSize )
253     {
254       mVisualSize = visualSize;
255
256       if( !mVectorRasterizeThread )
257       {
258         uint32_t width = static_cast< uint32_t >( visualSize.width );
259         uint32_t height = static_cast< uint32_t >( visualSize.height );
260
261         mVectorRasterizeThread = std::unique_ptr< VectorRasterizeThread >( new VectorRasterizeThread( mUrl.GetUrl(), mImpl->mRenderer, width, height ) );
262
263         mVectorRasterizeThread->SetResourceReadyCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnResourceReady ) ) );
264         mVectorRasterizeThread->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
265         mVectorRasterizeThread->SetLoopCount( mLoopCount );
266         mVectorRasterizeThread->SetPlayRange( mPlayRange );
267
268         mVectorRasterizeThread->Start();
269
270         if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY )
271         {
272           mVectorRasterizeThread->StartAnimation();
273           DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY );
274         }
275         else
276         {
277           // Render one frame
278           mVectorRasterizeThread->RenderFrame();
279         }
280       }
281       else
282       {
283         uint32_t width = static_cast< uint32_t >( visualSize.width );
284         uint32_t height = static_cast< uint32_t >( visualSize.height );
285
286         mVectorRasterizeThread->SetSize( width, height );
287       }
288     }
289   }
290 }
291
292 void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, const Property::Value& attributes )
293 {
294   // Check if action is valid for this visual type and perform action if possible
295   switch( actionId )
296   {
297     case DevelAnimatedVectorImageVisual::Action::PLAY:
298     {
299       if( IsOnStage())
300       {
301         if( mVectorRasterizeThread )
302         {
303           mVectorRasterizeThread->StartAnimation();
304           DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY );   //TODO: Should manage this globally
305         }
306       }
307       mActionStatus = DevelAnimatedVectorImageVisual::Action::PLAY;
308       break;
309     }
310     case DevelAnimatedVectorImageVisual::Action::PAUSE:
311     {
312       if( mVectorRasterizeThread )
313       {
314         mVectorRasterizeThread->PauseAnimation();
315         DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
316       }
317       mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
318       break;
319     }
320     case DevelAnimatedVectorImageVisual::Action::STOP:
321     {
322       if( mVectorRasterizeThread )
323       {
324         bool emitSignal = false;
325         if( mVectorRasterizeThread->GetPlayState() != DevelImageVisual::PlayState::STOPPED )
326         {
327           emitSignal = true;
328         }
329
330         mVectorRasterizeThread->StopAnimation();
331         DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
332
333         if( emitSignal )
334         {
335           OnAnimationFinished();
336         }
337       }
338       mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP;
339       break;
340     }
341   }
342 }
343
344 void AnimatedVectorImageVisual::OnResourceReady()
345 {
346   // If weak handle is holding a placement actor, it is the time to add the renderer to actor.
347   Actor actor = mPlacementActor.GetHandle();
348   if( actor )
349   {
350     actor.AddRenderer( mImpl->mRenderer );
351     // reset the weak handle so that the renderer only get added to actor once
352     mPlacementActor.Reset();
353
354     Stage::GetCurrent().KeepRendering( 0.0f );
355   }
356 }
357
358 void AnimatedVectorImageVisual::OnAnimationFinished()
359 {
360   if( mImpl->mEventObserver )
361   {
362     mImpl->mEventObserver->NotifyVisualEvent( *this, DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED );
363   }
364 }
365
366 } // namespace Internal
367
368 } // namespace Toolkit
369
370 } // namespace Dali