2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-extension/vector-animation-renderer/tizen-vector-animation-renderer.h>
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>
28 // The plugin factories
29 extern "C" DALI_EXPORT_API Dali::VectorAnimationRendererPlugin* CreateVectorAnimationRendererPlugin( void )
31 return new Dali::Plugin::TizenVectorAnimationRenderer;
43 const char* const DEFAULT_SAMPLER_TYPENAME( "sampler2D" );
44 const char* const PIXEL_AREA_UNIFORM_NAME( "pixelArea" );
46 const Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
48 } // unnamed namespace
50 TizenVectorAnimationRenderer::TizenVectorAnimationRenderer()
57 mTotalFrameNumber( 0 ),
63 TizenVectorAnimationRenderer::~TizenVectorAnimationRenderer()
65 Dali::Mutex::ScopedLock lock( mMutex );
67 for( auto&& iter : mBuffers )
69 tbm_surface_internal_unref( iter.first );
73 if( mTbmQueue != NULL )
75 tbm_surface_queue_destroy( mTbmQueue );
79 bool TizenVectorAnimationRenderer::CreateRenderer( const std::string& url, Renderer renderer, uint32_t width, uint32_t height )
85 mTargetSurface = NativeImageSourceQueue::New( mWidth, mHeight, NativeImageSourceQueue::COLOR_DEPTH_DEFAULT );
87 TextureSet textureSet = renderer.GetTextures();
89 Texture texture = Texture::New( *mTargetSurface );
90 textureSet.SetTexture( 0, texture );
92 SetShader( renderer );
94 mTbmQueue = AnyCast< tbm_surface_queue_h >( mTargetSurface->GetNativeImageSourceQueue() );
96 DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::CreateRenderer: file [%s]\n", url.c_str() );
101 void TizenVectorAnimationRenderer::SetSize( uint32_t width, uint32_t height )
103 Dali::Mutex::ScopedLock lock( mMutex );
105 mTargetSurface->SetSize( width, height );
110 // Reset the buffer list
111 for( auto&& iter : mBuffers )
113 tbm_surface_internal_unref( iter.first );
117 DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::SetSize: width = %d, height = %d\n", mWidth, mHeight );
120 bool TizenVectorAnimationRenderer::StartRender()
122 mRenderer = rlottie::Animation::loadFromFile( mUrl );
125 DALI_LOG_ERROR( "Failed to load a Lottie file [%s]\n", mUrl.c_str() );
129 mTotalFrameNumber = mRenderer->totalFrame();
131 DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::StartRender: file [%s]\n", mUrl.c_str() );
136 void TizenVectorAnimationRenderer::StopRender()
138 Dali::Mutex::ScopedLock lock( mMutex );
142 tbm_surface_queue_flush( mTbmQueue );
144 DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::StopRender: Stopped\n" );
148 void TizenVectorAnimationRenderer::Render( uint32_t frameNumber )
150 Dali::Mutex::ScopedLock lock( mMutex );
152 if( tbm_surface_queue_can_dequeue( mTbmQueue, 1 ) )
154 tbm_surface_h tbmSurface;
156 if( tbm_surface_queue_dequeue( mTbmQueue, &tbmSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
158 DALI_LOG_ERROR( "Failed to dequeue a tbm_surface\n" );
162 tbm_surface_info_s info;
163 tbm_surface_map( tbmSurface, TBM_OPTION_WRITE, &info );
165 bool existing = false;
166 for( auto&& iter : mBuffers )
168 if( iter.first == tbmSurface )
170 // Find the buffer in the existing list
174 mRenderer->renderSync( frameNumber, iter.second );
181 tbm_surface_internal_ref( tbmSurface );
183 unsigned char* buffer = info.planes[0].ptr;
185 // Create Surface object
186 rlottie::Surface surface( reinterpret_cast< uint32_t* >( buffer ), mWidth, mHeight, static_cast< size_t >( info.planes[0].stride ) );
189 mBuffers.push_back( SurfacePair( tbmSurface, surface ) );
192 mRenderer->renderSync( frameNumber, surface );
195 tbm_surface_unmap( tbmSurface );
197 tbm_surface_queue_enqueue( mTbmQueue, tbmSurface );
201 DALI_LOG_ERROR( "Cannot dequeue a tbm_surface [%d]\n", frameNumber );
205 uint32_t TizenVectorAnimationRenderer::GetTotalFrameNumber()
207 return mTotalFrameNumber;
210 void TizenVectorAnimationRenderer::SetShader( Renderer renderer )
212 NativeImageInterface::Extension* extension = static_cast< NativeImageInterface* >( mTargetSurface.Get() )->GetExtension();
215 Shader shader = renderer.GetShader();
217 std::string fragmentShader;
218 std::string vertexShader;
220 // Get custom fragment shader prefix
221 const char* fragmentPreFix = extension->GetCustomFragmentPreFix();
224 fragmentShader = fragmentPreFix;
225 fragmentShader += "\n";
228 // Get the current fragment shader source
229 Property::Value program = shader.GetProperty( Shader::Property::PROGRAM );
230 Property::Map* map = program.GetMap();
233 Property::Value* fragment = map->Find( "fragment" );
236 fragmentShader += fragment->Get< std::string >();
239 Property::Value* vertex = map->Find( "vertex" );
242 vertexShader = vertex->Get< std::string >();
246 // Get custom sampler type name
247 const char* customSamplerTypename = extension->GetCustomSamplerTypename();
248 if( customSamplerTypename )
250 size_t position = fragmentShader.find( DEFAULT_SAMPLER_TYPENAME );
251 if( position != std::string::npos )
253 fragmentShader.replace( position, strlen( DEFAULT_SAMPLER_TYPENAME ), customSamplerTypename );
257 // Set the modified shader again
258 Shader newShader = Shader::New( vertexShader, fragmentShader );
259 newShader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
261 renderer.SetShader( newShader );
263 DALI_LOG_RELEASE_INFO( "TizenVectorAnimationRenderer::SetShader: Shader is changed\n" );
267 } // namespace Plugin