Add 'ExclusiveArch: armv7l' limit build to arm architecture
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / filters / spread-filter.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include "spread-filter.h"
19
20 // EXTERNAL INCLUDES
21 #include <sstream>
22
23 // INTERNAL INCLUDES
24
25 namespace Dali
26 {
27
28 namespace Toolkit
29 {
30
31 namespace Internal
32 {
33
34 namespace
35 {
36
37 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
38
39 const char* const SPREAD_FRAGMENT_SOURCE =
40 {
41  "uniform float uSpread;\n"
42  "uniform vec2 uTexScale;\n"
43  "void main()\n"
44  "{\n"
45  "  vec4 color = texture2D( sTexture, vTexCoord);\n"
46  "# ifdef DEBUG_RENDER\n"
47  "  if( vTexCoord.s < 0.495 )\n"
48  "  {\n"
49  "# endif //def DEBUG_RENDER\n"
50  "    int spread = int(uSpread);\n"
51  "    for( int i = 1; i <= spread; ++i )\n"
52  "    {\n"
53  "      vec2 offset = uTexScale * float(i);\n"
54  "      color = max( texture2D( sTexture, vTexCoord + offset), color );\n"
55  "      color = max( texture2D( sTexture, vTexCoord - offset), color );\n"
56  "    }\n"
57  "# ifdef DEBUG_RENDER\n"
58  "  }\n"
59  "  else if( vTexCoord.s <= 0.505 )\n"
60  "  {\n"
61  "    color = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
62  "  }\n"
63  "# endif //def DEBUG_RENDER\n"
64  "  gl_FragColor = color;\n"
65  "}\n"
66 };
67
68 } // namespace
69
70
71 SpreadFilter::SpreadFilter()
72 : ImageFilter(),
73   mSpread(2)
74 {
75 }
76
77 SpreadFilter::~SpreadFilter()
78 {
79 }
80
81 void SpreadFilter::SetSpread( float spread )
82 {
83   mSpread = spread;
84 }
85
86 void SpreadFilter::Enable()
87 {
88   mCameraActor = CameraActor::New();
89   mCameraActor.SetParentOrigin(ParentOrigin::CENTER);
90
91   // create actor to render input with applied emboss effect
92   mActorForInput = ImageActor::New( mInputImage );
93   mActorForInput.SetParentOrigin( ParentOrigin::CENTER );
94   mActorForInput.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
95   mActorForInput.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
96
97   // create internal offscreen for result of horizontal pass
98   mImageForHorz = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::Unused );
99
100   // create an actor to render mImageForHorz for vertical blur pass
101   mActorForHorz = ImageActor::New( mImageForHorz );
102   mActorForHorz.SetParentOrigin( ParentOrigin::CENTER );
103   mActorForHorz.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
104   mActorForHorz.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
105
106   mRootActor.Add( mActorForInput );
107   mRootActor.Add( mActorForHorz );
108   mRootActor.Add( mCameraActor );
109
110   std::ostringstream fragmentSource;
111   if( mDebugRender )
112   {
113     fragmentSource << "#define DEBUG_RENDER\n";
114   }
115   fragmentSource << SPREAD_FRAGMENT_SOURCE;
116
117   mShaderForHorz = ShaderEffect::New( "", fragmentSource.str() );
118   mActorForInput.SetShaderEffect( mShaderForHorz );
119   mShaderForHorz.SetUniform( "uSpread", mSpread );
120   mShaderForHorz.SetUniform( "uTexScale", Vector2( 1.0f / mTargetSize.width, 0.0f ) );
121
122   mShaderForVert = ShaderEffect::New( "", fragmentSource.str() );
123   mActorForHorz.SetShaderEffect( mShaderForVert );
124   mShaderForVert.SetUniform( "uSpread", mSpread );
125   mShaderForVert.SetUniform( "uTexScale", Vector2( 0.0f, 1.0f / mTargetSize.height ) );
126
127   SetupCamera();
128   CreateRenderTasks();
129 }
130
131 void SpreadFilter::Disable()
132 {
133   if( mRootActor )
134   {
135     if( mCameraActor )
136     {
137       mRootActor.Remove( mCameraActor );
138       mCameraActor.Reset();
139     }
140
141     if( mActorForInput )
142     {
143       mRootActor.Remove( mActorForInput );
144       mActorForInput.Reset();
145     }
146
147     if( mActorForHorz )
148     {
149       mRootActor.Remove( mActorForHorz );
150       mActorForHorz.Reset();
151     }
152
153     RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
154
155     if( mRenderTaskForHorz )
156     {
157       taskList.RemoveTask(mRenderTaskForHorz);
158     }
159     if( mRenderTaskForVert )
160     {
161       taskList.RemoveTask(mRenderTaskForVert);
162     }
163
164     mRootActor.Reset();
165   }
166 }
167
168 void SpreadFilter::Refresh()
169 {
170   if( mRenderTaskForHorz )
171   {
172     mRenderTaskForHorz.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
173   }
174
175   if( mRenderTaskForVert )
176   {
177     mRenderTaskForVert.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
178   }
179 }
180
181 void SpreadFilter::SetupCamera()
182 {
183   // Create and place a camera for the embossing render, corresponding to its render target size
184   mCameraActor.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
185   mCameraActor.SetNearClippingPlane(1.0f);
186   mCameraActor.SetAspectRatio(mTargetSize.width / mTargetSize.height);
187   mCameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
188   mCameraActor.SetRotation(Quaternion(M_PI, Vector3::YAXIS));
189   mCameraActor.SetPosition(0.0f, 0.0f, ((mTargetSize.height * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
190 }
191
192 void SpreadFilter::CreateRenderTasks()
193 {
194   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
195
196   // perform a horizontal blur targeting the internal buffer
197   mRenderTaskForHorz = taskList.CreateTask();
198   mRenderTaskForHorz.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
199   mRenderTaskForHorz.SetSourceActor( mActorForInput );
200   mRenderTaskForHorz.SetExclusive(true);
201   mRenderTaskForHorz.SetInputEnabled( false );
202   mRenderTaskForHorz.SetClearEnabled( true );
203   mRenderTaskForHorz.SetClearColor( mBackgroundColor );
204   mRenderTaskForHorz.SetTargetFrameBuffer( mImageForHorz );
205   mRenderTaskForHorz.SetCameraActor( mCameraActor );
206
207   // use the internal buffer and perform a horizontal blur targeting the output buffer
208   mRenderTaskForVert = taskList.CreateTask();
209   mRenderTaskForVert.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
210   mRenderTaskForVert.SetSourceActor( mActorForHorz );
211   mRenderTaskForVert.SetExclusive(true);
212   mRenderTaskForVert.SetInputEnabled( false );
213   mRenderTaskForVert.SetClearEnabled( true );
214   mRenderTaskForVert.SetClearColor( mBackgroundColor );
215   mRenderTaskForVert.SetTargetFrameBuffer( mOutputImage );
216   mRenderTaskForVert.SetCameraActor( mCameraActor );
217 }
218
219 } // namespace Internal
220
221 } // namespace Toolkit
222
223 } // namespace Dali