Revert "VectorAnimationRenderer: Updated dependancy from lotti-player to rlottie...
[platform/core/uifw/dali-extension.git] / dali-extension / vector-animation-renderer / tizen-vector-animation-renderer.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-extension/vector-animation-renderer/tizen-vector-animation-renderer.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/devel-api/adaptor-framework/native-image-source-queue.h>
24 #include <dali/devel-api/images/native-image-interface-extension.h>
25 #include <cstring> // for strlen()
26 #include <tbm_surface_internal.h>
27
28 // The plugin factories
29 extern "C" DALI_EXPORT_API Dali::VectorAnimationRendererPlugin* CreateVectorAnimationRendererPlugin( void )
30 {
31   return new Dali::Plugin::TizenVectorAnimationRenderer;
32 }
33
34 namespace Dali
35 {
36
37 namespace Plugin
38 {
39
40 namespace
41 {
42
43 const char* const DEFAULT_SAMPLER_TYPENAME( "sampler2D" );
44 const char* const PIXEL_AREA_UNIFORM_NAME( "pixelArea" );
45
46 const Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
47
48 } // unnamed namespace
49
50 TizenVectorAnimationRenderer::TizenVectorAnimationRenderer()
51 : mUrl(),
52   mBuffers(),
53   mMutex(),
54   mTargetSurface(),
55   mRenderer(),
56   mTbmQueue( NULL ),
57   mTotalFrameNumber( 0 ),
58   mWidth( 0 ),
59   mHeight( 0 )
60 {
61 }
62
63 TizenVectorAnimationRenderer::~TizenVectorAnimationRenderer()
64 {
65   Dali::Mutex::ScopedLock lock( mMutex );
66
67   for( auto&& iter : mBuffers )
68   {
69     tbm_surface_internal_unref( iter.first );
70   }
71   mBuffers.clear();
72
73   if( mTbmQueue != NULL )
74   {
75     tbm_surface_queue_destroy( mTbmQueue );
76   }
77 }
78
79 bool TizenVectorAnimationRenderer::CreateRenderer( const std::string& url, Renderer renderer, uint32_t width, uint32_t height )
80 {
81   mUrl = url;
82   mWidth = width;
83   mHeight = height;
84
85   mTargetSurface = NativeImageSourceQueue::New( mWidth, mHeight, NativeImageSourceQueue::COLOR_DEPTH_DEFAULT );
86
87   TextureSet textureSet = renderer.GetTextures();
88
89   Texture texture = Texture::New( *mTargetSurface );
90   textureSet.SetTexture( 0, texture );
91
92   SetShader( renderer );
93
94   mTbmQueue = AnyCast< tbm_surface_queue_h >( mTargetSurface->GetNativeImageSourceQueue() );
95
96   DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::CreateRenderer: file [%s]\n", url.c_str() );
97
98   return true;
99 }
100
101 void TizenVectorAnimationRenderer::SetSize( uint32_t width, uint32_t height )
102 {
103   Dali::Mutex::ScopedLock lock( mMutex );
104
105   mTargetSurface->SetSize( width, height );
106
107   mWidth = width;
108   mHeight = height;
109
110   // Reset the buffer list
111   for( auto&& iter : mBuffers )
112   {
113     tbm_surface_internal_unref( iter.first );
114   }
115   mBuffers.clear();
116
117   DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::SetSize: width = %d, height = %d\n", mWidth, mHeight );
118 }
119
120 bool TizenVectorAnimationRenderer::StartRender()
121 {
122   mRenderer = lottie::Animation::loadFromFile( mUrl );
123   if( !mRenderer )
124   {
125     DALI_LOG_ERROR( "Failed to load a Lottie file [%s]\n", mUrl.c_str() );
126     return false;
127   }
128
129   mTotalFrameNumber = mRenderer->totalFrame();
130
131   DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::StartRender: file [%s]\n", mUrl.c_str() );
132
133   return true;
134 }
135
136 void TizenVectorAnimationRenderer::StopRender()
137 {
138   Dali::Mutex::ScopedLock lock( mMutex );
139
140   if( mTbmQueue )
141   {
142     tbm_surface_queue_flush( mTbmQueue );
143
144     DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::StopRender: Stopped\n" );
145   }
146 }
147
148 void TizenVectorAnimationRenderer::Render( uint32_t frameNumber )
149 {
150   Dali::Mutex::ScopedLock lock( mMutex );
151
152   if( tbm_surface_queue_can_dequeue( mTbmQueue, 1 ) )
153   {
154     tbm_surface_h tbmSurface;
155
156     if( tbm_surface_queue_dequeue( mTbmQueue, &tbmSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
157     {
158       DALI_LOG_ERROR( "Failed to dequeue a tbm_surface\n" );
159       return;
160     }
161
162     tbm_surface_info_s info;
163     tbm_surface_map( tbmSurface, TBM_OPTION_WRITE, &info );
164
165     bool existing = false;
166     for( auto&& iter : mBuffers )
167     {
168       if( iter.first == tbmSurface )
169       {
170         // Find the buffer in the existing list
171         existing = true;
172
173         // Render the frame
174         mRenderer->renderSync( frameNumber, iter.second );
175         break;
176       }
177     }
178
179     if( !existing )
180     {
181       tbm_surface_internal_ref( tbmSurface );
182
183       unsigned char* buffer = info.planes[0].ptr;
184
185       // Create Surface object
186       lottie::Surface surface( reinterpret_cast< uint32_t* >( buffer ), mWidth, mHeight, static_cast< size_t >( info.planes[0].stride ) );
187
188       // Push the buffer
189       mBuffers.push_back( SurfacePair( tbmSurface, surface ) );
190
191       // Render the frame
192       mRenderer->renderSync( frameNumber, surface );
193     }
194
195     tbm_surface_unmap( tbmSurface );
196
197     tbm_surface_queue_enqueue( mTbmQueue, tbmSurface );
198   }
199   else
200   {
201     DALI_LOG_ERROR( "Cannot dequeue a tbm_surface [%d]\n", frameNumber );
202   }
203 }
204
205 uint32_t TizenVectorAnimationRenderer::GetTotalFrameNumber()
206 {
207   return mTotalFrameNumber;
208 }
209
210 void TizenVectorAnimationRenderer::SetShader( Renderer renderer )
211 {
212   NativeImageInterface::Extension* extension = static_cast< NativeImageInterface* >( mTargetSurface.Get() )->GetExtension();
213   if( extension )
214   {
215     Shader shader = renderer.GetShader();
216
217     std::string fragmentShader;
218     std::string vertexShader;
219
220     // Get custom fragment shader prefix
221     const char* fragmentPreFix = extension->GetCustomFragmentPreFix();
222     if( fragmentPreFix )
223     {
224       fragmentShader = fragmentPreFix;
225       fragmentShader += "\n";
226     }
227
228     // Get the current fragment shader source
229     Property::Value program = shader.GetProperty( Shader::Property::PROGRAM );
230     Property::Map* map = program.GetMap();
231     if( map )
232     {
233       Property::Value* fragment = map->Find( "fragment" );
234       if( fragment )
235       {
236         fragmentShader += fragment->Get< std::string >();
237       }
238
239       Property::Value* vertex = map->Find( "vertex" );
240       if( vertex )
241       {
242         vertexShader = vertex->Get< std::string >();
243       }
244     }
245
246     // Get custom sampler type name
247     const char* customSamplerTypename = extension->GetCustomSamplerTypename();
248     if( customSamplerTypename )
249     {
250       size_t position = fragmentShader.find( DEFAULT_SAMPLER_TYPENAME );
251       if( position != std::string::npos )
252       {
253         fragmentShader.replace( position, strlen( DEFAULT_SAMPLER_TYPENAME ), customSamplerTypename );
254       }
255     }
256
257     // Set the modified shader again
258     Shader newShader = Shader::New( vertexShader, fragmentShader );
259     newShader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
260
261     renderer.SetShader( newShader );
262
263     DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::SetShader: Shader is changed\n" );
264   }
265 }
266
267 } // namespace Plugin
268
269 } // namespace Dali;