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