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