Rendering API clean-up
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / image-actor-impl.cpp
1 /*
2  * Copyright (c) 2014 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/event/actors/image-actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/animation/constraints.h> // for EqualToConstraint
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/devel-api/scripting/scripting.h>
28 #include <dali/internal/event/animation/constraint-impl.h>
29 #include <dali/internal/event/common/property-helper.h>
30 #include <dali/internal/event/effects/shader-effect-impl.h>
31 #include <dali/internal/event/images/image-connector.h>
32 #include <dali/internal/event/images/nine-patch-image-impl.h>
33
34 namespace Dali
35 {
36
37 namespace Internal
38 {
39
40 namespace
41 {
42
43 // Properties
44
45 //              Name           Type   writable animatable constraint-input  enum for index-checking
46 DALI_PROPERTY_TABLE_BEGIN
47 DALI_PROPERTY( "pixelArea",    RECTANGLE, true,    false,   true,    Dali::ImageActor::Property::PIXEL_AREA )
48 DALI_PROPERTY( "style",        STRING,    true,    false,   true,    Dali::ImageActor::Property::STYLE      )
49 DALI_PROPERTY( "border",       VECTOR4,   true,    false,   true,    Dali::ImageActor::Property::BORDER     )
50 DALI_PROPERTY( "image",        MAP,       true,    false,   false,   Dali::ImageActor::Property::IMAGE      )
51 DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
52
53 BaseHandle Create()
54 {
55   return Dali::ImageActor::New();
56 }
57
58 TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::Actor ), Create );
59
60 struct GridVertex
61 {
62   GridVertex( float positionX, float positionY, const Vector2& size )
63   : mPosition( positionX*size.x, positionY*size.y, 0.f ),
64     mTextureCoord( positionX+0.5f, positionY+0.5f )
65   {
66   }
67
68   Vector3 mPosition;
69   Vector2 mTextureCoord;
70 };
71
72 GeometryPtr CreateGeometry( unsigned int gridWidth, unsigned int gridHeight, const Vector2& size )
73 {
74   // Create vertices
75   std::vector< GridVertex > vertices;
76   vertices.reserve( ( gridWidth + 1 ) * ( gridHeight + 1 ) );
77
78   for( unsigned int y = 0u; y < gridHeight + 1; ++y )
79   {
80     float yPos = (float)y / gridHeight;
81     for( unsigned int x = 0u; x < gridWidth + 1; ++x )
82     {
83       float xPos = (float)x / gridWidth;
84       vertices.push_back( GridVertex( xPos - 0.5f, yPos - 0.5f, size ) );
85     }
86   }
87
88   // Create indices
89   Vector< unsigned int > indices;
90   indices.Reserve( ( gridWidth + 2 ) * gridHeight * 2 - 2);
91
92   for( unsigned int row = 0u; row < gridHeight; ++row )
93   {
94     unsigned int rowStartIndex = row*(gridWidth+1u);
95     unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u;
96
97     if( row != 0u ) // degenerate index on non-first row
98     {
99       indices.PushBack( rowStartIndex );
100     }
101
102     for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip
103     {
104       indices.PushBack( rowStartIndex + column);
105       indices.PushBack( nextRowStartIndex + column);
106     }
107
108     if( row != gridHeight-1u ) // degenerate index on non-last row
109     {
110       indices.PushBack( nextRowStartIndex + gridWidth );
111     }
112   }
113
114   Property::Map vertexFormat;
115   vertexFormat[ "aPosition" ] = Property::VECTOR3;
116   vertexFormat[ "aTexCoord" ] = Property::VECTOR2;
117   PropertyBufferPtr vertexPropertyBuffer = PropertyBuffer::New( vertexFormat );
118   if( vertices.size() > 0 )
119   {
120     vertexPropertyBuffer->SetData( &vertices[ 0 ], vertices.size() );
121   }
122
123   Property::Map indexFormat;
124   indexFormat[ "indices" ] = Property::INTEGER;
125   PropertyBufferPtr indexPropertyBuffer = PropertyBuffer::New( indexFormat );
126   if( indices.Size() > 0 )
127   {
128     indexPropertyBuffer->SetData( &indices[ 0 ], indices.Size() );
129   }
130
131   // Create the geometry object
132   GeometryPtr geometry = Geometry::New();
133   geometry->AddVertexBuffer( *vertexPropertyBuffer );
134   geometry->SetIndexBuffer( *indexPropertyBuffer );
135   geometry->SetGeometryType( Dali::Geometry::TRIANGLE_STRIP );
136
137   return geometry;
138 }
139
140 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
141   attribute mediump vec3 aPosition;\n
142   attribute mediump vec2 aTexCoord;\n
143   varying mediump vec2 vTexCoord;\n
144   uniform mediump mat4 uMvpMatrix;\n
145   uniform mediump vec3 uSize;\n
146   uniform mediump vec4 sTextureRect;\n
147   \n
148   void main()\n
149   {\n
150     gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n
151     vTexCoord = aTexCoord;\n
152   }\n
153 );
154
155 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
156   varying mediump vec2 vTexCoord;\n
157   uniform sampler2D sTexture;\n
158   uniform lowp vec4 uColor;\n
159   \n
160   void main()\n
161   {\n
162     gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
163   }\n
164 );
165
166 const char * const TEXTURE_RECT_UNIFORM_NAME( "sTextureRect" );
167
168 const int INVALID_RENDERER_ID = -1;
169 const uint16_t MAXIMUM_GRID_SIZE = 2048;
170 }
171
172 ImageActorPtr ImageActor::New()
173 {
174   ImageActorPtr actor( new ImageActor );
175
176   // Second-phase construction of base class
177   actor->Initialize();
178
179   //Create the renderer
180   actor->mRenderer = Renderer::New();
181
182   GeometryPtr quad  = CreateGeometry( 1u, 1u, Vector2::ONE );
183   actor->mRenderer->SetGeometry( *quad );
184
185   ShaderPtr shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, Dali::Shader::HINT_NONE );
186   actor->mRenderer->SetShader( *shader );
187   TextureSetPtr textureSet = TextureSet::New();
188   actor->mRenderer->SetTextures( *textureSet );
189
190   return actor;
191 }
192
193 void ImageActor::OnInitialize()
194 {
195   // TODO: Remove this, at the moment its needed for size negotiation to work
196   SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
197 }
198
199 void ImageActor::SetImage( ImagePtr& image )
200 {
201   if( !image )
202   {
203     if( mRendererIndex != INVALID_RENDERER_ID )
204     {
205       RemoveRenderer( mRendererIndex );
206       mRendererIndex = INVALID_RENDERER_ID;
207     }
208   }
209   else
210   {
211     SamplerPtr sampler = Sampler::New();
212     sampler->SetFilterMode( mMinFilter, mMagFilter );
213
214     TextureSet* textureSet( mRenderer->GetTextures() );
215     textureSet->SetImage( 0u, image.Get() );
216     textureSet->SetSampler( 0u, sampler );
217
218     if( mRendererIndex == INVALID_RENDERER_ID )
219     {
220       mRendererIndex = AddRenderer( *mRenderer );
221     }
222
223     if( !mIsPixelAreaSet )
224     {
225       mPixelArea = PixelArea( 0, 0, image->GetWidth(), image->GetHeight() );
226     }
227
228     RelayoutRequest();
229     UpdateTexureRect();
230   }
231 }
232
233 ImagePtr ImageActor::GetImage() const
234 {
235   return mRenderer->GetTextures()->GetImage( 0u );
236 }
237
238 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
239 {
240   mPixelArea = pixelArea;
241   mIsPixelAreaSet = true;
242
243   RelayoutRequest();
244   UpdateTexureRect();
245 }
246
247 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
248 {
249   return mPixelArea;
250 }
251
252 bool ImageActor::IsPixelAreaSet() const
253 {
254   return mIsPixelAreaSet;
255 }
256
257 void ImageActor::ClearPixelArea()
258 {
259   mIsPixelAreaSet = false;
260
261   int imageWidth = 0;
262   int imageHeight = 0;
263   ImagePtr image = GetImage();
264   if( image )
265   {
266     imageWidth = image->GetWidth();
267     imageHeight = image->GetHeight();
268   }
269
270   mPixelArea = PixelArea( 0, 0, imageWidth, imageHeight );
271
272   RelayoutRequest();
273   UpdateTexureRect();
274 }
275
276 void ImageActor::SetStyle( Dali::ImageActor::Style style )
277 {
278   DALI_LOG_WARNING( "SetStyle Deprecated. Only STYLE_QUAD supported." );
279   mStyle = style;
280 }
281
282 Dali::ImageActor::Style ImageActor::GetStyle() const
283 {
284   DALI_LOG_WARNING( "GetStyle Deprecated. Only STYLE_QUAD supported." );
285   return mStyle;
286 }
287
288 void ImageActor::SetNinePatchBorder( const Vector4& border )
289 {
290   DALI_LOG_WARNING( "SetNinePatchBorder Deprecated. Only STYLE_QUAD supported." );
291   mNinePatchBorder = border;
292 }
293
294 Vector4 ImageActor::GetNinePatchBorder() const
295 {
296   DALI_LOG_WARNING( "GetNinePatchBorder Deprecated. Only STYLE_QUAD supported." );
297   return mNinePatchBorder;
298 }
299
300 ImageActor::ImageActor()
301 : Actor( Actor::BASIC ),
302   mActorSize( Vector2::ZERO ),
303   mGridSize( 1u, 1u ),
304   mRendererIndex( INVALID_RENDERER_ID ),
305   mMinFilter( FilterMode::DEFAULT ),
306   mMagFilter( FilterMode::DEFAULT ),
307   mStyle( Dali::ImageActor::STYLE_QUAD ),
308   mIsPixelAreaSet( false )
309 {
310 }
311
312 ImageActor::~ImageActor()
313 {
314 }
315
316 Vector3 ImageActor::GetNaturalSize() const
317 {
318   Vector2 naturalSize( CalculateNaturalSize() );
319   return Vector3( naturalSize.width, naturalSize.height, 0.f );
320 }
321
322 Vector2 ImageActor::CalculateNaturalSize() const
323 {
324   // if no image then natural size is 0
325   Vector2 size( 0.0f, 0.0f );
326
327   ImagePtr image = GetImage();
328   if( image )
329   {
330     if( IsPixelAreaSet() )
331     {
332       PixelArea area(GetPixelArea());
333       size.width = area.width;
334       size.height = area.height;
335     }
336     else
337     {
338       size = image->GetNaturalSize();
339     }
340   }
341
342   return size;
343 }
344
345 void ImageActor::UpdateGeometry()
346 {
347   uint16_t gridWidth = 1u;
348   uint16_t gridHeight = 1u;
349
350   if( mShaderEffect )
351   {
352     Vector2 gridSize = mShaderEffect->GetGridSize( Vector2(mPixelArea.width, mPixelArea.height) );
353
354     //limit the grid size
355     gridWidth = std::min( MAXIMUM_GRID_SIZE, static_cast<uint16_t>(gridSize.width) );
356     gridHeight = std::min( MAXIMUM_GRID_SIZE, static_cast<uint16_t>(gridSize.height) );
357   }
358
359   mGridSize.SetWidth( gridWidth );
360   mGridSize.SetHeight( gridHeight );
361
362   GeometryPtr geometry = CreateGeometry( gridWidth, gridHeight, mActorSize );
363   mRenderer->SetGeometry( *geometry );
364 }
365 void ImageActor::UpdateTexureRect()
366 {
367   Vector4 textureRect( 0.f, 0.f, 1.f, 1.f );
368
369   ImagePtr image = GetImage();
370   if( mIsPixelAreaSet && image )
371   {
372     const float uScale = 1.0f / float(image->GetWidth());
373     const float vScale = 1.0f / float(image->GetHeight());
374     // bottom left
375     textureRect.x = uScale * float(mPixelArea.x);
376     textureRect.y = vScale * float(mPixelArea.y);
377     // top right
378     textureRect.z  = uScale * float(mPixelArea.x + mPixelArea.width);
379     textureRect.w = vScale * float(mPixelArea.y + mPixelArea.height);
380   }
381
382   TextureSet* textureSet = mRenderer->GetTextures();
383   textureSet->RegisterProperty( TEXTURE_RECT_UNIFORM_NAME, textureRect );
384 }
385
386 unsigned int ImageActor::GetDefaultPropertyCount() const
387 {
388   return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
389 }
390
391 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
392 {
393   Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
394
395   indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
396
397   int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
398   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
399   {
400     indices.PushBack( index );
401   }
402 }
403
404 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
405 {
406   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
407   {
408     return Actor::IsDefaultPropertyWritable(index);
409   }
410
411   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
412   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
413   {
414     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
415   }
416
417   return false;
418 }
419
420 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
421 {
422   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
423   {
424     return Actor::IsDefaultPropertyAnimatable( index );
425   }
426
427   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
428   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
429   {
430     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
431   }
432
433   return false;
434 }
435
436 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
437 {
438   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
439   {
440     return Actor::IsDefaultPropertyAConstraintInput( index );
441   }
442
443   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
444   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
445   {
446     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
447   }
448
449   return false;
450 }
451
452 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
453 {
454   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
455   {
456     return Actor::GetDefaultPropertyType( index );
457   }
458
459   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
460   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
461   {
462     return DEFAULT_PROPERTY_DETAILS[index].type;
463   }
464
465   // index out-of-bounds
466   return Property::NONE;
467 }
468
469 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
470 {
471   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
472   {
473     return Actor::GetDefaultPropertyName(index);
474   }
475
476   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
477   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
478   {
479     return DEFAULT_PROPERTY_DETAILS[index].name;
480   }
481
482   // index out-of-bounds
483   return NULL;
484 }
485
486 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
487 {
488   Property::Index index = Property::INVALID_INDEX;
489
490   // Look for name in default properties
491   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
492   {
493     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
494     if( 0 == strcmp( name.c_str(), property->name ) ) // Don't want to convert rhs to string
495     {
496       index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
497       break;
498     }
499   }
500
501   // If not found, check in base class
502   if( Property::INVALID_INDEX == index )
503   {
504     index = Actor::GetDefaultPropertyIndex( name );
505   }
506   return index;
507 }
508
509 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
510 {
511   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
512   {
513     Actor::SetDefaultProperty( index, propertyValue );
514   }
515   else
516   {
517     switch(index)
518     {
519       case Dali::ImageActor::Property::PIXEL_AREA:
520       {
521         SetPixelArea(propertyValue.Get<Rect<int> >());
522         break;
523       }
524       case Dali::ImageActor::Property::STYLE:
525       {
526         //not supported
527         break;
528       }
529       case Dali::ImageActor::Property::BORDER:
530       {
531         //not supported
532         break;
533       }
534       case Dali::ImageActor::Property::IMAGE:
535       {
536         Dali::Image img = Scripting::NewImage( propertyValue );
537         if(img)
538         {
539           ImagePtr image( &GetImplementation(img) );
540           SetImage( image );
541         }
542         else
543         {
544           DALI_LOG_WARNING("Cannot create image from property value\n");
545         }
546         break;
547       }
548       default:
549       {
550         DALI_LOG_WARNING("Unknown property (%d)\n", index);
551         break;
552       }
553     } // switch(index)
554
555   } // else
556 }
557
558 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
559 {
560   Property::Value ret;
561   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
562   {
563     ret = Actor::GetDefaultProperty( index );
564   }
565   else
566   {
567     switch( index )
568     {
569       case Dali::ImageActor::Property::PIXEL_AREA:
570       {
571         Rect<int> r = GetPixelArea();
572         ret = r;
573         break;
574       }
575       case Dali::ImageActor::Property::STYLE:
576       {
577         //not supported
578         break;
579       }
580       case Dali::ImageActor::Property::BORDER:
581       {
582         //not supported
583         break;
584       }
585       case Dali::ImageActor::Property::IMAGE:
586       {
587         Property::Map map;
588         Scripting::CreatePropertyMap( Dali::Image( GetImage().Get() ), map );
589         ret = Property::Value( map );
590         break;
591       }
592       default:
593       {
594         DALI_LOG_WARNING( "Unknown property (%d)\n", index );
595         break;
596       }
597     } // switch(index)
598   }
599
600   return ret;
601 }
602
603 void ImageActor::SetSortModifier(float modifier)
604 {
605   mRenderer->SetDepthIndex( modifier );
606 }
607
608 float ImageActor::GetSortModifier() const
609 {
610   return mRenderer->GetDepthIndex();
611 }
612
613 void ImageActor::SetBlendMode( BlendingMode::Type mode )
614 {
615   mRenderer->SetBlendMode( mode );
616 }
617
618 BlendingMode::Type ImageActor::GetBlendMode() const
619 {
620   return mRenderer->GetBlendMode();
621 }
622
623 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba,   BlendingFactor::Type destFactorRgba )
624 {
625   mRenderer->SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
626 }
627
628 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
629                                BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
630 {
631   mRenderer->SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
632 }
633
634 void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
635                                BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
636 {
637   mRenderer->GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
638 }
639
640 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
641 {
642   mRenderer->SetBlendEquation( equationRgba, equationRgba );
643 }
644
645 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
646 {
647   mRenderer->SetBlendEquation( equationRgb, equationAlpha );
648 }
649
650 void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
651 {
652   mRenderer->GetBlendEquation( equationRgb, equationAlpha );
653 }
654
655 void ImageActor::SetBlendColor( const Vector4& color )
656 {
657   mBlendColor = color;
658   mRenderer->SetBlendColor( mBlendColor );
659 }
660
661 const Vector4& ImageActor::GetBlendColor() const
662 {
663   return mBlendColor;
664 }
665
666 void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
667 {
668   mMinFilter = minFilter;
669   mMagFilter = magFilter;
670
671   SamplerPtr sampler = Sampler::New();
672   sampler->SetFilterMode( minFilter, magFilter );
673   mRenderer->GetTextures()->SetSampler( 0u, sampler.Get() );
674 }
675
676 void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
677 {
678   minFilter = mMinFilter;
679   magFilter = mMagFilter;
680 }
681
682 void ImageActor::SetShaderEffect( ShaderEffect& effect )
683 {
684   if( mShaderEffect )
685   {
686     mShaderEffect->Disconnect( this );
687   }
688
689   mShaderEffect = ShaderEffectPtr( &effect );
690   effect.Connect( this );
691
692   ShaderPtr shader = mShaderEffect->GetShader();
693   mRenderer->SetShader( *shader );
694
695   EffectImageUpdated();
696
697   UpdateGeometry();
698 }
699
700 ShaderEffectPtr ImageActor::GetShaderEffect() const
701 {
702   return mShaderEffect;
703 }
704
705 void ImageActor::RemoveShaderEffect()
706 {
707   if( mShaderEffect )
708   {
709     mShaderEffect->Disconnect( this );
710     // change to the standard shader and quad geometry
711     ShaderPtr shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, Dali::Shader::HINT_NONE );
712     mRenderer->SetShader( *shader );
713     mShaderEffect.Reset();
714
715     UpdateGeometry();
716   }
717 }
718
719 void ImageActor::EffectImageUpdated()
720 {
721   if( mShaderEffect )
722   {
723     Dali::Image effectImage = mShaderEffect->GetEffectImage();
724     if( effectImage )
725     {
726       Image& effectImageImpl = GetImplementation( effectImage );
727       mRenderer->GetTextures()->SetImage( 1u, &effectImageImpl );
728     }
729     else
730     {
731        mRenderer->GetTextures()->SetImage( 1u, 0 );
732     }
733   }
734 }
735
736 void ImageActor::OnRelayout( const Vector2& size, RelayoutContainer& container )
737 {
738   if( mActorSize != size )
739   {
740     mActorSize = size;
741     UpdateGeometry();
742   }
743 }
744
745 void ImageActor::OnSizeSet( const Vector3& targetSize )
746 {
747   Vector2 size( targetSize.x, targetSize.y );
748   if( mActorSize != size )
749   {
750     mActorSize = size;
751     UpdateGeometry();
752   }
753 }
754
755 } // namespace Internal
756
757 } // namespace Dali